[PATCH v2 4/5] setupapi: Remove all device interfaces in SetupDiRemoveDevice().
Zebediah Figura
z.figura12 at gmail.com
Wed Apr 7 23:56:44 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/setupapi/devinst.c | 80 +++++++++++++++++++++++++++++++++++
dlls/setupapi/tests/devinst.c | 30 +++++++++++++
2 files changed, 110 insertions(+)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
index 8f826c30250..7ff3cb01eb6 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -690,6 +690,81 @@ static void delete_device_iface(struct device_iface *iface)
heap_free(iface);
}
+/* remove all interfaces associated with the device, including those not
+ * enumerated in the set */
+static void remove_all_device_ifaces(struct device *device)
+{
+ HKEY classes_key;
+ DWORD i, len;
+ LONG ret;
+
+ if ((ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, KEY_READ, &classes_key)))
+ {
+ ERR("Failed to open classes key, error %u.\n", ret);
+ return;
+ }
+
+ for (i = 0; ; ++i)
+ {
+ WCHAR class_name[40];
+ HKEY class_key;
+ DWORD j;
+
+ len = ARRAY_SIZE(class_name);
+ if ((ret = RegEnumKeyExW(classes_key, i, class_name, &len, NULL, NULL, NULL, NULL)))
+ {
+ if (ret != ERROR_NO_MORE_ITEMS) ERR("Failed to enumerate classes, error %u.\n", ret);
+ break;
+ }
+
+ if ((ret = RegOpenKeyExW(classes_key, class_name, 0, KEY_READ, &class_key)))
+ {
+ ERR("Failed to open class %s, error %u.\n", debugstr_w(class_name), ret);
+ continue;
+ }
+
+ for (j = 0; ; ++j)
+ {
+ WCHAR iface_name[MAX_DEVICE_ID_LEN + 39], device_name[MAX_DEVICE_ID_LEN];
+ HKEY iface_key;
+
+ len = ARRAY_SIZE(iface_name);
+ if ((ret = RegEnumKeyExW(class_key, j, iface_name, &len, NULL, NULL, NULL, NULL)))
+ {
+ if (ret != ERROR_NO_MORE_ITEMS) ERR("Failed to enumerate interfaces, error %u.\n", ret);
+ break;
+ }
+
+ if ((ret = RegOpenKeyExW(class_key, iface_name, 0, KEY_ALL_ACCESS, &iface_key)))
+ {
+ ERR("Failed to open interface %s, error %u.\n", debugstr_w(iface_name), ret);
+ continue;
+ }
+
+ len = sizeof(device_name);
+ if ((ret = RegQueryValueExW(iface_key, L"DeviceInstance", NULL, NULL, (BYTE *)device_name, &len)))
+ {
+ ERR("Failed to query device instance, error %u.\n", ret);
+ RegCloseKey(iface_key);
+ continue;
+ }
+
+ if (!wcsicmp(device_name, device->instanceId))
+ {
+ if ((ret = RegDeleteTreeW(iface_key, NULL)))
+ ERR("Failed to delete interface %s subkeys, error %u.\n", debugstr_w(iface_name), ret);
+ if ((ret = RegDeleteKeyW(iface_key, L"")))
+ ERR("Failed to delete interface %s, error %u.\n", debugstr_w(iface_name), ret);
+ }
+
+ RegCloseKey(iface_key);
+ }
+ RegCloseKey(class_key);
+ }
+
+ RegCloseKey(classes_key);
+}
+
static void remove_device(struct device *device)
{
WCHAR id[MAX_DEVICE_ID_LEN], *p;
@@ -735,7 +810,10 @@ static void delete_device(struct device *device)
SetupDiCallClassInstaller(DIF_DESTROYPRIVATEDATA, device->set, &device_data);
if (device->phantom)
+ {
remove_device(device);
+ remove_all_device_ifaces(device);
+ }
RegCloseKey(device->key);
heap_free(device->instanceId);
@@ -1725,6 +1803,8 @@ BOOL WINAPI SetupDiRemoveDevice(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data)
}
CloseServiceHandle(manager);
+ remove_all_device_ifaces(device);
+
return TRUE;
}
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index 48b84c21e84..de302d21660 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -1448,6 +1448,7 @@ static void test_register_device_iface(void)
'E','n','u','m','\\','R','o','o','t','\\',
'L','E','G','A','C','Y','_','B','O','G','U','S',0};
SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
+ SP_DEVINFO_DATA device2 = {sizeof(device2)};
SP_DEVINFO_DATA device = {sizeof(device)};
HDEVINFO set, set2;
BOOL ret;
@@ -1487,11 +1488,40 @@ static void test_register_device_iface(void)
check_device_iface(set2, NULL, &guid, 1, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\deleted");
check_device_iface(set2, NULL, &guid, 2, 0, NULL);
+ ret = SetupDiEnumDeviceInfo(set2, 0, &device2);
+ ok(ret, "Failed to enumerate devices, error %#x.\n", GetLastError());
+ ret = SetupDiCreateDeviceInterfaceA(set2, &device2, &guid, "second", 0, NULL);
+ ok(ret, "Failed to create interface, error %#x.\n", GetLastError());
+
ret = SetupDiRemoveDevice(set, &device);
ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
+ check_device_iface(set, NULL, &guid, 0, SPINT_REMOVED, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}");
+ check_device_iface(set, NULL, &guid, 1, SPINT_REMOVED, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\removed");
+ check_device_iface(set, NULL, &guid, 2, 0, NULL);
+
+ check_device_iface(set2, NULL, &guid, 0, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}");
+ check_device_iface(set2, NULL, &guid, 1, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\deleted");
+ check_device_iface(set2, NULL, &guid, 2, 0, "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}\\second");
+ check_device_iface(set2, NULL, &guid, 3, 0, NULL);
+
SetupDiDestroyDeviceInfoList(set);
SetupDiDestroyDeviceInfoList(set2);
+
+ /* make sure all interface keys are deleted when a device is removed */
+
+ set = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
+ ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
+
+ ret = SetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, &device);
+ ok(ret, "Failed to create device, error %#x.\n", GetLastError());
+
+ set2 = SetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_DEVICEINTERFACE);
+ ok(set2 != INVALID_HANDLE_VALUE, "Failed to create device list, error %#x.\n", GetLastError());
+ check_device_iface(set2, NULL, &guid, 0, 0, NULL);
+ SetupDiDestroyDeviceInfoList(set2);
+
+ SetupDiDestroyDeviceInfoList(set);
}
static void test_registry_property_a(void)
--
2.30.2
More information about the wine-devel
mailing list