Author: janderwald Date: Thu Jul 23 02:13:04 2009 New Revision: 42149
URL: http://svn.reactos.org/svn/reactos?rev=42149&view=rev Log: - Remove old irp queue implementation - Implement KsCancelIo, KsReleaseIrpOnCancelableQueue, KsRemoveIrpFromCancelableQueue, KsRemoveSpecificIrpFromCancelableQueue, KsAddIrpToCancelableQueue, KsCancelRoutine
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c trunk/reactos/drivers/ksfilter/ks/kstypes.h
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/irp.c?r... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] Thu Jul 23 02:13:04 2009 @@ -746,7 +746,7 @@
/* - @unimplemented + @implemented */ KSDDKAPI VOID @@ -755,11 +755,55 @@ IN OUT PLIST_ENTRY QueueHead, IN PKSPIN_LOCK SpinLock) { - UNIMPLEMENTED; -} - -/* - @unimplemented + PDRIVER_CANCEL OldDriverCancel; + PIO_STACK_LOCATION IoStack; + PLIST_ENTRY Entry; + PIRP Irp; + KIRQL OldLevel; + + /* acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + /* point to first entry */ + Entry = QueueHead->Flink; + /* loop all items */ + while(Entry != QueueHead) + { + /* get irp offset */ + Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); + + /* set cancelled bit */ + Irp->Cancel = TRUE; + + /* now set the cancel routine */ + OldDriverCancel = IoSetCancelRoutine(Irp, NULL); + if (OldDriverCancel) + { + /* this irp hasnt been yet used, so free to cancel */ + KeReleaseSpinLock(SpinLock, OldLevel); + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* acquire cancel spinlock */ + IoAcquireCancelSpinLock(&Irp->CancelIrql); + + /* call provided cancel routine */ + OldDriverCancel(IoStack->DeviceObject, Irp); + + /* re-acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + } + /* move on to next entry */ + Entry = Entry->Flink; + } + + /* the irp has already been canceled */ + KeReleaseSpinLock(SpinLock, OldLevel); + +} + +/* + @implemented */ KSDDKAPI VOID @@ -768,7 +812,51 @@ IN PIRP Irp, IN PDRIVER_CANCEL DriverCancel OPTIONAL) { - UNIMPLEMENTED; + PKSPIN_LOCK SpinLock; + PDRIVER_CANCEL OldDriverCancel; + PIO_STACK_LOCATION IoStack; + KIRQL OldLevel; + + /* check for required parameters */ + if (!Irp) + return; + + if (!DriverCancel) + { + /* default to KsCancelRoutine */ + DriverCancel = KsCancelRoutine; + } + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get internal queue lock + * see KsAddIrpToCancelableQueue + */ + SpinLock = (PKSPIN_LOCK)Irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry.Flink; + + /* acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + + /* now set the cancel routine */ + OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); + + if (Irp->Cancel && OldDriverCancel == NULL) + { + /* the irp has already been canceled */ + KeReleaseSpinLock(SpinLock, OldLevel); + + /* cancel routine requires that cancel spinlock is held */ + IoAcquireCancelSpinLock(&Irp->CancelIrql); + + /* cancel irp */ + DriverCancel(IoStack->DeviceObject, Irp); + } + else + { + /* done */ + KeReleaseSpinLock(SpinLock, OldLevel); + } }
/* @@ -783,49 +871,95 @@ IN KSLIST_ENTRY_LOCATION ListLocation, IN KSIRP_REMOVAL_OPERATION RemovalOperation) { - PQUEUE_ENTRY Entry = NULL; PIRP Irp; + PLIST_ENTRY CurEntry; KIRQL OldIrql;
+ /* check parameters */ if (!QueueHead || !SpinLock) return NULL;
+ /* check if parameter ListLocation is valid */ if (ListLocation != KsListEntryTail && ListLocation != KsListEntryHead) return NULL;
- if (RemovalOperation != KsAcquireOnly && RemovalOperation != KsAcquireAndRemove) - return NULL; - + /* acquire list lock */ KeAcquireSpinLock(SpinLock, &OldIrql);
- if (!IsListEmpty(QueueHead)) - { - if (RemovalOperation == KsAcquireOnly) - { - if (ListLocation == KsListEntryHead) - Entry = (PQUEUE_ENTRY)QueueHead->Flink; - else - Entry = (PQUEUE_ENTRY)QueueHead->Blink; - } - else if (RemovalOperation == KsAcquireAndRemove) - { - if (ListLocation == KsListEntryTail) - Entry = (PQUEUE_ENTRY)RemoveTailList(QueueHead); - else - Entry = (PQUEUE_ENTRY)RemoveHeadList(QueueHead); - } - } + /* point to queue head */ + CurEntry = QueueHead; + + do + { + /* reset irp to null */ + Irp = NULL; + + /* iterate to next entry */ + if (ListLocation == KsListEntryHead) + CurEntry = CurEntry->Flink; + else + CurEntry = CurEntry->Blink; + + /* is the end of list reached */ + if (CurEntry == QueueHead) + { + /* reached end of list */ + break; + } + + /* get irp offset */ + Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry); + + if (Irp->Cancel) + { + /* irp has been canceled */ + break; + } + + if (Irp->CancelRoutine) + { + /* remove cancel routine */ + Irp->CancelRoutine = NULL; + + if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) + { + /* remove irp from list */ + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + } + + if (RemovalOperation == KsAcquireAndRemoveOnlySingleItem || RemovalOperation == KsAcquireOnlySingleItem) + break; + } + + }while(TRUE); + + /* release lock */ KeReleaseSpinLock(SpinLock, OldIrql);
- if (!Entry) - return NULL; - - Irp = Entry->Irp; - - if (RemovalOperation == KsAcquireAndRemove) - ExFreePool(Entry); - - return Irp; + if (!Irp || Irp->CancelRoutine == NULL) + { + /* either an irp has been acquired or nothing found */ + return Irp; + } + + /* time to remove the canceled irp */ + IoAcquireCancelSpinLock(&OldIrql); + /* acquire list lock */ + KeAcquireSpinLockAtDpcLevel(SpinLock); + + if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem) + { + /* remove it */ + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + } + + /* release list lock */ + KeReleaseSpinLockFromDpcLevel(SpinLock); + + /* release cancel spinlock */ + IoReleaseCancelSpinLock(OldIrql); + /* no non canceled irp has been found */ + return NULL; }
/* @@ -848,7 +982,7 @@ }
/* - @unimplemented + @implemented */ KSDDKAPI VOID @@ -856,7 +990,22 @@ KsRemoveSpecificIrpFromCancelableQueue( IN PIRP Irp) { - UNIMPLEMENTED; + PKSPIN_LOCK SpinLock; + KIRQL OldLevel; + + /* get internal queue lock + * see KsAddIrpToCancelableQueue + */ + SpinLock = (PKSPIN_LOCK)Irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry.Flink; + + /* acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + + /* remove the irp from the list */ + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + + /* release spinlock */ + KeReleaseSpinLock(SpinLock, OldLevel); }
@@ -873,11 +1022,66 @@ IN KSLIST_ENTRY_LOCATION ListLocation, IN PDRIVER_CANCEL DriverCancel OPTIONAL) { - UNIMPLEMENTED; -} - -/* - @unimplemented + PDRIVER_CANCEL OldDriverCancel; + PIO_STACK_LOCATION IoStack; + KIRQL OldLevel; + + /* check for required parameters */ + if (!QueueHead || !SpinLock || !Irp) + return; + + if (!DriverCancel) + { + /* default to KsCancelRoutine */ + DriverCancel = KsCancelRoutine; + } + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + + if (ListLocation == KsListEntryTail) + { + /* insert irp to tail of list */ + InsertTailList(QueueHead, &Irp->Tail.Overlay.ListEntry); + } + else + { + /* insert irp to head of list */ + InsertHeadList(QueueHead, &Irp->Tail.Overlay.ListEntry); + } + + /* store the spinlock in the device queue list entry, + * as other fields may have been internally been used + * used in KsCancelRoutine + */ + Irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry.Flink = (PLIST_ENTRY)SpinLock; + + /* now set the cancel routine */ + OldDriverCancel = IoSetCancelRoutine(Irp, DriverCancel); + + if (Irp->Cancel && OldDriverCancel == NULL) + { + /* the irp has already been canceled */ + KeReleaseSpinLock(SpinLock, OldLevel); + + /* cancel routine requires that cancel spinlock is held */ + IoAcquireCancelSpinLock(&Irp->CancelIrql); + + /* cancel irp */ + DriverCancel(IoStack->DeviceObject, Irp); + } + else + { + /* done */ + KeReleaseSpinLock(SpinLock, OldLevel); + } +} + +/* + @implemented */ KSDDKAPI VOID @@ -886,7 +1090,36 @@ IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; + PKSPIN_LOCK SpinLock; + KIRQL OldLevel; + + /* get internal queue lock + * see KsAddIrpToCancelableQueue + */ + SpinLock = (PKSPIN_LOCK)Irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry.Flink; + + /* acquire spinlock */ + KeAcquireSpinLock(SpinLock, &OldLevel); + + /* sanity check */ + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* release cancel spinlock */ + IoReleaseCancelSpinLock(DISPATCH_LEVEL); + + /* remove the irp from the list */ + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + + /* release spinlock */ + KeReleaseSpinLock(SpinLock, OldLevel); + + /* has the irp already been canceled */ + if (Irp->IoStatus.Status != STATUS_CANCELLED) + { + /* let's complete it */ + Irp->IoStatus.Status = STATUS_CANCELLED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } }
/*
Modified: trunk/reactos/drivers/ksfilter/ks/kstypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/kstypes... ============================================================================== --- trunk/reactos/drivers/ksfilter/ks/kstypes.h [iso-8859-1] (original) +++ trunk/reactos/drivers/ksfilter/ks/kstypes.h [iso-8859-1] Thu Jul 23 02:13:04 2009 @@ -74,12 +74,6 @@ typedef struct { LIST_ENTRY Entry; - PIRP Irp; -}QUEUE_ENTRY, *PQUEUE_ENTRY; - -typedef struct -{ - LIST_ENTRY Entry; UNICODE_STRING SymbolicLink; }SYMBOLIC_LINK_ENTRY, *PSYMBOLIC_LINK_ENTRY;