From: Matthias Gorzellik matthias.gorzellik@gmail.com
--- dlls/winebus.sys/main.c | 72 ++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 30 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index f7a634dbfe2..c48bb593164 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -87,7 +87,7 @@ struct device_extension
struct hid_report *last_reports[256]; struct list reports; - IRP *pending_read; + IRP *pending_reads[256];
UINT32 report_fixups; UINT64 unix_device; @@ -252,13 +252,13 @@ static WCHAR *get_compatible_ids(DEVICE_OBJECT *device) return dst; }
-static IRP *pop_pending_read(struct device_extension *ext) +static IRP *pop_pending_read(struct device_extension *ext, ULONG report_id) { IRP *pending;
RtlEnterCriticalSection(&ext->cs); - pending = ext->pending_read; - ext->pending_read = NULL; + pending = ext->pending_reads[report_id]; + ext->pending_reads[report_id] = NULL; RtlLeaveCriticalSection(&ext->cs);
return pending; @@ -269,11 +269,13 @@ static void remove_pending_irps(DEVICE_OBJECT *device) struct device_extension *ext = device->DeviceExtension; IRP *pending;
- if ((pending = pop_pending_read(ext))) - { - pending->IoStatus.Status = STATUS_DELETE_PENDING; - pending->IoStatus.Information = 0; - IoCompleteRequest(pending, IO_NO_INCREMENT); + for (UINT i = 0; i < ARRAY_SIZE(ext->pending_reads); ++i) { + if ((pending = pop_pending_read(ext, i))) + { + pending->IoStatus.Status = STATUS_DELETE_PENDING; + pending->IoStatus.Information = 0; + IoCompleteRequest(pending, IO_NO_INCREMENT); + } } }
@@ -539,11 +541,13 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re RtlEnterCriticalSection(&ext->cs); list_add_tail(&ext->reports, &report->entry);
- if (!ext->collection_desc.ReportIDs[0].ReportID) last_report = ext->last_reports[0]; - else last_report = ext->last_reports[report_buf[0]]; - memcpy(last_report->buffer, report_buf, report_len); + for ( UINT i = 0; i < ext->collection_desc.CollectionDescLength; ++i ) { + if (!ext->collection_desc.CollectionDesc[i].ReportIDs[0].ReportID) last_report = ext->last_reports[0]; + else last_report = ext->last_reports[report_buf[0]]; + memcpy(last_report->buffer, report_buf, report_len); + }
- if ((irp = pop_pending_read(ext))) + if ((irp = pop_pending_read(ext, report_buf[0]))) { deliver_next_report(ext, irp); IoCompleteRequest(irp, IO_NO_INCREMENT); @@ -1027,17 +1031,22 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) &ext->collection_desc))) { status = STATUS_SUCCESS; - reports = ext->collection_desc.ReportIDs; - for (i = 0; i < ext->collection_desc.ReportIDsLength; ++i) - { - if (!(size = reports[i].InputLength)) continue; - size = offsetof( struct hid_report, buffer[size] ); - if (!(report = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) status = STATUS_NO_MEMORY; - else + for ( ULONG j = 0; j < ext->collection_desc.CollectionDescLength; ++j) { + reports = ext->collection_desc.CollectionDesc[j].ReportIDs; + for (i = 0; i < ext->collection_desc.CollectionDesc[j].ReportIDsLength; ++i) { - report->length = reports[i].InputLength; - report->buffer[0] = reports[i].ReportID; - ext->last_reports[reports[i].ReportID] = report; + if (!(size = reports[i].InputLength)) continue; + size = offsetof( struct hid_report, buffer[size] ); + if (!(report = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) { + status = STATUS_NO_MEMORY; + break; + } + else + { + report->length = reports[i].InputLength; + report->buffer[0] = reports[i].ReportID; + ext->last_reports[reports[i].ReportID] = report; + } } } if (!status) ext->state = DEVICE_STATE_STARTED; @@ -1068,11 +1077,13 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) LIST_FOR_EACH_ENTRY_SAFE(report, next, &ext->reports, struct hid_report, entry) RtlFreeHeap(GetProcessHeap(), 0, report);
- reports = ext->collection_desc.ReportIDs; - for (i = 0; i < ext->collection_desc.ReportIDsLength; ++i) - { - if (!reports[i].InputLength) continue; - RtlFreeHeap(GetProcessHeap(), 0, ext->last_reports[reports[i].ReportID]); + for ( UINT j = 0; j < ext->collection_desc.CollectionDescLength; ++j ) { + reports = ext->collection_desc.CollectionDesc[j].ReportIDs; + for (i = 0; i < ext->collection_desc.CollectionDesc[j].ReportIDsLength; ++i) + { + if (!reports[i].InputLength) continue; + RtlFreeHeap(GetProcessHeap(), 0, ext->last_reports[reports[i].ReportID]); + } } HidP_FreeCollectionDescription(&ext->collection_desc); RtlFreeHeap(GetProcessHeap(), 0, ext->report_desc); @@ -1259,9 +1270,10 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) { if (!deliver_next_report(ext, irp)) { + UCHAR reportId = ((PUCHAR)irp->UserBuffer)[0]; /* hidclass.sys should guarantee this */ - assert(!ext->pending_read); - ext->pending_read = irp; + assert(!ext->pending_reads[reportId]); + ext->pending_reads[reportId] = irp; IoMarkIrpPending(irp); irp->IoStatus.Status = STATUS_PENDING; }