Zebediah Figura : hidclass.sys: Defer creating a child device until IRP_MN_START_DEVICE.
Alexandre Julliard
julliard at winehq.org
Tue Apr 20 16:27:44 CDT 2021
Module: wine
Branch: master
Commit: c5565a74c3441645d0e1da3fe6d6d5acc38c47a1
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c5565a74c3441645d0e1da3fe6d6d5acc38c47a1
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Mon Apr 19 23:37:10 2021 -0500
hidclass.sys: Defer creating a child device until IRP_MN_START_DEVICE.
This is necessary to allow the Hauppauge CIR receiver driver for cx2310x drivers
(hcw10cir.sys) to start.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/hidclass.sys/pnp.c | 91 ++++++++++++++++++++++--------------
dlls/ntoskrnl.exe/tests/driver_hid.c | 3 +-
2 files changed, 57 insertions(+), 37 deletions(-)
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c
index 7b365d267ed..de6f409a16b 100644
--- a/dlls/hidclass.sys/pnp.c
+++ b/dlls/hidclass.sys/pnp.c
@@ -99,17 +99,11 @@ static UINT32 alloc_rawinput_handle(void)
static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *bus_pdo)
{
- WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN], pdo_name[255];
- BASE_DEVICE_EXTENSION *ext, *pdo_ext;
- HID_DEVICE_ATTRIBUTES attr = {0};
- DEVICE_OBJECT *fdo, *child_pdo;
- UNICODE_STRING string;
- USAGE page, usage;
+ WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN];
+ BASE_DEVICE_EXTENSION *ext;
+ DEVICE_OBJECT *fdo;
NTSTATUS status;
minidriver *minidriver;
- HID_DESCRIPTOR descriptor;
- BYTE *reportDescriptor;
- INT i;
if ((status = get_device_id(bus_pdo, BusQueryDeviceID, device_id)))
{
@@ -148,30 +142,48 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
return status;
}
+ IoAttachDeviceToDeviceStack(fdo, bus_pdo);
+ fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ return STATUS_SUCCESS;
+}
+
+static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo)
+{
+ BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext;
+ HID_DEVICE_ATTRIBUTES attr = {0};
+ HID_DESCRIPTOR descriptor;
+ DEVICE_OBJECT *child_pdo;
+ BYTE *reportDescriptor;
+ UNICODE_STRING string;
+ WCHAR pdo_name[255];
+ USAGE page, usage;
+ NTSTATUS status;
+ INT i;
+
status = call_minidriver(IOCTL_HID_GET_DEVICE_ATTRIBUTES, fdo, NULL, 0, &attr, sizeof(attr));
if (status != STATUS_SUCCESS)
{
ERR("Minidriver failed to get Attributes(%x)\n",status);
- IoDeleteDevice(fdo);
- return status;
+ return;
}
- swprintf(pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", driver, bus_pdo);
+ swprintf(pdo_name, ARRAY_SIZE(pdo_name), L"\\Device\\HID#%p&%p", fdo->DriverObject,
+ fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject);
RtlInitUnicodeString(&string, pdo_name);
- if ((status = IoCreateDevice(driver, sizeof(*ext), &string, 0, 0, FALSE, &child_pdo)))
+ if ((status = IoCreateDevice(fdo->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo)))
{
ERR("Failed to create child PDO, status %#x.\n", status);
- IoDeleteDevice(fdo);
- return status;
+ return;
}
- ext->u.fdo.child_pdo = child_pdo;
+ fdo_ext->u.fdo.child_pdo = child_pdo;
pdo_ext = child_pdo->DeviceExtension;
pdo_ext->u.pdo.parent_fdo = fdo;
InitializeListHead(&pdo_ext->u.pdo.irp_queue);
KeInitializeSpinLock(&pdo_ext->u.pdo.irp_queue_lock);
- wcscpy(pdo_ext->device_id, ext->device_id);
- wcscpy(pdo_ext->instance_id, ext->instance_id);
+ wcscpy(pdo_ext->device_id, fdo_ext->device_id);
+ wcscpy(pdo_ext->instance_id, fdo_ext->instance_id);
pdo_ext->u.pdo.information.VendorID = attr.VendorID;
pdo_ext->u.pdo.information.ProductID = attr.ProductID;
@@ -183,8 +195,7 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
{
ERR("Cannot get Device Descriptor(%x)\n",status);
IoDeleteDevice(child_pdo);
- IoDeleteDevice(fdo);
- return status;
+ return;
}
for (i = 0; i < descriptor.bNumDescriptors; i++)
if (descriptor.DescriptorList[i].bReportType == HID_REPORT_DESCRIPTOR_TYPE)
@@ -194,8 +205,7 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
{
ERR("No Report Descriptor found in reply\n");
IoDeleteDevice(child_pdo);
- IoDeleteDevice(fdo);
- return status;
+ return;
}
reportDescriptor = HeapAlloc(GetProcessHeap(), 0, descriptor.DescriptorList[i].wReportLength);
@@ -206,8 +216,7 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
ERR("Cannot get Report Descriptor(%x)\n",status);
HeapFree(GetProcessHeap(), 0, reportDescriptor);
IoDeleteDevice(child_pdo);
- IoDeleteDevice(fdo);
- return status;
+ return;
}
pdo_ext->u.pdo.preparsed_data = ParseDescriptor(reportDescriptor, descriptor.DescriptorList[i].wReportLength);
@@ -216,15 +225,12 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
{
ERR("Cannot parse Report Descriptor\n");
IoDeleteDevice(child_pdo);
- IoDeleteDevice(fdo);
- return STATUS_NOT_SUPPORTED;
+ return;
}
pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.preparsed_data->dwSize;
- IoAttachDeviceToDeviceStack(fdo, bus_pdo);
-
- IoInvalidateDeviceRelations(bus_pdo, BusRelations);
+ IoInvalidateDeviceRelations(fdo_ext->u.fdo.hid_ext.PhysicalDeviceObject, BusRelations);
page = pdo_ext->u.pdo.preparsed_data->caps.UsagePage;
usage = pdo_ext->u.pdo.preparsed_data->caps.Usage;
@@ -241,9 +247,6 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b
sizeof(HID_XFER_PACKET) + pdo_ext->u.pdo.preparsed_data->caps.InputReportByteLength);
HID_StartDeviceThread(child_pdo);
-
- fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- return STATUS_SUCCESS;
}
static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp)
@@ -259,6 +262,7 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp)
case IRP_MN_QUERY_DEVICE_RELATIONS:
{
DEVICE_RELATIONS *devices;
+ DEVICE_OBJECT *child;
if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
return minidriver->PNPDispatch(device, irp);
@@ -270,9 +274,16 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp)
return STATUS_NO_MEMORY;
}
- devices->Objects[0] = ext->u.fdo.child_pdo;
- call_fastcall_func1(ObfReferenceObject, ext->u.fdo.child_pdo);
- devices->Count = 1;
+ if ((child = ext->u.fdo.child_pdo))
+ {
+ devices->Objects[0] = ext->u.fdo.child_pdo;
+ call_fastcall_func1(ObfReferenceObject, ext->u.fdo.child_pdo);
+ devices->Count = 1;
+ }
+ else
+ {
+ devices->Count = 0;
+ }
irp->IoStatus.Information = (ULONG_PTR)devices;
irp->IoStatus.u.Status = STATUS_SUCCESS;
@@ -280,6 +291,16 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp)
return IoCallDriver(ext->u.fdo.hid_ext.NextDeviceObject, irp);
}
+ case IRP_MN_START_DEVICE:
+ {
+ NTSTATUS ret;
+
+ if ((ret = minidriver->PNPDispatch(device, irp)))
+ return ret;
+ create_child(minidriver, device);
+ return STATUS_SUCCESS;
+ }
+
case IRP_MN_REMOVE_DEVICE:
{
NTSTATUS ret;
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c
index 92637f9d0bc..44ec1b09526 100644
--- a/dlls/ntoskrnl.exe/tests/driver_hid.c
+++ b/dlls/ntoskrnl.exe/tests/driver_hid.c
@@ -111,8 +111,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
if (winetest_debug > 1) trace("ioctl %#x\n", code);
- todo_wine_if (code != IOCTL_HID_READ_REPORT)
- ok(got_start_device, "expected IRP_MN_START_DEVICE before any ioctls\n");
+ ok(got_start_device, "expected IRP_MN_START_DEVICE before any ioctls\n");
irp->IoStatus.Information = 0;
More information about the wine-cvs
mailing list