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