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