Add tests + implementations for the `HSTRING_User{Size, Marshal, Unmarshal, Free}` methods, required by proxies generated for interfaces that utilize HSTRING.
-- v14: combase: Implement HSTRING_User{Unmarshal, Free}. combase: Implement HSTRING_UserMarshal. combase: Implement HSTRING_UserSize.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/combase.spec | 8 ++++---- dlls/combase/usrmarshal.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 7e2d34447a3..6d992d4a675 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -220,13 +220,13 @@ @ stdcall HPALETTE_UserMarshal(ptr ptr ptr) @ stdcall HPALETTE_UserSize(ptr long ptr) @ stdcall HPALETTE_UserUnmarshal(ptr ptr ptr) -@ stub HSTRING_UserFree +@ stdcall HSTRING_UserFree(ptr ptr) @ stub -arch=win64 HSTRING_UserFree64 -@ stub HSTRING_UserMarshal +@ stdcall HSTRING_UserMarshal(ptr ptr ptr) @ stub -arch=win64 HSTRING_UserMarshal64 -@ stub HSTRING_UserSize +@ stdcall HSTRING_UserSize(ptr long ptr) @ stub -arch=win64 HSTRING_UserSize64 -@ stub HSTRING_UserUnmarshal +@ stdcall HSTRING_UserUnmarshal(ptr ptr ptr) @ stub -arch=win64 HSTRING_UserUnmarshal64 @ stdcall HWND_UserFree(ptr ptr) @ stdcall HWND_UserMarshal(ptr ptr ptr) diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index 87513d335bf..93763434736 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -22,6 +22,7 @@ #define COBJMACROS #include "ole2.h"
+#include "inspectable.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -1025,3 +1026,38 @@ void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk) TRACE("%p.\n", punk); if (punk) IUnknown_Release(punk); } + +/****************************************************************************** + * HSTRING_UserSize (combase.@) + */ +ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG size, HSTRING *str) +{ + FIXME("%p, %lu, %p: stub\n", flags, size, str); + return size; +} + +/****************************************************************************** + * HSTRING_UserMarshal (combase.@) + */ +BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str) +{ + FIXME("%p, %p, %p: stub\n", flags, buf, str); + return buf; +} + +/****************************************************************************** + * HSTRING_UserUnmarshal (combase.@) + */ +BYTE * __RPC_USER HSTRING_UserUnmarshal(ULONG *flags, BYTE *buf, HSTRING *str) +{ + FIXME("%p, %p, %p: stub\n", flags, buf, str); + return buf; +} + +/****************************************************************************** + * HSTRING_UserFree (combase.@) + */ +void __RPC_USER HSTRING_UserFree(ULONG *flags, HSTRING *str) +{ + FIXME("%p, %p: stub\n", flags, str); +}
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 210 ++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index ceb8ffa6e09..81d8c9bc76d 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,214 @@ 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; + 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); + wire->context = 0xdeadbeef; /* The context value is not validated. */ + 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; + wire->context = 0xdeadbeef; /* The context value is not validated. */ + 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 +765,5 @@ START_TEST(string) test_compare(); test_trim(); test_hstring_struct(); + test_marshal(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 12 ++++++------ dlls/combase/usrmarshal.c | 24 +++++++++++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index 81d8c9bc76d..65fa1953573 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -625,7 +625,7 @@ static void test_marshal(void) 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); + 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) @@ -645,7 +645,7 @@ static void test_marshal(void) 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); + 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); @@ -664,7 +664,7 @@ static void test_marshal(void) 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); + 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); @@ -684,7 +684,7 @@ static void test_marshal(void) 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); + 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); @@ -710,7 +710,7 @@ static void test_marshal(void) 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); + 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); @@ -734,7 +734,7 @@ static void test_marshal(void) 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); + 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); diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index 93763434736..47927483623 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -22,6 +22,7 @@ #define COBJMACROS #include "ole2.h"
+#include "winstring.h" #include "inspectable.h" #include "wine/debug.h"
@@ -1027,12 +1028,33 @@ void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk) if (punk) IUnknown_Release(punk); }
+/* The HSTRING value, used for in-process marshaling. */ +struct hstring_wire_ptr +{ + ULONG context; + HSTRING str; +}; + +/* Length-prefixed string data, used in other cases. */ +struct hstring_wire_buf +{ + ULONG context; + ULONG size; + WCHAR data[]; +}; + /****************************************************************************** * HSTRING_UserSize (combase.@) */ ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG size, HSTRING *str) { - FIXME("%p, %lu, %p: stub\n", flags, size, str); + TRACE("%s, %lu, %s.\n", debugstr_user_flags(flags), size, debugstr_hstring(*str)); + + ALIGN_LENGTH(size, 7); + if (LOWORD(*flags) == MSHCTX_INPROC) + size += sizeof(struct hstring_wire_ptr); + else + size += offsetof(struct hstring_wire_buf, data[WindowsGetStringLen(*str)]); return size; }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 48 ++++++++++++++++--------------------- dlls/combase/usrmarshal.c | 32 ++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 29 deletions(-)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index 65fa1953573..282c9d9bb80 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -628,12 +628,11 @@ static void test_marshal(void) 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]); + 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); + 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); + ok(wire->hstring.str == str, "got unexpected address %p\n", wire->hstring.str); wire->context = 0xdeadbeef; /* The context value is not validated. */ next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); if (size == exp_size) @@ -649,11 +648,10 @@ static void test_marshal(void) 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]); + 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); + ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + 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]); @@ -668,11 +666,10 @@ static void test_marshal(void) 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]); + 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); + ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + 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) @@ -688,13 +685,11 @@ static void test_marshal(void) 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]); + 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)); + ok(wire->buf.size == str_bytes, "got buf.size %lu != %lu\n", wire->buf.size, str_bytes); + ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + ok(!memcmp(wire->buf.data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(wire->buf.data, str_bytes)); str2 = NULL; wire->context = 0xdeadbeef; /* The context value is not validated. */ next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); @@ -714,13 +709,11 @@ static void test_marshal(void) 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]); + 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)); + ok(wire->buf.size == str_bytes, "got buf.size %lu != %lu\n", wire->buf.size, str_bytes); + ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + 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]); @@ -738,11 +731,10 @@ static void test_marshal(void) 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]); + 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); + ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); + 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) diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index 47927483623..a8ead5cdeed 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1063,7 +1063,37 @@ ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG size, HSTRING *str) */ BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str) { - FIXME("%p, %p, %p: stub\n", flags, buf, str); + const ULONG context = sizeof(*str) == 8 ? WDT_INPROC64_CALL : WDT_INPROC_CALL; + + TRACE("%s, %p, %s.\n", debugstr_user_flags(flags), buf, debugstr_hstring(*str)); + + if (LOWORD(*flags) == MSHCTX_DIFFERENTMACHINE) + { + FIXME("MSHCTX_DIFFERENTMACHINE is not supported yet.\n"); + RpcRaiseException(RPC_S_INVALID_TAG); + } + + if (LOWORD(*flags) == MSHCTX_INPROC) + { + struct hstring_wire_ptr *wire = ALIGNED_POINTER(buf, 7); + + wire->context = context; + WindowsDuplicateString(*str, &wire->str); + buf = (BYTE *)(&wire->str + 1); + } + else + { + struct hstring_wire_buf *wire = ALIGNED_POINTER(buf, 7); + const WCHAR *str_buf; + UINT32 len; + + wire->context = context; + str_buf = WindowsGetStringRawBuffer(*str, &len); + wire->size = len * sizeof(WCHAR); + memcpy(wire->data, str_buf, wire->size); + buf = (BYTE*)&wire->data[len]; + } + return buf; }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 30 ++++++++++++------------------ dlls/combase/usrmarshal.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index 282c9d9bb80..cd5560dc8a6 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -635,9 +635,8 @@ static void test_marshal(void) ok(wire->hstring.str == str, "got unexpected address %p\n", wire->hstring.str); wire->context = 0xdeadbeef; /* The context value is not validated. */ 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); + ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + ok(str2 == str, "got str2 %p != %p\n", str2, str); HSTRING_UserFree(&umcb.Flags, &str2);
/* Test alignment */ @@ -653,9 +652,8 @@ static void test_marshal(void) ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); 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); + ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + ok(str2 == str, "got str2 %p != %p\n", str2, str); HSTRING_UserFree(&umcb.Flags, &str2);
/* INPROC marshaling with empty/NULL HSTRING */ @@ -672,8 +670,7 @@ static void test_marshal(void) 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(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); ok(!str2, "got str2 %p\n", str2); HSTRING_UserFree(&umcb.Flags, &str2);
@@ -693,13 +690,12 @@ static void test_marshal(void) str2 = NULL; wire->context = 0xdeadbeef; /* The context value is not validated. */ 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(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); + 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)); + 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); @@ -715,13 +711,12 @@ static void test_marshal(void) ok(wire->context == exp_context, "got unexpected prefix %#lx != %#lx\n", wire->context, exp_context); 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); + ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); + 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)); + 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); @@ -737,8 +732,7 @@ static void test_marshal(void) 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(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]); ok(!str2, "got str2 %p\n", str2); HSTRING_UserFree(&umcb.Flags, &str2);
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index a8ead5cdeed..d86ae861ea6 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1102,7 +1102,29 @@ BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str) */ BYTE * __RPC_USER HSTRING_UserUnmarshal(ULONG *flags, BYTE *buf, HSTRING *str) { - FIXME("%p, %p, %p: stub\n", flags, buf, str); + TRACE("%p, %p, %p\n", debugstr_user_flags(flags), buf, str); + + if (LOWORD(*flags) == MSHCTX_INPROC) + { + const struct hstring_wire_ptr *wire = ALIGNED_POINTER(buf, 7); + + *str = wire->str; + TRACE("str=%s\n", debugstr_hstring(*str)); + buf = (BYTE *)(&wire->str + 1); + } + else + { + const struct hstring_wire_buf *wire = ALIGNED_POINTER(buf, 7); + UINT32 len; + HRESULT hr; + + len = wire->size/sizeof(WCHAR); + hr = WindowsCreateString(wire->data, len, str); + if (FAILED(hr)) + RpcRaiseException(RPC_S_OUT_OF_MEMORY); + buf = (BYTE *)&wire->data[len]; + } + return buf; }
@@ -1111,5 +1133,8 @@ BYTE * __RPC_USER HSTRING_UserUnmarshal(ULONG *flags, BYTE *buf, HSTRING *str) */ void __RPC_USER HSTRING_UserFree(ULONG *flags, HSTRING *str) { - FIXME("%p, %p: stub\n", flags, str); + TRACE("%s, %s.\n", debugstr_user_flags(flags), debugstr_hstring(*str)); + + if (LOWORD(*flags) == MSHCTX_INPROC) + WindowsDeleteString(*str); }
On Thu Aug 7 15:26:06 2025 +0000, Nikolay Sivov wrote:
Definition is still too complicated for no reason I think. Maybe let's have two plane structures instead?
Okay, I have split this into two structs. However, I still have kept the union for the tests, since the underlying buffer is the same.
v14:
* Split hstring_wire into hstring_wire_ptr and hstring_wire_buf in the implementation code.