oleaut32: Fix multidimensional SAFEARRAY marshalling.
This commit is contained in:
parent
c4ae9e9c5a
commit
b08d3d2656
|
@ -120,9 +120,11 @@ static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
|
||||||
static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
|
static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
|
||||||
{
|
{
|
||||||
unsigned char *wiresa = buffer;
|
unsigned char *wiresa = buffer;
|
||||||
|
const SAFEARRAYBOUND *bounds;
|
||||||
VARTYPE vt;
|
VARTYPE vt;
|
||||||
SF_TYPE sftype;
|
SF_TYPE sftype;
|
||||||
ULONG cell_count;
|
ULONG cell_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
if(!lpsa)
|
if(!lpsa)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +165,18 @@ static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
|
||||||
ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
|
ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
|
||||||
wiresa += sizeof(GUID);
|
wiresa += sizeof(GUID);
|
||||||
}
|
}
|
||||||
ok(!memcmp(wiresa, lpsa->rgsabound, sizeof(lpsa->rgsabound[0]) * lpsa->cDims), "bounds mismatch\n");
|
|
||||||
|
/* bounds are marshaled in natural dimensions order */
|
||||||
|
bounds = (SAFEARRAYBOUND*)wiresa;
|
||||||
|
for(i=0; i<lpsa->cDims; i++)
|
||||||
|
{
|
||||||
|
ok(memcmp(bounds, &lpsa->rgsabound[lpsa->cDims-i-1], sizeof(SAFEARRAYBOUND)) == 0,
|
||||||
|
"bounds mismatch for dimension %d, got (%d,%d), expected (%d,%d)\n", i,
|
||||||
|
bounds->lLbound, bounds->cElements, lpsa->rgsabound[lpsa->cDims-i-1].lLbound,
|
||||||
|
lpsa->rgsabound[lpsa->cDims-i-1].cElements);
|
||||||
|
bounds++;
|
||||||
|
}
|
||||||
|
|
||||||
wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
|
wiresa += sizeof(lpsa->rgsabound[0]) * lpsa->cDims;
|
||||||
|
|
||||||
ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
|
ok(*(DWORD *)wiresa == cell_count, "wiresa + 0x28 should be %u instead of %u\n", cell_count, *(DWORD*)wiresa);
|
||||||
|
@ -209,7 +222,7 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
ULONG size, expected;
|
ULONG size, expected;
|
||||||
LPSAFEARRAY lpsa;
|
LPSAFEARRAY lpsa;
|
||||||
LPSAFEARRAY lpsa2 = NULL;
|
LPSAFEARRAY lpsa2 = NULL;
|
||||||
SAFEARRAYBOUND sab;
|
SAFEARRAYBOUND sab[2];
|
||||||
RPC_MESSAGE rpc_msg;
|
RPC_MESSAGE rpc_msg;
|
||||||
MIDL_STUB_MESSAGE stub_msg;
|
MIDL_STUB_MESSAGE stub_msg;
|
||||||
USER_MARSHAL_CB umcb;
|
USER_MARSHAL_CB umcb;
|
||||||
|
@ -220,22 +233,66 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
int i;
|
int i;
|
||||||
LONG indices[1];
|
LONG indices[1];
|
||||||
|
|
||||||
sab.lLbound = 5;
|
sab[0].lLbound = 5;
|
||||||
sab.cElements = 10;
|
sab[0].cElements = 10;
|
||||||
|
|
||||||
lpsa = SafeArrayCreate(VT_I2, 1, &sab);
|
lpsa = SafeArrayCreate(VT_I2, 1, sab);
|
||||||
*(DWORD *)lpsa->pvData = 0xcafebabe;
|
*(DWORD *)lpsa->pvData = 0xcafebabe;
|
||||||
|
|
||||||
lpsa->cLocks = 7;
|
lpsa->cLocks = 7;
|
||||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||||
expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
|
expected = (44 + 1 + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
|
||||||
expected += sab.cElements * sizeof(USHORT);
|
expected += sab[0].cElements * sizeof(USHORT);
|
||||||
ok(size == expected || size == expected + 12, /* win64 */
|
ok(size == expected || size == expected + 12, /* win64 */
|
||||||
"size should be %u bytes, not %u\n", expected, size);
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
||||||
expected = 44 + sab.cElements * sizeof(USHORT);
|
expected = 44 + sab[0].cElements * sizeof(USHORT);
|
||||||
|
ok(size == expected || size == expected + 12, /* win64 */
|
||||||
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
|
buffer = HeapAlloc(GetProcessHeap(), 0, 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 %u\n", (ULONG) (next - buffer), expected);
|
||||||
|
|
||||||
|
check_safearray(buffer, lpsa);
|
||||||
|
|
||||||
|
if (LPSAFEARRAY_UNMARSHAL_WORKS)
|
||||||
|
{
|
||||||
|
VARTYPE vt, vt2;
|
||||||
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_DIFFERENTMACHINE);
|
||||||
|
LPSAFEARRAY_UserUnmarshal(&umcb.Flags, buffer, &lpsa2);
|
||||||
|
ok(lpsa2 != NULL, "LPSAFEARRAY didn't unmarshal\n");
|
||||||
|
SafeArrayGetVartype(lpsa, &vt);
|
||||||
|
SafeArrayGetVartype(lpsa2, &vt2);
|
||||||
|
ok(vt == vt2, "vts differ %x %x\n", vt, vt2);
|
||||||
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
|
LPSAFEARRAY_UserFree(&umcb.Flags, &lpsa2);
|
||||||
|
}
|
||||||
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
|
lpsa->cLocks = 0;
|
||||||
|
SafeArrayDestroy(lpsa);
|
||||||
|
|
||||||
|
/* use two dimensions */
|
||||||
|
sab[0].lLbound = 5;
|
||||||
|
sab[0].cElements = 10;
|
||||||
|
sab[1].lLbound = 1;
|
||||||
|
sab[1].cElements = 2;
|
||||||
|
|
||||||
|
lpsa = SafeArrayCreate(VT_I2, 2, sab);
|
||||||
|
*(DWORD *)lpsa->pvData = 0xcafebabe;
|
||||||
|
|
||||||
|
lpsa->cLocks = 7;
|
||||||
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||||
|
expected = (44 + 1 + +sizeof(SAFEARRAYBOUND) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1);
|
||||||
|
expected += max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
|
||||||
|
ok(size == expected || size == expected + 12, /* win64 */
|
||||||
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
||||||
|
expected = 52 + max(sab[0].cElements, sab[1].cElements) * lpsa->cDims * sizeof(USHORT);
|
||||||
ok(size == expected || size == expected + 12, /* win64 */
|
ok(size == expected || size == expected + 12, /* win64 */
|
||||||
"size should be %u bytes, not %u\n", expected, size);
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
buffer = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
|
@ -284,22 +341,22 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
}
|
}
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
|
|
||||||
sab.lLbound = 5;
|
sab[0].lLbound = 5;
|
||||||
sab.cElements = 10;
|
sab[0].cElements = 10;
|
||||||
|
|
||||||
lpsa = SafeArrayCreate(VT_R8, 1, &sab);
|
lpsa = SafeArrayCreate(VT_R8, 1, sab);
|
||||||
*(double *)lpsa->pvData = 3.1415;
|
*(double *)lpsa->pvData = 3.1415;
|
||||||
|
|
||||||
lpsa->cLocks = 7;
|
lpsa->cLocks = 7;
|
||||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||||
expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
|
expected = (44 + 1 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
|
||||||
expected += sab.cElements * sizeof(double);
|
expected += sab[0].cElements * sizeof(double);
|
||||||
ok(size == expected || size == expected + 16, /* win64 */
|
ok(size == expected || size == expected + 16, /* win64 */
|
||||||
"size should be %u bytes, not %u\n", expected, size);
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
|
expected = (44 + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
|
||||||
expected += sab.cElements * sizeof(double);
|
expected += sab[0].cElements * sizeof(double);
|
||||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 0, &lpsa);
|
||||||
ok(size == expected || size == expected + 8, /* win64 */
|
ok(size == expected || size == expected + 8, /* win64 */
|
||||||
"size should be %u bytes, not %u\n", expected, size);
|
"size should be %u bytes, not %u\n", expected, size);
|
||||||
|
@ -344,19 +401,19 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
SafeArrayDestroyDescriptor(lpsa);
|
SafeArrayDestroyDescriptor(lpsa);
|
||||||
|
|
||||||
/* Test an array of VT_BSTR */
|
/* Test an array of VT_BSTR */
|
||||||
sab.lLbound = 3;
|
sab[0].lLbound = 3;
|
||||||
sab.cElements = sizeof(values) / sizeof(values[0]);
|
sab[0].cElements = sizeof(values) / sizeof(values[0]);
|
||||||
|
|
||||||
lpsa = SafeArrayCreate(VT_BSTR, 1, &sab);
|
lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
|
||||||
expected_bstr_size = 0;
|
expected_bstr_size = 0;
|
||||||
for (i = 0; i < sab.cElements; i++)
|
for (i = 0; i < sab[0].cElements; i++)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
WCHAR buf[128];
|
WCHAR buf[128];
|
||||||
for (j = 0; j <= i; j++)
|
for (j = 0; j <= i; j++)
|
||||||
buf[j] = 'a' + j;
|
buf[j] = 'a' + j;
|
||||||
buf[j] = 0;
|
buf[j] = 0;
|
||||||
indices[0] = i + sab.lLbound;
|
indices[0] = i + sab[0].lLbound;
|
||||||
values[i] = SysAllocString(buf);
|
values[i] = SysAllocString(buf);
|
||||||
hr = SafeArrayPutElement(lpsa, indices, values[i]);
|
hr = SafeArrayPutElement(lpsa, indices, values[i]);
|
||||||
ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
|
ok(hr == S_OK, "Failed to put bstr element hr 0x%x\n", hr);
|
||||||
|
@ -367,7 +424,7 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
|
|
||||||
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
|
||||||
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
size = LPSAFEARRAY_UserSize(&umcb.Flags, 1, &lpsa);
|
||||||
expected = 44 + (sab.cElements * sizeof(DWORD)) + expected_bstr_size;
|
expected = 44 + (sab[0].cElements * sizeof(DWORD)) + expected_bstr_size;
|
||||||
todo_wine
|
todo_wine
|
||||||
ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
|
ok(size == expected + sizeof(DWORD) || size == (expected + sizeof(DWORD) + 12 /* win64 */),
|
||||||
"size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
|
"size should be %u bytes, not %u\n", expected + (ULONG) sizeof(DWORD), size);
|
||||||
|
@ -401,7 +458,7 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
|
|
||||||
if (lpsa2)
|
if (lpsa2)
|
||||||
{
|
{
|
||||||
indices[0] = i + sab.lLbound;
|
indices[0] = i + sab[0].lLbound;
|
||||||
hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
|
hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
|
||||||
ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
|
ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
|
@ -423,7 +480,6 @@ static void test_marshal_LPSAFEARRAY(void)
|
||||||
HeapFree(GetProcessHeap(), 0, buffer);
|
HeapFree(GetProcessHeap(), 0, buffer);
|
||||||
SafeArrayDestroy(lpsa);
|
SafeArrayDestroy(lpsa);
|
||||||
|
|
||||||
|
|
||||||
/* VARTYPE-less arrays with FADF_VARIANT */
|
/* VARTYPE-less arrays with FADF_VARIANT */
|
||||||
hr = SafeArrayAllocDescriptor(1, &lpsa);
|
hr = SafeArrayAllocDescriptor(1, &lpsa);
|
||||||
ok(hr == S_OK, "saad failed %08x\n", hr);
|
ok(hr == S_OK, "saad failed %08x\n", hr);
|
||||||
|
|
|
@ -898,8 +898,10 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
|
||||||
VARTYPE vt;
|
VARTYPE vt;
|
||||||
SAFEARRAY *psa = *ppsa;
|
SAFEARRAY *psa = *ppsa;
|
||||||
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
|
ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
|
||||||
|
SAFEARRAYBOUND *bound;
|
||||||
SF_TYPE sftype;
|
SF_TYPE sftype;
|
||||||
GUID guid;
|
GUID guid;
|
||||||
|
INT i;
|
||||||
|
|
||||||
sftype = SAFEARRAY_GetUnionType(psa);
|
sftype = SAFEARRAY_GetUnionType(psa);
|
||||||
|
|
||||||
|
@ -932,7 +934,12 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
|
||||||
Buffer += sizeof(guid);
|
Buffer += sizeof(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(Buffer, psa->rgsabound, sizeof(psa->rgsabound[0]) * psa->cDims);
|
/* bounds are marshaled in opposite order comparing to storage layout */
|
||||||
|
bound = (SAFEARRAYBOUND*)Buffer;
|
||||||
|
for (i = 0; i < psa->cDims; i++)
|
||||||
|
{
|
||||||
|
memcpy(bound++, &psa->rgsabound[psa->cDims-i-1], sizeof(psa->rgsabound[0]));
|
||||||
|
}
|
||||||
Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
|
Buffer += sizeof(psa->rgsabound[0]) * psa->cDims;
|
||||||
|
|
||||||
*(ULONG *)Buffer = ulCellCount;
|
*(ULONG *)Buffer = ulCellCount;
|
||||||
|
|
Loading…
Reference in New Issue