mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
286 lines
10 KiB
Diff
286 lines
10 KiB
Diff
From cdc9b0c079ab9001800e97d2b6303f743f8c2175 Mon Sep 17 00:00:00 2001
|
|
From: Zebediah Figura <z.figura12@gmail.com>
|
|
Date: Thu, 27 Jun 2019 22:30:17 -0500
|
|
Subject: [PATCH] ntoskrnl.exe: IoInvalidateDeviceRelations() receives the
|
|
parent PDO.
|
|
|
|
Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
|
|
---
|
|
dlls/ntoskrnl.exe/ntoskrnl.c | 8 ++-
|
|
dlls/ntoskrnl.exe/ntoskrnl_private.h | 6 ++
|
|
dlls/ntoskrnl.exe/pnp.c | 86 ++++++++++++++++++++++++----
|
|
dlls/winebus.sys/bus.h | 1 +
|
|
dlls/winebus.sys/bus_iohid.c | 2 +-
|
|
dlls/winebus.sys/bus_sdl.c | 2 +-
|
|
dlls/winebus.sys/bus_udev.c | 2 +-
|
|
dlls/winebus.sys/main.c | 11 ++--
|
|
8 files changed, 97 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
|
|
index 92f9afab33..620f9572da 100644
|
|
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
|
|
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
|
|
@@ -1469,6 +1469,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;
|
|
@@ -1477,11 +1478,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;
|
|
|
|
@@ -1547,9 +1549,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 );
|
|
}
|
|
}
|
|
diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h
|
|
index b5244ef164..256e945e6f 100644
|
|
--- a/dlls/ntoskrnl.exe/ntoskrnl_private.h
|
|
+++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h
|
|
@@ -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
|
|
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
|
|
index 30865a05dc..c618885d42 100644
|
|
--- a/dlls/ntoskrnl.exe/pnp.c
|
|
+++ b/dlls/ntoskrnl.exe/pnp.c
|
|
@@ -316,25 +316,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 ))
|
|
{
|
|
@@ -362,19 +355,92 @@ 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];
|
|
+
|
|
+ TRACE("%p, %p\n", wine_parent, wine_parent->children);
|
|
+
|
|
+ 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.@)
|
|
*/
|
|
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h
|
|
index de8ddf7ad9..a250878489 100644
|
|
--- a/dlls/winebus.sys/bus.h
|
|
+++ b/dlls/winebus.sys/bus.h
|
|
@@ -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;
|
|
diff --git a/dlls/winebus.sys/bus_iohid.c b/dlls/winebus.sys/bus_iohid.c
|
|
index 7933374007..e992db8376 100644
|
|
--- a/dlls/winebus.sys/bus_iohid.c
|
|
+++ b/dlls/winebus.sys/bus_iohid.c
|
|
@@ -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);
|
|
}
|
|
}
|
|
|
|
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
|
|
index d24e21cff8..781deda767 100644
|
|
--- a/dlls/winebus.sys/bus_sdl.c
|
|
+++ b/dlls/winebus.sys/bus_sdl.c
|
|
@@ -988,7 +988,7 @@ static void try_add_device(SDL_JoystickID index)
|
|
HeapFree(GetProcessHeap(), 0, serial);
|
|
return;
|
|
}
|
|
- IoInvalidateDeviceRelations(device, BusRelations);
|
|
+ IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
|
}
|
|
else
|
|
{
|
|
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
|
|
index 08ad8765af..9a3df9ea6b 100644
|
|
--- a/dlls/winebus.sys/bus_udev.c
|
|
+++ b/dlls/winebus.sys/bus_udev.c
|
|
@@ -1241,7 +1241,7 @@ static void try_add_device(struct udev_device *dev)
|
|
return;
|
|
}
|
|
#endif
|
|
- IoInvalidateDeviceRelations(device, BusRelations);
|
|
+ IoInvalidateDeviceRelations(bus_pdo, BusRelations);
|
|
}
|
|
else
|
|
{
|
|
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
|
|
index b96e38c538..26200bde3e 100644
|
|
--- a/dlls/winebus.sys/main.c
|
|
+++ b/dlls/winebus.sys/main.c
|
|
@@ -73,7 +73,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;
|
|
|
|
@@ -482,6 +483,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:
|
|
if (check_bus_option(&SDL_enabled, 1))
|
|
{
|
|
@@ -521,11 +525,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);
|
|
--
|
|
2.17.1
|
|
|