Signed-off-by: Zebediah Figura z.figura12@gmail.com --- 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;