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.
-- v2: windows.devices.enumeration: Implement initial device enumeration for DeviceWatcher::Start(). windows.devices.enumeration: Implement EnumerationCompleted handler for DeviceWatcher. windows.devices.enumeration: Implement CreateWatcher. windows.devices.enumeration: Implement Added handler for DeviceWatcher. windows.devices.enumeration: Add tests for initial device enumeration in DeviceWatcher.
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..c71cadb7d3e 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 )) + { + IUnknown_AddRef( (IUnknown *)(*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 ); }
On Mon May 12 10:36:04 2025 +0000, Rémi Bernon wrote:
`enumerated_handler.event` is leaked at the end of the function.
Fixed, thanks.
On Mon May 12 10:36:04 2025 +0000, Rémi Bernon wrote:
I would argue that these maybe should be implemented after the tests have been added (and test should check that the callbacks have been called).
Yup, moved the tests to the first commit, and added a test to make sure that `Added` receives at least one device.
On Mon May 12 21:36:52 2025 +0000, Vibhav Pant wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/7997/diffs?diff_id=177149&start_sha=ed7ca4c63959f805aa2db26c5b251db717f9835d#be22ebd075fcc8cdd819ea1541a541e8d694dcec_33_33)
I've reimplemented this without weak references in the latest revision, thanks.
On Mon May 12 21:36:52 2025 +0000, Vibhav Pant wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/7997/diffs?diff_id=177149&start_sha=ed7ca4c63959f805aa2db26c5b251db717f9835d#be22ebd075fcc8cdd819ea1541a541e8d694dcec_317_388)
Sure, this is now handled by a `IAsyncOperationCompletedHandler`, thanks.