From c5565a74c3441645d0e1da3fe6d6d5acc38c47a1 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 19 Apr 2021 23:37:10 -0500 Subject: [PATCH] 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 Signed-off-by: Alexandre Julliard --- 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; -- 2.11.4.GIT