From: Paul Gofman pgofman@codeweavers.com
--- dlls/cfgmgr32/tests/Makefile.in | 2 +- dlls/cfgmgr32/tests/cfgmgr32.c | 45 ++++++++++++-- dlls/setupapi/devinst.c | 106 ++++++++++++++++++-------------- include/cfgmgr32.h | 2 + 4 files changed, 103 insertions(+), 52 deletions(-)
diff --git a/dlls/cfgmgr32/tests/Makefile.in b/dlls/cfgmgr32/tests/Makefile.in index 03b5e5f8fb0..64a01ccf492 100644 --- a/dlls/cfgmgr32/tests/Makefile.in +++ b/dlls/cfgmgr32/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = cfgmgr32.dll -IMPORTS = cfgmgr32 ole32 uuid +IMPORTS = cfgmgr32 setupapi ole32 uuid
SOURCES = \ cfgmgr32.c diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index d6c27fab539..f811410a6fd 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -115,12 +115,22 @@ static void test_CM_MapCrToWin32Err(void) } }
+DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); + static void test_CM_Get_Device_ID_List(void) { - WCHAR wguid_str[64], *wbuf, *wp; + struct + { + WCHAR id[128]; + DEVINST inst; + } + instances[128]; + SP_DEVINFO_DATA device = { sizeof(device) }; + unsigned int i, count, expected_count; + WCHAR wguid_str[64], id[128], *wbuf, *wp; char guid_str[64], *buf, *p; - unsigned int count; CONFIGRET ret; + HDEVINFO set; ULONG len;
StringFromGUID2(&GUID_DEVCLASS_DISPLAY, wguid_str, ARRAY_SIZE(wguid_str)); @@ -188,6 +198,33 @@ static void test_CM_Get_Device_ID_List(void) ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret); ok(buf[0] == 0x7c, "got %#x.\n", buf[0]);
+ set = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT); + ok(set != &GUID_DEVCLASS_DISPLAY, "got error %#lx.\n", GetLastError()); + for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i) + { + ok(i < ARRAY_SIZE(instances), "got %u.\n", i); + ret = SetupDiGetDeviceInstanceIdW(set, &device, instances[i].id, sizeof(instances[i].id), NULL); + ok(ret, "got error %#lx.\n", GetLastError()); + instances[i].inst = device.DevInst; + } + SetupDiDestroyDeviceInfoList(set); + expected_count = i; + for (i = 0; i < expected_count; ++i) + { + DEVPROPTYPE type; + ULONG size; + + *id = 0; + ret = CM_Get_Device_IDW(instances[i].inst, id, ARRAY_SIZE(id), 0); + ok(!ret, "got %#lx.\n", ret); + ok(!wcscmp(id, instances[i].id), "got %s, expected %s.\n", debugstr_w(id), debugstr_w(instances[i].id)); + size = len; + ret = CM_Get_DevNode_PropertyW(instances[i].inst, &DEVPROPKEY_GPU_LUID, &type, wbuf, &size, 0); + ok(!ret || ret == CR_NO_SUCH_VALUE, "got %#lx.\n", ret); + if (!ret) + ok(type == DEVPROP_TYPE_UINT64, "got %#lx.\n", type); + } + memset(wbuf, 0xcc, len * sizeof(*wbuf)); ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT); ok(!ret, "got %#lx.\n", ret); @@ -199,7 +236,7 @@ static void test_CM_Get_Device_ID_List(void) ok(!wcsnicmp(wp, L"PCI\", 4) || !wcsnicmp(wp, L"VMBUS\", 6), "got %s.\n", debugstr_w(wp)); wp += wcslen(wp) + 1; } - ok(count, "got 0.\n"); + ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
memset(buf, 0xcc, len * sizeof(*buf)); ret = CM_Get_Device_ID_ListA(guid_str, buf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT); @@ -212,7 +249,7 @@ static void test_CM_Get_Device_ID_List(void) ok(!strnicmp(p, "PCI\", 4) || !strnicmp(p, "VMBUS\", 6), "got %s.\n", debugstr_a(p)); p += strlen(p) + 1; } - ok(count, "got 0.\n"); + ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
free(wbuf); free(buf); diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 139f167a2f2..4947d664583 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -286,50 +286,45 @@ static inline void copy_device_iface_data(SP_DEVICE_INTERFACE_DATA *data, data->Reserved = (ULONG_PTR)iface; }
-static struct device **devnode_table; -static unsigned int devnode_table_size; +static WCHAR **devinst_table; +static unsigned int devinst_table_size;
-static DEVINST alloc_devnode(struct device *device) +static DEVINST get_devinst_for_device_id(const WCHAR *id) { unsigned int i;
- for (i = 0; i < devnode_table_size; ++i) + for (i = 0; i < devinst_table_size; ++i) { - if (!devnode_table[i]) + if (!devinst_table[i]) break; + if (!wcsicmp(devinst_table[i], id)) + return i; } + return i; +}
- if (i == devnode_table_size) +static DEVINST alloc_devinst_for_device_id(const WCHAR *id) +{ + DEVINST ret; + + ret = get_devinst_for_device_id(id); + if (ret == devinst_table_size) { - if (devnode_table) + if (devinst_table) { - devnode_table = realloc(devnode_table, devnode_table_size * 2 * sizeof(*devnode_table)); - memset(devnode_table + devnode_table_size, 0, devnode_table_size * sizeof(*devnode_table)); - devnode_table_size *= 2; + devinst_table = realloc(devinst_table, devinst_table_size * 2 * sizeof(*devinst_table)); + memset(devinst_table + devinst_table_size, 0, devinst_table_size * sizeof(*devinst_table)); + devinst_table_size *= 2; } else { - devnode_table_size = 256; - devnode_table = calloc(devnode_table_size, sizeof(*devnode_table)); + devinst_table_size = 256; + devinst_table = calloc(devinst_table_size, sizeof(*devinst_table)); } } - - devnode_table[i] = device; - return i; -} - -static void free_devnode(DEVINST devnode) -{ - devnode_table[devnode] = NULL; -} - -static struct device *get_devnode_device(DEVINST devnode) -{ - if (devnode < devnode_table_size) - return devnode_table[devnode]; - - WARN("device node %lu not found\n", devnode); - return NULL; + if (!devinst_table[ret]) + devinst_table[ret] = wcsdup(id); + return ret; }
static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) @@ -884,7 +879,6 @@ static void delete_device(struct device *device) { delete_device_iface(iface); } - free_devnode(device->devnode); list_remove(&device->entry); free(device); } @@ -930,7 +924,7 @@ static struct device *create_device(struct DeviceInfoSet *set, device->phantom = phantom; list_init(&device->interfaces); device->class = *class; - device->devnode = alloc_devnode(device); + device->devnode = alloc_devinst_for_device_id(device->instanceId); device->removed = FALSE; list_add_tail(&set->devices, &device->entry); device->params.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); @@ -952,6 +946,28 @@ static struct device *create_device(struct DeviceInfoSet *set, return device; }
+static struct device *get_devnode_device(DEVINST devnode, HDEVINFO *set) +{ + SP_DEVINFO_DATA data = { sizeof(data) }; + + *set = NULL; + if (devnode >= devinst_table_size || !devinst_table[devnode]) + { + WARN("device node %lu not found\n", devnode); + return NULL; + } + + *set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); + if (*set == INVALID_HANDLE_VALUE) return NULL; + if (!SetupDiOpenDeviceInfoW(*set, devinst_table[devnode], NULL, 0, &data)) + { + SetupDiDestroyDeviceInfoList(*set); + *set = NULL; + return NULL; + } + return get_device(*set, &data); +} + /*********************************************************************** * SetupDiBuildClassInfoList (SETUPAPI.@) * @@ -4234,14 +4250,12 @@ BOOL WINAPI SetupDiDeleteDevRegKey(HDEVINFO devinfo, SP_DEVINFO_DATA *device_dat */ CONFIGRET WINAPI CM_Get_Device_IDA(DEVINST devnode, char *buffer, ULONG len, ULONG flags) { - struct device *device = get_devnode_device(devnode); - TRACE("%lu, %p, %lu, %#lx\n", devnode, buffer, len, flags);
- if (!device) + if (devnode >= devinst_table_size || !devinst_table[devnode]) return CR_NO_SUCH_DEVINST;
- WideCharToMultiByte(CP_ACP, 0, device->instanceId, -1, buffer, len, 0, 0); + WideCharToMultiByte(CP_ACP, 0, devinst_table[devnode], -1, buffer, len, 0, 0); TRACE("Returning %s\n", debugstr_a(buffer)); return CR_SUCCESS; } @@ -4251,14 +4265,12 @@ CONFIGRET WINAPI CM_Get_Device_IDA(DEVINST devnode, char *buffer, ULONG len, ULO */ CONFIGRET WINAPI CM_Get_Device_IDW(DEVINST devnode, WCHAR *buffer, ULONG len, ULONG flags) { - struct device *device = get_devnode_device(devnode); - TRACE("%lu, %p, %lu, %#lx\n", devnode, buffer, len, flags);
- if (!device) + if (devnode >= devinst_table_size || !devinst_table[devnode]) return CR_NO_SUCH_DEVINST;
- lstrcpynW(buffer, device->instanceId, len); + lstrcpynW(buffer, devinst_table[devnode], len); TRACE("Returning %s\n", debugstr_w(buffer)); return CR_SUCCESS; } @@ -4268,14 +4280,12 @@ CONFIGRET WINAPI CM_Get_Device_IDW(DEVINST devnode, WCHAR *buffer, ULONG len, UL */ CONFIGRET WINAPI CM_Get_Device_ID_Size(ULONG *len, DEVINST devnode, ULONG flags) { - struct device *device = get_devnode_device(devnode); - TRACE("%p, %lu, %#lx\n", len, devnode, flags);
- if (!device) + if (devnode >= devinst_table_size || !devinst_table[devnode]) return CR_NO_SUCH_DEVINST;
- *len = lstrlenW(device->instanceId); + *len = lstrlenW(devinst_table[devnode]); return CR_SUCCESS; }
@@ -4851,7 +4861,8 @@ BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO devinfo, PSP_DEVINFO_DATA device_ CONFIGRET WINAPI CM_Get_DevNode_Property_ExW(DEVINST devnode, const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type, BYTE *prop_buff, ULONG *prop_buff_size, ULONG flags, HMACHINE machine) { - struct device *device = get_devnode_device(devnode); + HDEVINFO set; + struct device *device; LSTATUS ls;
TRACE("%lu, %p, %p, %p, %p, %#lx, %p\n", devnode, prop_key, prop_type, prop_buff, prop_buff_size, @@ -4860,13 +4871,14 @@ CONFIGRET WINAPI CM_Get_DevNode_Property_ExW(DEVINST devnode, const DEVPROPKEY * if (machine) return CR_MACHINE_UNAVAILABLE;
- if (!device) - return CR_NO_SUCH_DEVINST; - if (!prop_buff_size) return CR_INVALID_POINTER;
+ if (!(device = get_devnode_device(devnode, &set))) + return CR_NO_SUCH_DEVINST; + ls = get_device_property(device, prop_key, prop_type, prop_buff, *prop_buff_size, prop_buff_size, flags); + SetupDiDestroyDeviceInfoList(set); switch (ls) { case NO_ERROR: diff --git a/include/cfgmgr32.h b/include/cfgmgr32.h index 31e93290b49..90e25aac4f5 100644 --- a/include/cfgmgr32.h +++ b/include/cfgmgr32.h @@ -314,6 +314,8 @@ CMAPI CONFIGRET WINAPI CM_Get_Device_ID_List_Size_ExW(PULONG,PCWSTR,ULONG,HMACHI CMAPI CONFIGRET WINAPI CM_Get_Device_ID_Size(PULONG,DEVINST,ULONG); CMAPI CONFIGRET WINAPI CM_Get_Device_ID_Size_Ex(PULONG,DEVINST,ULONG,HMACHINE); CMAPI CONFIGRET WINAPI CM_Get_Device_Interface_PropertyW(LPCWSTR,const DEVPROPKEY*,DEVPROPTYPE*,PBYTE,PULONG,ULONG); +CMAPI CONFIGRET WINAPI CM_Get_DevNode_PropertyW(DEVINST,const DEVPROPKEY *,DEVPROPTYPE *type,PVOID,PULONG,ULONG); +CMAPI CONFIGRET WINAPI CM_Get_DevNode_PropertyExW(DEVINST,const DEVPROPKEY *,DEVPROPTYPE *type,PVOID,PULONG,ULONG,HMACHINE); CMAPI CONFIGRET WINAPI CM_Get_DevNode_Status(PULONG,PULONG,DEVINST,ULONG); CMAPI CONFIGRET WINAPI CM_Get_DevNode_Status_Ex(PULONG,PULONG,DEVINST,ULONG,HMACHINE); CMAPI CONFIGRET WINAPI CM_Get_Sibling(PDEVINST,DEVINST,ULONG);