зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1303060: Additions to ipc/mscom for out-of-process components; r=jimm
MozReview-Commit-ID: IYjONGbBraG --HG-- extra : rebase_source : a6eb90db7a9c21b91b9e763a15a9a661d41c5e77
This commit is contained in:
Родитель
af5bd498da
Коммит
f3b557f70c
|
@ -26,6 +26,10 @@ UNIFIED_SOURCES += [
|
|||
]
|
||||
|
||||
if CONFIG['ACCESSIBILITY']:
|
||||
DIRS += [
|
||||
'oop',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.mscom += [
|
||||
'ActivationContext.h',
|
||||
'DispatchForwarder.h',
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- 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_Factory_h
|
||||
#define mozilla_mscom_Factory_h
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#error This code is NOT for internal Gecko use!
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "Module.h"
|
||||
|
||||
#include <objbase.h>
|
||||
#include <unknwn.h>
|
||||
|
||||
/* WARNING! The code in this file may be loaded into the address spaces of other
|
||||
processes! It MUST NOT link against xul.dll or other Gecko binaries! Only
|
||||
inline code may be included! */
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
template <typename T>
|
||||
class MOZ_NONHEAP_CLASS Factory : public IClassFactory
|
||||
{
|
||||
template <typename... Args>
|
||||
HRESULT DoCreate(Args... args)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "This should not be executed");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
HRESULT DoCreate(HRESULT (*aFnPtr)(IUnknown*, REFIID, void**), Args... args)
|
||||
{
|
||||
return aFnPtr(mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
// IUnknown
|
||||
STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override
|
||||
{
|
||||
if (!aOutInterface) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (aIid == IID_IUnknown || aIid == IID_IClassFactory) {
|
||||
RefPtr<IClassFactory> punk(this);
|
||||
punk.forget(aOutInterface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*aOutInterface = nullptr;
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) AddRef() override
|
||||
{
|
||||
Module::Lock();
|
||||
return 2;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG) Release() override
|
||||
{
|
||||
Module::Unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// IClassFactory
|
||||
STDMETHODIMP CreateInstance(IUnknown* aOuter, REFIID aIid,
|
||||
void** aOutInterface) override
|
||||
{
|
||||
return DoCreate(&T::Create, aOuter, aIid, aOutInterface);
|
||||
}
|
||||
|
||||
STDMETHODIMP LockServer(BOOL aLock) override
|
||||
{
|
||||
if (aLock) {
|
||||
Module::Lock();
|
||||
} else {
|
||||
Module::Unlock();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MOZ_NONHEAP_CLASS SingletonFactory : public Factory<T>
|
||||
{
|
||||
public:
|
||||
STDMETHODIMP CreateInstance(IUnknown* aOuter, REFIID aIid,
|
||||
void** aOutInterface) override
|
||||
{
|
||||
if (aOuter || !aOutInterface) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
RefPtr<T> obj(sInstance);
|
||||
if (!obj) {
|
||||
obj = GetOrCreateSingleton();
|
||||
}
|
||||
|
||||
return obj->QueryInterface(aIid, aOutInterface);
|
||||
}
|
||||
|
||||
RefPtr<T> GetOrCreateSingleton()
|
||||
{
|
||||
if (!sInstance) {
|
||||
RefPtr<T> object;
|
||||
if (FAILED(T::Create(getter_AddRefs(object)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sInstance = object.forget();
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
RefPtr<T> GetSingleton()
|
||||
{
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
void ClearSingleton()
|
||||
{
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<HRESULT> hr = ::CoDisconnectObject(sInstance.get(), 0);
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
static StaticRefPtr<T> sInstance;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
StaticRefPtr<T> SingletonFactory<T>::sInstance;
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_mscom_Factory_h
|
|
@ -0,0 +1,339 @@
|
|||
/* -*- 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 "Handler.h"
|
||||
#include "Module.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
#include <objbase.h>
|
||||
#include <shlwapi.h>
|
||||
#include <string.h>
|
||||
|
||||
/* WARNING! The code in this file may be loaded into the address spaces of other
|
||||
processes! It MUST NOT link against xul.dll or other Gecko binaries! Only
|
||||
inline code may be included! */
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
Handler::Handler(IUnknown* aOuter, HRESULT& aResult)
|
||||
: mRefCnt(0)
|
||||
, mOuter(aOuter)
|
||||
, mUnmarshal(nullptr)
|
||||
, mHasPayload(false)
|
||||
{
|
||||
if (!aOuter) {
|
||||
aResult = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
|
||||
StabilizedRefCount<ULONG> stabilizer(mRefCnt);
|
||||
|
||||
aResult = ::CoGetStdMarshalEx(aOuter, SMEXF_HANDLER,
|
||||
getter_AddRefs(mInnerUnk));
|
||||
if (FAILED(aResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
aResult = mInnerUnk->QueryInterface(IID_IMarshal, (void**)&mUnmarshal);
|
||||
if (FAILED(aResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// mInnerMarshal is a weak ref
|
||||
mUnmarshal->Release();
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::InternalQueryInterface(REFIID riid, void** ppv)
|
||||
{
|
||||
if (!ppv) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (riid == IID_IUnknown) {
|
||||
RefPtr<IUnknown> punk(static_cast<IUnknown*>(&mInternalUnknown));
|
||||
punk.forget(ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (riid == IID_IMarshal) {
|
||||
RefPtr<IMarshal> ptr(this);
|
||||
ptr.forget(ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Try the handler implementation
|
||||
HRESULT hr = QueryHandlerInterface(mInnerUnk, riid, ppv);
|
||||
if (hr != E_NOINTERFACE) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Now forward to the marshaler's inner
|
||||
return mInnerUnk->QueryInterface(riid, ppv);
|
||||
}
|
||||
|
||||
ULONG
|
||||
Handler::InternalAddRef()
|
||||
{
|
||||
if (!mRefCnt) {
|
||||
Module::Lock();
|
||||
}
|
||||
return ++mRefCnt;
|
||||
}
|
||||
|
||||
ULONG
|
||||
Handler::InternalRelease()
|
||||
{
|
||||
if (--mRefCnt == 0) {
|
||||
delete this;
|
||||
Module::Unlock();
|
||||
}
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
CLSID* pCid)
|
||||
{
|
||||
return mUnmarshal->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext,
|
||||
mshlflags, pCid);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
DWORD* pSize)
|
||||
{
|
||||
if (!pSize) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pSize = 0;
|
||||
|
||||
RefPtr<IUnknown> unkToMarshal;
|
||||
HRESULT hr;
|
||||
|
||||
REFIID marshalAs = MarshalAs(riid);
|
||||
if (marshalAs == riid) {
|
||||
unkToMarshal = static_cast<IUnknown*>(pv);
|
||||
} else {
|
||||
hr = mInnerUnk->QueryInterface(marshalAs, getter_AddRefs(unkToMarshal));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
// We do not necessarily want to use the pv that COM is giving us; we may want
|
||||
// to marshal a different proxy that is more appropriate to what we're
|
||||
// wrapping...
|
||||
hr = mUnmarshal->GetMarshalSizeMax(marshalAs, unkToMarshal.get(),
|
||||
dwDestContext, pvDestContext,
|
||||
mshlflags, pSize);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (!HasPayload()) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DWORD payloadSize = 0;
|
||||
hr = GetHandlerPayloadSize(marshalAs, &payloadSize);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
*pSize += payloadSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::MarshalInterface(IStream* pStm, REFIID riid, void* pv,
|
||||
DWORD dwDestContext, void* pvDestContext,
|
||||
DWORD mshlflags)
|
||||
{
|
||||
// We do not necessarily want to use the pv that COM is giving us; we may want
|
||||
// to marshal a different proxy that is more appropriate to what we're
|
||||
// wrapping...
|
||||
RefPtr<IUnknown> unkToMarshal;
|
||||
HRESULT hr;
|
||||
|
||||
REFIID marshalAs = MarshalAs(riid);
|
||||
if (marshalAs == riid) {
|
||||
unkToMarshal = static_cast<IUnknown*>(pv);
|
||||
} else {
|
||||
hr = mInnerUnk->QueryInterface(marshalAs, getter_AddRefs(unkToMarshal));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = mUnmarshal->MarshalInterface(pStm, marshalAs, unkToMarshal.get(),
|
||||
dwDestContext, pvDestContext, mshlflags);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (!HasPayload()) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Unfortunately when COM re-marshals a proxy that prevouisly had a payload,
|
||||
// we must re-serialize it.
|
||||
return WriteHandlerPayload(pStm, marshalAs);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv)
|
||||
{
|
||||
REFIID unmarshalAs = MarshalAs(riid);
|
||||
HRESULT hr = mUnmarshal->UnmarshalInterface(pStm, unmarshalAs, ppv);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = ReadHandlerPayload(pStm, unmarshalAs);
|
||||
|
||||
// This method may be called on the same object multiple times (as new
|
||||
// interfaces are queried off the proxy). Not all interfaces will necessarily
|
||||
// refresh the payload, so we set mHasPayload using OR to reflect that fact.
|
||||
// (Otherwise mHasPayload could be cleared and the handler would think that
|
||||
// it doesn't have a payload even though it actually does).
|
||||
mHasPayload |= (hr == S_OK);
|
||||
|
||||
// hr may be S_FALSE, but we don't want to return that
|
||||
return SUCCEEDED(hr) ? S_OK : hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::ReleaseMarshalData(IStream* pStm)
|
||||
{
|
||||
return mUnmarshal->ReleaseMarshalData(pStm);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::DisconnectObject(DWORD dwReserved)
|
||||
{
|
||||
return mUnmarshal->DisconnectObject(dwReserved);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static HRESULT
|
||||
BuildClsidPath(wchar_t (&aPath)[N], REFCLSID aClsid)
|
||||
{
|
||||
const wchar_t kClsid[] = {L'C', L'L', L'S', L'I', L'D', L'\\'};
|
||||
const size_t kReqdGuidLen = 39;
|
||||
static_assert(N >= kReqdGuidLen + mozilla::ArrayLength(kClsid),
|
||||
"aPath array is too short");
|
||||
if (wcsncpy_s(aPath, kClsid, mozilla::ArrayLength(kClsid))) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
int guidConversionResult =
|
||||
StringFromGUID2(aClsid, &aPath[mozilla::ArrayLength(kClsid)],
|
||||
N - mozilla::ArrayLength(kClsid));
|
||||
if (!guidConversionResult) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::Unregister(REFCLSID aClsid)
|
||||
{
|
||||
wchar_t path[256] = {};
|
||||
HRESULT hr = BuildClsidPath(path, aClsid);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = HRESULT_FROM_WIN32(SHDeleteKey(HKEY_CLASSES_ROOT, path));
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Handler::Register(REFCLSID aClsid)
|
||||
{
|
||||
wchar_t path[256] = {};
|
||||
HRESULT hr = BuildClsidPath(path, aClsid);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
HKEY rawClsidKey;
|
||||
DWORD disposition;
|
||||
LONG result = RegCreateKeyEx(HKEY_CLASSES_ROOT, path, 0, nullptr,
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
|
||||
nullptr, &rawClsidKey, &disposition);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
return HRESULT_FROM_WIN32(result);
|
||||
}
|
||||
nsAutoRegKey clsidKey(rawClsidKey);
|
||||
|
||||
if (wcscat_s(path, L"\\InprocHandler32")) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
HKEY rawInprocHandlerKey;
|
||||
result = RegCreateKeyEx(HKEY_CLASSES_ROOT, path, 0, nullptr,
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
|
||||
nullptr, &rawInprocHandlerKey, &disposition);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
Unregister(aClsid);
|
||||
return HRESULT_FROM_WIN32(result);
|
||||
}
|
||||
nsAutoRegKey inprocHandlerKey(rawInprocHandlerKey);
|
||||
|
||||
wchar_t absLibPath[MAX_PATH + 1] = {};
|
||||
HMODULE thisModule;
|
||||
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCTSTR>(&Handler::Register),
|
||||
&thisModule)) {
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
DWORD size = GetModuleFileName(thisModule, absLibPath,
|
||||
mozilla::ArrayLength(absLibPath));
|
||||
if (!size || (size == mozilla::ArrayLength(absLibPath) &&
|
||||
GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
|
||||
DWORD lastError = GetLastError();
|
||||
Unregister(aClsid);
|
||||
return HRESULT_FROM_WIN32(lastError);
|
||||
}
|
||||
|
||||
result = RegSetValueEx(inprocHandlerKey, L"", 0, REG_EXPAND_SZ,
|
||||
reinterpret_cast<const BYTE*>(absLibPath),
|
||||
sizeof(absLibPath));
|
||||
if (result != ERROR_SUCCESS) {
|
||||
Unregister(aClsid);
|
||||
return HRESULT_FROM_WIN32(result);
|
||||
}
|
||||
|
||||
const wchar_t kApartment[] = L"Apartment";
|
||||
result = RegSetValueEx(inprocHandlerKey, L"ThreadingModel", 0, REG_SZ,
|
||||
reinterpret_cast<const BYTE*>(kApartment),
|
||||
sizeof(kApartment));
|
||||
if (result != ERROR_SUCCESS) {
|
||||
Unregister(aClsid);
|
||||
return HRESULT_FROM_WIN32(result);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/* -*- 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_Handler_h
|
||||
#define mozilla_mscom_Handler_h
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#error This code is NOT for internal Gecko use!
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
#include <objidl.h>
|
||||
|
||||
#include "mozilla/mscom/Aggregation.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
/* WARNING! The code in this file may be loaded into the address spaces of other
|
||||
processes! It MUST NOT link against xul.dll or other Gecko binaries! Only
|
||||
inline code may be included! */
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
class Handler : public IMarshal
|
||||
{
|
||||
public:
|
||||
// IMarshal
|
||||
STDMETHODIMP GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
CLSID* pCid) override;
|
||||
STDMETHODIMP GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
|
||||
void* pvDestContext, DWORD mshlflags,
|
||||
DWORD* pSize) override;
|
||||
STDMETHODIMP MarshalInterface(IStream* pStm, REFIID riid, void* pv,
|
||||
DWORD dwDestContext, void* pvDestContext,
|
||||
DWORD mshlflags) override;
|
||||
STDMETHODIMP UnmarshalInterface(IStream* pStm, REFIID riid,
|
||||
void** ppv) override;
|
||||
STDMETHODIMP ReleaseMarshalData(IStream* pStm) override;
|
||||
STDMETHODIMP DisconnectObject(DWORD dwReserved) override;
|
||||
|
||||
/**
|
||||
* This method allows the handler to return its own interfaces that override
|
||||
* those interfaces that are exposed by the underlying COM proxy.
|
||||
* @param aProxyUnknown is the IUnknown of the underlying COM proxy. This is
|
||||
* provided to give the handler implementation an
|
||||
* opportunity to acquire interfaces to the underlying
|
||||
* remote object, if needed.
|
||||
* @param aIid Interface requested, similar to IUnknown::QueryInterface
|
||||
* @param aOutInterface Outparam for the resulting interface to return to the
|
||||
* client.
|
||||
* @return The usual HRESULT codes similarly to IUnknown::QueryInterface
|
||||
*/
|
||||
virtual HRESULT QueryHandlerInterface(IUnknown* aProxyUnknown, REFIID aIid,
|
||||
void** aOutInterface) = 0;
|
||||
/**
|
||||
* Called when the implementer should deserialize data in aStream.
|
||||
* @return S_OK on success;
|
||||
* S_FALSE if the deserialization was successful but there was no data;
|
||||
* HRESULT error code otherwise.
|
||||
*/
|
||||
virtual HRESULT ReadHandlerPayload(IStream* aStream, REFIID aIid)
|
||||
{ return S_FALSE; }
|
||||
|
||||
/**
|
||||
* Unfortunately when COM marshals a proxy, it doesn't implicitly marshal
|
||||
* the payload that was originally sent with the proxy. We must implement
|
||||
* that code in the handler in order to make this happen.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function allows the implementer to substitute a different interface
|
||||
* for marshaling than the one that COM is intending to marshal. For example,
|
||||
* the implementer might want to marshal a proxy for an interface that is
|
||||
* derived from the requested interface.
|
||||
*
|
||||
* The default implementation is the identity function.
|
||||
*/
|
||||
virtual REFIID MarshalAs(REFIID aRequestedIid) { return aRequestedIid; }
|
||||
|
||||
/**
|
||||
* Called when the implementer must provide the size of the payload.
|
||||
*/
|
||||
virtual HRESULT GetHandlerPayloadSize(REFIID aIid, DWORD* aOutPayloadSize)
|
||||
{
|
||||
if (!aOutPayloadSize) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*aOutPayloadSize = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the implementer should serialize the payload data into aStream.
|
||||
*/
|
||||
virtual HRESULT WriteHandlerPayload(IStream* aStream, REFIID aIid)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IUnknown* GetProxy() const { return mInnerUnk; }
|
||||
|
||||
static HRESULT Register(REFCLSID aClsid);
|
||||
static HRESULT Unregister(REFCLSID aClsid);
|
||||
|
||||
protected:
|
||||
Handler(IUnknown* aOuter, HRESULT& aResult);
|
||||
virtual ~Handler() {}
|
||||
bool HasPayload() const { return mHasPayload; }
|
||||
IUnknown* GetOuter() const { return mOuter; }
|
||||
|
||||
private:
|
||||
ULONG mRefCnt;
|
||||
IUnknown* mOuter;
|
||||
RefPtr<IUnknown> mInnerUnk;
|
||||
IMarshal* mUnmarshal; // WEAK
|
||||
bool mHasPayload;
|
||||
DECLARE_AGGREGATABLE(Handler);
|
||||
};
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_mscom_Handler_h
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- 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 "Module.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <rpc.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
ULONG Module::sRefCount = 0;
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- 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_Module_h
|
||||
#define mozilla_mscom_Module_h
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#error This code is NOT for internal Gecko use!
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
#include <objbase.h>
|
||||
|
||||
/* WARNING! The code in this file may be loaded into the address spaces of other
|
||||
processes! It MUST NOT link against xul.dll or other Gecko binaries! Only
|
||||
inline code may be included! */
|
||||
|
||||
namespace mozilla {
|
||||
namespace mscom {
|
||||
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
static HRESULT CanUnload() { return sRefCount == 0 ? S_OK : S_FALSE; }
|
||||
|
||||
static void Lock() { ++sRefCount; }
|
||||
static void Unlock() { --sRefCount; }
|
||||
|
||||
private:
|
||||
static ULONG sRefCount;
|
||||
};
|
||||
|
||||
} // namespace mscom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_mscom_Module_h
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
Library('mscom_oop')
|
||||
|
||||
SOURCES += [
|
||||
'../ActivationContext.cpp',
|
||||
'../Registration.cpp',
|
||||
'../StructStream.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Handler.cpp',
|
||||
'Module.cpp',
|
||||
]
|
||||
|
||||
OS_LIBS += [
|
||||
'ole32',
|
||||
'oleaut32',
|
||||
'shlwapi',
|
||||
]
|
||||
|
||||
LIBRARY_DEFINES['UNICODE'] = True
|
||||
LIBRARY_DEFINES['_UNICODE'] = True
|
||||
LIBRARY_DEFINES['MOZ_NO_MOZALLOC'] = True
|
||||
|
||||
DISABLE_STL_WRAPPING = True
|
||||
NO_EXPAND_LIBS = True
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
# This DLL may be loaded into other processes, so we need static libs for
|
||||
# Windows 7 and Windows 8.
|
||||
USE_STATIC_LIBS = True
|
Загрузка…
Ссылка в новой задаче