Bug 1310841: Make mscom registration use CoGetClassObject so that COM will retain a reference to the proxy dll; r=jimm

MozReview-Commit-ID: GZxbLCC6gVi

--HG--
extra : amend_source : 3cee23be271cfd35860869bd9446a3c95aaa4945
extra : histedit_source : 25a8893fff465ffc50dc95c2a8a5f011f0fd381f
This commit is contained in:
Aaron Klotz 2016-10-25 15:04:47 -06:00
parent a426b005cc
commit 938166ed49
5 changed files with 108 additions and 14 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="IA2Marshal" version="1.0.0.0" />
<file name="IA2Marshal.dll">
<comInterfaceProxyStub
iid="{E89F726E-C4F4-4c19-BB19-B647D7FA8478}"
proxyStubClsid32="{E89F726E-C4F4-4c19-BB19-B647D7FA8478}"
name="IAccessible2"
tlbid="{CE3F726E-D1D3-44FE-B995-FF1DB3B48B2B}"
/>
</file>
</assembly>

View File

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/mscom/ActivationContext.h"
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
namespace mozilla {
namespace mscom {
ActivationContext::ActivationContext(HMODULE aLoadFromModule)
: mActCtx(INVALID_HANDLE_VALUE)
, mActivationCookie(0)
{
ACTCTX actCtx = {sizeof(actCtx)};
actCtx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
actCtx.lpResourceName = MAKEINTRESOURCE(2);
actCtx.hModule = aLoadFromModule;
mActCtx = ::CreateActCtx(&actCtx);
MOZ_ASSERT(mActCtx != INVALID_HANDLE_VALUE);
if (mActCtx == INVALID_HANDLE_VALUE) {
return;
}
if (!::ActivateActCtx(mActCtx, &mActivationCookie)) {
::ReleaseActCtx(mActCtx);
mActCtx = INVALID_HANDLE_VALUE;
}
}
ActivationContext::~ActivationContext()
{
if (mActCtx == INVALID_HANDLE_VALUE) {
return;
}
DebugOnly<BOOL> deactivated = ::DeactivateActCtx(0, mActivationCookie);
MOZ_ASSERT(deactivated);
::ReleaseActCtx(mActCtx);
}
} // namespace mscom
} // namespace mozilla

View File

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_mscom_ActivationContext_h
#define mozilla_mscom_ActivationContext_h
#include <windows.h>
namespace mozilla {
namespace mscom {
class ActivationContext
{
public:
explicit ActivationContext(HMODULE aLoadFromModule);
~ActivationContext();
explicit operator bool() const
{
return mActCtx != INVALID_HANDLE_VALUE;
}
private:
HANDLE mActCtx;
ULONG_PTR mActivationCookie;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_ActivationContext_h

View File

@ -9,6 +9,7 @@
// anything else that could possibly pull in Windows header files.
#define CINTERFACE
#include "mozilla/mscom/ActivationContext.h"
#include "mozilla/mscom/EnsureMTA.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/mscom/Utils.h"
@ -21,6 +22,7 @@
#include "mozilla/Pair.h"
#include "mozilla/StaticPtr.h"
#include "nsTArray.h"
#include "nsWindowsHelpers.h"
#include <oaidl.h>
#include <objidl.h>
@ -86,22 +88,21 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
return nullptr;
}
HMODULE proxyDll = LoadLibrary(modulePathBuf);
if (!proxyDll) {
nsModuleHandle proxyDll(LoadLibrary(modulePathBuf));
if (!proxyDll.get()) {
return nullptr;
}
auto DllGetClassObjectFn = reinterpret_cast<LPFNGETCLASSOBJECT>(
GetProcAddress(proxyDll, "DllGetClassObject"));
if (!DllGetClassObjectFn) {
FreeLibrary(proxyDll);
// Instantiate an activation context so that CoGetClassObject will use any
// COM metadata embedded in proxyDll's manifest to resolve CLSIDs.
ActivationContext actCtx(proxyDll);
if (!actCtx) {
return nullptr;
}
auto GetProxyDllInfoFn = reinterpret_cast<GetProxyDllInfoFnPtr>(
GetProcAddress(proxyDll, "GetProxyDllInfo"));
if (!GetProxyDllInfoFn) {
FreeLibrary(proxyDll);
return nullptr;
}
@ -109,15 +110,15 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
const CLSID* proxyClsid = nullptr;
GetProxyDllInfoFn(&proxyInfo, &proxyClsid);
if (!proxyInfo || !proxyClsid) {
FreeLibrary(proxyDll);
return nullptr;
}
// We call CoGetClassObject instead of DllGetClassObject because it forces
// the COM runtime to manage the lifetime of the DLL.
IUnknown* classObject = nullptr;
HRESULT hr = DllGetClassObjectFn(*proxyClsid, IID_IUnknown,
(void**) &classObject);
HRESULT hr = CoGetClassObject(*proxyClsid, CLSCTX_INPROC_SERVER, nullptr,
IID_IUnknown, (void**) &classObject);
if (FAILED(hr)) {
FreeLibrary(proxyDll);
return nullptr;
}
@ -126,7 +127,6 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
REGCLS_MULTIPLEUSE, &regCookie);
if (FAILED(hr)) {
classObject->lpVtbl->Release(classObject);
FreeLibrary(proxyDll);
return nullptr;
}
@ -136,13 +136,12 @@ RegisterProxy(const wchar_t* aLeafName, RegistrationFlags aFlags)
if (FAILED(hr)) {
CoRevokeClassObject(regCookie);
classObject->lpVtbl->Release(classObject);
FreeLibrary(proxyDll);
return nullptr;
}
// RegisteredProxy takes ownership of proxyDll, classObject, and typeLib
// references
auto result(MakeUnique<RegisteredProxy>(reinterpret_cast<uintptr_t>(proxyDll),
auto result(MakeUnique<RegisteredProxy>(reinterpret_cast<uintptr_t>(proxyDll.disown()),
classObject, regCookie, typeLib));
while (*proxyInfo) {

View File

@ -26,6 +26,7 @@ UNIFIED_SOURCES += [
if CONFIG['ACCESSIBILITY']:
EXPORTS.mozilla.mscom += [
'ActivationContext.h',
'DispatchForwarder.h',
'Interceptor.h',
'InterceptorLog.h',
@ -42,6 +43,7 @@ if CONFIG['ACCESSIBILITY']:
]
UNIFIED_SOURCES += [
'ActivationContext.cpp',
'DispatchForwarder.cpp',
'InterceptorLog.cpp',
'MainThreadHandoff.cpp',