-- v5: rtworkq: Support putting work on any id in RTWQ_CALLBACK_QUEUE_PRIVATE_MASK. rtworkq: Support putting work on RTWQ_CALLBACK_QUEUE_UNDEFINED. rtworkq/tests: Test putting work on an undefined queue id. mfplat/tests: Test putting work on an undefined queue id.
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 2b17b069d1d..0757592d15b 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -13232,6 +13232,52 @@ static void test_2dbuffer_copy(void) ID3D11Device_Release(device); }
+static void test_undefined_queue_id(void) +{ + struct test_callback *callback; + IMFAsyncResult *result; + HRESULT hr; + DWORD res; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); + + callback = create_test_callback(&test_async_callback_result_vtbl); + + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_UNDEFINED, &callback->IMFAsyncCallback_iface, NULL); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); + todo_wine + ok(res == 0, "got %#lx\n", res); + if (result) + IMFAsyncResult_Release(result); + + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK, &callback->IMFAsyncCallback_iface, NULL); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); + todo_wine + ok(res == 0, "got %#lx\n", res); + if (result) + IMFAsyncResult_Release(result); + + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK & (MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK - 1), + &callback->IMFAsyncCallback_iface, NULL); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); + todo_wine + ok(res == 0, "got %#lx\n", res); + if (result) + IMFAsyncResult_Release(result); + + IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface); + + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); +} + START_TEST(mfplat) { char **argv; @@ -13326,6 +13372,7 @@ START_TEST(mfplat) test_MFInitMediaTypeFromAMMediaType(); test_MFCreatePathFromURL(); test_2dbuffer_copy(); + test_undefined_queue_id();
CoUninitialize(); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/rtworkq/tests/rtworkq.c | 162 +++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+)
diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c index 2ff74d57b84..7d307334621 100644 --- a/dlls/rtworkq/tests/rtworkq.c +++ b/dlls/rtworkq/tests/rtworkq.c @@ -19,12 +19,123 @@ #include <stdarg.h> #include <string.h>
+#define COBJMACROS + #include "windef.h" #include "winbase.h" +#include "initguid.h" #include "rtworkq.h"
#include "wine/test.h"
+/* Should be kept in sync with corresponding MFASYNC_CALLBACK_ constants. */ +enum rtwq_callback_queue_id +{ + RTWQ_CALLBACK_QUEUE_UNDEFINED = 0x00000000, + RTWQ_CALLBACK_QUEUE_STANDARD = 0x00000001, + RTWQ_CALLBACK_QUEUE_RT = 0x00000002, + RTWQ_CALLBACK_QUEUE_IO = 0x00000003, + RTWQ_CALLBACK_QUEUE_TIMER = 0x00000004, + RTWQ_CALLBACK_QUEUE_MULTITHREADED = 0x00000005, + RTWQ_CALLBACK_QUEUE_LONG_FUNCTION = 0x00000007, + RTWQ_CALLBACK_QUEUE_PRIVATE_MASK = 0xffff0000, + RTWQ_CALLBACK_QUEUE_ALL = 0xffffffff, +}; + +struct test_callback +{ + IRtwqAsyncCallback IRtwqAsyncCallback_iface; + LONG refcount; + HANDLE event; + IRtwqAsyncResult *result; +}; + +static struct test_callback *impl_from_IRtwqAsyncCallback(IRtwqAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct test_callback, IRtwqAsyncCallback_iface); +} + +static HRESULT WINAPI testcallback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IRtwqAsyncCallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI testcallback_AddRef(IRtwqAsyncCallback *iface) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + return InterlockedIncrement(&callback->refcount); +} + +static ULONG WINAPI testcallback_Release(IRtwqAsyncCallback *iface) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + ULONG refcount = InterlockedDecrement(&callback->refcount); + + if (!refcount) + { + CloseHandle(callback->event); + free(callback); + } + + return refcount; +} + +static HRESULT WINAPI testcallback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + ok(flags != NULL && queue != NULL, "Unexpected arguments.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testcallback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + + callback->result = result; + SetEvent(callback->event); + + return S_OK; +} + +static const IRtwqAsyncCallbackVtbl testcallbackvtbl = +{ + testcallback_QueryInterface, + testcallback_AddRef, + testcallback_Release, + testcallback_GetParameters, + testcallback_Invoke, +}; + +static struct test_callback * create_test_callback(void) +{ + struct test_callback *callback = calloc(1, sizeof(*callback)); + + callback->IRtwqAsyncCallback_iface.lpVtbl = &testcallbackvtbl; + callback->refcount = 1; + callback->event = CreateEventA(NULL, FALSE, FALSE, NULL); + + return callback; +} + +static DWORD wait_async_callback_result(IRtwqAsyncCallback *iface, DWORD timeout, IRtwqAsyncResult **result) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + DWORD res = WaitForSingleObject(callback->event, timeout); + + *result = callback->result; + callback->result = NULL; + + return res; +} + static void test_platform_init(void) { APTTYPEQUALIFIER qualifier; @@ -101,7 +212,58 @@ static void test_platform_init(void) ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); }
+static void test_undefined_queue_id(void) +{ + IRtwqAsyncResult *result, *callback_result; + struct test_callback *test_callback; + HRESULT hr; + DWORD res; + + hr = RtwqStartup(); + ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); + + test_callback = create_test_callback(); + + hr = RtwqCreateAsyncResult(NULL, &test_callback->IRtwqAsyncCallback_iface, NULL, &result); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_UNDEFINED, 0, result); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); + todo_wine + ok(res == 0, "got %#lx\n", res); + todo_wine + ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result); + + hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK, 0, result); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); + todo_wine + ok(res == 0, "got %#lx\n", res); + todo_wine + ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result); + + hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK & (RTWQ_CALLBACK_QUEUE_PRIVATE_MASK - 1), 0, result); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); + todo_wine + ok(res == 0, "got %#lx\n", res); + todo_wine + ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result); + + IRtwqAsyncResult_Release(result); + + IRtwqAsyncCallback_Release(&test_callback->IRtwqAsyncCallback_iface); + + hr = RtwqShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); +} + START_TEST(rtworkq) { test_platform_init(); + test_undefined_queue_id(); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 5 +---- dlls/rtworkq/queue.c | 4 ++++ dlls/rtworkq/tests/rtworkq.c | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 0757592d15b..b0301d8e4b7 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -13245,13 +13245,10 @@ static void test_undefined_queue_id(void) callback = create_test_callback(&test_async_callback_result_vtbl);
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_UNDEFINED, &callback->IMFAsyncCallback_iface, NULL); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); - todo_wine ok(res == 0, "got %#lx\n", res); - if (result) - IMFAsyncResult_Release(result); + IMFAsyncResult_Release(result);
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK, &callback->IMFAsyncCallback_iface, NULL); todo_wine diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c index 9046a70b359..8b9bb631202 100644 --- a/dlls/rtworkq/queue.c +++ b/dlls/rtworkq/queue.c @@ -298,6 +298,10 @@ static struct queue *get_system_queue(DWORD queue_id) { switch (queue_id) { + case RTWQ_CALLBACK_QUEUE_UNDEFINED: + /* Works in native Windows. Undocumented, but seems to use standard. */ + queue_id = RTWQ_CALLBACK_QUEUE_STANDARD; + /* fall through */ case RTWQ_CALLBACK_QUEUE_STANDARD: case RTWQ_CALLBACK_QUEUE_RT: case RTWQ_CALLBACK_QUEUE_IO: diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c index 7d307334621..57e00b8afcd 100644 --- a/dlls/rtworkq/tests/rtworkq.c +++ b/dlls/rtworkq/tests/rtworkq.c @@ -228,12 +228,9 @@ static void test_undefined_queue_id(void) ok(hr == S_OK, "got %#lx\n", hr);
hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_UNDEFINED, 0, result); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); - todo_wine ok(res == 0, "got %#lx\n", res); - todo_wine ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result);
hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK, 0, result);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 10 ++-------- dlls/rtworkq/queue.c | 6 ++++-- dlls/rtworkq/tests/rtworkq.c | 6 ------ 3 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index b0301d8e4b7..07fdde41cbe 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -13251,23 +13251,17 @@ static void test_undefined_queue_id(void) IMFAsyncResult_Release(result);
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK, &callback->IMFAsyncCallback_iface, NULL); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); - todo_wine ok(res == 0, "got %#lx\n", res); - if (result) - IMFAsyncResult_Release(result); + IMFAsyncResult_Release(result);
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK & (MFASYNC_CALLBACK_QUEUE_PRIVATE_MASK - 1), &callback->IMFAsyncCallback_iface, NULL); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&callback->IMFAsyncCallback_iface, 100, &result); - todo_wine ok(res == 0, "got %#lx\n", res); - if (result) - IMFAsyncResult_Release(result); + IMFAsyncResult_Release(result);
IMFAsyncCallback_Release(&callback->IMFAsyncCallback_iface);
diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c index 8b9bb631202..29ea3c884f2 100644 --- a/dlls/rtworkq/queue.c +++ b/dlls/rtworkq/queue.c @@ -298,6 +298,10 @@ static struct queue *get_system_queue(DWORD queue_id) { switch (queue_id) { + default: + if (!(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK & queue_id)) + return NULL; + /* fall through */ case RTWQ_CALLBACK_QUEUE_UNDEFINED: /* Works in native Windows. Undocumented, but seems to use standard. */ queue_id = RTWQ_CALLBACK_QUEUE_STANDARD; @@ -309,8 +313,6 @@ static struct queue *get_system_queue(DWORD queue_id) case RTWQ_CALLBACK_QUEUE_MULTITHREADED: case RTWQ_CALLBACK_QUEUE_LONG_FUNCTION: return &system_queues[queue_id - 1]; - default: - return NULL; } }
diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c index 57e00b8afcd..d075989ad2b 100644 --- a/dlls/rtworkq/tests/rtworkq.c +++ b/dlls/rtworkq/tests/rtworkq.c @@ -234,21 +234,15 @@ static void test_undefined_queue_id(void) ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result);
hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK, 0, result); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); - todo_wine ok(res == 0, "got %#lx\n", res); - todo_wine ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result);
hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_PRIVATE_MASK & (RTWQ_CALLBACK_QUEUE_PRIVATE_MASK - 1), 0, result); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); - todo_wine ok(res == 0, "got %#lx\n", res); - todo_wine ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result);
IRtwqAsyncResult_Release(result);
This merge request was approved by Nikolay Sivov.