From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 208 ++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index ceb8ffa6e09..8806930cff8 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -24,6 +24,7 @@ #include "winbase.h" #include "winerror.h" #include "winstring.h" +#include "inspectable.h"
#include "wine/test.h"
@@ -545,6 +546,212 @@ static void test_hstring_struct(void) ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref.\n"); }
+static void * WINAPI user_allocate(SIZE_T size) +{ + ok(0, "unexpected user_allocate call\n"); + return CoTaskMemAlloc(size); +} + +static void WINAPI user_free(void *p) +{ + ok(0, "unexpected user_free call\n"); + CoTaskMemFree(p); +} + +static void init_user_marshal_cb(USER_MARSHAL_CB *umcb, + PMIDL_STUB_MESSAGE stub_msg, + PRPC_MESSAGE rpc_msg, unsigned char *buffer, + unsigned int size, MSHCTX context) +{ + memset(rpc_msg, 0, sizeof(*rpc_msg)); + rpc_msg->Buffer = buffer; + rpc_msg->BufferLength = size; + + memset(stub_msg, 0, sizeof(*stub_msg)); + stub_msg->RpcMsg = rpc_msg; + stub_msg->Buffer = buffer; + stub_msg->pfnAllocate = user_allocate; + stub_msg->pfnFree = user_free; + + memset(umcb, 0, sizeof(*umcb)); + umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION); + umcb->pStubMsg = stub_msg; + umcb->Signature = USER_MARSHAL_CB_SIGNATURE; + umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE; +} + +#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align)) +#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) + +union hstring_wire +{ + ULONG context; + struct { + ULONG context; + HSTRING str; + } hstring; + struct { + ULONG context; + ULONG size; + WCHAR data[]; + } buf; +}; + +static void test_marshal(void) +{ + static const WCHAR str_buf[] = L"marshal_test1"; + static const ULONG str_len = ARRAY_SIZE(str_buf) - 1; + static const ULONG str_bytes = str_len * sizeof(WCHAR); +#ifdef _WIN64 + const ULONG exp_context = WDT_INPROC64_CALL; +#else + const ULONG exp_context = WDT_INPROC_CALL; +#endif + HSTRING str, str_empty = NULL, str2 = NULL; + const union hstring_wire *wire; + BYTE *buffer = calloc(1, 80); + MIDL_STUB_MESSAGE stub_msg; + USER_MARSHAL_CB umcb; + ULONG size, exp_size; + RPC_MESSAGE rpc_msg; + INT32 result = -1; + BYTE *next; + HRESULT hr; + + hr = WindowsCreateString(str_buf, wcslen(str_buf), &str); + ok(hr == S_OK, "got hr %#lx\n", hr); + + /* INPROC marshaling */ + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); + size = HSTRING_UserSize(&umcb.Flags, 0, &str); + exp_size = sizeof(union hstring_wire); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC); + next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = (union hstring_wire *)buffer; + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + /* INPROC marshaling just consists of increasing the refcount and copying the address. */ + todo_wine ok(wire->hstring.str == str, "got unexpected address %p\n", wire->hstring.str); + next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + todo_wine ok(str2 == str, "got str2 %p != %p\n", str2, str); + HSTRING_UserFree(&umcb.Flags, &str2); + + /* Test alignment */ + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); + size = HSTRING_UserSize(&umcb.Flags, 1, &str); + exp_size = ALIGNED_LENGTH(1 + sizeof(union hstring_wire), 7); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + memset(buffer, 0, 80); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC); + next = HSTRING_UserMarshal(&umcb.Flags, &buffer[1], &str); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = ALIGNED_POINTER(&buffer[1], 7); + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + todo_wine ok(wire->hstring.str == str, "got unexpected address %p\n", wire->hstring.str); + next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[1], &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + todo_wine ok(str2 == str, "got str2 %p != %p\n", str2, str); + HSTRING_UserFree(&umcb.Flags, &str2); + + /* INPROC marshaling with empty/NULL HSTRING */ + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC); + size = HSTRING_UserSize(&umcb.Flags, 0, &str_empty); + exp_size = sizeof(union hstring_wire); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + memset(buffer, 0xff, 80); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC); + next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str_empty); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = (union hstring_wire *)buffer; + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + todo_wine ok(!wire->hstring.str, "got unexpected address %p\n", wire->hstring.str); + str2 = NULL; + next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + ok(!str2, "got str2 %p\n", str2); + HSTRING_UserFree(&umcb.Flags, &str2); + + /* Out of process marshaling */ + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HSTRING_UserSize(&umcb.Flags, 0, &str); + exp_size = offsetof(union hstring_wire, buf.data[str_len]); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + memset(buffer, 0, 80); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = (union hstring_wire *)buffer; + todo_wine ok(wire->buf.size == str_bytes, "got buf.size %lu != %lu\n", wire->buf.size, str_bytes); + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + if (size == exp_size) + todo_wine ok(!memcmp(wire->buf.data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(wire->buf.data, str_bytes)); + str2 = NULL; + next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + /* A new HSTRING should be allocated */ + todo_wine_if(str2) ok(str2 != str, "got str2 %p\n", str2); + hr = WindowsCompareStringOrdinal(str2, str, &result); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(!result, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str)); + HSTRING_UserFree(&umcb.Flags, &str2); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HSTRING_UserSize(&umcb.Flags, 1, &str); + exp_size = ALIGNED_LENGTH(1, 7) + offsetof(union hstring_wire, buf.data[str_len]); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + memset(buffer, 0, 80); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + next = HSTRING_UserMarshal(&umcb.Flags, &buffer[1], &str); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = ALIGNED_POINTER(&buffer[1], 7); + todo_wine ok(wire->buf.size == str_bytes, "got buf.size %lu != %lu\n", wire->buf.size, str_bytes); + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + if (size == exp_size) + todo_wine ok(!memcmp(wire->buf.data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(wire->buf.data, str_bytes)); + next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[1], &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + todo_wine_if(str2) ok(str2 != str, "got str2 %p\n", str2); + result = -1; + hr = WindowsCompareStringOrdinal(str2, str, &result); + ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(!result, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str)); + HSTRING_UserFree(&umcb.Flags, &str2); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL); + size = HSTRING_UserSize(&umcb.Flags, 0, &str_empty); + exp_size = offsetof(union hstring_wire, buf.data[0]); + todo_wine ok(size == exp_size, "got size %lu != %lu\n", size, exp_size); + memset(buffer, 0xff, 80); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL); + next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str_empty); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + wire = (union hstring_wire *)buffer; + todo_wine ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + todo_wine ok(!wire->buf.size, "got buf.size %lu\n", wire->buf.size); + str2 = NULL; + next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); + if (size == exp_size) + todo_wine ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + ok(!str2, "got str2 %p\n", str2); + HSTRING_UserFree(&umcb.Flags, &str2); + + WindowsDeleteString(str); + free(buffer); +} + START_TEST(string) { test_create_delete(); @@ -556,4 +763,5 @@ START_TEST(string) test_compare(); test_trim(); test_hstring_struct(); + test_marshal(); }