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/com_init_util.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker #include <windows.h> 8*6777b538SAndroid Build Coastguard Worker 9*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 10*6777b538SAndroid Build Coastguard Worker #include <winternl.h> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/logging.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h" 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker namespace base { 16*6777b538SAndroid Build Coastguard Worker namespace win { 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker namespace { 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 21*6777b538SAndroid Build Coastguard Worker const char kComNotInitialized[] = "COM is not initialized on this thread."; 22*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON() 23*6777b538SAndroid Build Coastguard Worker 24*6777b538SAndroid Build Coastguard Worker // Derived from combase.dll. 25*6777b538SAndroid Build Coastguard Worker struct OleTlsData { 26*6777b538SAndroid Build Coastguard Worker enum ApartmentFlags { 27*6777b538SAndroid Build Coastguard Worker LOGICAL_THREAD_REGISTERED = 0x2, 28*6777b538SAndroid Build Coastguard Worker STA = 0x80, 29*6777b538SAndroid Build Coastguard Worker MTA = 0x140, 30*6777b538SAndroid Build Coastguard Worker }; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker uintptr_t thread_base; 33*6777b538SAndroid Build Coastguard Worker uintptr_t sm_allocator; 34*6777b538SAndroid Build Coastguard Worker DWORD apartment_id; 35*6777b538SAndroid Build Coastguard Worker DWORD apartment_flags; 36*6777b538SAndroid Build Coastguard Worker // There are many more fields than this, but for our purposes, we only care 37*6777b538SAndroid Build Coastguard Worker // about |apartment_flags|. Correctly declaring the previous types allows this 38*6777b538SAndroid Build Coastguard Worker // to work between x86 and x64 builds. 39*6777b538SAndroid Build Coastguard Worker }; 40*6777b538SAndroid Build Coastguard Worker GetOleTlsData()41*6777b538SAndroid Build Coastguard WorkerOleTlsData* GetOleTlsData() { 42*6777b538SAndroid Build Coastguard Worker TEB* teb = NtCurrentTeb(); 43*6777b538SAndroid Build Coastguard Worker return reinterpret_cast<OleTlsData*>(teb->ReservedForOle); 44*6777b538SAndroid Build Coastguard Worker } 45*6777b538SAndroid Build Coastguard Worker 46*6777b538SAndroid Build Coastguard Worker } // namespace 47*6777b538SAndroid Build Coastguard Worker GetComApartmentTypeForThread()48*6777b538SAndroid Build Coastguard WorkerComApartmentType GetComApartmentTypeForThread() { 49*6777b538SAndroid Build Coastguard Worker OleTlsData* ole_tls_data = GetOleTlsData(); 50*6777b538SAndroid Build Coastguard Worker if (!ole_tls_data) 51*6777b538SAndroid Build Coastguard Worker return ComApartmentType::NONE; 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker if (ole_tls_data->apartment_flags & OleTlsData::ApartmentFlags::STA) 54*6777b538SAndroid Build Coastguard Worker return ComApartmentType::STA; 55*6777b538SAndroid Build Coastguard Worker 56*6777b538SAndroid Build Coastguard Worker if ((ole_tls_data->apartment_flags & OleTlsData::ApartmentFlags::MTA) == 57*6777b538SAndroid Build Coastguard Worker OleTlsData::ApartmentFlags::MTA) { 58*6777b538SAndroid Build Coastguard Worker return ComApartmentType::MTA; 59*6777b538SAndroid Build Coastguard Worker } 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker return ComApartmentType::NONE; 62*6777b538SAndroid Build Coastguard Worker } 63*6777b538SAndroid Build Coastguard Worker 64*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON() 65*6777b538SAndroid Build Coastguard Worker AssertComInitialized(const char * message)66*6777b538SAndroid Build Coastguard Workervoid AssertComInitialized(const char* message) { 67*6777b538SAndroid Build Coastguard Worker if (GetComApartmentTypeForThread() != ComApartmentType::NONE) 68*6777b538SAndroid Build Coastguard Worker return; 69*6777b538SAndroid Build Coastguard Worker 70*6777b538SAndroid Build Coastguard Worker // COM worker threads don't always set up the apartment, but they do perform 71*6777b538SAndroid Build Coastguard Worker // some thread registration, so we allow those. 72*6777b538SAndroid Build Coastguard Worker OleTlsData* ole_tls_data = GetOleTlsData(); 73*6777b538SAndroid Build Coastguard Worker if (ole_tls_data && (ole_tls_data->apartment_flags & 74*6777b538SAndroid Build Coastguard Worker OleTlsData::ApartmentFlags::LOGICAL_THREAD_REGISTERED)) { 75*6777b538SAndroid Build Coastguard Worker return; 76*6777b538SAndroid Build Coastguard Worker } 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker NOTREACHED() << (message ? message : kComNotInitialized); 79*6777b538SAndroid Build Coastguard Worker } 80*6777b538SAndroid Build Coastguard Worker AssertComApartmentType(ComApartmentType apartment_type)81*6777b538SAndroid Build Coastguard Workervoid AssertComApartmentType(ComApartmentType apartment_type) { 82*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(apartment_type, GetComApartmentTypeForThread()); 83*6777b538SAndroid Build Coastguard Worker } 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker #endif // DCHECK_IS_ON() 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker } // namespace win 88*6777b538SAndroid Build Coastguard Worker } // namespace base 89