mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1331687: Overload mscom::RegisterProxy to allow proxy registration from within xul.dll itself; r=jimm
MozReview-Commit-ID: EiIS5sOCntb --HG-- extra : rebase_source : e0c5f6001bc4c85bdf1db10baa748e393df5a031
This commit is contained in:
parent
5b748059a7
commit
a2e223b2f8
@ -7,12 +7,14 @@
|
|||||||
#ifndef mozilla_mscom_ActivationContext_h
|
#ifndef mozilla_mscom_ActivationContext_h
|
||||||
#define mozilla_mscom_ActivationContext_h
|
#define mozilla_mscom_ActivationContext_h
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace mscom {
|
namespace mscom {
|
||||||
|
|
||||||
class ActivationContext
|
class MOZ_RAII ActivationContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ActivationContext(HMODULE aLoadFromModule);
|
explicit ActivationContext(HMODULE aLoadFromModule);
|
||||||
@ -23,6 +25,11 @@ public:
|
|||||||
return mActCtx != INVALID_HANDLE_VALUE;
|
return mActCtx != INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ActivationContext(const ActivationContext&) = delete;
|
||||||
|
ActivationContext(ActivationContext&&) = delete;
|
||||||
|
ActivationContext& operator=(const ActivationContext&) = delete;
|
||||||
|
ActivationContext& operator=(ActivationContext&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HANDLE mActCtx;
|
HANDLE mActCtx;
|
||||||
ULONG_PTR mActivationCookie;
|
ULONG_PTR mActivationCookie;
|
||||||
|
@ -32,35 +32,64 @@
|
|||||||
/* This code MUST NOT use any non-inlined internal Mozilla APIs, as it will be
|
/* 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! */
|
compiled into DLLs that COM may load into non-Mozilla processes! */
|
||||||
|
|
||||||
namespace {
|
extern "C" {
|
||||||
|
|
||||||
// This function is defined in generated code for proxy DLLs but is not declared
|
// This function is defined in generated code for proxy DLLs but is not declared
|
||||||
// in rpcproxy.h, so we need this typedef.
|
// in rpcproxy.h, so we need this declaration.
|
||||||
typedef void (RPC_ENTRY *GetProxyDllInfoFnPtr)(const ProxyFileInfo*** aInfo,
|
void RPC_ENTRY GetProxyDllInfo(const ProxyFileInfo*** aInfo, const CLSID** aId);
|
||||||
const CLSID** aId);
|
|
||||||
|
|
||||||
} // anonymous namespace
|
#if defined(_MSC_VER)
|
||||||
|
extern IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace mscom {
|
namespace mscom {
|
||||||
|
|
||||||
|
static HMODULE
|
||||||
|
GetContainingModule()
|
||||||
|
{
|
||||||
|
HMODULE thisModule = nullptr;
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
thisModule = reinterpret_cast<HMODULE>(&__ImageBase);
|
||||||
|
#else
|
||||||
|
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||||
|
GET_MODULE_HANDLE_EX_UNCHANGED_REFCOUNT,
|
||||||
|
reinterpret_cast<LPCTSTR>(&GetContainingModule),
|
||||||
|
&thisModule)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return thisModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetContainingLibPath(wchar_t* aBuffer, size_t aBufferLen)
|
||||||
|
{
|
||||||
|
HMODULE thisModule = GetContainingModule();
|
||||||
|
if (!thisModule) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD fileNameResult = GetModuleFileName(thisModule, aBuffer, aBufferLen);
|
||||||
|
if (!fileNameResult || (fileNameResult == aBufferLen &&
|
||||||
|
::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
BuildLibPath(RegistrationFlags aFlags, wchar_t* aBuffer, size_t aBufferLen,
|
BuildLibPath(RegistrationFlags aFlags, wchar_t* aBuffer, size_t aBufferLen,
|
||||||
const wchar_t* aLeafName)
|
const wchar_t* aLeafName)
|
||||||
{
|
{
|
||||||
if (aFlags == RegistrationFlags::eUseBinDirectory) {
|
if (aFlags == RegistrationFlags::eUseBinDirectory) {
|
||||||
HMODULE thisModule = nullptr;
|
if (!GetContainingLibPath(aBuffer, aBufferLen)) {
|
||||||
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
|
||||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
|
||||||
reinterpret_cast<LPCTSTR>(&RegisterProxy),
|
|
||||||
&thisModule)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DWORD fileNameResult = GetModuleFileName(thisModule, aBuffer, aBufferLen);
|
|
||||||
if (!fileNameResult || (fileNameResult == aBufferLen &&
|
|
||||||
::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PathRemoveFileSpec(aBuffer)) {
|
if (!PathRemoveFileSpec(aBuffer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -79,6 +108,74 @@ BuildLibPath(RegistrationFlags aFlags, wchar_t* aBuffer, size_t aBufferLen,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
RegisterPSClsids(const ProxyFileInfo** aProxyInfo, const CLSID* aProxyClsid)
|
||||||
|
{
|
||||||
|
while (*aProxyInfo) {
|
||||||
|
const ProxyFileInfo& curInfo = **aProxyInfo;
|
||||||
|
for (unsigned short idx = 0, size = curInfo.TableSize; idx < size; ++idx) {
|
||||||
|
HRESULT hr = CoRegisterPSClsid(*(curInfo.pStubVtblList[idx]->header.piid),
|
||||||
|
*aProxyClsid);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++aProxyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniquePtr<RegisteredProxy>
|
||||||
|
RegisterProxy()
|
||||||
|
{
|
||||||
|
const ProxyFileInfo** proxyInfo = nullptr;
|
||||||
|
const CLSID* proxyClsid = nullptr;
|
||||||
|
GetProxyDllInfo(&proxyInfo, &proxyClsid);
|
||||||
|
if (!proxyInfo || !proxyClsid) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IUnknown* classObject = nullptr;
|
||||||
|
HRESULT hr = DllGetClassObject(*proxyClsid, IID_IUnknown, (void**)&classObject);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD regCookie;
|
||||||
|
hr = CoRegisterClassObject(*proxyClsid, classObject, CLSCTX_INPROC_SERVER,
|
||||||
|
REGCLS_MULTIPLEUSE, ®Cookie);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
classObject->lpVtbl->Release(classObject);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t modulePathBuf[MAX_PATH + 1] = {0};
|
||||||
|
if (!GetContainingLibPath(modulePathBuf, ArrayLength(modulePathBuf))) {
|
||||||
|
CoRevokeClassObject(regCookie);
|
||||||
|
classObject->lpVtbl->Release(classObject);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeLib* typeLib = nullptr;
|
||||||
|
hr = LoadTypeLibEx(modulePathBuf, REGKIND_NONE, &typeLib);
|
||||||
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
CoRevokeClassObject(regCookie);
|
||||||
|
classObject->lpVtbl->Release(classObject);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisteredProxy takes ownership of classObject and typeLib references
|
||||||
|
auto result(MakeUnique<RegisteredProxy>(classObject, regCookie, typeLib));
|
||||||
|
|
||||||
|
if (!RegisterPSClsids(proxyInfo, proxyClsid)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
UniquePtr<RegisteredProxy>
|
UniquePtr<RegisteredProxy>
|
||||||
RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
|
RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
|
||||||
{
|
{
|
||||||
@ -100,7 +197,7 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto GetProxyDllInfoFn = reinterpret_cast<GetProxyDllInfoFnPtr>(
|
auto GetProxyDllInfoFn = reinterpret_cast<decltype(&GetProxyDllInfo)>(
|
||||||
GetProcAddress(proxyDll, "GetProxyDllInfo"));
|
GetProcAddress(proxyDll, "GetProxyDllInfo"));
|
||||||
if (!GetProxyDllInfoFn) {
|
if (!GetProxyDllInfoFn) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -144,16 +241,8 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
|
|||||||
auto result(MakeUnique<RegisteredProxy>(reinterpret_cast<uintptr_t>(proxyDll.disown()),
|
auto result(MakeUnique<RegisteredProxy>(reinterpret_cast<uintptr_t>(proxyDll.disown()),
|
||||||
classObject, regCookie, typeLib));
|
classObject, regCookie, typeLib));
|
||||||
|
|
||||||
while (*proxyInfo) {
|
if (!RegisterPSClsids(proxyInfo, proxyClsid)) {
|
||||||
const ProxyFileInfo& curInfo = **proxyInfo;
|
return nullptr;
|
||||||
for (unsigned short i = 0, e = curInfo.TableSize; i < e; ++i) {
|
|
||||||
hr = CoRegisterPSClsid(*(curInfo.pStubVtblList[i]->header.piid),
|
|
||||||
*proxyClsid);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++proxyInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -192,6 +281,19 @@ RegisteredProxy::RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject,
|
|||||||
AddToRegistry(this);
|
AddToRegistry(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegisteredProxy::RegisteredProxy(IUnknown* aClassObject, uint32_t aRegCookie,
|
||||||
|
ITypeLib* aTypeLib)
|
||||||
|
: mModule(0)
|
||||||
|
, mClassObject(aClassObject)
|
||||||
|
, mRegCookie(aRegCookie)
|
||||||
|
, mTypeLib(aTypeLib)
|
||||||
|
, mIsRegisteredInMTA(IsCurrentThreadMTA())
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aClassObject);
|
||||||
|
MOZ_ASSERT(aTypeLib);
|
||||||
|
AddToRegistry(this);
|
||||||
|
}
|
||||||
|
|
||||||
// If we're initializing from a typelib, it doesn't matter which apartment we
|
// If we're initializing from a typelib, it doesn't matter which apartment we
|
||||||
// run in, so mIsRegisteredInMTA may always be set to false in this case.
|
// run in, so mIsRegisteredInMTA may always be set to false in this case.
|
||||||
RegisteredProxy::RegisteredProxy(ITypeLib* aTypeLib)
|
RegisteredProxy::RegisteredProxy(ITypeLib* aTypeLib)
|
||||||
|
@ -28,6 +28,8 @@ class RegisteredProxy
|
|||||||
public:
|
public:
|
||||||
RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject,
|
RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject,
|
||||||
uint32_t aRegCookie, ITypeLib* aTypeLib);
|
uint32_t aRegCookie, ITypeLib* aTypeLib);
|
||||||
|
RegisteredProxy(IUnknown* aClassObject, uint32_t aRegCookie,
|
||||||
|
ITypeLib* aTypeLib);
|
||||||
explicit RegisteredProxy(ITypeLib* aTypeLib);
|
explicit RegisteredProxy(ITypeLib* aTypeLib);
|
||||||
RegisteredProxy(RegisteredProxy&& aOther);
|
RegisteredProxy(RegisteredProxy&& aOther);
|
||||||
RegisteredProxy& operator=(RegisteredProxy&& aOther);
|
RegisteredProxy& operator=(RegisteredProxy&& aOther);
|
||||||
@ -63,6 +65,10 @@ enum class RegistrationFlags
|
|||||||
eUseSystemDirectory
|
eUseSystemDirectory
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For our own DLL that we are currently executing in (ie, xul).
|
||||||
|
// Assumes corresponding TLB is embedded in resources.
|
||||||
|
UniquePtr<RegisteredProxy> RegisterProxy();
|
||||||
|
|
||||||
// For DLL files. Assumes corresponding TLB is embedded in resources.
|
// For DLL files. Assumes corresponding TLB is embedded in resources.
|
||||||
UniquePtr<RegisteredProxy> RegisterProxy(const wchar_t* aLeafName,
|
UniquePtr<RegisteredProxy> RegisterProxy(const wchar_t* aLeafName,
|
||||||
RegistrationFlags aFlags =
|
RegistrationFlags aFlags =
|
||||||
|
Loading…
Reference in New Issue
Block a user