ole32: Implement SNB marshalling.

This commit is contained in:
Nikolay Sivov 2015-05-15 14:03:35 +03:00 committed by Alexandre Julliard
parent 04ed24fb79
commit aa3a234803
2 changed files with 194 additions and 8 deletions

View File

@ -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();
}

View File

@ -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;
}
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 */