mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 18:54:00 +00:00
[OLEAUT32][OLEAUT32_WINETEST] Import LPSAFEARRAY user marshal interface marshaling support from Wine (#8121)
Import the following Wine commits: oleaut32: Implement LPSAFEARRAY user marshal interface marshaling.a1f2b44a1b
oleaut32/tests: Add tests for LPSAFEARRAY user marshal interface marshaling.b2574278f7
containing the implementation itself and a test for it. Fixes: 1) improperly displayed comboboxes with OS type and version selection, 2) failure to save/load virtual machine settings in/from XML file in VirtualBox 3.0.0 - 4.0.36 versions and 3) improperly displayed comboboxes in 3DMark2001. As result, this also allows to create and start a virtual machine(s) in VirtualBox up to 3.0.8 version. For newer VirtualBox versions, another fix is required. CORE-8418, CORE-11254, CORE-14507, CORE-17980, CORE-18496, CORE-20015
This commit is contained in:
parent
4e7702a6a9
commit
42aaad43db
2 changed files with 365 additions and 0 deletions
|
@ -268,7 +268,11 @@ static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt)
|
|||
}
|
||||
|
||||
/* WdtpInterfacePointer_UserSize takes care of 2 additional DWORDs to store marshalling buffer size */
|
||||
#ifdef __REACTOS__
|
||||
static unsigned interface_user_size(ULONG *pFlags, ULONG Start, REFIID riid, IUnknown *punk)
|
||||
#else
|
||||
static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *punk)
|
||||
#endif
|
||||
{
|
||||
ULONG size = 0;
|
||||
|
||||
|
@ -283,7 +287,11 @@ static unsigned interface_variant_size(ULONG *pFlags, REFIID riid, IUnknown *pun
|
|||
}
|
||||
size += sizeof(ULONG);
|
||||
TRACE("wire-size extra of interface variant is %d\n", size);
|
||||
#ifdef __REACTOS__
|
||||
return Start + size;
|
||||
#else
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
|
||||
|
@ -304,13 +312,29 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
|
|||
case VT_VARIANT | VT_BYREF:
|
||||
return VARIANT_UserSize(pFlags, Start, V_VARIANTREF(pvar));
|
||||
case VT_UNKNOWN:
|
||||
#ifdef __REACTOS__
|
||||
return interface_user_size(pFlags, Start, &IID_IUnknown, V_UNKNOWN(pvar));
|
||||
#else
|
||||
return Start + interface_variant_size(pFlags, &IID_IUnknown, V_UNKNOWN(pvar));
|
||||
#endif
|
||||
case VT_UNKNOWN | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
return interface_user_size(pFlags, Start, &IID_IUnknown, *V_UNKNOWNREF(pvar));
|
||||
#else
|
||||
return Start + interface_variant_size(pFlags, &IID_IUnknown, *V_UNKNOWNREF(pvar));
|
||||
#endif
|
||||
case VT_DISPATCH:
|
||||
#ifdef __REACTOS__
|
||||
return interface_user_size(pFlags, Start, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
|
||||
#else
|
||||
return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
|
||||
#endif
|
||||
case VT_DISPATCH | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
return interface_user_size(pFlags, Start, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
|
||||
#else
|
||||
return Start + interface_variant_size(pFlags, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
|
||||
#endif
|
||||
case VT_RECORD:
|
||||
FIXME("wire-size record\n");
|
||||
return Start;
|
||||
|
@ -324,7 +348,11 @@ static ULONG wire_extra_user_size(ULONG *pFlags, ULONG Start, VARIANT *pvar)
|
|||
}
|
||||
|
||||
/* helper: called for VT_DISPATCH variants to marshal the IDispatch* into the buffer */
|
||||
#ifdef __REACTOS__
|
||||
static unsigned char* interface_user_marshal(ULONG *pFlags, unsigned char *Buffer,
|
||||
#else
|
||||
static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Buffer,
|
||||
#endif
|
||||
REFIID riid, IUnknown *punk)
|
||||
{
|
||||
TRACE("pFlags=%d, Buffer=%p, pUnk=%p\n", *pFlags, Buffer, punk);
|
||||
|
@ -345,7 +373,11 @@ static unsigned char* interface_variant_marshal(ULONG *pFlags, unsigned char *Bu
|
|||
}
|
||||
|
||||
/* helper: called for VT_DISPATCH / VT_UNKNOWN variants to unmarshal the buffer */
|
||||
#ifdef __REACTOS__
|
||||
static unsigned char *interface_user_unmarshal(ULONG *pFlags, unsigned char *Buffer,
|
||||
#else
|
||||
static unsigned char *interface_variant_unmarshal(ULONG *pFlags, unsigned char *Buffer,
|
||||
#endif
|
||||
REFIID riid, IUnknown **ppunk)
|
||||
{
|
||||
DWORD ptr;
|
||||
|
@ -459,16 +491,32 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer,
|
|||
Pos = VARIANT_UserMarshal(pFlags, Pos, V_VARIANTREF(pvar));
|
||||
break;
|
||||
case VT_UNKNOWN:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
|
||||
#else
|
||||
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWN(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_UNKNOWN | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
|
||||
#else
|
||||
Pos = interface_variant_marshal(pFlags, Pos, &IID_IUnknown, *V_UNKNOWNREF(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_DISPATCH:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
|
||||
#else
|
||||
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_DISPATCH | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
|
||||
#else
|
||||
Pos = interface_variant_marshal(pFlags, Pos, &IID_IDispatch, (IUnknown*)*V_DISPATCHREF(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_RECORD:
|
||||
FIXME("handle BRECORD by val\n");
|
||||
|
@ -590,16 +638,32 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe
|
|||
Pos = VARIANT_UserUnmarshal(pFlags, Pos, V_VARIANTREF(pvar));
|
||||
break;
|
||||
case VT_UNKNOWN:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
|
||||
#else
|
||||
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, &V_UNKNOWN(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_UNKNOWN | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
|
||||
#else
|
||||
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IUnknown, V_UNKNOWNREF(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_DISPATCH:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
|
||||
#else
|
||||
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)&V_DISPATCH(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_DISPATCH | VT_BYREF:
|
||||
#ifdef __REACTOS__
|
||||
Pos = interface_user_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
|
||||
#else
|
||||
Pos = interface_variant_unmarshal(pFlags, Pos, &IID_IDispatch, (IUnknown**)V_DISPATCHREF(pvar));
|
||||
#endif
|
||||
break;
|
||||
case VT_RECORD:
|
||||
FIXME("handle BRECORD by val\n");
|
||||
|
@ -733,22 +797,68 @@ static inline SF_TYPE SAFEARRAY_GetUnionType(SAFEARRAY *psa)
|
|||
|
||||
static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
switch (sftype)
|
||||
{
|
||||
case SF_BSTR:
|
||||
case SF_HAVEIID:
|
||||
case SF_UNKNOWN:
|
||||
case SF_DISPATCH:
|
||||
#else
|
||||
if (sftype == SF_BSTR)
|
||||
#endif
|
||||
return sizeof(DWORD);
|
||||
#ifdef __REACTOS__
|
||||
|
||||
case SF_VARIANT:
|
||||
#else
|
||||
else if (sftype == SF_VARIANT)
|
||||
#endif
|
||||
return sizeof(variant_wire_t) - sizeof(DWORD);
|
||||
#ifdef __REACTOS__
|
||||
|
||||
default:
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
return lpsa->cbElements;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static DWORD elem_mem_size(wireSAFEARRAY wiresa, SF_TYPE sftype)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
switch (sftype)
|
||||
{
|
||||
case SF_HAVEIID:
|
||||
case SF_UNKNOWN:
|
||||
case SF_DISPATCH:
|
||||
return sizeof(void *);
|
||||
|
||||
case SF_BSTR:
|
||||
#else
|
||||
if (sftype == SF_BSTR)
|
||||
#endif
|
||||
return sizeof(BSTR);
|
||||
#ifdef __REACTOS__
|
||||
|
||||
case SF_VARIANT:
|
||||
#else
|
||||
else if (sftype == SF_VARIANT)
|
||||
#endif
|
||||
return sizeof(VARIANT);
|
||||
#ifdef __REACTOS__
|
||||
|
||||
default:
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
return wiresa->cbElements;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY *ppsa)
|
||||
|
@ -795,8 +905,28 @@ ULONG WINAPI LPSAFEARRAY_UserSize(ULONG *pFlags, ULONG StartingSize, LPSAFEARRAY
|
|||
case SF_DISPATCH:
|
||||
case SF_UNKNOWN:
|
||||
case SF_HAVEIID:
|
||||
#ifdef __REACTOS__
|
||||
{
|
||||
IUnknown **lpUnk;
|
||||
GUID guid;
|
||||
|
||||
if (sftype == SF_HAVEIID)
|
||||
SafeArrayGetIID(psa, &guid);
|
||||
else if (sftype == SF_UNKNOWN)
|
||||
guid = IID_IUnknown;
|
||||
else
|
||||
guid = IID_IDispatch;
|
||||
|
||||
for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
|
||||
size = interface_user_size(pFlags, size, &guid, *lpUnk);
|
||||
|
||||
#else
|
||||
FIXME("size interfaces\n");
|
||||
#endif
|
||||
break;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
case SF_VARIANT:
|
||||
{
|
||||
VARIANT* lpVariant;
|
||||
|
@ -870,7 +1000,11 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
|
|||
Buffer += sizeof(ULONG);
|
||||
|
||||
hr = SafeArrayGetVartype(psa, &vt);
|
||||
#ifdef __REACTOS__
|
||||
if ((psa->fFeatures & FADF_HAVEIID) || FAILED(hr)) vt = 0;
|
||||
#else
|
||||
if (FAILED(hr)) vt = 0;
|
||||
#endif
|
||||
|
||||
*(ULONG *)Buffer = (USHORT)psa->cLocks | (vt << 16);
|
||||
Buffer += sizeof(ULONG);
|
||||
|
@ -916,8 +1050,28 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
|
|||
case SF_DISPATCH:
|
||||
case SF_UNKNOWN:
|
||||
case SF_HAVEIID:
|
||||
#ifdef __REACTOS__
|
||||
{
|
||||
IUnknown **lpUnk;
|
||||
const GUID *iid;
|
||||
|
||||
if (sftype == SF_HAVEIID)
|
||||
iid = &guid;
|
||||
else if (sftype == SF_UNKNOWN)
|
||||
iid = &IID_IUnknown;
|
||||
else
|
||||
iid = &IID_IDispatch;
|
||||
|
||||
for (lpUnk = psa->pvData; ulCellCount; ulCellCount--, lpUnk++)
|
||||
Buffer = interface_user_marshal(pFlags, Buffer, iid, *lpUnk);
|
||||
|
||||
#else
|
||||
FIXME("marshal interfaces\n");
|
||||
#endif
|
||||
break;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
case SF_VARIANT:
|
||||
{
|
||||
VARIANT* lpVariant;
|
||||
|
@ -1093,8 +1247,28 @@ unsigned char * WINAPI LPSAFEARRAY_UserUnmarshal(ULONG *pFlags, unsigned char *B
|
|||
case SF_DISPATCH:
|
||||
case SF_UNKNOWN:
|
||||
case SF_HAVEIID:
|
||||
#ifdef __REACTOS__
|
||||
{
|
||||
IUnknown **lpUnk;
|
||||
const GUID *iid;
|
||||
|
||||
if (sftype == SF_HAVEIID)
|
||||
iid = &guid;
|
||||
else if (sftype == SF_UNKNOWN)
|
||||
iid = &IID_IUnknown;
|
||||
else
|
||||
iid = &IID_IDispatch;
|
||||
|
||||
for (lpUnk = (*ppsa)->pvData; cell_count; cell_count--, lpUnk++)
|
||||
Buffer = interface_user_unmarshal(pFlags, Buffer, iid, lpUnk);
|
||||
|
||||
#else
|
||||
FIXME("marshal interfaces\n");
|
||||
#endif
|
||||
break;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
case SF_VARIANT:
|
||||
{
|
||||
VARIANT* lpVariant;
|
||||
|
|
|
@ -36,6 +36,16 @@
|
|||
# define V_U2(A) (*(A))
|
||||
#endif
|
||||
|
||||
#ifdef __REACTOS__
|
||||
typedef struct
|
||||
{
|
||||
IUnknown IUnknown_iface;
|
||||
ULONG refs;
|
||||
} HeapUnknown;
|
||||
|
||||
static const IUnknownVtbl HeapUnknown_Vtbl;
|
||||
#endif
|
||||
|
||||
static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
|
||||
static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
|
||||
static HRESULT (WINAPI *pVarBstrCmp)(BSTR,BSTR,LCID,ULONG);
|
||||
|
@ -112,10 +122,27 @@ static ULONG get_cell_count(const SAFEARRAY *psa)
|
|||
|
||||
static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
switch (sftype)
|
||||
{
|
||||
case SF_HAVEIID:
|
||||
case SF_UNKNOWN:
|
||||
case SF_DISPATCH:
|
||||
case SF_BSTR:
|
||||
#else
|
||||
if (sftype == SF_BSTR)
|
||||
#endif
|
||||
return sizeof(DWORD);
|
||||
#ifdef __REACTOS__
|
||||
|
||||
default:
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
return lpsa->cbElements;
|
||||
#ifdef __REACTOS__
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
|
||||
|
@ -136,7 +163,12 @@ static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
|
|||
if (!pSafeArrayGetVartype || !pSafeArrayGetIID)
|
||||
return;
|
||||
|
||||
#ifdef __REACTOS__
|
||||
/* If FADF_HAVEIID is set, VT will be 0. */
|
||||
if((lpsa->fFeatures & FADF_HAVEIID) || FAILED(SafeArrayGetVartype(lpsa, &vt)))
|
||||
#else
|
||||
if(FAILED(pSafeArrayGetVartype(lpsa, &vt)))
|
||||
#endif
|
||||
vt = 0;
|
||||
|
||||
sftype = get_union_type(lpsa);
|
||||
|
@ -224,8 +256,15 @@ static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
|
|||
|
||||
static void test_marshal_LPSAFEARRAY(void)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
HeapUnknown *heap_unknown[10];
|
||||
#endif
|
||||
unsigned char *buffer, *next;
|
||||
#ifdef __REACTOS__
|
||||
ULONG size, expected, size2;
|
||||
#else
|
||||
ULONG size, expected;
|
||||
#endif
|
||||
LPSAFEARRAY lpsa;
|
||||
LPSAFEARRAY lpsa2 = NULL;
|
||||
SAFEARRAYBOUND sab[2];
|
||||
|
@ -525,6 +564,156 @@ static void test_marshal_LPSAFEARRAY(void)
|
|||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
hr = SafeArrayDestroyDescriptor(lpsa);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
|
||||
#ifdef __REACTOS__
|
||||
/* Test an array of VT_UNKNOWN */
|
||||
sab[0].lLbound = 3;
|
||||
sab[0].cElements = ARRAY_SIZE(heap_unknown);
|
||||
|
||||
lpsa = SafeArrayCreate(VT_UNKNOWN, 1, sab);
|
||||
|
||||
/*
|
||||
* Calculate approximate expected size. Sizes are different between Windows
|
||||
* versions, so this should calculate the smallest size that seems sane.
|
||||
*/
|
||||
expected = 60;
|
||||
for (i = 0; i < sab[0].cElements; i++)
|
||||
{
|
||||
HeapUnknown *unk;
|
||||
VARIANT v;
|
||||
|
||||
unk = HeapAlloc(GetProcessHeap(), 0, sizeof(*unk));
|
||||
unk->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
|
||||
unk->refs = 1;
|
||||
|
||||
indices[0] = i + sab[0].lLbound;
|
||||
heap_unknown[i] = unk;
|
||||
hr = SafeArrayPutElement(lpsa, indices, &heap_unknown[i]->IUnknown_iface);
|
||||
ok(hr == S_OK, "Failed to put unknown element hr 0x%x\n", hr);
|
||||
ok(unk->refs == 2, "VT_UNKNOWN safearray elem %d, refcount %d\n", i, unk->refs);
|
||||
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_UNKNOWN(&v) = &unk->IUnknown_iface;
|
||||
expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
|
||||
}
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
||||
ok(size >= expected || size >= (expected + 12 ),
|
||||
"size should be at least %u bytes, not %u\n", expected, size);
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||
ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
|
||||
"size should be %u bytes, not %u\n", size + (ULONG) sizeof(DWORD), size2);
|
||||
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
memset(buffer, 0xcc, size);
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
||||
next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
|
||||
ok((next - buffer) <= size, "Marshaled %u bytes, expected at most %u\n", (ULONG) (next - buffer), size);
|
||||
check_safearray(buffer, lpsa);
|
||||
todo_wine
|
||||
ok(heap_unknown[0]->refs == 3, "Unexpected refcount %d\n", heap_unknown[0]->refs);
|
||||
|
||||
lpsa2 = NULL;
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
||||
next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
|
||||
ok((next - buffer) <= size, "Marshaled %u bytes, expected at most %u\n", (ULONG) (next - buffer), size);
|
||||
ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
|
||||
{
|
||||
IUnknown *gotvalue = NULL;
|
||||
|
||||
if (lpsa2)
|
||||
{
|
||||
indices[0] = i + sab[0].lLbound;
|
||||
hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
|
||||
ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%x\n", i, hr);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
|
||||
i, &heap_unknown[i]->IUnknown_iface, gotvalue);
|
||||
IUnknown_Release(gotvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
|
||||
|
||||
/* Set one of the elements to NULL, see how this effects size. */
|
||||
indices[0] = 3 + sab[0].lLbound;
|
||||
hr = SafeArrayPutElement(lpsa, indices, NULL);
|
||||
ok(hr == S_OK, "Failed to put unknown element hr 0x%x\n", hr);
|
||||
|
||||
expected = 60;
|
||||
for (i = 0; i < sab[0].cElements; i++)
|
||||
{
|
||||
VARIANT v;
|
||||
|
||||
V_VT(&v) = VT_UNKNOWN;
|
||||
V_UNKNOWN(&v) = (i != 3) ? &heap_unknown[i]->IUnknown_iface : NULL;
|
||||
expected += VARIANT_UserSize(&umcb.Flags, 0, &v) - 20;
|
||||
}
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
||||
ok(size >= expected || size >= (expected + 12 ),
|
||||
"size should be at least %u bytes, not %u\n", expected, size);
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
size2 = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||
ok(size2 == (size + sizeof(DWORD)) || size2 == (size + sizeof(DWORD) + 12),
|
||||
"size should be %u bytes, not %u\n", size + (ULONG) sizeof(DWORD), size2);
|
||||
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
memset(buffer, 0xcc, size);
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
||||
next = LPSAFEARRAY_UserMarshal(&umcb.Flags, buffer, &lpsa);
|
||||
ok((next - buffer) <= expected, "Marshaled %u bytes, expected at most %u bytes\n", (ULONG) (next - buffer), expected);
|
||||
check_safearray(buffer, lpsa);
|
||||
|
||||
lpsa2 = NULL;
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
||||
next = LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
|
||||
ok((next - buffer) <= expected, "Marshaled %u bytes, expected at most %u bytes\n", (ULONG) (next - buffer), expected);
|
||||
ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal, result %p\n", next);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(heap_unknown); i++)
|
||||
{
|
||||
IUnknown *gotvalue = NULL;
|
||||
|
||||
if (lpsa2)
|
||||
{
|
||||
indices[0] = i + sab[0].lLbound;
|
||||
hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
|
||||
ok(hr == S_OK, "Failed to get unk element at %d, hres 0x%x\n", i, hr);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
/* Our NULL interface. */
|
||||
if (i == 3)
|
||||
ok(gotvalue == NULL, "Interface %d expected NULL, got %p\n", i, gotvalue);
|
||||
else
|
||||
{
|
||||
ok(gotvalue == &heap_unknown[i]->IUnknown_iface, "Interface %d mismatch, expected %p, got %p\n",
|
||||
i, &heap_unknown[i]->IUnknown_iface, gotvalue);
|
||||
IUnknown_Release(gotvalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
IUnknown_Release(&heap_unknown[i]->IUnknown_iface);
|
||||
}
|
||||
|
||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||
LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
|
||||
|
||||
ok(heap_unknown[0]->refs == 1, "Unexpected refcount %d\n", heap_unknown[0]->refs);
|
||||
|
||||
hr = SafeArrayDestroy(lpsa);
|
||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void check_bstr(void *buffer, BSTR b)
|
||||
|
@ -670,11 +859,13 @@ static void test_marshal_BSTR(void)
|
|||
SysFreeString(b);
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
typedef struct
|
||||
{
|
||||
IUnknown IUnknown_iface;
|
||||
ULONG refs;
|
||||
} HeapUnknown;
|
||||
#endif
|
||||
|
||||
static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue