Bug 1315638: Modify MainThreadHandoff::FixArrayElements to be able to distinguish between outparams with different levels of indirection; r?jimm
MozReview-Commit-ID: HZgED9JT16m
--- a/accessible/ipc/win/PlatformChild.cpp
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -23,20 +23,24 @@ namespace a11y {
* outparams. Instead we manually define the relevant metadata here, and
* register it in a call to mozilla::mscom::RegisterArrayData.
* @see mozilla::mscom::ArrayData
*/
static const mozilla::mscom::ArrayData sPlatformChildArrayData[] = {
{IID_IEnumVARIANT, 3, 1, VT_DISPATCH, IID_IDispatch, 2},
{IID_IAccessible2, 30, 1, VT_UNKNOWN | VT_BYREF, IID_IAccessibleRelation, 2},
{IID_IAccessibleRelation, 7, 1, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 2},
- {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3},
- {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
- {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1},
- {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1}
+ {IID_IAccessible2_2, 48, 2, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 3,
+ mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+ {IID_IAccessibleTableCell, 4, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+ mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+ {IID_IAccessibleTableCell, 7, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+ mozilla::mscom::ArrayData::Flag::eAllocatedByServer},
+ {IID_IAccessibleHypertext2, 25, 0, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 1,
+ mozilla::mscom::ArrayData::Flag::eAllocatedByServer}
};
// Type libraries are thread-neutral, so we can register those from any
// apartment. OTOH, proxies must be registered from within the apartment where
// we intend to instantiate them. Therefore RegisterProxy() must be called
// via EnsureMTA.
PlatformChild::PlatformChild()
: mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
--- a/ipc/mscom/MainThreadHandoff.cpp
+++ b/ipc/mscom/MainThreadHandoff.cpp
@@ -253,20 +253,28 @@ MainThreadHandoff::FixArrayElements(ICal
// ICallFrame::GetParam is not able to coerce the param into a VARIANT.
// That's ok, we can try to do it ourselves.
CALLFRAMEPARAMINFO paramInfo;
hr = aFrame->GetParamInfo(aArrayData.mArrayParamIndex, ¶mInfo);
if (FAILED(hr)) {
return hr;
}
PVOID stackBase = aFrame->GetStackLocation();
- // We dereference because we need to obtain the value of a parameter
- // from a stack offset. This pointer is the base of the array.
- arrayPtr = *reinterpret_cast<PVOID*>(reinterpret_cast<PBYTE>(stackBase) +
- paramInfo.stackOffset);
+ if (aArrayData.mFlag == ArrayData::Flag::eAllocatedByServer) {
+ // In order for the server to allocate the array's buffer and store it in
+ // an outparam, the parameter must be typed as Type***. Since the base
+ // of the array is Type*, we must dereference twice.
+ arrayPtr = **reinterpret_cast<PVOID**>(reinterpret_cast<PBYTE>(stackBase) +
+ paramInfo.stackOffset);
+ } else {
+ // We dereference because we need to obtain the value of a parameter
+ // from a stack offset. This pointer is the base of the array.
+ arrayPtr = *reinterpret_cast<PVOID*>(reinterpret_cast<PBYTE>(stackBase) +
+ paramInfo.stackOffset);
+ }
} else if (FAILED(hr)) {
return hr;
} else {
arrayPtr = ResolveArrayPtr(paramVal);
}
MOZ_ASSERT(arrayPtr);
if (!arrayPtr) {
--- a/ipc/mscom/Registration.h
+++ b/ipc/mscom/Registration.h
@@ -80,47 +80,59 @@ UniquePtr<RegisteredProxy> RegisterTypel
* The COM interceptor uses type library information to build its interface
* proxies. Unfortunately type libraries do not encode size_is and length_is
* annotations that have been specified in IDL. This structure allows us to
* explicitly declare such relationships so that the COM interceptor may
* be made aware of them.
*/
struct ArrayData
{
+ enum class Flag
+ {
+ eNone = 0,
+ eAllocatedByServer = 1 // This implies an extra level of indirection
+ };
+
ArrayData(REFIID aIid, ULONG aMethodIndex, ULONG aArrayParamIndex,
VARTYPE aArrayParamType, REFIID aArrayParamIid,
- ULONG aLengthParamIndex)
+ ULONG aLengthParamIndex, Flag aFlag = Flag::eNone)
: mIid(aIid)
, mMethodIndex(aMethodIndex)
, mArrayParamIndex(aArrayParamIndex)
, mArrayParamType(aArrayParamType)
, mArrayParamIid(aArrayParamIid)
, mLengthParamIndex(aLengthParamIndex)
+ , mFlag(aFlag)
{
}
+
ArrayData(const ArrayData& aOther)
{
*this = aOther;
}
+
ArrayData& operator=(const ArrayData& aOther)
{
mIid = aOther.mIid;
mMethodIndex = aOther.mMethodIndex;
mArrayParamIndex = aOther.mArrayParamIndex;
mArrayParamType = aOther.mArrayParamType;
mArrayParamIid = aOther.mArrayParamIid;
mLengthParamIndex = aOther.mLengthParamIndex;
+ mFlag = aOther.mFlag;
return *this;
}
+
IID mIid;
ULONG mMethodIndex;
ULONG mArrayParamIndex;
VARTYPE mArrayParamType;
IID mArrayParamIid;
ULONG mLengthParamIndex;
+ Flag mFlag;
};
void RegisterArrayData(const ArrayData* aArrayData, size_t aLength);
template <size_t N>
inline void
RegisterArrayData(const ArrayData (&aData)[N])
{