xref: /aosp_15_r20/external/cronet/base/win/com_init_balancer.cc (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 #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)15 ComInitBalancer::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()22 ComInitBalancer::~ComInitBalancer() {
23   DCHECK(!spy_cookie_.has_value());
24 }
25 
Disable()26 void 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() const34 DWORD ComInitBalancer::GetReferenceCountForTesting() const {
35   return reference_count_;
36 }
37 
38 IFACEMETHODIMP
PreInitialize(DWORD apartment_type,DWORD reference_count)39 ComInitBalancer::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)44 ComInitBalancer::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)52 ComInitBalancer::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)62 ComInitBalancer::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