[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