gecko-dev/ipc/mscom/FastMarshaler.cpp
James Teh de10571c3c Bug 1654969: Always disable COM pings for mscom::FastMarshaler (and thus mscom::Interceptor). r=aklotz
Previously, we only did this when IsCallerExternalProcess() returned false.
There are three reasons for changing this:

1. There seem to be cases where IsCallerExternalProcess() returns true even when marshaling for a COM query in the MTA.
2. After bug 1627084, we pre-build a11y handler payloads on the main thread for bulk fetch calls. That will marshal interceptors. However, IsCallerExternalProcess() can't work in that case because it's not running on the thread on which the COM call is being handled.
3. If MSHLFLAGS_NOPING is used, Release calls from remote clients are never sent to the server. So, as soon as we use NOPING for our parent process, we're already going to leak references, even if we don't use NOPING for external callers. Put another way, as soon as we use NOPING for one caller, we may as well use it for all callers because COM pinging will never release the object anyway.

Differential Revision: https://phabricator.services.mozilla.com/D84778
2020-07-29 21:11:14 +00:00

165 lines
3.9 KiB
C++

/* -*- 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/FastMarshaler.h"
#include "mozilla/mscom/Utils.h"
#include <objbase.h>
namespace mozilla {
namespace mscom {
HRESULT
FastMarshaler::Create(IUnknown* aOuter, IUnknown** aOutMarshalerUnk) {
MOZ_ASSERT(XRE_IsContentProcess());
if (!aOuter || !aOutMarshalerUnk) {
return E_INVALIDARG;
}
*aOutMarshalerUnk = nullptr;
HRESULT hr;
RefPtr<FastMarshaler> fm(new FastMarshaler(aOuter, &hr));
if (FAILED(hr)) {
return hr;
}
return fm->InternalQueryInterface(IID_IUnknown, (void**)aOutMarshalerUnk);
}
FastMarshaler::FastMarshaler(IUnknown* aOuter, HRESULT* aResult)
: mRefCnt(0), mOuter(aOuter), mStdMarshalWeak(nullptr) {
*aResult =
::CoGetStdMarshalEx(aOuter, SMEXF_SERVER, getter_AddRefs(mStdMarshalUnk));
if (FAILED(*aResult)) {
return;
}
*aResult =
mStdMarshalUnk->QueryInterface(IID_IMarshal, (void**)&mStdMarshalWeak);
if (FAILED(*aResult)) {
return;
}
// mStdMarshalWeak is weak
mStdMarshalWeak->Release();
}
HRESULT
FastMarshaler::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;
}
return mStdMarshalUnk->QueryInterface(riid, ppv);
}
ULONG
FastMarshaler::InternalAddRef() { return ++mRefCnt; }
ULONG
FastMarshaler::InternalRelease() {
ULONG result = --mRefCnt;
if (!result) {
delete this;
}
return result;
}
DWORD
FastMarshaler::GetMarshalFlags(DWORD aDestContext, DWORD aMshlFlags) {
// Only worry about local contexts.
if (aDestContext != MSHCTX_LOCAL) {
return aMshlFlags;
}
return aMshlFlags | MSHLFLAGS_NOPING;
}
HRESULT
FastMarshaler::GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags,
CLSID* pCid) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->GetUnmarshalClass(
riid, pv, dwDestContext, pvDestContext,
GetMarshalFlags(dwDestContext, mshlflags), pCid);
}
HRESULT
FastMarshaler::GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags,
DWORD* pSize) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->GetMarshalSizeMax(
riid, pv, dwDestContext, pvDestContext,
GetMarshalFlags(dwDestContext, mshlflags), pSize);
}
HRESULT
FastMarshaler::MarshalInterface(IStream* pStm, REFIID riid, void* pv,
DWORD dwDestContext, void* pvDestContext,
DWORD mshlflags) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->MarshalInterface(
pStm, riid, pv, dwDestContext, pvDestContext,
GetMarshalFlags(dwDestContext, mshlflags));
}
HRESULT
FastMarshaler::UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->UnmarshalInterface(pStm, riid, ppv);
}
HRESULT
FastMarshaler::ReleaseMarshalData(IStream* pStm) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->ReleaseMarshalData(pStm);
}
HRESULT
FastMarshaler::DisconnectObject(DWORD dwReserved) {
if (!mStdMarshalWeak) {
return E_POINTER;
}
return mStdMarshalWeak->DisconnectObject(dwReserved);
}
} // namespace mscom
} // namespace mozilla