[PATCH resend 6/8] ntoskrnl.exe: IoInvalidateDeviceRelations() receives the parent PDO.

Zebediah Figura z.figura12 at gmail.com
Wed Nov 6 23:55:02 CST 2019


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ntoskrnl.exe/ntoskrnl.c         |  8 ++-
 dlls/ntoskrnl.exe/ntoskrnl_private.h |  6 ++
 dlls/ntoskrnl.exe/pnp.c              | 84 ++++++++++++++++++++++++----
 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              | 13 ++---
 8 files changed, 96 insertions(+), 22 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 1c9c75d8ddf..fcfc0b0314f 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -1472,6 +1472,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;
@@ -1480,11 +1481,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;
 
@@ -1550,9 +1552,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 b5244ef1641..256e945e6f3 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 a3dbe772ae9..62a32a4afc4 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -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.@)
  */
diff --git a/dlls/winebus.sys/bus.h b/dlls/winebus.sys/bus.h
index de8ddf7ad9d..a2508784899 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 f0f10ca98e0..ad542b5dfbf 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 64c5a8a1d2c..5f07ee24354 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -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
     {
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 6fa6efb7dce..b2cf62dedb0 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -1268,7 +1268,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 ec8e0f7f480..24ddb21c4ae 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -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);
-- 
2.23.0




More information about the wine-devel mailing list