-- v3: combase: Fix initialization flags in RoInitialize. vccorlib140: Add Platform::Details::InitializeData semi-stub.
From: Piotr Caban piotr@codeweavers.com
--- configure | 1 + configure.ac | 1 + dlls/vccorlib140/Makefile.in | 4 + dlls/vccorlib140/tests/Makefile.in | 4 + dlls/vccorlib140/tests/vccorlib.c | 222 +++++++++++++++++++++++++++++ dlls/vccorlib140/vccorlib.c | 42 ++++++ dlls/vccorlib140/vccorlib140.spec | 5 +- 7 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 dlls/vccorlib140/tests/Makefile.in create mode 100644 dlls/vccorlib140/tests/vccorlib.c create mode 100644 dlls/vccorlib140/vccorlib.c
diff --git a/configure b/configure index 1f606fb0fb6..8ee9a73e34d 100755 --- a/configure +++ b/configure @@ -22935,6 +22935,7 @@ wine_fn_config_makefile dlls/uxtheme/tests enable_tests wine_fn_config_makefile dlls/vbscript enable_vbscript wine_fn_config_makefile dlls/vbscript/tests enable_tests wine_fn_config_makefile dlls/vccorlib140 enable_vccorlib140 +wine_fn_config_makefile dlls/vccorlib140/tests enable_tests wine_fn_config_makefile dlls/vcomp enable_vcomp wine_fn_config_makefile dlls/vcomp/tests enable_tests wine_fn_config_makefile dlls/vcomp100 enable_vcomp100 diff --git a/configure.ac b/configure.ac index 33c5f0aee8d..53a1cebae94 100644 --- a/configure.ac +++ b/configure.ac @@ -3219,6 +3219,7 @@ WINE_CONFIG_MAKEFILE(dlls/uxtheme/tests) WINE_CONFIG_MAKEFILE(dlls/vbscript) WINE_CONFIG_MAKEFILE(dlls/vbscript/tests) WINE_CONFIG_MAKEFILE(dlls/vccorlib140) +WINE_CONFIG_MAKEFILE(dlls/vccorlib140/tests) WINE_CONFIG_MAKEFILE(dlls/vcomp) WINE_CONFIG_MAKEFILE(dlls/vcomp/tests) WINE_CONFIG_MAKEFILE(dlls/vcomp100) diff --git a/dlls/vccorlib140/Makefile.in b/dlls/vccorlib140/Makefile.in index a6388cbf8c5..13d54aa369e 100644 --- a/dlls/vccorlib140/Makefile.in +++ b/dlls/vccorlib140/Makefile.in @@ -1 +1,5 @@ MODULE = vccorlib140.dll +IMPORTS = combase + +SOURCES = \ + vccorlib.c diff --git a/dlls/vccorlib140/tests/Makefile.in b/dlls/vccorlib140/tests/Makefile.in new file mode 100644 index 00000000000..099ec81aa63 --- /dev/null +++ b/dlls/vccorlib140/tests/Makefile.in @@ -0,0 +1,4 @@ +TESTDLL = vccorlib140.dll +IMPORTS = ole32 uuid + +SOURCES = vccorlib.c diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c new file mode 100644 index 00000000000..581bca3c838 --- /dev/null +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -0,0 +1,222 @@ +/* + * Unit tests for miscellaneous vccorlib functions + * + * Copyright 2025 Piotr Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "objbase.h" +#include "wine/test.h" + +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE; static unsigned int called_ ## func = 0 + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func++; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func, n) \ + do { \ + ok(called_ ## func == n, "expected " #func " called %u times, got %u\n", n, called_ ## func); \ + expect_ ## func = FALSE; \ + called_ ## func = 0; \ + }while(0) + +DEFINE_EXPECT(PreInitialize); +DEFINE_EXPECT(PostInitialize); +DEFINE_EXPECT(PreUninitialize); +DEFINE_EXPECT(PostUninitialize); + +static HRESULT (__cdecl *pInitializeData)(int); +static void (__cdecl *pUninitializeData)(int); + +static BOOL init(void) +{ + HMODULE hmod = LoadLibraryA("vccorlib140.dll"); + + if (!hmod) + { + win_skip("vccorlib140.dll not available\n"); + return FALSE; + } + + pInitializeData = (void *)GetProcAddress(hmod, + "?InitializeData@Details@Platform@@YAJH@Z"); + ok(pInitializeData != NULL, "InitializeData not available\n"); + pUninitializeData = (void *)GetProcAddress(hmod, + "?UninitializeData@Details@Platform@@YAXH@Z"); + ok(pUninitializeData != NULL, "UninitializeData not available\n"); + + return TRUE; +} + +static HRESULT WINAPI InitializeSpy_QI(IInitializeSpy *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IInitializeSpy) || IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IInitializeSpy_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI InitializeSpy_AddRef(IInitializeSpy *iface) +{ + return 2; +} + +static ULONG WINAPI InitializeSpy_Release(IInitializeSpy *iface) +{ + return 1; +} + +static DWORD exp_coinit; +static HRESULT WINAPI InitializeSpy_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs) +{ + CHECK_EXPECT(PreInitialize); + todo_wine_if(coinit == COINIT_APARTMENTTHREADED) + ok(coinit == exp_coinit, "coinit = %lx\n", coinit); + return S_OK; +} + +static HRESULT WINAPI InitializeSpy_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs) +{ + CHECK_EXPECT(PostInitialize); + return hr; +} + +static HRESULT WINAPI InitializeSpy_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs) +{ + CHECK_EXPECT(PreUninitialize); + return S_OK; +} + +static HRESULT WINAPI InitializeSpy_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs) +{ + CHECK_EXPECT(PostUninitialize); + return S_OK; +} + +static const IInitializeSpyVtbl InitializeSpyVtbl = +{ + InitializeSpy_QI, + InitializeSpy_AddRef, + InitializeSpy_Release, + InitializeSpy_PreInitialize, + InitializeSpy_PostInitialize, + InitializeSpy_PreUninitialize, + InitializeSpy_PostUninitialize +}; + +static IInitializeSpy InitializeSpy = { &InitializeSpyVtbl }; + +static void test_InitializeData(void) +{ + ULARGE_INTEGER cookie; + HRESULT hr; + + hr = CoRegisterInitializeSpy(&InitializeSpy, &cookie); + ok(hr == S_OK, "CoRegisterInitializeSpy returned %lx\n", hr); + + hr = pInitializeData(0); + ok(hr == S_OK, "InitializeData returned %lx\n", hr); + + exp_coinit = COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE; + SET_EXPECT(PreInitialize); + SET_EXPECT(PostInitialize); + hr = pInitializeData(1); + ok(hr == S_OK, "InitializeData returned %lx\n", hr); + CHECK_CALLED(PreInitialize, 1); + CHECK_CALLED(PostInitialize, 1); + + SET_EXPECT(PreInitialize); + SET_EXPECT(PostInitialize); + hr = pInitializeData(1); + ok(hr == S_OK, "InitializeData returned %lx\n", hr); + CHECK_CALLED(PreInitialize, 1); + CHECK_CALLED(PostInitialize, 1); + + exp_coinit = COINIT_MULTITHREADED; + SET_EXPECT(PreInitialize); + SET_EXPECT(PostInitialize); + hr = pInitializeData(2); + ok(hr == RPC_E_CHANGED_MODE, "InitializeData returned %lx\n", hr); + CHECK_CALLED(PreInitialize, 1); + CHECK_CALLED(PostInitialize, 1); + + pUninitializeData(0); + SET_EXPECT(PreUninitialize); + SET_EXPECT(PostUninitialize); + pUninitializeData(1); + CHECK_CALLED(PreUninitialize, 1); + CHECK_CALLED(PostUninitialize, 1); + SET_EXPECT(PreUninitialize); + SET_EXPECT(PostUninitialize); + pUninitializeData(2); + CHECK_CALLED(PreUninitialize, 1); + CHECK_CALLED(PostUninitialize, 1); + + SET_EXPECT(PreInitialize); + SET_EXPECT(PostInitialize); + hr = pInitializeData(2); + ok(hr == S_OK, "InitializeData returned %lx\n", hr); + CHECK_CALLED(PreInitialize, 1); + CHECK_CALLED(PostInitialize, 1); + SET_EXPECT(PreUninitialize); + SET_EXPECT(PostUninitialize); + pUninitializeData(2); + CHECK_CALLED(PreUninitialize, 1); + CHECK_CALLED(PostUninitialize, 1); + + SET_EXPECT(PreInitialize); + SET_EXPECT(PostInitialize); + hr = pInitializeData(3); + ok(hr == S_OK, "InitializeData returned %lx\n", hr); + CHECK_CALLED(PreInitialize, 1); + CHECK_CALLED(PostInitialize, 1); + SET_EXPECT(PreUninitialize); + SET_EXPECT(PostUninitialize); + pUninitializeData(3); + CHECK_CALLED(PreUninitialize, 1); + CHECK_CALLED(PostUninitialize, 1); + + hr = CoRevokeInitializeSpy(cookie); + ok(hr == S_OK, "CoRevokeInitializeSpy returned %lx\n", hr); +} + +START_TEST(vccorlib) +{ + if(!init()) + return; + + test_InitializeData(); +} diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c new file mode 100644 index 00000000000..6665a5962a5 --- /dev/null +++ b/dlls/vccorlib140/vccorlib.c @@ -0,0 +1,42 @@ +/* + * Copyright 2025 Piotr Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "roapi.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(vccorlib); + +HRESULT __cdecl InitializeData(int type) +{ + HRESULT hres; + + FIXME("(%d) semi-stub\n", type); + + if (!type) return S_OK; + + hres = RoInitialize(type == 1 ? RO_INIT_SINGLETHREADED : RO_INIT_MULTITHREADED); + if (FAILED(hres)) return hres; + return S_OK; +} + +void __cdecl UninitializeData(int type) +{ + TRACE("(%d)\n", type); + + if (type) RoUninitialize(); +} diff --git a/dlls/vccorlib140/vccorlib140.spec b/dlls/vccorlib140/vccorlib140.spec index efdecef5de6..ecae1e9464a 100644 --- a/dlls/vccorlib140/vccorlib140.spec +++ b/dlls/vccorlib140/vccorlib140.spec @@ -184,8 +184,7 @@ @ stub -arch=win64 ?GetWeakReference@Details@Platform@@YAPEAU__abi_IUnknown@@QE$ADVObject@2@@Z @ stub -arch=win32 ?InitControlBlock@ControlBlock@Details@Platform@@AAEXPAX_N11@Z @ stub -arch=win64 ?InitControlBlock@ControlBlock@Details@Platform@@AEAAXPEAX_N11@Z -@ stub -arch=win32 ?InitializeData@Details@Platform@@YAJH@Z -@ stub -arch=win64 ?InitializeData@Details@Platform@@YAJH@Z +@ cdecl ?InitializeData@Details@Platform@@YAJH@Z(long) InitializeData @ stub -arch=win32 ?Intersect@Rect@Foundation@Windows@@QAAXV123@@Z @ stub -arch=win64 ?Intersect@Rect@Foundation@Windows@@QEAAXV123@@Z @ stub -arch=win32 ?IntersectsWith@Rect@Foundation@Windows@@QAA_NV123@@Z @@ -274,7 +273,7 @@ @ stub -arch=win64 ?ToString@uint64@default@@QEAAPE$AAVString@Platform@@XZ @ stub -arch=win32 ?ToString@uint8@default@@QAAP$AAVString@Platform@@XZ @ stub -arch=win64 ?ToString@uint8@default@@QEAAPE$AAVString@Platform@@XZ -@ stub ?UninitializeData@Details@Platform@@YAXH@Z +@ cdecl ?UninitializeData@Details@Platform@@YAXH@Z(long) UninitializeData @ stub -arch=win32 ?Union@Rect@Foundation@Windows@@QAAXV123@@Z @ stub -arch=win64 ?Union@Rect@Foundation@Windows@@QEAAXV123@@Z @ stub -arch=win32 ?Union@Rect@Foundation@Windows@@QAAXVPoint@23@@Z
From: Piotr Caban piotr@codeweavers.com
--- dlls/combase/roapi.c | 2 +- dlls/combase/tests/roapi.c | 30 ++++++++++++++++++++++++++++++ dlls/vccorlib140/tests/vccorlib.c | 3 +-- 3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/dlls/combase/roapi.c b/dlls/combase/roapi.c index df3a3c5c176..aee5f69bc5a 100644 --- a/dlls/combase/roapi.c +++ b/dlls/combase/roapi.c @@ -125,7 +125,7 @@ HRESULT WINAPI RoInitialize(RO_INIT_TYPE type) { switch (type) { case RO_INIT_SINGLETHREADED: - return CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + return CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); default: FIXME("type %d\n", type); case RO_INIT_MULTITHREADED: diff --git a/dlls/combase/tests/roapi.c b/dlls/combase/tests/roapi.c index ab5dbff6017..ea395778a85 100644 --- a/dlls/combase/tests/roapi.c +++ b/dlls/combase/tests/roapi.c @@ -22,6 +22,7 @@ #include "winbase.h" #include "winerror.h" #include "winstring.h" +#include "winternl.h"
#include "initguid.h" #include "roapi.h" @@ -212,6 +213,28 @@ static DWORD WINAPI mta_init_implicit_thread(void *dummy) return 0; }
+enum oletlsflags +{ + OLETLS_UUIDINITIALIZED = 0x2, + OLETLS_DISABLE_OLE1DDE = 0x40, + OLETLS_APARTMENTTHREADED = 0x80, + OLETLS_MULTITHREADED = 0x100, +}; + +struct oletlsdata +{ + void *threadbase; + void *smallocator; + DWORD id; + DWORD flags; +}; + +static DWORD get_oletlsflags(void) +{ + struct oletlsdata *data = NtCurrentTeb()->ReservedForOle; + return data ? data->flags : 0; +} + static void test_implicit_mta(void) { static const struct @@ -247,7 +270,14 @@ static void test_implicit_mta(void) { winetest_push_context("test %u", i); if (tests[i].ro_init) + { + DWORD flags = tests[i].mta ? OLETLS_MULTITHREADED : OLETLS_APARTMENTTHREADED; + hr = RoInitialize(tests[i].mta ? RO_INIT_MULTITHREADED : RO_INIT_SINGLETHREADED); + + flags |= OLETLS_DISABLE_OLE1DDE; + ok((get_oletlsflags() & flags) == flags, "get_oletlsflags() = %lx\n", get_oletlsflags()); + } else hr = CoInitializeEx(NULL, tests[i].mta ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED); ok(hr == S_OK, "got %#lx.\n", hr); diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index 581bca3c838..035cfdb880f 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -103,8 +103,7 @@ static DWORD exp_coinit; static HRESULT WINAPI InitializeSpy_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs) { CHECK_EXPECT(PreInitialize); - todo_wine_if(coinit == COINIT_APARTMENTTHREADED) - ok(coinit == exp_coinit, "coinit = %lx\n", coinit); + ok(coinit == exp_coinit, "coinit = %lx\n", coinit); return S_OK; }
On Wed Aug 6 17:33:31 2025 +0000, Piotr Caban wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/8725/diffs?diff_id=198685&start_sha=9a87b2249ec417889bb05f13783ce7e119809a6d#48b3cd062caffaafb4341438e88acfd833efc49c_164_153)
I've pushed a version that moves RoInitialize tests to combase. Thank you.