xref: /aosp_15_r20/external/cronet/base/win/scoped_com_initializer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 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/scoped_com_initializer.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <wrl/implements.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <ostream>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/win/resource_exhaustion.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace base {
15*6777b538SAndroid Build Coastguard Worker namespace win {
16*6777b538SAndroid Build Coastguard Worker 
ScopedCOMInitializer(Uninitialization uninitialization)17*6777b538SAndroid Build Coastguard Worker ScopedCOMInitializer::ScopedCOMInitializer(Uninitialization uninitialization) {
18*6777b538SAndroid Build Coastguard Worker   Initialize(COINIT_APARTMENTTHREADED, uninitialization);
19*6777b538SAndroid Build Coastguard Worker }
20*6777b538SAndroid Build Coastguard Worker 
ScopedCOMInitializer(SelectMTA mta,Uninitialization uninitialization)21*6777b538SAndroid Build Coastguard Worker ScopedCOMInitializer::ScopedCOMInitializer(SelectMTA mta,
22*6777b538SAndroid Build Coastguard Worker                                            Uninitialization uninitialization) {
23*6777b538SAndroid Build Coastguard Worker   Initialize(COINIT_MULTITHREADED, uninitialization);
24*6777b538SAndroid Build Coastguard Worker }
25*6777b538SAndroid Build Coastguard Worker 
~ScopedCOMInitializer()26*6777b538SAndroid Build Coastguard Worker ScopedCOMInitializer::~ScopedCOMInitializer() {
27*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
28*6777b538SAndroid Build Coastguard Worker   if (Succeeded()) {
29*6777b538SAndroid Build Coastguard Worker     if (com_balancer_) {
30*6777b538SAndroid Build Coastguard Worker       com_balancer_->Disable();
31*6777b538SAndroid Build Coastguard Worker       com_balancer_.Reset();
32*6777b538SAndroid Build Coastguard Worker     }
33*6777b538SAndroid Build Coastguard Worker     CoUninitialize();
34*6777b538SAndroid Build Coastguard Worker   }
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker 
Succeeded() const37*6777b538SAndroid Build Coastguard Worker bool ScopedCOMInitializer::Succeeded() const {
38*6777b538SAndroid Build Coastguard Worker   return SUCCEEDED(hr_);
39*6777b538SAndroid Build Coastguard Worker }
40*6777b538SAndroid Build Coastguard Worker 
GetCOMBalancerReferenceCountForTesting() const41*6777b538SAndroid Build Coastguard Worker DWORD ScopedCOMInitializer::GetCOMBalancerReferenceCountForTesting() const {
42*6777b538SAndroid Build Coastguard Worker   if (com_balancer_)
43*6777b538SAndroid Build Coastguard Worker     return com_balancer_->GetReferenceCountForTesting();
44*6777b538SAndroid Build Coastguard Worker   return 0;
45*6777b538SAndroid Build Coastguard Worker }
46*6777b538SAndroid Build Coastguard Worker 
Initialize(COINIT init,Uninitialization uninitialization)47*6777b538SAndroid Build Coastguard Worker void ScopedCOMInitializer::Initialize(COINIT init,
48*6777b538SAndroid Build Coastguard Worker                                       Uninitialization uninitialization) {
49*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
50*6777b538SAndroid Build Coastguard Worker   // COINIT_DISABLE_OLE1DDE is always added based on:
51*6777b538SAndroid Build Coastguard Worker   // https://docs.microsoft.com/en-us/windows/desktop/learnwin32/initializing-the-com-library
52*6777b538SAndroid Build Coastguard Worker   if (uninitialization == Uninitialization::kBlockPremature) {
53*6777b538SAndroid Build Coastguard Worker     com_balancer_ = Microsoft::WRL::Details::Make<internal::ComInitBalancer>(
54*6777b538SAndroid Build Coastguard Worker         init | COINIT_DISABLE_OLE1DDE);
55*6777b538SAndroid Build Coastguard Worker   }
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   hr_ = ::CoInitializeEx(nullptr, init | COINIT_DISABLE_OLE1DDE);
58*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(RPC_E_CHANGED_MODE, hr_) << "Invalid COM thread model change";
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   // CoInitializeEx may call RegisterClassEx to get an ATOM. On failure, the
61*6777b538SAndroid Build Coastguard Worker   // call to RegisterClassEx sets the last error code to
62*6777b538SAndroid Build Coastguard Worker   // ERROR_NOT_ENOUGH_MEMORY. CoInitializeEx is retuning the converted error
63*6777b538SAndroid Build Coastguard Worker   // code (a.k.a HRESULT_FROM_WIN32(...)). The following code handles the case
64*6777b538SAndroid Build Coastguard Worker   // where HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY) is being returned by
65*6777b538SAndroid Build Coastguard Worker   // CoInitializeEx. We assume they are due to ATOM exhaustion. This appears to
66*6777b538SAndroid Build Coastguard Worker   // happen most often when the browser is being driven by automation tools,
67*6777b538SAndroid Build Coastguard Worker   // though the underlying reason for this remains a mystery
68*6777b538SAndroid Build Coastguard Worker   // (https://crbug.com/1470483). There is nothing that Chrome can do to
69*6777b538SAndroid Build Coastguard Worker   // meaningfully run until the user restarts their session by signing out of
70*6777b538SAndroid Build Coastguard Worker   // Windows or restarting their computer.
71*6777b538SAndroid Build Coastguard Worker   if (init == COINIT_APARTMENTTHREADED &&
72*6777b538SAndroid Build Coastguard Worker       hr_ == HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY)) {
73*6777b538SAndroid Build Coastguard Worker     base::win::OnResourceExhausted();
74*6777b538SAndroid Build Coastguard Worker   }
75*6777b538SAndroid Build Coastguard Worker }
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker }  // namespace win
78*6777b538SAndroid Build Coastguard Worker }  // namespace base
79