 
            -- v10: windows.devices.enumeration: Implement IDeviceInformationStatics::{FindAllAsyncAqsFilterAndAdditionalProperties, CreateWatcherAqsFilterAndAdditionalProperties}.
 
            From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/tests/cfgmgr32.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 5841a1a8d4b..575c6b5b4e4 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -591,6 +591,13 @@ static const char *debugstr_DEVPROPKEY( const DEVPROPKEY *key ) return wine_dbg_sprintf( "{%s, %04lx}", debugstr_guid( &key->fmtid ), key->pid ); }
+static const char *debugstr_DEVPROPCOMPKEY( const DEVPROPCOMPKEY *key ) +{ + if (!key) return "(null)"; + return wine_dbg_sprintf( "{%s, %d, %s}", debugstr_DEVPROPKEY( &key->Key ), key->Store, + debugstr_w( key->LocaleName ) ); +} + static void test_DevGetObjectProperties( DEV_OBJECT_TYPE type, const WCHAR *id, const DEVPROPERTY *exp_props, ULONG props_len ) { DEVPROPCOMPKEY dummy_propcompkey = { DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL }; @@ -863,6 +870,7 @@ static void test_DevGetObjects( void ) DEVPROP_FILTER_EXPRESSION filters[4]; const DEV_OBJECT *objects = NULL; DEVPROPCOMPKEY prop_key = {0}; + DEVPROPCOMPKEY props[2]; HRESULT hr; ULONG i, len = 0;
@@ -1037,6 +1045,29 @@ static void test_DevGetObjects( void ) ok (!!prop, "got prop %p\n", prop ); winetest_pop_context(); } + pDevFreeObjects( len, objects ); + + /* DevGetObjects will not de-duplicate properties. */ + len = 0; + objects = NULL; + props[0] = prop_iface_class; + props[1] = prop_iface_class; + hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 2, props, 0, NULL, &len, &objects ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( len, "got len %lu\n", len ); + for (i = 0; i < len; i++) + { + const DEVPROPERTY *props = objects[i].pProperties; + + winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) ); + ok( objects[i].cPropertyCount == 2, "got cPropertyCount %lu\n", objects[i].cPropertyCount ); + ok( IsEqualDevPropCompKey( props[0].CompKey, prop_iface_class ), "got props[0].CompKey %s\n", + debugstr_DEVPROPCOMPKEY( &props[0].CompKey ) ); + ok( IsEqualDevPropCompKey( props[1].CompKey, prop_iface_class ), "got props[1].CompKey %s\n", + debugstr_DEVPROPCOMPKEY( &props[1].CompKey ) ); + winetest_pop_context(); + } + pDevFreeObjects( len, objects );
/* AND/OR with a single expression */ memset( filters, 0, sizeof( filters ) );
 
            From: Vibhav Pant vibhavp@gmail.com
--- .../tests/Makefile.in | 2 +- .../tests/devices.c | 219 +++++++++++++++++- 2 files changed, 211 insertions(+), 10 deletions(-)
diff --git a/dlls/windows.devices.enumeration/tests/Makefile.in b/dlls/windows.devices.enumeration/tests/Makefile.in index 0b47593720c..200e6707f58 100644 --- a/dlls/windows.devices.enumeration/tests/Makefile.in +++ b/dlls/windows.devices.enumeration/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = windows.devices.enumeration.dll -IMPORTS = combase uuid +IMPORTS = cfgmgr32 combase propsys uuid
SOURCES = \ devices.c diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 433f9c33f2b..c795c375e87 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -24,6 +24,10 @@ #include "winbase.h" #include "winerror.h" #include "winstring.h" +#include "devpropdef.h" +#include "devfiltertypes.h" +#include "devquery.h" +#include "propsys.h"
#include "initguid.h" #include "roapi.h" @@ -131,6 +135,12 @@ static ITypedEventHandler_IInspectable_IInspectable *inspectable_event_handler_c return &handler->iface; }
+struct device_property +{ + const WCHAR *name; + PropertyType type; +}; + struct device_watcher_added_handler_data { LONG devices_added; @@ -344,27 +354,217 @@ static void check_device_information_collection_async_( int line, IAsyncOperatio } }
-static void test_DeviceInformation_obj( int line, IDeviceInformation *info ) +/* Find the DEVPROPKEY associated with prop_name, ensure propval matches the value retrieved from DevGetObjectProperties. + * If propval is NULL, then check the retrieved DEVPROPERTY has Type DEVPROP_TYPE_EMPTY. + * This assumes that the DeviceInformationKind is DeviceInterface (DevObjectTypeDeviceInterfaceDisplay). */ +static void test_DeviceInformation_property( HSTRING device_id, const WCHAR *prop_name, IPropertyValue *propval ) { + PropertyType type = 0xdeadbeef; + DEVPROPCOMPKEY comp_key = {0}; + const DEVPROPERTY *prop; + DEVPROPKEY key = {0}; HRESULT hr; - HSTRING str; + ULONG len; + + hr = PSGetPropertyKeyFromName( prop_name, (PROPERTYKEY *)&key ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + + comp_key.Key = key; + prop = NULL; + len = 0; + hr = DevGetObjectProperties( DevObjectTypeDeviceInterfaceDisplay, WindowsGetStringRawBuffer( device_id, NULL ), 0, 1, &comp_key, &len, &prop ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( !!prop, "got prop %p\n", prop ); + ok( len == 1, "got len %lu != 1\n", len ); + + if (propval) + { + hr = IPropertyValue_get_Type( propval, &type ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + + switch (type) + { + case PropertyType_Boolean: + { + boolean bool_val, exp_val; + + hr = IPropertyValue_GetBoolean( propval, &bool_val ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( prop->Type == DEVPROP_TYPE_BOOLEAN, "got Type %#lx\n", prop->Type ); + exp_val = !!*(DEVPROP_BOOLEAN *)prop->Buffer; + ok( bool_val == exp_val, "got bool_val %d != %d\n", bool_val, exp_val ); + break; + } + case PropertyType_String: + { + HSTRING str; + + hr = IPropertyValue_GetString( propval, &str ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( prop->Type == DEVPROP_TYPE_STRING || prop->Type == DEVPROP_TYPE_STRING_INDIRECT, "got Type %#lx\n", prop->Type ); + /* TODO: + * For DEVPROP_TYPE_STRING_INDIRECT, WinRT extracts the locale-specific string from the referenced INF. + * System.ItemNameDisplay's value is formatted differently by WinRT. */ + if (!wcsicmp( prop_name, L"System.ItemNameDisplay" )) + skip("Unhandled property %s, skipping.\n", debugstr_w( prop_name ) ); + else if (prop->Type == DEVPROP_TYPE_STRING) + ok( !wcsicmp( WindowsGetStringRawBuffer( str, NULL ), prop->Buffer ), "got str %s != %s\n", debugstr_hstring( str ), + debugstr_w( prop->Buffer ) ); + WindowsDeleteString( str ); + break; + } + case PropertyType_Guid: + { + GUID guid; + + hr = IPropertyValue_GetGuid( propval, &guid ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( prop->Type == DEVPROP_TYPE_GUID, "got Type %#lx\n", prop->Type ); + ok( IsEqualGUID( &guid, prop->Buffer ), "got guid %s != %s\n", debugstr_guid( &guid ), debugstr_guid( prop->Buffer ) ); + break; + } + /* Used by System.Devices.PhysicalDeviceLocation */ + case PropertyType_UInt8Array: + { + BYTE *arr = NULL; + UINT32 len = 0; + + hr = IPropertyValue_GetUInt8Array( propval, &len, &arr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( prop->Type == (DEVPROP_TYPEMOD_ARRAY | DEVPROP_TYPE_BYTE), "got Type %#lx\n", prop->Type ); + ok( prop->BufferSize == sizeof( BYTE ) * len, "got BufferSize %lu\n", prop->BufferSize ); + if (prop->BufferSize == sizeof( BYTE ) * len) + ok( !memcmp( arr, prop->Buffer, len ), "got arr %s != %s \n", debugstr_an( (char *)arr, len ), debugstr_an( (char *)prop->Buffer, len ) ); + CoTaskMemFree( arr ); + break; + } + default: + skip( "Unhandled type %d, skipping.\n", type ); + break; + } + } + else + ok( prop->Type == DEVPROP_TYPE_EMPTY, "got Type %#lx\n", prop->Type ); + + DevFreeObjectProperties( len, prop ); + winetest_pop_context(); +} + + +static void test_DeviceInformation_obj( int line, IDeviceInformation *info ) +{ + HSTRING str = NULL, id = NULL; boolean bool_val; + HRESULT hr;
- hr = IDeviceInformation_get_Id( info, &str ); - ok_(__FILE__, line)( hr == S_OK, "got hr %#lx\n", hr ); - WindowsDeleteString( str ); - str = NULL; + hr = IDeviceInformation_get_Id( info, &id ); + ok_(__FILE__, line)( hr == S_OK, "get_Id failed, got hr %#lx\n", hr ); hr = IDeviceInformation_get_Name( info, &str ); - todo_wine ok_(__FILE__, line)( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok_(__FILE__, line)( hr == S_OK, "get_Name failed, got hr %#lx\n", hr ); WindowsDeleteString( str ); hr = IDeviceInformation_get_IsEnabled( info, &bool_val ); - todo_wine ok_(__FILE__, line)( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok_(__FILE__, line)( hr == S_OK, "get_IsEnabled failed, got hr %#lx\n", hr ); hr = IDeviceInformation_get_IsDefault( info, &bool_val ); - todo_wine ok_(__FILE__, line)( hr == S_OK, "got hr %#lx\n", hr ); + todo_wine ok_(__FILE__, line)( hr == S_OK, "get_IsDefault failed, got hr %#lx\n", hr ); +} + +static void test_DeviceInformation_properties( IDeviceInformation *info, const struct device_property *exp_props, SIZE_T exp_props_len ) +{ + IIterable_IKeyValuePair_HSTRING_IInspectable *iterable; + IIterator_IKeyValuePair_HSTRING_IInspectable *iterator; + IMapView_HSTRING_IInspectable *properties; + IInspectable *inspectable; + IPropertyValue *propval; + HSTRING str, id = NULL; + boolean valid; + HRESULT hr; + SIZE_T i; + + hr = IDeviceInformation_get_Properties( info, &properties ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + if (FAILED(hr)) return; + + hr = IDeviceInformation_get_Id( info, &id ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + for (i = 0; i < exp_props_len; i++) + { + PropertyType type = 0xdeadbeef; + HSTRING_HEADER hdr; + + winetest_push_context( "exp_props[%Iu]", i ); + hr = WindowsCreateStringReference( exp_props[i].name, wcslen( exp_props[i].name ), &hdr, &str ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + hr = IMapView_HSTRING_IInspectable_Lookup( properties, str, &inspectable ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + hr = IInspectable_QueryInterface( inspectable, &IID_IPropertyValue, (void **)&propval ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IInspectable_Release( inspectable ); + hr = IPropertyValue_get_Type( propval, &type ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + ok(type == exp_props[i].type, "got type %d != %d\n", type, exp_props[i].type ); + IPropertyValue_Release( propval ); + winetest_pop_context(); + } + + hr = IMapView_HSTRING_IInspectable_QueryInterface( properties, &IID_IIterable_IKeyValuePair_HSTRING_IInspectable, (void **)&iterable ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IMapView_HSTRING_IInspectable_Release( properties ); + hr = IIterable_IKeyValuePair_HSTRING_IInspectable_First( iterable, &iterator ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IIterable_IKeyValuePair_HSTRING_IInspectable_Release( iterable ); + + i = 0; + valid = FALSE; + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_HasCurrent( iterator, &valid ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + while (valid && SUCCEEDED( hr )) + { + IKeyValuePair_HSTRING_IInspectable *pair; + const WCHAR *prop_buf; + + winetest_push_context( "i=%Iu", i++ ); + + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_get_Current( iterator, &pair ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + + str = NULL; + hr = IKeyValuePair_HSTRING_IInspectable_get_Key( pair, &str ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + prop_buf = WindowsGetStringRawBuffer( str, NULL ); + inspectable = NULL; + hr = IKeyValuePair_HSTRING_IInspectable_get_Value( pair, &inspectable ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IKeyValuePair_HSTRING_IInspectable_Release( pair ); + + propval = NULL; + if (inspectable) + { + hr = IInspectable_QueryInterface( inspectable, &IID_IPropertyValue, (void **)&propval ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IInspectable_Release( inspectable ); + } + + winetest_push_context("%s: %s", debugstr_hstring( id ), debugstr_w( prop_buf ) ); + test_DeviceInformation_property( id, prop_buf, propval ); + WindowsDeleteString( str ); + winetest_pop_context(); + + hr = IIterator_IKeyValuePair_HSTRING_IInspectable_MoveNext( iterator, &valid ); + ok( hr == S_OK, " got hr %#lx\n", hr ); + + winetest_pop_context(); + } + WindowsDeleteString( id ); + IIterator_IKeyValuePair_HSTRING_IInspectable_Release( iterator ); + }
static void test_DeviceInformation( void ) { + static const struct device_property device_iface_exp_props[] = { + { L"System.Devices.InterfaceEnabled", PropertyType_Boolean }, + { L"System.Devices.DeviceInstanceId", PropertyType_String }, + }; static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation";
ITypedEventHandler_DeviceWatcher_IInspectable *stopped_handler, *enumerated_handler; @@ -557,6 +757,7 @@ static void test_DeviceInformation( void ) hr = IVectorView_DeviceInformation_GetAt( info_collection, i, &info ); ok( hr == S_OK, "got %#lx\n", hr ); test_DeviceInformation_obj( __LINE__, info ); + test_DeviceInformation_properties( info, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) ); IDeviceInformation_Release( info ); winetest_pop_context(); }
 
            From: Vibhav Pant vibhavp@gmail.com
--- .../tests/devices.c | 376 +++++++++++++++++- 1 file changed, 364 insertions(+), 12 deletions(-)
diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index c795c375e87..64983836088 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -32,6 +32,7 @@ #include "initguid.h" #include "roapi.h" #include "weakreference.h" +#include "ntddvdeo.h"
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections @@ -354,6 +355,231 @@ static void check_device_information_collection_async_( int line, IAsyncOperatio } }
+struct iterable_hstring +{ + IIterable_HSTRING IIterable_HSTRING_iface; + LONG ref; + + ULONG count; + HSTRING values[]; +}; + +C_ASSERT( sizeof( struct iterable_hstring ) == offsetof( struct iterable_hstring, values[0] ) ); + +static inline struct iterable_hstring *impl_from_IIterable_HSTRING( IIterable_HSTRING *iface ) +{ + return CONTAINING_RECORD( iface, struct iterable_hstring, IIterable_HSTRING_iface ); +} + +struct iterator_hstring +{ + IIterator_HSTRING IIterator_HSTRING_iface; + LONG ref; + + UINT32 index; + struct iterable_hstring *view; +}; + +static inline struct iterator_hstring *impl_from_IIterator_HSTRING( IIterator_HSTRING *iface ) +{ + return CONTAINING_RECORD( iface, struct iterator_hstring, IIterator_HSTRING_iface ); +} + +static HRESULT WINAPI iterator_hstring_QueryInterface( IIterator_HSTRING *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IIterator_HSTRING )) + { + IIterator_HSTRING_AddRef(( *out = iface )); + return S_OK; + } + + if (winetest_debug > 1) trace( "%s not implemented, returning E_NO_INTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI iterator_hstring_AddRef( IIterator_HSTRING *iface ) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + return ref; +} + +static ULONG WINAPI iterator_hstring_Release(IIterator_HSTRING *iface) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + if (!ref) + { + IIterable_HSTRING_Release( &impl->view->IIterable_HSTRING_iface ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI iterator_hstring_GetIids( IIterator_HSTRING *iface, ULONG *iid_count, IID **iids ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterator_hstring_GetRuntimeClassName( IIterator_HSTRING *iface, HSTRING *class_name ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterator_hstring_GetTrustLevel( IIterator_HSTRING *iface, TrustLevel *trust_level ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterator_hstring_get_Current( IIterator_HSTRING *iface, HSTRING *value ) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + + *value = NULL; + if (impl->index >= impl->view->count) return E_BOUNDS; + return WindowsDuplicateString( impl->view->values[impl->index], value ); +} + +static HRESULT WINAPI iterator_hstring_get_HasCurrent( IIterator_HSTRING *iface, boolean *value ) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + + *value = impl->index < impl->view->count; + return S_OK; +} + +static HRESULT WINAPI iterator_hstring_MoveNext( IIterator_HSTRING *iface, boolean *value ) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + + if (impl->index < impl->view->count) impl->index++; + return IIterator_HSTRING_get_HasCurrent( iface, value ); +} + +static HRESULT WINAPI iterator_hstring_GetMany( IIterator_HSTRING *iface, UINT32 items_size, HSTRING *items, UINT *count ) +{ + struct iterator_hstring *impl = impl_from_IIterator_HSTRING( iface ); + ULONG i, start = impl->index; + HRESULT hr = S_OK; + + for (i = start; i < impl->view->count && i < start + items_size; i++) + if (FAILED(hr = WindowsDuplicateString( impl->view->values[i], items + i - start ))) break; + + if (FAILED( hr )) while (i-- > start) WindowsDeleteString( items[i - start] ); + *count = i - start; + return hr; +} + +static const IIterator_HSTRINGVtbl iterator_hstring_vtbl = +{ + /* IUnknown methods */ + iterator_hstring_QueryInterface, + iterator_hstring_AddRef, + iterator_hstring_Release, + /* IInspectable methods */ + iterator_hstring_GetIids, + iterator_hstring_GetRuntimeClassName, + iterator_hstring_GetTrustLevel, + /* IIterator<HSTRING> methods */ + iterator_hstring_get_Current, + iterator_hstring_get_HasCurrent, + iterator_hstring_MoveNext, + iterator_hstring_GetMany, +}; + +static HRESULT STDMETHODCALLTYPE iterable_hstring_QueryInterface( IIterable_HSTRING *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IIterable_HSTRING )) + { + IIterable_HSTRING_AddRef(( *out = iface )); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE iterable_hstring_AddRef( IIterable_HSTRING *iface ) +{ + struct iterable_hstring *impl = impl_from_IIterable_HSTRING( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + return ref; +} + +static ULONG STDMETHODCALLTYPE iterable_hstring_Release( IIterable_HSTRING *iface ) +{ + struct iterable_hstring *impl = impl_from_IIterable_HSTRING( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + if (!ref) + { + while (impl->count--) WindowsDeleteString( impl->values[impl->count] ); + free( impl ); + } + return ref; +} + +static HRESULT WINAPI iterable_hstring_GetIids( IIterable_HSTRING *iface, ULONG *iid_count, IID **iids ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterable_hstring_GetRuntimeClassName( IIterable_HSTRING *iface, HSTRING *class_name ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterable_hstring_GetTrustLevel( IIterable_HSTRING *iface, TrustLevel *trust_level ) { return E_NOTIMPL; } + +static HRESULT WINAPI iterable_hstring_First( IIterable_HSTRING *iface, IIterator_HSTRING **value ) +{ + struct iterable_hstring *impl = impl_from_IIterable_HSTRING( iface ); + struct iterator_hstring *iter; + + if (!(iter = calloc( 1, sizeof( *iter ) ))) return E_OUTOFMEMORY; + iter->IIterator_HSTRING_iface.lpVtbl = &iterator_hstring_vtbl; + iter->ref = 1; + + IIterable_HSTRING_AddRef( iface ); + iter->view = impl; + + *value = &iter->IIterator_HSTRING_iface; + return S_OK; +} + +static const struct IIterable_HSTRINGVtbl iterable_hstring_vtbl = +{ + /* IUnknown methods */ + iterable_hstring_QueryInterface, + iterable_hstring_AddRef, + iterable_hstring_Release, + /* IInspectable methods */ + iterable_hstring_GetIids, + iterable_hstring_GetRuntimeClassName, + iterable_hstring_GetTrustLevel, + /* IIterable<HSTRING> methods */ + iterable_hstring_First, +}; + +static IIterable_HSTRING *iterable_hstring_create( const WCHAR **values, SIZE_T count ) +{ + struct iterable_hstring *impl; + HRESULT hr; + SIZE_T i; + + if (!(impl = malloc( offsetof( struct iterable_hstring, values[count] ) ))) return NULL; + impl->ref = 1; + + impl->IIterable_HSTRING_iface.lpVtbl = &iterable_hstring_vtbl; + impl->count = count; + for (i = 0; i < count; i++) + { + if (FAILED(hr = WindowsCreateString( values[i], wcslen(values[i]), &impl->values[i] ))) + { + while(i) WindowsDeleteString( impl->values[--i] ); + free( impl ); + return NULL; + } + } + + return &impl->IIterable_HSTRING_iface; +} + + /* Find the DEVPROPKEY associated with prop_name, ensure propval matches the value retrieved from DevGetObjectProperties. * If propval is NULL, then check the retrieved DEVPROPERTY has Type DEVPROP_TYPE_EMPTY. * This assumes that the DeviceInformationKind is DeviceInterface (DevObjectTypeDeviceInterfaceDisplay). */ @@ -559,11 +785,40 @@ static void test_DeviceInformation_properties( IDeviceInformation *info, const s
}
+static void test_DeviceInformationCollection( int line, IVectorView_DeviceInformation *info_collection, const struct device_property *exp_props, + SIZE_T exp_props_len ) +{ + UINT32 size, i; + HRESULT hr; + + hr = IVectorView_DeviceInformation_get_Size( info_collection, &size ); + ok_(__FILE__, line)( hr == S_OK, "got %#lx\n", hr ); + for (i = 0; i < size; i++) + { + IDeviceInformation *info; + + winetest_push_context( "info_collection %u", i ); + hr = IVectorView_DeviceInformation_GetAt( info_collection, i, &info ); + ok_(__FILE__, line)( hr == S_OK, "got %#lx\n", hr ); + test_DeviceInformation_obj( line, info ); + winetest_push_context("%d", line ); + test_DeviceInformation_properties( info, exp_props, exp_props_len ); + IDeviceInformation_Release( info ); + winetest_pop_context(); + winetest_pop_context(); + } +} + static void test_DeviceInformation( void ) { + static const WCHAR *device_iface_additional_props[] = { L"System.Devices.InterfaceClassGuid", L"{026e516e-b814-414b-83cd-856d6fef4822} 3" }; + static const WCHAR *device_invalid_props[] = { L"{026e516e-b814-414b-83cd-856d6fef4822}", L"{0-b814-414b-83cd-856d6fef4822} 3", L"{}" }; + static const WCHAR *device_nonexistent_props[] = { L"foo", L"", L" " }; static const struct device_property device_iface_exp_props[] = { { L"System.Devices.InterfaceEnabled", PropertyType_Boolean }, { L"System.Devices.DeviceInstanceId", PropertyType_String }, + /* Additional properties */ + { L"System.Devices.InterfaceClassGuid", PropertyType_Guid } }; static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation";
@@ -576,18 +831,18 @@ static void test_DeviceInformation( void ) IActivationFactory *factory; IDeviceInformationStatics2 *device_info_statics2; IDeviceInformationStatics *device_info_statics; + IIterable_HSTRING *additional_props; IDeviceWatcher *device_watcher; DeviceWatcherStatus status = 0xdeadbeef; IAsyncOperation_DeviceInformationCollection *info_collection_async = NULL; IVectorView_DeviceInformation *info_collection = NULL; - IDeviceInformation *info; IWeakReferenceSource *weak_src; IWeakReference *weak_ref; IDeviceWatcher *watcher; - UINT32 i, size; HSTRING str; HRESULT hr; ULONG ref; + int i;
enumerated_data.event = CreateEventW( NULL, FALSE, FALSE, NULL ); ok( !!enumerated_data.event, "failed to create event, got error %lu\n", GetLastError() ); @@ -748,20 +1003,53 @@ static void test_DeviceInformation( void ) await_device_information_collection( info_collection_async ); check_device_information_collection_async( info_collection_async, 1, Completed, S_OK, &info_collection ); IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) - 1 ); + IVectorView_DeviceInformation_Release( info_collection );
- hr = IVectorView_DeviceInformation_get_Size( info_collection, &size ); - ok( hr == S_OK, "got %#lx\n", hr ); - for (i = 0; i < size; i++) + hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, NULL, &info_collection_async ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + + if (SUCCEEDED( hr )) { - winetest_push_context( "info_collection %u", i ); - hr = IVectorView_DeviceInformation_GetAt( info_collection, i, &info ); - ok( hr == S_OK, "got %#lx\n", hr ); - test_DeviceInformation_obj( __LINE__, info ); - test_DeviceInformation_properties( info, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) ); - IDeviceInformation_Release( info ); + await_device_information_collection( info_collection_async ); + check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); + IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) - 1 ); + IVectorView_DeviceInformation_Release( info_collection ); + } + + additional_props = iterable_hstring_create( device_iface_additional_props, ARRAY_SIZE( device_iface_additional_props ) ); + hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + IIterable_HSTRING_Release( additional_props ); + if (SUCCEEDED( hr )) + { + await_device_information_collection( info_collection_async ); + check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); + IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) ); + IVectorView_DeviceInformation_Release( info_collection ); + } + + for (i = 0; i < ARRAY_SIZE( device_nonexistent_props ); i++ ) + { + winetest_push_context( "device_nonexistent_props[%d]", i ); + additional_props = iterable_hstring_create( &device_nonexistent_props[i], 1 ); + hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); + todo_wine ok( hr == TYPE_E_ELEMENTNOTFOUND, "got hr %#lx\n", hr ); + IIterable_HSTRING_Release( additional_props ); + winetest_pop_context(); + } + + for (i = 0; i < ARRAY_SIZE( device_invalid_props ); i++ ) + { + winetest_push_context( "device_invalid_props[%d]", i ); + additional_props = iterable_hstring_create( &device_invalid_props[i], 1 ); + hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx\n", hr ); + IIterable_HSTRING_Release( additional_props ); winetest_pop_context(); } - IVectorView_DeviceInformation_Release( info_collection );
IDeviceInformationStatics_Release( device_info_statics );
@@ -998,10 +1286,45 @@ static const struct test_case_filter filters_invalid_operand[] = { { L" System.StructuredQueryType.Boolean#True := System.StructuredQueryType.Boolean#True", E_INVALIDARG }, };
+static void test_DeviceInformation_prop_guid( IDeviceInformation *info, const WCHAR *prop, const GUID *guid_val ) +{ + IMapView_HSTRING_IInspectable *props; + IInspectable *inspectable; + IReference_GUID *val; + GUID guid = {0}; + HSTRING str; + HRESULT hr; + + hr = IDeviceInformation_get_Properties( info, &props ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + + hr = WindowsCreateString( prop, wcslen( prop ), &str ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + hr = IMapView_HSTRING_IInspectable_Lookup( props, str, &inspectable ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + WindowsDeleteString( str ); + IMapView_HSTRING_IInspectable_Release( props ); + + hr = IInspectable_QueryInterface( inspectable, &IID_IReference_GUID, (void **)&val ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IInspectable_Release( inspectable ); + hr = IReference_GUID_get_Value( val, &guid ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + IReference_GUID_Release( val ); + + ok( IsEqualGUID( &guid, guid_val ), "got guid %s != %s\n", debugstr_guid( &guid ), debugstr_guid( guid_val ) ); +} + static void test_aqs_filters( void ) { + static const WCHAR *filter_iface_display = L"System.Devices.InterfaceClassGuid := {e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"; static const WCHAR *class_name = RuntimeClass_Windows_Devices_Enumeration_DeviceInformation; + static const WCHAR *prop_name_iface_guid = L"System.Devices.InterfaceClassGuid"; + IAsyncOperation_DeviceInformationCollection *info_collection_async; + IVectorView_DeviceInformation *info_collection; IDeviceInformationStatics *statics; + IIterable_HSTRING *props_iterable; + UINT32 i, size; HSTRING str; HRESULT hr;
@@ -1046,6 +1369,35 @@ static void test_aqs_filters( void ) test_FindAllAsyncAqsFilter( statics, filters_invalid_operand, FALSE, FALSE ); test_CreateWatcherAqsFilter( statics, filters_invalid_operand, FALSE, FALSE, FALSE, FALSE );
+ props_iterable = iterable_hstring_create( &prop_name_iface_guid, 1 ); + hr = WindowsCreateString( filter_iface_display, wcslen( filter_iface_display ), &str ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( statics, str, props_iterable, &info_collection_async ); + todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + WindowsDeleteString( str ); + IIterable_HSTRING_Release( props_iterable ); + if (SUCCEEDED( hr )) + { + await_device_information_collection( info_collection_async ); + check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); + IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + + hr = IVectorView_DeviceInformation_get_Size( info_collection, &size ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + for (i = 0; i < size; i++) + { + IDeviceInformation *info; + + winetest_push_context( "i=%u", i ); + hr = IVectorView_DeviceInformation_GetAt( info_collection, i, &info ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + test_DeviceInformation_prop_guid( info, prop_name_iface_guid, &GUID_DEVINTERFACE_MONITOR ); + IDeviceInformation_Release( info ); + winetest_pop_context(); + } + IVectorView_DeviceInformation_Release( info_collection ); + } + IDeviceInformationStatics_Release( statics ); }
 
            From: Vibhav Pant vibhavp@gmail.com
--- .../windows.devices.enumeration/information.c | 180 ++++++++++++++++-- dlls/windows.devices.enumeration/main.c | 22 ++- dlls/windows.devices.enumeration/private.h | 5 +- .../tests/devices.c | 4 +- 4 files changed, 187 insertions(+), 24 deletions(-)
diff --git a/dlls/windows.devices.enumeration/information.c b/dlls/windows.devices.enumeration/information.c index c09a9ea37ef..0620975e4cb 100644 --- a/dlls/windows.devices.enumeration/information.c +++ b/dlls/windows.devices.enumeration/information.c @@ -19,6 +19,7 @@
#include "private.h"
+#include "roapi.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(enumeration); @@ -28,10 +29,11 @@ struct device_information IDeviceInformation IDeviceInformation_iface; LONG ref;
- HSTRING path; + IMap_HSTRING_IInspectable *properties; + HSTRING id; };
-static inline struct device_information *impl_DeviceInterface_from_IDeviceInformation( IDeviceInformation *iface ) +static inline struct device_information *impl_from_IDeviceInformation( IDeviceInformation *iface ) { return CONTAINING_RECORD( iface, struct device_information, IDeviceInformation_iface ); } @@ -57,7 +59,7 @@ static HRESULT WINAPI device_information_QueryInterface( IDeviceInformation *ifa
static ULONG WINAPI device_information_AddRef( IDeviceInformation *iface ) { - struct device_information *impl = impl_DeviceInterface_from_IDeviceInformation( iface ); + struct device_information *impl = impl_from_IDeviceInformation( iface ); ULONG ref = InterlockedIncrement( &impl->ref ); TRACE( "iface %p, ref %lu.\n", iface, ref ); return ref; @@ -65,14 +67,15 @@ static ULONG WINAPI device_information_AddRef( IDeviceInformation *iface )
static ULONG WINAPI device_information_Release( IDeviceInformation *iface ) { - struct device_information *impl = impl_DeviceInterface_from_IDeviceInformation( iface ); + struct device_information *impl = impl_from_IDeviceInformation( iface ); ULONG ref = InterlockedDecrement( &impl->ref );
TRACE( "iface %p, ref %lu.\n", iface, ref );
if (!ref) { - WindowsDeleteString( impl->path ); + if (impl->properties) IMap_HSTRING_IInspectable_Release( impl->properties ); + WindowsDeleteString( impl->id ); free( impl ); }
@@ -100,9 +103,9 @@ static HRESULT WINAPI device_information_GetTrustLevel( IDeviceInformation *ifac
static HRESULT WINAPI device_information_get_Id( IDeviceInformation *iface, HSTRING *id ) { - struct device_information *impl = impl_DeviceInterface_from_IDeviceInformation( iface ); + struct device_information *impl = impl_from_IDeviceInformation( iface ); TRACE( "iface %p, id %p\n", iface, id ); - return WindowsDuplicateString( impl->path, id ); + return WindowsDuplicateString( impl->id, id ); }
static HRESULT WINAPI device_information_get_Name( IDeviceInformation *iface, HSTRING *name ) @@ -131,8 +134,9 @@ static HRESULT WINAPI device_information_get_EnclosureLocation( IDeviceInformati
static HRESULT WINAPI device_information_get_Properties( IDeviceInformation *iface, IMapView_HSTRING_IInspectable **properties ) { - FIXME( "iface %p, properties %p stub!\n", iface, properties ); - return E_NOTIMPL; + struct device_information *impl = impl_from_IDeviceInformation( iface ); + TRACE( "iface %p, properties %p.\n", iface, properties ); + return IMap_HSTRING_IInspectable_GetView( impl->properties, properties ); }
static HRESULT WINAPI device_information_Update( IDeviceInformation *iface, IDeviceInformationUpdate *update ) @@ -176,19 +180,171 @@ static const struct IDeviceInformationVtbl device_information_vtbl = device_information_GetGlyphThumbnailAsync, };
-HRESULT device_information_create( const WCHAR *path, IDeviceInformation **info ) +static const char *debugstr_DEVPROPKEY( const DEVPROPKEY *key ) +{ + if (!key) return "(null)"; + return wine_dbg_sprintf( "{%s, %04lx}", debugstr_guid( &key->fmtid ), key->pid ); +} + +static HRESULT create_device_properties( const DEVPROPERTY *props, ULONG len, IMap_HSTRING_IInspectable **map ) +{ + static const WCHAR *propertyset_name = RuntimeClass_Windows_Foundation_Collections_PropertySet; + static const WCHAR *propertyvalue_name = RuntimeClass_Windows_Foundation_PropertyValue; + + IPropertyValueStatics *propval_statics = NULL; + IPropertySet *propset; + HSTRING_HEADER hdr; + HSTRING str; + HRESULT hr; + ULONG i; + + TRACE( "props %p, len %lu, map %p.\n", props, len, map ); + + WindowsCreateStringReference( propertyset_name, wcslen( propertyset_name ), &hdr, &str ); + if (FAILED(hr = RoActivateInstance( str, (IInspectable **)&propset ))) return hr; + hr = IPropertySet_QueryInterface( propset, &IID_IMap_HSTRING_IInspectable, (void **)map ); + IPropertySet_Release( propset ); + if (FAILED(hr)) goto done; + + WindowsCreateStringReference( propertyvalue_name, wcslen( propertyvalue_name ), &hdr, &str ); + hr = RoGetActivationFactory( str, &IID_IPropertyValueStatics, (void **)&propval_statics ); + + for (i = 0; SUCCEEDED(hr) && i < len; i++) + { + const DEVPROPERTY *prop = &props[i]; + const DEVPROPKEY *propkey = &prop->CompKey.Key; + HSTRING canonical_name; + IInspectable *val; + boolean replaced; + WCHAR *name; + + switch (prop->Type) + { + case DEVPROP_TYPE_BOOLEAN: + hr = IPropertyValueStatics_CreateBoolean( propval_statics, !!*(DEVPROP_BOOLEAN *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_BYTE: + case DEVPROP_TYPE_SBYTE: + hr = IPropertyValueStatics_CreateUInt8( propval_statics, *(BYTE *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_UINT16: + hr = IPropertyValueStatics_CreateUInt16( propval_statics, *(UINT16 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_INT16: + hr = IPropertyValueStatics_CreateInt16( propval_statics, *(INT16 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_UINT32: + hr = IPropertyValueStatics_CreateUInt32( propval_statics, *(UINT32 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_INT32: + hr = IPropertyValueStatics_CreateInt32( propval_statics, *(INT32 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_UINT64: + hr = IPropertyValueStatics_CreateUInt64( propval_statics, *(UINT64 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_INT64: + hr = IPropertyValueStatics_CreateInt64( propval_statics, *(INT64 *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_FLOAT: + hr = IPropertyValueStatics_CreateSingle( propval_statics, *(FLOAT *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_DOUBLE: + hr = IPropertyValueStatics_CreateDouble( propval_statics, *(DOUBLE *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_GUID: + hr = IPropertyValueStatics_CreateGuid( propval_statics, *(GUID *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_FILETIME: + hr = IPropertyValueStatics_CreateDateTime( propval_statics, *(DateTime *)prop->Buffer, &val ); + break; + case DEVPROP_TYPE_STRING: + { + WindowsCreateStringReference( prop->Buffer, wcslen( prop->Buffer ), &hdr, &str ); + hr = IPropertyValueStatics_CreateString( propval_statics, str, &val ); + break; + } + default: + FIXME("Unsupported DEVPROPTYPE: %#lx\n", prop->Type ); + continue; + } + if (FAILED(hr)) break; + if (SUCCEEDED(hr = PSGetNameFromPropertyKey( (PROPERTYKEY *)propkey, &name ))) + { + hr = WindowsCreateString( name, wcslen( name ), &canonical_name ); + CoTaskMemFree( name ); + } + else if (hr == TYPE_E_ELEMENTNOTFOUND) + { + const GUID *fmtid = &propkey->fmtid; + WCHAR buf[80]; + + WARN( "Unknown property key: %s\n", debugstr_DEVPROPKEY( propkey ) ); + swprintf( buf, ARRAY_SIZE( buf ), L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} %lu", fmtid->Data1, fmtid->Data2, fmtid->Data3, + fmtid->Data4[0], fmtid->Data4[1], fmtid->Data4[2], fmtid->Data4[3], fmtid->Data4[4], fmtid->Data4[5], fmtid->Data4[6], fmtid->Data4[7], propkey->pid ); + hr = WindowsCreateString( buf, wcslen( buf ), &canonical_name ); + } + + if (SUCCEEDED(hr)) + { + hr = IMap_HSTRING_IInspectable_Insert( *map, canonical_name, val, &replaced ); + WindowsDeleteString( canonical_name ); + } + IInspectable_Release( val ); + } + +done: + if (propval_statics) IPropertyValueStatics_Release( propval_statics ); + if (FAILED(hr) && *map) IMap_HSTRING_IInspectable_Release( *map ); + return hr; +} + +static const char *debugstr_DEV_OBJECT_TYPE( DEV_OBJECT_TYPE type ) +{ + static const char *str[] = { + "DevObjectTypeUnknown", + "DevObjectTypeDeviceInterface", + "DevObjectTypeDeviceContainer", + "DevObjectTypeDevice", + "DevObjectTypeDeviceInterfaceClass", + "DevObjectTypeAEP", + "DevObjectTypeAEPContainer", + "DevObjectTypeDeviceInstallerClass", + "DevObjectTypeDeviceInterfaceDisplay", + "DevObjectTypeDeviceContainerDisplay", + "DevObjectTypeAEPService", + "DevObjectTypeDevicePanel", + "DevObjectTypeAEPProtocol", + }; + if (type >= ARRAY_SIZE( str )) return wine_dbg_sprintf( "(unknown %d)", type ); + return wine_dbg_sprintf( "%s", str[type] ); +} + +static const char *debugstr_DEV_OBJECT( const DEV_OBJECT *obj ) +{ + if (!obj) return "(null)"; + return wine_dbg_sprintf( "{%s, %s, %lu, %p}", debugstr_DEV_OBJECT_TYPE( obj->ObjectType ), debugstr_w( obj->pszObjectId ), obj->cPropertyCount, + obj->pProperties ); +} + +HRESULT device_information_create( const DEV_OBJECT *obj, IDeviceInformation **info ) { struct device_information *impl; HRESULT hr;
- TRACE( "path %s, info %p\n", debugstr_w(path), info ); + TRACE( "obj %s, info %p\n", debugstr_DEV_OBJECT( obj ), info );
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; impl->IDeviceInformation_iface.lpVtbl = &device_information_vtbl; impl->ref = 1; + if (FAILED(hr = create_device_properties( obj->pProperties, obj->cPropertyCount, &impl->properties ))) + { + free( impl ); + return hr; + }
- if (FAILED(hr = WindowsCreateString( path, wcslen( path ), &impl->path ))) + if (FAILED(hr = WindowsCreateString( obj->pszObjectId, wcslen( obj->pszObjectId ), &impl->id ))) { + IMap_HSTRING_IInspectable_Release( impl->properties ); free( impl ); return hr; } diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 2125689eeef..c965ca363e0 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -24,10 +24,9 @@
#include "initguid.h" #include "private.h" -#include "devpropdef.h" -#include "devfiltertypes.h" #include "devquery.h" #include "aqs.h" +#include "devpkey.h"
#include "wine/debug.h"
@@ -347,7 +346,7 @@ static void WINAPI device_object_query_callback( HDEVQUERY query, void *data, case DevQueryResultAdd: { IDeviceInformation *info; - if (FAILED(hr = device_information_create( action_data->Data.DeviceObject.pszObjectId, &info ))) + if (FAILED(hr = device_information_create( &action_data->Data.DeviceObject, &info ))) break; typed_event_handlers_notify( &watcher->added_handlers, (IInspectable *)iface, (IInspectable *)info ); IDeviceInformation_Release( info ); @@ -361,6 +360,12 @@ static void WINAPI device_object_query_callback( HDEVQUERY query, void *data, IDeviceWatcher_Release( iface ); }
+static const DEVPROPCOMPKEY device_iface_default_props[] = +{ + { DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL }, + { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL }, +}; + static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) { struct device_watcher *impl = impl_from_IDeviceWatcher( iface ); @@ -394,8 +399,8 @@ static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) }
IWeakReferenceSource_GetWeakReference( &impl->weak_reference_source.IWeakReferenceSource_iface, &weak ); - hr = DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAsyncClose, 0, NULL, filters_len, filters, device_object_query_callback, - weak, &impl->query ); + hr = DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAsyncClose, ARRAY_SIZE( device_iface_default_props ), + device_iface_default_props, filters_len, filters, device_object_query_callback, weak, &impl->query ); if (FAILED(hr)) { ERR( "Failed to create device query: %#lx\n", hr ); @@ -645,16 +650,17 @@ static HRESULT find_all_async( IUnknown *invoker, IUnknown *param, PROPVARIANT * filters_len = params->expr->len; } if (FAILED(hr = vector_create( &iids, (void *)&vector ))) return hr; - if (FAILED(hr = DevGetObjects( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagNone, 0, NULL, filters_len, filters, &len, &objects ))) + hr = DevGetObjects( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagNone, ARRAY_SIZE( device_iface_default_props ), device_iface_default_props, filters_len, filters, + &len, &objects ); + if (FAILED(hr)) { IVector_IInspectable_Release( vector ); - ERR("DevGetObjects failed, hr %#lx\n", hr); return hr; } for (i = 0; i < len && SUCCEEDED(hr); i++) { IDeviceInformation *info; - if (SUCCEEDED(hr = device_information_create( objects[i].pszObjectId, &info ))) + if (SUCCEEDED(hr = device_information_create( &objects[i], &info ))) { hr = IVector_IInspectable_Append( vector, (IInspectable *)info ); IDeviceInformation_Release( info ); diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h index 0ce5624b21c..033e866b506 100644 --- a/dlls/windows.devices.enumeration/private.h +++ b/dlls/windows.devices.enumeration/private.h @@ -28,6 +28,9 @@ #include "winbase.h" #include "winstring.h" #include "objbase.h" +#include "devpropdef.h" +#include "devfiltertypes.h" +#include "devquerydef.h" #include "propsys.h"
#include "activation.h" @@ -63,7 +66,7 @@ extern HRESULT async_operation_inspectable_create( const GUID *iid, IUnknown *in 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 ); +extern HRESULT device_information_create( const DEV_OBJECT *obj, IDeviceInformation **info );
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ static inline impl_type *impl_from( iface_type *iface ) \ diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 64983836088..e29122cb242 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -707,9 +707,7 @@ static void test_DeviceInformation_properties( IDeviceInformation *info, const s SIZE_T i;
hr = IDeviceInformation_get_Properties( info, &properties ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); - if (FAILED(hr)) return; - + ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceInformation_get_Id( info, &id ); ok( hr == S_OK, "got hr %#lx\n", hr ); for (i = 0; i < exp_props_len; i++)
 
            From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/main.c | 204 ++++++++++++++---- .../tests/devices.c | 36 ++-- 2 files changed, 178 insertions(+), 62 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index c965ca363e0..94d5b31460a 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -35,7 +35,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(enumeration); struct devquery_params { IUnknown IUnknown_iface; + DEV_OBJECT_TYPE type; struct aqs_expr *expr; + DEVPROPCOMPKEY *prop_keys; + ULONG prop_keys_len; LONG ref; };
@@ -78,6 +81,7 @@ static ULONG WINAPI devquery_params_Release( IUnknown *iface ) if (!ref) { free_aqs_expr( impl->expr ); + free( impl->prop_keys ); free( impl ); } return ref; @@ -91,7 +95,7 @@ static const IUnknownVtbl devquery_params_vtbl = devquery_params_Release, };
-static HRESULT devquery_params_create( struct aqs_expr *expr, IUnknown **out ) +static HRESULT devquery_params_create( DEV_OBJECT_TYPE type, struct aqs_expr *expr, DEVPROPCOMPKEY *prop_keys, ULONG prop_keys_len, IUnknown **out ) { struct devquery_params *impl;
@@ -100,7 +104,10 @@ static HRESULT devquery_params_create( struct aqs_expr *expr, IUnknown **out )
impl->IUnknown_iface.lpVtbl = &devquery_params_vtbl; impl->ref = 1; + impl->type = type; impl->expr = expr; + impl->prop_keys = prop_keys; + impl->prop_keys_len = prop_keys_len; *out = &impl->IUnknown_iface; return S_OK; } @@ -399,8 +406,8 @@ static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) }
IWeakReferenceSource_GetWeakReference( &impl->weak_reference_source.IWeakReferenceSource_iface, &weak ); - hr = DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAsyncClose, ARRAY_SIZE( device_iface_default_props ), - device_iface_default_props, filters_len, filters, device_object_query_callback, weak, &impl->query ); + hr = DevCreateObjectQuery( query_params->type, DevQueryFlagAsyncClose, query_params->prop_keys_len, query_params->prop_keys, filters_len, filters, + device_object_query_callback, weak, &impl->query ); if (FAILED(hr)) { ERR( "Failed to create device query: %#lx\n", hr ); @@ -468,10 +475,94 @@ static const struct IDeviceWatcherVtbl device_watcher_vtbl = device_watcher_Stop, };
-static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) +static BOOL devpropcompkey_buf_find_devpropkey( const DEVPROPCOMPKEY *keys, ULONG keys_len, DEVPROPKEY key ) { + ULONG i; + + for (i = 0; i < keys_len; i++) + if (IsEqualDevPropKey(keys[i].Key, key)) return TRUE; + return FALSE; +} + +static HRESULT devpropcompkeys_init( DEVPROPCOMPKEY **keys, ULONG *keys_len, const DEVPROPCOMPKEY *values, ULONG len ) +{ + if (!(*keys = calloc( len, sizeof( **keys ) ))) return E_OUTOFMEMORY; + memcpy( *keys, values, len * sizeof( **keys ) ); + *keys_len = len; + return S_OK; +} + +static HRESULT count_iterable( IIterable_HSTRING *iterable, ULONG *count ) +{ + IIterator_HSTRING *iter; + boolean valid; + HRESULT hr; + + if (FAILED(hr = IIterable_HSTRING_First( iterable, &iter ))) return hr; + for (hr = IIterator_HSTRING_get_HasCurrent( iter, &valid ); SUCCEEDED(hr) && valid; hr = IIterator_HSTRING_MoveNext( iter, &valid )) + *count += 1; + IIterator_HSTRING_Release( iter ); + + return hr; +} + +static HRESULT WINAPI devpropcompkeys_append_names( DEVPROPCOMPKEY **keys, ULONG *keys_len, IIterable_HSTRING *names_iterable ) +{ + IIterator_HSTRING *names; + DEVPROPCOMPKEY *tmp; + ULONG count = 0; + boolean valid; + HRESULT hr; + + if (FAILED(hr = count_iterable( names_iterable, &count ))) return hr; + if (!(tmp = realloc( *keys, (*keys_len + count) * sizeof( **keys ) ))) return E_OUTOFMEMORY; + *keys = tmp; + + if (FAILED(hr = IIterable_HSTRING_First( names_iterable, &names ))) return hr; + for (hr = IIterator_HSTRING_get_HasCurrent( names, &valid ); SUCCEEDED( hr ) && valid; hr = IIterator_HSTRING_MoveNext( names, &valid )) + { + DEVPROPCOMPKEY key = {0}; + const WCHAR *buf; + HSTRING name; + + if (FAILED(hr = IIterator_HSTRING_get_Current( names, &name ))) break; + buf = WindowsGetStringRawBuffer( name, NULL ); + if (buf[0] == '{') + hr = PSPropertyKeyFromString( buf, (PROPERTYKEY *)&key.Key ); + else + hr = PSGetPropertyKeyFromName( buf, (PROPERTYKEY *)&key.Key ); + WindowsDeleteString( name ); + if (FAILED(hr)) break; + /* DevGetObjects(Ex) will not de-duplicate properties, so we need to do it ourselves. */ + if (!devpropcompkey_buf_find_devpropkey( *keys, *keys_len, key.Key )) + { + (*keys)[*keys_len] = key; + *keys_len += 1; + } + } + + IIterator_HSTRING_Release( names ); + return hr; +} + +static HRESULT device_watcher_create( HSTRING filter, IIterable_HSTRING *additional_props, DeviceInformationKind kind, IDeviceWatcher **out ) +{ + static const DEV_OBJECT_TYPE kind_type[] = { + DevObjectTypeUnknown, + DevObjectTypeDeviceInterfaceDisplay, + DevObjectTypeDeviceContainerDisplay, + DevObjectTypeDevice, + DevObjectTypeDeviceInterfaceClass, + DevObjectTypeAEP, + DevObjectTypeAEPContainer, + DevObjectTypeAEPService, + DevObjectTypeDevicePanel, + }; + DEV_OBJECT_TYPE type = DevObjectTypeUnknown; + DEVPROPCOMPKEY *prop_keys = NULL; + struct aqs_expr *expr = NULL; struct device_watcher *impl; - struct aqs_expr *expr; + ULONG prop_keys_len = 0; HRESULT hr;
if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; @@ -483,19 +574,19 @@ static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) return hr; } /* If the filter string is all whitespaces, we return E_INVALIDARG in IDeviceWatcher_Start, not here. */ - if (FAILED(hr = aqs_parse_query( WindowsGetStringRawBuffer( filter, NULL ), &expr, &impl->aqs_all_whitespace )) && !impl->aqs_all_whitespace) - { - weak_reference_strong_release( &impl->weak_reference_source ); - free( impl ); - return hr; - } - if (FAILED(hr = devquery_params_create( expr, &impl->query_params ))) + if (FAILED(hr = aqs_parse_query( WindowsGetStringRawBuffer( filter, NULL ), &expr, &impl->aqs_all_whitespace )) && !impl->aqs_all_whitespace) goto failed; + + if (kind < ARRAY_SIZE( kind_type )) { - free_aqs_expr( expr ); - weak_reference_strong_release( &impl->weak_reference_source ); - free( impl ); - return hr; + type = kind_type[kind]; + if (kind == DeviceInformationKind_DeviceInterface) + if (FAILED(hr = devpropcompkeys_init( &prop_keys, &prop_keys_len, device_iface_default_props, ARRAY_SIZE( device_iface_default_props ) ))) + goto failed; } + else FIXME( "Unknown DeviceInformationKind value: %u\n", kind ); + + if (additional_props && FAILED(hr = devpropcompkeys_append_names( &prop_keys, &prop_keys_len, additional_props ))) goto failed; + if (FAILED(hr = devquery_params_create( type, expr, prop_keys, prop_keys_len, &impl->query_params ))) goto failed;
list_init( &impl->added_handlers ); list_init( &impl->enumerated_handlers ); @@ -508,6 +599,13 @@ static HRESULT device_watcher_create( HSTRING filter, IDeviceWatcher **out ) *out = &impl->IDeviceWatcher_iface; TRACE( "created DeviceWatcher %p\n", *out ); return S_OK; + +failed: + free( prop_keys ); + free_aqs_expr( expr ); + weak_reference_strong_release( &impl->weak_reference_source ); + free( impl ); + return hr; }
struct device_information_statics @@ -650,8 +748,7 @@ static HRESULT find_all_async( IUnknown *invoker, IUnknown *param, PROPVARIANT * filters_len = params->expr->len; } if (FAILED(hr = vector_create( &iids, (void *)&vector ))) return hr; - hr = DevGetObjects( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagNone, ARRAY_SIZE( device_iface_default_props ), device_iface_default_props, filters_len, filters, - &len, &objects ); + hr = DevGetObjects( params->type, DevQueryFlagNone, params->prop_keys_len, params->prop_keys, filters_len, filters, &len, &objects ); if (FAILED(hr)) { IVector_IInspectable_Release( vector ); @@ -680,7 +777,7 @@ static HRESULT WINAPI device_statics_FindAllAsync( IDeviceInformationStatics *if IAsyncOperation_DeviceInformationCollection **op ) { TRACE( "iface %p, op %p\n", iface, op ); - return IDeviceInformationStatics_FindAllAsyncAqsFilter( iface, NULL, op ); + return IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( iface, NULL, NULL, op ); }
static HRESULT WINAPI device_statics_FindAllAsyncDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, @@ -693,34 +790,42 @@ static HRESULT WINAPI device_statics_FindAllAsyncDeviceClass( IDeviceInformation static HRESULT WINAPI device_statics_FindAllAsyncAqsFilter( IDeviceInformationStatics *iface, HSTRING filter, IAsyncOperation_DeviceInformationCollection **op ) { - struct aqs_expr *expr; - IUnknown *params; - HRESULT hr; - TRACE( "iface %p, aqs %p, op %p\n", iface, debugstr_hstring(filter), op ); - - if (FAILED(hr = aqs_parse_query(WindowsGetStringRawBuffer( filter, NULL ), &expr, NULL ))) return hr; - if (FAILED(hr = devquery_params_create( expr, ¶ms ))) - { - free_aqs_expr( expr ); - return hr; - } - return async_operation_inspectable_create( &IID_IAsyncOperation_DeviceInformationCollection, (IUnknown *)iface, (IUnknown *)params, - find_all_async, (IAsyncOperation_IInspectable **)op ); + return IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( iface, filter, NULL, op ); }
static HRESULT WINAPI device_statics_FindAllAsyncAqsFilterAndAdditionalProperties( IDeviceInformationStatics *iface, HSTRING filter, IIterable_HSTRING *additional_properties, IAsyncOperation_DeviceInformationCollection **op ) { - FIXME( "iface %p, aqs %p, additional_properties %p, op %p stub!\n", iface, debugstr_hstring(filter), additional_properties, op ); - return E_NOTIMPL; + DEVPROPCOMPKEY *prop_keys = NULL; + struct aqs_expr *expr = NULL; + ULONG prop_keys_len = 0; + IUnknown *params; + HRESULT hr; + + TRACE( "iface %p, aqs %s, additional_properties %p, op %p\n", iface, debugstr_hstring(filter), additional_properties, op ); + + if (FAILED(hr = devpropcompkeys_init( &prop_keys, &prop_keys_len, device_iface_default_props, ARRAY_SIZE( device_iface_default_props ) ))) goto failed; + if (additional_properties && FAILED(hr = devpropcompkeys_append_names( &prop_keys, &prop_keys_len, additional_properties ))) goto failed; + if (FAILED(hr = aqs_parse_query(WindowsGetStringRawBuffer( filter, NULL ), &expr, NULL ))) goto failed; + if (FAILED(hr = devquery_params_create( DevObjectTypeDeviceInterfaceDisplay, expr, prop_keys, prop_keys_len, ¶ms ))) goto failed; + + hr = async_operation_inspectable_create( &IID_IAsyncOperation_DeviceInformationCollection, (IUnknown *)iface, params, find_all_async, + (IAsyncOperation_IInspectable **)op ); + IUnknown_Release( params ); + return hr; + +failed: + free( prop_keys ); + free_aqs_expr( expr ); + return hr; }
static HRESULT WINAPI device_statics_CreateWatcher( IDeviceInformationStatics *iface, IDeviceWatcher **watcher ) { TRACE( "iface %p, watcher %p\n", iface, watcher ); - return device_watcher_create( NULL, watcher ); + return IDeviceInformationStatics_CreateWatcherAqsFilterAndAdditionalProperties( iface, NULL, NULL, watcher ); }
static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformationStatics *iface, DeviceClass class, IDeviceWatcher **watcher ) @@ -732,14 +837,14 @@ static HRESULT WINAPI device_statics_CreateWatcherDeviceClass( IDeviceInformatio 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 ); + return IDeviceInformationStatics_CreateWatcherAqsFilterAndAdditionalProperties( iface, filter, NULL, watcher ); }
static HRESULT WINAPI device_statics_CreateWatcherAqsFilterAndAdditionalProperties( IDeviceInformationStatics *iface, HSTRING filter, IIterable_HSTRING *additional_properties, IDeviceWatcher **watcher ) { - FIXME( "iface %p, aqs %p, additional_properties %p, watcher %p stub!\n", iface, debugstr_hstring(filter), additional_properties, watcher ); - return E_NOTIMPL; + TRACE( "iface %p, aqs %s, additional_properties %p, watcher %p\n", iface, debugstr_hstring(filter), additional_properties, watcher ); + return device_watcher_create( filter, additional_properties, DeviceInformationKind_DeviceInterface, watcher ); }
static const struct IDeviceInformationStaticsVtbl device_statics_vtbl = @@ -791,13 +896,30 @@ static HRESULT WINAPI device_statics2_FindAllAsync( IDeviceInformationStatics2 * return E_NOTIMPL; }
+static const char *debugstr_DeviceInformationKind( DeviceInformationKind kind ) +{ + static const char *str[] = { + "Unknown", + "DeviceInterface", + "DeviceContainer", + "Device", + "DeviceInterfaceClass", + "AssociationEndpoint", + "AssociationEndpointContainer", + "AssociationEndpointService", + "DevicePanel", + }; + if (kind < ARRAY_SIZE( str )) return wine_dbg_sprintf( "DeviceInformationKind_%s", str[kind] ); + return wine_dbg_sprintf( "(unknown %u)\n", kind ); +} + static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 *iface, HSTRING filter, IIterable_HSTRING *additional_properties, DeviceInformationKind kind, IDeviceWatcher **watcher ) { - FIXME( "iface %p, filter %s, additional_properties %p, kind %u, watcher %p semi-stub!\n", - iface, debugstr_hstring( filter ), additional_properties, kind, watcher ); - return device_watcher_create( filter, watcher ); + TRACE( "iface %p, filter %s, additional_properties %p, kind %s, watcher %p\n", + iface, debugstr_hstring( filter ), additional_properties, debugstr_DeviceInformationKind( kind ), watcher ); + return device_watcher_create( filter, additional_properties, kind, 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 e29122cb242..a4d33923a2c 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -1005,36 +1005,30 @@ static void test_DeviceInformation( void ) IVectorView_DeviceInformation_Release( info_collection );
hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, NULL, &info_collection_async ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr );
- if (SUCCEEDED( hr )) - { - await_device_information_collection( info_collection_async ); - check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); - IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); - test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) - 1 ); - IVectorView_DeviceInformation_Release( info_collection ); - } + await_device_information_collection( info_collection_async ); + check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); + IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) - 1 ); + IVectorView_DeviceInformation_Release( info_collection );
additional_props = iterable_hstring_create( device_iface_additional_props, ARRAY_SIZE( device_iface_additional_props ) ); hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); IIterable_HSTRING_Release( additional_props ); - if (SUCCEEDED( hr )) - { - await_device_information_collection( info_collection_async ); - check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); - IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); - test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) ); - IVectorView_DeviceInformation_Release( info_collection ); - } + await_device_information_collection( info_collection_async ); + check_device_information_collection_async_no_id( info_collection_async, Completed, S_OK, &info_collection ); + IAsyncOperation_DeviceInformationCollection_Release( info_collection_async ); + test_DeviceInformationCollection( __LINE__, info_collection, device_iface_exp_props, ARRAY_SIZE( device_iface_exp_props ) ); + IVectorView_DeviceInformation_Release( info_collection );
for (i = 0; i < ARRAY_SIZE( device_nonexistent_props ); i++ ) { winetest_push_context( "device_nonexistent_props[%d]", i ); additional_props = iterable_hstring_create( &device_nonexistent_props[i], 1 ); hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); - todo_wine ok( hr == TYPE_E_ELEMENTNOTFOUND, "got hr %#lx\n", hr ); + ok( hr == TYPE_E_ELEMENTNOTFOUND, "got hr %#lx\n", hr ); IIterable_HSTRING_Release( additional_props ); winetest_pop_context(); } @@ -1044,7 +1038,7 @@ static void test_DeviceInformation( void ) winetest_push_context( "device_invalid_props[%d]", i ); additional_props = iterable_hstring_create( &device_invalid_props[i], 1 ); hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( device_info_statics, NULL, additional_props, &info_collection_async ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx\n", hr ); + ok( hr == E_INVALIDARG, "got hr %#lx\n", hr ); IIterable_HSTRING_Release( additional_props ); winetest_pop_context(); } @@ -1371,7 +1365,7 @@ static void test_aqs_filters( void ) hr = WindowsCreateString( filter_iface_display, wcslen( filter_iface_display ), &str ); ok( hr == S_OK, "got hr %#lx\n", hr ); hr = IDeviceInformationStatics_FindAllAsyncAqsFilterAndAdditionalProperties( statics, str, props_iterable, &info_collection_async ); - todo_wine ok( hr == S_OK, "got hr %#lx\n", hr ); + ok( hr == S_OK, "got hr %#lx\n", hr ); WindowsDeleteString( str ); IIterable_HSTRING_Release( props_iterable ); if (SUCCEEDED( hr ))
 
            Rémi Bernon (@rbernon) commented about dlls/windows.devices.enumeration/main.c:
const WCHAR *buf;
HSTRING name;
if (FAILED(hr = IIterator_HSTRING_get_Current( names, &name ))) break;
buf = WindowsGetStringRawBuffer( name, NULL );
if (buf[0] == '{')
hr = PSPropertyKeyFromString( buf, (PROPERTYKEY *)&key.Key );
else
hr = PSGetPropertyKeyFromName( buf, (PROPERTYKEY *)&key.Key );
WindowsDeleteString( name );
if (FAILED(hr)) break;
/* DevGetObjects(Ex) will not de-duplicate properties, so we need to do it ourselves. */
if (!devpropcompkey_buf_find_devpropkey( *keys, *keys_len, key.Key ))
{
(*keys)[*keys_len] = key;
*keys_len += 1;
Fwiw the reason I did it with a local variable is because as a general rule I think it's better to avoid accessing/writing to pointers within a loop. I also find it more readable to have the results of a computation only written at some specific sucesss/failure points rather than being spread around, and it could be arguably incorrect to return a failure while still having modified the array. Shouldn't matter much here anyway.
 
            On Fri Oct 3 11:36:12 2025 +0000, Vibhav Pant wrote:
But are there actual cases of device properties not known by propsys?
Hm, It depends on what you mean by "actual cases". It's definitely possible to set a custom property key for a device/device interface that is not known to propsys. Every property key in `devpropkey.h` has an associated canonical name, so the custom property syntax is meant for properties that aren't registered with propsys.
Yes, but is this going to ever happen in practice? I don't want to mind much but in general I think we can and should avoid special cases where it's never going to be needed. Sure, in theory drivers could add custom properties, but we are not very likely going to ever support actual drivers in Wine.
 
            This merge request was approved by Rémi Bernon.
 
            Alexandre Julliard (@julliard) commented about dlls/windows.devices.enumeration/main.c:
IDeviceWatcher_Release( iface );}
+static const DEVPROPCOMPKEY device_iface_default_props[] = +{
- { DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL },
- { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL },
+};
I'm afraid not all compilers support that kind of thing:
``` ../wine/dlls/windows.devices.enumeration/main.c:372:7: error: initializer element is not a compile-time constant make: *** [Makefile:191506: dlls/windows.devices.enumeration/main.o] Error 1 ```
(clang in this case).
 
            On Tue Oct 7 11:44:39 2025 +0000, Rémi Bernon wrote:
Fwiw the reason I did it with a local variable is because as a general rule I think it's better to avoid accessing/writing to pointers within a loop. I also find it more readable to have the results of a computation only written at some specific sucesss/failure points rather than being spread around, and it could be arguably incorrect to return a failure while still having modified the array (which I indeed did as well in my suggestion, but that could more easily be changed). Shouldn't matter much here anyway.
Ah, fair. Rewrote the function, thanks.
 
            On Tue Oct 7 18:15:40 2025 +0000, Alexandre Julliard wrote:
I'm afraid not all compilers support that kind of thing:
../wine/dlls/windows.devices.enumeration/main.c:372:7: error: initializer element is not a compile-time constant make: *** [Makefile:191506: dlls/windows.devices.enumeration/main.o] Error 1(clang in this case).
Oh well, changed to make `device_iface_default_props` a local constant in the functions its used.



