[RDBSS]
authorPierre Schweitzer <pierre@reactos.org>
Sat, 15 Jul 2017 10:05:32 +0000 (10:05 +0000)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 15 Jul 2017 10:05:32 +0000 (10:05 +0000)
Implement RxNotifyChangeDirectory(), RxLowIoNotifyChangeDirectoryCompletion(), RxCancelNotifyChangeDirectoryRequestsForVNetRoot()

This means the first parts of the directory watch are here. Though, NFS driver doesn't support these, but at least, it reduces the UNIMPLEMENTED spam!

CORE-11327

svn path=/trunk/; revision=75353

reactos/sdk/include/ddk/mrx.h
reactos/sdk/lib/drivers/rdbsslib/rdbss.c

index 2115646..fa486f6 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _RXMINIRDR_
 #define _RXMINIRDR_
 
+#define RxSetIoStatusStatus(R, S) (R)->CurrentIrp->IoStatus.Status = (S)
+#define RxSetIoStatusInfo(R, I) (R)->CurrentIrp->IoStatus.Information = (I)
+
 #define RxShouldPostCompletion() ((KeGetCurrentIrql() >= DISPATCH_LEVEL))
 
 #define RX_REGISTERMINI_FLAG_DONT_PROVIDE_UNCS 0x00000001
index bc810d5..722d0a6 100644 (file)
@@ -913,13 +913,100 @@ RxCancelNotifyChangeDirectoryRequestsForFobx(
     UNIMPLEMENTED;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 RxCancelNotifyChangeDirectoryRequestsForVNetRoot(
    PV_NET_ROOT VNetRoot,
    BOOLEAN ForceFilesClosed)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    KIRQL OldIrql;
+    NTSTATUS Status;
+    PLIST_ENTRY Entry;
+    PRX_CONTEXT Context;
+    LIST_ENTRY ContextsToCancel;
+
+    /* Init a list for the contexts to cancel */
+    InitializeListHead(&ContextsToCancel);
+
+    /* Lock our list lock */
+    KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
+
+    /* Now, browse all the active contexts, to find the associated ones */
+    Entry = RxActiveContexts.Flink;
+    while (Entry != &RxActiveContexts)
+    {
+        Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
+        Entry = Entry->Flink;
+
+        /* Not the IRP we're looking for, ignore */
+        if (Context->MajorFunction != IRP_MJ_DIRECTORY_CONTROL ||
+            Context->MinorFunction != IRP_MN_NOTIFY_CHANGE_DIRECTORY)
+        {
+            continue;
+        }
+
+        /* Not the VNetRoot we're looking for, ignore */
+        if (Context->pFcb == NULL ||
+            (PV_NET_ROOT)Context->NotifyChangeDirectory.pVNetRoot != VNetRoot)
+        {
+            continue;
+        }
+
+        /* No cancel routine (can't be cancel, then), ignore */
+        if (Context->MRxCancelRoutine == NULL)
+        {
+            continue;
+        }
+
+        /* At that point, we found a matching context
+         * If we're not asked to force close, then fail - it's still open
+         */
+        if (!ForceFilesClosed)
+        {
+            Status = STATUS_FILES_OPEN;
+            break;
+        }
+
+        /* Mark our context as cancelled */
+        SetFlag(Context->Flags, RX_CONTEXT_FLAG_CANCELLED);
+
+        /* Move it to our list */
+        RemoveEntryList(&Context->ContextListEntry);
+        InsertTailList(&ContextsToCancel, &Context->ContextListEntry);
+
+        InterlockedIncrement((volatile long *)&Context->ReferenceCount);
+    }
+
+    /* Done with the contexts */
+    KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
+
+    if (Status != STATUS_SUCCESS)
+    {
+        return Status;
+    }
+
+    /* Now, handle all our "extracted" contexts */
+    while (!IsListEmpty(&ContextsToCancel))
+    {
+        Entry = RemoveHeadList(&ContextsToCancel);
+        Context = CONTAINING_RECORD(Entry, RX_CONTEXT, ContextListEntry);
+
+        /* If they had an associated IRP (should be always true) */
+        if (Context->CurrentIrp != NULL)
+        {
+            /* Then, call cancel routine */
+            ASSERT(Context->MRxCancelRoutine != NULL);
+            DPRINT1("Canceling %p with %p\n", Context, Context->MRxCancelRoutine);
+            Context->MRxCancelRoutine(Context);
+        }
+
+        /* And delete the context */
+        RxDereferenceAndDeleteRxContext(Context);
+    }
+
+    return Status;
 }
 
 VOID
@@ -5325,6 +5412,25 @@ RxLowIoLockControlShell(
     return STATUS_NOT_IMPLEMENTED;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+RxLowIoNotifyChangeDirectoryCompletion(
+    PRX_CONTEXT RxContext)
+{
+    PAGED_CODE();
+
+    DPRINT("Completing NCD with: %lx, %lx\n", RxContext->IoStatusBlock.Status, RxContext->IoStatusBlock.Information);
+
+    /* Just copy back the IO_STATUS to the IRP */
+    RxSetIoStatusStatus(RxContext, RxContext->IoStatusBlock.Status);
+    RxSetIoStatusInfo(RxContext, RxContext->IoStatusBlock.Information);
+
+    return RxContext->IoStatusBlock.Status;
+}
+
 /*
  * @implemented
  */
@@ -5469,12 +5575,63 @@ RxLowIoReadShellCompletion(
     return Status;
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 RxNotifyChangeDirectory(
     PRX_CONTEXT RxContext)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PIRP Irp;
+    NTSTATUS Status;
+    PIO_STACK_LOCATION Stack;
+
+    PAGED_CODE();
+
+    /* The IRP can abviously wait */
+    SetFlag(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
+
+    /* Initialize its lowio */
+    RxInitializeLowIoContext(&RxContext->LowIoContext, LOWIO_OP_NOTIFY_CHANGE_DIRECTORY);
+
+    _SEH2_TRY
+    {
+        /* Lock user buffer */
+        Stack = RxContext->CurrentIrpSp;
+        RxLockUserBuffer(RxContext, IoWriteAccess, Stack->Parameters.NotifyDirectory.Length);
+
+        /* Copy parameters from IO_STACK */
+        RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.WatchTree = BooleanFlagOn(Stack->Flags, SL_WATCH_TREE);
+        RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.CompletionFilter = Stack->Parameters.NotifyDirectory.CompletionFilter;
+        RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.NotificationBufferLength = Stack->Parameters.NotifyDirectory.Length;
+
+        /* If we have an associated MDL */
+        Irp = RxContext->CurrentIrp;
+        if (Irp->MdlAddress != NULL)
+        {
+            /* Then, call mini-rdr */
+            RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.pNotificationBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+            if (RxContext->LowIoContext.ParamsFor.NotifyChangeDirectory.pNotificationBuffer != NULL)
+            {
+                Status = RxLowIoSubmit(RxContext, RxLowIoNotifyChangeDirectoryCompletion);
+            }
+            else
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+            }
+        }
+        else
+        {
+            Status = STATUS_INVALID_PARAMETER;
+        }
+    }
+    _SEH2_FINALLY
+    {
+        /* All correct */
+    }
+    _SEH2_END;
+
+    return Status;
 }
 
 NTSTATUS