From: Rémi Bernon rbernon@codeweavers.com
--- dlls/hidclass.sys/device.c | 13 ++-- dlls/hidclass.sys/hid.h | 5 +- dlls/hidclass.sys/pnp.c | 153 +++++++++++++++++-------------------- 3 files changed, 82 insertions(+), 89 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index e6b34077a77..7c0154fda7a 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -219,7 +219,7 @@ static struct hid_report *hid_queue_pop_report( struct hid_queue *queue ) static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *packet ) { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; const BOOL polled = ext->u.pdo.information.Polled; ULONG size, report_len = polled ? packet->reportBufferLen : desc->InputLength; struct hid_report *last_report, *report; @@ -297,8 +297,9 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack
static HIDP_REPORT_IDS *find_report_with_type_and_id( BASE_DEVICE_EXTENSION *ext, BYTE type, BYTE id, BOOL any_id ) { - HIDP_REPORT_IDS *report, *reports = ext->u.pdo.device_desc.ReportIDs; - ULONG report_count = ext->u.pdo.device_desc.ReportIDsLength; + BASE_DEVICE_EXTENSION *fdo_ext = ext->u.pdo.parent_fdo->DeviceExtension; + HIDP_REPORT_IDS *report, *reports = fdo_ext->u.fdo.device_desc.ReportIDs; + ULONG report_count = fdo_ext->u.fdo.device_desc.ReportIDsLength;
for (report = reports; report != reports + report_count; report++) { @@ -315,7 +316,7 @@ static DWORD CALLBACK hid_device_thread(void *args) { DEVICE_OBJECT *device = (DEVICE_OBJECT*)args; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; BOOL polled = ext->u.pdo.information.Polled; HIDP_REPORT_IDS *report; HID_XFER_PACKET *packet; @@ -618,7 +619,7 @@ NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) } case IOCTL_HID_GET_COLLECTION_DESCRIPTOR: { - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc;
irp->IoStatus.Information = desc->PreparsedDataLength; if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < desc->PreparsedDataLength) @@ -694,7 +695,7 @@ NTSTATUS WINAPI pdo_read(DEVICE_OBJECT *device, IRP *irp) { struct hid_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); struct hid_report *report; BOOL removed; diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 7b5d5f19298..25a121b2ed1 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -48,6 +48,9 @@ typedef struct _BASE_DEVICE_EXTENSION /* this must be the first member */ HID_DEVICE_EXTENSION hid_ext;
+ HID_DEVICE_ATTRIBUTES attrs; + HIDP_DEVICE_DESC device_desc; + DEVICE_OBJECT *child_pdo; } fdo;
@@ -55,8 +58,8 @@ typedef struct _BASE_DEVICE_EXTENSION { DEVICE_OBJECT *parent_fdo;
+ HIDP_COLLECTION_DESC *collection_desc; HID_COLLECTION_INFORMATION information; - HIDP_DEVICE_DESC device_desc;
ULONG poll_interval; HANDLE halt_event; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index ddccffb91e2..549c3489aa3 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -113,7 +113,7 @@ C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]) < sizeof(RAWIN
static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param) { - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; INPUT input = {.type = INPUT_HARDWARE}; struct hid_packet hid = {0};
@@ -189,34 +189,70 @@ static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *b return STATUS_SUCCESS; }
-static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) +static NTSTATUS get_hid_device_desc( minidriver *minidriver, DEVICE_OBJECT *device, HIDP_DEVICE_DESC *desc ) { - BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext; - HID_DEVICE_ATTRIBUTES attr = {0}; HID_DESCRIPTOR descriptor = {0}; - HIDP_COLLECTION_DESC *desc; - DEVICE_OBJECT *child_pdo; - BYTE *reportDescriptor; - UNICODE_STRING string; - WCHAR pdo_name[255]; IO_STATUS_BLOCK io; - USAGE page, usage; - NTSTATUS status; + BYTE *report_desc; INT i;
- call_minidriver( IOCTL_HID_GET_DEVICE_ATTRIBUTES, fdo, NULL, 0, &attr, sizeof(attr), &io ); + call_minidriver( IOCTL_HID_GET_DEVICE_DESCRIPTOR, device, NULL, 0, &descriptor, sizeof(descriptor), &io ); + if (io.Status) return io.Status; + + for (i = 0; i < descriptor.bNumDescriptors; i++) + if (descriptor.DescriptorList[i].bReportType == HID_REPORT_DESCRIPTOR_TYPE) + break; + if (i >= descriptor.bNumDescriptors) return STATUS_NOT_FOUND; + + if (!(report_desc = malloc( descriptor.DescriptorList[i].wReportLength ))) return STATUS_NO_MEMORY; + call_minidriver( IOCTL_HID_GET_REPORT_DESCRIPTOR, device, NULL, 0, report_desc, + descriptor.DescriptorList[i].wReportLength, &io ); + if (!io.Status) io.Status = HidP_GetCollectionDescription( report_desc, descriptor.DescriptorList[i].wReportLength, + PagedPool, desc ); + free( report_desc ); + + if (io.Status && io.Status != HIDP_STATUS_SUCCESS) return STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; +} + +static NTSTATUS initialize_device( minidriver *minidriver, DEVICE_OBJECT *device ) +{ + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + IO_STATUS_BLOCK io; + NTSTATUS status; + + call_minidriver( IOCTL_HID_GET_DEVICE_ATTRIBUTES, device, NULL, 0, &ext->u.fdo.attrs, + sizeof(ext->u.fdo.attrs), &io ); if (io.Status != STATUS_SUCCESS) { ERR( "Minidriver failed to get attributes, status %#lx.\n", io.Status ); - return; + return io.Status; + } + + if ((status = get_hid_device_desc( minidriver, device, &ext->u.fdo.device_desc ))) + { + ERR( "Failed to get HID device description, status %#lx\n", status ); + return status; }
+ return STATUS_SUCCESS; +} + +static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) +{ + BASE_DEVICE_EXTENSION *fdo_ext = fdo->DeviceExtension, *pdo_ext; + DEVICE_OBJECT *child_pdo; + UNICODE_STRING string; + WCHAR pdo_name[255]; + USAGE page, usage; + NTSTATUS status; + 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(fdo->DriverObject, sizeof(*pdo_ext), &string, 0, 0, FALSE, &child_pdo))) { - ERR( "Failed to create child PDO, status %#lx.\n", io.Status ); + ERR( "Failed to create child PDO, status %#lx.\n", status ); return; } fdo_ext->u.fdo.child_pdo = child_pdo; @@ -225,60 +261,22 @@ static void create_child(minidriver *minidriver, DEVICE_OBJECT *fdo) pdo_ext->u.pdo.parent_fdo = fdo; list_init( &pdo_ext->u.pdo.queues ); KeInitializeSpinLock( &pdo_ext->u.pdo.queues_lock ); + + pdo_ext->u.pdo.collection_desc = fdo_ext->u.fdo.device_desc.CollectionDesc; + wcscpy(pdo_ext->device_id, fdo_ext->device_id); wcscpy(pdo_ext->instance_id, fdo_ext->instance_id); wcscpy(pdo_ext->container_id, fdo_ext->container_id); pdo_ext->class_guid = fdo_ext->class_guid;
- pdo_ext->u.pdo.information.VendorID = attr.VendorID; - pdo_ext->u.pdo.information.ProductID = attr.ProductID; - pdo_ext->u.pdo.information.VersionNumber = attr.VersionNumber; + pdo_ext->u.pdo.information.VendorID = fdo_ext->u.fdo.attrs.VendorID; + pdo_ext->u.pdo.information.ProductID = fdo_ext->u.fdo.attrs.ProductID; + pdo_ext->u.pdo.information.VersionNumber = fdo_ext->u.fdo.attrs.VersionNumber; pdo_ext->u.pdo.information.Polled = minidriver->minidriver.DevicesArePolled; + pdo_ext->u.pdo.information.DescriptorSize = pdo_ext->u.pdo.collection_desc->PreparsedDataLength;
- call_minidriver( IOCTL_HID_GET_DEVICE_DESCRIPTOR, fdo, NULL, 0, &descriptor, sizeof(descriptor), &io ); - if (io.Status != STATUS_SUCCESS) - { - ERR( "Cannot get Device Descriptor, status %#lx\n", status ); - IoDeleteDevice(child_pdo); - return; - } - for (i = 0; i < descriptor.bNumDescriptors; i++) - if (descriptor.DescriptorList[i].bReportType == HID_REPORT_DESCRIPTOR_TYPE) - break; - - if (i >= descriptor.bNumDescriptors) - { - ERR("No Report Descriptor found in reply\n"); - IoDeleteDevice(child_pdo); - return; - } - - reportDescriptor = malloc(descriptor.DescriptorList[i].wReportLength); - call_minidriver( IOCTL_HID_GET_REPORT_DESCRIPTOR, fdo, NULL, 0, reportDescriptor, - descriptor.DescriptorList[i].wReportLength, &io ); - if (io.Status != STATUS_SUCCESS) - { - ERR( "Cannot get Report Descriptor, status %#lx\n", status ); - free(reportDescriptor); - IoDeleteDevice(child_pdo); - return; - } - - io.Status = HidP_GetCollectionDescription( reportDescriptor, descriptor.DescriptorList[i].wReportLength, - PagedPool, &pdo_ext->u.pdo.device_desc ); - free(reportDescriptor); - if (io.Status != HIDP_STATUS_SUCCESS) - { - ERR("Cannot parse Report Descriptor\n"); - IoDeleteDevice(child_pdo); - return; - } - - desc = pdo_ext->u.pdo.device_desc.CollectionDesc; - pdo_ext->u.pdo.information.DescriptorSize = desc->PreparsedDataLength; - - page = desc->UsagePage; - usage = desc->Usage; + page = pdo_ext->u.pdo.collection_desc->UsagePage; + usage = pdo_ext->u.pdo.collection_desc->Usage; if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE) pdo_ext->u.pdo.rawinput_handle = WINE_MOUSE_HANDLE; else if (page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD) @@ -302,6 +300,7 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) minidriver *minidriver = find_minidriver(device->DriverObject); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + NTSTATUS status;
TRACE("irp %p, minor function %#x.\n", irp, stack->MinorFunction);
@@ -340,25 +339,17 @@ static NTSTATUS fdo_pnp(DEVICE_OBJECT *device, IRP *irp) }
case IRP_MN_START_DEVICE: - { - NTSTATUS ret; - - if ((ret = minidriver->PNPDispatch(device, irp))) - return ret; - create_child(minidriver, device); - return STATUS_SUCCESS; - } + status = minidriver->PNPDispatch( device, irp ); + if (!status) status = initialize_device( minidriver, device ); + if (!status) create_child( minidriver, device ); + return status;
case IRP_MN_REMOVE_DEVICE: - { - NTSTATUS ret; - - ret = minidriver->PNPDispatch(device, irp); - - IoDetachDevice(ext->u.fdo.hid_ext.NextDeviceObject); - IoDeleteDevice(device); - return ret; - } + status = minidriver->PNPDispatch( device, irp ); + HidP_FreeCollectionDescription( &ext->u.fdo.device_desc ); + IoDetachDevice( ext->u.fdo.hid_ext.NextDeviceObject ); + IoDeleteDevice( device ); + return status;
default: return minidriver->PNPDispatch(device, irp); @@ -373,7 +364,7 @@ static WCHAR *query_hardware_ids(DEVICE_OBJECT *device) static const WCHAR hid_format[] = L"HID_DEVICE";
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; HID_COLLECTION_INFORMATION *info = &ext->u.pdo.information; WCHAR *dst; DWORD size; @@ -443,7 +434,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; - HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; + HIDP_COLLECTION_DESC *desc = ext->u.pdo.collection_desc; NTSTATUS status = irp->IoStatus.Status; struct hid_queue *queue, *next; KIRQL irql; @@ -551,8 +542,6 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp) hid_queue_destroy( queue ); KeReleaseSpinLock( &ext->u.pdo.queues_lock, irql );
- HidP_FreeCollectionDescription(&ext->u.pdo.device_desc); - RtlFreeUnicodeString(&ext->u.pdo.link_name);
irp->IoStatus.Status = STATUS_SUCCESS;