Add tests + implementations for the `HSTRING_User{Size, Marshal, Unmarshal, Free}` methods, required by proxies generated for interfaces that utilize HSTRING.
-- v15: combase: Implement HSTRING_User{Unmarshal, Free}. combase: Implement HSTRING_UserMarshal. combase: Implement HSTRING_UserSize. combase/tests: Add tests for HSTRING marshaling methods.
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 | 207 ++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index ceb8ffa6e09..b12fe28b071 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,211 @@ 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)) + +static void test_marshal(void) +{ + struct hstring_wire_inproc + { + ULONG context; + HSTRING str; + }; + + struct hstring_wire_local + { + ULONG context; + ULONG size; + WCHAR data[1]; + }; + + const ULONG exp_context = sizeof(void *) == 8 ? WDT_INPROC64_CALL : WDT_INPROC_CALL; + 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); + HSTRING str, str_empty = NULL, str2 = NULL; + struct hstring_wire_inproc *inproc; + struct hstring_wire_local *local; + MIDL_STUB_MESSAGE stub_msg; + USER_MARSHAL_CB umcb; + ULONG size, exp_size; + RPC_MESSAGE rpc_msg; + BYTE *next, *buffer; + INT32 result = -1; + HRESULT hr; + + buffer = calloc(1, 80); + + 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(*inproc); + 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]); + inproc = (struct hstring_wire_inproc *)buffer; + todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + /* INPROC marshaling just consists of increasing the refcount and copying the address. */ + todo_wine ok(inproc->str == str, "got unexpected address %p\n", inproc->str); + inproc->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(*inproc), 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]); + inproc = ALIGNED_POINTER(&buffer[1], 7); + todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + todo_wine ok(inproc->str == str, "got unexpected address %p\n", inproc->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(*inproc); + 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]); + inproc = (struct hstring_wire_inproc *)buffer; + todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + todo_wine ok(!inproc->str, "got unexpected address %p\n", inproc->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(struct hstring_wire_local, 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]); + local = (struct hstring_wire_local *)buffer; + todo_wine ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); + todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + if (size == exp_size) + todo_wine ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes)); + str2 = NULL; + local->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(struct hstring_wire_local, 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]); + local = ALIGNED_POINTER(&buffer[1], 7); + todo_wine ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); + todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + if (size == exp_size) + todo_wine ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->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(struct hstring_wire_local, 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]); + local = (struct hstring_wire_local *)buffer; + todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + todo_wine ok(!local->size, "got buf.size %lu\n", local->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 +762,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 | 22 +++++++++++++++++++++- 2 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index b12fe28b071..87e90ab8e3d 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -622,7 +622,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(*inproc); - 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) @@ -642,7 +642,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(*inproc), 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); @@ -661,7 +661,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(*inproc); - 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); @@ -681,7 +681,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(struct hstring_wire_local, 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); @@ -707,7 +707,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(struct hstring_wire_local, 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); @@ -731,7 +731,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(struct hstring_wire_local, 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..10193dd3b9e 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,31 @@ void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk) if (punk) IUnknown_Release(punk); }
+struct hstring_wire_inproc +{ + ULONG context; + HSTRING str; +}; + +struct hstring_wire_local +{ + ULONG context; + ULONG size; + WCHAR data[1]; +}; + /****************************************************************************** * 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_inproc); + else + size += offsetof(struct hstring_wire_local, 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 87e90ab8e3d..21f477365ed 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -625,12 +625,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]); inproc = (struct hstring_wire_inproc *)buffer; - todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); /* INPROC marshaling just consists of increasing the refcount and copying the address. */ - todo_wine ok(inproc->str == str, "got unexpected address %p\n", inproc->str); + ok(inproc->str == str, "got unexpected address %p\n", inproc->str); inproc->context = 0xdeadbeef; /* The context value is not validated. */ next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); if (size == exp_size) @@ -646,11 +645,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]); inproc = ALIGNED_POINTER(&buffer[1], 7); - todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); - todo_wine ok(inproc->str == str, "got unexpected address %p\n", inproc->str); + ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + ok(inproc->str == str, "got unexpected address %p\n", inproc->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]); @@ -665,11 +663,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]); inproc = (struct hstring_wire_inproc *)buffer; - todo_wine ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); - todo_wine ok(!inproc->str, "got unexpected address %p\n", inproc->str); + ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); + ok(!inproc->str, "got unexpected address %p\n", inproc->str); str2 = NULL; next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); if (size == exp_size) @@ -685,13 +682,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]); local = (struct hstring_wire_local *)buffer; - todo_wine ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); - todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); - if (size == exp_size) - todo_wine ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes)); + ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); + ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes)); str2 = NULL; local->context = 0xdeadbeef; /* The context value is not validated. */ next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2); @@ -711,13 +706,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]); local = ALIGNED_POINTER(&buffer[1], 7); - todo_wine ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); - todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); - if (size == exp_size) - todo_wine ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes)); + ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes); + ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->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]); @@ -735,11 +728,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]); local = (struct hstring_wire_local *)buffer; - todo_wine ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); - todo_wine ok(!local->size, "got buf.size %lu\n", local->size); + ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); + ok(!local->size, "got buf.size %lu\n", local->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 10193dd3b9e..e152683d0a9 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1061,7 +1061,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_inproc *wire = ALIGNED_POINTER(buf, 7); + + wire->context = context; + WindowsDuplicateString(*str, &wire->str); + buf = (BYTE *)(wire + 1); + } + else + { + struct hstring_wire_local *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 21f477365ed..d18ba1faed1 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -632,9 +632,8 @@ static void test_marshal(void) ok(inproc->str == str, "got unexpected address %p\n", inproc->str); inproc->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 */ @@ -650,9 +649,8 @@ static void test_marshal(void) ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context); ok(inproc->str == str, "got unexpected address %p\n", inproc->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 */ @@ -669,8 +667,7 @@ static void test_marshal(void) ok(!inproc->str, "got unexpected address %p\n", inproc->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);
@@ -690,13 +687,12 @@ static void test_marshal(void) str2 = NULL; local->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); @@ -712,13 +708,12 @@ static void test_marshal(void) ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context); ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->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); @@ -734,8 +729,7 @@ static void test_marshal(void) ok(!local->size, "got buf.size %lu\n", local->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 e152683d0a9..e0c0eb53514 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1100,7 +1100,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_inproc *wire = ALIGNED_POINTER(buf, 7); + + *str = wire->str; + TRACE("str=%s\n", debugstr_hstring(*str)); + buf = (BYTE *)(wire + 1); + } + else + { + const struct hstring_wire_local *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; }
@@ -1109,5 +1131,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 Tue Aug 26 12:30:54 2025 +0000, Nikolay Sivov wrote:
I think it's generally fine, please see attached diff for some mostly cosmetic changes [hstring.diff](/uploads/d6c7986ab815f7a66e7e43bf9550e9ec/hstring.diff). I think it simplifies things a little.
Sure, I have applied these changes in the revision. Thanks :)
Nikolay Sivov (@nsivov) commented about dlls/combase/usrmarshal.c:
#define COBJMACROS #include "ole2.h"
+#include "inspectable.h"
I believe prototypes should go to winstring.h, they appear in other headers too, but that's autogenerated.