ntoskrnl.exe: Load a driver's root PnP devices when the driver is started.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d4c91cc6f9
commit
b06740ecde
|
@ -3648,6 +3648,8 @@ 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 ) );
|
||||
|
||||
set_service_status( service_handle, SERVICE_RUNNING,
|
||||
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
|
||||
return STATUS_SUCCESS;
|
||||
|
|
|
@ -76,6 +76,7 @@ extern POBJECT_TYPE SeTokenObjectType;
|
|||
|
||||
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(void) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -375,6 +375,18 @@ static BOOL install_device_driver( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVIN
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the function driver for a newly created PDO, if one is present, and
|
||||
* send IRPs to start the device. */
|
||||
static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *sp_device )
|
||||
{
|
||||
load_function_driver( device, set, sp_device );
|
||||
if (device->DriverObject)
|
||||
{
|
||||
send_pnp_irp( device, IRP_MN_START_DEVICE );
|
||||
send_power_irp( device, PowerDeviceD0 );
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_bus_relations( DEVICE_OBJECT *device )
|
||||
{
|
||||
static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0};
|
||||
|
@ -420,19 +432,14 @@ static void handle_bus_relations( DEVICE_OBJECT *device )
|
|||
return;
|
||||
}
|
||||
|
||||
load_function_driver( device, set, &sp_device );
|
||||
if (device->DriverObject)
|
||||
{
|
||||
send_pnp_irp( device, IRP_MN_START_DEVICE );
|
||||
send_power_irp( device, PowerDeviceD0 );
|
||||
}
|
||||
start_device( device, set, &sp_device );
|
||||
|
||||
SetupDiDestroyDeviceInfoList( set );
|
||||
}
|
||||
|
||||
static void handle_removal_relations( DEVICE_OBJECT *device )
|
||||
static void remove_device( DEVICE_OBJECT *device )
|
||||
{
|
||||
TRACE( "(%p)\n", device );
|
||||
TRACE("Removing device %p.\n", device);
|
||||
|
||||
send_power_irp( device, PowerDeviceD3 );
|
||||
send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL );
|
||||
|
@ -452,7 +459,7 @@ void WINAPI IoInvalidateDeviceRelations( DEVICE_OBJECT *device_object, DEVICE_RE
|
|||
handle_bus_relations( device_object );
|
||||
break;
|
||||
case RemovalRelations:
|
||||
handle_removal_relations( device_object );
|
||||
remove_device( device_object );
|
||||
break;
|
||||
default:
|
||||
FIXME("Unhandled relation %#x.\n", type);
|
||||
|
@ -755,6 +762,23 @@ POWER_STATE WINAPI PoSetPowerState( DEVICE_OBJECT *device, POWER_STATE_TYPE type
|
|||
|
||||
static DRIVER_OBJECT *pnp_manager;
|
||||
|
||||
struct root_pnp_device
|
||||
{
|
||||
WCHAR id[MAX_DEVICE_ID_LEN];
|
||||
struct wine_rb_entry entry;
|
||||
DEVICE_OBJECT *device;
|
||||
};
|
||||
|
||||
static int root_pnp_devices_rb_compare( const void *key, const struct wine_rb_entry *entry )
|
||||
{
|
||||
const struct root_pnp_device *device = WINE_RB_ENTRY_VALUE( entry, const struct root_pnp_device, entry );
|
||||
const WCHAR *k = key;
|
||||
|
||||
return wcsicmp( k, device->id );
|
||||
}
|
||||
|
||||
static struct wine_rb_tree root_pnp_devices = { root_pnp_devices_rb_compare };
|
||||
|
||||
static NTSTATUS WINAPI pnp_manager_device_pnp( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||
|
@ -783,7 +807,74 @@ void pnp_manager_start(void)
|
|||
ERR("Failed to create PnP manager driver, status %#x.\n", status);
|
||||
}
|
||||
|
||||
static void destroy_root_pnp_device( struct wine_rb_entry *entry, void *context )
|
||||
{
|
||||
struct root_pnp_device *device = WINE_RB_ENTRY_VALUE(entry, struct root_pnp_device, entry);
|
||||
remove_device( device->device );
|
||||
}
|
||||
|
||||
void pnp_manager_stop(void)
|
||||
{
|
||||
wine_rb_destroy( &root_pnp_devices, destroy_root_pnp_device, NULL );
|
||||
IoDeleteDriver( pnp_manager );
|
||||
}
|
||||
|
||||
void pnp_manager_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;
|
||||
DEVICE_OBJECT *device;
|
||||
NTSTATUS status;
|
||||
unsigned int i;
|
||||
HDEVINFO set;
|
||||
|
||||
TRACE("Searching for new root-enumerated devices for driver %s.\n", debugstr_w(driver_name));
|
||||
|
||||
set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES );
|
||||
if (set == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
ERR("Failed to build device set, error %#x.\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; SetupDiEnumDeviceInfo( set, i, &sp_device ); ++i)
|
||||
{
|
||||
if (!SetupDiGetDeviceRegistryPropertyW( set, &sp_device, SPDRP_SERVICE,
|
||||
NULL, (BYTE *)buffer, sizeof(buffer), NULL )
|
||||
|| lstrcmpiW( buffer, driver_name ))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL );
|
||||
|
||||
if (wine_rb_get( &root_pnp_devices, id ))
|
||||
continue;
|
||||
|
||||
TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id));
|
||||
|
||||
if ((status = IoCreateDevice( pnp_manager, sizeof(struct root_pnp_device), NULL,
|
||||
FILE_DEVICE_CONTROLLER, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &device )))
|
||||
{
|
||||
ERR("Failed to create root-enumerated PnP device %s, status %#x.\n", debugstr_w(id), status);
|
||||
continue;
|
||||
}
|
||||
|
||||
pnp_device = device->DeviceExtension;
|
||||
wcscpy( pnp_device->id, id );
|
||||
pnp_device->device = device;
|
||||
if (wine_rb_put( &root_pnp_devices, id, &pnp_device->entry ))
|
||||
{
|
||||
ERR("Failed to insert device %s into tree.\n", debugstr_w(id));
|
||||
IoDeleteDevice( device );
|
||||
continue;
|
||||
}
|
||||
|
||||
start_device( device, set, &sp_device );
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(set);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue