From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 26 +++--- dlls/setupapi/devinst.c | 131 +++++++++++++++++++++++++++-- dlls/setupapi/tests/devinst.c | 26 +++--- 3 files changed, 149 insertions(+), 34 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 60cc530240e..1822923e552 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1696,30 +1696,30 @@ static void test_pnp_devices(void) memset(buffer_w, 0, sizeof(buffer_w)); ret = SetupDiGetDevicePropertyW(set, &device, &DEVPKEY_Device_HardwareIds, &prop_type, (BYTE *)buffer_w, sizeof(buffer_w), &size, 0); - todo_wine ok(ret, "failed to get device property, error %#lx\n", GetLastError()); - todo_wine ok(prop_type == DEVPROP_TYPE_STRING_LIST, "got type %#lx\n", prop_type); - todo_wine ok(size == sizeof(expect_hardware_id_w), "got size %lu\n", size); - todo_wine ok(!memcmp(buffer_w, expect_hardware_id_w, size), "got hardware IDs %s\n", debugstr_wn(buffer_w, size)); + ok(ret, "failed to get device property, error %#lx\n", GetLastError()); + ok(prop_type == DEVPROP_TYPE_STRING_LIST, "got type %#lx\n", prop_type); + ok(size == sizeof(expect_hardware_id_w), "got size %lu\n", size); + ok(!memcmp(buffer_w, expect_hardware_id_w, size), "got hardware IDs %s\n", debugstr_wn(buffer_w, size));
prop_type = DEVPROP_TYPE_EMPTY; size = 0; memset(buffer_w, 0, sizeof(buffer_w)); ret = SetupDiGetDevicePropertyW(set, &device, &DEVPKEY_Device_CompatibleIds, &prop_type, (BYTE *)buffer_w, sizeof(buffer_w), &size, 0); - todo_wine ok(ret, "failed to get device property, error %#lx\n", GetLastError()); - todo_wine ok(prop_type == DEVPROP_TYPE_STRING_LIST, "got type %#lx\n", prop_type); - todo_wine ok(size == sizeof(expect_compat_id_w), "got size %lu\n", size); - todo_wine ok(!memcmp(buffer_w, expect_compat_id_w, size), "got compatible IDs %s\n", debugstr_wn(buffer_w, size)); + ok(ret, "failed to get device property, error %#lx\n", GetLastError()); + ok(prop_type == DEVPROP_TYPE_STRING_LIST, "got type %#lx\n", prop_type); + ok(size == sizeof(expect_compat_id_w), "got size %lu\n", size); + ok(!memcmp(buffer_w, expect_compat_id_w, size), "got compatible IDs %s\n", debugstr_wn(buffer_w, size));
prop_type = DEVPROP_TYPE_EMPTY; size = 0; ret = SetupDiGetDevicePropertyW(set, &device, &DEVPKEY_Device_ContainerId, &prop_type, (BYTE *)&buffer_guid, sizeof(buffer_guid), &size, 0); - todo_wine ok(ret, "failed to get device property, error %#lx\n", GetLastError()); - todo_wine ok(prop_type == DEVPROP_TYPE_GUID, "got type %#lx\n", prop_type); - todo_wine ok(size == sizeof(expect_container_id_guid), "got size %lu\n", size); - todo_wine ok(IsEqualGUID(&buffer_guid, &expect_container_id_guid), "got container ID %s != %s\n", - debugstr_guid(&buffer_guid), debugstr_guid(&expect_container_id_guid)); + ok(ret, "failed to get device property, error %#lx\n", GetLastError()); + ok(prop_type == DEVPROP_TYPE_GUID, "got type %#lx\n", prop_type); + ok(size == sizeof(expect_container_id_guid), "got size %lu\n", size); + ok(IsEqualGUID(&buffer_guid, &expect_container_id_guid), "got container ID %s != %s\n", + debugstr_guid(&buffer_guid), debugstr_guid(&expect_container_id_guid));
ret = SetupDiEnumDeviceInterfaces(set, NULL, &child_class, 0, &iface); ok(ret, "failed to get interface, error %#lx\n", GetLastError()); diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 066bd6f09c2..76b4a767ff3 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -895,10 +895,9 @@ static struct device *create_device(struct DeviceInfoSet *set, return device; }
-static struct device *get_devnode_device(DEVINST devnode, HDEVINFO *set) +static struct device *get_devnode_device(DEVINST devnode, HDEVINFO *set, SP_DEVINFO_DATA *data) { - SP_DEVINFO_DATA data = { sizeof(data) }; - + data->cbSize = sizeof(*data); *set = NULL; if (devnode >= devinst_table_size || !devinst_table[devnode]) { @@ -908,13 +907,13 @@ static struct device *get_devnode_device(DEVINST devnode, HDEVINFO *set)
*set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); if (*set == INVALID_HANDLE_VALUE) return NULL; - if (!SetupDiOpenDeviceInfoW(*set, devinst_table[devnode], NULL, 0, &data)) + if (!SetupDiOpenDeviceInfoW(*set, devinst_table[devnode], NULL, 0, data)) { SetupDiDestroyDeviceInfoList(*set); *set = NULL; return NULL; } - return get_device(*set, &data); + return get_device(*set, data); }
/*********************************************************************** @@ -5275,6 +5274,119 @@ BOOL WINAPI SetupDiGetDevicePropertyKeys( HDEVINFO devinfo, PSP_DEVINFO_DATA dev return !ret; }
+static DWORD get_device_property( struct device *device, HDEVINFO devinfo, PSP_DEVINFO_DATA device_data, + const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type, BYTE *buf, DWORD buf_size, + DWORD *req_size, DWORD flags ) +{ + DWORD ret = ERROR_SUCCESS; + + if (!prop_key) + return ERROR_INVALID_DATA; + if (!prop_type || (!buf && buf_size)) + return ERROR_INVALID_USER_BUFFER; + if (flags) + return ERROR_INVALID_FLAGS; + + if (IsEqualGUID( &prop_key->fmtid, &DEVPKEY_Device_DeviceDesc.fmtid )) + { + DWORD reg_prop = prop_key->pid - 2, size, type; + + if (prop_key->pid < 2 || reg_prop >= ARRAY_SIZE(PropertyMap)) + return get_device_reg_property( device->key, prop_key, prop_type, buf, buf_size, req_size, flags ); + + ret = ERROR_SUCCESS; + switch (reg_prop) + { + /* DEVPROP_TYPE_STRING */ + case SPDRP_DEVICEDESC: + case SPDRP_SERVICE: + case SPDRP_CLASS: + case SPDRP_DRIVER: + case SPDRP_MFG: + case SPDRP_LOCATION_INFORMATION: + case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME: + type = DEVPROP_TYPE_STRING; + if (!SetupDiGetDeviceRegistryPropertyW( devinfo, device_data, reg_prop, NULL, buf, buf_size, &size )) + ret = GetLastError(); + break; + /* DEVPROP_TYPE_STRING_LIST */ + case SPDRP_COMPATIBLEIDS: + case SPDRP_HARDWAREID: + case SPDRP_UPPERFILTERS: + case SPDRP_LOWERFILTERS: + type = DEVPROP_TYPE_STRING_LIST; + if (!SetupDiGetDeviceRegistryPropertyW( devinfo, device_data, reg_prop, NULL, buf, buf_size, &size )) + ret = GetLastError(); + break; + /* DEVPROP_TYPE_(U)INT32 */ + case SPDRP_CONFIGFLAGS: + case SPDRP_CAPABILITIES: + case SPDRP_UI_NUMBER: + type = reg_prop == SPDRP_CONFIGFLAGS ? DEVPROP_TYPE_UINT32 : DEVPROP_TYPE_INT32; + if (!SetupDiGetDeviceRegistryPropertyW( devinfo, device_data, reg_prop, NULL, buf, buf_size, &size )) + ret = GetLastError(); + break; + /* DEVROP_TYPE_GUID */ + case SPDRP_CLASSGUID: + case SPDRP_BUSTYPEGUID: + case SPDRP_BASE_CONTAINERID: + { + WCHAR guid_str[39]; + + type = DEVPROP_TYPE_GUID; + size = sizeof( GUID ); + if (!SetupDiGetDeviceRegistryPropertyW( devinfo, device_data, reg_prop, NULL, (BYTE *)guid_str, + sizeof( guid_str ), NULL )) + { + ret = GetLastError(); + break; + } + if (buf_size >= sizeof( GUID )) + { + if (guid_str[0] == '{' && guid_str[37] == '}') + { + guid_str[37] = 0; + if (!UuidFromStringW( &guid_str[1], (GUID *)buf )) + break; + } + ERR( "Invalid GUID string: %s\n", debugstr_w( guid_str ) ); + } + else + ret = ERROR_INSUFFICIENT_BUFFER; + break; + } + default: + FIXME( "Unimplemented builtin property {%s, %#lx}\n", debugstr_guid( &prop_key->fmtid ), prop_key->pid ); + return get_device_reg_property( device->key, prop_key, prop_type, buf, buf_size, req_size, flags ); + } + if (ret != ERROR_INVALID_DATA) + { + *prop_type = type; + if (req_size) + *req_size = size; + } + else + ret = ERROR_NOT_FOUND; + } + else if (IsEqualDevPropKey( *prop_key, DEVPKEY_Device_InstanceId )) + { + DWORD size = (wcslen( device->instanceId ) + 1) * sizeof( WCHAR ); + *prop_type = DEVPROP_TYPE_STRING; + if (buf_size >= size) + wcscpy( (WCHAR *)buf, device->instanceId ); + else + ret = ERROR_INSUFFICIENT_BUFFER; + if (req_size) + *req_size = size; + } + else if (IsEqualDevPropKey( *prop_key, DEVPKEY_Device_ContainerId )) + return get_device_property( device, devinfo, device_data, &DEVPKEY_Device_BaseContainerId, prop_type, buf, + buf_size, req_size, flags ); + else + ret = get_device_reg_property( device->key, prop_key, prop_type, buf, buf_size, req_size, flags ); + return ret; +} + /*********************************************************************** * SetupDiGetDevicePropertyW (SETUPAPI.@) */ @@ -5291,7 +5403,8 @@ BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO devinfo, PSP_DEVINFO_DATA device_ if (!(device = get_device(devinfo, device_data))) return FALSE;
- ls = get_device_reg_property(device->key, prop_key, prop_type, prop_buff, prop_buff_size, required_size, flags); + ls = get_device_property(device, devinfo, device_data, prop_key, prop_type, prop_buff, prop_buff_size, + required_size, flags);
SetLastError(ls); return !ls; @@ -5304,6 +5417,7 @@ CONFIGRET WINAPI CM_Get_DevNode_Property_ExW(DEVINST devnode, const DEVPROPKEY * BYTE *prop_buff, ULONG *prop_buff_size, ULONG flags, HMACHINE machine) { HDEVINFO set; + SP_DEVINFO_DATA data = { sizeof(data) }; struct device *device; LSTATUS ls;
@@ -5316,10 +5430,11 @@ CONFIGRET WINAPI CM_Get_DevNode_Property_ExW(DEVINST devnode, const DEVPROPKEY * if (!prop_buff_size) return CR_INVALID_POINTER;
- if (!(device = get_devnode_device(devnode, &set))) + if (!(device = get_devnode_device(devnode, &set, &data))) return CR_NO_SUCH_DEVINST;
- ls = get_device_reg_property(device->key, prop_key, prop_type, prop_buff, *prop_buff_size, prop_buff_size, flags); + ls = get_device_property(device, set, &data, prop_key, prop_type, prop_buff, *prop_buff_size, + prop_buff_size, flags); SetupDiDestroyDeviceInfoList(set); switch (ls) { diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 385ce9304a9..2de54521a22 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -1258,21 +1258,21 @@ static void test_device_property(void) SetLastError(0xdeadbeef); ret = pSetupDiGetDevicePropertyW(set, &device_data, &DEVPKEY_Device_InstanceId, &type, buffer, sizeof(buffer), &size, 0); err = GetLastError(); - todo_wine ok(ret, "Expect success\n"); - todo_wine ok(err == NO_ERROR, "Expect last error %#x, got %#lx\n", NO_ERROR, err); - todo_wine ok(type == DEVPROP_TYPE_STRING, "Expect type %#x, got %#lx\n", DEVPROP_TYPE_STRING, type); - todo_wine ok(size == sizeof(instance_id), "Got size %lu\n", size); - todo_wine ok(!wcsicmp(instance_id, (WCHAR *)buffer), "Expect buffer %s, got %s\n", debugstr_w(instance_id), debugstr_w((WCHAR*)buffer)); + ok(ret, "Expect success\n"); + ok(err == NO_ERROR, "Expect last error %#x, got %#lx\n", NO_ERROR, err); + ok(type == DEVPROP_TYPE_STRING, "Expect type %#x, got %#lx\n", DEVPROP_TYPE_STRING, type); + ok(size == sizeof(instance_id), "Got size %lu\n", size); + ok(!wcsicmp(instance_id, (WCHAR *)buffer), "Expect buffer %s, got %s\n", debugstr_w(instance_id), debugstr_w((WCHAR*)buffer));
type = DEVPROP_TYPE_EMPTY; size = 0; ret = pSetupDiGetDevicePropertyW(set, &device_data, &DEVPKEY_Device_ClassGuid, &type, (BYTE *)&guid_val, sizeof(guid_val), &size, 0); err = GetLastError(); - todo_wine ok(ret, "Expect success\n"); - todo_wine ok(err == NO_ERROR, "Expect last error %#x, got %#lx\n", NO_ERROR, err); - todo_wine ok(type == DEVPROP_TYPE_GUID, "Expect type %#x, got %#lx\n", DEVPROP_TYPE_GUID, type); - todo_wine ok(size == sizeof(guid_val), "Got size %lu\n", size); - todo_wine ok(IsEqualGUID(&guid_val, &guid), "Expect buffer %s, got %s\n", debugstr_guid(&guid), debugstr_guid(&guid_val)); + ok(ret, "Expect success\n"); + ok(err == NO_ERROR, "Expect last error %#x, got %#lx\n", NO_ERROR, err); + ok(type == DEVPROP_TYPE_GUID, "Expect type %#x, got %#lx\n", DEVPROP_TYPE_GUID, type); + ok(size == sizeof(guid_val), "Got size %lu\n", size); + ok(IsEqualGUID(&guid_val, &guid), "Expect buffer %s, got %s\n", debugstr_guid(&guid), debugstr_guid(&guid_val));
for (i = 0; i < ARRAY_SIZE(inbuilt_props); i++) { @@ -2641,9 +2641,9 @@ todo_wine { ret = SetupDiSetDeviceRegistryPropertyW(set, &device, prop->reg_prop, prop->reg_value, prop->reg_size); ok(ret, "Failed to set property, error %#lx.\n", GetLastError()); ret = SetupDiGetDevicePropertyW(set, &device, &key, &type, buf, sizeof(buf), &size, 0); - todo_wine ok(ret, "Failed to get property, error %#lx.\n", GetLastError()); - todo_wine ok(type == prop->devprop_type, "Got unexpected type %#lx.\n", type); - todo_wine ok(size == prop->devprop_size, "Got unexpected size %lu.\n", size); + ok(ret, "Failed to get property, error %#lx.\n", GetLastError()); + ok(type == prop->devprop_type, "Got unexpected type %#lx.\n", type); + ok(size == prop->devprop_size, "Got unexpected size %lu.\n", size); if (size == prop->devprop_size) ok(!memcmp(buf, prop->devprop_value, size), "Got unexpected property value.\n"); winetest_pop_context();