hidclass requires the minidriver to do this, and to return success from IRP_MN_START_DEVICE.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winehid.sys/main.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/winehid.sys/main.c b/dlls/winehid.sys/main.c index 0f18514208a..975deac993f 100644 --- a/dlls/winehid.sys/main.c +++ b/dlls/winehid.sys/main.c @@ -68,6 +68,14 @@ static NTSTATUS WINAPI internal_ioctl(DEVICE_OBJECT *device, IRP *irp) } }
+static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) +{ + HID_DEVICE_EXTENSION *ext = device->DeviceExtension; + + IoSkipCurrentIrpStackLocation(irp); + return IoCallDriver(ext->NextDeviceObject, irp); +} + static NTSTATUS WINAPI add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *device) { TRACE("(%p, %p)\n", driver, device); @@ -81,6 +89,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path) TRACE("(%p, %s)\n", driver, debugstr_w(path->Buffer));
driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = internal_ioctl; + driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; driver->DriverExtension->AddDevice = add_device;
memset(®istration, 0, sizeof(registration));
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winebus.sys/main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index 97a333dc8c3..acd166758e7 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -607,6 +607,10 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) status = STATUS_SUCCESS; break;
+ case IRP_MN_START_DEVICE: + status = STATUS_SUCCESS; + break; + case IRP_MN_REMOVE_DEVICE: { struct pnp_device *pnp_device = ext->pnp_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@gmail.com --- Unchanged from previous submission.
Tested with a Hauppauge 955Q (2040:b123), installed using WinTV 8.5. Note however that the driver still does not run with upstream Wine; it needs an additional patch to expose composite device interfaces from wineusb (or from a layered driver on top of wineusb).
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;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=89016
Your paranoid android.
=== w8 (32 bit report) ===
ntoskrnl.exe: driver.c:272: Test failed: Got unexpected test_load_image_notify_count 0.
=== w864 (64 bit report) ===
ntoskrnl.exe: 0b2c:ntoskrnl: unhandled exception c0000005 at 00007FF9FBF63DAA