Zebediah Figura : winedevice: Introduce a custom service control to reënumerate root PnP devices.

Alexandre Julliard julliard at winehq.org
Fri Apr 2 16:10:12 CDT 2021


Module: wine
Branch: master
Commit: 73bfe36eab54e28b8deddc3ad1cf1d2df29f6956
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=73bfe36eab54e28b8deddc3ad1cf1d2df29f6956

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Fri Apr  2 10:53:35 2021 -0500

winedevice: Introduce a custom service control to reënumerate root PnP devices.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/ntoskrnl.c         |  2 +-
 dlls/ntoskrnl.exe/ntoskrnl.exe.spec  |  1 +
 dlls/ntoskrnl.exe/ntoskrnl_private.h |  3 ++-
 dlls/ntoskrnl.exe/pnp.c              | 23 +++++++++++++++++++----
 programs/winedevice/device.c         |  6 ++++++
 5 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 1ddd3f4d4f0..bb9f4bf5259 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -3824,7 +3824,7 @@ NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name )
     driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
     driver->service_handle = service_handle;
 
-    pnp_manager_enumerate_root_devices( service_name->Buffer + wcslen( servicesW ) );
+    wine_enumerate_root_devices( service_name->Buffer + wcslen( servicesW ) );
 
     set_service_status( service_handle, SERVICE_RUNNING,
                         SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 0f5ab76a195..6dea87f347b 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1686,3 +1686,4 @@
 # or 'wine_' (for user-visible functions) to avoid namespace conflicts.
 
 @ cdecl wine_ntoskrnl_main_loop(long)
+@ cdecl wine_enumerate_root_devices(wstr)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h
index c0b588f3135..c736a9805a0 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl_private.h
+++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h
@@ -101,11 +101,12 @@ struct wine_driver
 
 void ObReferenceObject( void *obj ) DECLSPEC_HIDDEN;
 
-void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) DECLSPEC_HIDDEN;
 void pnp_manager_start(void) DECLSPEC_HIDDEN;
 void pnp_manager_stop_driver( struct wine_driver *driver ) DECLSPEC_HIDDEN;
 void pnp_manager_stop(void) DECLSPEC_HIDDEN;
 
+void CDECL wine_enumerate_root_devices( const WCHAR *driver_name );
+
 struct wine_driver *get_driver( const WCHAR *name ) DECLSPEC_HIDDEN;
 
 static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
index dce6bb90c68..7994a8b85b9 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -1047,13 +1047,14 @@ void pnp_manager_stop(void)
     RpcBindingFree( &plugplay_binding_handle );
 }
 
-void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
+void CDECL wine_enumerate_root_devices( const WCHAR *driver_name )
 {
     static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
     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;
     struct wine_driver *driver;
     DEVICE_OBJECT *device;
     NTSTATUS status;
@@ -1082,8 +1083,13 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
 
         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));
 
@@ -1097,10 +1103,19 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
         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);
 }
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index 3acc5e8a799..509cab96308 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(winedevice);
 static const WCHAR servicesW[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
 
 extern NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event );
+extern void CDECL wine_enumerate_root_devices( const WCHAR *driver_name );
 
 static WCHAR winedeviceW[] = L"winedevice";
 static SERVICE_STATUS_HANDLE service_handle;
@@ -55,6 +56,8 @@ static void set_service_status( SERVICE_STATUS_HANDLE handle, DWORD state, DWORD
     SetServiceStatus( handle, &status );
 }
 
+#define SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES 128
+
 static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name )
 {
     UNICODE_STRING service_name;
@@ -78,6 +81,9 @@ static DWORD device_handler( DWORD ctrl, const WCHAR *driver_name )
         result = RtlNtStatusToDosError(ZwUnloadDriver( &service_name ));
         break;
 
+    case SERVICE_CONTROL_REENUMERATE_ROOT_DEVICES:
+        wine_enumerate_root_devices( driver_name );
+
     default:
         FIXME( "got driver ctrl %x for %s\n", ctrl, wine_dbgstr_w(driver_name) );
         break;




More information about the wine-cvs mailing list