xref: /aosp_15_r20/external/cronet/base/win/com_init_balancer.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_WIN_COM_INIT_BALANCER_H_
6 #define BASE_WIN_COM_INIT_BALANCER_H_
7 
8 #include <objidl.h>
9 #include <winnt.h>
10 #include <wrl/implements.h>
11 
12 #include <optional>
13 
14 #include "base/base_export.h"
15 #include "base/threading/thread_checker.h"
16 #include "base/win/windows_types.h"
17 
18 namespace base {
19 namespace win {
20 namespace internal {
21 
22 // Implementation class of the IInitializeSpy Interface that prevents premature
23 // uninitialization of the COM library, often caused by unbalanced
24 // CoInitialize/CoUninitialize pairs. The use of this class is encouraged in
25 // COM-supporting threads that execute third-party code.
26 //
27 // Disable() must be called before uninitializing the COM library in order to
28 // revoke the registered spy and allow for the successful uninitialization of
29 // the COM library.
30 class BASE_EXPORT ComInitBalancer
31     : public Microsoft::WRL::RuntimeClass<
32           Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
33           IInitializeSpy> {
34  public:
35   // Constructs a COM initialize balancer. |co_init| defines the apartment's
36   // concurrency model used by the balancer.
37   explicit ComInitBalancer(DWORD co_init);
38 
39   ComInitBalancer(const ComInitBalancer&) = delete;
40   ComInitBalancer& operator=(const ComInitBalancer&) = delete;
41 
42   ~ComInitBalancer() override;
43 
44   // Disables balancer by revoking the registered spy and consequently
45   // unblocking attempts to uninitialize the COM library.
46   void Disable();
47 
48   DWORD GetReferenceCountForTesting() const;
49 
50  private:
51   // IInitializeSpy:
52   IFACEMETHODIMP PreInitialize(DWORD apartment_type,
53                                DWORD reference_count) override;
54   IFACEMETHODIMP PostInitialize(HRESULT result,
55                                 DWORD apartment_type,
56                                 DWORD new_reference_count) override;
57   IFACEMETHODIMP PreUninitialize(DWORD reference_count) override;
58   IFACEMETHODIMP PostUninitialize(DWORD new_reference_count) override;
59 
60   const DWORD co_init_;
61 
62   // The current apartment reference count set after the completion of the last
63   // call made to CoInitialize or CoUninitialize.
64   DWORD reference_count_ = 0;
65 
66   std::optional<ULARGE_INTEGER> spy_cookie_;
67   THREAD_CHECKER(thread_checker_);
68 };
69 
70 }  // namespace internal
71 }  // namespace win
72 }  // namespace base
73 
74 #endif  // BASE_WIN_COM_INIT_BALANCER_H_
75