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