Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/oleaut32/usrmarshal.c | 84 ++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 9 deletions(-)
diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c index 5eeafb8e378..69c7c1cfdda 100644 --- a/dlls/oleaut32/usrmarshal.c +++ b/dlls/oleaut32/usrmarshal.c @@ -286,6 +286,12 @@ static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *pun return size; }
+static ULONG interface_safearray_size(ULONG *pFlags, ULONG Start, REFIID riid, IUnknown *punk) +{ + TRACE("(%x,%d,%p)\n", *pFlags, Start, punk); + return Start + interface_variant_size(pFlags, riid, punk); +} + static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar) { if (V_ISARRAY(pvar)) @@ -733,22 +739,40 @@ static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype) { - if (sftype == SF_BSTR) + switch (sftype) + { + case SF_BSTR: + case SF_HAVEIID: + case SF_UNKNOWN: + case SF_DISPATCH: return sizeof(DWORD); - else if (sftype == SF_VARIANT) + + case SF_VARIANT: return sizeof(variant_wire_t) - sizeof(DWORD); - else + + default: return lpsa->cbElements; + } }
static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype) { - if (sftype == SF_BSTR) + switch (sftype) + { + case SF_HAVEIID: + case SF_UNKNOWN: + case SF_DISPATCH: + return sizeof(void *); + + case SF_BSTR: return sizeof(BSTR); - else if (sftype == SF_VARIANT) + + case SF_VARIANT: return sizeof(VARIANT); - else + + default: return wiresa->cbElements; + } }
ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa) @@ -795,6 +819,22 @@ ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: + { + IUnknown **lpUnk; + GUID guid; + + if (sftype == SF_HAVEIID) + SafeArrayGetIID(psa, &guid); + else if (sftype == SF_UNKNOWN) + memcpy(&guid, &IID_IUnknown, sizeof(guid)); + else + memcpy(&guid, &IID_IDispatch, sizeof(guid)); + + for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++) + size = interface_safearray_size(pFlags, size, &guid, *lpUnk); + + break; + } FIXME("size interfaces\n"); break; case SF_VARIANT: @@ -870,7 +910,7 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf Buffer += sizeof(ULONG);
hr = SafeArrayGetVartype(psa, &vt); - if (FAILED(hr)) vt = 0; + if ((psa->fFeatures & FADF_HAVEIID) || FAILED(hr)) vt = 0;
*(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16); Buffer += sizeof(ULONG); @@ -916,8 +956,21 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: - FIXME("marshal interfaces\n"); + { + IUnknown **lpUnk; + + for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++) + { + if (sftype == SF_HAVEIID) + Buffer = interface_variant_marshal(pFlags, Buffer, &guid, *lpUnk); + else if (sftype == SF_UNKNOWN) + Buffer = interface_variant_marshal(pFlags, Buffer, &IID_IUnknown, *lpUnk); + else + Buffer = interface_variant_marshal(pFlags, Buffer, &IID_IDispatch, *lpUnk); + } + break; + } case SF_VARIANT: { VARIANT* lpVariant; @@ -1093,8 +1146,21 @@ unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *B case SF_DISPATCH: case SF_UNKNOWN: case SF_HAVEIID: - FIXME("marshal interfaces\n"); + { + IUnknown **lpUnk; + + for (lpUnk = (*ppsa)->pvData; cell_count; cell_count--, lpUnk++) + { + if (sftype == SF_HAVEIID) + Buffer = interface_variant_unmarshal(pFlags, Buffer, &guid, lpUnk); + else if (sftype == SF_UNKNOWN) + Buffer = interface_variant_unmarshal(pFlags, Buffer, &IID_IUnknown, lpUnk); + else + Buffer = interface_variant_unmarshal(pFlags, Buffer, &IID_IDispatch, lpUnk); + } + break; + } case SF_VARIANT: { VARIANT* lpVariant;