Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/devinst.c | 28 ++++++++++++++++++++++++---- dlls/setupapi/tests/devinst.c | 2 -- 2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 55fca897c3..479b8297b0 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -556,6 +556,19 @@ static BOOL SETUPDI_SetDeviceRegistryPropertyW(struct device *device, return FALSE; }
+static void remove_device_iface(struct device_iface *iface) +{ + RegDeleteTreeW(iface->refstr_key, NULL); + RegDeleteKeyW(iface->refstr_key, emptyW); + RegCloseKey(iface->refstr_key); + iface->refstr_key = NULL; + /* Also remove the class key if it's empty. */ + RegDeleteKeyW(iface->class_key, emptyW); + RegCloseKey(iface->class_key); + iface->class_key = NULL; + iface->flags |= SPINT_REMOVED; +} + static void SETUPDI_RemoveDevice(struct device *device) { struct device_iface *iface, *next; @@ -1537,11 +1550,18 @@ BOOL WINAPI SetupDiRemoveDevice( /*********************************************************************** * SetupDiRemoveDeviceInterface (SETUPAPI.@) */ -BOOL WINAPI SetupDiRemoveDeviceInterface(HDEVINFO info, PSP_DEVICE_INTERFACE_DATA data) +BOOL WINAPI SetupDiRemoveDeviceInterface(HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *iface_data) { - FIXME("(%p, %p): stub\n", info, data); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct device_iface *iface; + + TRACE("devinfo %p, iface_data %p.\n", devinfo, iface_data); + + if (!(iface = get_device_iface(devinfo, iface_data))) + return FALSE; + + remove_device_iface(iface); + + return TRUE; }
/*********************************************************************** diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 338393e5f2..fbc62dcbb9 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -552,7 +552,6 @@ static void check_device_iface_(int line, HDEVINFO set, SP_DEVINFO_DATA *device, ok_(__FILE__, line)(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); ok_(__FILE__, line)(IsEqualGUID(&iface.InterfaceClassGuid, class), "Got unexpected class %s.\n", wine_dbgstr_guid(&iface.InterfaceClassGuid)); -todo_wine_if(flags & SPINT_REMOVED) ok_(__FILE__, line)(iface.Flags == flags, "Got unexpected flags %#x.\n", iface.Flags); ret = SetupDiGetDeviceInterfaceDetailA(set, &iface, detail, sizeof(buffer), NULL, NULL); ok_(__FILE__, line)(ret, "Failed to get interface detail, error %#x.\n", GetLastError()); @@ -656,7 +655,6 @@ static void test_device_iface(void) ret = SetupDiEnumDeviceInterfaces(set, &device, &guid2, 0, &iface); ok(ret, "Failed to enumerate interfaces, error %#x.\n", GetLastError()); ret = SetupDiRemoveDeviceInterface(set, &iface); -todo_wine ok(ret, "Failed to remove interface, error %#x.\n", GetLastError());
check_device_iface(set, &device, &guid2, 0, SPINT_REMOVED, "\\?\ROOT#LEGACY_BOGUS#0000#{6A55B5A5-3F65-11DB-B704-0011955C2BDB}");
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/devinst.c | 2 +- dlls/setupapi/tests/devinst.c | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 479b8297b0..f2f4256365 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -594,7 +594,7 @@ static void SETUPDI_RemoveDevice(struct device *device) { list_remove(&iface->entry); if (device->phantom) - RegDeleteKeyW(iface->refstr_key, emptyW); + remove_device_iface(iface); RegCloseKey(iface->refstr_key); RegCloseKey(iface->class_key); heap_free(iface->refstr); diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index fbc62dcbb9..45d145d14c 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -670,12 +670,6 @@ static void test_device_iface_detail(void) 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', 'E','n','u','m','\','R','o','o','t','\', 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; - static const WCHAR devclass[] = {'S','y','s','t','e','m','\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', - 'C','o','n','t','r','o','l','\','D','e','v','i','c','e','C','l','a','s','s','e','s','\', - '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', - '1','1','d','b','-','b','7','0','4','-', - '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; static const char path[] = "\\?\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; @@ -750,7 +744,6 @@ static void test_device_iface_detail(void)
/* remove once Wine is fixed */ devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); - devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, devclass); }
static void test_device_key(void)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/devinst.c | 63 +++++++++++++++++++++++++++---------------- dlls/setupapi/tests/devinst.c | 6 ----- 2 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index f2f4256365..7c551aab6f 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -118,6 +118,7 @@ struct device GUID class; DEVINST devnode; struct list entry; + BOOL removed; };
struct device_iface @@ -167,6 +168,12 @@ static struct device *get_device(HDEVINFO devinfo, const SP_DEVINFO_DATA *data) return NULL; }
+ if (device->removed) + { + SetLastError(ERROR_NO_SUCH_DEVINST); + return NULL; + } + return device; }
@@ -569,32 +576,36 @@ static void remove_device_iface(struct device_iface *iface) iface->flags |= SPINT_REMOVED; }
-static void SETUPDI_RemoveDevice(struct device *device) +static void remove_device(struct device *device) +{ + struct device_iface *iface; + + LIST_FOR_EACH_ENTRY(iface, &device->interfaces, struct device_iface, entry) + { + remove_device_iface(iface); + } + + RegDeleteTreeW(device->key, NULL); + RegDeleteKeyW(device->key, emptyW); + RegCloseKey(device->key); + device->key = NULL; + device->removed = TRUE; +} + +static void delete_device(struct device *device) { struct device_iface *iface, *next;
- if (device->key != INVALID_HANDLE_VALUE) - RegCloseKey(device->key); if (device->phantom) - { - HKEY enumKey; - LONG l; + remove_device(device);
- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, - KEY_ALL_ACCESS, NULL, &enumKey, NULL); - if (!l) - { - RegDeleteTreeW(enumKey, device->instanceId); - RegCloseKey(enumKey); - } - } + RegCloseKey(device->key); heap_free(device->instanceId); + LIST_FOR_EACH_ENTRY_SAFE(iface, next, &device->interfaces, struct device_iface, entry) { list_remove(&iface->entry); - if (device->phantom) - remove_device_iface(iface); RegCloseKey(iface->refstr_key); RegCloseKey(iface->class_key); heap_free(iface->refstr); @@ -635,6 +646,7 @@ static struct device *SETUPDI_CreateDeviceInfo(struct DeviceInfoSet *set, list_init(&device->interfaces); device->class = *class; device->devnode = alloc_devnode(device); + device->removed = FALSE; list_add_tail(&set->devices, &device->entry); set->cDevices++;
@@ -1538,13 +1550,18 @@ BOOL WINAPI SetupDiRegisterDeviceInfo(HDEVINFO devinfo, SP_DEVINFO_DATA *device_ /*********************************************************************** * SetupDiRemoveDevice (SETUPAPI.@) */ -BOOL WINAPI SetupDiRemoveDevice( - HDEVINFO devinfo, - PSP_DEVINFO_DATA info) +BOOL WINAPI SetupDiRemoveDevice(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data) { - FIXME("(%p, %p): stub\n", devinfo, info); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + struct device *device; + + TRACE("devinfo %p, device_data %p.\n", devinfo, device_data); + + if (!(device = get_device(devinfo, device_data))) + return FALSE; + + remove_device(device); + + return TRUE; }
/*********************************************************************** @@ -2616,7 +2633,7 @@ BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
LIST_FOR_EACH_ENTRY_SAFE(device, device2, &set->devices, struct device, entry) { - SETUPDI_RemoveDevice(device); + delete_device(device); } heap_free(set);
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 45d145d14c..07e082b2e1 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -338,7 +338,6 @@ static void test_device_info(void) check_device_info(set, 3, &guid, NULL);
ret = SetupDiRemoveDevice(set, &device); -todo_wine ok(ret, "Got unexpected error %#x.\n", GetLastError());
check_device_info(set, 0, &guid, "ROOT\LEGACY_BOGUS\0000"); @@ -349,10 +348,8 @@ todo_wine ok(IsEqualGUID(&ret_device.ClassGuid, &guid), "Got unexpected class %s.\n", wine_dbgstr_guid(&ret_device.ClassGuid)); ret = SetupDiGetDeviceInstanceIdA(set, &ret_device, id, sizeof(id), NULL); -todo_wine { ok(!ret, "Expected failure.\n"); ok(GetLastError() == ERROR_NO_SUCH_DEVINST, "Got unexpected error %#x.\n", GetLastError()); -} ok(ret_device.DevInst == device.DevInst, "Expected device node %#x, got %#x.\n", device.DevInst, ret_device.DevInst);
@@ -522,7 +519,6 @@ static void test_register_device_info(void) ok(!strcasecmp(id, "Root\LEGACY_BOGUS\0000"), "Got unexpected id %s.\n", id);
ret = SetupDiRemoveDevice(set, &device); -todo_wine ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
ret = SetupDiEnumDeviceInfo(set, 1, &device); @@ -849,7 +845,6 @@ todo_wine { }
ret = SetupDiRemoveDevice(set, &device); -todo_wine ok(ret, "Failed to remove device, error %#x.\n", GetLastError()); SetupDiDestroyDeviceInfoList(set);
@@ -891,7 +886,6 @@ static void test_register_device_iface(void) check_device_iface(set2, NULL, &guid, 1, 0, NULL);
ret = SetupDiRemoveDevice(set, &device); -todo_wine ok(ret, "Failed to remove device, error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/setupapi/devinst.c | 17 +++++++++++++++++ dlls/setupapi/tests/devinst.c | 31 ------------------------------- 2 files changed, 17 insertions(+), 31 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 7c551aab6f..72e7876356 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -578,7 +578,9 @@ static void remove_device_iface(struct device_iface *iface)
static void remove_device(struct device *device) { + WCHAR id[MAX_DEVICE_ID_LEN], *p; struct device_iface *iface; + HKEY enum_key;
LIST_FOR_EACH_ENTRY(iface, &device->interfaces, struct device_iface, entry) { @@ -587,6 +589,21 @@ static void remove_device(struct device *device)
RegDeleteTreeW(device->key, NULL); RegDeleteKeyW(device->key, emptyW); + + /* delete all empty parents of the key */ + if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, 0, &enum_key)) + { + strcpyW(id, device->instanceId); + + while ((p = strrchrW(id, '\'))) + { + *p = 0; + RegDeleteKeyW(enum_key, id); + } + + RegCloseKey(enum_key); + } + RegCloseKey(device->key); device->key = NULL; device->removed = TRUE; diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 07e082b2e1..29f12c3f53 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -466,9 +466,6 @@ static void test_get_device_instance_id(void)
static void test_register_device_info(void) { - static const WCHAR bogus[] = {'S','y','s','t','e','m','\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', - 'E','n','u','m','\','R','o','o','t','\','L','E','G','A','C','Y','_','B','O','G','U','S',0}; SP_DEVINFO_DATA device = {0}; BOOL ret; HDEVINFO set; @@ -526,9 +523,6 @@ static void test_register_device_info(void) ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
SetupDiDestroyDeviceInfoList(set); - - /* remove once Wine is fixed */ - devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); }
static void check_device_iface_(int line, HDEVINFO set, SP_DEVINFO_DATA *device, @@ -662,10 +656,6 @@ static void test_device_iface(void)
static void test_device_iface_detail(void) { - static const WCHAR bogus[] = {'S','y','s','t','e','m','\', - 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\', - 'E','n','u','m','\','R','o','o','t','\', - 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; static const char path[] = "\\?\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; @@ -737,9 +727,6 @@ static void test_device_iface_detail(void)
heap_free(detail); SetupDiDestroyDeviceInfoList(set); - - /* remove once Wine is fixed */ - devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); }
static void test_device_key(void) @@ -849,7 +836,6 @@ todo_wine { SetupDiDestroyDeviceInfoList(set);
/* remove once Wine is fixed */ - devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, classKey); }
@@ -890,9 +876,6 @@ static void test_register_device_iface(void)
SetupDiDestroyDeviceInfoList(set); SetupDiDestroyDeviceInfoList(set2); - - /* remove once Wine is fixed */ - devinst_RegDeleteTreeW(HKEY_LOCAL_MACHINE, bogus); }
static void test_registry_property_a(void) @@ -992,14 +975,7 @@ todo_wine { SetupDiDestroyDeviceInfoList(set);
res = RegOpenKeyA(HKEY_LOCAL_MACHINE, bogus, &key); -todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n"); - /* FIXME: Remove when Wine is fixed */ - if (res == ERROR_SUCCESS) - { - /* Wine doesn't delete the information currently */ - RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus); - } }
static void test_registry_property_w(void) @@ -1103,14 +1079,7 @@ todo_wine { SetupDiDestroyDeviceInfoList(set);
res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus, &key); -todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Key should not exist.\n"); - /* FIXME: Remove when Wine is fixed */ - if (res == ERROR_SUCCESS) - { - /* Wine doesn't delete the information currently */ - RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus); - } }
static void test_get_inf_class(void)