From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/coremessaging/Makefile.in | 5 +- dlls/coremessaging/tests/Makefile.in | 2 +- dlls/coremessaging/tests/coremessaging.c | 274 +++++++++++++++++++++++ 3 files changed, 278 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 83d00b6261f..a3842be5c3e 100644 --- a/dlls/coremessaging/tests/coremessaging.c +++ b/dlls/coremessaging/tests/coremessaging.c @@ -30,6 +30,8 @@ #define WIDL_using_Windows_System #include "windows.system.h"
+#include "dispatcherqueue.h" + #include "wine/test.h"
#define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid ) @@ -44,14 +46,190 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) IUnknown_Release( unk ); }
+struct typed_event_handler_dispatcher_queue +{ + ITypedEventHandler_DispatcherQueue_IInspectable ITypedEventHandler_DispatcherQueue_IInspectable_iface; + LONG ref; + + HANDLE event; +}; + +static struct typed_event_handler_dispatcher_queue *impl_from_ITypedEventHandler_DispatcherQueue_IInspectable( ITypedEventHandler_DispatcherQueue_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct typed_event_handler_dispatcher_queue, ITypedEventHandler_DispatcherQueue_IInspectable_iface ); +} + +static HRESULT WINAPI typed_event_handler_dispatcher_queue_QueryInterface( ITypedEventHandler_DispatcherQueue_IInspectable *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_ITypedEventHandler_DispatcherQueue_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IUnknown )) + { + *out = iface; + ITypedEventHandler_DispatcherQueue_IInspectable_AddRef( iface ); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI typed_event_handler_dispatcher_queue_AddRef( ITypedEventHandler_DispatcherQueue_IInspectable *iface ) +{ + struct typed_event_handler_dispatcher_queue *handler = impl_from_ITypedEventHandler_DispatcherQueue_IInspectable( iface ); + return InterlockedIncrement( &handler->ref ); +} + +static ULONG WINAPI typed_event_handler_dispatcher_queue_Release( ITypedEventHandler_DispatcherQueue_IInspectable *iface ) +{ + struct typed_event_handler_dispatcher_queue *handler = impl_from_ITypedEventHandler_DispatcherQueue_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &handler->ref ); + + if (!ref) + { + CloseHandle( handler->event ); + free( handler ); + } + + return ref; +} + +static HRESULT WINAPI typed_event_handler_dispatcher_queue_Invoke( ITypedEventHandler_DispatcherQueue_IInspectable *iface, IDispatcherQueue *queue, IInspectable *inspectable ) +{ + struct typed_event_handler_dispatcher_queue *handler = impl_from_ITypedEventHandler_DispatcherQueue_IInspectable( iface ); + + SetEvent( handler->event ); + return S_OK; +} + +static const ITypedEventHandler_DispatcherQueue_IInspectableVtbl typed_event_handler_dispatcher_queue_vtbl = +{ + typed_event_handler_dispatcher_queue_QueryInterface, + typed_event_handler_dispatcher_queue_AddRef, + typed_event_handler_dispatcher_queue_Release, + typed_event_handler_dispatcher_queue_Invoke, +}; + +static HRESULT create_typed_event_handler_dispatcher_queue( ITypedEventHandler_DispatcherQueue_IInspectable **handler ) +{ + struct typed_event_handler_dispatcher_queue *impl; + + *handler = NULL; + + if (!(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; + + impl->ITypedEventHandler_DispatcherQueue_IInspectable_iface.lpVtbl = &typed_event_handler_dispatcher_queue_vtbl; + impl->ref = 1; + impl->event = CreateEventW( NULL, FALSE, FALSE, NULL ); + + *handler = &impl->ITypedEventHandler_DispatcherQueue_IInspectable_iface; + return S_OK; +} + +struct dispatcher_queue_handler +{ + IDispatcherQueueHandler IDispatcherQueueHandler_iface; + LONG ref; + + HANDLE event; +}; + +static struct dispatcher_queue_handler *impl_from_IDispatcherQueueHandler( IDispatcherQueueHandler *iface ) +{ + return CONTAINING_RECORD( iface, struct dispatcher_queue_handler, IDispatcherQueueHandler_iface ); +} + +static HRESULT WINAPI dispatcher_queue_handler_QueryInterface( IDispatcherQueueHandler *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_IDispatcherQueueHandler ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IUnknown )) + { + *out = iface; + IDispatcherQueueHandler_AddRef( iface ); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI dispatcher_queue_handler_AddRef( IDispatcherQueueHandler *iface ) +{ + struct dispatcher_queue_handler *handler = impl_from_IDispatcherQueueHandler( iface ); + return InterlockedIncrement( &handler->ref ); +} + +static ULONG WINAPI dispatcher_queue_handler_Release( IDispatcherQueueHandler *iface ) +{ + struct dispatcher_queue_handler *handler = impl_from_IDispatcherQueueHandler( iface ); + ULONG ref = InterlockedDecrement( &handler->ref ); + + if (!ref) + { + CloseHandle( handler->event ); + free( handler ); + } + + return ref; +} + +static HRESULT WINAPI dispatcher_queue_handler_Invoke( IDispatcherQueueHandler *iface ) +{ + struct dispatcher_queue_handler *handler = impl_from_IDispatcherQueueHandler( iface ); + + WaitForSingleObject( handler->event, INFINITE ); + return S_OK; +} + +static const IDispatcherQueueHandlerVtbl dispatcher_queue_handler_vtbl = +{ + dispatcher_queue_handler_QueryInterface, + dispatcher_queue_handler_AddRef, + dispatcher_queue_handler_Release, + dispatcher_queue_handler_Invoke, +}; + +static HRESULT create_dispatcher_queue_handler( IDispatcherQueueHandler **handler ) +{ + struct dispatcher_queue_handler *impl; + + *handler = NULL; + + if (!(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; + + impl->IDispatcherQueueHandler_iface.lpVtbl = &dispatcher_queue_handler_vtbl; + impl->ref = 1; + impl->event = CreateEventW( NULL, FALSE, FALSE, NULL ); + + *handler = &impl->IDispatcherQueueHandler_iface; + return S_OK; +} + static void test_DispatcherQueueController_Statics(void) { static const WCHAR *dispatcher_queue_controller_statics_name = L"Windows.System.DispatcherQueueController"; IDispatcherQueueControllerStatics *dispatcher_queue_controller_statics = (void *)0xdeadbeef; + ITypedEventHandler_DispatcherQueue_IInspectable *event_handler_iface = (void *)0xdeadbeef; + struct typed_event_handler_dispatcher_queue *event_handler = (void *)0xdeadbeef; + IDispatcherQueueController *dispatcher_queue_controller = (void *)0xdeadbeef; + struct dispatcher_queue_handler *queue_handler = (void *)0xdeadbeef; + IDispatcherQueueHandler *handler_iface = (void *)0xdeadbeef; + IDispatcherQueue2 *dispatcher_queue2 = (void *)0xdeadbeef; + IDispatcherQueue *dispatcher_queue = (void *)0xdeadbeef; IActivationFactory *factory = (void *)0xdeadbeef; + IAsyncAction *operation = (void *)0xdeadbeef; + IAsyncInfo *async_info = (void *)0xdeadbeef; + EventRegistrationToken token; + AsyncStatus status; HSTRING str = NULL; + boolean result; HRESULT hr; + DWORD ret; LONG ref; + MSG msg;
hr = WindowsCreateString( dispatcher_queue_controller_statics_name, wcslen( dispatcher_queue_controller_statics_name ), &str ); ok( hr == S_OK, "got hr %#lx.\n", hr ); @@ -71,6 +249,102 @@ static void test_DispatcherQueueController_Statics(void) hr = IActivationFactory_QueryInterface( factory, &IID_IDispatcherQueueControllerStatics, (void **)&dispatcher_queue_controller_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
+ hr = IDispatcherQueueControllerStatics_CreateOnDedicatedThread( dispatcher_queue_controller_statics, NULL ); + todo_wine + ok( hr == E_POINTER || hr == 0x80000005 /* win10 22h2 */, "got hr %#lx.\n", hr ); + hr = IDispatcherQueueControllerStatics_CreateOnDedicatedThread( dispatcher_queue_controller_statics, &dispatcher_queue_controller ); + todo_wine + ok( hr == S_OK, "got hr %#lx.\n", hr ); + if (FAILED(hr)) goto done; + + hr = IDispatcherQueueController_get_DispatcherQueue( dispatcher_queue_controller, NULL ); + todo_wine + ok( hr == E_POINTER || hr == 0x80000005 /* win10 22h2 */, "got hr %#lx.\n", hr ); + hr = IDispatcherQueueController_get_DispatcherQueue( dispatcher_queue_controller, &dispatcher_queue ); + todo_wine + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + check_interface( dispatcher_queue, &IID_IUnknown ); + check_interface( dispatcher_queue, &IID_IInspectable ); + check_interface( dispatcher_queue, &IID_IAgileObject ); + + hr = create_dispatcher_queue_handler( &handler_iface ); + ok( hr == S_OK, "Unexpected hr %#lx.\n", hr ); + + hr = IDispatcherQueue_TryEnqueue( dispatcher_queue, handler_iface, &result ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( result == TRUE, "got result %d.\n", result ); + + hr = IDispatcherQueue_QueryInterface( dispatcher_queue, &IID_IDispatcherQueue2, (void **)&dispatcher_queue2 ); + ok( hr == S_OK || broken(hr == E_NOINTERFACE) /* w1064v1809 */, "got hr %#lx.\n", hr ); + if (SUCCEEDED(hr)) + { + hr = IDispatcherQueue2_get_HasThreadAccess( dispatcher_queue2, &result ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( result == FALSE, "got result %d.\n", result ); + ref = IDispatcherQueue2_Release( dispatcher_queue2 ); + ok( ref == 3, "got ref %ld.\n", ref ); + } + + hr = create_typed_event_handler_dispatcher_queue( &event_handler_iface ); + ok( hr == S_OK, "got 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( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IDispatcherQueueController_ShutdownQueueAsync( dispatcher_queue_controller, NULL ); + ok( hr == E_POINTER || hr == 0x80000005 /* win10 22h2 */, "got hr %#lx.\n", hr ); + hr = IDispatcherQueueController_ShutdownQueueAsync( dispatcher_queue_controller, &operation ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + check_interface( operation, &IID_IInspectable ); + check_interface( operation, &IID_IAgileObject ); + check_interface( operation, &IID_IAsyncAction ); + + hr = IAsyncAction_QueryInterface( operation, &IID_IAsyncInfo, (void **)&async_info ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IAsyncInfo_get_Status( async_info, &status ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( status == Started, "got 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( !ret, "Unexpected wait result %lu.\n", ret ); + + hr = IAsyncInfo_get_Status( async_info, &status ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( status == Completed, "got status %d.\n", status ); + + hr = IAsyncInfo_Close( async_info ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ref = IAsyncInfo_Release( async_info ); + ok( ref == 2, "got ref %ld.\n", ref ); + ref = IAsyncAction_Release( operation ); + ok( ref == 1, "got ref %ld.\n", ref ); + hr = IDispatcherQueue_remove_ShutdownCompleted( dispatcher_queue, token ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IDispatcherQueue_TryEnqueue( dispatcher_queue, handler_iface, &result ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( result == FALSE, "got result %d.\n", result ); + + ref = ITypedEventHandler_DispatcherQueue_IInspectable_Release( event_handler_iface ); + ok( ref == 0, "got ref %ld.\n", ref ); + ref = IDispatcherQueueHandler_Release( handler_iface ); + ok( ref == 0, "got ref %ld.\n", ref ); + ref = IDispatcherQueue_Release( dispatcher_queue ); + ok( ref == 1, "got ref %ld.\n", ref ); + ref = IDispatcherQueueController_Release( dispatcher_queue_controller ); + ok( ref == 0, "got ref %ld.\n", ref ); +done: ref = IDispatcherQueueControllerStatics_Release( dispatcher_queue_controller_statics ); ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory );