Commit 0b8c1d69 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

setupapi: Remove all device interfaces in SetupDiRemoveDevice().

parent 316b8b85
......@@ -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;
}
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment