From: Vibhav Pant vibhavp@gmail.com
--- dlls/windows.devices.enumeration/Makefile.in | 2 +- .../windows.devices.enumeration/information.c | 26 +++- dlls/windows.devices.enumeration/main.c | 129 +++++++++++++++--- dlls/windows.devices.enumeration/private.h | 4 +- .../tests/devices.c | 2 +- 5 files changed, 137 insertions(+), 26 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 afff96c9894..6673f954025 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,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(enumeration); struct devinfo_DeviceInterface { IDeviceInformation IDeviceInformation_iface; + + HSTRING path; LONG ref; };
@@ -78,7 +82,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 +115,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 +197,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 4ea1555c8fc..73130a28f87 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -342,39 +342,128 @@ static HRESULT WINAPI findall_async( IUnknown *invoker, IUnknown *param, PROPVAR .iterable = &IID_IIterable_DeviceInformation, .iterator = &IID_IIterator_DeviceInformation, }; - IVectorView_DeviceInformation *view; - IDeviceInformation *device; IVector_IInspectable *vector; + HKEY iface_key; HRESULT hr = S_OK; + 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 );
- hr = deviceinformation_iface_create( &device ); + hr = vector_create( &iids, (void *)&vector ); if (FAILED( hr )) return hr;
- hr = vector_create( &iids, (void *)&vector ); - 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++) { - IDeviceInformation_Release( device ); - 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] ); + 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; + + hr = IVector_IInspectable_Append( vector, (IInspectable *)info ); + if (FAILED( hr )) + { + IVector_IInspectable_Release( vector ); + break; + } + } }
- hr = IVector_IInspectable_Append( vector, (IInspectable *)device ); - IDeviceInformation_Release( device ); - if (FAILED( hr )) + if (SUCCEEDED( hr )) { + IVectorView_DeviceInformation *view; + hr = IVector_IInspectable_GetView( vector, (void *)&view ); IVector_IInspectable_Release( vector ); - return hr; + if (SUCCEEDED( hr )) + { + result->vt = VT_UNKNOWN; + result->punkVal = (IUnknown *)view; + } } - - hr = IVector_IInspectable_GetView( vector, (void *)&view ); - IVector_IInspectable_Release( vector ); - if (FAILED( hr )) - return hr; - - result->vt = VT_UNKNOWN; - result->punkVal = (IUnknown *)view; + RegCloseKey( iface_key ); return hr; }
diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h index 802163a2027..c7a8191e02c 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"
@@ -59,7 +60,8 @@ extern HRESULT async_operation_device_info_collection_result_create( IUnknown *invoker, IUnknown *param, async_operation_callback callback, IAsyncOperation_DeviceInformationCollection **out ); extern HRESULT vector_create( const struct vector_iids *iids, void **out ); -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 64733cc5096..0954cc9cd44 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -492,7 +492,7 @@ static void test_DeviceInformation( void ) ok( hr == S_OK, "got %#lx\n", hr ); if (SUCCEEDED( hr )) { - todo_wine test_DeviceInformation_obj(__LINE__, info); + test_DeviceInformation_obj(__LINE__, info); IDeviceInformation_Release( info ); } winetest_pop_context();