From: Vibhav Pant vibhavp@gmail.com
--- .../windows.devices.enumeration/information.c | 188 ++++++++++++++++-- dlls/windows.devices.enumeration/main.c | 22 +- dlls/windows.devices.enumeration/private.h | 5 +- .../tests/devices.c | 2 +- 4 files changed, 195 insertions(+), 22 deletions(-)
diff --git a/dlls/windows.devices.enumeration/information.c b/dlls/windows.devices.enumeration/information.c index c09a9ea37ef..6047412f19f 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,179 @@ 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 ); + + if (FAILED(hr = WindowsCreateStringReference( propertyset_name, wcslen( propertyset_name ), &hdr, &str ))) return hr; + 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; + + if (FAILED(hr = WindowsCreateStringReference( propertyvalue_name, wcslen( propertyvalue_name ), &hdr, &str ))) goto done; + if (FAILED(hr = RoGetActivationFactory( str, &IID_IPropertyValueStatics, (void **)&propval_statics ))) goto done; + + for (i = 0; i < len; i++) + { + const DEVPROPERTY *prop = &props[i]; + const DEVPROPKEY *propkey = &prop->CompKey.Key; + HSTRING canonical_name; + IInspectable *val; + boolean replaced; + WCHAR *name; + + 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 (FAILED(hr)) break; + + 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: + { + if (SUCCEEDED(hr = WindowsCreateString( prop->Buffer, wcslen( prop->Buffer ), &str ))) + { + hr = IPropertyValueStatics_CreateString( propval_statics, str, &val ); + WindowsDeleteString( str ); + } + break; + } + default: + FIXME("Unsupported DEVPROPTYPE: %#lx\n", prop->Type ); + WindowsDeleteString( canonical_name ); + continue; + } + if (FAILED(hr)) + { + WindowsDeleteString( canonical_name ); + break; + } + + hr = IMap_HSTRING_IInspectable_Insert( *map, canonical_name, val, &replaced ); + IInspectable_Release( val ); + WindowsDeleteString( canonical_name ); + if (FAILED(hr)) break; + } + +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 9e4cc378c75..a646a41073b 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -701,7 +701,7 @@ static void test_DeviceInformation_obj( int line, IDeviceInformation *info, cons hr = IDeviceInformation_get_IsDefault( info, &bool_val ); todo_wine ok_(__FILE__, line)( hr == S_OK, "get_IsDefault failed, got hr %#lx\n", hr ); hr = IDeviceInformation_get_Properties( info, &properties ); - todo_wine ok_(__FILE__, line)( hr == S_OK, "get_Properties failed, got hr %#lx\n", hr ); + ok_(__FILE__, line)( hr == S_OK, "get_Properties failed, got hr %#lx\n", hr ); if (FAILED(hr)) { WindowsDeleteString( id );