Commit f7bc6495 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

hidclass.sys: Support canceling read IRPs.

parent 85082e8b
...@@ -134,14 +134,44 @@ static IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext) ...@@ -134,14 +134,44 @@ static IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext)
KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql);
entry = RemoveHeadList(&ext->irp_queue); while (!irp && (entry = RemoveHeadList(&ext->irp_queue)) != &ext->irp_queue)
if (entry != &ext->irp_queue) {
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry); irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry);
if (!IoSetCancelRoutine(irp, NULL))
{
/* cancel routine is already cleared, meaning that it was called. let it handle completion. */
InitializeListHead(&irp->Tail.Overlay.s.ListEntry);
irp = NULL;
}
}
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
return irp; return irp;
} }
static void WINAPI read_cancel_routine(DEVICE_OBJECT *device, IRP *irp)
{
BASE_DEVICE_EXTENSION *ext;
KIRQL old_irql;
TRACE("cancel %p IRP on device %p\n", irp, device);
ext = device->DeviceExtension;
IoReleaseCancelSpinLock(irp->CancelIrql);
KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql);
RemoveEntryList(&irp->Tail.Overlay.s.ListEntry);
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
irp->IoStatus.u.Status = STATUS_CANCELLED;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device) void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device)
{ {
BASE_DEVICE_EXTENSION *ext; BASE_DEVICE_EXTENSION *ext;
...@@ -669,10 +699,20 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) ...@@ -669,10 +699,20 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp)
KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql); KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql);
IoSetCancelRoutine(irp, read_cancel_routine);
if (irp->Cancel && !IoSetCancelRoutine(irp, NULL))
{
/* IRP was canceled before we set cancel routine */
InitializeListHead(&irp->Tail.Overlay.s.ListEntry);
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
return STATUS_CANCELLED;
}
InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry);
rc = STATUS_PENDING; IoMarkIrpPending(irp);
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql); KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
rc = STATUS_PENDING;
} }
else else
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment