setupapi: Remove all device interfaces in SetupDiRemoveDevice().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
316b8b8589
commit
0b8c1d69e6
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue