From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 86 ++++++++++++++++++++++++++++++++++ dlls/cfgmgr32/cfgmgr32.spec | 4 +- dlls/cfgmgr32/tests/cfgmgr32.c | 80 ++++++++++++++++++++++++++++++- 3 files changed, 167 insertions(+), 3 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index db9b65e9acb..af03d245559 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -476,6 +476,58 @@ static LSTATUS get_device_interface_property( const struct device_interface *ifa return err; } +static LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ) +{ + ULONG capacity = *size, count = 0; + LSTATUS err = ERROR_SUCCESS; + WCHAR path[MAX_PATH]; + HKEY props_key; + + if (capacity < ++count || !buffer) err = ERROR_MORE_DATA; + else buffer[count - 1] = DEVPKEY_DeviceInterface_Enabled; + if (capacity < ++count || !buffer) err = ERROR_MORE_DATA; + else buffer[count - 1] = DEVPKEY_Device_InstanceId; + if (capacity < ++count || !buffer) err = ERROR_MORE_DATA; + else buffer[count - 1] = DEVPKEY_DeviceInterface_ClassGuid; + + for (UINT i = 0; i < ARRAY_SIZE(device_interface_properties); i++) + { + const struct property_desc *desc = device_interface_properties + i; + if (desc->name && !RegQueryValueExW( hkey, desc->name, NULL, NULL, NULL, NULL )) + { + if (capacity < ++count || !buffer) err = ERROR_MORE_DATA; + else buffer[count - 1] = *desc->key; + } + } + + swprintf( path, ARRAY_SIZE(path), L"%s\\Properties", iface->refstr ); + if (!open_key( hkey, path, KEY_ENUMERATE_SUB_KEYS, TRUE, &props_key )) + { + WCHAR name[MAX_PATH]; + for (ULONG i = 0, len = ARRAY_SIZE(name); !RegEnumValueW( props_key, i, name, &len, 0, NULL, NULL, NULL ); i++, len = ARRAY_SIZE(name)) + { + if (capacity < ++count || !buffer) err = ERROR_MORE_DATA; + else err = propkey_from_string( name, buffer + count - 1 ); + } + RegCloseKey( props_key ); + } + + *size = count; + return err; +} + +static LSTATUS get_device_interface_property_keys( const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ) +{ + LSTATUS err; + HKEY hkey; + + if ((err = open_device_interface_key( iface, KEY_ALL_ACCESS, TRUE, &hkey ))) return err; + err = enum_device_interface_property_keys( hkey, iface, buffer, size ); + RegCloseKey( hkey ); + + return err; +} + static CONFIGRET map_error( LSTATUS err ) { switch (err) @@ -994,3 +1046,37 @@ CONFIGRET WINAPI CM_Get_Device_Interface_PropertyW( const WCHAR *iface, const DE { return CM_Get_Device_Interface_Property_ExW( iface, key, type, buffer, size, flags, NULL ); } + +/*********************************************************************** + * CM_Get_Device_Interface_Property_Keys_ExW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Device_Interface_Property_Keys_ExW( const WCHAR *name, DEVPROPKEY *buffer, ULONG *size, ULONG flags, HMACHINE machine ) +{ + struct device_interface iface; + LSTATUS err; + + TRACE( "name %s, buffer %p, size %p, flags %#lx\n", debugstr_w(name), buffer, size, flags); + if (machine) FIXME( "machine %p not implemented!\n", machine ); + if (flags) FIXME( "flags %#lx not implemented!\n", flags ); + + if (!name || !size) return CR_INVALID_POINTER; + if (*size && !buffer) return CR_INVALID_POINTER; + if (init_device_interface( &iface, name )) + { + *size = 0; + return CR_INVALID_DATA; + } + + err = get_device_interface_property_keys( &iface, buffer, size ); + if (err && err != ERROR_MORE_DATA) *size = 0; + if (err == ERROR_FILE_NOT_FOUND) return CR_NO_SUCH_DEVICE_INTERFACE; + return map_error( err ); +} + +/*********************************************************************** + * CM_Get_Device_Interface_Property_KeysW (cfgmgr32.@) + */ +CONFIGRET WINAPI CM_Get_Device_Interface_Property_KeysW( const WCHAR *iface, DEVPROPKEY *keys, ULONG *count, ULONG flags ) +{ + return CM_Get_Device_Interface_Property_Keys_ExW( iface, keys, count, flags, NULL ); +} diff --git a/dlls/cfgmgr32/cfgmgr32.spec b/dlls/cfgmgr32/cfgmgr32.spec index e2d4c029a01..2aee10c2672 100644 --- a/dlls/cfgmgr32/cfgmgr32.spec +++ b/dlls/cfgmgr32/cfgmgr32.spec @@ -122,8 +122,8 @@ @ stdcall CM_Get_Device_Interface_List_Size_ExW(ptr ptr wstr long ptr) @ stdcall CM_Get_Device_Interface_PropertyW(wstr ptr ptr ptr ptr long) @ stdcall CM_Get_Device_Interface_Property_ExW(wstr ptr ptr ptr ptr long ptr) -@ stub CM_Get_Device_Interface_Property_KeysW -@ stub CM_Get_Device_Interface_Property_Keys_ExW +@ stdcall CM_Get_Device_Interface_Property_KeysW(wstr ptr ptr long) +@ stdcall CM_Get_Device_Interface_Property_Keys_ExW(wstr ptr ptr long ptr) @ stub CM_Get_First_Log_Conf @ stub CM_Get_First_Log_Conf_Ex @ stub CM_Get_Global_State diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 9e6a75c2e4a..6002a3fe64b 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -607,6 +607,83 @@ static void test_CM_Get_Device_Interface_Property_setupapi(void) ok(ret == CR_NO_SUCH_DEVICE_INTERFACE || broken(ret == CR_INVALID_DATA) /* w7 */, "got %#lx.\n", ret); } +static void test_CM_Get_Device_Interface_Property_Keys(void) +{ + DEVPROPKEY buffer[128]; + DEVINSTID_W iface; + CONFIGRET ret; + WCHAR *tmp; + ULONG size; + GUID guid; + + guid = GUID_DEVINTERFACE_HID; + ret = CM_Get_Device_Interface_List_SizeW( &size, &guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ); + ok_x4( ret, ==, CR_SUCCESS ); + iface = malloc( size * sizeof(*iface) ); + ok_ptr( iface, !=, NULL ); + ret = CM_Get_Device_Interface_ListW( &guid, NULL, iface, size, CM_GET_DEVICE_INTERFACE_LIST_PRESENT ); + ok_x4( ret, ==, CR_SUCCESS ); + + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( NULL, buffer, &size, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( size, ==, sizeof(buffer) ); + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( L"qqq", buffer, &size, 0 ); + ok_x4( ret, ==, CR_INVALID_DATA ); + ok_u4( size, ==, 0 ); + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, NULL, NULL, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, NULL, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, NULL, &size, 0 ); + ok_x4( ret, ==, CR_INVALID_POINTER ); + ok_u4( size, ==, sizeof(buffer) ); + size = 0; + ret = CM_Get_Device_Interface_Property_KeysW( iface, NULL, &size, 0 ); + ok_x4( ret, ==, CR_BUFFER_SMALL ); + todo_wine ok( size == 10 || broken(size == 11), "got %#lx\n", size ); + size = sizeof(buffer); + memset( buffer, 0xcd, sizeof(buffer) ); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, &size, 0 ); + ok_x4( ret, ==, CR_SUCCESS ); + todo_wine ok( size == 10 || broken(size == 11), "got %#lx\n", size ); + ok( !memcmp( buffer + 0, &DEVPKEY_DeviceInterface_Enabled, sizeof(*buffer) ), "got {%s,%#lx}\n", debugstr_guid( &buffer[0].fmtid ), buffer[0].pid ); + ok( !memcmp( buffer + 1, &DEVPKEY_Device_InstanceId, sizeof(*buffer) ), "got {%s,%#lx}\n", debugstr_guid( &buffer[1].fmtid ), buffer[1].pid ); + ok( !memcmp( buffer + 2, &DEVPKEY_DeviceInterface_ClassGuid, sizeof(*buffer) ), "got {%s,%#lx}\n", debugstr_guid( &buffer[2].fmtid ), buffer[2].pid ); + todo_wine ok( !memcmp( buffer + 3, &DEVPKEY_Device_ContainerId, sizeof(*buffer) ), "got {%s,%#lx}\n", debugstr_guid( &buffer[3].fmtid ), buffer[3].pid ); + + tmp = wcsrchr( iface, '{' ); + tmp[1] = '6'; + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, &size, 0 ); + ok_x4( ret, ==, CR_NO_SUCH_DEVICE_INTERFACE ); + tmp[1] = '5'; + + tmp[0] = '.'; + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, &size, 0 ); + ok_x4( ret, ==, CR_INVALID_DATA ); + tmp[0] = '{'; + + tmp[-1] = 0; + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, &size, 0 ); + ok_x4( ret, ==, CR_INVALID_DATA ); + tmp[-1] = '#'; + + tmp[-2]++; + size = sizeof(buffer); + ret = CM_Get_Device_Interface_Property_KeysW( iface, buffer, &size, 0 ); + ok_x4( ret, ==, CR_NO_SUCH_DEVICE_INTERFACE ); + tmp[-2]--; + + free( iface ); +} + static void test_CM_Get_Device_Interface_PropertyW(void) { WCHAR expect[MAX_PATH]; @@ -2817,10 +2894,11 @@ START_TEST(cfgmgr32) test_CM_Get_Device_Interface_List_Size(); test_CM_Get_Device_Interface_List(); test_CM_Open_Device_Interface_Key(); + test_CM_Get_Device_Interface_Property_Keys(); test_CM_Get_Device_Interface_PropertyW(); + test_CM_Get_Device_Interface_Property_setupapi(); test_CM_Get_Device_ID_List(); test_CM_Register_Notification(); - test_CM_Get_Device_Interface_Property_setupapi(); test_DevGetObjects(); test_DevCreateObjectQuery(); test_DevGetObjectProperties_invalid(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10148