From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/coremessaging/tests/coremessaging.c | 158 +++++++++++++++++++++++ 1 file changed, 158 insertions(+)
diff --git a/dlls/coremessaging/tests/coremessaging.c b/dlls/coremessaging/tests/coremessaging.c index a3842be5c3e..5e7c0ed2606 100644 --- a/dlls/coremessaging/tests/coremessaging.c +++ b/dlls/coremessaging/tests/coremessaging.c @@ -208,6 +208,163 @@ 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; + struct dispatcher_queue_handler *queue_handler = NULL; + IDispatcherQueueHandler *handler_iface = NULL; + struct DispatcherQueueOptions options = { 0 }; + IDispatcherQueue2 *dispatcher_queue2 = NULL; + IDispatcherQueue *dispatcher_queue = NULL; + IAsyncAction *operation = NULL; + IAsyncInfo *async_info = NULL; + EventRegistrationToken token; + AsyncStatus status; + boolean result; + HRESULT hr; + DWORD ret; + LONG ref; + MSG msg; + + 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) /* w1064v1809 */, "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), "got IDispatcherQueue2_get_HasThreadAccess 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, "got IDispatcherQueue_TryEnqueue 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 ); + queue_handler = impl_from_IDispatcherQueueHandler( handler_iface ); + + hr = IDispatcherQueue_add_ShutdownCompleted( dispatcher_queue, event_handler_iface, &token ); + ok_(__FILE__, line)( hr == S_OK, "got IDispatcherQueue_add_ShutdownCompleted 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, "got IAsyncAction_QueryInterface hr %#lx.\n", hr ); + + hr = IAsyncInfo_get_Status( async_info, &status ); + ok_(__FILE__, line)( hr == S_OK, "got IAsyncInfo_get_Status hr %#lx.\n", hr ); + ok_(__FILE__, line)( status == Started, "got IAsyncInfo_get_Status status %d.\n", status ); + + SetEvent( queue_handler->event ); + while (PeekMessageW( &msg, NULL, 0, 0, PM_REMOVE )) + { + TranslateMessage( &msg ); + DispatchMessageW( &msg ); + } + Sleep( 100 ); + 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, "got IAsyncInfo_get_Status hr %#lx.\n", hr ); + ok_(__FILE__, line)( status == Completed, "got IAsyncInfo_get_Status status %d.\n", status ); + + hr = IAsyncInfo_Close( async_info ); + ok_(__FILE__, line)( hr == S_OK, "got IAsyncInfo_Close hr %#lx.\n", hr ); + ref = IAsyncInfo_Release( async_info ); + ok_(__FILE__, line)( ref == 2, "got IAsyncInfo_Release 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, "got IDispatcherQueue_remove_ShutdownCompleted 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, "got IDispatcherQueue_Release ref %ld.\n", ref ); +done: + ref = IDispatcherQueueController_Release( dispatcher_queue_controller ); + ok_(__FILE__, line)( ref == 0, "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 /* win10 22h2 */, "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, "got dispatcher_queue_controller %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"; @@ -358,6 +515,7 @@ START_TEST(coremessaging) hr = RoInitialize( RO_INIT_MULTITHREADED ); ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr );
+ test_CreateDispatcherQueueController(); test_DispatcherQueueController_Statics();
RoUninitialize();