From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/coremessaging/Makefile.in | 5 +- dlls/coremessaging/tests/Makefile.in | 2 +- dlls/coremessaging/tests/coremessaging.c | 161 +++++++++++++++++++++++ 3 files changed, 165 insertions(+), 3 deletions(-)
diff --git a/dlls/coremessaging/Makefile.in b/dlls/coremessaging/Makefile.in index 049d9d7e0a3..25de74385c5 100644 --- a/dlls/coremessaging/Makefile.in +++ b/dlls/coremessaging/Makefile.in @@ -1,5 +1,6 @@ -MODULE = coremessaging.dll -IMPORTS = combase +MODULE = coremessaging.dll +IMPORTS = combase +IMPORTLIB = coremessaging
SOURCES = \ classes.idl \ diff --git a/dlls/coremessaging/tests/Makefile.in b/dlls/coremessaging/tests/Makefile.in index b048cbe204e..c8947c28c50 100644 --- a/dlls/coremessaging/tests/Makefile.in +++ b/dlls/coremessaging/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = coremessaging.dll -IMPORTS = combase +IMPORTS = combase coremessaging user32
SOURCES = \ coremessaging.c diff --git a/dlls/coremessaging/tests/coremessaging.c b/dlls/coremessaging/tests/coremessaging.c index 9055ec71c9f..04be062e16a 100644 --- a/dlls/coremessaging/tests/coremessaging.c +++ b/dlls/coremessaging/tests/coremessaging.c @@ -208,6 +208,158 @@ static HRESULT create_dispatcher_queue_handler( IDispatcherQueueHandler **handle return S_OK; }
+#define check_create_dispatcher_queue_controller( size, thread_type, apartment_type, expected_hr ) \ + check_create_dispatcher_queue_controller_( __LINE__, size, thread_type, apartment_type, expected_hr ) +static void check_create_dispatcher_queue_controller_( unsigned int line, DWORD size, DISPATCHERQUEUE_THREAD_TYPE thread_type, \ + DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartment_type, HRESULT expected_hr ) +{ + ITypedEventHandler_DispatcherQueue_IInspectable *event_handler_iface = NULL; + struct typed_event_handler_dispatcher_queue *event_handler = NULL; + IDispatcherQueueController *dispatcher_queue_controller = NULL; + IDispatcherQueueHandler *handler_iface = NULL; + IDispatcherQueue2 *dispatcher_queue2 = NULL; + IDispatcherQueue *dispatcher_queue = NULL; + struct DispatcherQueueOptions options; + IAsyncAction *operation = NULL; + IAsyncInfo *async_info = NULL; + EventRegistrationToken token; + AsyncStatus status; + boolean result; + HRESULT hr; + DWORD ret; + LONG ref; + MSG msg; + + memset( &options, 0, sizeof( options ) ); + options.dwSize = size; + options.threadType = thread_type; + options.apartmentType = apartment_type; + + hr = CreateDispatcherQueueController( options, &dispatcher_queue_controller ); + todo_wine + ok_(__FILE__, line)( hr == expected_hr, "got CreateDispatcherQueueController hr %#lx.\n", hr ); + if (FAILED(hr)) return; + + hr = IDispatcherQueueController_get_DispatcherQueue( dispatcher_queue_controller, &dispatcher_queue ); + todo_wine + ok_(__FILE__, line)( hr == S_OK, "got IDispatcherQueueController_get_DispatcherQueue hr %#lx.\n", hr ); + if (FAILED(hr)) goto done; + + hr = IDispatcherQueue_QueryInterface( dispatcher_queue, &IID_IDispatcherQueue2, (void **)&dispatcher_queue2 ); + ok_(__FILE__, line)( hr == S_OK || broken(hr == E_NOINTERFACE) /* w1064v1709 */, "got IDispatcherQueue_QueryInterface hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + hr = IDispatcherQueue2_get_HasThreadAccess( dispatcher_queue2, &result ); + ok_(__FILE__, line)( hr == S_OK, "got IDispatcherQueue2_get_HasThreadAccess hr %#lx.\n", hr ); + ok_(__FILE__, line)( result == (thread_type == DQTYPE_THREAD_CURRENT ? TRUE : FALSE), "IDispatcherQueue2_get_HasThreadAccess returned result %d.\n", result ); + ref = IDispatcherQueue2_Release( dispatcher_queue2 ); + ok_(__FILE__, line)( ref == (thread_type == DQTYPE_THREAD_CURRENT ? 2 : 3), "got IDispatcherQueue2_Release ref %ld.\n", ref ); + } + + hr = create_dispatcher_queue_handler( &handler_iface ); + ok_(__FILE__, line)( hr == S_OK, "create_dispatcher_queue_handler failed, hr %#lx.\n", hr ); + + hr = IDispatcherQueue_TryEnqueue( dispatcher_queue, handler_iface, &result ); + ok_(__FILE__, line)( hr == S_OK, "got IDispatcherQueue_TryEnqueue hr %#lx.\n", hr ); + ok_(__FILE__, line)( result == TRUE, "IDispatcherQueue_TryEnqueue returned result %d.\n", result ); + + hr = create_typed_event_handler_dispatcher_queue( &event_handler_iface ); + ok_(__FILE__, line)( hr == S_OK, "create_typed_event_handler_dispatcher_queue failed, hr %#lx.\n", hr ); + event_handler = impl_from_ITypedEventHandler_DispatcherQueue_IInspectable( event_handler_iface ); + + hr = IDispatcherQueue_add_ShutdownCompleted( dispatcher_queue, event_handler_iface, &token ); + ok_(__FILE__, line)( hr == S_OK, "IDispatcherQueue_add_ShutdownCompleted returned hr %#lx.\n", hr ); + hr = IDispatcherQueueController_ShutdownQueueAsync( dispatcher_queue_controller, &operation ); + ok_(__FILE__, line)( hr == S_OK, "got IDispatcherQueueController_ShutdownQueueAsync hr %#lx.\n", hr ); + + hr = IAsyncAction_QueryInterface( operation, &IID_IAsyncInfo, (void **)&async_info ); + ok_(__FILE__, line)( hr == S_OK, "IAsyncAction_QueryInterface returned hr %#lx.\n", hr ); + + hr = IAsyncInfo_get_Status( async_info, &status ); + ok_(__FILE__, line)( hr == S_OK, "IAsyncInfo_get_Status returned hr %#lx.\n", hr ); + ok_(__FILE__, line)( status == Started, "IAsyncInfo_get_Status returned status %d.\n", status ); + while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE )) + { + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } + ret = WaitForSingleObject( event_handler->event, INFINITE ); + ok_(__FILE__, line)( !ret, "Unexpected wait result %lu.\n", ret ); + hr = IAsyncInfo_get_Status( async_info, &status ); + ok_(__FILE__, line)( hr == S_OK, "IAsyncInfo_get_Status returned hr %#lx.\n", hr ); + ok_(__FILE__, line)( status == Completed, "IAsyncInfo_get_Status returned status %d.\n", status ); + + hr = IAsyncInfo_Close( async_info ); + ok_(__FILE__, line)( hr == S_OK, "IAsyncInfo_Close returned hr %#lx.\n", hr ); + ref = IAsyncInfo_Release( async_info ); + ok_(__FILE__, line)( ref == 2, "got ref %ld.\n", ref ); + ref = IAsyncAction_Release( operation ); + ok_(__FILE__, line)( ref == 1, "got IAsyncAction_Release ref %ld.\n", ref ); + hr = IDispatcherQueue_remove_ShutdownCompleted( dispatcher_queue, token ); + ok_(__FILE__, line)( hr == S_OK, "IDispatcherQueue_remove_ShutdownCompleted returned hr %#lx.\n", hr ); + + ref = ITypedEventHandler_DispatcherQueue_IInspectable_Release( event_handler_iface ); + ok_(__FILE__, line)( ref == 0, "got ITypedEventHandler_DispatcherQueue_IInspectable_Release ref %ld.\n", ref ); + ref = IDispatcherQueueHandler_Release( handler_iface ); + ok_(__FILE__, line)( ref == 0, "got IDispatcherQueueHandler_Release ref %ld.\n", ref ); + ref = IDispatcherQueue_Release( dispatcher_queue ); + ok_(__FILE__, line)( ref == 1 || broken(ref == 2) /* Race condition */, "got IDispatcherQueue_Release ref %ld.\n", ref ); +done: + ref = IDispatcherQueueController_Release( dispatcher_queue_controller ); + ok_(__FILE__, line)( ref == 0 || broken(ref == 1) /* Race condition */, "got IDispatcherQueueController_Release ref %ld.\n", ref ); +} + +static void test_CreateDispatcherQueueController(void) +{ + IDispatcherQueueController *dispatcher_queue_controller = (void *)0xdeadbeef; + struct DispatcherQueueOptions options = {0}; + HRESULT hr; + + hr = CreateDispatcherQueueController( options, NULL ); + todo_wine + ok( hr == E_POINTER || hr == 0x80000005 /* E_POINTER #if !defined(_WIN32) */, "got hr %#lx.\n", hr ); + hr = CreateDispatcherQueueController( options, &dispatcher_queue_controller ); + todo_wine + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( dispatcher_queue_controller == (void *)0xdeadbeef, "CreateDispatcherQueueController returned IDispatcherQueueController %p.\n", dispatcher_queue_controller ); + + /* Invalid args */ + + check_create_dispatcher_queue_controller( 0, 0, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, 0, DQTAT_COM_ASTA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, 0, DQTAT_COM_STA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_CURRENT, DQTAT_COM_ASTA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_CURRENT, DQTAT_COM_STA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_DEDICATED, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_DEDICATED, DQTAT_COM_ASTA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( 0, DQTYPE_THREAD_DEDICATED, DQTAT_COM_STA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0, DQTAT_COM_ASTA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0, DQTAT_COM_STA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0xdeadbeef, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0xdeadbeef, DQTAT_COM_ASTA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), 0xdeadbeef, DQTAT_COM_STA, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ) - 1, DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE, E_INVALIDARG ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ) + 1, DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE, E_INVALIDARG ); + + if (0) /* Silently crashes in Windows */ + { + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_DEDICATED, 0xdeadbeef, S_OK ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_DEDICATED, DQTAT_COM_NONE, S_OK ); + } + + /* Valid args */ + + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_CURRENT, 0xdeadbeef, S_OK ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE, S_OK ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_CURRENT, DQTAT_COM_ASTA, S_OK ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_CURRENT, DQTAT_COM_STA, S_OK ); + + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_DEDICATED, DQTAT_COM_ASTA, S_OK ); + check_create_dispatcher_queue_controller( sizeof( DispatcherQueueOptions ), DQTYPE_THREAD_DEDICATED, DQTAT_COM_STA, S_OK ); +} + static void test_DispatcherQueueController_Statics(void) { static const WCHAR *dispatcher_queue_controller_statics_name = L"Windows.System.DispatcherQueueController"; @@ -352,6 +504,15 @@ START_TEST(coremessaging) ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr );
test_DispatcherQueueController_Statics(); + test_CreateDispatcherQueueController(); + + RoUninitialize(); + + hr = RoInitialize( RO_INIT_SINGLETHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_DispatcherQueueController_Statics(); + test_CreateDispatcherQueueController();
RoUninitialize(); }