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