ntoskrnl.exe: IoInvalidateDeviceRelations() receives the parent PDO.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-11-06 23:55:02 -06:00 committed by Alexandre Julliard
parent a60a014dc4
commit ca683dcaad
8 changed files with 96 additions and 22 deletions

View File

@ -1471,6 +1471,7 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
{
static const WCHAR auto_format[] = {'\\','D','e','v','i','c','e','\\','%','0','8','x',0};
NTSTATUS status;
struct wine_device *wine_device;
DEVICE_OBJECT *device;
HANDLE manager = get_device_manager();
static unsigned int auto_idx = 0;
@ -1479,11 +1480,12 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
if (!(device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(DEVICE_OBJECT) + ext_size, 1 )))
if (!(wine_device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(struct wine_device) + ext_size, 1 )))
return STATUS_NO_MEMORY;
device = &wine_device->device_obj;
device->DriverObject = driver;
device->DeviceExtension = device + 1;
device->DeviceExtension = wine_device + 1;
device->DeviceType = type;
device->StackSize = 1;
@ -1549,9 +1551,11 @@ void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
if (status == STATUS_SUCCESS)
{
struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj);
DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
while (*prev && *prev != device) prev = &(*prev)->NextDevice;
if (*prev) *prev = (*prev)->NextDevice;
ExFreePool( wine_device->children );
ObDereferenceObject( device );
}
}

View File

@ -86,4 +86,10 @@ static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
'\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
'\\','S','e','r','v','i','c','e','s',
'\\',0};
struct wine_device
{
DEVICE_OBJECT device_obj;
DEVICE_RELATIONS *children;
};
#endif

View File

@ -318,25 +318,18 @@ static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *
}
}
static void handle_bus_relations( DEVICE_OBJECT *device )
static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set )
{
static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0};
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
BOOL need_driver = TRUE;
HDEVINFO set;
HKEY key;
/* We could (should?) do a full IRP_MN_QUERY_DEVICE_RELATIONS query,
* but we don't have to, we have the DEVICE_OBJECT of the new device
* so we can simply handle the process here */
if (get_device_instance_id( device, device_instance_id ))
return;
set = SetupDiCreateDeviceInfoList( NULL, NULL );
if (!SetupDiCreateDeviceInfoW( set, device_instance_id, &GUID_NULL, NULL, NULL, 0, &sp_device )
&& !SetupDiOpenDeviceInfoW( set, device_instance_id, NULL, 0, &sp_device ))
{
@ -364,19 +357,90 @@ static void handle_bus_relations( DEVICE_OBJECT *device )
}
start_device( device, set, &sp_device );
SetupDiDestroyDeviceInfoList( set );
}
static void remove_device( DEVICE_OBJECT *device )
{
struct wine_device *wine_device = CONTAINING_RECORD(device, struct wine_device, device_obj);
TRACE("Removing device %p.\n", device);
if (wine_device->children)
{
ULONG i;
for (i = 0; i < wine_device->children->Count; ++i)
remove_device( wine_device->children->Objects[i] );
}
send_power_irp( device, PowerDeviceD3 );
send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL );
send_pnp_irp( device, IRP_MN_REMOVE_DEVICE );
}
static BOOL device_in_list( const DEVICE_RELATIONS *list, const DEVICE_OBJECT *device )
{
ULONG i;
for (i = 0; i < list->Count; ++i)
{
if (list->Objects[i] == device)
return TRUE;
}
return FALSE;
}
static void handle_bus_relations( DEVICE_OBJECT *parent )
{
struct wine_device *wine_parent = CONTAINING_RECORD(parent, struct wine_device, device_obj);
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
DEVICE_RELATIONS *relations;
IO_STATUS_BLOCK irp_status;
IO_STACK_LOCATION *irpsp;
NTSTATUS status;
HDEVINFO set;
IRP *irp;
ULONG i;
TRACE( "(%p)\n", parent );
set = SetupDiCreateDeviceInfoList( NULL, NULL );
parent = IoGetAttachedDevice( parent );
if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, parent, NULL, 0, NULL, NULL, &irp_status )))
{
SetupDiDestroyDeviceInfoList( set );
return;
}
irpsp = IoGetNextIrpStackLocation( irp );
irpsp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
irpsp->Parameters.QueryDeviceRelations.Type = BusRelations;
if ((status = send_device_irp( parent, irp, (ULONG_PTR *)&relations )))
{
ERR("Failed to enumerate child devices, status %#x.\n", status);
SetupDiDestroyDeviceInfoList( set );
return;
}
TRACE("Got %u devices.\n", relations->Count);
for (i = 0; i < relations->Count; ++i)
{
DEVICE_OBJECT *child = relations->Objects[i];
if (!wine_parent->children || !device_in_list( wine_parent->children, child ))
{
TRACE("Adding new device %p.\n", child);
enumerate_new_device( child, set );
}
}
ExFreePool( wine_parent->children );
wine_parent->children = relations;
SetupDiDestroyDeviceInfoList( set );
}
/***********************************************************************
* IoInvalidateDeviceRelations (NTOSKRNL.EXE.@)
*/

View File

@ -54,3 +54,4 @@ DWORD check_bus_option(const UNICODE_STRING *option, DWORD default_value) DECLSP
BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
HANDLE driver_key DECLSPEC_HIDDEN;
DEVICE_OBJECT *bus_pdo DECLSPEC_HIDDEN;

View File

@ -357,7 +357,7 @@ static void handle_DeviceMatchingCallback(void *context, IOReturn result, void *
struct platform_private *private = impl_from_DEVICE_OBJECT(device);
private->device = IOHIDDevice;
private->buffer = NULL;
IoInvalidateDeviceRelations(device, BusRelations);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
}

View File

@ -996,7 +996,7 @@ static void try_add_device(unsigned int index)
HeapFree(GetProcessHeap(), 0, serial);
return;
}
IoInvalidateDeviceRelations(device, BusRelations);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
else
{

View File

@ -1268,7 +1268,7 @@ static void try_add_device(struct udev_device *dev)
return;
}
#endif
IoInvalidateDeviceRelations(device, BusRelations);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
else
{

View File

@ -89,7 +89,8 @@ static DRIVER_OBJECT *driver_obj;
static DEVICE_OBJECT *mouse_obj;
/* The root-enumerated device stack. */
static DEVICE_OBJECT *bus_pdo, *bus_fdo;
DEVICE_OBJECT *bus_pdo;
static DEVICE_OBJECT *bus_fdo;
HANDLE driver_key;
@ -560,7 +561,7 @@ static void mouse_device_create(void)
mouse_obj = bus_create_hid_device(busidW, 0, 0, -1, 0, 0, busidW, FALSE,
&wine_mouse_class, &mouse_vtbl, 0);
IoInvalidateDeviceRelations(mouse_obj, BusRelations);
IoInvalidateDeviceRelations(bus_pdo, BusRelations);
}
static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
@ -572,6 +573,9 @@ static NTSTATUS fdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
switch (irpsp->MinorFunction)
{
case IRP_MN_QUERY_DEVICE_RELATIONS:
irp->IoStatus.u.Status = handle_IRP_MN_QUERY_DEVICE_RELATIONS(irp);
break;
case IRP_MN_START_DEVICE:
mouse_device_create();
@ -613,11 +617,6 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp)
switch (irpsp->MinorFunction)
{
case IRP_MN_QUERY_DEVICE_RELATIONS:
TRACE("IRP_MN_QUERY_DEVICE_RELATIONS\n");
status = handle_IRP_MN_QUERY_DEVICE_RELATIONS(irp);
irp->IoStatus.u.Status = status;
break;
case IRP_MN_QUERY_ID:
TRACE("IRP_MN_QUERY_ID\n");
status = handle_IRP_MN_QUERY_ID(device, irp);