Add implementations for the `HSTRING_User{Size, Marshal, Unmarshal, Free}` methods, required by proxies generated for interfaces that utilize HSTRING.
-- v2: 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..b3321d8baa8 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 start, HSTRING *str) +{ + FIXME("%p, %lu, %p: stub\n", flags, start, str); + return start; +} + +/****************************************************************************** + * 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/oleaut32/tests/Makefile.in | 2 +- dlls/oleaut32/tests/usrmarshal.c | 103 +++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/dlls/oleaut32/tests/Makefile.in b/dlls/oleaut32/tests/Makefile.in index b8e7615a04e..bc90ca78271 100644 --- a/dlls/oleaut32/tests/Makefile.in +++ b/dlls/oleaut32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = oleaut32.dll -IMPORTS = oleaut32 ole32 rpcrt4 user32 gdi32 advapi32 +IMPORTS = oleaut32 ole32 rpcrt4 user32 gdi32 advapi32 combase
SOURCES = \ dispatch.c \ diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 922736b1591..e6d41a30268 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -28,6 +28,8 @@ #include "objbase.h" #include "propidl.h" /* for LPSAFEARRAY_User* routines */
+#include "winstring.h" +#include "inspectable.h" #include "wine/test.h"
typedef struct @@ -807,6 +809,106 @@ static void test_marshal_BSTR(void) SysFreeString(b); }
+#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align)) +#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) +#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) +#define ALIGN_POINTER( _Ptr, _Align ) _Ptr = ALIGNED_POINTER( _Ptr, _Align ) + +static void test_marshal_HSTRING(void) +{ + static const WCHAR str_buf[] = L"marshal_test1"; + static const struct test { + const WCHAR *buf; + MSHCTX ctx; + ULONG offset; + ULONG size; + } tests[] = { + {L"", MSHCTX_INPROC, 0, sizeof(HSTRING)*2}, + {L"", MSHCTX_INPROC, 1, ALIGNED_LENGTH(1 + sizeof(HSTRING) * 2, 7)}, + {L"", MSHCTX_LOCAL, 0, 8 }, + {L"", MSHCTX_LOCAL, 1, 16 }, + {L"", MSHCTX_NOSHAREDMEM, 0, 8 }, + {L"", MSHCTX_NOSHAREDMEM, 1, 16 }, + {str_buf, MSHCTX_INPROC, 0, sizeof(HSTRING) * 2 }, + {str_buf, MSHCTX_LOCAL, 0, 8 + (ARRAY_SIZE(str_buf) - 1) * sizeof(WCHAR)}, + {str_buf, MSHCTX_LOCAL, 1, 8 + 8 + (ARRAY_SIZE(str_buf) - 1) * sizeof(WCHAR)}, + {str_buf, MSHCTX_NOSHAREDMEM, 0, 8 + (ARRAY_SIZE(str_buf) - 1) * sizeof(WCHAR)}, + {str_buf, MSHCTX_NOSHAREDMEM, 1, 8 + 8 + (ARRAY_SIZE(str_buf) - 1) * sizeof(WCHAR)} + }; + SIZE_T i; + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { +#ifdef _WIN64 + const ULONG exp_prefix = WDT_INPROC64_CALL; +#else + const ULONG exp_prefix = WDT_INPROC_CALL; +#endif + const struct test *test = &tests[i]; + MIDL_STUB_MESSAGE stub_msg; + BYTE *buffer, *next, *ptr; + HSTRING str, str2 = NULL; + USER_MARSHAL_CB umcb; + RPC_MESSAGE rpc_msg; + int order = -1; + ULONG size; + HRESULT hr; + BOOL empty = !wcslen(test->buf); + + winetest_push_context("tests[%Iu]", i); + hr = WindowsCreateString(test->buf, wcslen(test->buf), &str); + ok(hr == S_OK, "got hr %#lx.\n", hr); + + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, test->ctx); + size = HSTRING_UserSize(&umcb.Flags, test->offset, &str); + todo_wine ok(size == test->size, "got size %lu != %lu\n", size, test->size); + + if (size != test->size) + { + WindowsDeleteString(str); + winetest_pop_context(); + continue; + } + + buffer = calloc(1, size); + init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, test->ctx); + next = HSTRING_UserMarshal(&umcb.Flags, &buffer[test->offset], &str); + todo_wine ok(next == buffer + size, "got next %p != %p\n", next, buffer + size); + ptr = ALIGNED_POINTER(&buffer[test->offset], 7); + todo_wine ok(*(ULONG *)ptr == exp_prefix, "got unexpected prefix %lx\n", *(ULONG *)ptr); + ptr += sizeof(ULONG); + if (test->ctx == MSHCTX_INPROC) + { + ALIGN_POINTER(ptr, sizeof(HSTRING) - 1); + todo_wine_if(!empty) ok(*(DWORD_PTR *)ptr == (DWORD_PTR)str, "got unexpected address %Ix\n", *(DWORD_PTR *)ptr); + } + else + { + ULONG size; + + size = *(ULONG *)ptr; + todo_wine_if(!empty) ok(size == wcslen(test->buf) * sizeof(WCHAR), "got unexpected size %lu\n", *(ULONG *)ptr); + ptr += sizeof(ULONG); + if (size == wcslen(test->buf) * sizeof(WCHAR)) + todo_wine_if(size) ok(!memcmp(ptr, test->buf, size), "got unexpected buffer %s\n", debugstr_wn((WCHAR *)ptr, size)); + } + + next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[test->offset], &str2); + todo_wine ok(next == buffer + size, "got next %p != %p\n", next, buffer + size); + if (test->ctx == MSHCTX_INPROC || empty) + todo_wine_if(!empty) ok(str2 == str, "got str2 %p != %p\n", str2, str); + else + todo_wine_if(str2) ok(str2 != str, "got str2 %p != %p\n", str2, str); + hr = WindowsCompareStringOrdinal(str, str2, &order); + todo_wine_if(!empty) ok(!order, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str)); + HSTRING_UserFree(&umcb.Flags, &str2); + + free(buffer); + WindowsDeleteString(str); + winetest_pop_context(); + } +} + static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface); @@ -1758,6 +1860,7 @@ START_TEST(usrmarshal) test_marshal_LPSAFEARRAY(); test_marshal_BSTR(); test_marshal_VARIANT(); + test_marshal_HSTRING();
CoUninitialize(); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/usrmarshal.c | 9 ++++++++- dlls/oleaut32/tests/usrmarshal.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index b3321d8baa8..51cb242635e 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"
@@ -1032,7 +1033,13 @@ void WINAPI WdtpInterfacePointer_UserFree(IUnknown *punk) */ ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG start, HSTRING *str) { - FIXME("%p, %lu, %p: stub\n", flags, start, str); + TRACE("%s, %lu, %s.\n", debugstr_user_flags(flags), start, debugstr_hstring(*str)); + + ALIGN_LENGTH(start, 7); + if (LOWORD(*flags) == MSHCTX_INPROC) + start += sizeof(*str) * 2; + else + start += sizeof(ULONG64) + WindowsGetStringLen(*str) * sizeof(WCHAR); return start; }
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index e6d41a30268..41c7c1d255b 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -861,7 +861,7 @@ static void test_marshal_HSTRING(void)
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, test->ctx); size = HSTRING_UserSize(&umcb.Flags, test->offset, &str); - todo_wine ok(size == test->size, "got size %lu != %lu\n", size, test->size); + ok(size == test->size, "got size %lu != %lu\n", size, test->size);
if (size != test->size) {
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/usrmarshal.c | 38 +++++++++++++++++++++++++++++++- dlls/oleaut32/tests/usrmarshal.c | 10 ++++----- 2 files changed, 42 insertions(+), 6 deletions(-)
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index 51cb242635e..3302f62338e 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1048,7 +1048,43 @@ ULONG __RPC_USER HSTRING_UserSize(ULONG *flags, ULONG start, HSTRING *str) */ BYTE * __RPC_USER HSTRING_UserMarshal(ULONG *flags, BYTE *buf, HSTRING *str) { - FIXME("%p, %p, %p: stub\n", flags, buf, str); + 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); + return buf; + } + + ALIGN_POINTER(buf, 7); +#ifdef _WIN64 + *(ULONG *)buf = WDT_INPROC64_CALL; +#else + *(ULONG *)buf = WDT_INPROC_CALL; +#endif + buf += sizeof(ULONG); + if (LOWORD(*flags) == MSHCTX_INPROC) + { + HSTRING dup; + + WindowsDuplicateString(*str, &dup); + ALIGN_POINTER(buf, sizeof(*str) - 1); + *(HSTRING *)buf = dup; + buf += sizeof(*str); + } + else + { + UINT32 len, size; + const WCHAR *str_buf; + + str_buf = WindowsGetStringRawBuffer(*str, &len); + *(ULONG *)buf = size = len * sizeof(WCHAR); + buf += sizeof(ULONG); + memcpy(buf, str_buf, size); + buf += size; + } + return buf; }
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 41c7c1d255b..0f2ce7dd70d 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -873,24 +873,24 @@ static void test_marshal_HSTRING(void) buffer = calloc(1, size); init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, test->ctx); next = HSTRING_UserMarshal(&umcb.Flags, &buffer[test->offset], &str); - 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); ptr = ALIGNED_POINTER(&buffer[test->offset], 7); - todo_wine ok(*(ULONG *)ptr == exp_prefix, "got unexpected prefix %lx\n", *(ULONG *)ptr); + ok(*(ULONG *)ptr == exp_prefix, "got unexpected prefix %lx\n", *(ULONG *)ptr); ptr += sizeof(ULONG); if (test->ctx == MSHCTX_INPROC) { ALIGN_POINTER(ptr, sizeof(HSTRING) - 1); - todo_wine_if(!empty) ok(*(DWORD_PTR *)ptr == (DWORD_PTR)str, "got unexpected address %Ix\n", *(DWORD_PTR *)ptr); + ok(*(DWORD_PTR *)ptr == (DWORD_PTR)str, "got unexpected address %Ix\n", *(DWORD_PTR *)ptr); } else { ULONG size;
size = *(ULONG *)ptr; - todo_wine_if(!empty) ok(size == wcslen(test->buf) * sizeof(WCHAR), "got unexpected size %lu\n", *(ULONG *)ptr); + ok(size == wcslen(test->buf) * sizeof(WCHAR), "got unexpected size %lu\n", *(ULONG *)ptr); ptr += sizeof(ULONG); if (size == wcslen(test->buf) * sizeof(WCHAR)) - todo_wine_if(size) ok(!memcmp(ptr, test->buf, size), "got unexpected buffer %s\n", debugstr_wn((WCHAR *)ptr, size)); + ok(!memcmp(ptr, test->buf, size), "got unexpected buffer %s\n", debugstr_wn((WCHAR *)ptr, size)); }
next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[test->offset], &str2);
From: Vibhav Pant vibhavp@gmail.com
--- dlls/combase/usrmarshal.c | 36 ++++++++++++++++++++++++++++++-- dlls/oleaut32/tests/usrmarshal.c | 8 +++---- 2 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/dlls/combase/usrmarshal.c b/dlls/combase/usrmarshal.c index 3302f62338e..757e84d6eb7 100644 --- a/dlls/combase/usrmarshal.c +++ b/dlls/combase/usrmarshal.c @@ -1093,7 +1093,36 @@ 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); +#ifdef _WIN64 + static const ULONG prefix = WDT_INPROC64_CALL; +#else + static const ULONG prefix = WDT_INPROC_CALL; +#endif + TRACE("%p, %p, %p\n", debugstr_user_flags(flags), buf, str); + + ALIGN_POINTER(buf, 7); + if (*(ULONG *)buf != prefix) + RpcRaiseException(RPC_S_INVALID_TAG); + buf += sizeof(ULONG); + if (LOWORD(*flags) == MSHCTX_INPROC) + { + ALIGN_POINTER(buf, sizeof(*str) - 1); + *str = *(HSTRING *)buf; + TRACE("str=%s\n", debugstr_hstring(*str)); + buf += sizeof(*str); + } + else + { + UINT32 size; + + size = *(ULONG *)buf; + buf += sizeof(ULONG); + if (size % 2) + RpcRaiseException(RPC_S_INVALID_BOUND); + WindowsCreateString((WCHAR *)buf, size/sizeof(WCHAR), str); + buf += size; + } + return buf; }
@@ -1102,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); } diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 0f2ce7dd70d..fa9da1f8d4f 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -894,13 +894,13 @@ static void test_marshal_HSTRING(void) }
next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[test->offset], &str2); - 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); if (test->ctx == MSHCTX_INPROC || empty) - todo_wine_if(!empty) ok(str2 == str, "got str2 %p != %p\n", str2, str); + ok(str2 == str, "got str2 %p != %p\n", str2, str); else - todo_wine_if(str2) ok(str2 != str, "got str2 %p != %p\n", str2, str); + ok(str2 != str, "got str2 %p != %p\n", str2, str); hr = WindowsCompareStringOrdinal(str, str2, &order); - todo_wine_if(!empty) ok(!order, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str)); + ok(!order, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str)); HSTRING_UserFree(&umcb.Flags, &str2);
free(buffer);