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?rev=42149&r1=42148&r2=42149&view=diff
==============================================================================
--- 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.h?rev=42149&r1=42148&r2=42149&view=diff
==============================================================================
--- 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;
 


Reply via email to