- Make ks and portcls compile under msvc
[reactos.git] / reactos / drivers / ksfilter / ks / irp.c
index 988af9d..2603701 100644 (file)
@@ -34,6 +34,18 @@ KsDereferenceBusObject(
     UNIMPLEMENTED;
 }
 
+/*
+    @unimplemented
+*/
+KSDDKAPI
+VOID
+NTAPI
+KsDereferenceSoftwareBusObject(
+    IN KSDEVICE_HEADER  Header)
+{
+    UNIMPLEMENTED;
+}
+
 /*
     @implemented
 */
@@ -746,7 +758,7 @@ KsDispatchFastReadFailure(
 
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -755,11 +767,55 @@ KsCancelIo(
     IN  OUT PLIST_ENTRY QueueHead,
     IN  PKSPIN_LOCK SpinLock)
 {
-    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);
+
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -768,7 +824,49 @@ KsReleaseIrpOnCancelableQueue(
     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 */
+    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
+
+    /* 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 +881,95 @@ KsRemoveIrpFromCancelableQueue(
     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))
+    /* point to queue head */
+    CurEntry = QueueHead;
+
+    do
     {
-        if (RemovalOperation == KsAcquireOnly)
+        /* 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)
         {
-            if (ListLocation == KsListEntryHead)
-                Entry = (PQUEUE_ENTRY)QueueHead->Flink;
-            else
-                Entry = (PQUEUE_ENTRY)QueueHead->Blink;
+            /* reached end of list */
+            break;
         }
-        else if (RemovalOperation == KsAcquireAndRemove)
+
+        /* get irp offset */
+        Irp = (PIRP)CONTAINING_RECORD(Irp, IRP, Tail.Overlay.ListEntry);
+
+        if (Irp->Cancel)
         {
-            if (ListLocation == KsListEntryTail)
-                Entry = (PQUEUE_ENTRY)RemoveTailList(QueueHead);
-            else
-                Entry = (PQUEUE_ENTRY)RemoveHeadList(QueueHead);
+            /* 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;
+    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);
 
-    Irp = Entry->Irp;
+    if (RemovalOperation == KsAcquireAndRemove || RemovalOperation == KsAcquireAndRemoveOnlySingleItem)
+    {
+        /* remove it */
+        RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+    }
 
-    if (RemovalOperation == KsAcquireAndRemove)
-        ExFreePool(Entry);
+    /* release list lock */
+    KeReleaseSpinLockFromDpcLevel(SpinLock);
 
-    return Irp;
+    /* release cancel spinlock */
+    IoReleaseCancelSpinLock(OldIrql);
+    /* no non canceled irp has been found */
+    return NULL;
 }
 
 /*
@@ -848,7 +992,7 @@ KsMoveIrpsOnCancelableQueue(
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -856,7 +1000,20 @@ NTAPI
 KsRemoveSpecificIrpFromCancelableQueue(
     IN  PIRP Irp)
 {
-    UNIMPLEMENTED;
+    PKSPIN_LOCK SpinLock;
+    KIRQL OldLevel;
+
+    /* get internal queue lock */
+    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
+
+    /* acquire spinlock */
+    KeAcquireSpinLock(SpinLock, &OldLevel);
+
+    /* remove the irp from the list */
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+    /* release spinlock */
+    KeReleaseSpinLock(SpinLock, OldLevel);
 }
 
 
@@ -873,11 +1030,63 @@ KsAddIrpToCancelableQueue(
     IN  KSLIST_ENTRY_LOCATION ListLocation,
     IN  PDRIVER_CANCEL DriverCancel OPTIONAL)
 {
-    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 internal queue lock */
+    KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) = 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);
+    }
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 VOID
@@ -886,7 +1095,34 @@ KsCancelRoutine(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  PIRP Irp)
 {
-    UNIMPLEMENTED;
+    PKSPIN_LOCK SpinLock;
+    KIRQL OldLevel;
+
+    /* get internal queue lock */
+    SpinLock = KSQUEUE_SPINLOCK_IRP_STORAGE(Irp);
+
+    /* 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);
+    }
 }
 
 /*
@@ -970,8 +1206,8 @@ FindMatchingCreateItem(
     return STATUS_NOT_FOUND;
 }
 
-NTAPI
 NTSTATUS
+NTAPI
 KspCreate(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  PIRP Irp)
@@ -1154,8 +1390,8 @@ RosDeviceInterfaceReferenceStringHack(
 
 }
 
-NTAPI
 NTSTATUS
+NTAPI
 KspDeviceControl(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  PIRP Irp)
@@ -1189,8 +1425,8 @@ KspDeviceControl(
     return ObjectHeader->DispatchTable.DeviceIoControl(DeviceObject, Irp);
 }
 
-NTAPI
 NTSTATUS
+NTAPI
 KspDispatchIrp(
     IN  PDEVICE_OBJECT DeviceObject,
     IN  PIRP Irp)
@@ -1409,3 +1645,29 @@ KsDispatchIrp(
         return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
     }
 }
+
+/*
+    @unimplemented
+*/
+KSDDKAPI
+ULONG
+NTAPI
+KsGetNodeIdFromIrp(
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    return (ULONG)-1;
+}
+
+/*
+    @unimplemented
+*/
+KSDDKAPI
+PKSPIN
+NTAPI
+KsGetPinFromIrp(
+    IN PIRP Irp)
+{
+    UNIMPLEMENTED
+    return NULL;
+}