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 #include "base/win/com_init_balancer.h" 6 7 #include <objbase.h> 8 9 #include "base/check_op.h" 10 11 namespace base { 12 namespace win { 13 namespace internal { 14 ComInitBalancer(DWORD co_init)15ComInitBalancer::ComInitBalancer(DWORD co_init) : co_init_(co_init) { 16 ULARGE_INTEGER spy_cookie = {}; 17 HRESULT hr = ::CoRegisterInitializeSpy(this, &spy_cookie); 18 if (SUCCEEDED(hr)) 19 spy_cookie_ = spy_cookie; 20 } 21 ~ComInitBalancer()22ComInitBalancer::~ComInitBalancer() { 23 DCHECK(!spy_cookie_.has_value()); 24 } 25 Disable()26void ComInitBalancer::Disable() { 27 if (spy_cookie_.has_value()) { 28 ::CoRevokeInitializeSpy(spy_cookie_.value()); 29 reference_count_ = 0; 30 spy_cookie_.reset(); 31 } 32 } 33 GetReferenceCountForTesting() const34DWORD ComInitBalancer::GetReferenceCountForTesting() const { 35 return reference_count_; 36 } 37 38 IFACEMETHODIMP PreInitialize(DWORD apartment_type,DWORD reference_count)39ComInitBalancer::PreInitialize(DWORD apartment_type, DWORD reference_count) { 40 return S_OK; 41 } 42 43 IFACEMETHODIMP PostInitialize(HRESULT result,DWORD apartment_type,DWORD new_reference_count)44ComInitBalancer::PostInitialize(HRESULT result, 45 DWORD apartment_type, 46 DWORD new_reference_count) { 47 reference_count_ = new_reference_count; 48 return result; 49 } 50 51 IFACEMETHODIMP PreUninitialize(DWORD reference_count)52ComInitBalancer::PreUninitialize(DWORD reference_count) { 53 if (reference_count == 1 && spy_cookie_.has_value()) { 54 // Increase the reference count to prevent premature and unbalanced 55 // uninitalization of the COM library. 56 ::CoInitializeEx(nullptr, co_init_); 57 } 58 return S_OK; 59 } 60 61 IFACEMETHODIMP PostUninitialize(DWORD new_reference_count)62ComInitBalancer::PostUninitialize(DWORD new_reference_count) { 63 reference_count_ = new_reference_count; 64 return S_OK; 65 } 66 67 } // namespace internal 68 } // namespace win 69 } // namespace base 70