Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/compobj.c | 1 + dlls/ole32/tests/compobj.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index aeed3b85fa..bd28f42b33 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -5264,6 +5264,7 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier) apartment_release(apt); *type = APTTYPE_MTA; *qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA; + return S_OK; }
return info->apt ? S_OK : CO_E_NOTINITIALIZED; diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 7eb25af9e6..624120890d 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -648,7 +648,8 @@ static void _test_apt_type(APTTYPE expected_type, APTTYPEQUALIFIER expected_qual return;
hr = pCoGetApartmentType(&type, &qualifier); - ok_(__FILE__, line)(hr == S_OK || hr == CO_E_NOTINITIALIZED, "Unexpected return code: 0x%08x\n", hr); + ok_(__FILE__, line)(hr == S_OK || (type == APTTYPE_CURRENT && hr == CO_E_NOTINITIALIZED), + "Unexpected hr %#x.\n", hr); ok_(__FILE__, line)(type == expected_type, "Wrong apartment type %d, expected %d\n", type, expected_type); ok_(__FILE__, line)(qualifier == expected_qualifier, "Wrong apartment qualifier %d, expected %d\n", qualifier, expected_qualifier);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- configure | 1 + configure.ac | 1 + dlls/rtworkq/Makefile.in | 1 + dlls/rtworkq/queue.c | 9 +++ dlls/rtworkq/tests/Makefile.in | 5 ++ dlls/rtworkq/tests/rtworkq.c | 107 +++++++++++++++++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 dlls/rtworkq/tests/Makefile.in create mode 100644 dlls/rtworkq/tests/rtworkq.c
diff --git a/configure b/configure index cb85fb8b8f..1d20d141c1 100755 --- a/configure +++ b/configure @@ -20864,6 +20864,7 @@ wine_fn_config_makefile dlls/rsaenh/tests enable_tests wine_fn_config_makefile dlls/rstrtmgr enable_rstrtmgr wine_fn_config_makefile dlls/rtutils enable_rtutils wine_fn_config_makefile dlls/rtworkq enable_rtworkq +wine_fn_config_makefile dlls/rtworkq/tests enable_tests wine_fn_config_makefile dlls/samlib enable_samlib wine_fn_config_makefile dlls/sane.ds enable_sane_ds wine_fn_config_makefile dlls/sapi enable_sapi diff --git a/configure.ac b/configure.ac index b3389b796b..2e102990b5 100644 --- a/configure.ac +++ b/configure.ac @@ -3609,6 +3609,7 @@ WINE_CONFIG_MAKEFILE(dlls/rsaenh/tests) WINE_CONFIG_MAKEFILE(dlls/rstrtmgr) WINE_CONFIG_MAKEFILE(dlls/rtutils) WINE_CONFIG_MAKEFILE(dlls/rtworkq) +WINE_CONFIG_MAKEFILE(dlls/rtworkq/tests) WINE_CONFIG_MAKEFILE(dlls/samlib) WINE_CONFIG_MAKEFILE(dlls/sane.ds) WINE_CONFIG_MAKEFILE(dlls/sapi) diff --git a/dlls/rtworkq/Makefile.in b/dlls/rtworkq/Makefile.in index a224198986..345fad1c1e 100644 --- a/dlls/rtworkq/Makefile.in +++ b/dlls/rtworkq/Makefile.in @@ -1,5 +1,6 @@ MODULE = rtworkq.dll IMPORTLIB = rtworkq +IMPORTS = ole32
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c index 65007602c7..70af6a7658 100644 --- a/dlls/rtworkq/queue.c +++ b/dlls/rtworkq/queue.c @@ -69,6 +69,7 @@ static CRITICAL_SECTION_DEBUG queues_critsect_debug = static CRITICAL_SECTION queues_section = { &queues_critsect_debug, -1, 0, 0, 0, 0 };
static LONG platform_lock; +static CO_MTA_USAGE_COOKIE mta_cookie;
static struct queue_handle *get_queue_obj(DWORD handle) { @@ -1117,6 +1118,7 @@ HRESULT WINAPI RtwqUnlockPlatform(void) static void init_system_queues(void) { struct queue_desc desc; + HRESULT hr;
/* Always initialize standard queue, keep the rest lazy. */
@@ -1128,6 +1130,9 @@ static void init_system_queues(void) return; }
+ if (FAILED(hr = CoIncrementMTAUsage(&mta_cookie))) + WARN("Failed to initialize MTA, hr %#x.\n", hr); + desc.queue_type = RTWQ_STANDARD_WORKQUEUE; desc.ops = &pool_queue_ops; desc.target_queue = 0; @@ -1149,6 +1154,7 @@ HRESULT WINAPI RtwqStartup(void) static void shutdown_system_queues(void) { unsigned int i; + HRESULT hr;
EnterCriticalSection(&queues_section);
@@ -1157,6 +1163,9 @@ static void shutdown_system_queues(void) shutdown_queue(&system_queues[i]); }
+ if (FAILED(hr = CoDecrementMTAUsage(mta_cookie))) + WARN("Failed to uninitialize MTA, hr %#x.\n", hr); + LeaveCriticalSection(&queues_section); }
diff --git a/dlls/rtworkq/tests/Makefile.in b/dlls/rtworkq/tests/Makefile.in new file mode 100644 index 0000000000..8354cd810d --- /dev/null +++ b/dlls/rtworkq/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = rtworkq.dll +IMPORTS = rtworkq ole32 + +C_SRCS = \ + rtworkq.c diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c new file mode 100644 index 0000000000..627e024d76 --- /dev/null +++ b/dlls/rtworkq/tests/rtworkq.c @@ -0,0 +1,107 @@ +/* + * Copyright 2020 Nikolay Sivov for CodeWeavers + * + * 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 <stdarg.h> +#include <string.h> + +#include "windef.h" +#include "winbase.h" +#include "rtworkq.h" + +#include "wine/test.h" + +static void test_platform_init(void) +{ + APTTYPEQUALIFIER qualifier; + APTTYPE apttype; + HRESULT hr; + + /* Startup initializes MTA. */ + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#x.\n", hr); + + hr = RtwqStartup(); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + ok(apttype == APTTYPE_MTA && qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + hr = RtwqShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#x.\n", hr); + + /* Try with STA initialized before startup. */ + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(apttype == APTTYPE_MAINSTA && qualifier == APTTYPEQUALIFIER_NONE, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + hr = RtwqStartup(); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(apttype == APTTYPE_MAINSTA && qualifier == APTTYPEQUALIFIER_NONE, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + hr = RtwqShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + CoUninitialize(); + + /* Startup -> init main STA -> uninitialize -> shutdown */ + hr = RtwqStartup(); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + ok(apttype == APTTYPE_MTA && qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(apttype == APTTYPE_MAINSTA && qualifier == APTTYPEQUALIFIER_NONE, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + CoUninitialize(); + + hr = CoGetApartmentType(&apttype, &qualifier); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(apttype == APTTYPE_MTA && qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, + "Unexpected apartment type %d, qualifier %d.\n", apttype, qualifier); + + hr = RtwqShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); +} + +START_TEST(rtworkq) +{ + test_platform_init(); +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65203
Your paranoid android.
=== debian10 (32 bit WoW report) ===
rtworkq: rtworkq: Timeout
Report validation errors: The report seems to have been truncated
Based on patch by Derek Lesho.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/tests/mfplat.c | 158 ++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 66524f1b48..ec84c6c261 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -63,6 +63,8 @@ static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TY const D3D_FEATURE_LEVEL *feature_levels, UINT levels, UINT sdk_version, ID3D11Device **device_out, D3D_FEATURE_LEVEL *obtained_feature_level, ID3D11DeviceContext **immediate_context);
+static HRESULT (WINAPI *pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier); + static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines); static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); @@ -86,6 +88,7 @@ static HRESULT (WINAPI *pMFTRegisterLocalByCLSID)(REFCLSID clsid, REFGUID catego const MFT_REGISTER_TYPE_INFO *output_types); static HRESULT (WINAPI *pMFTUnregisterLocal)(IClassFactory *factory); static HRESULT (WINAPI *pMFTUnregisterLocalByCLSID)(CLSID clsid); +static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0}; static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0}; @@ -122,6 +125,7 @@ struct test_callback { IMFAsyncCallback IMFAsyncCallback_iface; HANDLE event; + DWORD param; };
static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface) @@ -651,6 +655,7 @@ static void init_functions(void) #define X(f) p##f = (void*)GetProcAddress(mod, #f) X(MFAddPeriodicCallback); X(MFAllocateSerialWorkQueue); + X(MFAllocateWorkQueueEx); X(MFCopyImage); X(MFCreateDXGIDeviceManager); X(MFCreateSourceResolver); @@ -666,13 +671,17 @@ static void init_functions(void) X(MFTRegisterLocalByCLSID); X(MFTUnregisterLocal); X(MFTUnregisterLocalByCLSID); -#undef X
if ((mod = LoadLibraryA("d3d11.dll"))) { - pD3D11CreateDevice = (void *)GetProcAddress(mod, "D3D11CreateDevice"); + X(D3D11CreateDevice); }
+ mod = GetModuleHandleA("ole32.dll"); + + X(CoGetApartmentType); +#undef X + is_win8_plus = pMFPutWaitingWorkItem != NULL; }
@@ -4079,12 +4088,154 @@ static void test_MFTRegisterLocal(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); }
+static void test_queue_com(void) +{ + static int system_queues[] = + { + MFASYNC_CALLBACK_QUEUE_STANDARD, + MFASYNC_CALLBACK_QUEUE_RT, + MFASYNC_CALLBACK_QUEUE_IO, + MFASYNC_CALLBACK_QUEUE_TIMER, + MFASYNC_CALLBACK_QUEUE_MULTITHREADED, + MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION, + }; + + static int user_queues[] = + { + MF_STANDARD_WORKQUEUE, + MF_WINDOW_WORKQUEUE, + MF_MULTITHREADED_WORKQUEUE, + }; + + char path_name[MAX_PATH]; + PROCESS_INFORMATION info; + STARTUPINFOA startup; + char **argv; + int i; + + if (!pCoGetApartmentType) + { + win_skip("CoGetApartmentType() is not available.\n"); + return; + } + + winetest_get_mainargs(&argv); + + for (i = 0; i < ARRAY_SIZE(system_queues); ++i) + { + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + sprintf(path_name, "%s mfplat s%d", argv[0], system_queues[i]); + ok(CreateProcessA( NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), + "CreateProcess failed.\n" ); + winetest_wait_child_process(info.hProcess); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + } + + for (i = 0; i < ARRAY_SIZE(user_queues); ++i) + { + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + sprintf(path_name, "%s mfplat u%d", argv[0], user_queues[i]); + ok(CreateProcessA( NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), + "CreateProcess failed.\n" ); + winetest_wait_child_process(info.hProcess); + CloseHandle(info.hProcess); + CloseHandle(info.hThread); + } +} + +static HRESULT WINAPI test_queue_com_state_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct test_callback *callback = impl_from_IMFAsyncCallback(iface); + APTTYPEQUALIFIER qualifier; + APTTYPE com_type; + HRESULT hr; + + hr = pCoGetApartmentType(&com_type, &qualifier); + ok(SUCCEEDED(hr), "Failed to get apartment type, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + todo_wine { + if (callback->param == MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION) + ok(com_type == APTTYPE_MAINSTA && qualifier == APTTYPEQUALIFIER_NONE, + "%#x: unexpected type %u, qualifier %u.\n", callback->param, com_type, qualifier); + else + ok(com_type == APTTYPE_MTA && qualifier == APTTYPEQUALIFIER_NONE, + "%#x: unexpected type %u, qualifier %u.\n", callback->param, com_type, qualifier); + } + } + + SetEvent(callback->event); + return S_OK; +} + +static const IMFAsyncCallbackVtbl test_queue_com_state_callback_vtbl = +{ + testcallback_QueryInterface, + testcallback_AddRef, + testcallback_Release, + testcallback_GetParameters, + test_queue_com_state_callback_Invoke, +}; + +static void test_queue_com_state(const char *name) +{ + struct test_callback callback = { { &test_queue_com_state_callback_vtbl } }; + DWORD queue, queue_type; + HRESULT hr; + + callback.event = CreateEventA(NULL, FALSE, FALSE, NULL); + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); + + if (name[0] == 's') + { + callback.param = name[1] - '0'; + hr = MFPutWorkItem(callback.param, &callback.IMFAsyncCallback_iface, NULL); + ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr); + WaitForSingleObject(callback.event, INFINITE); + } + else if (name[0] == 'u') + { + queue_type = name[1] - '0'; + + hr = pMFAllocateWorkQueueEx(queue_type, &queue); + ok(hr == S_OK, "Failed to allocate a queue, hr %#x.\n", hr); + + callback.param = queue; + hr = MFPutWorkItem(queue, &callback.IMFAsyncCallback_iface, NULL); + ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr); + WaitForSingleObject(callback.event, INFINITE); + + hr = MFUnlockWorkQueue(queue); + ok(hr == S_OK, "Failed to unlock the queue, hr %#x.\n", hr); + } + + CloseHandle(callback.event); + + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); +} + START_TEST(mfplat) { - CoInitialize(NULL); + char **argv; + int argc;
init_functions();
+ argc = winetest_get_mainargs(&argv); + if (argc >= 3) + { + test_queue_com_state(argv[2]); + return; + } + + CoInitialize(NULL); + test_startup(); test_register(); test_media_type(); @@ -4119,6 +4270,7 @@ START_TEST(mfplat) test_dxgi_device_manager(); test_MFCreateTransformActivate(); test_MFTRegisterLocal(); + test_queue_com();
CoUninitialize(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65204
Your paranoid android.
=== w1064v1809 (64 bit report) ===
mfplat: mfplat.c:2571: Test failed: Unexpected return value 0x102. mfplat.c:1922: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1925: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:1928: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:1931: Test failed: Unexpected result, hr 0xc00d3e85. 1924:mfplat: unhandled exception c0000005 at 0000000000401993
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=65202
Your paranoid android.
=== w8 (32 bit report) ===
ole32: compobj.c:2932: Test failed: PeekMessageA failed: 1400