[ros-diffs] [pschweitzer] 55934: [NTOSKRNL] Stub FsRtlCancelNotify Implement FsRtlCheckNotifyForDelete, FsRtlNotifyCompleteIrp, FsRtlNotifyCompleteIrpList, FsRtlNotifySetCancelRoutine

pschweitzer at svn.reactos.org pschweitzer at svn.reactos.org
Wed Feb 29 20:01:22 UTC 2012


Author: pschweitzer
Date: Wed Feb 29 20:01:21 2012
New Revision: 55934

URL: http://svn.reactos.org/svn/reactos?rev=55934&view=rev
Log:
[NTOSKRNL]
Stub FsRtlCancelNotify
Implement FsRtlCheckNotifyForDelete, FsRtlNotifyCompleteIrp, FsRtlNotifyCompleteIrpList, FsRtlNotifySetCancelRoutine

Modified:
    trunk/reactos/ntoskrnl/fsrtl/notify.c

Modified: trunk/reactos/ntoskrnl/fsrtl/notify.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/notify.c?rev=55934&r1=55933&r2=55934&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] Wed Feb 29 20:01:21 2012
@@ -13,6 +13,50 @@
 #include <debug.h>
 
 /* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
+                           IN NTSTATUS Status);
+
+BOOLEAN
+FsRtlNotifySetCancelRoutine(IN PIRP Irp,
+                            IN PNOTIFY_CHANGE NotifyChange OPTIONAL);
+
+VOID
+NTAPI
+FsRtlCancelNotify(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+    UNIMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+VOID
+FsRtlCheckNotifyForDelete(IN PLIST_ENTRY NotifyList,
+                          IN PVOID FsContext)
+{
+    PLIST_ENTRY NextEntry;
+    PNOTIFY_CHANGE NotifyChange;
+
+    if (!IsListEmpty(NotifyList))
+    {
+        /* Browse the notifications list to find the matching entry */
+        for (NextEntry = NotifyList->Flink;
+             NextEntry != NotifyList;
+             NextEntry = NextEntry->Flink)
+        {
+            NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList);
+            /* If the current record matches with the given context, it's the good one */
+            if (NotifyChange->FsContext == FsContext && !IsListEmpty(&(NotifyChange->NotifyIrps)))
+            {
+                FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_DELETE_PENDING);
+            }
+        }
+    }
+}
 
 PNOTIFY_CHANGE
 FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList,
@@ -55,10 +99,138 @@
     RealNotifySync->OwnerCount++;
 }
 
+/*
+ * @implemented
+ */
+VOID
+FsRtlNotifyCompleteIrp(IN PIRP Irp,
+                       IN PNOTIFY_CHANGE NotifyChange,
+                       IN ULONG DataLength,
+                       IN NTSTATUS Status,
+                       IN BOOLEAN SkipCompletion)
+{
+    PVOID Buffer;
+    PIO_STACK_LOCATION Stack;
+
+    PAGED_CODE();
+
+    /* Check if we need to complete */
+    if (!FsRtlNotifySetCancelRoutine(Irp, NotifyChange) && SkipCompletion)
+    {
+        return;
+    }
+
+    /* No succes => no data to return just complete */
+    if (Status != STATUS_SUCCESS)
+    {
+        goto Completion;
+    }
+
+    /* Ensure there's something to return */
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+    if (!DataLength || Stack->Parameters.NotifyDirectory.Length < DataLength)
+    {
+        Status = STATUS_NOTIFY_ENUM_DIR;
+        goto Completion;
+    }
+
+    /* Ensture there's a buffer where to find data */
+    if (!NotifyChange->AllocatedBuffer)
+    {
+        Irp->IoStatus.Information = DataLength;
+        NotifyChange->Buffer = NULL;
+        goto Completion;
+    }
+
+    /* Now, browse all the way to return data
+     * and find the one that will work. We will
+     * return data whatever happens
+     */
+    if (Irp->AssociatedIrp.SystemBuffer)
+    {
+        Buffer = Irp->AssociatedIrp.SystemBuffer;
+        goto CopyAndComplete;
+    }
+
+    if (Irp->MdlAddress)
+    {
+        Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+        goto CopyAndComplete;
+    }
+
+    if (!(Stack->Control & SL_PENDING_RETURNED))
+    {
+        Buffer = Irp->UserBuffer;
+        goto CopyAndComplete;
+    }
+
+    Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_SYNCHRONOUS_PAGING_IO);
+    Irp->AssociatedIrp.SystemBuffer = NotifyChange->AllocatedBuffer;
+    /* Nothing to copy */
+    goto ReleaseAndComplete;
+
+CopyAndComplete:
+    _SEH2_TRY
+    {
+        RtlCopyMemory(Buffer, NotifyChange->AllocatedBuffer, DataLength);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Do nothing */
+    }
+    _SEH2_END;
+
+ReleaseAndComplete:
+    PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength);
+
+    /* Release buffer UNLESS it's used */
+    if (NotifyChange->AllocatedBuffer != Irp->AssociatedIrp.SystemBuffer &&
+        NotifyChange->AllocatedBuffer)
+    {
+        ExFreePoolWithTag(NotifyChange->AllocatedBuffer, 0);
+    }
+
+    /* Prepare for return */
+    NotifyChange->AllocatedBuffer = 0;
+    NotifyChange->ThisBufferLength = 0;
+    Irp->IoStatus.Information = DataLength;
+    NotifyChange->Buffer = NULL;
+
+    /* Finally complete */
+Completion:
+    IoMarkIrpPending(Irp);
+    Irp->IoStatus.Status = Status;
+    IofCompleteRequest(Irp, EVENT_INCREMENT);
+}
+
+/*
+ * @implemented
+ */
 VOID
 FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange,
                            IN NTSTATUS Status)
 {
+    PIRP Irp;
+    ULONG DataLength;
+    PLIST_ENTRY NextEntry;
+
+    DataLength = NotifyChange->DataLength;
+
+    NotifyChange->Flags &= (INVALIDATE_BUFFERS | WATCH_TREE);
+    NotifyChange->DataLength = 0;
+    NotifyChange->LastEntry = 0;
+
+    while (!IsListEmpty(&(NotifyChange->NotifyIrps)))
+    {
+        /* We take the first entry */
+        NextEntry = RemoveHeadList(&(NotifyChange->NotifyIrps));
+        Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
+        /* We complete it */
+        FsRtlNotifyCompleteIrp(Irp, NotifyChange, DataLength, Status, TRUE);
+        /* If we're notifying success, just notify first one */
+        if (Status == STATUS_SUCCESS)
+            break;
+    }
 }
 
 VOID
@@ -72,6 +244,55 @@
         ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex));
         RealNotifySync->OwningThread = (ULONG_PTR)0;
     }
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+FsRtlNotifySetCancelRoutine(IN PIRP Irp,
+                            IN PNOTIFY_CHANGE NotifyChange OPTIONAL)
+{
+    PDRIVER_CANCEL CancelRoutine;
+
+    /* Acquire cancel lock */
+    IoAcquireCancelSpinLock(&Irp->CancelIrql);
+
+    /* If NotifyChange was given */
+    if (NotifyChange)
+    {
+        /* First get cancel routine */
+        CancelRoutine = IoSetCancelRoutine(Irp, NULL);
+        Irp->IoStatus.Information = 0;
+        /* Release cancel lock */
+        IoReleaseCancelSpinLock(Irp->CancelIrql);
+        /* If there was a cancel routine */
+        if (CancelRoutine)
+        {
+            /* Decrease reference count */
+            InterlockedDecrement((PLONG)&NotifyChange->ReferenceCount);
+            /* Notify that we removed cancel routine */
+            return TRUE;
+        }
+    }
+    else
+    {
+        /* If IRP is cancel, call FsRtl cancel routine */
+        if (Irp->Cancel)
+        {
+             FsRtlCancelNotify(NULL, Irp);
+        }
+        else
+        {
+            /* Otherwise, define FsRtl cancel routine as IRP cancel routine */
+            IoSetCancelRoutine(Irp, FsRtlCancelNotify);
+            /* Release lock */
+            IoReleaseCancelSpinLock(Irp->CancelIrql);
+        }
+    }
+
+    /* Return that we didn't removed cancel routine */
+    return FALSE;
 }
 
 /* PUBLIC FUNCTIONS **********************************************************/




More information about the Ros-diffs mailing list