Supersedes !7997
From: Vibhav Pant vibhavp@gmail.com
--- .../tests/devices.c | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-)
diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index a6c0ce0fe03..80e9d3b2904 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; @@ -75,7 +77,8 @@ static HRESULT WINAPI device_watcher_handler_QueryInterface( struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable( iface );
if (IsEqualGUID( iid, &IID_IUnknown ) || - IsEqualGUID( iid, &IID_ITypedEventHandler_DeviceWatcher_IInspectable )) + IsEqualGUID( iid, &IID_ITypedEventHandler_DeviceWatcher_IInspectable ) || + (impl->test_deviceinformation && IsEqualGUID( iid, &IID_ITypedEventHandler_DeviceWatcher_DeviceInformation ))) { IUnknown_AddRef( &impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface ); *out = &impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface; @@ -101,19 +104,26 @@ 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 ) { struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable( iface ); - ULONG ref; - trace( "iface %p, sender %p, args %p\n", iface, sender, args );
impl->invoked = TRUE; impl->args = args;
- IDeviceWatcher_AddRef( sender ); - ref = IDeviceWatcher_Release( sender ); - 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 +328,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 +346,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 ); @@ -410,7 +424,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 ); @@ -447,6 +461,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\n" ); + 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 +516,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 | 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 df582f76523..451e2d44949 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -439,8 +439,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 80e9d3b2904..fc3b227527d 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -462,7 +462,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: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.devices.enumeration/main.c | 63 ++++++++++--------------- 1 file changed, 25 insertions(+), 38 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 451e2d44949..1f3b09f8960 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -220,6 +220,28 @@ static const struct IDeviceWatcherVtbl device_watcher_vtbl = device_watcher_Stop, };
+static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) +{ + struct device_watcher *impl; + HRESULT hr; + + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + + impl->ref = 1; + impl->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; + if (FAILED(hr = WindowsDuplicateString( filter, &impl->filter ))) + { + free( impl ); + return hr; + } + + list_init( &impl->stopped_handlers ); + + *out = &impl->IDeviceWatcher_iface; + TRACE( "created DeviceWatcher %p\n", *out ); + return S_OK; +} + struct device_information_statics { IActivationFactory IActivationFactory_iface; @@ -440,7 +462,7 @@ static HRESULT WINAPI device_statics_FindAllAsyncAqsFilterAndAdditionalPropertie static HRESULT WINAPI device_statics_CreateWatcher( IDeviceInformationStatics *iface, IDeviceWatcher **watcher ) { TRACE( "iface %p, watcher %p\n", iface, watcher ); - return IDeviceInformationStatics_CreateWatcherAqsFilter( iface, NULL, watcher ); + return device_watcher_create( NULL, watcher ); }
static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, IDeviceWatcher **watcher ) @@ -451,25 +473,8 @@ static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformatio
static HRESULT WINAPI device_statics_CreateWatcherAqsFilter( IDeviceInformationStatics *iface, 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; - if (FAILED(hr = WindowsDuplicateString( filter, &this->filter ))) - { - free( this ); - return hr; - } - - list_init( &this->stopped_handlers ); - - *watcher = &this->IDeviceWatcher_iface; - return S_OK; + return device_watcher_create( filter, watcher ); }
static HRESULT WINAPI device_statics_CreateWatcherAqsFilterAndAdditionalProperties( IDeviceInformationStatics *iface, HSTRING filter, @@ -532,27 +537,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->stopped_handlers ); - - *watcher = &this->IDeviceWatcher_iface; - return S_OK; + return device_watcher_create( filter, watcher ); }
static const struct IDeviceInformationStatics2Vtbl device_statics2_vtbl =
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.devices.enumeration/main.c | 24 +++++++++++++++---- .../tests/devices.c | 18 +++++++------- 2 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 1f3b09f8960..a67369b6e07 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -33,6 +33,9 @@ struct device_watcher
struct list stopped_handlers; HSTRING filter; + + CRITICAL_SECTION cs; + DeviceWatcherStatus status; };
static inline struct device_watcher *impl_from_IDeviceWatcher( IDeviceWatcher *iface ) @@ -78,6 +81,8 @@ static ULONG WINAPI device_watcher_Release( IDeviceWatcher *iface ) { typed_event_handlers_clear( &impl->stopped_handlers ); WindowsDeleteString( impl->filter ); + impl->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &impl->cs ); free( impl ); }
@@ -170,10 +175,17 @@ static HRESULT WINAPI device_watcher_remove_Stopped( IDeviceWatcher *iface, Even return typed_event_handlers_remove( &impl->stopped_handlers, &token ); }
-static HRESULT WINAPI device_watcher_Status( IDeviceWatcher *iface, DeviceWatcherStatus *status ) +static HRESULT WINAPI device_watcher_get_Status( IDeviceWatcher *iface, DeviceWatcherStatus *status ) { - FIXME( "iface %p, status %p stub!\n", iface, status ); - return E_NOTIMPL; + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + + TRACE( "iface %p, status %p\n", iface, status ); + + EnterCriticalSection( &impl->cs ); + *status = impl->status; + LeaveCriticalSection( &impl->cs ); + + return S_OK; }
static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) @@ -215,7 +227,7 @@ static const struct IDeviceWatcherVtbl device_watcher_vtbl = device_watcher_remove_EnumerationCompleted, device_watcher_add_Stopped, device_watcher_remove_Stopped, - device_watcher_Status, + device_watcher_get_Status, device_watcher_Start, device_watcher_Stop, }; @@ -237,6 +249,10 @@ static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out )
list_init( &impl->stopped_handlers );
+ InitializeCriticalSectionEx( &impl->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); + impl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": device_watcher.cs"); + impl->status = DeviceWatcherStatus_Created; + *out = &impl->IDeviceWatcher_iface; TRACE( "created DeviceWatcher %p\n", *out ); return S_OK; diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index fc3b227527d..2dc5b1433dc 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -391,13 +391,13 @@ static void test_DeviceInformation( void ) ok( hr == S_OK, "got hr %#lx\n", hr );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Created, "got status %u\n", status ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( status == DeviceWatcherStatus_Created, "got status %u\n", status );
hr = IDeviceWatcher_Start( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status );
ref = IDeviceWatcher_AddRef( device_watcher ); @@ -407,7 +407,7 @@ static void test_DeviceInformation( void ) ok( !WaitForSingleObject( stopped_handler.event, 1000 ), "wait for stopped_handler.event failed\n" );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); todo_wine ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); ok( stopped_handler.invoked, "stopped_handler not invoked\n" ); ok( stopped_handler.args == NULL, "stopped_handler not invoked\n" ); @@ -438,13 +438,13 @@ static void test_DeviceInformation( void ) ok( hr == S_OK, "got hr %#lx\n", hr );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Created, "got status %u\n", status ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( status == DeviceWatcherStatus_Created, "got status %u\n", status );
hr = IDeviceWatcher_Start( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status );
ref = IDeviceWatcher_AddRef( device_watcher ); @@ -454,7 +454,7 @@ static void test_DeviceInformation( void ) ok( !WaitForSingleObject( stopped_handler.event, 1000 ), "wait for stopped_handler.event failed\n" );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); todo_wine ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); ok( stopped_handler.invoked, "stopped_handler not invoked\n" ); ok( stopped_handler.args == NULL, "stopped_handler not invoked\n" ); @@ -477,7 +477,7 @@ static void test_DeviceInformation( void ) 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\n" ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + 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 );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.devices.enumeration/async.c | 143 ++++++++++++++++++ dlls/windows.devices.enumeration/main.c | 87 ++++++++++- dlls/windows.devices.enumeration/private.h | 2 + .../tests/devices.c | 16 +- 4 files changed, 234 insertions(+), 14 deletions(-)
diff --git a/dlls/windows.devices.enumeration/async.c b/dlls/windows.devices.enumeration/async.c index 3235c65a0a4..0c4f6d647d2 100644 --- a/dlls/windows.devices.enumeration/async.c +++ b/dlls/windows.devices.enumeration/async.c @@ -514,3 +514,146 @@ HRESULT async_operation_inspectable_create( const GUID *iid, IUnknown *invoker, TRACE( "created IAsyncOperation_IInspectable %p\n", *out ); return S_OK; } + +struct async_action +{ + IAsyncAction IAsyncAction_iface; + IAsyncInfoImpl *IAsyncInfoImpl_inner; + LONG ref; +}; + +static inline struct async_action *impl_from_IAsyncAction( IAsyncAction *iface ) +{ + return CONTAINING_RECORD( iface, struct async_action, IAsyncAction_iface ); +} + +static HRESULT WINAPI async_action_QueryInterface( IAsyncAction *iface, REFIID iid, void **out ) +{ + struct async_action *impl = impl_from_IAsyncAction( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IAsyncAction )) + { + IInspectable_AddRef( (*out = &impl->IAsyncAction_iface) ); + return S_OK; + } + + return IAsyncInfoImpl_QueryInterface( impl->IAsyncInfoImpl_inner, iid, out ); +} + +static ULONG WINAPI async_action_AddRef( IAsyncAction *iface ) +{ + struct async_action *impl = impl_from_IAsyncAction( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI async_action_Release( IAsyncAction *iface ) +{ + struct async_action *impl = impl_from_IAsyncAction( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) + { + /* guard against re-entry if inner releases an outer iface */ + InterlockedIncrement( &impl->ref ); + IAsyncInfoImpl_Release( impl->IAsyncInfoImpl_inner ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI async_action_GetIids( IAsyncAction *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI async_action_GetRuntimeClassName( IAsyncAction *iface, HSTRING *class_name ) +{ + return WindowsCreateString( L"Windows.Foundation.IAsyncOperation`1<Boolean>", + ARRAY_SIZE(L"Windows.Foundation.IAsyncOperation`1<Boolean>"), + class_name ); +} + +static HRESULT WINAPI async_action_GetTrustLevel( IAsyncAction *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI async_action_put_Completed( IAsyncAction *iface, IAsyncActionCompletedHandler *bool_handler ) +{ + IAsyncOperationCompletedHandlerImpl *handler = (IAsyncOperationCompletedHandlerImpl *)bool_handler; + struct async_action *impl = impl_from_IAsyncAction( iface ); + TRACE( "iface %p, handler %p.\n", iface, handler ); + return IAsyncInfoImpl_put_Completed( impl->IAsyncInfoImpl_inner, handler ); +} + +static HRESULT WINAPI async_action_get_Completed( IAsyncAction *iface, IAsyncActionCompletedHandler **bool_handler ) +{ + IAsyncOperationCompletedHandlerImpl **handler = (IAsyncOperationCompletedHandlerImpl **)bool_handler; + struct async_action *impl = impl_from_IAsyncAction( iface ); + TRACE( "iface %p, handler %p.\n", iface, handler ); + return IAsyncInfoImpl_get_Completed( impl->IAsyncInfoImpl_inner, handler ); +} + +static HRESULT WINAPI async_action_GetResults( IAsyncAction *iface ) +{ + struct async_action *impl = impl_from_IAsyncAction( iface ); + PROPVARIANT result; + HRESULT hr; + + TRACE( "iface %p.\n", iface ); + + PropVariantInit( &result ); + hr = IAsyncInfoImpl_get_Result( impl->IAsyncInfoImpl_inner, &result ); + PropVariantClear( &result ); + return hr; +} + +static const struct IAsyncActionVtbl async_action_vtbl = +{ + /* IUnknown methods */ + async_action_QueryInterface, + async_action_AddRef, + async_action_Release, + /* IInspectable methods */ + async_action_GetIids, + async_action_GetRuntimeClassName, + async_action_GetTrustLevel, + /* IAsyncOperation<boolean> */ + async_action_put_Completed, + async_action_get_Completed, + async_action_GetResults, +}; + +HRESULT async_action_create( IUnknown *invoker, async_operation_callback callback, IAsyncAction **out ) +{ + struct async_action *impl; + HRESULT hr; + + *out = NULL; + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + impl->IAsyncAction_iface.lpVtbl = &async_action_vtbl; + impl->ref = 1; + + if (FAILED(hr = async_info_create( invoker, NULL, callback, (IInspectable *)&impl->IAsyncAction_iface, &impl->IAsyncInfoImpl_inner )) || + FAILED(hr = IAsyncInfoImpl_Start( impl->IAsyncInfoImpl_inner ))) + { + if (impl->IAsyncInfoImpl_inner) IAsyncInfoImpl_Release( impl->IAsyncInfoImpl_inner ); + free( impl ); + return hr; + } + + *out = &impl->IAsyncAction_iface; + TRACE( "created IAsyncAction %p\n", *out ); + return S_OK; +} diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index a67369b6e07..0efe0966b5f 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -188,22 +188,97 @@ static HRESULT WINAPI device_watcher_get_Status( IDeviceWatcher *iface, DeviceWa return S_OK; }
+static HRESULT device_watcher_start_async( IUnknown *invoker, IUnknown *param, PROPVARIANT *result ) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher( (IDeviceWatcher *)invoker ); + DeviceWatcherStatus status; + + EnterCriticalSection( &impl->cs ); + if (impl->status == DeviceWatcherStatus_Stopping) status = DeviceWatcherStatus_Stopped; + else status = DeviceWatcherStatus_EnumerationCompleted; + impl->status = status; + LeaveCriticalSection( &impl->cs ); + + if (status == DeviceWatcherStatus_Stopped) typed_event_handlers_notify( &impl->stopped_handlers, (IInspectable *)invoker, NULL ); + return S_OK; +} + static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) { - FIXME( "iface %p stub!\n", iface ); + struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); + IAsyncAction *async; + HRESULT hr = S_OK; + + FIXME( "iface %p: semi-stub!\n", iface ); + + if (!WindowsIsStringEmpty( impl->filter )) + { + FIXME( "Unsupported filter: %s\n", debugstr_hstring( impl->filter ) ); + return E_NOTIMPL; + } + + EnterCriticalSection( &impl->cs ); + switch (impl->status) + { + case DeviceWatcherStatus_EnumerationCompleted: hr = E_ILLEGAL_METHOD_CALL; break; + case DeviceWatcherStatus_Started: hr = E_ILLEGAL_METHOD_CALL; break; + case DeviceWatcherStatus_Stopping: hr = E_ILLEGAL_METHOD_CALL; break; + default: hr = E_ILLEGAL_METHOD_CALL; + + case DeviceWatcherStatus_Aborted: + case DeviceWatcherStatus_Created: + case DeviceWatcherStatus_Stopped: + impl->status = DeviceWatcherStatus_Started; + hr = async_action_create( (IUnknown *)iface, device_watcher_start_async, &async ); + IAsyncAction_Release( async ); + break; + } + LeaveCriticalSection( &impl->cs ); + + return hr; +} + +static HRESULT device_watcher_stop_async( IUnknown *invoker, IUnknown *param, PROPVARIANT *result ) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher( (IDeviceWatcher *)invoker ); + + EnterCriticalSection( &impl->cs ); + impl->status = DeviceWatcherStatus_Stopped; + LeaveCriticalSection( &impl->cs ); + + typed_event_handlers_notify( &impl->stopped_handlers, (IInspectable *)invoker, NULL ); return S_OK; }
static HRESULT WINAPI device_watcher_Stop( IDeviceWatcher *iface ) { struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); - HRESULT hr; + IAsyncAction *async; + HRESULT hr = S_OK; + + TRACE( "iface %p\n", iface );
- FIXME( "iface %p semi-stub!\n", iface ); + EnterCriticalSection( &impl->cs ); + switch (impl->status) + { + case DeviceWatcherStatus_Aborted: break; + case DeviceWatcherStatus_Created: hr = E_ILLEGAL_METHOD_CALL; break; + case DeviceWatcherStatus_Stopped: hr = E_ILLEGAL_METHOD_CALL; break; + case DeviceWatcherStatus_Stopping: hr = E_ILLEGAL_METHOD_CALL; break; + default: hr = E_ILLEGAL_METHOD_CALL; + + case DeviceWatcherStatus_EnumerationCompleted: + impl->status = DeviceWatcherStatus_Stopping; + hr = async_action_create( (IUnknown *)iface, device_watcher_stop_async, &async ); + IAsyncAction_Release( async ); + break; + case DeviceWatcherStatus_Started: + impl->status = DeviceWatcherStatus_Stopping; + /* an async start is in progress, let it handle stopped state change */ + break; + } + LeaveCriticalSection( &impl->cs );
- IDeviceWatcher_AddRef( &impl->IDeviceWatcher_iface ); - hr = typed_event_handlers_notify( &impl->stopped_handlers, (IInspectable *)iface, NULL ); - IDeviceWatcher_Release( &impl->IDeviceWatcher_iface ); return hr; }
diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h index cc5be350379..e0a8e46f8b5 100644 --- a/dlls/windows.devices.enumeration/private.h +++ b/dlls/windows.devices.enumeration/private.h @@ -58,6 +58,8 @@ HRESULT typed_event_handlers_clear( struct list *list );
extern HRESULT async_operation_inspectable_create( const GUID *iid, IUnknown *invoker, IUnknown *param, async_operation_callback callback, IAsyncOperation_IInspectable **out ); +extern HRESULT async_action_create( IUnknown *invoker, async_operation_callback callback, IAsyncAction **out ); + extern HRESULT vector_create( const struct vector_iids *iids, void **out ); extern HRESULT device_information_create( const WCHAR *path, IDeviceInformation **info );
diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 2dc5b1433dc..2f6c0b8191f 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -398,17 +398,17 @@ static void test_DeviceInformation( void ) ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status ); + 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" );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); + ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); ok( stopped_handler.invoked, "stopped_handler not invoked\n" ); ok( stopped_handler.args == NULL, "stopped_handler not invoked\n" );
@@ -445,17 +445,17 @@ static void test_DeviceInformation( void ) ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Started, "got status %u\n", status ); + 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" );
hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); + ok( status == DeviceWatcherStatus_Stopped, "got status %u\n", status ); ok( stopped_handler.invoked, "stopped_handler not invoked\n" ); ok( stopped_handler.args == NULL, "stopped_handler not invoked\n" );
@@ -478,10 +478,10 @@ static void test_DeviceInformation( void ) todo_wine ok( added_handler.devices_added > 0, "devices_added should be greater than 0\n" ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine ok( status == DeviceWatcherStatus_EnumerationCompleted, "got status %u\n", status ); + 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 ); }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 16 ++++++++++------ dlls/windows.devices.enumeration/tests/devices.c | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 0efe0966b5f..3af782e8790 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 enumerated_handlers; struct list stopped_handlers; HSTRING filter;
@@ -79,6 +80,7 @@ static ULONG WINAPI device_watcher_Release( IDeviceWatcher *iface )
if (!ref) { + typed_event_handlers_clear( &impl->enumerated_handlers ); typed_event_handlers_clear( &impl->stopped_handlers ); WindowsDeleteString( impl->filter ); impl->cs.DebugInfo->Spare[0] = 0; @@ -149,20 +151,21 @@ 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 ) { 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->stopped_handlers, (ITypedEventHandler_IInspectable_IInspectable *)handler, token ); } @@ -170,7 +173,6 @@ static HRESULT WINAPI device_watcher_add_Stopped( IDeviceWatcher *iface, ITypedE static HRESULT WINAPI device_watcher_remove_Stopped( IDeviceWatcher *iface, EventRegistrationToken token ) { struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); - TRACE( "iface %p, token %#I64x.\n", iface, token.value ); return typed_event_handlers_remove( &impl->stopped_handlers, &token ); } @@ -200,6 +202,7 @@ static HRESULT device_watcher_start_async( IUnknown *invoker, IUnknown *param, P LeaveCriticalSection( &impl->cs );
if (status == DeviceWatcherStatus_Stopped) typed_event_handlers_notify( &impl->stopped_handlers, (IInspectable *)invoker, NULL ); + if (status == DeviceWatcherStatus_EnumerationCompleted) typed_event_handlers_notify( &impl->enumerated_handlers, (IInspectable *)invoker, NULL ); return S_OK; }
@@ -322,6 +325,7 @@ static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) return hr; }
+ list_init( &impl->enumerated_handlers ); list_init( &impl->stopped_handlers );
InitializeCriticalSectionEx( &impl->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO ); diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 2f6c0b8191f..42190b74137 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -470,11 +470,11 @@ 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 ); - todo_wine ok( !WaitForSingleObject( enumerated_handler.event, 5000 ), "wait for enumerated_handler.event failed\n" ); + 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\n" ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/windows.devices.enumeration/main.c | 106 +++++++++++++----------- 1 file changed, 59 insertions(+), 47 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 3af782e8790..960ebdfb1f0 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -26,6 +26,58 @@
WINE_DEFAULT_DEBUG_CHANNEL(enumeration);
+typedef HRESULT (*enum_device_information_cb)( IDeviceInformation *info, void *context ); + +static HRESULT enum_device_information( enum_device_information_cb callback, void *context ) +{ + HKEY iface_key; + HRESULT hr; + DWORD i; + + if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) + return HRESULT_FROM_WIN32( GetLastError() ); + + for (i = 0, hr = S_OK; SUCCEEDED(hr); i++) + { + char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)]; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; + SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof(iface)}; + HDEVINFO set = INVALID_HANDLE_VALUE; + GUID iface_class; + WCHAR name[40]; + DWORD j, len; + LSTATUS ret; + + len = ARRAY_SIZE(name); + ret = RegEnumKeyExW( iface_key, i, name, &len, NULL, NULL, NULL, NULL ); + if (ret == ERROR_NO_MORE_ITEMS) break; + if (ret) hr = HRESULT_FROM_WIN32( ret ); + + if (SUCCEEDED(hr) && SUCCEEDED(hr = CLSIDFromString( name, &iface_class ))) + { + set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); + if (set == INVALID_HANDLE_VALUE) hr = HRESULT_FROM_WIN32( GetLastError() ); + } + + for (j = 0; SUCCEEDED(hr) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface ); j++) + { + IDeviceInformation *info; + + detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof(buffer), NULL, NULL )) continue; + + if (SUCCEEDED(hr = device_information_create( detail->DevicePath, &info ))) + { + hr = callback( info, context ); + IDeviceInformation_Release( info ); + } + } + } + + RegCloseKey( iface_key ); + return hr; +} + struct device_watcher { IDeviceWatcher IDeviceWatcher_iface; @@ -451,6 +503,12 @@ static HRESULT WINAPI device_statics_CreateFromIdAsyncAdditionalProperties( IDev return E_NOTIMPL; }
+static HRESULT append_device_information( IDeviceInformation *info, void *context ) +{ + IVector_IInspectable *vector = context; + return IVector_IInspectable_Append( vector, (IInspectable *)info ); +} + static HRESULT find_all_async( IUnknown *invoker, IUnknown *param, PROPVARIANT *result ) { static const struct vector_iids iids = @@ -462,58 +520,12 @@ static HRESULT find_all_async( IUnknown *invoker, IUnknown *param, PROPVARIANT * }; IVectorView_DeviceInformation *view; IVector_IInspectable *vector; - HKEY iface_key; HRESULT hr; - DWORD i;
TRACE( "invoker %p, param %p, result %p\n", invoker, param, result );
if (FAILED(hr = vector_create( &iids, (void *)&vector ))) return hr; - - if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) - { - IVector_IInspectable_Release( vector ); - return HRESULT_FROM_WIN32( GetLastError() ); - } - - for (i = 0; SUCCEEDED(hr); i++) - { - char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)]; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; - SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof(iface)}; - HDEVINFO set = INVALID_HANDLE_VALUE; - GUID iface_class; - WCHAR name[40]; - DWORD j, len; - LSTATUS ret; - - len = ARRAY_SIZE(name); - ret = RegEnumKeyExW( iface_key, i, name, &len, NULL, NULL, NULL, NULL ); - if (ret == ERROR_NO_MORE_ITEMS) break; - if (ret) hr = HRESULT_FROM_WIN32( ret ); - - if (SUCCEEDED(hr) && SUCCEEDED(hr = CLSIDFromString( name, &iface_class ))) - { - set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); - if (set == INVALID_HANDLE_VALUE) hr = HRESULT_FROM_WIN32( GetLastError() ); - } - - for (j = 0; SUCCEEDED(hr) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface ); j++) - { - IDeviceInformation *info; - - detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); - if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof(buffer), NULL, NULL )) continue; - - if (SUCCEEDED(hr = device_information_create( detail->DevicePath, &info ))) - { - hr = IVector_IInspectable_Append( vector, (IInspectable *)info ); - IDeviceInformation_Release( info ); - } - } - } - - RegCloseKey( iface_key ); + hr = enum_device_information( append_device_information, vector );
if (SUCCEEDED(hr)) hr = IVector_IInspectable_GetView( vector, (void *)&view ); IVector_IInspectable_Release( vector );
From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 26 +++++++++++++++---- .../tests/devices.c | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 960ebdfb1f0..80a5d8b834c 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -83,6 +83,7 @@ struct device_watcher IDeviceWatcher IDeviceWatcher_iface; LONG ref;
+ struct list added_handlers; struct list enumerated_handlers; struct list stopped_handlers; HSTRING filter; @@ -132,6 +133,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 ); @@ -164,14 +166,16 @@ 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, @@ -242,13 +246,24 @@ static HRESULT WINAPI device_watcher_get_Status( IDeviceWatcher *iface, DeviceWa return S_OK; }
+static HRESULT add_device_information( IDeviceInformation *info, void *invoker ) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher( (IDeviceWatcher *)invoker ); + typed_event_handlers_notify( &impl->added_handlers, (IInspectable *)invoker, (IInspectable *)info ); + return S_OK; +} + static HRESULT device_watcher_start_async( IUnknown *invoker, IUnknown *param, PROPVARIANT *result ) { struct device_watcher *impl = impl_from_IDeviceWatcher( (IDeviceWatcher *)invoker ); DeviceWatcherStatus status; + HRESULT hr; + + hr = enum_device_information( add_device_information, invoker );
EnterCriticalSection( &impl->cs ); - if (impl->status == DeviceWatcherStatus_Stopping) status = DeviceWatcherStatus_Stopped; + if (FAILED(hr)) status = DeviceWatcherStatus_Aborted; + else if (impl->status == DeviceWatcherStatus_Stopping) status = DeviceWatcherStatus_Stopped; else status = DeviceWatcherStatus_EnumerationCompleted; impl->status = status; LeaveCriticalSection( &impl->cs ); @@ -377,6 +392,7 @@ static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) return hr; }
+ list_init( &impl->added_handlers ); list_init( &impl->enumerated_handlers ); list_init( &impl->stopped_handlers );
diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 42190b74137..d9247bb6ced 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_Start( device_watcher ); ok( hr == S_OK, "got hr %#lx\n", hr ); 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\n" ); + ok( added_handler.devices_added > 0, "devices_added should be greater than 0" ); hr = IDeviceWatcher_get_Status( device_watcher, &status ); ok( hr == S_OK, "got hr %#lx\n", hr ); ok( status == DeviceWatcherStatus_EnumerationCompleted, "got status %u\n", status );
This merge request was approved by Rémi Bernon.