Nikolay Sivov : oleaut32: Fix multidimensional SAFEARRAY marshalling.

Alexandre Julliard julliard at winehq.org
Tue Oct 19 13:03:45 CDT 2010


Module: wine
Branch: master
Commit: b08d3d2656746cfd78be59cea2e06abd178a1ddc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b08d3d2656746cfd78be59cea2e06abd178a1ddc

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Oct 19 02:35:27 2010 +0400

oleaut32: Fix multidimensional SAFEARRAY marshalling.

---

 dlls/oleaut32/tests/usrmarshal.c |   96 ++++++++++++++++++++++++++++++--------
 dlls/oleaut32/usrmarshal.c       |    9 +++-
 2 files changed, 84 insertions(+), 21 deletions(-)

diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c
index 9275837..1aae0f5 100644
--- a/dlls/oleaut32/tests/usrmarshal.c
+++ b/dlls/oleaut32/tests/usrmarshal.c
@@ -120,9 +120,11 @@ static DWORD elem_wire_size(LPSAFEARRAY lpsa, SF_TYPE sftype)
 static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
 {
     unsigned char *wiresa = buffer;
+    const SAFEARRAYBOUND *bounds;
     VARTYPE vt;
     SF_TYPE sftype;
     ULONG cell_count;
+    int i;
 
     if(!lpsa)
     {
@@ -163,7 +165,18 @@ static void check_safearray(void *buffer, LPSAFEARRAY lpsa)
         ok(IsEqualGUID(&guid, wiresa), "guid mismatch\n");
         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;
 
     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;
     LPSAFEARRAY lpsa;
     LPSAFEARRAY lpsa2 = NULL;
-    SAFEARRAYBOUND sab;
+    SAFEARRAYBOUND sab[2];
     RPC_MESSAGE rpc_msg;
     MIDL_STUB_MESSAGE stub_msg;
     USER_MARSHAL_CB umcb;
@@ -220,22 +233,66 @@ static void test_marshal_LPSAFEARRAY(void)
     int i;
     LONG indices[1];
 
-    sab.lLbound = 5;
-    sab.cElements = 10;
+    sab[0].lLbound = 5;
+    sab[0].cElements = 10;
 
-    lpsa = SafeArrayCreate(VT_I2, 1, &sab);
+    lpsa = SafeArrayCreate(VT_I2, 1, 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(ULONG) - 1) & ~(sizeof(ULONG) - 1);
-    expected += sab.cElements * sizeof(USHORT);
+    expected += sab[0].cElements * 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 = 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 */
        "size should be %u bytes, not %u\n", expected, size);
     buffer = HeapAlloc(GetProcessHeap(), 0, size);
@@ -284,22 +341,22 @@ static void test_marshal_LPSAFEARRAY(void)
     }
     HeapFree(GetProcessHeap(), 0, buffer);
 
-    sab.lLbound = 5;
-    sab.cElements = 10;
+    sab[0].lLbound = 5;
+    sab[0].cElements = 10;
 
-    lpsa = SafeArrayCreate(VT_R8, 1, &sab);
+    lpsa = SafeArrayCreate(VT_R8, 1, sab);
     *(double *)lpsa->pvData = 3.1415;
 
     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(double) - 1)) & ~(sizeof(double) - 1);
-    expected += sab.cElements * sizeof(double);
+    expected += sab[0].cElements * sizeof(double);
     ok(size == expected || size == expected + 16, /* win64 */
        "size should be %u bytes, not %u\n", expected, size);
     init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_DIFFERENTMACHINE);
     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);
     ok(size == expected || size == expected + 8, /* win64 */
        "size should be %u bytes, not %u\n", expected, size);
@@ -344,19 +401,19 @@ static void test_marshal_LPSAFEARRAY(void)
     SafeArrayDestroyDescriptor(lpsa);
 
     /* Test an array of VT_BSTR */
-    sab.lLbound = 3;
-    sab.cElements = sizeof(values) / sizeof(values[0]);
+    sab[0].lLbound = 3;
+    sab[0].cElements = sizeof(values) / sizeof(values[0]);
 
-    lpsa = SafeArrayCreate(VT_BSTR, 1, &sab);
+    lpsa = SafeArrayCreate(VT_BSTR, 1, sab);
     expected_bstr_size = 0;
-    for (i = 0; i < sab.cElements; i++)
+    for (i = 0; i < sab[0].cElements; i++)
     {
         int j;
         WCHAR buf[128];
         for (j = 0; j <= i; j++)
             buf[j] = 'a' + j;
         buf[j] = 0;
-        indices[0] = i + sab.lLbound;
+        indices[0] = i + sab[0].lLbound;
         values[i] = SysAllocString(buf);
         hr = SafeArrayPutElement(lpsa, indices, values[i]);
         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);
     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
     ok(size == expected + sizeof(DWORD) || size  == (expected + sizeof(DWORD) + 12 /* win64 */),
             "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)
         {
-            indices[0] = i + sab.lLbound;
+            indices[0] = i + sab[0].lLbound;
             hr = SafeArrayGetElement(lpsa2, indices, &gotvalue);
             ok(hr == S_OK, "Failed to get bstr element at hres 0x%x\n", hr);
             if (hr == S_OK)
@@ -423,7 +480,6 @@ static void test_marshal_LPSAFEARRAY(void)
     HeapFree(GetProcessHeap(), 0, buffer);
     SafeArrayDestroy(lpsa);
 
-
     /* VARTYPE-less arrays with FADF_VARIANT */
     hr = SafeArrayAllocDescriptor(1, &lpsa);
     ok(hr == S_OK, "saad failed %08x\n", hr);
diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c
index 402794c..4884c66 100644
--- a/dlls/oleaut32/usrmarshal.c
+++ b/dlls/oleaut32/usrmarshal.c
@@ -898,8 +898,10 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
         VARTYPE vt;
         SAFEARRAY *psa = *ppsa;
         ULONG ulCellCount = SAFEARRAY_GetCellCount(psa);
+        SAFEARRAYBOUND *bound;
         SF_TYPE sftype;
         GUID guid;
+        INT i;
 
         sftype = SAFEARRAY_GetUnionType(psa);
 
@@ -932,7 +934,12 @@ unsigned char * WINAPI LPSAFEARRAY_UserMarshal(ULONG *pFlags, unsigned char *Buf
             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;
 
         *(ULONG *)Buffer = ulCellCount;




More information about the wine-cvs mailing list