Add tests + implementations for the `HSTRING_User{Size, Marshal, Unmarshal, Free}` methods, required by proxies generated for interfaces that utilize HSTRING.
-- v16: combase: Implement HSTRING_User{Unmarshal, Free}. combase: Implement HSTRING_UserMarshal. combase: Implement HSTRING_UserSize. combase/tests: Add tests for HSTRING marshaling methods. combase: Add stubs for HSTRING_User{Size, Marshal, Unmarshal, Free}.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/combase.spec | 8 ++++---- dlls/combase/usrmarshal.c | 36 ++++++++++++++++++++++++++++++++++++ include/winstring.h | 5 +++++ 3 files changed, 45 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..46a9038ba6f 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -22,6 +22,7 @@ #define COBJMACROS #include "ole2.h"
+#include "winstring.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); +} diff --git a/include/winstring.h b/include/winstring.h index 79b284a842e..d0e5e86fd0c 100644 --- a/include/winstring.h +++ b/include/winstring.h @@ -47,6 +47,11 @@ HRESULT WINAPI WindowsSubstringWithSpecifiedLength(HSTRING str, UINT32 pos, HRESULT WINAPI WindowsTrimStringEnd(HSTRING str, HSTRING charstr, HSTRING *out); HRESULT WINAPI WindowsTrimStringStart(HSTRING str, HSTRING charstr, HSTRING *out);
+ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG size, HSTRING *str); +BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str); +BYTE * __RPC_USER HSTRING_UserUnmarshal(ULONG *flags, BYTE *buf, HSTRING *str); +void __RPC_USER HSTRING_UserFree(ULONG *flags, HSTRING *str); + #ifdef __cplusplus } #endif
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/tests/string.c | 206 ++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index ceb8ffa6e09..e50b51f3f11 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -545,6 +545,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 +761,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 | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/dlls/combase/tests/string.c b/dlls/combase/tests/string.c index e50b51f3f11..5f6e2af5ee7 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -621,7 +621,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) @@ -641,7 +641,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); @@ -660,7 +660,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); @@ -680,7 +680,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); @@ -706,7 +706,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); @@ -730,7 +730,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 46a9038ba6f..6d2d7bb16f5 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1027,12 +1027,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 5f6e2af5ee7..5b5c69e07e5 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -624,12 +624,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) @@ -645,11 +644,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]); @@ -664,11 +662,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) @@ -684,13 +681,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); @@ -710,13 +705,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]); @@ -734,11 +727,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 6d2d7bb16f5..ad84b9b45a2 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1060,7 +1060,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 5b5c69e07e5..ade37e753da 100644 --- a/dlls/combase/tests/string.c +++ b/dlls/combase/tests/string.c @@ -631,9 +631,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 */ @@ -649,9 +648,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 */ @@ -668,8 +666,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);
@@ -689,13 +686,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); @@ -711,13 +707,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); @@ -733,8 +728,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 ad84b9b45a2..1d9afd0d248 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1099,7 +1099,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; }
@@ -1108,5 +1130,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 Fri Aug 29 11:14:42 2025 +0000, Vibhav Pant wrote:
changed this line in [version 16 of the diff](/wine/wine/-/merge_requests/8703/diffs?diff_id=204168&start_sha=47ae926b68efc79dbd718d8259b72103c790ec23#b3d65984ee0bbd71c3ec15744b467c93cb7ff587_26_26)
Yes, I didn't notice that winstring.h declares them as well. Thanks.
This merge request was approved by Nikolay Sivov.
This merge request was approved by Huw Davies.