diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index dc0e5ff5f2a..4e406fe700e 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -4499,10 +4499,114 @@ BOOL WINAPI SetupDiGetDevicePropertyKeys( HDEVINFO devinfo, PSP_DEVINFO_DATA dev DEVPROPKEY *prop_keys, DWORD prop_keys_len, DWORD *required_prop_keys, DWORD flags ) { - FIXME( "%p, %p, %p, %lu, %p, %#lx stub!\n", devinfo, device_data, prop_keys, prop_keys_len, + struct device *device; + DWORD count = 0, i; + HKEY hkey; + LSTATUS ls; + DEVPROPKEY *keys_buf = NULL; + + TRACE( "%p, %p, %p, %lu, %p, %#lx\n", devinfo, device_data, prop_keys, prop_keys_len, required_prop_keys, flags); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + + if (flags) + { + SetLastError( ERROR_INVALID_FLAGS ); + return FALSE; + } + if (!prop_keys && prop_keys_len) + { + SetLastError( ERROR_INVALID_USER_BUFFER ); + return FALSE; + } + + device = get_device( devinfo, device_data ); + if (!device) + return FALSE; + + ls = RegOpenKeyExW( device->key, L"Properties", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ); + if (ls) + { + SetLastError( ls ); + return FALSE; + } + + keys_buf = malloc( sizeof( *keys_buf ) * prop_keys_len ); + if (!keys_buf && prop_keys_len) + { + RegCloseKey( hkey ); + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + for (i = 0; ;i++) + { + WCHAR guid_str[39]; + HKEY propkey; + DWORD len, j; + GUID prop_guid; + + len = ARRAY_SIZE( guid_str ); + ls = RegEnumKeyExW( hkey, i, guid_str, &len, NULL, NULL, NULL, NULL ); + if (ls) + { + if (ls == ERROR_NO_MORE_ITEMS) + ls = ERROR_SUCCESS; + else + ERR( "Could not enumerate subkeys for device %s: %lu\n", + debugstr_w( device->instanceId ), ls ); + break; + } + ls = RegOpenKeyExW( hkey, guid_str, 0, KEY_ENUMERATE_SUB_KEYS, &propkey ); + if (ls) + break; + guid_str[37] = 0; + if (UuidFromStringW( &guid_str[1], &prop_guid )) + { + ERR( "Could not parse propkey GUID string %s\n", debugstr_w( &guid_str[1] ) ); + RegCloseKey( propkey ); + continue; + } + for (j = 0; ;j++) + { + DEVPROPID pid; + WCHAR key_name[6]; + + len = 5; + ls = RegEnumKeyExW( propkey, j, key_name, &len, NULL, NULL, NULL, NULL ); + if (ls) + { + if (ls != ERROR_NO_MORE_ITEMS) + ERR( "Could not enumerate subkeys for device %s under %s: %lu\n", debugstr_w( device->instanceId ), + debugstr_guid( &prop_guid ), ls ); + break; + } + swscanf( key_name, L"%04X", &pid ); + if (++count <= prop_keys_len) + { + keys_buf[count-1].fmtid = prop_guid; + keys_buf[count-1].pid = pid; + } + } + RegCloseKey( propkey ); + } + + RegCloseKey( hkey ); + if (!ls) + { + if (required_prop_keys) + *required_prop_keys = count; + + if (prop_keys_len < count) + { + free( keys_buf ); + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + memcpy( prop_keys, keys_buf, count * sizeof( *keys_buf ) ); + } + free( keys_buf ); + SetLastError( ls ); + return !ls; } /*********************************************************************** diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 3ba71e86d3f..c5c0114b2b7 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -1200,61 +1200,61 @@ static void test_device_property(void) ret = pSetupDiGetDevicePropertyKeys(NULL, NULL, NULL, 0, NULL, 0); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INVALID_HANDLE, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INVALID_HANDLE, "Expect last error %#x, got %#lx\n", ERROR_INVALID_HANDLE, err); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, NULL, NULL, 0, NULL, 0); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INVALID_PARAMETER, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INVALID_PARAMETER, "Expect last error %#x, got %#lx\n", ERROR_INVALID_PARAMETER, err); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 10, NULL, 0); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INVALID_USER_BUFFER, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INVALID_USER_BUFFER, "Expect last error %#x, got %#lx\n", ERROR_INVALID_USER_BUFFER, err); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, NULL, 0); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n", ERROR_INSUFFICIENT_BUFFER, err); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, &keys_len, 0xdeadbeef); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n", ERROR_INVALID_FLAGS, err); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, &device_data, NULL, 0, &keys_len, 0); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INSUFFICIENT_BUFFER, "Expect last error %#x, got %#lx\n", ERROR_INSUFFICIENT_BUFFER, err); keys = calloc(keys_len, sizeof(*keys)); - todo_wine ok(keys_len && !!keys, "Failed to allocate buffer\n"); + ok(keys_len && !!keys, "Failed to allocate buffer\n"); SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyKeys(set, &device_data, keys, keys_len, &keys_len, 0xdeadbeef); ok(!ret, "Expect failure\n"); err = GetLastError(); - todo_wine ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n", + ok(err == ERROR_INVALID_FLAGS, "Expect last error %#x, got %#lx\n", ERROR_INVALID_FLAGS, err); required_len = 0xdeadbeef; ret = SetupDiGetDevicePropertyKeys(set, &device_data, keys, keys_len, &required_len, 0); - todo_wine ok(ret, "Expect success\n"); + ok(ret, "Expect success\n"); err = GetLastError(); - todo_wine ok(!err, "Expect last error %#x, got %#lx\n", ERROR_SUCCESS, err); - todo_wine ok(keys_len == required_len, "%lu != %lu\n", keys_len, required_len); - todo_wine ok(keys_len >= expected_keys, "Expected %lu >= %lu\n", keys_len, expected_keys); + ok(!err, "Expect last error %#x, got %#lx\n", ERROR_SUCCESS, err); + ok(keys_len == required_len, "%lu != %lu\n", keys_len, required_len); + ok(keys_len >= expected_keys, "Expected %lu >= %lu\n", keys_len, expected_keys); keys_len = 0; if (keys) @@ -1266,7 +1266,7 @@ static void test_device_property(void) } } - todo_wine ok(keys_len == expected_keys, "%lu != %lu\n", keys_len, expected_keys); + ok(keys_len == expected_keys, "%lu != %lu\n", keys_len, expected_keys); free(keys); } else