[PATCH 5/8] ntoskrnl: Introduce a custom service control to reënumerate root PnP devices.

Zebediah Figura z.figura12 at gmail.com
Wed Mar 31 11:16:35 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at 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);
 }
-- 
2.30.2




More information about the wine-devel mailing list