forked from Mirrors/wine-wine
hidclass.sys: Support canceling read IRPs.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Aric Stewart <aric@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>stable
parent
85082e8bd3
commit
f7bc649598
|
@ -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)
|
||||||
|
|
||||||
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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue