ApartmentRegion.h (3510B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_mscom_ApartmentRegion_h 8 #define mozilla_mscom_ApartmentRegion_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Attributes.h" 12 #include "mozilla/mscom/COMWrappers.h" 13 14 namespace mozilla::mscom { 15 16 // This runtime-dynamic apartment class is used in ProcessRuntime.cpp, to 17 // initialize the process's main thread. Do not use it in new contexts if at all 18 // possible; instead, prefer ApartmentRegionT, below. 19 // 20 // For backwards compatibility, this class does not yet automatically disable 21 // OLE1/DDE, although there is believed to be no code relying on it. 22 // 23 // (TODO: phase out all uses of CoInitialize without `COINIT_DISABLE_OLE1DDE`?) 24 class MOZ_NON_TEMPORARY_CLASS ApartmentRegion final { 25 public: 26 /** 27 * This constructor is to be used when we want to instantiate the object but 28 * we do not yet know which type of apartment we want. Call Init() to 29 * complete initialization. 30 */ 31 constexpr ApartmentRegion() : mInitResult(CO_E_NOTINITIALIZED) {} 32 33 explicit ApartmentRegion(COINIT aAptType) 34 : mInitResult(wrapped::CoInitializeEx(nullptr, aAptType)) { 35 // If this fires then we're probably mixing apartments on the same thread 36 MOZ_ASSERT(IsValid()); 37 } 38 39 ~ApartmentRegion() { 40 if (IsValid()) { 41 wrapped::CoUninitialize(); 42 } 43 } 44 45 explicit operator bool() const { return IsValid(); } 46 47 bool IsValidOutermost() const { return mInitResult == S_OK; } 48 49 bool IsValid() const { return SUCCEEDED(mInitResult); } 50 51 bool Init(COINIT aAptType) { 52 MOZ_ASSERT(mInitResult == CO_E_NOTINITIALIZED); 53 mInitResult = wrapped::CoInitializeEx(nullptr, aAptType); 54 MOZ_ASSERT(IsValid()); 55 return IsValid(); 56 } 57 58 HRESULT GetHResult() const { return mInitResult; } 59 60 ApartmentRegion(const ApartmentRegion&) = delete; 61 ApartmentRegion& operator=(const ApartmentRegion&) = delete; 62 ApartmentRegion(ApartmentRegion&&) = delete; 63 ApartmentRegion& operator=(ApartmentRegion&&) = delete; 64 65 private: 66 HRESULT mInitResult; 67 }; 68 69 template <COINIT AptType, bool UseOLE1 = false> 70 class MOZ_NON_TEMPORARY_CLASS ApartmentRegionT final { 71 static COINIT ActualType() { 72 static_assert( 73 !((AptType & COINIT_DISABLE_OLE1DDE) == 0 && UseOLE1), 74 "only one of `UseOLE1` and `COINIT_DISABLE_OLE1DDE` permitted"); 75 if (UseOLE1) return AptType; 76 return static_cast<COINIT>(AptType | COINIT_DISABLE_OLE1DDE); 77 } 78 79 public: 80 ApartmentRegionT() : mAptRgn(ActualType()) {} 81 82 ~ApartmentRegionT() = default; 83 84 explicit operator bool() const { return mAptRgn.IsValid(); } 85 86 bool IsValidOutermost() const { return mAptRgn.IsValidOutermost(); } 87 88 bool IsValid() const { return mAptRgn.IsValid(); } 89 90 HRESULT GetHResult() const { return mAptRgn.GetHResult(); } 91 92 ApartmentRegionT(const ApartmentRegionT&) = delete; 93 ApartmentRegionT& operator=(const ApartmentRegionT&) = delete; 94 ApartmentRegionT(ApartmentRegionT&&) = delete; 95 ApartmentRegionT& operator=(ApartmentRegionT&&) = delete; 96 97 private: 98 ApartmentRegion mAptRgn; 99 }; 100 101 using STARegion = ApartmentRegionT<COINIT_APARTMENTTHREADED>; 102 using MTARegion = ApartmentRegionT<COINIT_MULTITHREADED>; 103 104 } // namespace mozilla::mscom 105 106 #endif // mozilla_mscom_ApartmentRegion_h