mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1325834: Make mscom::ProxyStream use CreateStreamOnHGlobal instead of SHCreateMemStream on Windows 7; r=jimm
MozReview-Commit-ID: FAlPgS6iJL
This commit is contained in:
parent
7b5efdb1fd
commit
45cba5a03b
@ -106,7 +106,9 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
|
|||||||
const BYTE* buf = proxyStream.GetBuffer(bufLen);
|
const BYTE* buf = proxyStream.GetBuffer(bufLen);
|
||||||
MOZ_ASSERT(buf || !bufLen);
|
MOZ_ASSERT(buf || !bufLen);
|
||||||
aMsg->WriteInt(bufLen);
|
aMsg->WriteInt(bufLen);
|
||||||
aMsg->WriteBytes(reinterpret_cast<const char*>(buf), bufLen);
|
if (bufLen) {
|
||||||
|
aMsg->WriteBytes(reinterpret_cast<const char*>(buf), bufLen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||||
@ -128,11 +130,12 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
|
|||||||
if (!proxyStream.IsValid()) {
|
if (!proxyStream.IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Interface* rawInterface = nullptr;
|
|
||||||
if (!proxyStream.GetInterface(_IID, (void**)&rawInterface)) {
|
typename paramType::COMPtrType ptr;
|
||||||
|
if (!proxyStream.GetInterface(_IID, mozilla::mscom::getter_AddRefs(ptr))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
typename paramType::COMPtrType ptr(rawInterface);
|
|
||||||
aResult->Set(mozilla::Move(ptr));
|
aResult->Set(mozilla::Move(ptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "mozilla/mscom/EnsureMTA.h"
|
#include "mozilla/mscom/EnsureMTA.h"
|
||||||
#include "mozilla/mscom/ProxyStream.h"
|
#include "mozilla/mscom/ProxyStream.h"
|
||||||
#include "mozilla/mscom/Utils.h"
|
#include "mozilla/mscom/Utils.h"
|
||||||
|
#include "mozilla/WindowsVersion.h"
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
#include "nsExceptionHandler.h"
|
#include "nsExceptionHandler.h"
|
||||||
@ -55,14 +56,12 @@ ProxyStream::ProxyStream(const BYTE* aInitBuf, const int aInitBufSize)
|
|||||||
|
|
||||||
auto marshalFn = [&]() -> void
|
auto marshalFn = [&]() -> void
|
||||||
{
|
{
|
||||||
IUnknown* rawUnmarshaledProxy = nullptr;
|
|
||||||
// OK to forget mStream when calling into this function because the stream
|
// OK to forget mStream when calling into this function because the stream
|
||||||
// gets released even if the unmarshaling part fails.
|
// gets released even if the unmarshaling part fails.
|
||||||
unmarshalResult =
|
unmarshalResult =
|
||||||
::CoGetInterfaceAndReleaseStream(mStream.forget().take(), IID_IUnknown,
|
::CoGetInterfaceAndReleaseStream(mStream.forget().take(), IID_IUnknown,
|
||||||
(void**)&rawUnmarshaledProxy);
|
getter_AddRefs(mUnmarshaledProxy));
|
||||||
MOZ_ASSERT(SUCCEEDED(unmarshalResult));
|
MOZ_ASSERT(SUCCEEDED(unmarshalResult));
|
||||||
mUnmarshaledProxy.reset(rawUnmarshaledProxy);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess()) {
|
||||||
@ -74,19 +73,74 @@ ProxyStream::ProxyStream(const BYTE* aInitBuf, const int aInitBufSize)
|
|||||||
EnsureMTA mta(marshalFn);
|
EnsureMTA mta(marshalFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#if defined(MOZ_CRASHREPORTER)
|
||||||
if (FAILED(unmarshalResult)) {
|
if (FAILED(unmarshalResult)) {
|
||||||
nsPrintfCString hrAsStr("0x%08X", unmarshalResult);
|
nsPrintfCString hrAsStr("0x%08X", unmarshalResult);
|
||||||
CrashReporter::AnnotateCrashReport(
|
CrashReporter::AnnotateCrashReport(
|
||||||
NS_LITERAL_CSTRING("CoGetInterfaceAndReleaseStreamFailure"), hrAsStr);
|
NS_LITERAL_CSTRING("CoGetInterfaceAndReleaseStreamFailure"), hrAsStr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif // defined(MOZ_CRASHREPORTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
already_AddRefed<IStream>
|
already_AddRefed<IStream>
|
||||||
ProxyStream::InitStream(const BYTE* aInitBuf, const UINT aInitBufSize)
|
ProxyStream::InitStream(const BYTE* aInitBuf, const UINT aInitBufSize)
|
||||||
{
|
{
|
||||||
return already_AddRefed<IStream>(::SHCreateMemStream(aInitBuf, aInitBufSize));
|
if (!aInitBuf || !aInitBufSize) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
RefPtr<IStream> stream;
|
||||||
|
|
||||||
|
if (IsWin8OrLater()) {
|
||||||
|
// This function is not safe for us to use until Windows 8
|
||||||
|
stream = already_AddRefed<IStream>(::SHCreateMemStream(aInitBuf, aInitBufSize));
|
||||||
|
if (!stream) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
HGLOBAL hglobal = ::GlobalAlloc(GMEM_MOVEABLE, aInitBufSize);
|
||||||
|
if (!hglobal) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stream takes ownership of hglobal if this call is successful
|
||||||
|
hr = ::CreateStreamOnHGlobal(hglobal, TRUE, getter_AddRefs(stream));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
::GlobalFree(hglobal);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The default stream size is derived from ::GlobalSize(hglobal), which due
|
||||||
|
// to rounding may be larger than aInitBufSize. We forcibly set the correct
|
||||||
|
// stream size here.
|
||||||
|
ULARGE_INTEGER streamSize;
|
||||||
|
streamSize.QuadPart = aInitBufSize;
|
||||||
|
hr = stream->SetSize(streamSize);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* streamBuf = ::GlobalLock(hglobal);
|
||||||
|
if (!streamBuf) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(streamBuf, aInitBuf, aInitBufSize);
|
||||||
|
|
||||||
|
::GlobalUnlock(hglobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the stream is rewound
|
||||||
|
LARGE_INTEGER streamOffset;
|
||||||
|
streamOffset.QuadPart = 0;
|
||||||
|
hr = stream->Seek(streamOffset, STREAM_SEEK_SET, nullptr);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxyStream::ProxyStream(ProxyStream&& aOther)
|
ProxyStream::ProxyStream(ProxyStream&& aOther)
|
||||||
@ -97,13 +151,14 @@ ProxyStream::ProxyStream(ProxyStream&& aOther)
|
|||||||
ProxyStream&
|
ProxyStream&
|
||||||
ProxyStream::operator=(ProxyStream&& aOther)
|
ProxyStream::operator=(ProxyStream&& aOther)
|
||||||
{
|
{
|
||||||
mStream = mozilla::Move(aOther.mStream);
|
mStream = Move(aOther.mStream);
|
||||||
mGlobalLockedBuf = aOther.mGlobalLockedBuf;
|
mGlobalLockedBuf = aOther.mGlobalLockedBuf;
|
||||||
aOther.mGlobalLockedBuf = nullptr;
|
aOther.mGlobalLockedBuf = nullptr;
|
||||||
mHGlobal = aOther.mHGlobal;
|
mHGlobal = aOther.mHGlobal;
|
||||||
aOther.mHGlobal = nullptr;
|
aOther.mHGlobal = nullptr;
|
||||||
mBufSize = aOther.mBufSize;
|
mBufSize = aOther.mBufSize;
|
||||||
aOther.mBufSize = 0;
|
aOther.mBufSize = 0;
|
||||||
|
mUnmarshaledProxy = Move(aOther.mUnmarshaledProxy);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,6 +202,7 @@ ProxyStream::GetInterface(REFIID aIID, void** aOutInterface) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = E_UNEXPECTED;
|
HRESULT hr = E_UNEXPECTED;
|
||||||
|
|
||||||
auto qiFn = [&]() -> void
|
auto qiFn = [&]() -> void
|
||||||
{
|
{
|
||||||
hr = mUnmarshaledProxy->QueryInterface(aIID, aOutInterface);
|
hr = mUnmarshaledProxy->QueryInterface(aIID, aOutInterface);
|
||||||
@ -158,6 +214,7 @@ ProxyStream::GetInterface(REFIID aIID, void** aOutInterface) const
|
|||||||
// mUnmarshaledProxy requires that we execute this in the MTA
|
// mUnmarshaledProxy requires that we execute this in the MTA
|
||||||
EnsureMTA mta(qiFn);
|
EnsureMTA mta(qiFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +223,13 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
|
|||||||
, mHGlobal(nullptr)
|
, mHGlobal(nullptr)
|
||||||
, mBufSize(0)
|
, mBufSize(0)
|
||||||
{
|
{
|
||||||
|
if (!aObject) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<IStream> stream;
|
RefPtr<IStream> stream;
|
||||||
HGLOBAL hglobal = NULL;
|
HGLOBAL hglobal = NULL;
|
||||||
|
int streamSize = 0;
|
||||||
|
|
||||||
HRESULT marshalResult = S_OK;
|
HRESULT marshalResult = S_OK;
|
||||||
|
|
||||||
@ -185,6 +247,12 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATSTG statstg;
|
||||||
|
hr = stream->Stat(&statstg, STATFLAG_NONAME);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
streamSize = static_cast<int>(statstg.cbSize.LowPart);
|
||||||
|
}
|
||||||
|
|
||||||
hr = ::GetHGlobalFromStream(stream, &hglobal);
|
hr = ::GetHGlobalFromStream(stream, &hglobal);
|
||||||
MOZ_ASSERT(SUCCEEDED(hr));
|
MOZ_ASSERT(SUCCEEDED(hr));
|
||||||
};
|
};
|
||||||
@ -198,19 +266,27 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject)
|
|||||||
EnsureMTA mta(marshalFn);
|
EnsureMTA mta(marshalFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#if defined(MOZ_CRASHREPORTER)
|
||||||
if (FAILED(marshalResult)) {
|
if (FAILED(marshalResult)) {
|
||||||
nsPrintfCString hrAsStr("0x%08X", marshalResult);
|
nsPrintfCString hrAsStr("0x%08X", marshalResult);
|
||||||
CrashReporter::AnnotateCrashReport(
|
CrashReporter::AnnotateCrashReport(
|
||||||
NS_LITERAL_CSTRING("CoMarshalInterfaceFailure"), hrAsStr);
|
NS_LITERAL_CSTRING("CoMarshalInterfaceFailure"), hrAsStr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif // defined(MOZ_CRASHREPORTER)
|
||||||
|
|
||||||
mStream = mozilla::Move(stream);
|
mStream = mozilla::Move(stream);
|
||||||
|
mBufSize = streamSize;
|
||||||
|
|
||||||
if (hglobal) {
|
if (hglobal) {
|
||||||
mGlobalLockedBuf = reinterpret_cast<BYTE*>(::GlobalLock(hglobal));
|
mGlobalLockedBuf = reinterpret_cast<BYTE*>(::GlobalLock(hglobal));
|
||||||
mHGlobal = hglobal;
|
mHGlobal = hglobal;
|
||||||
mBufSize = static_cast<int>(::GlobalSize(hglobal));
|
|
||||||
|
// If we couldn't get the stream size directly from mStream, we may use
|
||||||
|
// the size of the memory block allocated by the HGLOBAL, though it might
|
||||||
|
// be larger than the actual stream size.
|
||||||
|
if (!streamSize) {
|
||||||
|
mBufSize = static_cast<int>(::GlobalSize(hglobal));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace mscom {
|
namespace mscom {
|
||||||
|
|
||||||
class ProxyStream
|
class ProxyStream final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProxyStream();
|
ProxyStream();
|
||||||
@ -34,8 +34,7 @@ public:
|
|||||||
|
|
||||||
inline bool IsValid() const
|
inline bool IsValid() const
|
||||||
{
|
{
|
||||||
// This check must be exclusive OR
|
return !(mStream && mUnmarshaledProxy);
|
||||||
return (mStream && !mUnmarshaledProxy) || (mUnmarshaledProxy && !mStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetInterface(REFIID aIID, void** aOutInterface) const;
|
bool GetInterface(REFIID aIID, void** aOutInterface) const;
|
||||||
@ -47,8 +46,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
already_AddRefed<IStream> InitStream(const BYTE* aInitBuf,
|
static already_AddRefed<IStream> InitStream(const BYTE* aInitBuf,
|
||||||
const UINT aInitBufSize);
|
const UINT aInitBufSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<IStream> mStream;
|
RefPtr<IStream> mStream;
|
||||||
|
Loading…
Reference in New Issue
Block a user