From d236f79291f10c29c53808635110770e842ba8c1 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Wed, 15 Feb 2017 14:37:20 -0700 Subject: [PATCH] Bug 1339942: Make mscom registration able to be compiled and run outside Mozilla processes; r=jimm MozReview-Commit-ID: 3ETSE5Qn8nd --HG-- extra : rebase_source : cfab62cd77e0bed75a8600d1f0441b9683966307 --- ipc/mscom/Registration.cpp | 130 ++++++++++++++++++++++++++++--------- ipc/mscom/Registration.h | 6 ++ 2 files changed, 104 insertions(+), 32 deletions(-) diff --git a/ipc/mscom/Registration.cpp b/ipc/mscom/Registration.cpp index ff28b0f78547..a5cdbd2db60a 100644 --- a/ipc/mscom/Registration.cpp +++ b/ipc/mscom/Registration.cpp @@ -10,25 +10,32 @@ #define CINTERFACE #include "mozilla/mscom/ActivationContext.h" -#include "mozilla/mscom/EnsureMTA.h" #include "mozilla/mscom/Registration.h" #include "mozilla/mscom/Utils.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Assertions.h" -#include "mozilla/ClearOnShutdown.h" #include "mozilla/Move.h" -#include "mozilla/Mutex.h" #include "mozilla/Pair.h" +#include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" -#include "nsTArray.h" +#include "mozilla/Vector.h" #include "nsWindowsHelpers.h" +#if defined(MOZILLA_INTERNAL_API) +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/mscom/EnsureMTA.h" +#else +#include +#endif // defined(MOZILLA_INTERNAL_API) + #include #include #include #include +#include + /* This code MUST NOT use any non-inlined internal Mozilla APIs, as it will be compiled into DLLs that COM may load into non-Mozilla processes! */ @@ -274,7 +281,9 @@ RegisteredProxy::RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject, , mClassObject(aClassObject) , mRegCookie(aRegCookie) , mTypeLib(aTypeLib) +#if defined(MOZILLA_INTERNAL_API) , mIsRegisteredInMTA(IsCurrentThreadMTA()) +#endif // defined(MOZILLA_INTERNAL_API) { MOZ_ASSERT(aClassObject); MOZ_ASSERT(aTypeLib); @@ -287,7 +296,9 @@ RegisteredProxy::RegisteredProxy(IUnknown* aClassObject, uint32_t aRegCookie, , mClassObject(aClassObject) , mRegCookie(aRegCookie) , mTypeLib(aTypeLib) +#if defined(MOZILLA_INTERNAL_API) , mIsRegisteredInMTA(IsCurrentThreadMTA()) +#endif // defined(MOZILLA_INTERNAL_API) { MOZ_ASSERT(aClassObject); MOZ_ASSERT(aTypeLib); @@ -301,7 +312,9 @@ RegisteredProxy::RegisteredProxy(ITypeLib* aTypeLib) , mClassObject(nullptr) , mRegCookie(0) , mTypeLib(aTypeLib) +#if defined(MOZILLA_INTERNAL_API) , mIsRegisteredInMTA(false) +#endif // defined(MOZILLA_INTERNAL_API) { MOZ_ASSERT(aTypeLib); AddToRegistry(this); @@ -320,11 +333,16 @@ RegisteredProxy::~RegisteredProxy() ::CoRevokeClassObject(mRegCookie); mClassObject->lpVtbl->Release(mClassObject); }; +#if defined(MOZILLA_INTERNAL_API) + // This code only supports MTA when built internally if (mIsRegisteredInMTA) { EnsureMTA mta(cleanupFn); } else { cleanupFn(); } +#else + cleanupFn(); +#endif // defined(MOZILLA_INTERNAL_API) } if (mModule) { ::FreeLibrary(reinterpret_cast(mModule)); @@ -363,75 +381,120 @@ RegisteredProxy::GetTypeInfoForInterface(REFIID aIid, return mTypeLib->lpVtbl->GetTypeInfoOfGuid(mTypeLib, aIid, aOutTypeInfo); } -static StaticAutoPtr> sRegistry; -static StaticAutoPtr sRegMutex; -static StaticAutoPtr>> sArrayData; +static StaticAutoPtr> sRegistry; -static Mutex& +namespace UseGetMutexForAccess { + +// This must not be accessed directly; use GetMutex() instead +static CRITICAL_SECTION sMutex; + +} // UseGetMutexForAccess + +static CRITICAL_SECTION* GetMutex() { - static Mutex& mutex = []() -> Mutex& { - if (!sRegMutex) { - sRegMutex = new Mutex("RegisteredProxy::sRegMutex"); - ClearOnShutdown(&sRegMutex, ShutdownPhase::ShutdownThreads); - } - return *sRegMutex; + static CRITICAL_SECTION& mutex = []() -> CRITICAL_SECTION& { +#if defined(RELEASE_OR_BETA) + DWORD flags = CRITICAL_SECTION_NO_DEBUG_INFO; +#else + DWORD flags = 0; +#endif + InitializeCriticalSectionEx(&UseGetMutexForAccess::sMutex, 4000, flags); +#if !defined(MOZILLA_INTERNAL_API) + atexit([]() { DeleteCriticalSection(&UseGetMutexForAccess::sMutex); }); +#endif + return UseGetMutexForAccess::sMutex; }(); - return mutex; + return &mutex; } /* static */ bool RegisteredProxy::Find(REFIID aIid, ITypeInfo** aTypeInfo) { - MutexAutoLock lock(GetMutex()); - nsTArray& registry = *sRegistry; - for (uint32_t idx = 0, len = registry.Length(); idx < len; ++idx) { - if (SUCCEEDED(registry[idx]->GetTypeInfoForInterface(aIid, aTypeInfo))) { + AutoCriticalSection lock(GetMutex()); + + if (!sRegistry) { + return false; + } + + for (auto&& proxy : *sRegistry) { + if (SUCCEEDED(proxy->GetTypeInfoForInterface(aIid, aTypeInfo))) { return true; } } + return false; } /* static */ void RegisteredProxy::AddToRegistry(RegisteredProxy* aProxy) { - MutexAutoLock lock(GetMutex()); + MOZ_ASSERT(aProxy); + + AutoCriticalSection lock(GetMutex()); + if (!sRegistry) { - sRegistry = new nsTArray(); - ClearOnShutdown(&sRegistry); + sRegistry = new Vector(); + +#if !defined(MOZILLA_INTERNAL_API) + // sRegistry allocation is fallible outside of Mozilla processes + if (!sRegistry) { + return; + } +#endif } - sRegistry->AppendElement(aProxy); + + sRegistry->emplaceBack(aProxy); } /* static */ void RegisteredProxy::DeleteFromRegistry(RegisteredProxy* aProxy) { - MutexAutoLock lock(GetMutex()); - sRegistry->RemoveElement(aProxy); + MOZ_ASSERT(aProxy); + + AutoCriticalSection lock(GetMutex()); + + MOZ_ASSERT(sRegistry && !sRegistry->empty()); + + if (!sRegistry) { + return; + } + + sRegistry->erase(std::remove(sRegistry->begin(), sRegistry->end(), aProxy), + sRegistry->end()); + + if (sRegistry->empty()) { + sRegistry = nullptr; + } } +#if defined(MOZILLA_INTERNAL_API) + +static StaticAutoPtr>> sArrayData; + void RegisterArrayData(const ArrayData* aArrayData, size_t aLength) { - MutexAutoLock lock(GetMutex()); + AutoCriticalSection lock(GetMutex()); + if (!sArrayData) { - sArrayData = new nsTArray>(); + sArrayData = new Vector>(); ClearOnShutdown(&sArrayData, ShutdownPhase::ShutdownThreads); } - sArrayData->AppendElement(MakePair(aArrayData, aLength)); + + sArrayData->emplaceBack(MakePair(aArrayData, aLength)); } const ArrayData* FindArrayData(REFIID aIid, ULONG aMethodIndex) { - MutexAutoLock lock(GetMutex()); + AutoCriticalSection lock(GetMutex()); + if (!sArrayData) { return nullptr; } - for (uint32_t outerIdx = 0, outerLen = sArrayData->Length(); - outerIdx < outerLen; ++outerIdx) { - auto& data = sArrayData->ElementAt(outerIdx); + + for (auto&& data : *sArrayData) { for (size_t innerIdx = 0, innerLen = data.second(); innerIdx < innerLen; ++innerIdx) { const ArrayData* array = data.first(); @@ -441,8 +504,11 @@ FindArrayData(REFIID aIid, ULONG aMethodIndex) } } } + return nullptr; } +#endif // defined(MOZILLA_INTERNAL_API) + } // namespace mscom } // namespace mozilla diff --git a/ipc/mscom/Registration.h b/ipc/mscom/Registration.h index 32f14ba8839d..8cccd0f257fe 100644 --- a/ipc/mscom/Registration.h +++ b/ipc/mscom/Registration.h @@ -56,7 +56,9 @@ private: IUnknown* mClassObject; uint32_t mRegCookie; ITypeLib* mTypeLib; +#if defined(MOZILLA_INTERNAL_API) bool mIsRegisteredInMTA; +#endif // defined(MOZILLA_INTERNAL_API) }; enum class RegistrationFlags @@ -78,6 +80,8 @@ UniquePtr RegisterTypelib(const wchar_t* aLeafName, RegistrationFlags aFlags = RegistrationFlags::eUseBinDirectory); +#if defined(MOZILLA_INTERNAL_API) + /** * The COM interceptor uses type library information to build its interface * proxies. Unfortunately type libraries do not encode size_is and length_is @@ -144,6 +148,8 @@ RegisterArrayData(const ArrayData (&aData)[N]) const ArrayData* FindArrayData(REFIID aIid, ULONG aMethodIndex); +#endif // defined(MOZILLA_INTERNAL_API) + } // namespace mscom } // namespace mozilla