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