From: Cameron Gutman Date: Tue, 3 Jan 2012 19:37:03 +0000 (+0000) Subject: [NDISUIO] X-Git-Tag: backups/wlan-bringup@60693~45 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=31b309b74def815acbc21dd8a26852230437d881 [NDISUIO] - Make reads cancelable - Fix a bug in IOCTL_CANCEL_READ handling svn path=/branches/wlan-bringup/; revision=54823 --- diff --git a/drivers/network/ndisuio/ioctl.c b/drivers/network/ndisuio/ioctl.c index a00c173fed1..0bb191d1313 100644 --- a/drivers/network/ndisuio/ioctl.c +++ b/drivers/network/ndisuio/ioctl.c @@ -109,7 +109,7 @@ CancelPacketRead(PIRP Irp, PIO_STACK_LOCATION IrpSp) { PacketEntry->PacketLength = 0; - ExInterlockedInsertTailList(&AdapterContext->PacketList, + ExInterlockedInsertHeadList(&AdapterContext->PacketList, &PacketEntry->ListEntry, &AdapterContext->Spinlock); diff --git a/drivers/network/ndisuio/readwrite.c b/drivers/network/ndisuio/readwrite.c index 61bfc51bbb0..b6549710688 100644 --- a/drivers/network/ndisuio/readwrite.c +++ b/drivers/network/ndisuio/readwrite.c @@ -11,6 +11,30 @@ #define NDEBUG #include +VOID +NTAPI +ReadIrpCancel(PDEVICE_OBJECT DeviceObject, PIRP Irp) +{ + PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; + PNDISUIO_PACKET_ENTRY PacketEntry; + + /* Release the cancel spin lock */ + IoReleaseCancelSpinLock(Irp->CancelIrql); + + /* Indicate a 0-byte packet on the queue to cancel the read */ + PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY)); + if (PacketEntry) + { + PacketEntry->PacketLength = 0; + + ExInterlockedInsertHeadList(&AdapterContext->PacketList, + &PacketEntry->ListEntry, + &AdapterContext->Spinlock); + + KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE); + } +} + NTSTATUS NTAPI NduDispatchRead(PDEVICE_OBJECT DeviceObject, @@ -19,7 +43,7 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject, PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2; - KIRQL OldIrql; + KIRQL OldIrql, OldCancelIrql; NTSTATUS Status; PLIST_ENTRY ListEntry; PNDISUIO_PACKET_ENTRY PacketEntry = NULL; @@ -36,6 +60,22 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject, return STATUS_INVALID_PARAMETER; } + /* Make the read cancellable */ + IoAcquireCancelSpinLock(&OldCancelIrql); + IoSetCancelRoutine(Irp, ReadIrpCancel); + if (Irp->Cancel) + { + IoReleaseCancelSpinLock(OldCancelIrql); + + /* Indicate a 0 byte read */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; + } + IoReleaseCancelSpinLock(OldCancelIrql); + while (TRUE) { KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql); @@ -52,10 +92,22 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject, TRUE, NULL); if (Status != STATUS_SUCCESS) + { + /* Remove the cancel routine */ + IoAcquireCancelSpinLock(&OldCancelIrql); + IoSetCancelRoutine(Irp, NULL); + IoReleaseCancelSpinLock(OldCancelIrql); + break; + } } else { + /* Remove the cancel routine */ + IoAcquireCancelSpinLock(&OldCancelIrql); + IoSetCancelRoutine(Irp, NULL); + IoReleaseCancelSpinLock(OldCancelIrql); + /* Remove the first packet in the list */ ListEntry = RemoveHeadList(&AdapterContext->PacketList); PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);