Nikolay Sivov : ole32: Implement SNB marshalling.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 15 08:38:42 CDT 2015


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 15 14:03:35 2015 +0300

ole32: Implement SNB marshalling.

---

 dlls/ole32/tests/usrmarshal.c |  94 ++++++++++++++++++++++++++++++++++++
 dlls/ole32/usrmarshal.c       | 108 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 194 insertions(+), 8 deletions(-)

diff --git a/dlls/ole32/tests/usrmarshal.c b/dlls/ole32/tests/usrmarshal.c
index c994af5..51ccc59 100644
--- a/dlls/ole32/tests/usrmarshal.c
+++ b/dlls/ole32/tests/usrmarshal.c
@@ -768,6 +768,99 @@ static void test_marshal_STGMEDIUM(void)
     HeapFree(GetProcessHeap(), 0, expect_buffer);
 }
 
+static void test_marshal_SNB(void)
+{
+    static const WCHAR str1W[] = {'s','t','r','i','n','g','1',0};
+    static const WCHAR str2W[] = {'s','t','r','2',0};
+    unsigned char *buffer, *src, *mbuf;
+    MIDL_STUB_MESSAGE stub_msg;
+    WCHAR **ptrW, *dataW;
+    USER_MARSHAL_CB umcb;
+    RPC_MESSAGE rpc_msg;
+    RemSNB *wiresnb;
+    SNB snb, snb2;
+    ULONG size;
+
+    /* 4 bytes alignment */
+    snb = NULL;
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    size = SNB_UserSize(&umcb.Flags, 3, &snb);
+    ok(size == 16, "Size should be 16, instead of %d\n", size);
+
+    /* NULL block */
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    size = SNB_UserSize(&umcb.Flags, 0, &snb);
+    ok(size == 12, "Size should be 12, instead of %d\n", size);
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, size);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    mbuf = SNB_UserMarshal(&umcb.Flags, buffer, &snb);
+    ok(mbuf == buffer + size, "got %p, %p\n", mbuf, buffer + size);
+
+    wiresnb = (RemSNB*)buffer;
+    ok(wiresnb->ulCntStr == 0, "got %u\n", wiresnb->ulCntStr);
+    ok(wiresnb->ulCntChar == 0, "got %u\n", wiresnb->ulCntChar);
+    ok(*(ULONG*)wiresnb->rgString == 0, "got %u\n", *(ULONG*)wiresnb->rgString);
+
+    snb2 = NULL;
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
+    ok(snb2 == NULL, "got %p\n", snb2);
+
+    HeapFree(GetProcessHeap(), 0, buffer);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    SNB_UserFree(&umcb.Flags, &snb2);
+
+    /* block with actual data */
+
+    /* allocate source block, n+1 pointers first, then data */
+    src = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR*)*3 + sizeof(str1W) + sizeof(str2W));
+    ptrW = (WCHAR**)src;
+    dataW = *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*));
+    ptrW++;
+    *ptrW = (WCHAR*)(src + 3*sizeof(WCHAR*) + sizeof(str1W));
+    ptrW++;
+    *ptrW = NULL;
+    lstrcpyW(dataW, str1W);
+    dataW += lstrlenW(str1W) + 1;
+    lstrcpyW(dataW, str2W);
+
+    snb = (SNB)src;
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    size = SNB_UserSize(&umcb.Flags, 0, &snb);
+    ok(size == 38, "Size should be 38, instead of %d\n", size);
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, size);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+    SNB_UserMarshal(&umcb.Flags, buffer, &snb);
+
+    wiresnb = (RemSNB*)buffer;
+    ok(wiresnb->ulCntStr == 13, "got %u\n", wiresnb->ulCntStr);
+    ok(wiresnb->ulCntChar == 2, "got %u\n", wiresnb->ulCntChar);
+    /* payload length is stored one more time, as ULONG */
+    ok(*(ULONG*)wiresnb->rgString == wiresnb->ulCntStr, "got %u\n", *(ULONG*)wiresnb->rgString);
+    dataW = &wiresnb->rgString[2];
+    ok(!lstrcmpW(dataW, str1W), "marshalled string 0: %s\n", wine_dbgstr_w(dataW));
+    dataW += sizeof(str1W)/sizeof(WCHAR);
+    ok(!lstrcmpW(dataW, str2W), "marshalled string 1: %s\n", wine_dbgstr_w(dataW));
+
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
+
+    snb2 = NULL;
+    SNB_UserUnmarshal(&umcb.Flags, buffer, &snb2);
+
+    ptrW = snb2;
+    ok(!lstrcmpW(*ptrW, str1W), "unmarshalled string 0: %s\n", wine_dbgstr_w(*ptrW));
+    ptrW++;
+    ok(!lstrcmpW(*ptrW, str2W), "unmarshalled string 1: %s\n", wine_dbgstr_w(*ptrW));
+    ptrW++;
+    ok(*ptrW == NULL, "expected terminating NULL ptr, got %p, start %p\n", *ptrW, snb2);
+
+    HeapFree(GetProcessHeap(), 0, buffer);
+    init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
+    SNB_UserFree(&umcb.Flags, &snb2);
+}
+
 START_TEST(usrmarshal)
 {
     CoInitialize(NULL);
@@ -780,6 +873,7 @@ START_TEST(usrmarshal)
     test_marshal_HMETAFILEPICT();
     test_marshal_WdtpInterfacePointer();
     test_marshal_STGMEDIUM();
+    test_marshal_SNB();
 
     CoUninitialize();
 }
diff --git a/dlls/ole32/usrmarshal.c b/dlls/ole32/usrmarshal.c
index cd16fb2..7875bef 100644
--- a/dlls/ole32/usrmarshal.c
+++ b/dlls/ole32/usrmarshal.c
@@ -2160,25 +2160,117 @@ void __RPC_USER FLAG_STGMEDIUM_UserFree(ULONG *pFlags, FLAG_STGMEDIUM *pStgMediu
 
 ULONG __RPC_USER SNB_UserSize(ULONG *pFlags, ULONG StartingSize, SNB *pSnb)
 {
-    FIXME(":stub\n");
-    return StartingSize;
+    ULONG size = StartingSize;
+
+    TRACE("(%s, %d, %p\n", debugstr_user_flags(pFlags), StartingSize, pSnb);
+
+    ALIGN_LENGTH(size, 3);
+
+    /* two counters from RemSNB header, plus one more ULONG */
+    size += 3*sizeof(ULONG);
+
+    /* now actual data length */
+    if (*pSnb)
+    {
+        WCHAR **ptrW = *pSnb;
+
+        while (*ptrW)
+        {
+            size += (strlenW(*ptrW) + 1)*sizeof(WCHAR);
+            ptrW++;
+        }
+    }
+
+    return size;
 }
 
-unsigned char * __RPC_USER SNB_UserMarshal(  ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
+struct SNB_wire {
+    ULONG charcnt;
+    ULONG strcnt;
+    ULONG datalen;
+    WCHAR data[1];
+};
+
+unsigned char * __RPC_USER SNB_UserMarshal(ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
 {
-    FIXME(":stub\n");
-    return pBuffer;
+    struct SNB_wire *wire;
+    ULONG size;
+
+    TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, pSnb);
+
+    ALIGN_POINTER(pBuffer, 3);
+
+    wire = (struct SNB_wire*)pBuffer;
+    wire->charcnt = wire->strcnt = 0;
+    size = 3*sizeof(ULONG);
+
+    if (*pSnb)
+    {
+        WCHAR **ptrW = *pSnb;
+        WCHAR *dataW = wire->data;
+
+        while (*ptrW)
+        {
+            ULONG len = strlenW(*ptrW) + 1;
+
+            wire->strcnt++;
+            wire->charcnt += len;
+            memcpy(dataW, *ptrW, len*sizeof(WCHAR));
+            dataW += len;
+
+            size += len*sizeof(WCHAR);
+            ptrW++;
+        }
+    }
+
+    wire->datalen = wire->charcnt;
+    return pBuffer + size;
 }
 
 unsigned char * __RPC_USER SNB_UserUnmarshal(ULONG *pFlags, unsigned char *pBuffer, SNB *pSnb)
 {
-    FIXME(":stub\n");
-    return pBuffer;
+    USER_MARSHAL_CB *umcb = (USER_MARSHAL_CB*)pFlags;
+    struct SNB_wire *wire;
+
+    TRACE("(%s, %p, %p)\n", debugstr_user_flags(pFlags), pBuffer, pSnb);
+
+    wire = (struct SNB_wire*)pBuffer;
+
+    if (*pSnb)
+        umcb->pStubMsg->pfnFree(*pSnb);
+
+    if (wire->datalen == 0)
+        *pSnb = NULL;
+    else
+    {
+        WCHAR *src = wire->data, *dest;
+        WCHAR **ptrW;
+        ULONG i;
+
+        ptrW = *pSnb = umcb->pStubMsg->pfnAllocate((wire->strcnt+1)*sizeof(WCHAR*) + wire->datalen);
+        dest = (WCHAR*)(*pSnb + wire->strcnt + 1);
+
+        for (i = 0; i < wire->strcnt; i++)
+        {
+            ULONG len = strlenW(src);
+            memcpy(dest, src, (len + 1)*sizeof(WCHAR));
+            *ptrW = dest;
+            src += len + 1;
+            dest += len + 1;
+            ptrW++;
+        }
+        *ptrW = NULL;
+    }
+
+    return pBuffer + 3*sizeof(ULONG) + wire->datalen*sizeof(WCHAR);
 }
 
 void __RPC_USER SNB_UserFree(ULONG *pFlags, SNB *pSnb)
 {
-    FIXME(":stub\n");
+    USER_MARSHAL_CB *umcb = (USER_MARSHAL_CB*)pFlags;
+    TRACE("(%p)\n", pSnb);
+    if (*pSnb)
+        umcb->pStubMsg->pfnFree(*pSnb);
 }
 
 /* call_as/local stubs for unknwn.idl */




More information about the wine-cvs mailing list