Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 48 +++++++++++++++++++++++++----------- dlls/ntoskrnl.exe/pnp.c | 21 +++++++++++++--- 2 files changed, 51 insertions(+), 18 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index f51055fd6c0..d4536c39578 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -88,6 +88,21 @@ static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
DECLARE_CRITICAL_SECTION(drivers_cs);
+static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name ) +{ + static const WCHAR driverW[] = {'\','D','r','i','v','e','r','\',0}; + WCHAR *str; + + if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - lstrlenW(servicesW)*sizeof(WCHAR) ))) + return FALSE; + + lstrcpyW( str, driverW ); + lstrcpynW( str + lstrlenW(driverW), service_name->Buffer + lstrlenW(servicesW), + service_name->Length/sizeof(WCHAR) - lstrlenW(servicesW) + 1 ); + RtlInitUnicodeString( drv_name, str ); + return TRUE; +} + static HANDLE get_device_manager(void) { static HANDLE device_manager; @@ -875,6 +890,8 @@ PEPROCESS PsInitialSystemProcess = NULL; static HANDLE stop_event; static SERVICE_STATUS_HANDLE group_handle;
+#define SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES 128 + static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) { UNICODE_STRING service_name; @@ -898,6 +915,22 @@ static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name ) result = RtlNtStatusToDosError( ZwUnloadDriver( &service_name ) ); break;
+ case SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES: + { + struct wine_rb_entry *entry; + UNICODE_STRING drv_name; + + if (!get_drv_name( &drv_name, &service_name )) + return STATUS_NO_MEMORY; + + entry = wine_rb_get( &wine_drivers, &drv_name ); + RtlFreeUnicodeString( &drv_name ); + + TRACE( "reenumerating PnP devices for %s\n", debugstr_w(service_name.Buffer) ); + pnp_manager_enumerate_root_devices( WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry ) ); + return NO_ERROR; + } + default: FIXME( "got driver ctrl %#x for %s\n", ctrl, debugstr_w(driver_name) ); break; @@ -3834,21 +3867,6 @@ static NTSTATUS WINAPI init_driver( DRIVER_OBJECT *driver_object, UNICODE_STRING return status; }
-static BOOLEAN get_drv_name( UNICODE_STRING *drv_name, const UNICODE_STRING *service_name ) -{ - static const WCHAR driverW[] = {'\','D','r','i','v','e','r','\',0}; - WCHAR *str; - - if (!(str = heap_alloc( sizeof(driverW) + service_name->Length - lstrlenW(servicesW)*sizeof(WCHAR) ))) - return FALSE; - - lstrcpyW( str, driverW ); - lstrcpynW( str + lstrlenW(driverW), service_name->Buffer + lstrlenW(servicesW), - service_name->Length/sizeof(WCHAR) - lstrlenW(servicesW) + 1 ); - RtlInitUnicodeString( drv_name, str ); - return TRUE; -} - /*********************************************************************** * ZwLoadDriver (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 1c1f241591b..9c86450406d 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -1054,7 +1054,8 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) static const WCHAR rootW[] = {'R','O','O','T',0}; WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(driverW)], id[MAX_DEVICE_ID_LEN]; SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; - struct root_pnp_device *pnp_device; + struct list new_list = LIST_INIT(new_list); + struct root_pnp_device *pnp_device, *next; DEVICE_OBJECT *device; NTSTATUS status; unsigned int i; @@ -1080,8 +1081,13 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver )
SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL );
- if (find_root_pnp_device( driver, id )) + if ((pnp_device = find_root_pnp_device( driver, id ))) + { + TRACE("Found device %s already enumerated.\n", debugstr_w(id)); + list_remove( &pnp_device->entry ); + list_add_tail( &new_list, &pnp_device->entry ); continue; + }
TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id));
@@ -1095,10 +1101,19 @@ void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) pnp_device = device->DeviceExtension; wcscpy( pnp_device->id, id ); pnp_device->device = device; - list_add_tail( &driver->root_pnp_devices, &pnp_device->entry ); + list_add_tail( &new_list, &pnp_device->entry );
start_device( device, set, &sp_device ); }
+ LIST_FOR_EACH_ENTRY_SAFE( pnp_device, next, &driver->root_pnp_devices, struct root_pnp_device, entry ) + { + TRACE("Removing device %s.\n", debugstr_w(pnp_device->id)); + + remove_device( pnp_device->device ); + } + + list_move_head( &driver->root_pnp_devices, &new_list ); + SetupDiDestroyDeviceInfoList(set); }