After `DeviceWatcher::Start()` gets called, `DeviceWatcher` enumerates through a list of all `DeviceInformation` objects on the current system through the `Added` event handlers, dispatching `EnumerationCompleted` once this has finished. This MR implements this functionality.
-- v3: windows.devices.enumeration: Implement initial device enumeration for DeviceWatcher::Start().
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/devices.c | 57 +++++++++++++++++-- 1 file changed, 51 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index a6c0ce0fe03..d6d7f74c165 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -58,6 +58,8 @@ struct device_watcher_handler ITypedEventHandler_DeviceWatcher_IInspectable ITypedEventHandler_DeviceWatcher_IInspectable_iface; LONG ref;
+ unsigned int test_deviceinformation : 1; + LONG devices_added; HANDLE event; BOOL invoked; IInspectable *args; @@ -101,6 +103,7 @@ static ULONG WINAPI device_watcher_handler_Release( ITypedEventHandler_DeviceWat return ref; }
+static void test_DeviceInformation_obj( int line, IDeviceInformation *info ); static HRESULT WINAPI device_watcher_handler_Invoke( ITypedEventHandler_DeviceWatcher_IInspectable *iface, IDeviceWatcher *sender, IInspectable *args ) { @@ -113,7 +116,19 @@ static HRESULT WINAPI device_watcher_handler_Invoke( ITypedEventHandler_DeviceWa
IDeviceWatcher_AddRef( sender ); ref = IDeviceWatcher_Release( sender ); - ok( ref == 3, "got ref %lu\n", ref ); + todo_wine ok( ref == 3, "got ref %lu\n", ref ); + + if (impl->test_deviceinformation) + { + IDeviceInformation *info; + HRESULT hr; + + hr = IInspectable_QueryInterface( args, &IID_IDeviceInformation, (void *)&info ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + test_DeviceInformation_obj( __LINE__, info ); + InterlockedIncrement( &impl->devices_added ); + IDeviceInformation_Release( info ); + }
SetEvent( impl->event );
@@ -318,8 +333,8 @@ static void test_DeviceInformation( void ) { static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation";
- static struct device_watcher_handler stopped_handler, added_handler; - EventRegistrationToken stopped_token, added_token; + static struct device_watcher_handler stopped_handler, added_handler, enumerated_handler; + EventRegistrationToken stopped_token, added_token, enumerated_token; IInspectable *inspectable, *inspectable2; IActivationFactory *factory; IDeviceInformationStatics2 *device_info_statics2; @@ -336,8 +351,12 @@ static void test_DeviceInformation( void )
device_watcher_handler_create( &added_handler ); device_watcher_handler_create( &stopped_handler ); + device_watcher_handler_create( &enumerated_handler ); + stopped_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL ); ok( !!stopped_handler.event, "failed to create event, got error %lu\n", GetLastError() ); + enumerated_handler.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ok( !!enumerated_handler.event, "failed to create event, got error %lu\n", GetLastError() );
hr = WindowsCreateString( device_info_name, wcslen( device_info_name ), &str ); ok( hr == S_OK, "got hr %#lx\n", hr ); @@ -387,7 +406,7 @@ static void test_DeviceInformation( void ) todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status );
ref = IDeviceWatcher_AddRef( device_watcher ); - ok( ref == 2, "got ref %lu\n", ref ); + todo_wine ok( ref == 2, "got ref %lu\n", ref ); hr = IDeviceWatcher_Stop( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); ok( !WaitForSingleObject( stopped_handler.event, 1000 ), "wait for stopped_handler.event failed\n" ); @@ -410,7 +429,7 @@ static void test_DeviceInformation( void ) goto skip_device_statics; }
- IDeviceInformationStatics_CreateWatcherAqsFilter( device_info_statics, NULL, &device_watcher ); + hr = IDeviceInformationStatics_CreateWatcherAqsFilter( device_info_statics, NULL, &device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr );
check_interface( device_watcher, &IID_IUnknown, TRUE ); @@ -434,7 +453,7 @@ static void test_DeviceInformation( void ) todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status );
ref = IDeviceWatcher_AddRef( device_watcher ); - ok( ref == 2, "got ref %lu\n", ref ); + todo_wine ok( ref == 2, "got ref %lu\n", ref ); hr = IDeviceWatcher_Stop( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); ok( !WaitForSingleObject( stopped_handler.event, 1000 ), "wait for stopped_handler.event failed\n" ); @@ -447,6 +466,31 @@ static void test_DeviceInformation( void )
IDeviceWatcher_Release( device_watcher );
+ hr = IDeviceInformationStatics_CreateWatcher( device_info_statics, &device_watcher ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + + if (device_watcher) + { + added_handler.test_deviceinformation = 1; + hr = IDeviceWatcher_add_Added( device_watcher, (void *)&added_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, &added_token ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + hr = IDeviceWatcher_add_EnumerationCompleted( device_watcher, (void *)&enumerated_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, &enumerated_token ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + + hr = IDeviceWatcher_Start( device_watcher ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok( !WaitForSingleObject( enumerated_handler.event, 5000 ), "wait for enumerated_handler.event failed\n" ); + todo_wine ok( added_handler.devices_added > 0, "devices_added should be greater than 0" ); + hr = IDeviceWatcher_get_Status( device_watcher, &status ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok( status == DeviceWatcherStatus_EnumerationCompleted, "got status %u\n", status ); + + hr = IDeviceWatcher_Start( device_watcher ); + todo_wine ok( hr == E_ILLEGAL_METHOD_CALL, "Start returned %#lx\n", hr ); + + IDeviceWatcher_Release( device_watcher ); + } + hr = IDeviceInformationStatics_FindAllAsync( device_info_statics, &info_collection_async ); ok( hr == S_OK, "got %#lx\n", hr );
@@ -477,6 +521,7 @@ skip_device_statics: done: WindowsDeleteString( str ); CloseHandle( stopped_handler.event ); + CloseHandle( enumerated_handler.event ); }
static void test_DeviceAccessInformation( void )
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index ba7edaa5199..b1890235c6a 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -31,6 +31,7 @@ struct device_watcher IDeviceWatcher IDeviceWatcher_iface; LONG ref;
+ struct list added_handlers; struct list stopped_handlers; HSTRING filter; }; @@ -76,6 +77,7 @@ static ULONG WINAPI device_watcher_Release( IDeviceWatcher *iface )
if (!ref) { + typed_event_handlers_clear( &impl->added_handlers ); typed_event_handlers_clear( &impl->stopped_handlers ); WindowsDeleteString( impl->filter ); free( impl ); @@ -105,14 +107,18 @@ static HRESULT WINAPI device_watcher_GetTrustLevel( IDeviceWatcher *iface, Trust static HRESULT WINAPI device_watcher_add_Added( IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_DeviceInformation *handler, EventRegistrationToken *token ) { - FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); - return S_OK; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + + TRACE( "iface %p, handler %p, token %p\n", iface, handler, token ); + return typed_event_handlers_append( &impl->added_handlers, (ITypedEventHandler_IInspectable_IInspectable *)handler, token ); }
static HRESULT WINAPI device_watcher_remove_Added( IDeviceWatcher *iface, EventRegistrationToken token ) { - FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); - return E_NOTIMPL; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + + TRACE( "iface %p, token %#I64x.\n", iface, token.value ); + return typed_event_handlers_remove( &impl->added_handlers, &token ); }
static HRESULT WINAPI device_watcher_add_Updated( IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_DeviceInformationUpdate *handler, @@ -465,6 +471,7 @@ static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationS return hr; }
+ list_init( &this->added_handlers ); list_init( &this->stopped_handlers );
*watcher = &this->IDeviceWatcher_iface; @@ -548,6 +555,7 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 return hr; }
+ list_init( &this->added_handlers ); list_init( &this->stopped_handlers );
*watcher = &this->IDeviceWatcher_iface;
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 4 ++-- dlls/windows.devices.enumeration/tests/devices.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index b1890235c6a..de6ae50fc0d 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -444,8 +444,8 @@ static HRESULT WINAPI device_statics_FindAllAsyncAqsFilterAndAdditionalPropertie
static HRESULT WINAPI device_statics_CreateWatcher( IDeviceInformationStatics *iface, IDeviceWatcher **watcher ) { - FIXME( "iface %p, watcher %p stub!\n", iface, watcher ); - return E_NOTIMPL; + TRACE( "iface %p, watcher %p\n", iface, watcher ); + return IDeviceInformationStatics_CreateWatcherAqsFilter( iface, NULL, watcher ); }
static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, IDeviceWatcher **watcher ) diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index d6d7f74c165..dfbd3fa04d8 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -467,7 +467,7 @@ static void test_DeviceInformation( void ) IDeviceWatcher_Release( device_watcher );
hr = IDeviceInformationStatics_CreateWatcher( device_info_statics, &device_watcher ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr );
if (device_watcher) {
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 16 ++++++++++++---- dlls/windows.devices.enumeration/tests/devices.c | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index de6ae50fc0d..78d77effb35 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -32,6 +32,7 @@ struct device_watcher LONG ref;
struct list added_handlers; + struct list enumerated_handlers; struct list stopped_handlers; HSTRING filter; }; @@ -78,6 +79,7 @@ static ULONG WINAPI device_watcher_Release( IDeviceWatcher *iface ) if (!ref) { typed_event_handlers_clear( &impl->added_handlers ); + typed_event_handlers_clear( &impl->enumerated_handlers ); typed_event_handlers_clear( &impl->stopped_handlers ); WindowsDeleteString( impl->filter ); free( impl ); @@ -150,14 +152,18 @@ static HRESULT WINAPI device_watcher_remove_Removed( IDeviceWatcher *iface, Even static HRESULT WINAPI device_watcher_add_EnumerationCompleted( IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_IInspectable *handler, EventRegistrationToken *token ) { - FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); - return E_NOTIMPL; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + + TRACE( "iface %p, handler %p, token %p\n", iface, handler, token ); + return typed_event_handlers_append( &impl->enumerated_handlers, (ITypedEventHandler_IInspectable_IInspectable *)handler, token ); }
static HRESULT WINAPI device_watcher_remove_EnumerationCompleted( IDeviceWatcher *iface, EventRegistrationToken token ) { - FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); - return E_NOTIMPL; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + + TRACE( "iface %p, token %#I64x.\n", iface, token.value ); + return typed_event_handlers_remove( &impl->enumerated_handlers, &token ); }
static HRESULT WINAPI device_watcher_add_Stopped( IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_IInspectable *handler, EventRegistrationToken *token ) @@ -472,6 +478,7 @@ static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationS }
list_init( &this->added_handlers ); + list_init( &this->enumerated_handlers ); list_init( &this->stopped_handlers );
*watcher = &this->IDeviceWatcher_iface; @@ -556,6 +563,7 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 }
list_init( &this->added_handlers ); + list_init( &this->enumerated_handlers ); list_init( &this->stopped_handlers );
*watcher = &this->IDeviceWatcher_iface; diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index dfbd3fa04d8..57e62904da5 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -475,7 +475,7 @@ static void test_DeviceInformation( void ) hr = IDeviceWatcher_add_Added( device_watcher, (void *)&added_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, &added_token ); ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceWatcher_add_EnumerationCompleted( device_watcher, (void *)&enumerated_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, &enumerated_token ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr );
hr = IDeviceWatcher_Start( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 288 +++++++++++++++--- .../tests/devices.c | 6 +- 2 files changed, 252 insertions(+), 42 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 78d77effb35..f86380ba733 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -21,6 +21,7 @@ #include "initguid.h" #include "private.h" #include "setupapi.h" +#include "roapi.h"
#include "wine/debug.h"
@@ -35,6 +36,10 @@ struct device_watcher struct list enumerated_handlers; struct list stopped_handlers; HSTRING filter; + + CRITICAL_SECTION cs; + DeviceWatcherStatus status; + IAsyncOperation_DeviceInformationCollection *async_op; };
static inline struct device_watcher *impl_from_IDeviceWatcher( IDeviceWatcher *iface ) @@ -42,6 +47,89 @@ static inline struct device_watcher *impl_from_IDeviceWatcher( IDeviceWatcher *i return CONTAINING_RECORD( iface, struct device_watcher, IDeviceWatcher_iface ); }
+typedef HRESULT (*async_invoke_func)( IAsyncOperationCompletedHandler_IInspectable *, IAsyncOperation_IInspectable *, + AsyncStatus, void * ); + +struct async_handler +{ + IAsyncOperationCompletedHandler_IInspectable IAsyncOperationCompletedHandler_IInspectable_iface; + LONG ref; + const GUID *iid; + + async_invoke_func invoke_cb; + void *data; +}; + +static inline struct async_handler *impl_from_IAsyncOperationCompletedHandler_IInspectable( IAsyncOperationCompletedHandler_IInspectable *iface ) +{ + return CONTAINING_RECORD( iface, struct async_handler, IAsyncOperationCompletedHandler_IInspectable_iface ); +} + +static HRESULT WINAPI async_handler_QueryInterface( IAsyncOperationCompletedHandler_IInspectable *iface, REFIID iid, void **out ) +{ + struct async_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, impl->iid )) + { + IAsyncOperationCompletedHandler_IInspectable_AddRef( (*out = &impl->IAsyncOperationCompletedHandler_IInspectable_iface) ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI async_handler_AddRef( IAsyncOperationCompletedHandler_IInspectable *iface ) +{ + struct async_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI async_handler_Release( IAsyncOperationCompletedHandler_IInspectable *iface ) +{ + struct async_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI async_handler_Invoke( IAsyncOperationCompletedHandler_IInspectable *iface, IAsyncOperation_IInspectable *info, AsyncStatus status ) +{ + struct async_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable( iface ); + TRACE( "iface %p, info %p, status %d.\n", iface, info, status ); + return impl->invoke_cb( iface, info, status, impl->data ); +} + +static const struct IAsyncOperationCompletedHandler_IInspectableVtbl async_handler_vtbl = +{ + async_handler_QueryInterface, + async_handler_AddRef, + async_handler_Release, + async_handler_Invoke +}; + +static HRESULT async_handler_create( async_invoke_func on_invoke, void *data, const GUID *iid, void **out ) +{ + struct async_handler *this; + + if (!(this = calloc( 1, sizeof( *this ) ))) return E_OUTOFMEMORY; + + this->IAsyncOperationCompletedHandler_IInspectable_iface.lpVtbl = &async_handler_vtbl; + this->ref = 1; + this->iid = iid; + this->invoke_cb = on_invoke; + this->data = data; + *out = this; + return S_OK; +} + static HRESULT WINAPI device_watcher_QueryInterface( IDeviceWatcher *iface, REFIID iid, void **out ) { struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); @@ -82,6 +170,10 @@ static ULONG WINAPI device_watcher_Release( IDeviceWatcher *iface ) typed_event_handlers_clear( &impl->enumerated_handlers ); typed_event_handlers_clear( &impl->stopped_handlers ); WindowsDeleteString( impl->filter ); + impl->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &impl->cs ); + if (impl->async_op) + IAsyncOperation_DeviceInformationCollection_Release( impl->async_op ); free( impl ); }
@@ -188,10 +280,138 @@ static HRESULT WINAPI device_watcher_Status( IDeviceWatcher *iface, DeviceWatche return E_NOTIMPL; }
+static HRESULT device_watcher_findall_invoke( IAsyncOperationCompletedHandler_IInspectable *iface, IAsyncOperation_IInspectable *async_info, AsyncStatus status, + void *watcher ) +{ + IVectorView_DeviceInformation *collection = NULL; + struct device_watcher *impl; + IDeviceInformation *info; + UINT32 i, size; + HRESULT hr; + + impl = impl_from_IDeviceWatcher( watcher ); + if (status == Completed) + { + void *out; + if (FAILED( hr = IAsyncOperation_IInspectable_GetResults( async_info, (void *)&out ) )) goto done; + if (FAILED( hr = IInspectable_QueryInterface( out, &IID_IVectorView_DeviceInformation, (void *)&collection ))) goto done; + } + else + { + hr = E_FAIL; + goto done; + } + + if (!WindowsIsStringEmpty( impl->filter )) + { + FIXME( "Unsupported filter: %s\n", debugstr_hstring( impl->filter ) ); + hr = E_NOTIMPL; + goto done; + } + if (FAILED( hr = IVectorView_DeviceInformation_get_Size( collection, &size ))) + goto done; + for (i = 0; i < size && SUCCEEDED( hr = IVectorView_DeviceInformation_GetAt( collection, i, &info ) ); i++) + { + DeviceWatcherStatus status; + + EnterCriticalSection( &impl->cs ); + status = impl->status; + LeaveCriticalSection( &impl->cs ); + if (status != DeviceWatcherStatus_Started) + { + IDeviceInformation_Release( info ); + goto done; + } + + typed_event_handlers_notify( &impl->added_handlers, (IInspectable *)watcher, (IInspectable *)info ); + IDeviceInformation_Release( info ); + } + +done: + EnterCriticalSection( &impl->cs ); + IAsyncOperation_DeviceInformationCollection_Release( impl->async_op ); + impl->async_op = NULL; + if (SUCCEEDED( hr ) && impl->status == DeviceWatcherStatus_Started) + { + impl->status = DeviceWatcherStatus_EnumerationCompleted; + LeaveCriticalSection( &impl->cs ); + typed_event_handlers_notify( &impl->enumerated_handlers, (IInspectable *)watcher, NULL ); + } + else + { + if (FAILED( hr )) + impl->status = DeviceWatcherStatus_Aborted; + LeaveCriticalSection( &impl->cs ); + } + + IDeviceWatcher_Release( watcher ); + return hr; +} + static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) { - FIXME( "iface %p stub!\n", iface ); - return S_OK; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + IDeviceInformationStatics *statics; + const WCHAR *name = RuntimeClass_Windows_Devices_Enumeration_DeviceInformation; + HSTRING class_name; + HRESULT hr; + + FIXME( "iface %p: semi-stub!\n", iface ); + + if (!WindowsIsStringEmpty( impl->filter )) + { + FIXME("Unsupported filter: %s\n", debugstr_hstring( impl->filter )); + return E_NOTIMPL; + } + hr = WindowsCreateString( name, wcslen( name ), &class_name ); + if (FAILED( hr )) return hr; + hr = RoGetActivationFactory( class_name, &IID_IDeviceInformationStatics, (void *)&statics ); + WindowsDeleteString( class_name ); + if (FAILED( hr )) return hr; + + EnterCriticalSection( &impl->cs ); + switch (impl->status) + { + case DeviceWatcherStatus_Created: + case DeviceWatcherStatus_Stopped: + case DeviceWatcherStatus_Aborted: + { + IAsyncOperationCompletedHandler_IInspectable *handler; + HRESULT hr; + + if (FAILED( hr = async_handler_create( device_watcher_findall_invoke, iface, &IID_IAsyncOperationCompletedHandler_DeviceInformationCollection, + (void *)&handler ) )) + { + impl->status = DeviceWatcherStatus_Aborted; + break; + } + if (FAILED( hr = IDeviceInformationStatics_FindAllAsync( statics, &impl->async_op ))) + { + IAsyncOperationCompletedHandler_IInspectable_Release( handler ); + impl->status = DeviceWatcherStatus_Aborted; + break; + } + + IDeviceWatcher_AddRef( iface ); + if (FAILED( hr = IAsyncOperation_DeviceInformationCollection_put_Completed( impl->async_op, + (IAsyncOperationCompletedHandler_DeviceInformationCollection *) handler))) + { + IAsyncOperationCompletedHandler_IInspectable_Release( handler ); + IAsyncOperation_DeviceInformationCollection_Release( impl->async_op ); + impl->async_op = NULL; + IDeviceWatcher_Release( iface ); + break; + } + + impl->status = DeviceWatcherStatus_Started; + break; + } + default: + hr = E_ILLEGAL_METHOD_CALL; + } + LeaveCriticalSection( &impl->cs ); + IDeviceInformationStatics_Release( statics ); + return hr; }
static HRESULT WINAPI device_watcher_Stop( IDeviceWatcher *iface ) @@ -201,6 +421,10 @@ static HRESULT WINAPI device_watcher_Stop( IDeviceWatcher *iface )
FIXME( "iface %p semi-stub!\n", iface );
+ EnterCriticalSection( &impl->cs ); + impl->status = DeviceWatcherStatus_Stopped; + LeaveCriticalSection( &impl->cs ); + IDeviceWatcher_AddRef( &impl->IDeviceWatcher_iface ); hr = typed_event_handlers_notify( &impl->stopped_handlers, (IInspectable *)iface, NULL ); IDeviceWatcher_Release( &impl->IDeviceWatcher_iface ); @@ -448,35 +672,23 @@ static HRESULT WINAPI device_statics_FindAllAsyncAqsFilterAndAdditionalPropertie return E_NOTIMPL; }
-static HRESULT WINAPI device_statics_CreateWatcher( IDeviceInformationStatics *iface, IDeviceWatcher **watcher ) -{ - TRACE( "iface %p, watcher %p\n", iface, watcher ); - return IDeviceInformationStatics_CreateWatcherAqsFilter( iface, NULL, watcher ); -} - -static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, IDeviceWatcher **watcher ) -{ - FIXME( "iface %p, class %d, watcher %p stub!\n", iface, class, watcher ); - return E_NOTIMPL; -} - -static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationStatics *iface, HSTRING filter, IDeviceWatcher **watcher ) +static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **watcher ) { struct device_watcher *this; HRESULT hr;
- TRACE( "iface %p, filter %s, watcher %p\n", iface, debugstr_hstring(filter), watcher ); - if (!(this = calloc( 1, sizeof(*this) ))) return E_OUTOFMEMORY;
- this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; this->ref = 1; + this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; if (FAILED(hr = WindowsDuplicateString( filter, &this->filter ))) { free( this ); return hr; }
+ InitializeCriticalSectionEx( &this->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); + this->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": device_watcher.cs"); list_init( &this->added_handlers ); list_init( &this->enumerated_handlers ); list_init( &this->stopped_handlers ); @@ -485,6 +697,24 @@ static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationS return S_OK; }
+static HRESULT WINAPI device_statics_CreateWatcher( IDeviceInformationStatics *iface, IDeviceWatcher **watcher ) +{ + TRACE( "iface %p, watcher %p\n", iface, watcher ); + return device_watcher_create( NULL, watcher ); +} + +static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, IDeviceWatcher **watcher ) +{ + FIXME( "iface %p, class %d, watcher %p stub!\n", iface, class, watcher ); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationStatics *iface, HSTRING filter, IDeviceWatcher **watcher ) +{ + TRACE( "iface %p, filter %s, watcher %p\n", iface, debugstr_hstring(filter), watcher ); + return device_watcher_create( filter, watcher ); +} + static HRESULT WINAPI device_statics_CreateWatcherAqsFilterAndAdditionalProperties( IDeviceInformationStatics *iface, HSTRING filter, IIterable_HSTRING *additional_properties, IDeviceWatcher **watcher ) { @@ -545,29 +775,9 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 IIterable_HSTRING *additional_properties, DeviceInformationKind kind, IDeviceWatcher **watcher ) { - struct device_watcher *this; - HRESULT hr; - FIXME( "iface %p, filter %s, additional_properties %p, kind %u, watcher %p semi-stub!\n", iface, debugstr_hstring( filter ), additional_properties, kind, watcher ); - - if (!(this = calloc( 1, sizeof(*this) ))) - return E_OUTOFMEMORY; - - this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; - this->ref = 1; - if (FAILED(hr = WindowsDuplicateString( filter, &this->filter ))) - { - free( this ); - return hr; - } - - list_init( &this->added_handlers ); - list_init( &this->enumerated_handlers ); - list_init( &this->stopped_handlers ); - - *watcher = &this->IDeviceWatcher_iface; - return S_OK; + return device_watcher_create( filter, watcher ); }
static const struct IDeviceInformationStatics2Vtbl device_statics2_vtbl = diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 57e62904da5..d690d9b4745 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -479,14 +479,14 @@ static void test_DeviceInformation( void )
hr = IDeviceWatcher_Start( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( !WaitForSingleObject( enumerated_handler.event, 5000 ), "wait for enumerated_handler.event failed\n" ); - todo_wine ok( added_handler.devices_added > 0, "devices_added should be greater than 0" ); + ok( !WaitForSingleObject( enumerated_handler.event, 5000 ), "wait for enumerated_handler.event failed\n" ); + ok( added_handler.devices_added > 0, "devices_added should be greater than 0" ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); todo_wine ok( status == DeviceWatcherStatus_EnumerationCompleted, "got status %u\n", status );
hr = IDeviceWatcher_Start( device_watcher ); - todo_wine ok( hr == E_ILLEGAL_METHOD_CALL, "Start returned %#lx\n", hr ); + ok( hr == E_ILLEGAL_METHOD_CALL, "Start returned %#lx\n", hr );
IDeviceWatcher_Release( device_watcher ); }
v2:
* Remove weak references in DeviceWatcher implementation. * Mark DeviceWatcher refcount tests with`todo_wine`. * Test for the `Added` handler being invoked.