Bug 1303060: Additions to ipc/mscom for out-of-process components; r?jimm
MozReview-Commit-ID: IYjONGbBraG
--- a/ipc/mscom/moz.build
+++ b/ipc/mscom/moz.build
@@ -21,16 +21,20 @@ UNIFIED_SOURCES += [
'AgileReference.cpp',
'EnsureMTA.cpp',
'MainThreadRuntime.cpp',
'ProxyStream.cpp',
'Utils.cpp',
]
if CONFIG['ACCESSIBILITY']:
+ DIRS += [
+ 'oop',
+ ]
+
EXPORTS.mozilla.mscom += [
'ActivationContext.h',
'DispatchForwarder.h',
'IHandlerPayload.h',
'Interceptor.h',
'InterceptorLog.h',
'MainThreadHandoff.h',
'MainThreadInvoker.h',
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/Factory.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
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/Handler.cpp
@@ -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
+
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/Handler.h
@@ -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
+
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/Module.cpp
@@ -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
+
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/Module.h
@@ -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
+
new file mode 100644
--- /dev/null
+++ b/ipc/mscom/oop/moz.build
@@ -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