From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/Makefile.in | 2 +- .../windows.devices.enumeration/information.c | 28 +++- dlls/windows.devices.enumeration/main.c | 130 ++++++++++++++++-- dlls/windows.devices.enumeration/private.h | 4 +- .../tests/devices.c | 2 +- 5 files changed, 145 insertions(+), 21 deletions(-)
diff --git a/dlls/windows.devices.enumeration/Makefile.in b/dlls/windows.devices.enumeration/Makefile.in index 062a914e322..ba3bc7a4b6c 100644 --- a/dlls/windows.devices.enumeration/Makefile.in +++ b/dlls/windows.devices.enumeration/Makefile.in @@ -1,5 +1,5 @@ MODULE = windows.devices.enumeration.dll -IMPORTS = combase uuid +IMPORTS = advapi32 combase setupapi uuid
SOURCES = \ access.c \ diff --git a/dlls/windows.devices.enumeration/information.c b/dlls/windows.devices.enumeration/information.c index 1d9cedf66e5..82e1f6197ee 100644 --- a/dlls/windows.devices.enumeration/information.c +++ b/dlls/windows.devices.enumeration/information.c @@ -20,6 +20,8 @@ #include "private.h"
#include <roapi.h> +#include <setupapi.h> +#include <cfgmgr32.h>
#include <wine/debug.h> #include <wine/rbtree.h> @@ -30,6 +32,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(enumeration); struct devinfo_DeviceInterface { IDeviceInformation IDeviceInformation_iface; + + WCHAR instance_id[MAX_DEVICE_ID_LEN]; + + HSTRING path; LONG ref; };
@@ -78,7 +84,10 @@ static ULONG STDMETHODCALLTYPE devinfo_DeviceInterface_Release( IDeviceInformati impl = impl_DeviceInterface_from_IDeviceInformation( iface ); ref = InterlockedDecrement( &impl->ref ); if (!ref) + { + WindowsDeleteString( impl->path ); free( impl ); + }
return ref; } @@ -108,8 +117,12 @@ static HRESULT STDMETHODCALLTYPE device_information_GetTrustLevel(
static HRESULT STDMETHODCALLTYPE devinfo_DeviceInterface_get_Id( IDeviceInformation *iface, HSTRING *id ) { - FIXME( "(%p, %p) stub!\n", iface, id ); - return E_NOTIMPL; + struct devinfo_DeviceInterface *impl; + + TRACE( "(%p, %p)\n", iface, id ); + + impl = impl_DeviceInterface_from_IDeviceInformation( iface ); + return WindowsDuplicateString( impl->path, id ); }
static HRESULT STDMETHODCALLTYPE devinfo_DeviceInterface_get_Name( IDeviceInformation *iface, HSTRING *name ) @@ -186,15 +199,24 @@ static const struct IDeviceInformationVtbl devinfo_DeviceInterface_vtbl = { devinfo_DeviceInterface_GetGlyphThumbnailAsync, };
-HRESULT deviceinformation_iface_create( IDeviceInformation **info ) +HRESULT deviceinformation_iface_create( const SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail, + IDeviceInformation **info ) { struct devinfo_DeviceInterface *impl; + HRESULT res;
impl = calloc( 1, sizeof( *impl ) ); if (!impl) return E_OUTOFMEMORY;
impl->IDeviceInformation_iface.lpVtbl = &devinfo_DeviceInterface_vtbl; + res = WindowsCreateString( iface_detail->DevicePath, wcslen( iface_detail->DevicePath ), + &impl->path ); + if (FAILED( res )) + { + free( impl ); + return res; + } impl->ref = 1; *info = &impl->IDeviceInformation_iface; return S_OK; diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 8b198387155..3bdfb8dba8b 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -335,34 +335,134 @@ static HRESULT WINAPI device_statics_CreateFromIdAsyncAdditionalProperties( IDev
static HRESULT WINAPI findall_async( IUnknown *invoker, IUnknown *param, PROPVARIANT *result ) { - IDeviceInformation **devices; - IVectorView_DeviceInformation *view; + IDeviceInformation **devices = NULL; + HKEY iface_key; HRESULT hr = S_OK; + SIZE_T devices_len = 0; + DWORD i;
- FIXME( "invoker %p, param %p, result %p semi-stub!\n", invoker, param, result ); + TRACE( "invoker %p, param %p, result %p\n", invoker, param, result );
- devices = calloc( 1, sizeof( *devices ) ); - if (!devices) - return E_OUTOFMEMORY; - - hr = deviceinformation_iface_create( &devices[0] ); - if (FAILED( hr )) + iface_key = + SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ); + if (!iface_key) + return HRESULT_FROM_WIN32( GetLastError() ); + for (i = 0;SUCCEEDED( hr );i++) { - free( devices ); - return hr; + WCHAR keyName[40]; + DWORD keylen = 40; + GUID iface_class; + LSTATUS ret; + HDEVINFO devinfo; + DWORD j; + + ret = RegEnumKeyExW( iface_key, i, keyName, &keylen, NULL, NULL, NULL, NULL ); + if (ret == ERROR_NO_MORE_ITEMS) + break; + else if (ret) + { + hr = HRESULT_FROM_WIN32( ret ); + break; + } + hr = CLSIDFromString( keyName, &iface_class ); + if (FAILED( hr )) + { + ERR( "Could not parse interface GUID string %s: %#lx\n", debugstr_w( keyName ), hr ); + continue; + } + + devinfo = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); + if (devinfo == INVALID_HANDLE_VALUE) + { + DWORD err = GetLastError(); + ERR( "Could not get device list for interface %s: %lu\n", debugstr_guid( &iface_class ), err ); + hr = HRESULT_FROM_WIN32( err ); + break; + } + + for (j = 0; ;j++) + { + + SP_DEVICE_INTERFACE_DATA iface_data = {0}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail_data; + SIZE_T size = + offsetof( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH + 1] ); + void *addr; + BOOL success; + IDeviceInformation *info; + + iface_data.cbSize = sizeof( iface_data ); + iface_detail_data = malloc( size ); + if (!iface_detail_data) + { + + hr = E_OUTOFMEMORY; + break; + } + iface_detail_data->cbSize = sizeof( *iface_detail_data ); + + success = SetupDiEnumDeviceInterfaces( devinfo, NULL, &iface_class, j, + &iface_data ); + if (!success) + { + + DWORD err = GetLastError(); + free( iface_detail_data ); + + if (err == ERROR_NO_MORE_ITEMS) + break; + ERR( "Could not enumerate device interfaces: %lu\n", err ); + hr = HRESULT_FROM_WIN32( err ); + break; + } + + success = SetupDiGetDeviceInterfaceDetailW( devinfo, &iface_data, iface_detail_data, + size, NULL, NULL ); + if (!success) + { + + DWORD err = GetLastError(); + free( iface_detail_data ); + ERR( "Could not get interface details for %s: %lu\n", + debugstr_guid( &iface_class ), err ); + hr = HRESULT_FROM_WIN32( err ); + break; + } + + hr = deviceinformation_iface_create( iface_detail_data, &info ); + free( iface_detail_data ); + if (FAILED( hr )) + break; + + addr = realloc( devices, sizeof( *devices ) * (devices_len + 1) ); + if (!addr) + { + IDeviceInformation_Release( info ); + hr = E_OUTOFMEMORY; + break; + } + devices = addr; + devices[devices_len++] = info; + } }
- hr = vectorview_deviceinformation_create( devices, 1, &view ); if (SUCCEEDED( hr )) { - result->vt = VT_UNKNOWN; - result->punkVal = (IUnknown *)view; + IVectorView_DeviceInformation *view; + hr = vectorview_deviceinformation_create( devices, devices_len, &view ); + if (SUCCEEDED( hr )) + { + result->vt = VT_UNKNOWN; + result->punkVal = (IUnknown *)view; + } } else { - IDeviceInformation_Release( devices[0] ); + while (devices_len--) + IDeviceInformation_Release( devices[devices_len] ); free( devices ); } + RegCloseKey( iface_key ); return hr; }
diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h index fccae4cea41..71fed550a55 100644 --- a/dlls/windows.devices.enumeration/private.h +++ b/dlls/windows.devices.enumeration/private.h @@ -28,6 +28,7 @@ #include "winbase.h" #include "winstring.h" #include "objbase.h" +#include "setupapi.h"
#include "activation.h"
@@ -52,7 +53,8 @@ extern HRESULT async_operation_device_info_collection_result_create( IAsyncOperation_DeviceInformationCollection **out ); extern HRESULT vectorview_deviceinformation_create( IDeviceInformation **devices, SIZE_T len, IVectorView_DeviceInformation **view ); -extern HRESULT deviceinformation_iface_create( IDeviceInformation **info ); +extern HRESULT deviceinformation_iface_create( const SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail, + 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 3a685addab2..d1261e299b7 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -497,7 +497,7 @@ static void test_DeviceInformation( void ) UINT32 idx2 = 0; boolean found = FALSE;
- todo_wine test_DeviceInformation_obj(__LINE__, info); + test_DeviceInformation_obj(__LINE__, info); IDeviceInformation_Release( info ); hr = IVectorView_DeviceInformation_IndexOf( info_collection, info, &idx2, &found ); todo_wine ok( SUCCEEDED( hr ), "got %#lx\n", hr );