[RDBSS]
[reactos.git] / reactos / sdk / lib / drivers / rxce / rxce.c
index c531409..2685567 100644 (file)
@@ -58,17 +58,59 @@ NTSTATUS
 RxInsertWorkQueueItem(
     PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
     WORK_QUEUE_TYPE WorkQueueType,
-    PRX_WORK_DISPATCH_ITEM DispatchItem);
+    PRX_WORK_QUEUE_ITEM WorkQueueItem);
 
 PVOID
 RxNewMapUserBuffer(
     PRX_CONTEXT RxContext);
 
+VOID
+NTAPI
+RxpDestroySrvCall(
+    IN PVOID Context);
+
+VOID
+RxpDispatchChangeBufferingStateRequests(
+    PSRV_CALL SrvCall,
+    PSRV_OPEN SrvOpen,
+    PLIST_ENTRY DiscardedRequests);
+
+VOID
+NTAPI
+RxScavengerTimerRoutine(
+    PVOID Context);
+
+VOID
+NTAPI
+RxTimerDispatch(
+    _In_ struct _KDPC *Dpc,
+    _In_opt_ PVOID DeferredContext,
+    _In_opt_ PVOID SystemArgument1,
+    _In_opt_ PVOID SystemArgument2);
+
 VOID
 NTAPI
 RxWorkItemDispatcher(
     PVOID Context);
 
+PVOID
+NTAPI
+_RxAllocatePoolWithTag(
+    _In_ POOL_TYPE PoolType,
+    _In_ SIZE_T NumberOfBytes,
+    _In_ ULONG Tag);
+
+VOID
+NTAPI
+_RxFreePool(
+    _In_ PVOID Buffer);
+
+VOID
+NTAPI
+_RxFreePoolWithTag(
+    _In_ PVOID Buffer,
+    _In_ ULONG Tag);
+
 extern ULONG ReadAheadGranularity;
 
 volatile LONG RxNumberOfActiveFcbs = 0;
@@ -86,12 +128,21 @@ RX_DISPATCHER RxDispatcher;
 RX_WORK_QUEUE_DISPATCHER RxDispatcherWorkQueues;
 FAST_MUTEX RxLowIoPagingIoSyncMutex;
 BOOLEAN RxContinueFromAssert = TRUE;
+ULONG RxExplodePoolTags = 1;
+LARGE_INTEGER RxTimerInterval;
+RX_SPIN_LOCK RxTimerLock;
+LIST_ENTRY RxTimerQueueHead;
+LIST_ENTRY RxRecurrentWorkItemsList;
+KDPC RxTimerDpc;
+KTIMER RxTimer;
+ULONG RxTimerTickCount;
 #if DBG
 BOOLEAN DumpDispatchRoutine = TRUE;
 #else
 BOOLEAN DumpDispatchRoutine = FALSE;
 #endif
 
+#if RDBSS_ASSERTS
 #ifdef ASSERT
 #undef ASSERT
 #endif
@@ -101,6 +152,18 @@ BOOLEAN DumpDispatchRoutine = FALSE;
     {                                             \
         RxAssert(#exp, __FILE__, __LINE__, NULL); \
     }
+#endif
+
+#if RX_POOL_WRAPPER
+#undef RxAllocatePool
+#undef RxAllocatePoolWithTag
+#undef RxFreePool
+
+#define RxAllocatePool(P, S) _RxAllocatePoolWithTag(P, S, 0)
+#define RxAllocatePoolWithTag _RxAllocatePoolWithTag
+#define RxFreePool _RxFreePool
+#define RxFreePoolWithTag _RxFreePoolWithTag
+#endif
 
 /* FUNCTIONS ****************************************************************/
 
@@ -225,7 +288,7 @@ RxAllocateFcbObject(
     /* Otherwise, allocate it */
     else
     {
-        Buffer = ExAllocatePoolWithTag(PoolType, NameSize + FcbSize + SrvOpenSize + FobxSize + NonPagedSize, RX_FCB_POOLTAG);
+        Buffer = RxAllocatePoolWithTag(PoolType, NameSize + FcbSize + SrvOpenSize + FobxSize + NonPagedSize, RX_FCB_POOLTAG);
         if (Buffer == NULL)
         {
             return NULL;
@@ -260,10 +323,10 @@ RxAllocateFcbObject(
         /* If we were not allocated from non paged, allocate the NON_PAGED_FCB now */
         if (PoolType != NonPagedPool)
         {
-            NonPagedFcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NON_PAGED_FCB), RX_NONPAGEDFCB_POOLTAG);
+            NonPagedFcb = RxAllocatePoolWithTag(NonPagedPool, sizeof(NON_PAGED_FCB), RX_NONPAGEDFCB_POOLTAG);
             if (NonPagedFcb == NULL)
             {
-                ExFreePoolWithTag(Buffer, RX_FCB_POOLTAG);
+                RxFreePoolWithTag(Buffer, RX_FCB_POOLTAG);
                 return NULL;
             }
 
@@ -399,7 +462,7 @@ RxAllocateObject(
 
     /* Now, allocate the object */
     ObjectSize = ExtensionSize + StructSize + NameLength;
-    Object = ExAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
+    Object = RxAllocatePoolWithTag(NonPagedPool, ObjectSize, Tag);
     if (Object == NULL)
     {
         return NULL;
@@ -527,6 +590,149 @@ RxBootstrapWorkerThreadDispatcher(
     RxpWorkerThreadDispatcher(RxWorkQueue, NULL);
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+RxChangeBufferingState(
+    PSRV_OPEN SrvOpen,
+    PVOID Context,
+    BOOLEAN ComputeNewState)
+{
+    PFCB Fcb;
+    NTSTATUS Status, MiniStatus;
+    ULONG NewBufferingState, OldBufferingState;
+
+    PAGED_CODE();
+
+    DPRINT("RxChangeBufferingState(%p, %p, %d)\n", SrvOpen, Context, ComputeNewState);
+
+    Fcb = (PFCB)SrvOpen->pFcb;
+    ASSERT(NodeTypeIsFcb(Fcb));
+    /* First of all, mark that buffering state is changing */
+    SetFlag(Fcb->FcbState, FCB_STATE_BUFFERSTATE_CHANGING);
+
+    /* Assume success */
+    Status = STATUS_SUCCESS;
+    _SEH2_TRY
+    {
+        /* If we're asked to compute a new state, ask the mini-rdr for it */
+        if (ComputeNewState)
+        {
+            MINIRDR_CALL_THROUGH(MiniStatus, Fcb->MRxDispatch, MRxComputeNewBufferingState,
+                                 ((PMRX_SRV_OPEN)SrvOpen, Context, &NewBufferingState));
+            if (MiniStatus != STATUS_SUCCESS)
+            {
+                NewBufferingState = 0;
+            }
+        }
+        else
+        {
+            /* If not, use SRV_OPEN state */
+            NewBufferingState = SrvOpen->BufferingFlags;
+        }
+
+        /* If no shared access, and if we're not asked to compute a new state, use maximum flags set */
+        if ((Fcb->ShareAccess.SharedRead + Fcb->ShareAccess.SharedWrite + Fcb->ShareAccess.SharedDelete) == 0 && !ComputeNewState)
+        {
+            SetFlag(NewBufferingState, FCB_STATE_BUFFERING_STATE_WITH_NO_SHARES);
+        }
+
+        /* If there's a lock operation to complete, clear that flag */
+        if (Fcb->OutstandingLockOperationsCount != 0)
+        {
+            ClearFlag(NewBufferingState, FCB_STATE_LOCK_BUFFERING_ENABLED);
+        }
+
+        /* Get the old state */
+        OldBufferingState = Fcb->FcbState & FCB_STATE_BUFFERING_STATE_MASK;
+        DPRINT("ChangeBufferingState %x -> %x (%x)\n", OldBufferingState, NewBufferingState, SrvOpen->BufferingFlags);
+
+        /* If we're dropping write cache, then flush the FCB */
+        if (BooleanFlagOn(OldBufferingState, FCB_STATE_WRITECACHING_ENABLED) &&
+            !BooleanFlagOn(NewBufferingState, FCB_STATE_WRITECACHING_ENABLED))
+        {
+            DPRINT("Flushing\n");
+
+            Status = RxFlushFcbInSystemCache(Fcb, TRUE);
+        }
+
+        /* If we're dropping read cache, then purge */
+        if (Fcb->UncleanCount == 0 ||
+            (BooleanFlagOn(OldBufferingState, FCB_STATE_READCACHING_ENABLED) &&
+             !BooleanFlagOn(NewBufferingState, FCB_STATE_READCACHING_ENABLED)) ||
+            BooleanFlagOn(NewBufferingState, FCB_STATE_DELETE_ON_CLOSE))
+        {
+            DPRINT("Purging\n");
+
+            if (!NT_SUCCESS(Status))
+            {
+                 DPRINT("Previous flush failed with status: %lx\n", Status);
+            }
+
+            CcPurgeCacheSection(&Fcb->NonPaged->SectionObjectPointers, NULL, 0, TRUE);
+        }
+
+        /* If there's already a change pending in SRV_OPEN */
+        if (ComputeNewState && BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING))
+        {
+            /* If there's a FOBX at least */
+            if (!IsListEmpty(&SrvOpen->FobxList))
+            {
+                PRX_CONTEXT RxContext;
+
+                /* Create a fake context to pass to the mini-rdr */
+                RxContext = RxCreateRxContext(NULL, Fcb->RxDeviceObject, RX_CONTEXT_FLAG_MUST_SUCCEED_NONBLOCKING | RX_CONTEXT_FLAG_WAIT);
+                if (RxContext != NULL)
+                {
+                    PFOBX Fobx;
+
+                    RxContext->pFcb = RX_GET_MRX_FCB(Fcb);
+
+                    /* Give the first FOBX */
+                    Fobx = CONTAINING_RECORD(SrvOpen->FobxList.Flink, FOBX, FobxQLinks);
+                    RxContext->pFobx = (PMRX_FOBX)Fobx;
+                    RxContext->pRelevantSrvOpen = Fobx->pSrvOpen;
+
+                    /* If there was a delayed close, perform it */
+                    if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_CLOSE_DELAYED))
+                    {
+                        DPRINT("Oplock break close for %p\n", SrvOpen);
+
+                        RxCloseAssociatedSrvOpen(Fobx, RxContext);
+                    }
+                    /* Otherwise, inform the mini-rdr about completion */
+                    else
+                    {
+                        MINIRDR_CALL_THROUGH(MiniStatus, Fcb->MRxDispatch, MRxCompleteBufferingStateChangeRequest,
+                                             (RxContext, (PMRX_SRV_OPEN)SrvOpen, Context));
+                        (void)MiniStatus;
+                    }
+
+                    RxDereferenceAndDeleteRxContext(RxContext);
+                }
+            }
+        }
+
+        /* Set the new state */
+        Fcb->FcbState ^= (NewBufferingState ^ Fcb->FcbState) & FCB_STATE_BUFFERING_STATE_MASK;
+    }
+    _SEH2_FINALLY
+    {
+        /* Job done, clear the flag */
+        ClearFlag(Fcb->FcbState, FCB_STATE_BUFFERSTATE_CHANGING);
+
+        if (!BooleanFlagOn(NewBufferingState, FCB_STATE_FILETIMECACHEING_ENABLED))
+        {
+            ClearFlag(Fcb->FcbState, FCB_STATE_TIME_AND_SIZE_ALREADY_SET);
+        }
+    }
+    _SEH2_END;
+
+    return Status;
+}
+
 NTSTATUS
 RxCheckVNetRootCredentials(
     PRX_CONTEXT RxContext,
@@ -698,11 +904,71 @@ RxCompleteRequest_Real(
     }
 }
 
+/*
+ * @implemented
+ */
 VOID
 RxCompleteSrvOpenKeyAssociation(
     IN OUT PSRV_OPEN SrvOpen)
 {
-    UNIMPLEMENTED;
+    PSRV_CALL SrvCall;
+
+    SrvCall = (PSRV_CALL)((PFCB)SrvOpen->pFcb)->VNetRoot->pNetRoot->pSrvCall;
+    /* Only handle requests if opening was a success */
+    if (SrvOpen->Condition == Condition_Good)
+    {
+        KIRQL OldIrql;
+        BOOLEAN ProcessChange;
+        LIST_ENTRY DiscardedRequests;
+
+        /* Initialize our discarded requests list */
+        InitializeListHead(&DiscardedRequests);
+
+        RxAcquireBufferingManagerMutex(&SrvCall->BufferingManager);
+
+        /* Transfer our requests in the SRV_CALL */
+        RxTransferList(&SrvCall->BufferingManager.SrvOpenLists[0], &SrvOpen->SrvOpenKeyList);
+
+        /* Was increased in RxInitiateSrvOpenKeyAssociation(), opening is done */
+        InterlockedDecrement(&SrvCall->BufferingManager.NumberOfOutstandingOpens);
+
+        /* Dispatch requests and get the discarded ones */
+        RxpDispatchChangeBufferingStateRequests(SrvCall, SrvOpen, &DiscardedRequests);
+
+        RxReleaseBufferingManagerMutex(&SrvCall->BufferingManager);
+
+        /* Is there still anything to process? */
+        KeAcquireSpinLock(&SrvCall->BufferingManager.SpinLock, &OldIrql);
+        if (IsListEmpty(&SrvCall->BufferingManager.HandlerList))
+        {
+            ProcessChange = FALSE;
+        }
+        else
+        {
+            ProcessChange = (SrvCall->BufferingManager.HandlerInactive == FALSE);
+            if (ProcessChange)
+            {
+                SrvCall->BufferingManager.HandlerInactive = TRUE;
+            }
+        }
+        KeReleaseSpinLock(&SrvCall->BufferingManager.SpinLock, OldIrql);
+
+        /* Yes? Go ahead! */
+        if (ProcessChange)
+        {
+            RxReferenceSrvCall(SrvCall);
+            RxPostToWorkerThread(RxFileSystemDeviceObject, HyperCriticalWorkQueue,
+                                 &SrvCall->BufferingManager.HandlerWorkItem,
+                                 RxProcessChangeBufferingStateRequests, SrvCall);
+        }
+
+        /* And discard left requests */
+        RxpDiscardChangeBufferingStateRequests(&DiscardedRequests);
+    }
+    else
+    {
+        InterlockedDecrement(&SrvCall->BufferingManager.NumberOfOutstandingOpens);
+    }
 }
 
 /*
@@ -731,7 +997,7 @@ RxConstructNetRoot(
     ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
 
     /* Allocate the context */
-    Context = ExAllocatePoolWithTag(PagedPool, sizeof(MRX_CREATENETROOT_CONTEXT), RX_SRVCALL_POOLTAG);
+    Context = RxAllocatePoolWithTag(PagedPool, sizeof(MRX_CREATENETROOT_CONTEXT), RX_SRVCALL_POOLTAG);
     if (Context == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -797,7 +1063,7 @@ RxConstructNetRoot(
     RxTransitionVNetRoot(VirtualNetRoot, VRootCondition);
 
     /* Context is not longer needed */
-    ExFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
+    RxFreePoolWithTag(Context, RX_SRVCALL_POOLTAG);
 
     DPRINT("Status: %x\n", Status);
 
@@ -829,7 +1095,7 @@ RxConstructSrvCall(
     ASSERT(*LockHoldingState == LHS_ExclusiveLockHeld);
 
     /* Allocate the context for mini-rdr */
-    Calldown = ExAllocatePoolWithTag(NonPagedPool, sizeof(MRX_SRVCALLDOWN_STRUCTURE), RX_SRVCALL_POOLTAG);
+    Calldown = RxAllocatePoolWithTag(NonPagedPool, sizeof(MRX_SRVCALLDOWN_STRUCTURE), RX_SRVCALL_POOLTAG);
     if (Calldown == NULL)
     {
         SrvCall->Context = NULL;
@@ -1695,6 +1961,9 @@ RxCreateVNetRoot(
     return VNetRoot;
 }
 
+/*
+ * @implemented
+ */
 VOID
 RxDereference(
     IN OUT PVOID Instance,
@@ -1756,14 +2025,26 @@ RxDereference(
     /* We have to be locked exclusively */
     if (LockHoldingState != LHS_ExclusiveLockHeld)
     {
-        UNIMPLEMENTED;
+        if ((NodeType == RDBSS_NTC_FOBX && RefCount == 0) ||
+             (NodeType >= RDBSS_NTC_SRVCALL && NodeType <= RDBSS_NTC_V_NETROOT))
+        {
+            RxpMarkInstanceForScavengedFinalization(Instance);
+        }
+
         RxReleaseScavengerMutex();
         return;
     }
+    else
+    {
+        if (BooleanFlagOn(NodeType, RX_SCAVENGER_MASK))
+        {
+            RxpUndoScavengerFinalizationMarking(Instance);
+        }
+    }
 
     RxReleaseScavengerMutex();
 
-    /* TODO: Really deallocate stuff - we're leaking as hell! */
+    /* Now, deallocate the memory */
     switch (NodeType)
     {
         case RDBSS_NTC_SRVCALL:
@@ -1779,20 +2060,53 @@ RxDereference(
         }
 
         case RDBSS_NTC_NETROOT:
-            UNIMPLEMENTED;
+        {
+            PNET_ROOT NetRoot;
+
+            NetRoot = (PNET_ROOT)Instance;
+
+            ASSERT(NetRoot->pSrvCall->RxDeviceObject != NULL);
+            ASSERT(RxIsPrefixTableLockAcquired(NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable));
+            RxFinalizeNetRoot(NetRoot, TRUE, TRUE);
             break;
+        }
 
         case RDBSS_NTC_V_NETROOT:
-            UNIMPLEMENTED;
+        {
+            PV_NET_ROOT VNetRoot;
+
+            VNetRoot = (PV_NET_ROOT)Instance;
+
+            ASSERT(VNetRoot->pNetRoot->pSrvCall->RxDeviceObject != NULL);
+            ASSERT(RxIsPrefixTableLockAcquired(VNetRoot->pNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable));
+            RxFinalizeVNetRoot(VNetRoot, TRUE, TRUE);
             break;
+        }
 
         case RDBSS_NTC_SRVOPEN:
-            UNIMPLEMENTED;
+        {
+            PSRV_OPEN SrvOpen;
+
+            SrvOpen = (PSRV_OPEN)Instance;
+
+            ASSERT(RxIsFcbAcquired(SrvOpen->Fcb));
+            if (SrvOpen->OpenCount == 0)
+            {
+                RxFinalizeSrvOpen(SrvOpen, FALSE, FALSE);
+            }
             break;
+        }
 
         case RDBSS_NTC_FOBX:
-            UNIMPLEMENTED;
+        {
+            PFOBX Fobx;
+
+            Fobx = (PFOBX)Instance;
+
+            ASSERT(RxIsFcbAcquired(Fobx->SrvOpen->Fcb));
+            RxFinalizeNetFobx(Fobx, TRUE, FALSE);
             break;
+        }
     }
 }
 
@@ -1878,6 +2192,14 @@ RxDereferenceAndDeleteRxContext_Real(
     }
 }
 
+VOID
+NTAPI
+RxDispatchChangeBufferingStateRequests(
+    PVOID Context)
+{
+    UNIMPLEMENTED;
+}
+
 /*
  * @implemented
  */
@@ -1893,7 +2215,7 @@ RxDispatchToWorkerThread(
     PRX_WORK_DISPATCH_ITEM DispatchItem;
 
     /* Allocate a bit of context */
-    DispatchItem = ExAllocatePoolWithTag(PagedPool, sizeof(RX_WORK_DISPATCH_ITEM), RX_WORKQ_POOLTAG);
+    DispatchItem = RxAllocatePoolWithTag(PagedPool, sizeof(RX_WORK_DISPATCH_ITEM), RX_WORKQ_POOLTAG);
     if (DispatchItem == NULL)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -1906,10 +2228,10 @@ RxDispatchToWorkerThread(
     DispatchItem->WorkQueueItem.Parameter = DispatchItem;
 
     /* Insert item */
-    Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, DispatchItem);
+    Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, &DispatchItem->WorkQueueItem);
     if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+        RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
         DPRINT1("RxInsertWorkQueueItem failed! Queue: %ld, Routine: %p, Context: %p, Status: %lx\n", WorkQueueType, Routine, pContext, Status);
     }
 
@@ -2113,6 +2435,27 @@ RxFcbTableRemoveFcb(
     return STATUS_SUCCESS;
 }
 
+/*
+ * @implemented
+ */
+VOID
+RxFinalizeFcbTable(
+    IN OUT PRX_FCB_TABLE FcbTable)
+{
+    USHORT Bucket;
+
+    PAGED_CODE();
+
+    /* Just delete the lock */
+    ExDeleteResourceLite(&FcbTable->TableLock);
+
+    /* And make sure (checked) that the table is really empty... */
+    for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
+    {
+        ASSERT(IsListEmpty(&FcbTable->HashBuckets[Bucket]));
+    }
+}
+
 /*
  * @implemented
  */
@@ -2171,7 +2514,7 @@ RxFinalizeNetFcb(
 
     ASSERT(ForceFinalize || ((ThisFcb->OpenCount == 0) && (ThisFcb->UncleanCount == 0)));
 
-    DPRINT("Finalizing FCB open: %d (%d)", ThisFcb->OpenCount, ForceFinalize);
+    DPRINT("Finalizing FCB open: %d (%d)\n", ThisFcb->OpenCount, ForceFinalize);
 
     /* If finalization was not already initiated, go ahead */
     if (!ThisFcb->UpperFinalizationDone)
@@ -2188,7 +2531,7 @@ RxFinalizeNetFcb(
                 Entry = ThisFcb->BufferedLocks.List;
                 ThisFcb->BufferedLocks.List = Entry->Next;
 
-                ExFreePool(Entry);
+                RxFreePool(Entry);
             }
         }
 
@@ -2221,7 +2564,7 @@ RxFinalizeNetFcb(
     /* Now, release everything */
     if (ThisFcb->pBufferingStateChangeCompletedEvent != NULL)
     {
-        ExFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
+        RxFreePool(ThisFcb->pBufferingStateChangeCompletedEvent);
     }
 
     if (ThisFcb->MRxDispatch != NULL)
@@ -2234,7 +2577,7 @@ RxFinalizeNetFcb(
     ExDeleteResourceLite(ThisFcb->Header.PagingIoResource);
 
     InterlockedDecrement((volatile long *)&ThisFcb->pNetRoot->NumberOfFcbs);
-    RxDereferenceNetRoot(ThisFcb->pNetRoot, LHS_LockNotHeld);
+    RxDereferenceVNetRoot(ThisFcb->VNetRoot, LHS_LockNotHeld);
 
     ASSERT(IsListEmpty(&ThisFcb->FcbTableEntry.HashLinks));
     ASSERT(!ThisFcb->fMiniInited);
@@ -2245,1097 +2588,2163 @@ RxFinalizeNetFcb(
     return TRUE;
 }
 
+/*
+ * @implemented
+ */
 BOOLEAN
-RxFinalizeNetRoot(
-    OUT PNET_ROOT ThisNetRoot,
-    IN BOOLEAN RecursiveFinalize,
-    IN BOOLEAN ForceFinalize
-    )
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
-
-BOOLEAN
-RxFinalizeSrvCall(
-    OUT PSRV_CALL ThisSrvCall,
-    IN BOOLEAN RecursiveFinalize,
-    IN BOOLEAN ForceFinalize)
+RxFinalizeNetFobx(
+    _Out_ PFOBX ThisFobx,
+    _In_ BOOLEAN RecursiveFinalize,
+    _In_ BOOLEAN ForceFinalize)
 {
-    UNIMPLEMENTED;
-    return FALSE;
-}
+    PFCB Fcb;
+    PSRV_OPEN SrvOpen;
 
-BOOLEAN
-RxFinalizeSrvOpen(
-    OUT PSRV_OPEN ThisSrvOpen,
-    IN BOOLEAN RecursiveFinalize,
-    IN BOOLEAN ForceFinalize)
-{
-    UNIMPLEMENTED;
-    return FALSE;
-}
+    PAGED_CODE();
 
-NTSTATUS
-RxFindOrConstructVirtualNetRoot(
-    IN PRX_CONTEXT RxContext,
-    IN PUNICODE_STRING CanonicalName,
-    IN NET_ROOT_TYPE NetRootType,
-    IN PUNICODE_STRING RemainingName)
-{
-    ULONG Flags;
-    NTSTATUS Status;
-    PVOID Container;
-    BOOLEAN Construct;
-    PV_NET_ROOT VNetRoot;
-    RX_CONNECTION_ID ConnectionID;
-    PRDBSS_DEVICE_OBJECT RxDeviceObject;
-    LOCK_HOLDING_STATE LockHoldingState;
+    ASSERT(NodeType(ThisFobx) == RDBSS_NTC_FOBX);
 
-    PAGED_CODE();
+    /* Only finalize if forced or if there's no ref left */
+    if (ThisFobx->NodeReferenceCount != 0 &&
+        !ForceFinalize)
+    {
+        return FALSE;
+    }
 
-    RxDeviceObject = RxContext->RxDeviceObject;
-    ASSERT(RxDeviceObject->Dispatch != NULL);
-    ASSERT(NodeType(RxDeviceObject->Dispatch) == RDBSS_NTC_MINIRDR_DISPATCH);
+    DPRINT("Finalize Fobx: %p (with %d ref), forced: %d\n", ThisFobx, ThisFobx->NodeReferenceCount, ForceFinalize);
 
-    /* Ask the mini-rdr for connection ID */
-    ConnectionID.SessionID = 0;
-    if (RxDeviceObject->Dispatch->MRxGetConnectionId != NULL)
+    SrvOpen = ThisFobx->SrvOpen;
+    Fcb = SrvOpen->Fcb;
+    /* If it wasn't finalized yet, do it */
+    if (!ThisFobx->UpperFinalizationDone)
     {
-        Status = RxDeviceObject->Dispatch->MRxGetConnectionId(RxContext, &ConnectionID);
-        if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
+        ASSERT(NodeType(SrvOpen->Fcb) != RDBSS_NTC_OPENTARGETDIR_FCB);
+        ASSERT(RxIsFcbAcquiredExclusive(SrvOpen->Fcb));
+
+        /* Remove it from the SRV_OPEN */
+        RemoveEntryList(&ThisFobx->FobxQLinks);
+
+        /* If we were used to browse a directory, free the query buffer */
+        if (BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_FREE_UNICODE))
         {
-            /* mini-rdr is expected not to fail - unless it's not implemented */
-            DPRINT1("Failed to initialize connection ID\n");
-            ASSERT(FALSE);
+            RxFreePoolWithTag(ThisFobx->UnicodeQueryTemplate.Buffer, RX_DIRCTL_POOLTAG);
         }
-    }
 
-    RxContext->Create.NetNamePrefixEntry = NULL;
+        /* Notify the mini-rdr */
+        if (Fcb->MRxDispatch != NULL && Fcb->MRxDispatch->MRxDeallocateForFobx != NULL)
+        {
+            Fcb->MRxDispatch->MRxDeallocateForFobx((PMRX_FOBX)ThisFobx);
+        }
 
-    Status = STATUS_MORE_PROCESSING_REQUIRED;
-    RxAcquirePrefixTableLockShared(RxDeviceObject->pRxNetNameTable, TRUE);
-    LockHoldingState = LHS_SharedLockHeld;
-    Construct = TRUE;
-    Flags = 0;
+        /* If the SRV_OPEN wasn't closed yet, do it */
+        if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
+        {
+            NTSTATUS Status;
 
-    /* We will try twice to find a matching VNetRoot: shared locked and then exlusively locked */
-    while (TRUE)
+            Status = RxCloseAssociatedSrvOpen(ThisFobx, FALSE);
+            DPRINT("Closing SRV_OPEN %p for %p: %x\n", SrvOpen, ThisFobx, Status);
+        }
+
+        /* Finalization done */
+        ThisFobx->UpperFinalizationDone = TRUE;
+    }
+
+    /* If we're still referenced, don't go any further! */
+    if (ThisFobx->NodeReferenceCount != 0)
     {
-        PNET_ROOT NetRoot;
-        PV_NET_ROOT SavedVNetRoot;
+        return FALSE;
+    }
 
-        /* Look in prefix table */
-        Container = RxPrefixTableLookupName(RxDeviceObject->pRxNetNameTable, CanonicalName, RemainingName, &ConnectionID);
-        if (Container != NULL)
-        {
-            /* If that's not a VNetRoot, that's a SrvCall, not interesting, loop again */
-            if (NodeType(Container) != RDBSS_NTC_V_NETROOT)
-            {
-                ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
-                RxDereferenceSrvCall(Container, LockHoldingState);
-            }
-            else
-            {
-                VNetRoot = Container;
-                NetRoot = VNetRoot->NetRoot;
+    /* At that point, everything should be closed */
+    ASSERT(IsListEmpty(&ThisFobx->ClosePendingList));
 
-                /* If the matching VNetRoot isn't in a good shape, there's something wrong - fail */
-                if ((NetRoot->Condition != Condition_InTransition && NetRoot->Condition != Condition_Good) ||
-                    NetRoot->SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
-                {
-                    Status = STATUS_BAD_NETWORK_PATH;
-                    SavedVNetRoot = NULL;
-                }
-                else
-                {
-                    LUID LogonId;
-                    ULONG SessionId;
-                    PUNICODE_STRING UserName, UserDomain, Password;
+    /* Was the FOBX allocated with another object?
+     * If so, mark the buffer free in said object
+     */
+    if (ThisFobx == Fcb->InternalFobx)
+    {
+        ClearFlag(Fcb->FcbState, FCB_STATE_FOBX_USED);
+    }
+    else if (ThisFobx == SrvOpen->InternalFobx)
+    {
+        ClearFlag(SrvOpen->Flags, SRVOPEN_FLAG_FOBX_USED);
+    }
 
-                    /* We can reuse if we use same credentials */
-                    Status = RxInitializeVNetRootParameters(RxContext, &LogonId,
-                                                            &SessionId, &UserName,
-                                                            &UserDomain, &Password,
-                                                            &Flags);
-                    if (NT_SUCCESS(Status))
-                    {
-                        SavedVNetRoot = VNetRoot;
-                        Status = RxCheckVNetRootCredentials(RxContext, VNetRoot,
-                                                            &LogonId, UserName,
-                                                            UserDomain, Password,
-                                                            Flags);
-                        if (Status == STATUS_MORE_PROCESSING_REQUIRED)
-                        {
-                            PLIST_ENTRY ListEntry;
+    ThisFobx->pSrvOpen = NULL;
 
-                            for (ListEntry = NetRoot->VirtualNetRoots.Flink;
-                                 ListEntry != &NetRoot->VirtualNetRoots;
-                                 ListEntry = ListEntry->Flink)
-                            {
-                                SavedVNetRoot = CONTAINING_RECORD(ListEntry, V_NET_ROOT, NetRootListEntry);
-                                Status = RxCheckVNetRootCredentials(RxContext, SavedVNetRoot,
-                                                                    &LogonId, UserName,
-                                                                    UserDomain, Password,
-                                                                    Flags);
-                                if (Status != STATUS_MORE_PROCESSING_REQUIRED)
-                                {
-                                    break;
-                                }
-                            }
+    /* A FOBX less */
+    InterlockedDecrement((volatile long *)&SrvOpen->pVNetRoot->NumberOfFobxs);
 
-                            if (ListEntry == &NetRoot->VirtualNetRoots)
-                            {
-                                SavedVNetRoot = NULL;
-                            }
-                        }
+    RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
 
-                        if (!NT_SUCCESS(Status))
-                        {
-                            SavedVNetRoot = NULL;
-                        }
+    /* If it wasn't allocated with another object, free the FOBX */
+    if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_ENCLOSED_ALLOCATED))
+    {
+        RxFreeFcbObject(ThisFobx);
+    }
 
-                        RxUninitializeVNetRootParameters(UserName, UserDomain, Password, &Flags);
-                    }
-                }
+    return TRUE;
+}
 
-                /* We'll fail, if we had referenced a VNetRoot, dereference it */
-                if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status))
-                {
-                    if (SavedVNetRoot == NULL)
-                    {
-                        RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
-                    }
-                }
-                /* Reference VNetRoot we'll keep, and dereference current */
-                else if (SavedVNetRoot != VNetRoot)
-                {
-                    RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
-                    if (SavedVNetRoot != NULL)
-                    {
-                        RxReferenceVNetRoot(SavedVNetRoot);
-                    }
-                }
-            }
+/*
+ * @implemented
+ */
+BOOLEAN
+RxFinalizeNetRoot(
+    OUT PNET_ROOT ThisNetRoot,
+    IN BOOLEAN RecursiveFinalize,
+    IN BOOLEAN ForceFinalize)
+{
+    PSRV_CALL SrvCall;
+    PRX_FCB_TABLE FcbTable;
+    PRX_PREFIX_TABLE PrefixTable;
 
-            /* We may have found something, or we fail hard, so don't attempt to create a VNetRoot */
-            if (Status != STATUS_MORE_PROCESSING_REQUIRED)
-            {
-                Construct = FALSE;
-                break;
-            }
-        }
+    PAGED_CODE();
 
-        /* If we're locked exclusive, we won't loop again, it was the second pass */
-        if (LockHoldingState != LHS_SharedLockHeld)
-        {
-            break;
-        }
+    ASSERT(NodeType(ThisNetRoot) == RDBSS_NTC_NETROOT);
 
-        /* Otherwise, prepare for second pass, exclusive, making sure we can acquire without delay */
-        if (RxAcquirePrefixTableLockExclusive(RxDeviceObject->pRxNetNameTable, FALSE))
-        {
-            RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
-            LockHoldingState = LHS_ExclusiveLockHeld;
-            break;
-        }
+    PrefixTable = ThisNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+    ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
 
-        RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
-        RxAcquirePrefixTableLockExclusive(RxDeviceObject->pRxNetNameTable, TRUE);
-        LockHoldingState = LHS_ExclusiveLockHeld;
+    /* If sme finalization is already ongoing, leave */
+    if (BooleanFlagOn(ThisNetRoot->Flags, NETROOT_FLAG_FINALIZATION_IN_PROGRESS))
+    {
+        return FALSE;
     }
 
-    /* We didn't fail, and didn't find any VNetRoot, construct one */
-    if (Construct)
-    {
-        ASSERT(LockHoldingState == LHS_ExclusiveLockHeld);
+    /* Mark we're finalizing */
+    SetFlag(ThisNetRoot->Flags, NETROOT_FLAG_FINALIZATION_IN_PROGRESS);
 
-        Status = RxConstructVirtualNetRoot(RxContext, CanonicalName, NetRootType, &VNetRoot, &LockHoldingState, &ConnectionID);
-        ASSERT(Status != STATUS_SUCCESS || LockHoldingState != LHS_LockNotHeld);
+    FcbTable = &ThisNetRoot->FcbTable;
+    /* Did caller asked us to finalize any associated FCB? */
+    if (RecursiveFinalize)
+    {
+        USHORT Bucket;
 
-        if (Status == STATUS_SUCCESS)
+        /* Browse all the FCBs in our FCB table */
+        RxAcquireFcbTableLockExclusive(FcbTable, TRUE);
+        for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
         {
-            DPRINT("CanonicalName: %wZ (%d)\n", CanonicalName, CanonicalName->Length);
-            DPRINT("VNetRoot: %wZ (%d)\n", &VNetRoot->PrefixEntry.Prefix, VNetRoot->PrefixEntry.Prefix.Length);
-            ASSERT(CanonicalName->Length >= VNetRoot->PrefixEntry.Prefix.Length);
+            PLIST_ENTRY HashBucket, ListEntry;
 
-            RemainingName->Buffer = Add2Ptr(CanonicalName->Buffer, VNetRoot->PrefixEntry.Prefix.Length);
-            RemainingName->Length = CanonicalName->Length - VNetRoot->PrefixEntry.Prefix.Length;
-            RemainingName->MaximumLength = RemainingName->Length;
+            HashBucket = &FcbTable->HashBuckets[Bucket];
+            ListEntry = HashBucket->Flink;
+            while (ListEntry != HashBucket)
+            {    
+                PFCB Fcb;
 
-            if (BooleanFlagOn(Flags, VNETROOT_FLAG_CSCAGENT_INSTANCE))
-            {
-                DPRINT("CSC instance, VNetRoot: %p\n", VNetRoot);
+                Fcb = CONTAINING_RECORD(ListEntry, FCB, FcbTableEntry.HashLinks);
+                ASSERT(NodeTypeIsFcb(Fcb));
+
+                ListEntry = ListEntry->Flink;
+
+                /* If the FCB isn't orphaned, then, it's time to purge it */
+                if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_ORPHANED))
+                {
+                    NTSTATUS Status;
+
+                    Status = RxAcquireExclusiveFcb(NULL, Fcb);
+                    ASSERT(Status == STATUS_SUCCESS);
+                    RxPurgeFcb(Fcb);
+                }
             }
-            VNetRoot->Flags |= Flags;
         }
+        RxReleaseFcbTableLock(FcbTable);
     }
 
-    /* Release the prefix table - caller expects it to be released */
-    if (LockHoldingState != LHS_LockNotHeld)
+    /* Only finalize if forced or if there's a single ref left */
+    if (ThisNetRoot->NodeReferenceCount != 1 && !ForceFinalize)
     {
-        RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
+        return FALSE;
     }
 
-    /* If we failed creating, quit */
-    if (Status != STATUS_SUCCESS)
+    DPRINT("Finalizing NetRoot %p for %wZ\n", ThisNetRoot, &ThisNetRoot->PrefixEntry.Prefix);
+
+    /* If we're still referenced, don't go any further! */
+    if (ThisNetRoot->NodeReferenceCount != 1)
     {
-        DPRINT1("RxFindOrConstructVirtualNetRoot() = Status: %x\n", Status);
-        return Status;
+        return FALSE;
     }
 
-    /* Otherwise, wait until the VNetRoot is stable */
-    DPRINT("Waiting for stable condition for: %p\n", VNetRoot);
-    RxWaitForStableVNetRoot(VNetRoot, RxContext);
-    /* It's all good, update the RX_CONTEXT with all our structs */
-    if (VNetRoot->Condition == Condition_Good)
-    {
-        PNET_ROOT NetRoot;
+    /* Finalize the FCB table (and make sure it's empty!) */
+    RxFinalizeFcbTable(FcbTable);
 
-        NetRoot = VNetRoot->NetRoot;
-        RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
-        RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
-        RxContext->Create.pSrvCall = (PMRX_SRV_CALL)NetRoot->SrvCall;
+    /* If name wasn't remove already, do it now */
+    if (!BooleanFlagOn(ThisNetRoot->Flags, NETROOT_FLAG_NAME_ALREADY_REMOVED))
+    {
+        RxRemovePrefixTableEntry(PrefixTable, &ThisNetRoot->PrefixEntry);
     }
-    else
+
+    /* Delete the object */
+    SrvCall = (PSRV_CALL)ThisNetRoot->pSrvCall;
+    RxFreeObject(ThisNetRoot);
+
+    /* And dereference the associated SRV_CALL */
+    if (SrvCall != NULL)
     {
-        RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
-        RxContext->Create.pVNetRoot = NULL;
-        Status = STATUS_BAD_NETWORK_PATH;
+        RxDereferenceSrvCall(SrvCall, LHS_ExclusiveLockHeld);
     }
 
-    return Status;
+    return TRUE;
 }
 
 /*
  * @implemented
  */
-NTSTATUS
-RxFindOrCreateConnections(
-    _In_ PRX_CONTEXT RxContext,
-    _In_ PUNICODE_STRING CanonicalName,
-    _In_ NET_ROOT_TYPE NetRootType,
-    _Out_ PUNICODE_STRING LocalNetRootName,
-    _Out_ PUNICODE_STRING FilePathName,
-    _Inout_ PLOCK_HOLDING_STATE LockState,
-    _In_ PRX_CONNECTION_ID RxConnectionId)
+BOOLEAN
+RxFinalizeSrvCall(
+    OUT PSRV_CALL ThisSrvCall,
+    IN BOOLEAN RecursiveFinalize,
+    IN BOOLEAN ForceFinalize)
 {
-    PVOID Container;
-    PSRV_CALL SrvCall;
-    PNET_ROOT NetRoot;
-    PV_NET_ROOT VNetRoot;
-    NTSTATUS Status = STATUS_UNSUCCESSFUL;
     PRX_PREFIX_TABLE PrefixTable;
-    UNICODE_STRING RemainingName, NetRootName;
 
     PAGED_CODE();
 
-    DPRINT("RxFindOrCreateConnections(%p, %wZ, %x, %p, %p, %p, %p)\n",
-           RxContext, CanonicalName, NetRootType, LocalNetRootName,
-           FilePathName, LockState, RxConnectionId);
+    ASSERT(NodeType(ThisSrvCall) == RDBSS_NTC_SRVCALL);
 
-    *FilePathName = *CanonicalName;
-    LocalNetRootName->Length = 0;
-    LocalNetRootName->MaximumLength = 0;
-    LocalNetRootName->Buffer = CanonicalName->Buffer;
+    PrefixTable = ThisSrvCall->RxDeviceObject->pRxNetNameTable;
+    ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
 
-    /* UNC path, split it */
-    if (FilePathName->Buffer[1] == ';')
+    /* Only finalize if forced or if there's a single ref left */
+    if (ThisSrvCall->NodeReferenceCount != 1 &&
+        !ForceFinalize)
     {
-        BOOLEAN Slash;
-        USHORT i, Length;
+        return FALSE;
+    }
 
-        Slash = FALSE;
-        for (i = 2; i < FilePathName->Length / sizeof(WCHAR); ++i)
-        {
-            if (FilePathName->Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
-            {
-                Slash = TRUE;
-                break;
-            }
-        }
+    DPRINT("Finalizing SrvCall %p for %wZ\n", ThisSrvCall, &ThisSrvCall->PrefixEntry.Prefix);
 
-        if (!Slash)
+    /* If it wasn't finalized yet, do it */
+    if (!ThisSrvCall->UpperFinalizationDone)
+    {
+        BOOLEAN WillFree;
+
+        /* Remove ourselves from prefix table */
+        RxRemovePrefixTableEntry(PrefixTable, &ThisSrvCall->PrefixEntry);
+
+        /* Remember our third arg, in case we get queued for later execution */
+        if (ForceFinalize)
         {
-            return STATUS_OBJECT_NAME_INVALID;
+            SetFlag(ThisSrvCall->Flags, SRVCALL_FLAG_FORCE_FINALIZED);
         }
 
-        FilePathName->Buffer = &FilePathName->Buffer[i];
-        Length = (USHORT)((ULONG_PTR)FilePathName->Buffer - (ULONG_PTR)LocalNetRootName->Buffer);
-        LocalNetRootName->Length = Length;
-        LocalNetRootName->MaximumLength = Length;
-        FilePathName->Length -= Length;
+        /* And done */
+        ThisSrvCall->UpperFinalizationDone = TRUE;
 
-        DPRINT("CanonicalName: %wZ\n", CanonicalName);
-        DPRINT(" -> FilePathName: %wZ\n", FilePathName);
-        DPRINT(" -> LocalNetRootName: %wZ\n", LocalNetRootName);
-    }
+        /* Would defered execution free the object? */
+        WillFree = (ThisSrvCall->NodeReferenceCount == 1);
 
-    Container = NULL;
-    PrefixTable = RxContext->RxDeviceObject->pRxNetNameTable;
+        /* If we have a device object */
+        if (ThisSrvCall->RxDeviceObject != NULL)
+        {
+            NTSTATUS Status;
 
-    _SEH2_TRY
-    {
-RetryLookup:
-        ASSERT(*LockState != LHS_LockNotHeld);
-
-        /* If previous lookup left something, dereference it */
-        if (Container != NULL)
-        {
-            switch (NodeType(Container))
+            /* If we're not executing in the RDBSS thread, queue for execution within the thread */
+            if (RxGetRDBSSProcess() != IoGetCurrentProcess())
             {
-                case RDBSS_NTC_SRVCALL:
-                    RxDereferenceSrvCall(Container, *LockState);
-                    break;
-
-                case RDBSS_NTC_NETROOT:
-                    RxDereferenceNetRoot(Container, *LockState);
-                    break;
+                /* Extra ref, as usual */
+                InterlockedIncrement((volatile long *)&ThisSrvCall->NodeReferenceCount);
+                /* And dispatch */
+                RxDispatchToWorkerThread(ThisSrvCall->RxDeviceObject, DelayedWorkQueue, RxpDestroySrvCall, ThisSrvCall);
 
-                case RDBSS_NTC_V_NETROOT:
-                    RxDereferenceVNetRoot(Container, *LockState);
-                    break;
-
-                default:
-                    /* Should never happen */
-                    ASSERT(FALSE);
-                    break;
+                /* Return to the caller, in advance, whether we're freeing the object or not */
+                return WillFree;
             }
+
+            /* If in the right thread already, call the mini-rdr */
+            MINIRDR_CALL_THROUGH(Status, ThisSrvCall->RxDeviceObject->Dispatch,
+                                 MRxFinalizeSrvCall, ((PMRX_SRV_CALL)ThisSrvCall, ForceFinalize));
+            (void)Status;
         }
+    }
 
-        /* Look for our NetRoot in prefix table */
-        Container = RxPrefixTableLookupName(PrefixTable, FilePathName, &RemainingName, RxConnectionId);
-        DPRINT("Container %p for path %wZ\n", Container, FilePathName);
+    /* If we're still referenced, don't go any further! */
+    if (ThisSrvCall->NodeReferenceCount != 1)
+    {
+        return FALSE;
+    }
 
-        while (TRUE)
-        {
-            UNICODE_STRING SrvCallName;
+    /* Don't leak */
+    if (ThisSrvCall->pDomainName != NULL)
+    {
+        RxFreePool(ThisSrvCall->pDomainName);
+    }
 
-            SrvCall = NULL;
-            NetRoot = NULL;
-            VNetRoot = NULL;
+    /* And free! */
+    RxTearDownBufferingManager(ThisSrvCall);
+    RxFreeObject(ThisSrvCall);
 
-            /* Assume we didn't succeed */
-            RxContext->Create.pVNetRoot = NULL;
-            RxContext->Create.pNetRoot = NULL;
-            RxContext->Create.pSrvCall = NULL;
-            RxContext->Create.Type = NetRootType;
+    return TRUE;
+}
 
-            /* If we found something */
-            if (Container != NULL)
-            {
-                /* A VNetRoot */
-                if (NodeType(Container) == RDBSS_NTC_V_NETROOT)
-                {
-                    VNetRoot = Container;
-                    /* Use its NetRoot */
-                    NetRoot = VNetRoot->NetRoot;
+/*
+ * @implemented
+ */
+BOOLEAN
+RxFinalizeSrvOpen(
+    OUT PSRV_OPEN ThisSrvOpen,
+    IN BOOLEAN RecursiveFinalize,
+    IN BOOLEAN ForceFinalize)
+{
+    PFCB Fcb;
 
-                    /* If it's not stable, wait for it to be stable */
-                    if (NetRoot->Condition == Condition_InTransition)
-                    {
-                        RxReleasePrefixTableLock(PrefixTable);
-                        DPRINT("Waiting for stable condition for: %p\n", NetRoot);
-                        RxWaitForStableNetRoot(NetRoot, RxContext);
-                        RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
-                        *LockState = LHS_ExclusiveLockHeld;
+    PAGED_CODE();
 
-                        /* Now that's it's ok, retry lookup to find what we want */
-                        if (NetRoot->Condition == Condition_Good)
-                        {
-                            goto RetryLookup;
-                        }
-                    }
+    /* We have to have a SRV_OPEN */
+    ASSERT(NodeType(ThisSrvOpen) == RDBSS_NTC_SRVOPEN);
 
-                    /* Is the associated netroot good? */
-                    if (NetRoot->Condition == Condition_Good)
-                    {
-                        SrvCall = (PSRV_CALL)NetRoot->pSrvCall;
+    /* If that's a recursive finalization, finalize any related FOBX */
+    if (RecursiveFinalize)
+    {
+        PLIST_ENTRY ListEntry;
 
-                        /* If it is, and SrvCall as well, then, we have our active connection */
-                        if (SrvCall->Condition == Condition_Good &&
-                            SrvCall->RxDeviceObject == RxContext->RxDeviceObject)
-                        {
-                            RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
-                            RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
-                            RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
+        for (ListEntry = ThisSrvOpen->FobxList.Flink;
+             ListEntry != &ThisSrvOpen->FobxList;
+             ListEntry = ListEntry->Flink)
+        {
+            PFOBX Fobx;
 
-                            Status = STATUS_CONNECTION_ACTIVE;
-                            _SEH2_LEAVE;
-                        }
-                    }
+            Fobx = CONTAINING_RECORD(ListEntry, FOBX, FobxQLinks);
+            RxFinalizeNetFobx(Fobx, TRUE, ForceFinalize);
+        }
+    }
 
-                    /* If VNetRoot was well constructed, it means the connection is active */
-                    if (VNetRoot->ConstructionStatus == STATUS_SUCCESS)
-                    {
-                        Status = STATUS_CONNECTION_ACTIVE;
-                    }
-                    else
-                    {
-                        Status = VNetRoot->ConstructionStatus;
-                    }
+    /* If we have still references, don't finalize unless forced */
+    if (ThisSrvOpen->NodeReferenceCount != 0 &&
+        !ForceFinalize)
+    {
+        return FALSE;
+    }
 
-                    RxDereferenceVNetRoot(VNetRoot, *LockState);
-                    _SEH2_LEAVE;
-                }
-                /* Can only be a SrvCall */
-                else
-                {
-                    ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
-                    SrvCall = Container;
+    DPRINT("Finalize SRV_OPEN: %p (with %d ref), forced: %d\n", ThisSrvOpen, ThisSrvOpen->NodeReferenceCount, ForceFinalize);
 
-                    /* Wait for the SRV_CALL to be stable */
-                    if (SrvCall->Condition == Condition_InTransition)
-                    {
-                        RxReleasePrefixTableLock(PrefixTable);
-                        DPRINT("Waiting for stable condition for: %p\n", SrvCall);
-                        RxWaitForStableSrvCall(SrvCall, RxContext);
-                        RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
-                        *LockState = LHS_ExclusiveLockHeld;
+    /* Only finalize if closed, or if it wasn't already done and SRV_OPEN is in a bad shape */
+    Fcb = (PFCB)ThisSrvOpen->pFcb;
+    if ((!ThisSrvOpen->UpperFinalizationDone && ThisSrvOpen->Condition != Condition_Good) ||
+        BooleanFlagOn(ThisSrvOpen->Flags, SRVOPEN_FLAG_CLOSED))
+    {
+        PV_NET_ROOT VNetRoot;
 
-                        /* It went good, loop again to find what we look for */
-                        if (SrvCall->Condition == Condition_Good)
-                        {
-                            goto RetryLookup;
-                        }
-                    }
+        /* Associated FCB can't be fake one */
+        ASSERT(NodeType(Fcb) != RDBSS_NTC_OPENTARGETDIR_FCB);
+        ASSERT(RxIsFcbAcquiredExclusive (Fcb));
 
-                    /* If it's not good... */
-                    if (SrvCall->Condition != Condition_Good)
-                    {
-                        /* But SRV_CALL was well constructed, assume a connection was active */
-                        if (SrvCall->Status == STATUS_SUCCESS)
-                        {
-                            Status = STATUS_CONNECTION_ACTIVE;
-                        }
-                        else
-                        {
-                            Status = SrvCall->Status;
-                        }
+        /* Purge any pending operation */
+        RxPurgeChangeBufferingStateRequestsForSrvOpen(ThisSrvOpen);
 
-                        RxDereferenceSrvCall(SrvCall, *LockState);
-                        _SEH2_LEAVE;
-                    }
-                }
-            }
+        /* If the FCB wasn't orphaned, inform the mini-rdr about close */
+        if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_ORPHANED))
+        {
+            NTSTATUS Status;
 
-            /* If we found a SRV_CALL not matching our DO, quit */
-            if (SrvCall != NULL && SrvCall->Condition == Condition_Good &&
-                SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
-            {
-                RxDereferenceSrvCall(SrvCall, *LockState);
-                Status = STATUS_BAD_NETWORK_NAME;
-                _SEH2_LEAVE;
-            }
+            MINIRDR_CALL_THROUGH(Status, Fcb->MRxDispatch, MRxForceClosed, ((PMRX_SRV_OPEN)ThisSrvOpen));
+            (void)Status;
+        }
 
-            /* Now, we want exclusive lock */
-            if (*LockState == LHS_SharedLockHeld)
-            {
-                if (!RxAcquirePrefixTableLockExclusive(PrefixTable, FALSE))
-                {
-                    RxReleasePrefixTableLock(PrefixTable);
-                    RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
-                    *LockState = LHS_ExclusiveLockHeld;
-                    goto RetryLookup;
-                }
+        /* Remove ourselves from the FCB */
+        RemoveEntryList(&ThisSrvOpen->SrvOpenQLinks);
+        InitializeListHead(&ThisSrvOpen->SrvOpenQLinks);
+        ++Fcb->SrvOpenListVersion;
 
-                RxReleasePrefixTableLock(PrefixTable);
-                *LockState = LHS_ExclusiveLockHeld;
-            }
+        /* If we have a V_NET_ROOT, dereference it */
+        VNetRoot = (PV_NET_ROOT)ThisSrvOpen->pVNetRoot;
+        if (VNetRoot != NULL)
+        {
+            InterlockedDecrement((volatile long *)&VNetRoot->pNetRoot->NumberOfSrvOpens);
+            RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
+            ThisSrvOpen->pVNetRoot = NULL;
+        }
 
-            ASSERT(*LockState == LHS_ExclusiveLockHeld);
+        /* Finalization done */
+        ThisSrvOpen->UpperFinalizationDone = TRUE;
+    }
 
-            /* If we reach that point, we found something, no need to create something */
-            if (Container != NULL)
-            {
-                break;
-            }
+    /* Don't free memory if still referenced */
+    if (ThisSrvOpen->NodeReferenceCount != 0)
+    {
+        return FALSE;
+    }
 
-            /* Get the name for the SRV_CALL */
-            RxExtractServerName(FilePathName, &SrvCallName, NULL);
-            DPRINT(" -> SrvCallName: %wZ\n", &SrvCallName);
-            /* And create the SRV_CALL */
-            SrvCall = RxCreateSrvCall(RxContext, &SrvCallName, NULL, RxConnectionId);
-            if (SrvCall == NULL)
-            {
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                _SEH2_LEAVE;
-            }
+    /* No key association left */
+    ASSERT(IsListEmpty(&ThisSrvOpen->SrvOpenKeyList));
 
-            /* Reset RX_CONTEXT, so far, connection creation isn't a success */
-            RxReferenceSrvCall(SrvCall);
-            RxContext->Create.pVNetRoot = NULL;
-            RxContext->Create.pNetRoot = NULL;
-            RxContext->Create.pSrvCall = NULL;
-            RxContext->Create.Type = NetRootType;
-            Container = SrvCall;
+    /* If we're still in some FCB, remove us */
+    if (!IsListEmpty(&ThisSrvOpen->SrvOpenQLinks))
+    {
+        RemoveEntryList(&ThisSrvOpen->SrvOpenQLinks);
+    }
 
-            /* Construct SRV_CALL, ie, use mini-rdr */
-            Status = RxConstructSrvCall(RxContext, SrvCall, LockState);
-            ASSERT(Status != STATUS_SUCCESS || RxIsPrefixTableLockAcquired(PrefixTable));
-            if (Status != STATUS_SUCCESS)
-            {
-                DPRINT1("RxConstructSrvCall() = Status: %x\n", Status);
-                RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
-                RxDereferenceSrvCall(SrvCall, *LockState);
-                RxReleasePrefixTableLock(PrefixTable);
-                _SEH2_LEAVE;
-            }
+    /* If enclosed allocation, mark the memory zone free and dereference FCB */
+    if (BooleanFlagOn(ThisSrvOpen->Flags, SRVOPEN_FLAG_ENCLOSED_ALLOCATED))
+    {
+        ClearFlag(Fcb->FcbState, FCB_STATE_SRVOPEN_USED);
+        RxDereferenceNetFcb(Fcb);
+    }
+    /* Otherwise, free the memory */
+    else
+    {
+        RxFreeFcbObject(ThisSrvOpen);
+    }
 
-            /* Loop again to make use of SRV_CALL stable condition wait */
-        }
+    return TRUE;
+}
 
-        /* At that point, we have a stable SRV_CALL (either found or constructed) */
-        ASSERT((NodeType(SrvCall) == RDBSS_NTC_SRVCALL) && (SrvCall->Condition == Condition_Good));
-        ASSERT(NetRoot == NULL && VNetRoot == NULL);
-        ASSERT(SrvCall->RxDeviceObject == RxContext->RxDeviceObject);
+/*
+ * @implemented
+ */
+BOOLEAN
+RxFinalizeVNetRoot(
+    OUT PV_NET_ROOT ThisVNetRoot,
+    IN BOOLEAN RecursiveFinalize,
+    IN BOOLEAN ForceFinalize)
+{
+    PNET_ROOT NetRoot;
+    PRX_PREFIX_TABLE PrefixTable;
 
-        /* Call mini-rdr to get NetRoot name */
-        SrvCall->RxDeviceObject->Dispatch->MRxExtractNetRootName(FilePathName, (PMRX_SRV_CALL)SrvCall, &NetRootName, NULL);
-        /* And create the NetRoot with that name */
-        NetRoot = RxCreateNetRoot(SrvCall, &NetRootName, 0, RxConnectionId);
-        if (NetRoot == NULL)
-        {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            _SEH2_LEAVE;
-        }
-        NetRoot->Type = NetRootType;
+    PAGED_CODE();
 
-        RxDereferenceSrvCall(SrvCall, *LockState);
+    ASSERT(NodeType(ThisVNetRoot) == RDBSS_NTC_V_NETROOT);
 
-        /* Finally, create the associated VNetRoot */
-        VNetRoot = RxCreateVNetRoot(RxContext, NetRoot, CanonicalName, LocalNetRootName, FilePathName, RxConnectionId);
-        if (VNetRoot == NULL)
-        {
-            RxFinalizeNetRoot(NetRoot, TRUE, TRUE);
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            _SEH2_LEAVE;
-        }
-        RxReferenceVNetRoot(VNetRoot);
-
-        /* We're get closer! */
-        NetRoot->Condition = Condition_InTransition;
-        RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
-        RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
-        RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
-
-        /* Construct the NetRoot, involving the mini-rdr now that we have our three control structs */
-        Status = RxConstructNetRoot(RxContext, SrvCall, NetRoot, VNetRoot, LockState);
-        if (!NT_SUCCESS(Status))
-        {
-            RxTransitionVNetRoot(VNetRoot, Condition_Bad);
-            DPRINT1("RxConstructNetRoot failed Ctxt: %p, VNet: %p, Status: %lx, Condition: %d\n", RxContext, VNetRoot, Status, VNetRoot->Condition);
-            RxDereferenceVNetRoot(VNetRoot, *LockState);
-
-            RxContext->Create.pNetRoot = NULL;
-            RxContext->Create.pVNetRoot = NULL;
-        }
-        else
-        {
-            PIO_STACK_LOCATION Stack;
-
-            ASSERT(*LockState == LHS_ExclusiveLockHeld);
+    PrefixTable = ThisVNetRoot->pNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+    ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
 
-            Stack = RxContext->CurrentIrpSp;
-            if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
-            {
-                RxExclusivePrefixTableLockToShared(PrefixTable);
-                *LockState = LHS_SharedLockHeld;
-            }
-        }
-    }
-    _SEH2_FINALLY
+    /* Only finalize if forced or if there's a single ref left */
+    if (ThisVNetRoot->NodeReferenceCount != 1 &&
+        !ForceFinalize)
     {
-        if (Status != STATUS_SUCCESS && Status != STATUS_CONNECTION_ACTIVE)
-        {
-            if (*LockState != LHS_LockNotHeld)
-            {
-                RxReleasePrefixTableLock(PrefixTable);
-                *LockState = LHS_LockNotHeld;
-            }
-        }
+        return FALSE;
     }
-    _SEH2_END;
 
-    DPRINT("RxFindOrCreateConnections() = Status: %x\n", Status);
-    return Status;
-}
+    DPRINT("Finalizing VNetRoot %p for %wZ\n", ThisVNetRoot, &ThisVNetRoot->PrefixEntry.Prefix);
 
-/*
- * @implemented
- */
-VOID
-NTAPI
-RxFinishFcbInitialization(
-    IN OUT PMRX_FCB Fcb,
-    IN RX_FILE_TYPE FileType,
-    IN PFCB_INIT_PACKET InitPacket OPTIONAL)
-{
-    NODE_TYPE_CODE OldType;
+    NetRoot = (PNET_ROOT)ThisVNetRoot->pNetRoot;
+    /* If it wasn't finalized yet, do it */
+    if (!ThisVNetRoot->UpperFinalizationDone)
+    {
+        ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
 
-    PAGED_CODE();
+        /* Reference the NetRoot so that it doesn't disappear */
+        RxReferenceNetRoot(NetRoot);
+        RxOrphanSrvOpens(ThisVNetRoot);
+        /* Remove us from the available VNetRoot for NetRoot */
+        RxRemoveVirtualNetRootFromNetRoot(NetRoot, ThisVNetRoot);
+        /* Remove extra ref */
+        RxDereferenceNetRoot(NetRoot, LHS_ExclusiveLockHeld);
 
-    DPRINT("RxFinishFcbInitialization(%p, %x, %p)\n", Fcb, FileType, InitPacket);
+        /* Remove ourselves from prefix table */
+        RxRemovePrefixTableEntry(PrefixTable, &ThisVNetRoot->PrefixEntry);
 
-    OldType = Fcb->Header.NodeTypeCode;
-    Fcb->Header.NodeTypeCode = FileType;
-    /* If mini-rdr already did the job for mailslot attributes, 0 the rest */
-    if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_TIME_AND_SIZE_ALREADY_SET) && FileType == RDBSS_NTC_MAILSLOT)
-    {
-        FILL_IN_FCB((PFCB)Fcb, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+        /* Finalization done */
+        ThisVNetRoot->UpperFinalizationDone = TRUE;
     }
-    /* Otherwise, if mini-rdr provided us with an init packet, copy its data */
-    else if (InitPacket != NULL)
+
+    /* If we're still referenced, don't go any further! */
+    if (ThisVNetRoot->NodeReferenceCount != 1)
     {
-        FILL_IN_FCB((PFCB)Fcb, *InitPacket->pAttributes, *InitPacket->pNumLinks,
-                    InitPacket->pCreationTime->QuadPart, InitPacket->pLastAccessTime->QuadPart,
-                    InitPacket->pLastWriteTime->QuadPart, InitPacket->pLastChangeTime->QuadPart,
-                    InitPacket->pAllocationSize->QuadPart, InitPacket->pFileSize->QuadPart,
-                    InitPacket->pValidDataLength->QuadPart);
+        return FALSE;
     }
 
-    if (FileType != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
-        FileType != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
+    /* If there's an associated device, notify mini-rdr */
+    if (NetRoot->pSrvCall->RxDeviceObject != NULL)
     {
-        /* If our FCB newly points to a file, initiliaz everything related */
-        if (FileType == RDBSS_NTC_STORAGE_TYPE_FILE &&
-            !OldType != RDBSS_NTC_STORAGE_TYPE_FILE)
-        {
-            RxInitializeLowIoPerFcbInfo(&((PFCB)Fcb)->Specific.Fcb.LowIoPerFcbInfo);
-            FsRtlInitializeFileLock(&((PFCB)Fcb)->Specific.Fcb.FileLock, &RxLockOperationCompletion,
-                                    &RxUnlockOperation);
-
-            ((PFCB)Fcb)->BufferedLocks.List = NULL;
-            ((PFCB)Fcb)->BufferedLocks.PendingLockOps = 0;
+        NTSTATUS Status;
 
-            Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
-        }
-        else
-        {
-            ASSERT(FileType >= RDBSS_NTC_SPOOLFILE && FileType <= RDBSS_NTC_MAILSLOT);
-        }
+        MINIRDR_CALL_THROUGH(Status, NetRoot->pSrvCall->RxDeviceObject->Dispatch,
+                             MRxFinalizeVNetRoot, ((PMRX_V_NET_ROOT)ThisVNetRoot, FALSE));
+        (void)Status;
     }
+
+    /* Free parameters */
+    RxUninitializeVNetRootParameters(ThisVNetRoot->pUserName, ThisVNetRoot->pUserDomainName,
+                                     ThisVNetRoot->pPassword, &ThisVNetRoot->Flags);
+    /* Dereference our NetRoot, we won't reference it anymore */
+    RxDereferenceNetRoot(NetRoot, LHS_ExclusiveLockHeld);
+
+    /* And free the object! */
+    RxFreePoolWithTag(ThisVNetRoot, RX_V_NETROOT_POOLTAG);
+
+    return TRUE;
 }
 
-/*
- * @implemented
- */
 NTSTATUS
-RxFinishSrvCallConstruction(
-    PMRX_SRVCALLDOWN_STRUCTURE Calldown)
+RxFindOrConstructVirtualNetRoot(
+    IN PRX_CONTEXT RxContext,
+    IN PUNICODE_STRING CanonicalName,
+    IN NET_ROOT_TYPE NetRootType,
+    IN PUNICODE_STRING RemainingName)
 {
+    ULONG Flags;
     NTSTATUS Status;
-    PSRV_CALL SrvCall;
-    PRX_CONTEXT Context;
-    RX_BLOCK_CONDITION Condition;
-    PRX_PREFIX_TABLE PrefixTable;
+    PVOID Container;
+    BOOLEAN Construct;
+    PV_NET_ROOT VNetRoot;
+    RX_CONNECTION_ID ConnectionID;
+    PRDBSS_DEVICE_OBJECT RxDeviceObject;
+    LOCK_HOLDING_STATE LockHoldingState;
 
-    DPRINT("RxFinishSrvCallConstruction(%p)\n", Calldown);
+    PAGED_CODE();
 
-    SrvCall = (PSRV_CALL)Calldown->SrvCall;
-    Context = Calldown->RxContext;
-    PrefixTable = Context->RxDeviceObject->pRxNetNameTable;
+    RxDeviceObject = RxContext->RxDeviceObject;
+    ASSERT(RxDeviceObject->Dispatch != NULL);
+    ASSERT(NodeType(RxDeviceObject->Dispatch) == RDBSS_NTC_MINIRDR_DISPATCH);
 
-    /* We have a winner, notify him */
-    if (Calldown->BestFinisher != NULL)
+    /* Ask the mini-rdr for connection ID */
+    ConnectionID.SessionID = 0;
+    if (RxDeviceObject->Dispatch->MRxGetConnectionId != NULL)
     {
-        DPRINT("Notify the winner: %p (%wZ)\n", Calldown->BestFinisher, &Calldown->BestFinisher->DeviceName);
-
-        ASSERT(SrvCall->RxDeviceObject == Calldown->BestFinisher);
-
-        MINIRDR_CALL_THROUGH(Status, Calldown->BestFinisher->Dispatch,
-                             MRxSrvCallWinnerNotify,
-                             ((PMRX_SRV_CALL)SrvCall, TRUE,
-                              Calldown->CallbackContexts[Calldown->BestFinisherOrdinal].RecommunicateContext));
-        if (Status != STATUS_SUCCESS)
-        {
-            Condition = Condition_Bad;
-        }
-        else
+        Status = RxDeviceObject->Dispatch->MRxGetConnectionId(RxContext, &ConnectionID);
+        if (!NT_SUCCESS(Status) && Status != STATUS_NOT_IMPLEMENTED)
         {
-            Condition = Condition_Good;
+            /* mini-rdr is expected not to fail - unless it's not implemented */
+            DPRINT1("Failed to initialize connection ID\n");
+            ASSERT(FALSE);
         }
     }
-    /* Otherwise, just fail our SRV_CALL */
-    else
-    {
-        Status = Calldown->CallbackContexts[0].Status;
-        Condition = Condition_Bad;
-    }
-
-    RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
-    RxTransitionSrvCall(SrvCall, Condition);
-    ExFreePoolWithTag(Calldown, RX_SRVCALL_POOLTAG);
 
-    /* If async, finish it here, otherwise, caller has already finished the stuff */
-    if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
-    {
-        DPRINT("Finishing async call\n");
-
-        RxReleasePrefixTableLock(PrefixTable);
+    RxContext->Create.NetNamePrefixEntry = NULL;
 
-        /* Make sure we weren't cancelled in-between */
-        if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_CANCELLED))
-        {
-            Status = STATUS_CANCELLED;
-        }
+    Status = STATUS_MORE_PROCESSING_REQUIRED;
+    RxAcquirePrefixTableLockShared(RxDeviceObject->pRxNetNameTable, TRUE);
+    LockHoldingState = LHS_SharedLockHeld;
+    Construct = TRUE;
+    Flags = 0;
 
-        /* In case that was a create, context can be reused */
-        if (Context->MajorFunction == IRP_MJ_CREATE)
-        {
-            RxpPrepareCreateContextForReuse(Context);
-        }
+    /* We will try twice to find a matching VNetRoot: shared locked and then exlusively locked */
+    while (TRUE)
+    {
+        PNET_ROOT NetRoot;
+        PV_NET_ROOT SavedVNetRoot;
 
-        /* If that's a failure, reset everything and return failure */
-        if (Status != STATUS_SUCCESS)
+        /* Look in prefix table */
+        Container = RxPrefixTableLookupName(RxDeviceObject->pRxNetNameTable, CanonicalName, RemainingName, &ConnectionID);
+        if (Container != NULL)
         {
-            Context->MajorFunction = Context->CurrentIrpSp->MajorFunction;
-            if (Context->MajorFunction == IRP_MJ_DEVICE_CONTROL)
+            /* If that's not a VNetRoot, that's a SrvCall, not interesting, loop again */
+            if (NodeType(Container) != RDBSS_NTC_V_NETROOT)
             {
-                if (Context->Info.Buffer != NULL)
-                {
-                    ExFreePool(Context->Info.Buffer);
-                    Context->Info.Buffer = NULL;
-                }
+                ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
+                RxDereferenceSrvCall(Container, LockHoldingState);
             }
-            Context->CurrentIrp->IoStatus.Information = 0;
-            Context->CurrentIrp->IoStatus.Status = Status;
-            RxCompleteRequest(Context, Status);
-        }
-        /* Otherwise, call resume routine and done! */
-        else
-        {
-            Status = Context->ResumeRoutine(Context);
-            if (Status != STATUS_PENDING)
+            else
             {
-                RxCompleteRequest(Context, Status);
-            }
-
-            DPRINT("Not completing, pending\n");
-        }
-    }
-
-    RxDereferenceSrvCall(SrvCall, LHS_LockNotHeld);
-    return Status;
-}
-
-/*
- * @implemented
- */
-VOID
-NTAPI
-RxFinishSrvCallConstructionDispatcher(
-    IN PVOID Context)
-{
-    KIRQL OldIrql;
-    BOOLEAN Direct, KeepLoop;
+                VNetRoot = Container;
+                NetRoot = VNetRoot->NetRoot;
 
-    DPRINT("RxFinishSrvCallConstructionDispatcher(%p)\n", Context);
+                /* If the matching VNetRoot isn't in a good shape, there's something wrong - fail */
+                if ((NetRoot->Condition != Condition_InTransition && NetRoot->Condition != Condition_Good) ||
+                    NetRoot->SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
+                {
+                    Status = STATUS_BAD_NETWORK_PATH;
+                    SavedVNetRoot = NULL;
+                }
+                else
+                {
+                    LUID LogonId;
+                    ULONG SessionId;
+                    PUNICODE_STRING UserName, UserDomain, Password;
+
+                    /* We can reuse if we use same credentials */
+                    Status = RxInitializeVNetRootParameters(RxContext, &LogonId,
+                                                            &SessionId, &UserName,
+                                                            &UserDomain, &Password,
+                                                            &Flags);
+                    if (NT_SUCCESS(Status))
+                    {
+                        SavedVNetRoot = VNetRoot;
+                        Status = RxCheckVNetRootCredentials(RxContext, VNetRoot,
+                                                            &LogonId, UserName,
+                                                            UserDomain, Password,
+                                                            Flags);
+                        if (Status == STATUS_MORE_PROCESSING_REQUIRED)
+                        {
+                            PLIST_ENTRY ListEntry;
+
+                            for (ListEntry = NetRoot->VirtualNetRoots.Flink;
+                                 ListEntry != &NetRoot->VirtualNetRoots;
+                                 ListEntry = ListEntry->Flink)
+                            {
+                                SavedVNetRoot = CONTAINING_RECORD(ListEntry, V_NET_ROOT, NetRootListEntry);
+                                Status = RxCheckVNetRootCredentials(RxContext, SavedVNetRoot,
+                                                                    &LogonId, UserName,
+                                                                    UserDomain, Password,
+                                                                    Flags);
+                                if (Status != STATUS_MORE_PROCESSING_REQUIRED)
+                                {
+                                    break;
+                                }
+                            }
+
+                            if (ListEntry == &NetRoot->VirtualNetRoots)
+                            {
+                                SavedVNetRoot = NULL;
+                            }
+                        }
+
+                        if (!NT_SUCCESS(Status))
+                        {
+                            SavedVNetRoot = NULL;
+                        }
+
+                        RxUninitializeVNetRootParameters(UserName, UserDomain, Password, &Flags);
+                    }
+                }
+
+                /* We'll fail, if we had referenced a VNetRoot, dereference it */
+                if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status))
+                {
+                    if (SavedVNetRoot == NULL)
+                    {
+                        RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
+                    }
+                }
+                /* Reference VNetRoot we'll keep, and dereference current */
+                else if (SavedVNetRoot != VNetRoot)
+                {
+                    RxDereferenceVNetRoot(VNetRoot, LockHoldingState);
+                    if (SavedVNetRoot != NULL)
+                    {
+                        RxReferenceVNetRoot(SavedVNetRoot);
+                    }
+                }
+            }
+
+            /* We may have found something, or we fail hard, so don't attempt to create a VNetRoot */
+            if (Status != STATUS_MORE_PROCESSING_REQUIRED)
+            {
+                Construct = FALSE;
+                break;
+            }
+        }
+
+        /* If we're locked exclusive, we won't loop again, it was the second pass */
+        if (LockHoldingState != LHS_SharedLockHeld)
+        {
+            break;
+        }
+
+        /* Otherwise, prepare for second pass, exclusive, making sure we can acquire without delay */
+        if (RxAcquirePrefixTableLockExclusive(RxDeviceObject->pRxNetNameTable, FALSE))
+        {
+            RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
+            LockHoldingState = LHS_ExclusiveLockHeld;
+            break;
+        }
+
+        RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
+        RxAcquirePrefixTableLockExclusive(RxDeviceObject->pRxNetNameTable, TRUE);
+        LockHoldingState = LHS_ExclusiveLockHeld;
+    }
+
+    /* We didn't fail, and didn't find any VNetRoot, construct one */
+    if (Construct)
+    {
+        ASSERT(LockHoldingState == LHS_ExclusiveLockHeld);
+
+        Status = RxConstructVirtualNetRoot(RxContext, CanonicalName, NetRootType, &VNetRoot, &LockHoldingState, &ConnectionID);
+        ASSERT(Status != STATUS_SUCCESS || LockHoldingState != LHS_LockNotHeld);
+
+        if (Status == STATUS_SUCCESS)
+        {
+            DPRINT("CanonicalName: %wZ (%d)\n", CanonicalName, CanonicalName->Length);
+            DPRINT("VNetRoot: %wZ (%d)\n", &VNetRoot->PrefixEntry.Prefix, VNetRoot->PrefixEntry.Prefix.Length);
+            ASSERT(CanonicalName->Length >= VNetRoot->PrefixEntry.Prefix.Length);
+
+            RemainingName->Buffer = Add2Ptr(CanonicalName->Buffer, VNetRoot->PrefixEntry.Prefix.Length);
+            RemainingName->Length = CanonicalName->Length - VNetRoot->PrefixEntry.Prefix.Length;
+            RemainingName->MaximumLength = RemainingName->Length;
+
+            if (BooleanFlagOn(Flags, VNETROOT_FLAG_CSCAGENT_INSTANCE))
+            {
+                DPRINT("CSC instance, VNetRoot: %p\n", VNetRoot);
+            }
+            VNetRoot->Flags |= Flags;
+        }
+    }
+
+    /* Release the prefix table - caller expects it to be released */
+    if (LockHoldingState != LHS_LockNotHeld)
+    {
+        RxReleasePrefixTableLock(RxDeviceObject->pRxNetNameTable);
+    }
+
+    /* If we failed creating, quit */
+    if (Status != STATUS_SUCCESS)
+    {
+        DPRINT1("RxFindOrConstructVirtualNetRoot() = Status: %x\n", Status);
+        return Status;
+    }
+
+    /* Otherwise, wait until the VNetRoot is stable */
+    DPRINT("Waiting for stable condition for: %p\n", VNetRoot);
+    RxWaitForStableVNetRoot(VNetRoot, RxContext);
+    /* It's all good, update the RX_CONTEXT with all our structs */
+    if (VNetRoot->Condition == Condition_Good)
+    {
+        PNET_ROOT NetRoot;
+
+        NetRoot = VNetRoot->NetRoot;
+        RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
+        RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
+        RxContext->Create.pSrvCall = (PMRX_SRV_CALL)NetRoot->SrvCall;
+    }
+    else
+    {
+        RxDereferenceVNetRoot(VNetRoot, LHS_LockNotHeld);
+        RxContext->Create.pVNetRoot = NULL;
+        Status = STATUS_BAD_NETWORK_PATH;
+    }
+
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxFindOrCreateConnections(
+    _In_ PRX_CONTEXT RxContext,
+    _In_ PUNICODE_STRING CanonicalName,
+    _In_ NET_ROOT_TYPE NetRootType,
+    _Out_ PUNICODE_STRING LocalNetRootName,
+    _Out_ PUNICODE_STRING FilePathName,
+    _Inout_ PLOCK_HOLDING_STATE LockState,
+    _In_ PRX_CONNECTION_ID RxConnectionId)
+{
+    PVOID Container;
+    PSRV_CALL SrvCall;
+    PNET_ROOT NetRoot;
+    PV_NET_ROOT VNetRoot;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    PRX_PREFIX_TABLE PrefixTable;
+    UNICODE_STRING RemainingName, NetRootName;
+
+    PAGED_CODE();
+
+    DPRINT("RxFindOrCreateConnections(%p, %wZ, %x, %p, %p, %p, %p)\n",
+           RxContext, CanonicalName, NetRootType, LocalNetRootName,
+           FilePathName, LockState, RxConnectionId);
+
+    *FilePathName = *CanonicalName;
+    LocalNetRootName->Length = 0;
+    LocalNetRootName->MaximumLength = 0;
+    LocalNetRootName->Buffer = CanonicalName->Buffer;
+
+    /* UNC path, split it */
+    if (FilePathName->Buffer[1] == ';')
+    {
+        BOOLEAN Slash;
+        USHORT i, Length;
+
+        Slash = FALSE;
+        for (i = 2; i < FilePathName->Length / sizeof(WCHAR); ++i)
+        {
+            if (FilePathName->Buffer[i] == OBJ_NAME_PATH_SEPARATOR)
+            {
+                Slash = TRUE;
+                break;
+            }
+        }
+
+        if (!Slash)
+        {
+            return STATUS_OBJECT_NAME_INVALID;
+        }
+
+        FilePathName->Buffer = &FilePathName->Buffer[i];
+        Length = (USHORT)((ULONG_PTR)FilePathName->Buffer - (ULONG_PTR)LocalNetRootName->Buffer);
+        LocalNetRootName->Length = Length;
+        LocalNetRootName->MaximumLength = Length;
+        FilePathName->Length -= Length;
+
+        DPRINT("CanonicalName: %wZ\n", CanonicalName);
+        DPRINT(" -> FilePathName: %wZ\n", FilePathName);
+        DPRINT(" -> LocalNetRootName: %wZ\n", LocalNetRootName);
+    }
+
+    Container = NULL;
+    PrefixTable = RxContext->RxDeviceObject->pRxNetNameTable;
+
+    _SEH2_TRY
+    {
+RetryLookup:
+        ASSERT(*LockState != LHS_LockNotHeld);
+
+        /* If previous lookup left something, dereference it */
+        if (Container != NULL)
+        {
+            switch (NodeType(Container))
+            {
+                case RDBSS_NTC_SRVCALL:
+                    RxDereferenceSrvCall(Container, *LockState);
+                    break;
+
+                case RDBSS_NTC_NETROOT:
+                    RxDereferenceNetRoot(Container, *LockState);
+                    break;
+
+                case RDBSS_NTC_V_NETROOT:
+                    RxDereferenceVNetRoot(Container, *LockState);
+                    break;
+
+                default:
+                    /* Should never happen */
+                    ASSERT(FALSE);
+                    break;
+            }
+        }
+
+        /* Look for our NetRoot in prefix table */
+        Container = RxPrefixTableLookupName(PrefixTable, FilePathName, &RemainingName, RxConnectionId);
+        DPRINT("Container %p for path %wZ\n", Container, FilePathName);
+
+        while (TRUE)
+        {
+            UNICODE_STRING SrvCallName;
+
+            SrvCall = NULL;
+            NetRoot = NULL;
+            VNetRoot = NULL;
+
+            /* Assume we didn't succeed */
+            RxContext->Create.pVNetRoot = NULL;
+            RxContext->Create.pNetRoot = NULL;
+            RxContext->Create.pSrvCall = NULL;
+            RxContext->Create.Type = NetRootType;
+
+            /* If we found something */
+            if (Container != NULL)
+            {
+                /* A VNetRoot */
+                if (NodeType(Container) == RDBSS_NTC_V_NETROOT)
+                {
+                    VNetRoot = Container;
+                    /* Use its NetRoot */
+                    NetRoot = VNetRoot->NetRoot;
+
+                    /* If it's not stable, wait for it to be stable */
+                    if (NetRoot->Condition == Condition_InTransition)
+                    {
+                        RxReleasePrefixTableLock(PrefixTable);
+                        DPRINT("Waiting for stable condition for: %p\n", NetRoot);
+                        RxWaitForStableNetRoot(NetRoot, RxContext);
+                        RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+                        *LockState = LHS_ExclusiveLockHeld;
+
+                        /* Now that's it's ok, retry lookup to find what we want */
+                        if (NetRoot->Condition == Condition_Good)
+                        {
+                            goto RetryLookup;
+                        }
+                    }
+
+                    /* Is the associated netroot good? */
+                    if (NetRoot->Condition == Condition_Good)
+                    {
+                        SrvCall = (PSRV_CALL)NetRoot->pSrvCall;
+
+                        /* If it is, and SrvCall as well, then, we have our active connection */
+                        if (SrvCall->Condition == Condition_Good &&
+                            SrvCall->RxDeviceObject == RxContext->RxDeviceObject)
+                        {
+                            RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
+                            RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
+                            RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
+
+                            Status = STATUS_CONNECTION_ACTIVE;
+                            _SEH2_LEAVE;
+                        }
+                    }
+
+                    /* If VNetRoot was well constructed, it means the connection is active */
+                    if (VNetRoot->ConstructionStatus == STATUS_SUCCESS)
+                    {
+                        Status = STATUS_CONNECTION_ACTIVE;
+                    }
+                    else
+                    {
+                        Status = VNetRoot->ConstructionStatus;
+                    }
+
+                    RxDereferenceVNetRoot(VNetRoot, *LockState);
+                    _SEH2_LEAVE;
+                }
+                /* Can only be a SrvCall */
+                else
+                {
+                    ASSERT(NodeType(Container) == RDBSS_NTC_SRVCALL);
+                    SrvCall = Container;
+
+                    /* Wait for the SRV_CALL to be stable */
+                    if (SrvCall->Condition == Condition_InTransition)
+                    {
+                        RxReleasePrefixTableLock(PrefixTable);
+                        DPRINT("Waiting for stable condition for: %p\n", SrvCall);
+                        RxWaitForStableSrvCall(SrvCall, RxContext);
+                        RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+                        *LockState = LHS_ExclusiveLockHeld;
+
+                        /* It went good, loop again to find what we look for */
+                        if (SrvCall->Condition == Condition_Good)
+                        {
+                            goto RetryLookup;
+                        }
+                    }
+
+                    /* If it's not good... */
+                    if (SrvCall->Condition != Condition_Good)
+                    {
+                        /* But SRV_CALL was well constructed, assume a connection was active */
+                        if (SrvCall->Status == STATUS_SUCCESS)
+                        {
+                            Status = STATUS_CONNECTION_ACTIVE;
+                        }
+                        else
+                        {
+                            Status = SrvCall->Status;
+                        }
+
+                        RxDereferenceSrvCall(SrvCall, *LockState);
+                        _SEH2_LEAVE;
+                    }
+                }
+            }
+
+            /* If we found a SRV_CALL not matching our DO, quit */
+            if (SrvCall != NULL && SrvCall->Condition == Condition_Good &&
+                SrvCall->RxDeviceObject != RxContext->RxDeviceObject)
+            {
+                RxDereferenceSrvCall(SrvCall, *LockState);
+                Status = STATUS_BAD_NETWORK_NAME;
+                _SEH2_LEAVE;
+            }
+
+            /* Now, we want exclusive lock */
+            if (*LockState == LHS_SharedLockHeld)
+            {
+                if (!RxAcquirePrefixTableLockExclusive(PrefixTable, FALSE))
+                {
+                    RxReleasePrefixTableLock(PrefixTable);
+                    RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+                    *LockState = LHS_ExclusiveLockHeld;
+                    goto RetryLookup;
+                }
+
+                RxReleasePrefixTableLock(PrefixTable);
+                *LockState = LHS_ExclusiveLockHeld;
+            }
+
+            ASSERT(*LockState == LHS_ExclusiveLockHeld);
+
+            /* If we reach that point, we found something, no need to create something */
+            if (Container != NULL)
+            {
+                break;
+            }
+
+            /* Get the name for the SRV_CALL */
+            RxExtractServerName(FilePathName, &SrvCallName, NULL);
+            DPRINT(" -> SrvCallName: %wZ\n", &SrvCallName);
+            /* And create the SRV_CALL */
+            SrvCall = RxCreateSrvCall(RxContext, &SrvCallName, NULL, RxConnectionId);
+            if (SrvCall == NULL)
+            {
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                _SEH2_LEAVE;
+            }
+
+            /* Reset RX_CONTEXT, so far, connection creation isn't a success */
+            RxReferenceSrvCall(SrvCall);
+            RxContext->Create.pVNetRoot = NULL;
+            RxContext->Create.pNetRoot = NULL;
+            RxContext->Create.pSrvCall = NULL;
+            RxContext->Create.Type = NetRootType;
+            Container = SrvCall;
+
+            /* Construct SRV_CALL, ie, use mini-rdr */
+            Status = RxConstructSrvCall(RxContext, SrvCall, LockState);
+            ASSERT(Status != STATUS_SUCCESS || RxIsPrefixTableLockAcquired(PrefixTable));
+            if (Status != STATUS_SUCCESS)
+            {
+                DPRINT1("RxConstructSrvCall() = Status: %x\n", Status);
+                RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+                RxDereferenceSrvCall(SrvCall, *LockState);
+                RxReleasePrefixTableLock(PrefixTable);
+                _SEH2_LEAVE;
+            }
+
+            /* Loop again to make use of SRV_CALL stable condition wait */
+        }
+
+        /* At that point, we have a stable SRV_CALL (either found or constructed) */
+        ASSERT((NodeType(SrvCall) == RDBSS_NTC_SRVCALL) && (SrvCall->Condition == Condition_Good));
+        ASSERT(NetRoot == NULL && VNetRoot == NULL);
+        ASSERT(SrvCall->RxDeviceObject == RxContext->RxDeviceObject);
+
+        /* Call mini-rdr to get NetRoot name */
+        SrvCall->RxDeviceObject->Dispatch->MRxExtractNetRootName(FilePathName, (PMRX_SRV_CALL)SrvCall, &NetRootName, NULL);
+        /* And create the NetRoot with that name */
+        NetRoot = RxCreateNetRoot(SrvCall, &NetRootName, 0, RxConnectionId);
+        if (NetRoot == NULL)
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+        NetRoot->Type = NetRootType;
+
+        RxDereferenceSrvCall(SrvCall, *LockState);
+
+        /* Finally, create the associated VNetRoot */
+        VNetRoot = RxCreateVNetRoot(RxContext, NetRoot, CanonicalName, LocalNetRootName, FilePathName, RxConnectionId);
+        if (VNetRoot == NULL)
+        {
+            RxFinalizeNetRoot(NetRoot, TRUE, TRUE);
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            _SEH2_LEAVE;
+        }
+        RxReferenceVNetRoot(VNetRoot);
+
+        /* We're get closer! */
+        NetRoot->Condition = Condition_InTransition;
+        RxContext->Create.pSrvCall = (PMRX_SRV_CALL)SrvCall;
+        RxContext->Create.pNetRoot = (PMRX_NET_ROOT)NetRoot;
+        RxContext->Create.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
+
+        /* Construct the NetRoot, involving the mini-rdr now that we have our three control structs */
+        Status = RxConstructNetRoot(RxContext, SrvCall, NetRoot, VNetRoot, LockState);
+        if (!NT_SUCCESS(Status))
+        {
+            RxTransitionVNetRoot(VNetRoot, Condition_Bad);
+            DPRINT1("RxConstructNetRoot failed Ctxt: %p, VNet: %p, Status: %lx, Condition: %d\n", RxContext, VNetRoot, Status, VNetRoot->Condition);
+            RxDereferenceVNetRoot(VNetRoot, *LockState);
+
+            RxContext->Create.pNetRoot = NULL;
+            RxContext->Create.pVNetRoot = NULL;
+        }
+        else
+        {
+            PIO_STACK_LOCATION Stack;
+
+            ASSERT(*LockState == LHS_ExclusiveLockHeld);
+
+            Stack = RxContext->CurrentIrpSp;
+            if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_CREATE_TREE_CONNECTION))
+            {
+                RxExclusivePrefixTableLockToShared(PrefixTable);
+                *LockState = LHS_SharedLockHeld;
+            }
+        }
+    }
+    _SEH2_FINALLY
+    {
+        if (Status != STATUS_SUCCESS && Status != STATUS_CONNECTION_ACTIVE)
+        {
+            if (*LockState != LHS_LockNotHeld)
+            {
+                RxReleasePrefixTableLock(PrefixTable);
+                *LockState = LHS_LockNotHeld;
+            }
+        }
+    }
+    _SEH2_END;
+
+    DPRINT("RxFindOrCreateConnections() = Status: %x\n", Status);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxFinishFcbInitialization(
+    IN OUT PMRX_FCB Fcb,
+    IN RX_FILE_TYPE FileType,
+    IN PFCB_INIT_PACKET InitPacket OPTIONAL)
+{
+    NODE_TYPE_CODE OldType;
+
+    PAGED_CODE();
+
+    DPRINT("RxFinishFcbInitialization(%p, %x, %p)\n", Fcb, FileType, InitPacket);
+
+    OldType = Fcb->Header.NodeTypeCode;
+    Fcb->Header.NodeTypeCode = FileType;
+    /* If mini-rdr already did the job for mailslot attributes, 0 the rest */
+    if (BooleanFlagOn(Fcb->FcbState, FCB_STATE_TIME_AND_SIZE_ALREADY_SET) && FileType == RDBSS_NTC_MAILSLOT)
+    {
+        FILL_IN_FCB((PFCB)Fcb, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    }
+    /* Otherwise, if mini-rdr provided us with an init packet, copy its data */
+    else if (InitPacket != NULL)
+    {
+        FILL_IN_FCB((PFCB)Fcb, *InitPacket->pAttributes, *InitPacket->pNumLinks,
+                    InitPacket->pCreationTime->QuadPart, InitPacket->pLastAccessTime->QuadPart,
+                    InitPacket->pLastWriteTime->QuadPart, InitPacket->pLastChangeTime->QuadPart,
+                    InitPacket->pAllocationSize->QuadPart, InitPacket->pFileSize->QuadPart,
+                    InitPacket->pValidDataLength->QuadPart);
+    }
+
+    if (FileType != RDBSS_NTC_STORAGE_TYPE_UNKNOWN &&
+        FileType != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)
+    {
+        /* If our FCB newly points to a file, initiliaz everything related */
+        if (FileType == RDBSS_NTC_STORAGE_TYPE_FILE &&
+            OldType != RDBSS_NTC_STORAGE_TYPE_FILE)
+        {
+            RxInitializeLowIoPerFcbInfo(&((PFCB)Fcb)->Specific.Fcb.LowIoPerFcbInfo);
+            FsRtlInitializeFileLock(&((PFCB)Fcb)->Specific.Fcb.FileLock, &RxLockOperationCompletion,
+                                    &RxUnlockOperation);
+
+            ((PFCB)Fcb)->BufferedLocks.List = NULL;
+            ((PFCB)Fcb)->BufferedLocks.PendingLockOps = 0;
+
+            Fcb->Header.IsFastIoPossible = FastIoIsQuestionable;
+        }
+        else
+        {
+            ASSERT(FileType >= RDBSS_NTC_SPOOLFILE && FileType <= RDBSS_NTC_MAILSLOT);
+        }
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxFinishSrvCallConstruction(
+    PMRX_SRVCALLDOWN_STRUCTURE Calldown)
+{
+    NTSTATUS Status;
+    PSRV_CALL SrvCall;
+    PRX_CONTEXT Context;
+    RX_BLOCK_CONDITION Condition;
+    PRX_PREFIX_TABLE PrefixTable;
+
+    DPRINT("RxFinishSrvCallConstruction(%p)\n", Calldown);
+
+    SrvCall = (PSRV_CALL)Calldown->SrvCall;
+    Context = Calldown->RxContext;
+    PrefixTable = Context->RxDeviceObject->pRxNetNameTable;
+
+    /* We have a winner, notify him */
+    if (Calldown->BestFinisher != NULL)
+    {
+        DPRINT("Notify the winner: %p (%wZ)\n", Calldown->BestFinisher, &Calldown->BestFinisher->DeviceName);
+
+        ASSERT(SrvCall->RxDeviceObject == Calldown->BestFinisher);
+
+        MINIRDR_CALL_THROUGH(Status, Calldown->BestFinisher->Dispatch,
+                             MRxSrvCallWinnerNotify,
+                             ((PMRX_SRV_CALL)SrvCall, TRUE,
+                              Calldown->CallbackContexts[Calldown->BestFinisherOrdinal].RecommunicateContext));
+        if (Status != STATUS_SUCCESS)
+        {
+            Condition = Condition_Bad;
+        }
+        else
+        {
+            Condition = Condition_Good;
+        }
+    }
+    /* Otherwise, just fail our SRV_CALL */
+    else
+    {
+        Status = Calldown->CallbackContexts[0].Status;
+        Condition = Condition_Bad;
+    }
+
+    RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+    RxTransitionSrvCall(SrvCall, Condition);
+    RxFreePoolWithTag(Calldown, RX_SRVCALL_POOLTAG);
+
+    /* If async, finish it here, otherwise, caller has already finished the stuff */
+    if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION))
+    {
+        DPRINT("Finishing async call\n");
+
+        RxReleasePrefixTableLock(PrefixTable);
+
+        /* Make sure we weren't cancelled in-between */
+        if (BooleanFlagOn(Context->Flags, RX_CONTEXT_FLAG_CANCELLED))
+        {
+            Status = STATUS_CANCELLED;
+        }
+
+        /* In case that was a create, context can be reused */
+        if (Context->MajorFunction == IRP_MJ_CREATE)
+        {
+            RxpPrepareCreateContextForReuse(Context);
+        }
+
+        /* If that's a failure, reset everything and return failure */
+        if (Status != STATUS_SUCCESS)
+        {
+            Context->MajorFunction = Context->CurrentIrpSp->MajorFunction;
+            if (Context->MajorFunction == IRP_MJ_DEVICE_CONTROL)
+            {
+                if (Context->Info.Buffer != NULL)
+                {
+                    RxFreePool(Context->Info.Buffer);
+                    Context->Info.Buffer = NULL;
+                }
+            }
+            Context->CurrentIrp->IoStatus.Information = 0;
+            Context->CurrentIrp->IoStatus.Status = Status;
+            RxCompleteRequest(Context, Status);
+        }
+        /* Otherwise, call resume routine and done! */
+        else
+        {
+            Status = Context->ResumeRoutine(Context);
+            if (Status != STATUS_PENDING)
+            {
+                RxCompleteRequest(Context, Status);
+            }
+
+            DPRINT("Not completing, pending\n");
+        }
+    }
+
+    RxDereferenceSrvCall(SrvCall, LHS_LockNotHeld);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxFinishSrvCallConstructionDispatcher(
+    IN PVOID Context)
+{
+    KIRQL OldIrql;
+    BOOLEAN Direct, KeepLoop;
+
+    DPRINT("RxFinishSrvCallConstructionDispatcher(%p)\n", Context);
 
     /* In case of failure of starting dispatcher, context is not set
      * We keep track of it to fail associated SRV_CALL
      */
     Direct = (Context == NULL);
 
-    /* Separated thread, loop forever */
-    while (TRUE)
+    /* Separated thread, loop forever */
+    while (TRUE)
+    {
+        PLIST_ENTRY ListEntry;
+        PMRX_SRVCALLDOWN_STRUCTURE Calldown;
+
+        /* If there are no SRV_CALL to finalize left, just finish thread */
+        KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
+        if (IsListEmpty(&RxSrvCalldownList))
+        {
+            KeepLoop =  FALSE;
+            RxSrvCallConstructionDispatcherActive = FALSE;
+        }
+        /* Otherwise, get the SRV_CALL to finish construction */
+        else
+        {
+            ListEntry = RemoveHeadList(&RxSrvCalldownList);
+            KeepLoop =  TRUE;
+        }
+        KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
+
+        /* Nothing to do */
+        if (!KeepLoop)
+        {
+            break;
+        }
+
+        /* If direct is set, reset the finisher to avoid electing a winner
+         * and fail SRV_CALL (see upper comment)
+         */
+        Calldown = CONTAINING_RECORD(ListEntry, MRX_SRVCALLDOWN_STRUCTURE, SrvCalldownList);
+        if (Direct)
+        {
+            Calldown->BestFinisher = NULL;
+        }
+        /* Finish SRV_CALL construction */
+        RxFinishSrvCallConstruction(Calldown);
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxFlushFcbInSystemCache(
+    IN PFCB Fcb,
+    IN BOOLEAN SynchronizeWithLazyWriter)
+{
+    IO_STATUS_BLOCK IoStatus;
+
+    PAGED_CODE();
+
+    /* Deal with Cc */
+    CcFlushCache(&Fcb->NonPaged->SectionObjectPointers, NULL, 0, &IoStatus);
+    /* If we're asked to sync with LW, do it in case of success */
+    if (SynchronizeWithLazyWriter && NT_SUCCESS(IoStatus.Status))
+    {
+        RxAcquirePagingIoResource((PRX_CONTEXT)NULL, Fcb);
+        RxReleasePagingIoResource((PRX_CONTEXT)NULL, Fcb);
+    }
+
+    DPRINT("Flushing for FCB %p returns %lx\n", Fcb, IoStatus.Status);
+    return IoStatus.Status;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxFreeFcbObject(
+    PVOID Object)
+{
+    PAGED_CODE();
+
+    /* If that's a FOBX/SRV_OPEN, nothing to do, just free it */
+    if (NodeType(Object) == RDBSS_NTC_FOBX || NodeType(Object) == RDBSS_NTC_SRVOPEN)
+    {
+        RxFreePoolWithTag(Object, RX_FCB_POOLTAG);
+    }
+    /* If that's a FCB... */
+    else if (NodeTypeIsFcb(Object))
+    {
+        PFCB Fcb;
+        PRDBSS_DEVICE_OBJECT DeviceObject;
+
+        Fcb = (PFCB)Object;
+        DeviceObject = Fcb->RxDeviceObject;
+
+        /* Delete per stream contexts */
+        FsRtlTeardownPerStreamContexts(&Fcb->Header);
+
+        SetFlag(Fcb->Header.Flags, FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH);
+
+        /* If there was a non-paged FCB allocated, free it */
+        if (!BooleanFlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE))
+        {
+            RxFreePoolWithTag(Fcb->NonPaged, RX_NONPAGEDFCB_POOLTAG);
+        }
+
+        /* Free the FCB */
+        RxFreePool(Fcb);
+
+        /* Update statistics */
+        InterlockedDecrement(&RxNumberOfActiveFcbs);
+        InterlockedDecrement((volatile long *)&DeviceObject->NumberOfActiveFcbs);
+    }
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxFreeObject(
+    PVOID pObject)
+{
+    PAGED_CODE();
+
+    /* First, perform a few sanity checks if we're dealing with a SRV_CALL or a NET_ROOT */
+    if (NodeType(pObject) == RDBSS_NTC_SRVCALL)
+    {
+        PSRV_CALL SrvCall;
+        PRDBSS_DEVICE_OBJECT DeviceObject;
+
+        SrvCall = (PSRV_CALL)pObject;
+        DeviceObject = SrvCall->RxDeviceObject;
+        if (DeviceObject != NULL)
+        {
+            if (!BooleanFlagOn(DeviceObject->Dispatch->MRxFlags, RDBSS_MANAGE_SRV_CALL_EXTENSION))
+            {
+                ASSERT(SrvCall->Context == NULL);
+            }
+
+            ASSERT(SrvCall->Context2 == NULL);
+
+            SrvCall->RxDeviceObject = NULL;
+        }
+    }
+    else if (NodeType(pObject) == RDBSS_NTC_NETROOT)
+    {
+        PNET_ROOT NetRoot;
+
+        NetRoot = (PNET_ROOT)pObject;
+        NetRoot->pSrvCall = NULL;
+        NetRoot->NodeTypeCode = NodeType(pObject) | 0xF000;
+    }
+
+    /* And just free the object */
+    RxFreePool(pObject);
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxGatherRequestsForSrvOpen(
+    IN OUT PSRV_CALL SrvCall,
+    IN PSRV_OPEN SrvOpen,
+    IN OUT PLIST_ENTRY RequestsListHead)
+{
+    KIRQL OldIrql;
+    LIST_ENTRY Discarded, *Entry;
+    PCHANGE_BUFFERING_STATE_REQUEST Request;
+
+    /* Dispatch any pending operation first */
+    RxpDispatchChangeBufferingStateRequests(SrvCall, SrvOpen, &Discarded);
+
+    /* Then, get any entry related to our key and SRV_OPEN */
+    KeAcquireSpinLock(&SrvCall->BufferingManager.SpinLock, &OldIrql);
+    Entry = SrvCall->BufferingManager.HandlerList.Flink;
+    while (Entry != &SrvCall->BufferingManager.HandlerList)
+    {
+        Request = CONTAINING_RECORD(Entry, CHANGE_BUFFERING_STATE_REQUEST, ListEntry);
+        Entry = Entry->Flink;
+        if (Request->SrvOpenKey == SrvOpen->Key && Request->SrvOpen == SrvOpen)
+        {
+            RemoveEntryList(&Request->ListEntry);
+            InsertTailList(RequestsListHead, &Request->ListEntry);
+        }
+    }
+    KeReleaseSpinLock(&SrvCall->BufferingManager.SpinLock, OldIrql);
+
+    /* Perform the same search in the last change list */
+    Entry = SrvCall->BufferingManager.LastChanceHandlerList.Flink;
+    while (Entry != &SrvCall->BufferingManager.LastChanceHandlerList)
+    {
+        Request = CONTAINING_RECORD(Entry, CHANGE_BUFFERING_STATE_REQUEST, ListEntry);
+        Entry = Entry->Flink;
+        if (Request->SrvOpenKey == SrvOpen->Key && Request->SrvOpen == SrvOpen)
+        {
+            RemoveEntryList(&Request->ListEntry);
+            InsertTailList(RequestsListHead, &Request->ListEntry);
+        }
+    }
+
+    /* Discard the discarded requests */
+    RxpDiscardChangeBufferingStateRequests(&Discarded);
+}
+
+/*
+ * @implemented
+ */
+PRDBSS_DEVICE_OBJECT
+RxGetDeviceObjectOfInstance(
+    PVOID Instance)
+{
+    NODE_TYPE_CODE NodeType;
+    PRDBSS_DEVICE_OBJECT DeviceObject;
+
+    PAGED_CODE();
+
+    /* We only handle a few object types */
+    NodeType = NodeType(Instance);
+    ASSERT((NodeType == RDBSS_NTC_SRVCALL) || (NodeType == RDBSS_NTC_NETROOT) ||
+           (NodeType == RDBSS_NTC_V_NETROOT) || (NodeType == RDBSS_NTC_SRVOPEN) || (NodeType == RDBSS_NTC_FOBX));
+
+    /* Get the device object depending on the object */
+    switch (NodeType)
+    {
+        case RDBSS_NTC_FOBX:
+        {
+            PFOBX Fobx;
+
+            Fobx = (PFOBX)Instance;
+            DeviceObject = Fobx->RxDeviceObject;
+            break;
+        }
+
+        case RDBSS_NTC_SRVCALL:
+        {
+            PSRV_CALL SrvCall;
+
+            SrvCall = (PSRV_CALL)Instance;
+            DeviceObject = SrvCall->RxDeviceObject;
+            break;
+        }
+
+        case RDBSS_NTC_NETROOT:
+        {
+            PNET_ROOT NetRoot;
+
+            NetRoot = (PNET_ROOT)Instance;
+            DeviceObject = NetRoot->pSrvCall->RxDeviceObject;
+            break;
+        }
+
+        case RDBSS_NTC_V_NETROOT:
+        {
+            PV_NET_ROOT VNetRoot;
+
+            VNetRoot = (PV_NET_ROOT)Instance;
+            DeviceObject = VNetRoot->pNetRoot->pSrvCall->RxDeviceObject;
+            break;
+        }
+
+        case RDBSS_NTC_SRVOPEN:
+        {
+            PSRV_OPEN SrvOpen;
+
+            SrvOpen = (PSRV_OPEN)Instance;
+            DeviceObject = ((PFCB)SrvOpen->pFcb)->RxDeviceObject;
+            break;
+        }
+
+        default:
+            DeviceObject = NULL;
+            break;
+    }
+
+    /* Job done */
+    return DeviceObject;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxGetFileSizeWithLock(
+    IN PFCB Fcb,
+    OUT PLONGLONG FileSize)
+{
+    PAGED_CODE();
+
+    *FileSize = Fcb->Header.FileSize.QuadPart;
+}
+
+/*
+ * @implemented
+ */
+PEPROCESS
+NTAPI
+RxGetRDBSSProcess(
+    VOID)
+{
+    return RxData.OurProcess;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxInitializeBufferingManager(
+   PSRV_CALL SrvCall)
+{
+    KeInitializeSpinLock(&SrvCall->BufferingManager.SpinLock);
+    InitializeListHead(&SrvCall->BufferingManager.DispatcherList);
+    InitializeListHead(&SrvCall->BufferingManager.HandlerList);
+    InitializeListHead(&SrvCall->BufferingManager.LastChanceHandlerList);
+    SrvCall->BufferingManager.DispatcherActive = FALSE;
+    SrvCall->BufferingManager.HandlerInactive = FALSE;
+    SrvCall->BufferingManager.LastChanceHandlerActive = FALSE;
+    SrvCall->BufferingManager.NumberOfOutstandingOpens = 0;
+    InitializeListHead(&SrvCall->BufferingManager.SrvOpenLists[0]);
+    ExInitializeFastMutex(&SrvCall->BufferingManager.Mutex);
+
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxInitializeContext(
+    IN PIRP Irp,
+    IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
+    IN ULONG InitialContextFlags,
+    IN OUT PRX_CONTEXT RxContext)
+{
+    PIO_STACK_LOCATION Stack;
+
+    /* Initialize our various fields */
+    RxContext->NodeTypeCode = RDBSS_NTC_RX_CONTEXT;
+    RxContext->NodeByteSize = sizeof(RX_CONTEXT);
+    RxContext->ReferenceCount = 1;
+    RxContext->SerialNumber = InterlockedExchangeAdd((volatile LONG *)&RxContextSerialNumberCounter, 1);
+    RxContext->RxDeviceObject = RxDeviceObject;
+    KeInitializeEvent(&RxContext->SyncEvent, SynchronizationEvent, FALSE);
+    RxInitializeScavengerEntry(&RxContext->ScavengerEntry);
+    InitializeListHead(&RxContext->BlockedOperations);
+    RxContext->MRxCancelRoutine = NULL;
+    RxContext->ResumeRoutine = NULL;
+    RxContext->Flags |= InitialContextFlags;
+    RxContext->CurrentIrp = Irp;
+    RxContext->LastExecutionThread = PsGetCurrentThread();
+    RxContext->OriginalThread = RxContext->LastExecutionThread;
+
+    /* If've got no IRP, mark RX_CONTEXT */
+    if (Irp == NULL)
+    {
+        RxContext->CurrentIrpSp = NULL;
+        RxContext->MajorFunction = IRP_MJ_MAXIMUM_FUNCTION + 1;
+        RxContext->MinorFunction = 0;
+    }
+    else
+    {
+        /* Otherwise, first determine whether we are performing async operation */
+        Stack = IoGetCurrentIrpStackLocation(Irp);
+        if (Stack->FileObject != NULL)
+        {
+            PFCB Fcb;
+
+            Fcb = Stack->FileObject->FsContext;
+            if (!IoIsOperationSynchronous(Irp) ||
+                ((Fcb != NULL && NodeTypeIsFcb(Fcb)) &&
+                 (Stack->MajorFunction == IRP_MJ_READ || Stack->MajorFunction == IRP_MJ_WRITE || Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
+                 (Fcb->pNetRoot != NULL && (Fcb->pNetRoot->Type == NET_ROOT_PIPE))))
+            {
+                RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
+            }
+        }
+
+        if (Stack->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
+        {
+            RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
+        }
+        if (Stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
+        {
+            RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
+        }
+
+        /* Set proper flags if TopLevl IRP/Device */
+        if (!RxIsThisTheTopLevelIrp(Irp))
+        {
+            RxContext->Flags |= RX_CONTEXT_FLAG_RECURSIVE_CALL;
+        }
+        if (RxGetTopDeviceObjectIfRdbssIrp() == RxDeviceObject)
+        {
+            RxContext->Flags |= RX_CONTEXT_FLAG_THIS_DEVICE_TOP_LEVEL;
+        }
+
+        /* Copy stack information */
+        RxContext->MajorFunction = Stack->MajorFunction;
+        RxContext->MinorFunction = Stack->MinorFunction;
+        ASSERT(RxContext->MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
+        RxContext->CurrentIrpSp = Stack;
+
+        /* If we have a FO associated, learn for more */
+        if (Stack->FileObject != NULL)
+        {
+            PFCB Fcb;
+            PFOBX Fobx;
+
+            /* Get the FCB and CCB (FOBX) */
+            Fcb = Stack->FileObject->FsContext;
+            Fobx = Stack->FileObject->FsContext2;
+            RxContext->pFcb = (PMRX_FCB)Fcb;
+            if (Fcb != NULL && NodeTypeIsFcb(Fcb))
+            {
+                RxContext->NonPagedFcb = Fcb->NonPaged;
+            }
+
+            /* We have a FOBX, this not a DFS opening, keep track of it */
+            if (Fobx != NULL && Fobx != UIntToPtr(DFS_OPEN_CONTEXT) && Fobx != UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT))
+            {
+                RxContext->pFobx = (PMRX_FOBX)Fobx;
+                RxContext->pRelevantSrvOpen = Fobx->pSrvOpen;
+                if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
+                {
+                    RxContext->FobxSerialNumber = InterlockedIncrement((volatile LONG *)&Fobx->FobxSerialNumber);
+                }
+            }
+            else
+            {
+                RxContext->pFobx = NULL;
+            }
+
+            /* In case of directory change notification, Fobx may be a VNetRoot, take note of that */
+            if (RxContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && RxContext->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY &&
+                Fobx != NULL)
+            {
+                PV_NET_ROOT VNetRoot = NULL;
+
+                if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
+                {
+                    VNetRoot = Fcb->VNetRoot;
+                }
+                else if (Fobx->NodeTypeCode == RDBSS_NTC_V_NETROOT)
+                {
+                    VNetRoot = (PV_NET_ROOT)Fobx;
+                }
+
+                if (VNetRoot != NULL)
+                {
+                    RxContext->NotifyChangeDirectory.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
+                }
+            }
+
+            /* Remember if that's a write through file */
+            RxContext->RealDevice = Stack->FileObject->DeviceObject;
+            if (BooleanFlagOn(Stack->FileObject->Flags, FO_WRITE_THROUGH))
+            {
+                RxContext->Flags |= RX_CONTEXT_FLAG_WRITE_THROUGH;
+            }
+        }
+    }
+
+    if (RxContext->MajorFunction != IRP_MJ_DEVICE_CONTROL)
+    {
+        DPRINT("New Ctxt: %p for MN: %d, IRP: %p, THRD: %p, FCB: %p, FOBX:%p #%lx\n",
+               RxContext, RxContext->MinorFunction, Irp,
+               PsGetCurrentThread(), RxContext->pFcb, RxContext->pFobx,
+               RxContext->SerialNumber);
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+RxInitializeDispatcher(
+    VOID)
+{
+    NTSTATUS Status;
+    HANDLE ThreadHandle;
+
+    PAGED_CODE();
+
+    RxFileSystemDeviceObject->DispatcherContext.NumberOfWorkerThreads = 0;
+    RxFileSystemDeviceObject->DispatcherContext.pTearDownEvent = NULL;
+
+    /* Set appropriate timeouts: 10s & 60s */
+    RxWorkQueueWaitInterval[CriticalWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
+    RxWorkQueueWaitInterval[DelayedWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
+    RxWorkQueueWaitInterval[HyperCriticalWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
+    RxSpinUpDispatcherWaitInterval.QuadPart = -60 * 1000 * 1000 * 10;
+
+    RxDispatcher.NumberOfProcessors = 1;
+    RxDispatcher.OwnerProcess = IoGetCurrentProcess();
+    RxDispatcher.pWorkQueueDispatcher = &RxDispatcherWorkQueues;
+
+    /* Initialize our dispatchers */
+    Status = RxInitializeWorkQueueDispatcher(RxDispatcher.pWorkQueueDispatcher);
+    if (!NT_SUCCESS(Status))
     {
-        PLIST_ENTRY ListEntry;
-        PMRX_SRVCALLDOWN_STRUCTURE Calldown;
+        return Status;
+    }
 
-        /* If there are no SRV_CALL to finalize left, just finish thread */
-        KeAcquireSpinLock(&RxStrucSupSpinLock, &OldIrql);
-        if (IsListEmpty(&RxSrvCalldownList))
-        {
-            KeepLoop =  FALSE;
-            RxSrvCallConstructionDispatcherActive = FALSE;
-        }
-        /* Otherwise, get the SRV_CALL to finish construction */
-        else
-        {
-            ListEntry = RemoveHeadList(&RxSrvCalldownList);
-            KeepLoop =  TRUE;
-        }
-        KeReleaseSpinLock(&RxStrucSupSpinLock, OldIrql);
+    Status = RxInitializeMRxDispatcher(RxFileSystemDeviceObject);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
 
-        /* Nothing to do */
-        if (!KeepLoop)
-        {
-            break;
-        }
+    /* And start them */
+    RxDispatcher.State = RxDispatcherActive;
+    InitializeListHead(&RxDispatcher.SpinUpRequests);
+    KeInitializeSpinLock(&RxDispatcher.SpinUpRequestsLock);
+    KeInitializeEvent(&RxDispatcher.SpinUpRequestsEvent, 0, 0);
+    KeInitializeEvent(&RxDispatcher.SpinUpRequestsTearDownEvent, 0, 0);
+    Status = PsCreateSystemThread(&ThreadHandle, PROCESS_ALL_ACCESS, NULL,
+                                  NULL, NULL, RxSpinUpRequestsDispatcher, &RxDispatcher);
+    if (NT_SUCCESS(Status))
+    {
+        ZwClose(ThreadHandle);
+    }
 
-        /* If direct is set, reset the finisher to avoid electing a winner
-         * and fail SRV_CALL (see upper comment)
-         */
-        Calldown = CONTAINING_RECORD(ListEntry, MRX_SRVCALLDOWN_STRUCTURE, SrvCalldownList);
-        if (Direct)
-        {
-            Calldown->BestFinisher = NULL;
-        }
-        /* Finish SRV_CALL construction */
-        RxFinishSrvCallConstruction(Calldown);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxInitializeFcbTable(
+    IN OUT PRX_FCB_TABLE FcbTable,
+    IN BOOLEAN CaseInsensitiveMatch)
+{
+    USHORT i;
+
+    PAGED_CODE();
+
+    FcbTable->NodeTypeCode = RDBSS_NTC_FCB_TABLE;
+    FcbTable->NodeByteSize = sizeof(RX_FCB_TABLE);
+
+    ExInitializeResourceLite(&FcbTable->TableLock);
+    FcbTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
+    FcbTable->Version = 0;
+    FcbTable->TableEntryForNull = NULL;
+
+    FcbTable->NumberOfBuckets = RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS;
+    for (i = 0; i < FcbTable->NumberOfBuckets; ++i)
+    {
+        InitializeListHead(&FcbTable->HashBuckets[i]);
     }
+
+    FcbTable->Lookups = 0;
+    FcbTable->FailedLookups = 0;
+    FcbTable->Compares = 0;
 }
 
+/*
+ * @implemented
+ */
 VOID
-RxFreeFcbObject(
-    PVOID Object)
+NTAPI
+RxInitializeLowIoContext(
+    OUT PLOWIO_CONTEXT LowIoContext,
+    IN ULONG Operation)
 {
-    UNIMPLEMENTED;
+    PRX_CONTEXT RxContext;
+    PIO_STACK_LOCATION Stack;
+
+    PAGED_CODE();
+
+    RxContext = CONTAINING_RECORD(LowIoContext, RX_CONTEXT, LowIoContext);
+    ASSERT(LowIoContext == &RxContext->LowIoContext);
+
+    Stack = RxContext->CurrentIrpSp;
+
+    KeInitializeEvent(&RxContext->SyncEvent, NotificationEvent, FALSE);
+    RxContext->LowIoContext.ResourceThreadId = (ERESOURCE_THREAD)PsGetCurrentThread();
+    RxContext->LowIoContext.Operation = Operation;
+
+    switch (Operation)
+    {
+        case LOWIO_OP_READ:
+        case LOWIO_OP_WRITE:
+            /* In case of RW, set a canary, to make sure these fields are properly set
+             * they will be asserted when lowio request will be submit to mini-rdr
+             * See LowIoSubmit()
+             */
+            RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset = 0xFFFFFFEE;
+            RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount = 0xEEEEEEEE;
+            RxContext->LowIoContext.ParamsFor.ReadWrite.Key = Stack->Parameters.Read.Key;
+
+            /* Keep track of paging IOs */
+            if (BooleanFlagOn(RxContext->CurrentIrp->Flags, IRP_PAGING_IO))
+            {
+                RxContext->LowIoContext.ParamsFor.ReadWrite.Flags = LOWIO_READWRITEFLAG_PAGING_IO;
+            }
+            else
+            {
+                RxContext->LowIoContext.ParamsFor.ReadWrite.Flags = 0;
+            }
+
+            break;
+
+        case LOWIO_OP_FSCTL:
+        case LOWIO_OP_IOCTL:
+            /* This will be initialized later on with a call to RxLowIoPopulateFsctlInfo() */
+            RxContext->LowIoContext.ParamsFor.FsCtl.Flags = 0;
+            RxContext->LowIoContext.ParamsFor.FsCtl.InputBufferLength = 0;
+            RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = NULL;
+            RxContext->LowIoContext.ParamsFor.FsCtl.OutputBufferLength = 0;
+            RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = NULL;
+            RxContext->LowIoContext.ParamsFor.FsCtl.MinorFunction = 0;
+            break;
+
+        /* Nothing to do for these */
+        case LOWIO_OP_SHAREDLOCK:
+        case LOWIO_OP_EXCLUSIVELOCK:
+        case LOWIO_OP_UNLOCK:
+        case LOWIO_OP_UNLOCK_MULTIPLE:
+        case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
+        case LOWIO_OP_CLEAROUT:
+            break;
+
+        default:
+            /* Should never happen */
+            ASSERT(FALSE);
+            break;
+    }
 }
 
+/*
+ * @implemented
+ */
 VOID
-RxFreeObject(
-    PVOID pObject)
+RxInitializeLowIoPerFcbInfo(
+    PLOWIO_PER_FCB_INFO LowIoPerFcbInfo)
 {
-    UNIMPLEMENTED;
+    PAGED_CODE();
+
+    InitializeListHead(&LowIoPerFcbInfo->PagingIoReadsOutstanding);
+    InitializeListHead(&LowIoPerFcbInfo->PagingIoWritesOutstanding);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxInitializeMRxDispatcher(
+     IN OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject)
+{
+    PAGED_CODE();
+
+    pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads = 0;
+    pMRxDeviceObject->DispatcherContext.pTearDownEvent = NULL;
+
+    return STATUS_SUCCESS;
 }
 
 /*
  * @implemented
  */
 VOID
-RxGetFileSizeWithLock(
-    IN PFCB Fcb,
-    OUT PLONGLONG FileSize)
+RxInitializePrefixTable(
+    IN OUT PRX_PREFIX_TABLE ThisTable,
+    IN ULONG TableSize OPTIONAL,
+    IN BOOLEAN CaseInsensitiveMatch)
 {
     PAGED_CODE();
 
-    *FileSize = Fcb->Header.FileSize.QuadPart;
+    if (TableSize == 0)
+    {
+        TableSize = RX_PREFIX_TABLE_DEFAULT_LENGTH;
+    }
+
+    ThisTable->NodeTypeCode = RDBSS_NTC_PREFIX_TABLE;
+    ThisTable->NodeByteSize = sizeof(RX_PREFIX_TABLE);
+    InitializeListHead(&ThisTable->MemberQueue);
+    ThisTable->Version = 0;
+    ThisTable->TableEntryForNull = NULL;
+    ThisTable->IsNetNameTable = FALSE;
+    ThisTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
+    ThisTable->TableSize = TableSize;
+
+    if (TableSize > 0)
+    {
+        USHORT i;
+
+        for (i = 0; i < RX_PREFIX_TABLE_DEFAULT_LENGTH; ++i)
+        {
+            InitializeListHead(&ThisTable->HashBuckets[i]);
+        }
+    }
 }
 
 /*
  * @implemented
  */
-PEPROCESS
-NTAPI
-RxGetRDBSSProcess(
-    VOID)
+VOID
+RxInitializePurgeSyncronizationContext(
+    PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext)
 {
-    return RxData.OurProcess;
+    PAGED_CODE();
+
+    InitializeListHead(&PurgeSyncronizationContext->ContextsAwaitingPurgeCompletion);
+    PurgeSyncronizationContext->PurgeInProgress = FALSE;
+}
+
+NTSTATUS
+RxInitializeSrvCallParameters(
+    IN PRX_CONTEXT RxContext,
+    IN OUT PSRV_CALL SrvCall)
+{
+    PAGED_CODE();
+
+    SrvCall->pPrincipalName = NULL;
+
+    /* We only have stuff to initialize for file opening from DFS */
+    if (RxContext->MajorFunction != IRP_MJ_CREATE || RxContext->Create.EaLength == 0)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    ASSERT(RxContext->Create.EaBuffer != NULL);
+
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 /*
  * @implemented
  */
 NTSTATUS
-RxInitializeBufferingManager(
-   PSRV_CALL SrvCall)
+NTAPI
+RxInitializeRxTimer(
+    VOID)
 {
-    KeInitializeSpinLock(&SrvCall->BufferingManager.SpinLock);
-    InitializeListHead(&SrvCall->BufferingManager.DispatcherList);
-    InitializeListHead(&SrvCall->BufferingManager.HandlerList);
-    InitializeListHead(&SrvCall->BufferingManager.LastChanceHandlerList);
-    SrvCall->BufferingManager.DispatcherActive = FALSE;
-    SrvCall->BufferingManager.HandlerInactive = FALSE;
-    SrvCall->BufferingManager.LastChanceHandlerActive = FALSE;
-    SrvCall->BufferingManager.NumberOfOutstandingOpens = 0;
-    InitializeListHead(&SrvCall->BufferingManager.SrvOpenLists[0]);
-    ExInitializeFastMutex(&SrvCall->BufferingManager.Mutex);
+    PAGED_CODE();
+
+    RxTimerInterval.HighPart = -1;
+    RxTimerInterval.LowPart = -550000;
+    KeInitializeSpinLock(&RxTimerLock);
+    InitializeListHead(&RxTimerQueueHead);
+    InitializeListHead(&RxRecurrentWorkItemsList);
+    KeInitializeDpc(&RxTimerDpc, RxTimerDispatch, NULL);
+    KeInitializeTimer(&RxTimer);
+    RxTimerTickCount = 0;
 
     return STATUS_SUCCESS;
 }
 
-/*
- * @implemented
- */
-VOID
-NTAPI
-RxInitializeContext(
-    IN PIRP Irp,
-    IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
-    IN ULONG InitialContextFlags,
-    IN OUT PRX_CONTEXT RxContext)
+NTSTATUS
+RxInitializeVNetRootParameters(
+   PRX_CONTEXT RxContext,
+   OUT LUID *LogonId,
+   OUT PULONG SessionId,
+   OUT PUNICODE_STRING *UserNamePtr,
+   OUT PUNICODE_STRING *UserDomainNamePtr,
+   OUT PUNICODE_STRING *PasswordPtr,
+   OUT PULONG Flags)
 {
-    PIO_STACK_LOCATION Stack;
+    NTSTATUS Status;
+    PACCESS_TOKEN Token;
 
-    /* Initialize our various fields */
-    RxContext->NodeTypeCode = RDBSS_NTC_RX_CONTEXT;
-    RxContext->NodeByteSize = sizeof(RX_CONTEXT);
-    RxContext->ReferenceCount = 1;
-    RxContext->SerialNumber = InterlockedExchangeAdd((volatile LONG *)&RxContextSerialNumberCounter, 1);
-    RxContext->RxDeviceObject = RxDeviceObject;
-    KeInitializeEvent(&RxContext->SyncEvent, SynchronizationEvent, FALSE);
-    RxInitializeScavengerEntry(&RxContext->ScavengerEntry);
-    InitializeListHead(&RxContext->BlockedOperations);
-    RxContext->MRxCancelRoutine = NULL;
-    RxContext->ResumeRoutine = NULL;
-    RxContext->Flags |= InitialContextFlags;
-    RxContext->CurrentIrp = Irp;
-    RxContext->LastExecutionThread = PsGetCurrentThread();
-    RxContext->OriginalThread = RxContext->LastExecutionThread;
+    PAGED_CODE();
 
-    /* If've got no IRP, mark RX_CONTEXT */
-    if (Irp == NULL)
+    DPRINT("RxInitializeVNetRootParameters(%p, %p, %p, %p, %p, %p, %p)\n", RxContext,
+           LogonId, SessionId, UserNamePtr, UserDomainNamePtr, PasswordPtr, Flags);
+
+    *UserNamePtr = NULL;
+    *UserDomainNamePtr = NULL;
+    *PasswordPtr = NULL;
+    /* By default, that's not CSC instance */
+    *Flags &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
+
+    Token = SeQuerySubjectContextToken(&RxContext->Create.NtCreateParameters.SecurityContext->AccessState->SubjectSecurityContext);
+    if (SeTokenIsRestricted(Token))
     {
-        RxContext->CurrentIrpSp = NULL;
-        RxContext->MajorFunction = IRP_MJ_MAXIMUM_FUNCTION + 1;
-        RxContext->MinorFunction = 0;
+        return STATUS_ACCESS_DENIED;
     }
-    else
+
+    /* Get LogonId */
+    Status = SeQueryAuthenticationIdToken(Token, LogonId);
+    if (!NT_SUCCESS(Status))
     {
-        /* Otherwise, first determine whether we are performing async operation */
-        Stack = IoGetCurrentIrpStackLocation(Irp);
-        if (Stack->FileObject != NULL)
-        {
-            PFCB Fcb;
+        return Status;
+    }
 
-            Fcb = Stack->FileObject->FsContext;
-            if (!IoIsOperationSynchronous(Irp) ||
-                ((Fcb != NULL && NodeTypeIsFcb(Fcb)) &&
-                 (Stack->MajorFunction == IRP_MJ_READ || Stack->MajorFunction == IRP_MJ_WRITE || Stack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
-                 (Fcb->pNetRoot != NULL && (Fcb->pNetRoot->Type == NET_ROOT_PIPE))))
-            {
-                RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
-            }
-        }
+    /* And SessionId */
+    Status = SeQuerySessionIdToken(Token, SessionId);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
 
-        if (Stack->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && Stack->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
-        {
-            RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
-        }
-        if (Stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
-        {
-            RxContext->Flags |= RX_CONTEXT_FLAG_ASYNC_OPERATION;
-        }
+    if (RxContext->Create.UserName.Buffer != NULL)
+    {
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto Leave;
+    }
 
-        /* Set proper flags if TopLevl IRP/Device */
-        if (!RxIsThisTheTopLevelIrp(Irp))
-        {
-            RxContext->Flags |= RX_CONTEXT_FLAG_RECURSIVE_CALL;
-        }
-        if (RxGetTopDeviceObjectIfRdbssIrp() == RxDeviceObject)
-        {
-            RxContext->Flags |= RX_CONTEXT_FLAG_THIS_DEVICE_TOP_LEVEL;
-        }
+    /* Deal with connection credentials */
+    if (RxContext->Create.UserDomainName.Buffer != NULL)
+    {
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto Leave;
+    }
 
-        /* Copy stack information */
-        RxContext->MajorFunction = Stack->MajorFunction;
-        RxContext->MinorFunction = Stack->MinorFunction;
-        ASSERT(RxContext->MajorFunction <= IRP_MJ_MAXIMUM_FUNCTION);
-        RxContext->CurrentIrpSp = Stack;
+    if (RxContext->Create.Password.Buffer != NULL)
+    {
+        UNIMPLEMENTED;
+        Status = STATUS_NOT_IMPLEMENTED;
+        goto Leave;
+    }
 
-        /* If we have a FO associated, learn for more */
-        if (Stack->FileObject != NULL)
+Leave:
+    if (NT_SUCCESS(Status))
+    {
+        /* If that's a CSC instance, mark it as such */
+        if (RxIsThisACscAgentOpen(RxContext))
         {
-            PFCB Fcb;
-            PFOBX Fobx;
-
-            /* Get the FCB and CCB (FOBX) */
-            Fcb = Stack->FileObject->FsContext;
-            Fobx = Stack->FileObject->FsContext2;
-            RxContext->pFcb = (PMRX_FCB)Fcb;
-            if (Fcb != NULL && NodeTypeIsFcb(Fcb))
-            {
-                RxContext->NonPagedFcb = Fcb->NonPaged;
-            }
-
-            /* We have a FOBX, this not a DFS opening, keep track of it */
-            if (Fobx != NULL && Fobx != UIntToPtr(DFS_OPEN_CONTEXT) && Fobx != UIntToPtr(DFS_DOWNLEVEL_OPEN_CONTEXT))
-            {
-                RxContext->pFobx = (PMRX_FOBX)Fobx;
-                RxContext->pRelevantSrvOpen = Fobx->pSrvOpen;
-                if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
-                {
-                    RxContext->FobxSerialNumber = InterlockedIncrement((volatile LONG *)&Fobx->FobxSerialNumber);
-                }
-            }
-            else
-            {
-                RxContext->pFobx = NULL;
-            }
+            *Flags |= VNETROOT_FLAG_CSCAGENT_INSTANCE;
+        }
+        return Status;
+    }
 
-            /* In case of directory change notification, Fobx may be a VNetRoot, take note of that */
-            if (RxContext->MajorFunction == IRP_MJ_DIRECTORY_CONTROL && RxContext->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY &&
-                Fobx != NULL)
-            {
-                PV_NET_ROOT VNetRoot = NULL;
+    return Status;
+}
 
-                if (Fobx->NodeTypeCode == RDBSS_NTC_FOBX)
-                {
-                    VNetRoot = Fcb->VNetRoot;
-                }
-                else if (Fobx->NodeTypeCode == RDBSS_NTC_V_NETROOT)
-                {
-                    VNetRoot = (PV_NET_ROOT)Fobx;
-                }
+/*
+ * @implemented
+ */
+VOID
+RxInitializeWorkQueue(
+   PRX_WORK_QUEUE WorkQueue,
+   WORK_QUEUE_TYPE WorkQueueType,
+   ULONG MaximumNumberOfWorkerThreads,
+   ULONG MinimumNumberOfWorkerThreads)
+{
+    PAGED_CODE();
 
-                if (VNetRoot != NULL)
-                {
-                    RxContext->NotifyChangeDirectory.pVNetRoot = (PMRX_V_NET_ROOT)VNetRoot;
-                }
-            }
+    WorkQueue->Type = WorkQueueType;
+    WorkQueue->MaximumNumberOfWorkerThreads = MaximumNumberOfWorkerThreads;
+    WorkQueue->MinimumNumberOfWorkerThreads = MinimumNumberOfWorkerThreads;
 
-            /* Remember if that's a write through file */
-            RxContext->RealDevice = Stack->FileObject->DeviceObject;
-            if (BooleanFlagOn(Stack->FileObject->Flags, FO_WRITE_THROUGH))
-            {
-                RxContext->Flags |= RX_CONTEXT_FLAG_WRITE_THROUGH;
-            }
-        }
-    }
+    WorkQueue->State = RxWorkQueueActive;
+    WorkQueue->SpinUpRequestPending = FALSE;
+    WorkQueue->pRundownContext = NULL;
+    WorkQueue->NumberOfWorkItemsDispatched = 0;
+    WorkQueue->NumberOfWorkItemsToBeDispatched = 0;
+    WorkQueue->CumulativeQueueLength = 0;
+    WorkQueue->NumberOfSpinUpRequests = 0;
+    WorkQueue->NumberOfActiveWorkerThreads = 0;
+    WorkQueue->NumberOfIdleWorkerThreads = 0;
+    WorkQueue->NumberOfFailedSpinUpRequests = 0;
+    WorkQueue->WorkQueueItemForSpinUpWorkerThreadInUse = 0;
+    WorkQueue->WorkQueueItemForTearDownWorkQueue.List.Flink = NULL;
+    WorkQueue->WorkQueueItemForTearDownWorkQueue.WorkerRoutine = NULL;
+    WorkQueue->WorkQueueItemForTearDownWorkQueue.Parameter = NULL;
+    WorkQueue->WorkQueueItemForTearDownWorkQueue.pDeviceObject = NULL;
+    WorkQueue->WorkQueueItemForSpinUpWorkerThread.List.Flink = NULL;
+    WorkQueue->WorkQueueItemForSpinUpWorkerThread.WorkerRoutine = NULL;
+    WorkQueue->WorkQueueItemForSpinUpWorkerThread.Parameter = NULL;
+    WorkQueue->WorkQueueItemForSpinUpWorkerThread.pDeviceObject = NULL;
+    WorkQueue->WorkQueueItemForSpinDownWorkerThread.List.Flink = NULL;
+    WorkQueue->WorkQueueItemForSpinDownWorkerThread.WorkerRoutine = NULL;
+    WorkQueue->WorkQueueItemForSpinDownWorkerThread.Parameter = NULL;
+    WorkQueue->WorkQueueItemForSpinDownWorkerThread.pDeviceObject = NULL;
 
-    if (RxContext->MajorFunction != IRP_MJ_DEVICE_CONTROL)
-    {
-        DPRINT("New Ctxt: %p for MN: %d, IRP: %p, THRD: %p, FCB: %p, FOBX:%p #%lx\n",
-               RxContext, RxContext->MinorFunction, Irp,
-               PsGetCurrentThread(), RxContext->pFcb, RxContext->pFobx,
-               RxContext->SerialNumber);
-    }
+    KeInitializeQueue(&WorkQueue->Queue, MaximumNumberOfWorkerThreads);
+    KeInitializeSpinLock(&WorkQueue->SpinLock);
 }
 
 /*
  * @implemented
  */
 NTSTATUS
-NTAPI
-RxInitializeDispatcher(
-    VOID)
+RxInitializeWorkQueueDispatcher(
+   PRX_WORK_QUEUE_DISPATCHER Dispatcher)
 {
     NTSTATUS Status;
-    HANDLE ThreadHandle;
+    ULONG MaximumNumberOfWorkerThreads;
 
     PAGED_CODE();
 
-    RxFileSystemDeviceObject->DispatcherContext.NumberOfWorkerThreads = 0;
-    RxFileSystemDeviceObject->DispatcherContext.pTearDownEvent = NULL;
-
-    /* Set appropriate timeouts: 10s & 60s */
-    RxWorkQueueWaitInterval[CriticalWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
-    RxWorkQueueWaitInterval[DelayedWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
-    RxWorkQueueWaitInterval[HyperCriticalWorkQueue].QuadPart = -10 * 1000 * 1000 * 10;
-    RxSpinUpDispatcherWaitInterval.QuadPart = -60 * 1000 * 1000 * 10;
+    /* Number of threads will depend on system capacity */
+    if (MmQuerySystemSize() != MmLargeSystem)
+    {
+        MaximumNumberOfWorkerThreads = 5;
+    }
+    else
+    {
+        MaximumNumberOfWorkerThreads = 10;
+    }
 
-    RxDispatcher.NumberOfProcessors = 1;
-    RxDispatcher.OwnerProcess = IoGetCurrentProcess();
-    RxDispatcher.pWorkQueueDispatcher = &RxDispatcherWorkQueues;
+    /* Initialize the work queues */
+    RxInitializeWorkQueue(&Dispatcher->WorkQueue[CriticalWorkQueue], CriticalWorkQueue,
+                          MaximumNumberOfWorkerThreads, 1);
+    RxInitializeWorkQueue(&Dispatcher->WorkQueue[DelayedWorkQueue], DelayedWorkQueue, 2, 1);
+    RxInitializeWorkQueue(&Dispatcher->WorkQueue[HyperCriticalWorkQueue], HyperCriticalWorkQueue, 5, 1);
 
-    /* Initialize our dispatchers */
-    Status = RxInitializeWorkQueueDispatcher(RxDispatcher.pWorkQueueDispatcher);
+    /* And start the worker threads */
+    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[HyperCriticalWorkQueue],
+                                  RxBootstrapWorkerThreadDispatcher,
+                                  &Dispatcher->WorkQueue[HyperCriticalWorkQueue]);
     if (!NT_SUCCESS(Status))
     {
         return Status;
     }
 
-    Status = RxInitializeMRxDispatcher(RxFileSystemDeviceObject);
+    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[CriticalWorkQueue],
+                                  RxBootstrapWorkerThreadDispatcher,
+                                  &Dispatcher->WorkQueue[CriticalWorkQueue]);
     if (!NT_SUCCESS(Status))
     {
         return Status;
     }
 
-    /* And start them */
-    RxDispatcher.State = RxDispatcherActive;
-    InitializeListHead(&RxDispatcher.SpinUpRequests);
-    KeInitializeSpinLock(&RxDispatcher.SpinUpRequestsLock);
-    KeInitializeEvent(&RxDispatcher.SpinUpRequestsEvent, 0, 0);
-    KeInitializeEvent(&RxDispatcher.SpinUpRequestsTearDownEvent, 0, 0);
-    Status = PsCreateSystemThread(&ThreadHandle, PROCESS_ALL_ACCESS, NULL,
-                                  NULL, NULL, RxSpinUpRequestsDispatcher, &RxDispatcher);
-    if (NT_SUCCESS(Status))
-    {
-        ZwClose(ThreadHandle);
-    }
-
+    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[DelayedWorkQueue],
+                                  RxBootstrapWorkerThreadDispatcher,
+                                  &Dispatcher->WorkQueue[DelayedWorkQueue]);
     return Status;
 }
 
@@ -3343,1036 +4752,1225 @@ RxInitializeDispatcher(
  * @implemented
  */
 VOID
-RxInitializeFcbTable(
-    IN OUT PRX_FCB_TABLE FcbTable,
-    IN BOOLEAN CaseInsensitiveMatch)
+RxInitiateSrvOpenKeyAssociation(
+   IN OUT PSRV_OPEN SrvOpen)
 {
-    USHORT i;
+    PRX_BUFFERING_MANAGER BufferingManager;
 
     PAGED_CODE();
 
-    FcbTable->NodeTypeCode = RDBSS_NTC_FCB_TABLE;
-    FcbTable->NodeByteSize = sizeof(RX_FCB_TABLE);
-
-    ExInitializeResourceLite(&FcbTable->TableLock);
-    FcbTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
-    FcbTable->Version = 0;
-    FcbTable->TableEntryForNull = NULL;
+    SrvOpen->Key = NULL;
 
-    FcbTable->NumberOfBuckets = RX_FCB_TABLE_NUMBER_OF_HASH_BUCKETS;
-    for (i = 0; i < FcbTable->NumberOfBuckets; ++i)
-    {
-        InitializeListHead(&FcbTable->HashBuckets[i]);
-    }
+    /* Just keep track of the opening request */
+    BufferingManager = &((PSRV_CALL)((PFCB)SrvOpen->pFcb)->VNetRoot->pNetRoot->pSrvCall)->BufferingManager;
+    InterlockedIncrement(&BufferingManager->NumberOfOutstandingOpens);
 
-    FcbTable->Lookups = 0;
-    FcbTable->FailedLookups = 0;
-    FcbTable->Compares = 0;
+    InitializeListHead(&SrvOpen->SrvOpenKeyList);
 }
 
 /*
  * @implemented
  */
-VOID
-NTAPI
-RxInitializeLowIoContext(
-    OUT PLOWIO_CONTEXT LowIoContext,
-    IN ULONG Operation)
+NTSTATUS
+RxInsertWorkQueueItem(
+    PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
+    WORK_QUEUE_TYPE WorkQueueType,
+    PRX_WORK_QUEUE_ITEM WorkQueueItem)
 {
-    PRX_CONTEXT RxContext;
-    PIO_STACK_LOCATION Stack;
-
-    PAGED_CODE();
-
-    RxContext = CONTAINING_RECORD(LowIoContext, RX_CONTEXT, LowIoContext);
-    ASSERT(LowIoContext = &RxContext->LowIoContext);
+    KIRQL OldIrql;
+    NTSTATUS Status;
+    BOOLEAN SpinUpThreads;
+    PRX_WORK_QUEUE WorkQueue;
 
-    Stack = RxContext->CurrentIrpSp;
+    /* No dispatcher, nothing to insert */
+    if (RxDispatcher.State != RxDispatcherActive)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
 
-    KeInitializeEvent(&RxContext->SyncEvent, NotificationEvent, FALSE);
-    RxContext->LowIoContext.ResourceThreadId = (ERESOURCE_THREAD)PsGetCurrentThread();
-    RxContext->LowIoContext.Operation = Operation;
+    /* Get the work queue */
+    WorkQueue = &RxDispatcher.pWorkQueueDispatcher->WorkQueue[WorkQueueType];
 
-    switch (Operation)
+    KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
+    /* Only insert if the work queue is in decent state */
+    if (WorkQueue->State != RxWorkQueueActive || pMRxDeviceObject->DispatcherContext.pTearDownEvent != NULL)
     {
-        case LOWIO_OP_READ:
-        case LOWIO_OP_WRITE:
-            /* In case of RW, set a canary, to make sure these fields are properly set
-             * they will be asserted when lowio request will be submit to mini-rdr
-             * See LowIoSubmit()
-             */
-            RxContext->LowIoContext.ParamsFor.ReadWrite.ByteOffset = 0xFFFFFFEE;
-            RxContext->LowIoContext.ParamsFor.ReadWrite.ByteCount = 0xEEEEEEEE;
-            RxContext->LowIoContext.ParamsFor.ReadWrite.Key = Stack->Parameters.Read.Key;
+        Status = STATUS_UNSUCCESSFUL;
+    }
+    else
+    {
+        SpinUpThreads = FALSE;
+        WorkQueueItem->pDeviceObject = pMRxDeviceObject;
+        InterlockedIncrement(&pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads);
+        WorkQueue->CumulativeQueueLength += WorkQueue->NumberOfWorkItemsToBeDispatched;
+        InterlockedIncrement(&WorkQueue->NumberOfWorkItemsToBeDispatched);
 
-            /* Keep track of paging IOs */
-            if (BooleanFlagOn(RxContext->CurrentIrp->Flags, IRP_PAGING_IO))
-            {
-                RxContext->LowIoContext.ParamsFor.ReadWrite.Flags = LOWIO_READWRITEFLAG_PAGING_IO;
-            }
-            else
-            {
-                RxContext->LowIoContext.ParamsFor.ReadWrite.Flags = 0;
-            }
+        /* If required (and possible!), spin up a new worker thread */
+        if (WorkQueue->NumberOfIdleWorkerThreads < WorkQueue->NumberOfWorkItemsToBeDispatched &&
+            WorkQueue->NumberOfActiveWorkerThreads < WorkQueue->MaximumNumberOfWorkerThreads &&
+            !WorkQueue->SpinUpRequestPending)
+        {
+            WorkQueue->SpinUpRequestPending = TRUE;
+            SpinUpThreads = TRUE;
+        }
 
-            break;
+        Status = STATUS_SUCCESS;
+    }
+    KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
 
-        case LOWIO_OP_FSCTL:
-        case LOWIO_OP_IOCTL:
-            /* This will be initialized later on with a call to RxLowIoPopulateFsctlInfo() */
-            RxContext->LowIoContext.ParamsFor.FsCtl.Flags = 0;
-            RxContext->LowIoContext.ParamsFor.FsCtl.InputBufferLength = 0;
-            RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = NULL;
-            RxContext->LowIoContext.ParamsFor.FsCtl.OutputBufferLength = 0;
-            RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = NULL;
-            RxContext->LowIoContext.ParamsFor.FsCtl.MinorFunction = 0;
-            break;
+    /* If we failed, return and still not insert item */
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
 
-        /* Nothing to do for these */
-        case LOWIO_OP_SHAREDLOCK:
-        case LOWIO_OP_EXCLUSIVELOCK:
-        case LOWIO_OP_UNLOCK:
-        case LOWIO_OP_UNLOCK_MULTIPLE:
-        case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
-        case LOWIO_OP_CLEAROUT:
-            break;
+    /* All fine, insert the item */
+    KeInsertQueue(&WorkQueue->Queue, &WorkQueueItem->List);
 
-        default:
-            /* Should never happen */
-            ASSERT(FALSE);
-            break;
+    /* And start a new worker thread if needed */
+    if (SpinUpThreads)
+    {
+        RxSpinUpWorkerThreads(WorkQueue);
     }
+
+    return Status;
 }
 
-/*
- * @implemented
- */
-VOID
-RxInitializeLowIoPerFcbInfo(
-    PLOWIO_PER_FCB_INFO LowIoPerFcbInfo)
+BOOLEAN
+RxIsThisACscAgentOpen(
+    IN PRX_CONTEXT RxContext)
 {
-    PAGED_CODE();
+    BOOLEAN CscAgent;
 
-    InitializeListHead(&LowIoPerFcbInfo->PagingIoReadsOutstanding);
-    InitializeListHead(&LowIoPerFcbInfo->PagingIoWritesOutstanding);
-}
+    CscAgent = FALSE;
 
-/*
- * @implemented
- */
-NTSTATUS
-RxInitializeMRxDispatcher(
-     IN OUT PRDBSS_DEVICE_OBJECT pMRxDeviceObject)
-{
-    PAGED_CODE();
+    /* Client Side Caching is DFS stuff - we don't support it */
+    if (RxContext->Create.EaLength != 0)
+    {
+        UNIMPLEMENTED;
+    }
 
-    pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads = 0;
-    pMRxDeviceObject->DispatcherContext.pTearDownEvent = NULL;
+    if (RxContext->Create.NtCreateParameters.DfsNameContext != NULL &&
+        ((PDFS_NAME_CONTEXT)RxContext->Create.NtCreateParameters.DfsNameContext)->NameContextType == 0xAAAAAAAA)
+    {
+        CscAgent = TRUE;
+    }
 
-    return STATUS_SUCCESS;
+    return CscAgent;
 }
 
-/*
- * @implemented
- */
 VOID
-RxInitializePrefixTable(
-    IN OUT PRX_PREFIX_TABLE ThisTable,
-    IN ULONG TableSize OPTIONAL,
-    IN BOOLEAN CaseInsensitiveMatch)
+RxLockUserBuffer(
+    IN PRX_CONTEXT RxContext,
+    IN LOCK_OPERATION Operation,
+    IN ULONG BufferLength)
 {
+    PIRP Irp;
+    PMDL Mdl = NULL;
+
     PAGED_CODE();
 
-    if (TableSize == 0)
-    {
-        TableSize = RX_PREFIX_TABLE_DEFAULT_LENGTH;
+    _SEH2_TRY
+    {
+        Irp = RxContext->CurrentIrp;
+        /* If we already have a MDL, make sure it's locked */
+        if (Irp->MdlAddress != NULL)
+        {
+            ASSERT(RxLowIoIsMdlLocked(Irp->MdlAddress));
+        }
+        else
+        {
+            /* That likely means the driver asks for buffered IOs - we don't support it! */
+            ASSERT(!BooleanFlagOn(Irp->Flags, IRP_INPUT_OPERATION));
+
+            /* If we have a real length */
+            if (BufferLength > 0)
+            {
+                /* Allocate a MDL and lock it */
+                Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
+                if (Mdl == NULL)
+                {
+                    RxContext->StoredStatus = STATUS_INSUFFICIENT_RESOURCES;
+                    ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
+                }
+
+                MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
+            }
+        }
     }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        NTSTATUS Status;
 
-    ThisTable->NodeTypeCode = RDBSS_NTC_PREFIX_TABLE;
-    ThisTable->NodeByteSize = sizeof(RX_PREFIX_TABLE);
-    InitializeListHead(&ThisTable->MemberQueue);
-    ThisTable->Version = 0;
-    ThisTable->TableEntryForNull = NULL;
-    ThisTable->IsNetNameTable = FALSE;
-    ThisTable->CaseInsensitiveMatch = CaseInsensitiveMatch;
-    ThisTable->TableSize = TableSize;
+        Status = _SEH2_GetExceptionCode();
 
-    if (TableSize > 0)
-    {
-        USHORT i;
+        /* Free the possible MDL we have allocated */
+        IoFreeMdl(Mdl);
+        Irp->MdlAddress = NULL;
 
-        for (i = 0; i < RX_PREFIX_TABLE_DEFAULT_LENGTH; ++i)
+        RxContext->Flags |= RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT;
+
+        /* Fix status */
+        if (!FsRtlIsNtstatusExpected(Status))
         {
-            InitializeListHead(&ThisTable->HashBuckets[i]);
+            Status = STATUS_INVALID_USER_BUFFER;
         }
+
+        RxContext->IoStatusBlock.Status = Status;
+        ExRaiseStatus(Status);
     }
+    _SEH2_END;
 }
 
 /*
  * @implemented
  */
-VOID
-RxInitializePurgeSyncronizationContext(
-    PPURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext)
-{
-    PAGED_CODE();
-
-    InitializeListHead(&PurgeSyncronizationContext->ContextsAwaitingPurgeCompletion);
-    PurgeSyncronizationContext->PurgeInProgress = FALSE;
-}
-
-NTSTATUS
-RxInitializeSrvCallParameters(
-    IN PRX_CONTEXT RxContext,
-    IN OUT PSRV_CALL SrvCall)
-{
-    PAGED_CODE();
-
-    SrvCall->pPrincipalName = NULL;
-
-    /* We only have stuff to initialize for file opening from DFS */
-    if (RxContext->MajorFunction != IRP_MJ_CREATE || RxContext->Create.EaLength == 0)
-    {
-        return STATUS_SUCCESS;
-    }
-
-    ASSERT(RxContext->Create.EaBuffer != NULL);
-
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS
-RxInitializeVNetRootParameters(
-   PRX_CONTEXT RxContext,
-   OUT LUID *LogonId,
-   OUT PULONG SessionId,
-   OUT PUNICODE_STRING *UserNamePtr,
-   OUT PUNICODE_STRING *UserDomainNamePtr,
-   OUT PUNICODE_STRING *PasswordPtr,
-   OUT PULONG Flags)
+RxLowIoCompletionTail(
+    IN PRX_CONTEXT RxContext)
 {
     NTSTATUS Status;
-    PACCESS_TOKEN Token;
+    USHORT Operation;
 
     PAGED_CODE();
 
-    DPRINT("RxInitializeVNetRootParameters(%p, %p, %p, %p, %p, %p, %p)\n", RxContext,
-           LogonId, SessionId, UserNamePtr, UserDomainNamePtr, PasswordPtr, Flags);
-
-    *UserNamePtr = NULL;
-    *UserDomainNamePtr = NULL;
-    *PasswordPtr = NULL;
-    /* By default, that's not CSC instance */
-    *Flags &= ~VNETROOT_FLAG_CSCAGENT_INSTANCE;
-
-    Token = SeQuerySubjectContextToken(&RxContext->Create.NtCreateParameters.SecurityContext->AccessState->SubjectSecurityContext);
-    if (SeTokenIsRestricted(Token))
-    {
-        return STATUS_ACCESS_DENIED;
-    }
+    DPRINT("RxLowIoCompletionTail(%p)\n", RxContext);
 
-    /* Get LogonId */
-    Status = SeQueryAuthenticationIdToken(Token, LogonId);
-    if (!NT_SUCCESS(Status))
+    /* Only continue if we're at APC_LEVEL or lower */
+    if (KeGetCurrentIrql() >= DISPATCH_LEVEL &&
+        !BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL))
     {
-        return Status;
+        return STATUS_MORE_PROCESSING_REQUIRED;
     }
 
-    /* And SessionId */
-    Status = SeQuerySessionIdToken(Token, SessionId);
-    if (!NT_SUCCESS(Status))
+    /* Call the completion routine */
+    DPRINT("Calling completion routine: %p\n", RxContext->LowIoContext.CompletionRoutine);
+    Status = RxContext->LowIoContext.CompletionRoutine(RxContext);
+    if (Status == STATUS_MORE_PROCESSING_REQUIRED || Status == STATUS_RETRY)
     {
         return Status;
     }
 
-    if (RxContext->Create.UserName.Buffer != NULL)
-    {
-        UNIMPLEMENTED;
-        Status = STATUS_NOT_IMPLEMENTED;
-        goto Leave;
-    }
-
-    /* Deal with connection credentials */
-    if (RxContext->Create.UserDomainName.Buffer != NULL)
+    /* If it was a RW operation, for a paging file ... */
+    Operation = RxContext->LowIoContext.Operation;
+    if (Operation == LOWIO_OP_READ || Operation == LOWIO_OP_WRITE)
     {
-        UNIMPLEMENTED;
-        Status = STATUS_NOT_IMPLEMENTED;
-        goto Leave;
+        /* Remove ourselves from the list and resume operations */
+        if (BooleanFlagOn(RxContext->LowIoContext.ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO))
+        {
+            ExAcquireFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
+            RemoveEntryList(&RxContext->RxContextSerializationQLinks);
+            RxContext->RxContextSerializationQLinks.Flink = NULL;
+            RxContext->RxContextSerializationQLinks.Blink = NULL;
+            ExReleaseFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
+            RxResumeBlockedOperations_ALL(RxContext);
+        }
     }
-
-    if (RxContext->Create.Password.Buffer != NULL)
+    else
     {
-        UNIMPLEMENTED;
-        Status = STATUS_NOT_IMPLEMENTED;
-        goto Leave;
+        /* Sanity check: we had known operation */
+        ASSERT(Operation < LOWIO_OP_MAXIMUM);
     }
 
-Leave:
-    if (NT_SUCCESS(Status))
+    /* If not sync operation, complete now. Otherwise, caller has already completed */
+    if (!BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_SYNCCALL))
     {
-        /* If that's a CSC instance, mark it as such */
-        if (RxIsThisACscAgentOpen(RxContext))
-        {
-            *Flags |= VNETROOT_FLAG_CSCAGENT_INSTANCE;
-        }
-        return Status;
+        RxCompleteRequest(RxContext, Status);
     }
 
+    DPRINT("Status: %x\n", Status);
     return Status;
 }
 
 /*
  * @implemented
  */
-VOID
-RxInitializeWorkQueue(
-   PRX_WORK_QUEUE WorkQueue,
-   WORK_QUEUE_TYPE WorkQueueType,
-   ULONG MaximumNumberOfWorkerThreads,
-   ULONG MinimumNumberOfWorkerThreads)
+NTSTATUS
+NTAPI
+RxLowIoPopulateFsctlInfo(
+    IN PRX_CONTEXT RxContext)
 {
-    PAGED_CODE();
-
-    WorkQueue->Type = WorkQueueType;
-    WorkQueue->MaximumNumberOfWorkerThreads = MaximumNumberOfWorkerThreads;
-    WorkQueue->MinimumNumberOfWorkerThreads = MinimumNumberOfWorkerThreads;
+    PMDL Mdl;
+    PIRP Irp;
+    UCHAR Method;
+    PIO_STACK_LOCATION Stack;
 
-    WorkQueue->State = RxWorkQueueActive;
-    WorkQueue->SpinUpRequestPending = FALSE;
-    WorkQueue->pRundownContext = NULL;
-    WorkQueue->NumberOfWorkItemsDispatched = 0;
-    WorkQueue->NumberOfWorkItemsToBeDispatched = 0;
-    WorkQueue->CumulativeQueueLength = 0;
-    WorkQueue->NumberOfSpinUpRequests = 0;
-    WorkQueue->NumberOfActiveWorkerThreads = 0;
-    WorkQueue->NumberOfIdleWorkerThreads = 0;
-    WorkQueue->NumberOfFailedSpinUpRequests = 0;
-    WorkQueue->WorkQueueItemForSpinUpWorkerThreadInUse = 0;
-    WorkQueue->WorkQueueItemForTearDownWorkQueue.List.Flink = NULL;
-    WorkQueue->WorkQueueItemForTearDownWorkQueue.WorkerRoutine = NULL;
-    WorkQueue->WorkQueueItemForTearDownWorkQueue.Parameter = NULL;
-    WorkQueue->WorkQueueItemForTearDownWorkQueue.pDeviceObject = NULL;
-    WorkQueue->WorkQueueItemForSpinUpWorkerThread.List.Flink = NULL;
-    WorkQueue->WorkQueueItemForSpinUpWorkerThread.WorkerRoutine = NULL;
-    WorkQueue->WorkQueueItemForSpinUpWorkerThread.Parameter = NULL;
-    WorkQueue->WorkQueueItemForSpinUpWorkerThread.pDeviceObject = NULL;
-    WorkQueue->WorkQueueItemForSpinDownWorkerThread.List.Flink = NULL;
-    WorkQueue->WorkQueueItemForSpinDownWorkerThread.WorkerRoutine = NULL;
-    WorkQueue->WorkQueueItemForSpinDownWorkerThread.Parameter = NULL;
-    WorkQueue->WorkQueueItemForSpinDownWorkerThread.pDeviceObject = NULL;
+    PAGED_CODE();
 
-    KeInitializeQueue(&WorkQueue->Queue, MaximumNumberOfWorkerThreads);
-    KeInitializeSpinLock(&WorkQueue->SpinLock);
-}
+    DPRINT("RxLowIoPopulateFsctlInfo(%p)\n", RxContext);
 
-/*
- * @implemented
- */
-NTSTATUS
-RxInitializeWorkQueueDispatcher(
-   PRX_WORK_QUEUE_DISPATCHER Dispatcher)
-{
-    NTSTATUS Status;
-    ULONG MaximumNumberOfWorkerThreads;
+    Irp = RxContext->CurrentIrp;
+    Stack = RxContext->CurrentIrpSp;
 
-    PAGED_CODE();
+    /* Copy stack parameters */
+    RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode = Stack->Parameters.FileSystemControl.FsControlCode;
+    RxContext->LowIoContext.ParamsFor.FsCtl.InputBufferLength = Stack->Parameters.FileSystemControl.InputBufferLength;
+    RxContext->LowIoContext.ParamsFor.FsCtl.OutputBufferLength = Stack->Parameters.FileSystemControl.OutputBufferLength;
+    RxContext->LowIoContext.ParamsFor.FsCtl.MinorFunction = Stack->MinorFunction;
+    Method = METHOD_FROM_CTL_CODE(RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode);
 
-    /* Number of threads will depend on system capacity */
-    if (MmQuerySystemSize() != MmLargeSystem)
+    /* Same buffer in case of buffered */
+    if (Method == METHOD_BUFFERED)
     {
-        MaximumNumberOfWorkerThreads = 5;
+        RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
+        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->AssociatedIrp.SystemBuffer;
+
+        return STATUS_SUCCESS;
     }
-    else
+
+    /* Two buffers for neither */
+    if (Method == METHOD_NEITHER)
     {
-        MaximumNumberOfWorkerThreads = 10;
+        RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Stack->Parameters.FileSystemControl.Type3InputBuffer;
+        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->UserBuffer;
+
+        return STATUS_SUCCESS;
     }
 
-    /* Initialize the work queues */
-    RxInitializeWorkQueue(&Dispatcher->WorkQueue[CriticalWorkQueue], CriticalWorkQueue,
-                          MaximumNumberOfWorkerThreads, 1);
-    RxInitializeWorkQueue(&Dispatcher->WorkQueue[DelayedWorkQueue], DelayedWorkQueue, 2, 1);
-    RxInitializeWorkQueue(&Dispatcher->WorkQueue[HyperCriticalWorkQueue], HyperCriticalWorkQueue, 5, 1);
+    /* Only IN/OUT remain */
+    ASSERT(Method == METHOD_IN_DIRECT || Method == METHOD_OUT_DIRECT);
 
-    /* And start the worker threads */
-    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[HyperCriticalWorkQueue],
-                                  RxBootstrapWorkerThreadDispatcher,
-                                  &Dispatcher->WorkQueue[HyperCriticalWorkQueue]);
-    if (!NT_SUCCESS(Status))
+    /* Use system buffer for input */
+    RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
+    /* And MDL for output */
+    Mdl = Irp->MdlAddress;
+    if (Mdl != NULL)
     {
-        return Status;
-    }
-
-    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[CriticalWorkQueue],
-                                  RxBootstrapWorkerThreadDispatcher,
-                                  &Dispatcher->WorkQueue[CriticalWorkQueue]);
-    if (!NT_SUCCESS(Status))
+        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        if (RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer == NULL)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+    else
     {
-        return Status;
+        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = NULL;
     }
 
-    Status = RxSpinUpWorkerThread(&Dispatcher->WorkQueue[DelayedWorkQueue],
-                                  RxBootstrapWorkerThreadDispatcher,
-                                  &Dispatcher->WorkQueue[DelayedWorkQueue]);
-    return Status;
-}
-
-VOID
-RxInitiateSrvOpenKeyAssociation (
-   IN OUT PSRV_OPEN SrvOpen
-   )
-{
-    UNIMPLEMENTED;
+    return STATUS_SUCCESS;
 }
 
-/*
- * @implemented
- */
 NTSTATUS
-RxInsertWorkQueueItem(
-    PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
-    WORK_QUEUE_TYPE WorkQueueType,
-    PRX_WORK_DISPATCH_ITEM DispatchItem)
+NTAPI
+RxLowIoSubmit(
+    IN PRX_CONTEXT RxContext,
+    IN PLOWIO_COMPLETION_ROUTINE CompletionRoutine)
 {
-    KIRQL OldIrql;
     NTSTATUS Status;
-    BOOLEAN SpinUpThreads;
-    PRX_WORK_QUEUE WorkQueue;
+    USHORT Operation;
+    BOOLEAN Synchronous;
+    PLOWIO_CONTEXT LowIoContext;
 
-    /* No dispatcher, nothing to insert */
-    if (RxDispatcher.State != RxDispatcherActive)
-    {
-        return STATUS_UNSUCCESSFUL;
-    }
+    DPRINT("RxLowIoSubmit(%p, %p)\n", RxContext, CompletionRoutine);
 
-    /* Get the work queue */
-    WorkQueue = &RxDispatcher.pWorkQueueDispatcher->WorkQueue[WorkQueueType];
+    PAGED_CODE();
 
-    KeAcquireSpinLock(&WorkQueue->SpinLock, &OldIrql);
-    /* Only insert if the work queue is in decent state */
-    if (WorkQueue->State != RxWorkQueueActive || pMRxDeviceObject->DispatcherContext.pTearDownEvent != NULL)
+    LowIoContext = &RxContext->LowIoContext;
+    Synchronous = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
+
+    LowIoContext->CompletionRoutine = CompletionRoutine;
+
+    Status = STATUS_SUCCESS;
+    Operation = LowIoContext->Operation;
+    switch (Operation)
     {
-        Status = STATUS_UNSUCCESSFUL;
+        case LOWIO_OP_READ:
+        case LOWIO_OP_WRITE:
+            /* Check that the parameters were properly set by caller
+             * See comment in RxInitializeLowIoContext()
+             */
+            ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteOffset != 0xFFFFFFEE);
+            ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteCount != 0xEEEEEEEE);
+
+            /* Lock the buffer */
+            RxLockUserBuffer(RxContext,
+                             (Operation == LOWIO_OP_READ ? IoWriteAccess : IoReadAccess),
+                             LowIoContext->ParamsFor.ReadWrite.ByteCount);
+            if (RxNewMapUserBuffer(RxContext) == NULL)
+            {
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+            LowIoContext->ParamsFor.ReadWrite.Buffer = RxContext->CurrentIrp->MdlAddress;
+
+            /* If that's a paging IO, initialize serial operation */
+            if (BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO))
+            {
+                PFCB Fcb;
+
+                Fcb = (PFCB)RxContext->pFcb;
+
+                ExAcquireFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
+                RxContext->BlockedOpsMutex = &RxLowIoPagingIoSyncMutex;
+                if (Operation == LOWIO_OP_READ)
+                {
+                    InsertTailList(&Fcb->Specific.Fcb.PagingIoReadsOutstanding, &RxContext->RxContextSerializationQLinks);
+                }
+                else
+                {
+                    InsertTailList(&Fcb->Specific.Fcb.PagingIoWritesOutstanding, &RxContext->RxContextSerializationQLinks);
+                }
+
+                ExReleaseFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
+            }
+
+            break;
+
+        case LOWIO_OP_FSCTL:
+        case LOWIO_OP_IOCTL:
+            /* Set FSCTL/IOCTL parameters */
+            Status = RxLowIoPopulateFsctlInfo(RxContext);
+            /* Check whether we're consistent: a length means a buffer */
+            if (NT_SUCCESS(Status))
+            {
+                if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0 &&
+                     LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL) ||
+                    (LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0 &&
+                     LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL))
+                {
+                    Status = STATUS_INVALID_PARAMETER;
+                }
+            }
+            break;
+
+        /* Nothing to do */
+        case LOWIO_OP_SHAREDLOCK:
+        case LOWIO_OP_EXCLUSIVELOCK:
+        case LOWIO_OP_UNLOCK:
+        case LOWIO_OP_UNLOCK_MULTIPLE:
+        case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
+        case LOWIO_OP_CLEAROUT:
+            break;
+
+        default:
+            ASSERT(FALSE);
+            Status = STATUS_INVALID_PARAMETER;
+            break;
     }
-    else
+
+    /* No need to perform extra init in case of posting */
+    RxContext->Flags |= RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED;
+
+    /* Preflight checks were OK, time to submit */
+    if (NT_SUCCESS(Status))
     {
-        SpinUpThreads = FALSE;
-        DispatchItem->WorkQueueItem.pDeviceObject = pMRxDeviceObject;
-        InterlockedIncrement(&pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads);
-        WorkQueue->CumulativeQueueLength += WorkQueue->NumberOfWorkItemsToBeDispatched;
-        InterlockedIncrement(&WorkQueue->NumberOfWorkItemsToBeDispatched);
+        PMINIRDR_DISPATCH Dispatch;
 
-        /* If required (and possible!), spin up a new worker thread */
-        if (WorkQueue->NumberOfIdleWorkerThreads < WorkQueue->NumberOfWorkItemsToBeDispatched &&
-            WorkQueue->NumberOfActiveWorkerThreads < WorkQueue->MaximumNumberOfWorkerThreads &&
-            !WorkQueue->SpinUpRequestPending)
+        if (!Synchronous)
         {
-            WorkQueue->SpinUpRequestPending = TRUE;
-            SpinUpThreads = TRUE;
+            InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
+            /* If not synchronous, we're likely to return before the operation is finished */
+            if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
+            {
+                IoMarkIrpPending(RxContext->CurrentIrp);
+            }
         }
 
-        Status = STATUS_SUCCESS;
-    }
-    KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
+        Dispatch = RxContext->RxDeviceObject->Dispatch;
+        if (Dispatch != NULL)
+        {
+            /* We'll try to execute until the mini-rdr doesn't return pending */
+            do
+            {
+                RxContext->IoStatusBlock.Information = 0;
 
-    /* If we failed, return and still not insert item */
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
-    }
+                MINIRDR_CALL(Status, RxContext, Dispatch, MRxLowIOSubmit[Operation], (RxContext));
+                if (Status == STATUS_PENDING)
+                {
+                    /* Unless it's not synchronous, caller will be happy with pending op */
+                    if (!Synchronous)
+                    {
+                        return Status;
+                    }
 
-    /* All fine, insert the item */
-    KeInsertQueue(&WorkQueue->Queue, &DispatchItem->WorkQueueItem.List);
+                    RxWaitSync(RxContext);
+                    Status = RxContext->IoStatusBlock.Status;
+                }
+                else
+                {
+                    if (!Synchronous)
+                    {
+                        /* We had marked the IRP pending, whereas the operation finished, drop that */
+                        if (Status != STATUS_RETRY)
+                        {
+                            if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
+                            {
+                                RxContext->CurrentIrpSp->Flags &= ~SL_PENDING_RETURNED;
+                            }
 
-    /* And start a new worker thread if needed */
-    if (SpinUpThreads)
-    {
-        RxSpinUpWorkerThreads(WorkQueue);
+                            InterlockedDecrement((volatile long *)&RxContext->ReferenceCount);
+                        }
+                    }
+                }
+            } while (Status == STATUS_PENDING);
+        }
+        else
+        {
+            Status = STATUS_INVALID_PARAMETER;
+        }
     }
 
-    return Status;
+    /* Call completion and return */
+    RxContext->IoStatusBlock.Status = Status;
+    LowIoContext->Flags |= LOWIO_CONTEXT_FLAG_SYNCCALL;
+    return RxLowIoCompletionTail(RxContext);
 }
 
-BOOLEAN
-RxIsThisACscAgentOpen(
+/*
+ * @implemented
+ */
+PVOID
+RxMapSystemBuffer(
     IN PRX_CONTEXT RxContext)
 {
-    BOOLEAN CscAgent;
-
-    CscAgent = FALSE;
+    PIRP Irp;
 
-    /* Client Side Caching is DFS stuff - we don't support it */ 
-    if (RxContext->Create.EaLength != 0)
-    {
-        UNIMPLEMENTED;
-    }
+    PAGED_CODE();
 
-    if (RxContext->Create.NtCreateParameters.DfsNameContext != NULL &&
-        ((PDFS_NAME_CONTEXT)RxContext->Create.NtCreateParameters.DfsNameContext)->NameContextType == 0xAAAAAAAA)
+    Irp = RxContext->CurrentIrp;
+    /* We should have a MDL (buffered IOs are not supported!) */
+    if (Irp->MdlAddress != NULL)
     {
-        CscAgent = TRUE;
+        ASSERT(FALSE);
+        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
     }
 
-    return CscAgent;
+    /* Just return system buffer */
+    return Irp->AssociatedIrp.SystemBuffer;
 }
 
+/*
+ * @implemented
+ */
 VOID
-RxLockUserBuffer(
-    IN PRX_CONTEXT RxContext,
-    IN LOCK_OPERATION Operation,
-    IN ULONG BufferLength)
+RxMarkFobxOnCleanup(
+    PFOBX pFobx,
+    PBOOLEAN NeedPurge)
 {
-    PIRP Irp;
-    PMDL Mdl = NULL;
+    PFCB Fcb;
+    PFOBX ScavengerFobx;
+    LARGE_INTEGER TickCount;
+    PRDBSS_SCAVENGER Scavenger;
+
+    PAGED_CODE();
+
+    /* No FOBX, nothing to mark */
+    if (pFobx == NULL)
+    {
+        return;
+    }
+
+    /* Query time for close */
+    KeQueryTickCount(&TickCount);
+
+    Fcb = (PFCB)pFobx->pSrvOpen->pFcb;
+    ASSERT(NodeTypeIsFcb(Fcb));
 
-    PAGED_CODE();
+    Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
+    RxAcquireScavengerMutex();
 
-    _SEH2_TRY
+    ScavengerFobx = NULL;
+    /* If that's not a file, or even not a disk resource, just mark as dormant */
+    if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE || Fcb->VNetRoot->pNetRoot->DeviceType != FILE_DEVICE_DISK)
     {
-        Irp = RxContext->CurrentIrp;
-        /* If we already have a MDL, make sure it's locked */
-        if (Irp->MdlAddress != NULL)
-        {
-            ASSERT(RxLowIoIsMdlLocked(Irp->MdlAddress));
-        }
-        else
+        SetFlag(pFobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT);
+        InitializeListHead(&pFobx->ClosePendingList);
+        ++Scavenger->NumberOfDormantFiles;
+    }
+    else
+    {
+        ASSERT(Scavenger->NumberOfDormantFiles >= 0);
+        /* If we're about to reach the maximum dormant of FOBX */
+        if (Scavenger->NumberOfDormantFiles >= Scavenger->MaximumNumberOfDormantFiles)
         {
-            /* That likely means the driver asks for buffered IOs - we don't support it! */
-            ASSERT(!BooleanFlagOn(Irp->Flags, IRP_INPUT_OPERATION));
-
-            /* If we have a real length */
-            if (BufferLength > 0)
+            /* This should never be wrong... */
+            if (!IsListEmpty(&Scavenger->ClosePendingFobxsList))
             {
-                /* Allocate a MDL and lock it */
-                Mdl = IoAllocateMdl(Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp);
-                if (Mdl == NULL)
+                /* Then, take the first from the list (oldest) and save it for later purge */
+                ScavengerFobx = CONTAINING_RECORD(Scavenger->ClosePendingFobxsList.Flink, FOBX, ClosePendingList);
+                if (ScavengerFobx->pSrvOpen != NULL && ScavengerFobx->pSrvOpen->pFcb == RX_GET_MRX_FCB(Fcb))
                 {
-                    RxContext->StoredStatus = STATUS_INSUFFICIENT_RESOURCES;
-                    ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
+                    *NeedPurge = TRUE;
+                    ScavengerFobx = NULL;
+                }
+                else
+                {
+                    RxReferenceNetFobx(ScavengerFobx);
                 }
-
-                MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation);
             }
         }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        NTSTATUS Status;
 
-        Status = _SEH2_GetExceptionCode();
+        /* Mark ourselves as dormant */
+        SetFlag(pFobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT);
+        pFobx->CloseTime.QuadPart = TickCount.QuadPart;
 
-        /* Free the possible MDL we have allocated */
-        IoFreeMdl(Mdl);
-        Irp->MdlAddress = NULL;
+        /* And insert us in the list of dormant files */
+        InsertTailList(&Scavenger->ClosePendingFobxsList, &pFobx->ClosePendingList);
+        /* If scavenger was inactive, start it */
+        if (Scavenger->NumberOfDormantFiles++ == 0 && Scavenger->State == RDBSS_SCAVENGER_INACTIVE)
+        {
+            Scavenger->State = RDBSS_SCAVENGER_DORMANT;
+            RxPostOneShotTimerRequest(RxFileSystemDeviceObject, &Scavenger->WorkItem, RxScavengerTimerRoutine,
+                                      Fcb->RxDeviceObject, Scavenger->TimeLimit);
+        }
+    }
 
-        RxContext->Flags |= RX_CONTEXT_FLAG_NO_EXCEPTION_BREAKPOINT;
+    RxReleaseScavengerMutex();
 
-        /* Fix status */
-        if (!FsRtlIsNtstatusExpected(Status))
+    /* If we had reached max */
+    if (ScavengerFobx != NULL)
+    {
+        NTSTATUS Status;
+
+        /* Purge the oldest FOBX */
+        Status = RxPurgeFobxFromCache(ScavengerFobx);
+        if (Status != STATUS_SUCCESS)
         {
-            Status = STATUS_INVALID_USER_BUFFER;
+            *NeedPurge = TRUE;
         }
-
-        RxContext->IoStatusBlock.Status = Status;
-        ExRaiseStatus(Status);
     }
-    _SEH2_END;
 }
 
-NTSTATUS
-RxLowIoCompletionTail(
-    IN PRX_CONTEXT RxContext)
+/*
+ * @implemented
+ */
+VOID
+RxMarkFobxOnClose(
+    PFOBX Fobx)
 {
-    NTSTATUS Status;
-    USHORT Operation;
+    PFCB Fcb;
+    PRDBSS_SCAVENGER Scavenger;
 
     PAGED_CODE();
 
-    DPRINT("RxLowIoCompletionTail(%p)\n", RxContext);
-
-    /* Only continue if we're at APC_LEVEL or lower */
-    if (KeGetCurrentIrql() >= DISPATCH_LEVEL &&
-        !BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_CAN_COMPLETE_AT_DPC_LEVEL))
+    /* No FOBX, nothing to mark */
+    if (Fobx == NULL)
     {
-        return STATUS_MORE_PROCESSING_REQUIRED;
+        return;
     }
 
-    /* Call the completion routine */
-    DPRINT("Calling completion routine: %p\n", RxContext->LowIoContext.CompletionRoutine);
-    Status = RxContext->LowIoContext.CompletionRoutine(RxContext);
-    if (Status == STATUS_MORE_PROCESSING_REQUIRED || Status == STATUS_RETRY)
-    {
-        return Status;
-    }
+    Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
+    ASSERT(NodeTypeIsFcb(Fcb));
 
-    /* If it was a RW operation, for a paging file ... */
-    Operation = RxContext->LowIoContext.Operation;
-    if (Operation == LOWIO_OP_READ || Operation == LOWIO_OP_WRITE)
+    Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
+
+    RxAcquireScavengerMutex();
+    /* Only mark it if it was already marked as dormant */
+    if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT))
     {
-        if (BooleanFlagOn(RxContext->LowIoContext.ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO))
+        /* If FCB wasn't already decrement, do it now */
+        if (!Fobx->fOpenCountDecremented)
         {
-            UNIMPLEMENTED;
-            Status = STATUS_NOT_IMPLEMENTED;
+            Fcb = (PFCB)Fobx->pSrvOpen->pFcb;
+            ASSERT(NodeTypeIsFcb(Fcb));
+            InterlockedDecrement((volatile long *)&Fcb->OpenCount);
+
+            Fobx->fOpenCountDecremented = TRUE;
         }
-    }
-    else
-    {
-        /* Sanity check: we had known operation */
-        ASSERT(Operation < LOWIO_OP_MAXIMUM);
+
+        /* We're no longer dormant */
+        InterlockedDecrement(&Scavenger->NumberOfDormantFiles);
+        ClearFlag(Fobx->Flags, FOBX_FLAG_MARKED_AS_DORMANT);
     }
 
-    /* If not sync operation, complete now. Otherwise, caller has already completed */
-    if (!BooleanFlagOn(RxContext->LowIoContext.Flags, LOWIO_CONTEXT_FLAG_SYNCCALL))
+    /* If we were inserted in the scavenger, drop ourselves out */
+    if (!IsListEmpty(&Fobx->ClosePendingList))
     {
-        RxCompleteRequest(RxContext, Status);
+        RemoveEntryList(&Fobx->ClosePendingList);
+        InitializeListHead(&Fobx->ClosePendingList);
     }
 
-    DPRINT("Status: %x\n", Status);
-    return Status;
+    RxReleaseScavengerMutex();
 }
 
 /*
  * @implemented
  */
-NTSTATUS
-NTAPI
-RxLowIoPopulateFsctlInfo(
-    IN PRX_CONTEXT RxContext)
+PVOID
+RxNewMapUserBuffer(
+    PRX_CONTEXT RxContext)
 {
-    PMDL Mdl;
     PIRP Irp;
-    UCHAR Method;
-    PIO_STACK_LOCATION Stack;
 
     PAGED_CODE();
 
-    DPRINT("RxLowIoPopulateFsctlInfo(%p)\n", RxContext);
-
     Irp = RxContext->CurrentIrp;
-    Stack = RxContext->CurrentIrpSp;
-
-    /* Copy stack parameters */
-    RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode = Stack->Parameters.FileSystemControl.FsControlCode;
-    RxContext->LowIoContext.ParamsFor.FsCtl.InputBufferLength = Stack->Parameters.FileSystemControl.InputBufferLength;
-    RxContext->LowIoContext.ParamsFor.FsCtl.OutputBufferLength = Stack->Parameters.FileSystemControl.OutputBufferLength;
-    RxContext->LowIoContext.ParamsFor.FsCtl.MinorFunction = Stack->MinorFunction;
-    Method = METHOD_FROM_CTL_CODE(RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode);
-
-    /* Same buffer in case of buffered */
-    if (Method == METHOD_BUFFERED)
+    if (Irp->MdlAddress != NULL)
     {
-        RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
-        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->AssociatedIrp.SystemBuffer;
-
-        return STATUS_SUCCESS;
+        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
     }
 
-    /* Two buffers for neither */
-    if (Method == METHOD_NEITHER)
-    {
-        RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Stack->Parameters.FileSystemControl.Type3InputBuffer;
-        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = Irp->UserBuffer;
+    return Irp->UserBuffer;
+}
 
-        return STATUS_SUCCESS;
-    }
+BOOLEAN
+NTAPI
+RxNoOpAcquire(
+    IN PVOID Fcb,
+    IN BOOLEAN Wait)
+{
+    UNIMPLEMENTED;
+    return FALSE;
+}
 
-    /* Only IN/OUT remain */
-    ASSERT(Method == METHOD_IN_DIRECT || Method == METHOD_OUT_DIRECT);
+VOID
+NTAPI
+RxNoOpRelease(
+    IN PVOID Fcb)
+{
+    UNIMPLEMENTED;
+}
 
-    /* Use system buffer for input */
-    RxContext->LowIoContext.ParamsFor.FsCtl.pInputBuffer = Irp->AssociatedIrp.SystemBuffer;
-    /* And MDL for output */
-    Mdl = Irp->MdlAddress;
-    if (Mdl != NULL)
-    {
-        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
-        if (RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer == NULL)
-        {
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-    }
-    else
-    {
-        RxContext->LowIoContext.ParamsFor.FsCtl.pOutputBuffer = NULL;
-    }
+VOID
+RxOrphanThisFcb(
+    PFCB Fcb)
+{
+    UNIMPLEMENTED;
+}
 
-    return STATUS_SUCCESS;
+VOID
+RxOrphanSrvOpens(
+    IN PV_NET_ROOT ThisVNetRoot)
+{
+    UNIMPLEMENTED;
 }
 
-NTSTATUS
-NTAPI
-RxLowIoSubmit(
-    IN PRX_CONTEXT RxContext,
-    IN PLOWIO_COMPLETION_ROUTINE CompletionRoutine)
+/*
+ * @implemented
+ */
+BOOLEAN
+RxpAcquirePrefixTableLockShared(
+   PRX_PREFIX_TABLE pTable,
+   BOOLEAN Wait,
+   BOOLEAN ProcessBufferingStateChangeRequests)
 {
-    NTSTATUS Status;
-    USHORT Operation;
-    BOOLEAN Synchronous;
-    PLOWIO_CONTEXT LowIoContext;
+    PAGED_CODE();
 
-    DPRINT("RxLowIoSubmit(%p, %p)\n", RxContext, CompletionRoutine);
+    DPRINT("RxpAcquirePrefixTableLockShared(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
+           pTable->TableLock.ActiveEntries);
 
-    PAGED_CODE();
+    return ExAcquireResourceSharedLite(&pTable->TableLock, Wait);
+}
 
-    LowIoContext = &RxContext->LowIoContext;
-    Synchronous = !BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_ASYNC_OPERATION);
+/*
+ * @implemented
+ */
+BOOLEAN
+RxpAcquirePrefixTableLockExclusive(
+   PRX_PREFIX_TABLE pTable,
+   BOOLEAN Wait,
+   BOOLEAN ProcessBufferingStateChangeRequests)
+{
+    PAGED_CODE();
 
-    LowIoContext->CompletionRoutine = CompletionRoutine;
+    DPRINT("RxpAcquirePrefixTableLockExclusive(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
+           pTable->TableLock.ActiveEntries);
 
-    Status = STATUS_SUCCESS;
-    Operation = LowIoContext->Operation;
-    switch (Operation)
-    {
-        case LOWIO_OP_READ:
-        case LOWIO_OP_WRITE:
-            /* Check that the parameters were properly set by caller
-             * See comment in RxInitializeLowIoContext()
-             */
-            ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteOffset != 0xFFFFFFEE);
-            ASSERT(LowIoContext->ParamsFor.ReadWrite.ByteCount != 0xEEEEEEEE);
+    return ExAcquireResourceExclusiveLite(&pTable->TableLock, Wait);
+}
 
-            /* Lock the buffer */
-            RxLockUserBuffer(RxContext,
-                             (Operation == LOWIO_OP_READ ? IoWriteAccess : IoReadAccess),
-                             LowIoContext->ParamsFor.ReadWrite.ByteCount);
-            if (RxNewMapUserBuffer(RxContext) == NULL)
-            {
-                return STATUS_INSUFFICIENT_RESOURCES;
-            }
-            LowIoContext->ParamsFor.ReadWrite.Buffer = RxContext->CurrentIrp->MdlAddress;
+/*
+ * @implemented
+ */
+BOOLEAN
+RxpDereferenceAndFinalizeNetFcb(
+    OUT PFCB ThisFcb,
+    IN PRX_CONTEXT RxContext,
+    IN BOOLEAN RecursiveFinalize,
+    IN BOOLEAN ForceFinalize)
+{
+    NTSTATUS Status;
+    ULONG References;
+    PNET_ROOT NetRoot;
+    BOOLEAN ResourceAcquired, NetRootReferenced, Freed;
 
-            /* If that's a paging IO, initialize serial operation */
-            if (BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags, LOWIO_READWRITEFLAG_PAGING_IO))
-            {
-                PFCB Fcb;
+    PAGED_CODE();
 
-                Fcb = (PFCB)RxContext->pFcb;
+    ASSERT(!ForceFinalize);
+    ASSERT(NodeTypeIsFcb(ThisFcb));
+    ASSERT(RxIsFcbAcquiredExclusive(ThisFcb));
 
-                ExAcquireFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
-                RxContext->BlockedOpsMutex = &RxLowIoPagingIoSyncMutex;
-                if (Operation == LOWIO_OP_READ)
-                {
-                    InsertTailList(&Fcb->Specific.Fcb.PagingIoReadsOutstanding, &RxContext->RxContextSerializationQLinks);
-                }
-                else
-                {
-                    InsertTailList(&Fcb->Specific.Fcb.PagingIoWritesOutstanding, &RxContext->RxContextSerializationQLinks);
-                }
+    /* Unless we're recursively finalizing, or forcing, if FCB is still in use, quit */
+    References = InterlockedDecrement((volatile long *)&ThisFcb->NodeReferenceCount);
+    if (!ForceFinalize && !RecursiveFinalize && (ThisFcb->OpenCount != 0 || ThisFcb->UncleanCount != 0 || References > 1))
+    {
+        return FALSE;
+    }
 
-                ExReleaseFastMutexUnsafe(&RxLowIoPagingIoSyncMutex);
-            }
+    Freed = FALSE;
+    Status = STATUS_SUCCESS;
+    NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->pNetRoot;
+    ResourceAcquired = FALSE;
+    NetRootReferenced = FALSE;
+    /* If FCB isn't orphaned, it still have context attached */
+    if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_ORPHANED))
+    {
+        /* Don't let NetRoot go away before we're done */
+        RxReferenceNetRoot(NetRoot);
+        NetRootReferenced = TRUE;
 
-            break;
+        /* Try to acquire the table lock exclusively */
+        if (!RxIsFcbTableLockExclusive(&NetRoot->FcbTable))
+        {
+            RxReferenceNetFcb(ThisFcb);
 
-        case LOWIO_OP_FSCTL:
-        case LOWIO_OP_IOCTL:
-            /* Set FSCTL/IOCTL parameters */
-            Status = RxLowIoPopulateFsctlInfo(RxContext);
-            /* Check whether we're consistent: a length means a buffer */
-            if (NT_SUCCESS(Status))
+            if (!RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
             {
-                if ((LowIoContext->ParamsFor.FsCtl.InputBufferLength > 0 &&
-                     LowIoContext->ParamsFor.FsCtl.pInputBuffer == NULL) ||
-                    (LowIoContext->ParamsFor.FsCtl.OutputBufferLength > 0 &&
-                     LowIoContext->ParamsFor.FsCtl.pOutputBuffer == NULL))
+                if (RxContext != NULL && RxContext != (PVOID)-1 && RxContext != (PVOID)-2)
                 {
-                    Status = STATUS_INVALID_PARAMETER;
+                    RxContext->Flags |= RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
                 }
-            }
-            break;
 
-        /* Nothing to do */
-        case LOWIO_OP_SHAREDLOCK:
-        case LOWIO_OP_EXCLUSIVELOCK:
-        case LOWIO_OP_UNLOCK:
-        case LOWIO_OP_UNLOCK_MULTIPLE:
-        case LOWIO_OP_NOTIFY_CHANGE_DIRECTORY:
-        case LOWIO_OP_CLEAROUT:
-            break;
+                RxReleaseFcb(RxContext, ThisFcb);
 
-        default:
-            ASSERT(FALSE);
-            Status = STATUS_INVALID_PARAMETER;
-            break;
-    }
+                RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
 
-    /* No need to perform extra init in case of posting */
-    RxContext->Flags |= RX_CONTEXT_FLAG_NO_PREPOSTING_NEEDED;
+                Status = RxAcquireExclusiveFcb(RxContext, ThisFcb);
+            }
 
-    /* Preflight checks were OK, time to submit */
-    if (NT_SUCCESS(Status))
-    {
-        PMINIRDR_DISPATCH Dispatch;
+            References = RxDereferenceNetFcb(ThisFcb);
 
-        if (!Synchronous)
-        {
-            InterlockedIncrement((volatile long *)&RxContext->ReferenceCount);
-            /* If not synchronous, we're likely to return before the operation is finished */
-            if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
-            {
-                IoMarkIrpPending(RxContext->CurrentIrp);
-            }
+            ResourceAcquired = TRUE;
         }
+    }
 
-        Dispatch = RxContext->RxDeviceObject->Dispatch;
-        if (Dispatch != NULL)
-        {
-            /* We'll try to execute until the mini-rdr doesn't return pending */
-            do
-            {
-                RxContext->IoStatusBlock.Information = 0;
-
-                MINIRDR_CALL(Status, RxContext, Dispatch, MRxLowIOSubmit[Operation], (RxContext));
-                if (Status == STATUS_PENDING)
-                {
-                    /* Unless it's not synchronous, caller will be happy with pending op */
-                    if (!Synchronous)
-                    {
-                        return Status;
-                    }
+    /* If locking was OK (or not needed!), attempt finalization */
+    if (Status == STATUS_SUCCESS)
+    {
+        Freed = RxFinalizeNetFcb(ThisFcb, RecursiveFinalize, ForceFinalize, References);
+    }
 
-                    RxWaitSync(RxContext);
-                    Status = RxContext->IoStatusBlock.Status;
-                }
-                else
-                {
-                    if (!Synchronous)
-                    {
-                        /* We had marked the IRP pending, whereas the operation finished, drop that */
-                        if (Status != STATUS_RETRY)
-                        {
-                            if (!BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_IN_FSP))
-                            {
-                                RxContext->CurrentIrpSp->Flags &= ~SL_PENDING_RETURNED;
-                            }
+    /* Release table lock if acquired */
+    if (ResourceAcquired)
+    {
+        RxReleaseFcbTableLock(&NetRoot->FcbTable);
+    }
 
-                            InterlockedDecrement((volatile long *)&RxContext->ReferenceCount);
-                        }
-                    }
-                }
-            } while (Status == STATUS_PENDING);
-        }
-        else
-        {
-            Status = STATUS_INVALID_PARAMETER;
-        }
+    /* We don't need the NetRoot anylonger */
+    if (NetRootReferenced)
+    {
+        RxDereferenceNetRoot(NetRoot, LHS_LockNotHeld);
     }
 
-    /* Call completion and return */
-    RxContext->IoStatusBlock.Status = Status;
-    LowIoContext->Flags |= LOWIO_CONTEXT_FLAG_SYNCCALL;
-    return RxLowIoCompletionTail(RxContext);
+    return Freed;
 }
 
 /*
  * @implemented
  */
-PVOID
-RxMapSystemBuffer(
-    IN PRX_CONTEXT RxContext)
+LONG
+RxpDereferenceNetFcb(
+   PFCB Fcb)
 {
-    PIRP Irp;
+    LONG NewCount;
 
     PAGED_CODE();
 
-    Irp = RxContext->CurrentIrp;
-    /* We should have a MDL (buffered IOs are not supported!) */
-    if (Irp->MdlAddress != NULL)
-    {
-        ASSERT(FALSE);
-        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
-    }
+    ASSERT(NodeTypeIsFcb(Fcb));
 
-    /* Just return system buffer */
-    return Irp->AssociatedIrp.SystemBuffer;
-}
+    NewCount = InterlockedDecrement((volatile long *)&Fcb->NodeReferenceCount);
+    ASSERT(NewCount >= 0);
 
-VOID
-RxMarkFobxOnCleanup(
-    PFOBX pFobx,
-    PBOOLEAN NeedPurge)
-{
-    UNIMPLEMENTED;
+    PRINT_REF_COUNT(NETFCB, NewCount);
+
+    return NewCount;
 }
 
+/*
+ * @implemented
+ */
 VOID
-RxMarkFobxOnClose(
-    PFOBX Fobx)
+NTAPI
+RxpDestroySrvCall(
+    IN PVOID Context)
 {
-    UNIMPLEMENTED;
+    NTSTATUS Status;
+    PSRV_CALL SrvCall;
+    BOOLEAN ForceFinalize;
+    PRX_PREFIX_TABLE PrefixTable;
+
+    SrvCall = (PSRV_CALL)Context;
+    /* At this step, RxFinalizeSrvCall already cleaned some fields */
+    ASSERT(SrvCall->UpperFinalizationDone);
+
+    PrefixTable = SrvCall->RxDeviceObject->pRxNetNameTable;
+    /* Were we called with ForceFinalize? */
+    ForceFinalize = BooleanFlagOn(SrvCall->Flags, SRVCALL_FLAG_FORCE_FINALIZED);
+
+    /* Notify mini-rdr */
+    MINIRDR_CALL_THROUGH(Status, SrvCall->RxDeviceObject->Dispatch,
+                         MRxFinalizeSrvCall, ((PMRX_SRV_CALL)SrvCall,
+                         ForceFinalize));
+    (void)Status;
+
+    /* Dereference our extra reference (set before queueing) */
+    RxAcquirePrefixTableLockExclusive(PrefixTable, TRUE);
+    InterlockedDecrement((volatile long *)&SrvCall->NodeReferenceCount);
+    /* And finalize for real, with the right context */
+    RxFinalizeSrvCall(SrvCall, FALSE, ForceFinalize);
+    RxReleasePrefixTableLock(PrefixTable);
 }
 
 /*
  * @implemented
  */
-PVOID
-RxNewMapUserBuffer(
-    PRX_CONTEXT RxContext)
+VOID
+RxpDiscardChangeBufferingStateRequests(
+    _Inout_ PLIST_ENTRY DiscardedRequests)
 {
-    PIRP Irp;
+    PLIST_ENTRY Entry;
 
     PAGED_CODE();
 
-    Irp = RxContext->CurrentIrp;
-    if (Irp->MdlAddress != NULL)
+    /* No requests to discard */
+    if (IsListEmpty(DiscardedRequests))
     {
-        return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+        return;
     }
 
-    return Irp->UserBuffer;
+    /* Free all the discarded requests */
+    Entry = DiscardedRequests->Flink;
+    while (Entry != DiscardedRequests)
+    {
+        PCHANGE_BUFFERING_STATE_REQUEST Request;
+
+        Request = CONTAINING_RECORD(Entry, CHANGE_BUFFERING_STATE_REQUEST, ListEntry);
+        Entry = Entry->Flink;
+
+        DPRINT("Req %p for %p (%p) discarded\n", Request, Request->SrvOpenKey, Request->SrvOpen);
+
+        RxPrepareRequestForReuse(Request);
+        RxFreePool(Request);
+    }
 }
 
-BOOLEAN
-NTAPI
-RxNoOpAcquire(
-    IN PVOID Fcb,
-    IN BOOLEAN Wait)
+/*
+ * @implemented
+ */
+VOID
+RxpDispatchChangeBufferingStateRequests(
+    PSRV_CALL SrvCall,
+    PSRV_OPEN SrvOpen,
+    PLIST_ENTRY DiscardedRequests)
 {
-    UNIMPLEMENTED;
-    return FALSE;
-}
+    KIRQL OldIrql;
+    NTSTATUS Status;
+    BOOLEAN StartDispatcher;
+    LIST_ENTRY AcceptedReqs;
+    LIST_ENTRY DispatcherList;
+    PRX_BUFFERING_MANAGER BufferingManager;
+
+    /* Initialize our lists */
+    InitializeListHead(&AcceptedReqs);
+    InitializeListHead(DiscardedRequests);
+
+    /* Transfer the requests to dispatch locally */
+    BufferingManager = &SrvCall->BufferingManager;
+    KeAcquireSpinLock(&BufferingManager->SpinLock, &OldIrql);
+    RxTransferList(&DispatcherList, &BufferingManager->DispatcherList);
+    KeReleaseSpinLock(&BufferingManager->SpinLock, OldIrql);
+
+    /* If there were requests */
+    if (!IsListEmpty(&DispatcherList))
+    {
+        PLIST_ENTRY Entry;
+
+        /* For each of the entries... */
+        Entry = DispatcherList.Flink;
+        while (Entry != &DispatcherList)
+        {
+            PCHANGE_BUFFERING_STATE_REQUEST Request;
+
+            Request = CONTAINING_RECORD(Entry, CHANGE_BUFFERING_STATE_REQUEST, ListEntry);
+            Entry = Entry->Flink;
+
+            /* If we have been provided a SRV_OPEN, see whether it matches */
+            if (SrvOpen != NULL)
+            {
+                /* Match, the request is accepted */
+                if (Request->SrvOpenKey == SrvOpen->Key)
+                {
+                    Request->SrvOpen = SrvOpen;
+                    RxReferenceSrvOpen(SrvOpen);
+
+                    RemoveEntryList(&Request->ListEntry);
+                    InsertTailList(&AcceptedReqs, &Request->ListEntry);
+
+                    /* Move to the next entry */
+                    continue;
+                }
+                else
+                {
+                    Status = STATUS_PENDING;
+                }
+            }
+            else
+            {
+                /* No SRV_OPEN provided, try to find one */
+                Status = RxpLookupSrvOpenForRequestLite(SrvCall, Request);
+            }
+
+            /* We found a matching SRV_OPEN, accept the request */
+            if (Status == STATUS_SUCCESS)
+            {
+                RemoveEntryList(&Request->ListEntry);
+                InsertTailList(&AcceptedReqs, &Request->ListEntry);
+            }
+            /* Another run might help handling it, don't discard it */
+            else if (Status == STATUS_PENDING)
+            {
+                continue;
+            }
+            /* Otherwise, discard the request */
+            else
+            {
+                ASSERT(Status == STATUS_NOT_FOUND);
+
+                RemoveEntryList(&Request->ListEntry);
+                InsertTailList(DiscardedRequests, &Request->ListEntry);
+            }
+        }
+    }
 
-VOID
-NTAPI
-RxNoOpRelease(
-    IN PVOID Fcb)
-{
-    UNIMPLEMENTED;
-}
+    KeAcquireSpinLock(&BufferingManager->SpinLock, &OldIrql);
+    /* Nothing to dispatch, no need to start dispatcher */
+    if (IsListEmpty(&DispatcherList))
+    {
+        StartDispatcher = FALSE;
+    }
+    else
+    {
+        /* Transfer back the list of the not treated entries to the buffering manager */
+        RxTransferList(&BufferingManager->DispatcherList, &DispatcherList);
+        StartDispatcher = (BufferingManager->DispatcherActive == FALSE);
+        /* If the dispatcher isn't active, start it */
+        if (StartDispatcher)
+        {
+            BufferingManager->DispatcherActive = TRUE;
+        }
+    }
 
-VOID
-RxOrphanThisFcb(
-    PFCB Fcb)
-{
-    UNIMPLEMENTED;
+    /* If there were accepted requests, move them to the buffering manager */
+    if (!IsListEmpty(&AcceptedReqs))
+    {
+        RxTransferList(&BufferingManager->HandlerList, &AcceptedReqs);
+    }
+    KeReleaseSpinLock(&BufferingManager->SpinLock, OldIrql);
+
+    /* If we're to start the dispatcher, do it */
+    if (StartDispatcher)
+    {
+        RxReferenceSrvCall(SrvCall);
+        DPRINT("Starting dispatcher\n");
+        RxPostToWorkerThread(RxFileSystemDeviceObject, HyperCriticalWorkQueue,
+                             &BufferingManager->DispatcherWorkItem,
+                             RxDispatchChangeBufferingStateRequests, SrvCall);
+    }
 }
 
 /*
  * @implemented
  */
-BOOLEAN
-RxpAcquirePrefixTableLockShared(
-   PRX_PREFIX_TABLE pTable,
-   BOOLEAN Wait,
-   BOOLEAN ProcessBufferingStateChangeRequests)
+NTSTATUS
+RxpLookupSrvOpenForRequestLite(
+    IN PSRV_CALL SrvCall,
+    IN OUT PCHANGE_BUFFERING_STATE_REQUEST Request)
 {
+    NTSTATUS Status;
+    PLIST_ENTRY Entry;
+    PSRV_OPEN SrvOpen;
+
     PAGED_CODE();
 
-    DPRINT("RxpAcquirePrefixTableLockShared(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
-           pTable->TableLock.ActiveEntries);
+    Status = STATUS_SUCCESS;
+    /* Browse all our associated SRV_OPENs to find the one! */
+    for (Entry = SrvCall->BufferingManager.SrvOpenLists[0].Flink;
+         Entry != &SrvCall->BufferingManager.SrvOpenLists[0];
+         Entry = Entry->Flink)
+    {
+        /* Same key, not orphaned, this is ours */
+        SrvOpen = CONTAINING_RECORD(Entry, SRV_OPEN, SrvOpenKeyList);
+        if (SrvOpen->Key == Request->SrvOpenKey)
+        {
+            if (!BooleanFlagOn(SrvOpen->pFcb->FcbState, FCB_STATE_ORPHANED))
+            {
+                RxReferenceSrvOpen(SrvOpen);
+                break;
+            }
+        }
+    }
 
-    return ExAcquireResourceSharedLite(&pTable->TableLock, Wait);
-}
+    /* We didn't manage to find a SRV_OPEN */
+    if (Entry == &SrvCall->BufferingManager.SrvOpenLists[0])
+    {
+        SrvOpen = NULL;
 
-/*
- * @implemented
- */
-BOOLEAN
-RxpAcquirePrefixTableLockExclusive(
-   PRX_PREFIX_TABLE pTable,
-   BOOLEAN Wait,
-   BOOLEAN ProcessBufferingStateChangeRequests)
-{
-    PAGED_CODE();
+        /* The coming open might help, mark as pending for later retry */
+        if (SrvCall->BufferingManager.NumberOfOutstandingOpens != 0)
+        {
+            Status = STATUS_PENDING;
+        }
+        /* Else, it's a complete failure */
+        else
+        {
+            Status = STATUS_NOT_FOUND;
+        }
+    }
 
-    DPRINT("RxpAcquirePrefixTableLockExclusive(%p, %d, %d) -> %d\n", pTable, Wait, ProcessBufferingStateChangeRequests,
-           pTable->TableLock.ActiveEntries);
+    /* Return the (not) found SRV_OPEN */
+    Request->SrvOpen = SrvOpen;
 
-    return ExAcquireResourceExclusiveLite(&pTable->TableLock, Wait);
+    return Status;
 }
 
 /*
  * @implemented
  */
-BOOLEAN
-RxpDereferenceAndFinalizeNetFcb(
-    OUT PFCB ThisFcb,
-    IN PRX_CONTEXT RxContext,
-    IN BOOLEAN RecursiveFinalize,
-    IN BOOLEAN ForceFinalize)
+VOID
+RxpMarkInstanceForScavengedFinalization(
+   PVOID Instance)
 {
-    NTSTATUS Status;
-    ULONG References;
-    PNET_ROOT NetRoot;
-    BOOLEAN ResourceAcquired, NetRootReferenced, Freed;
+    NODE_TYPE_CODE NodeType;
+    PNODE_TYPE_AND_SIZE Node;
+    PRDBSS_SCAVENGER Scavenger;
+    PRDBSS_DEVICE_OBJECT DeviceObject;
+    PLIST_ENTRY ScavengerHead, InstEntry;
 
     PAGED_CODE();
 
-    ASSERT(!ForceFinalize);
-    ASSERT(NodeTypeIsFcb(ThisFcb));
-    ASSERT(RxIsFcbAcquiredExclusive(ThisFcb));
-
-    /* Unless we're recursively finalizing, or forcing, if FCB is still in use, quit */
-    References = InterlockedDecrement((volatile long *)&ThisFcb->NodeReferenceCount);
-    if (!ForceFinalize && !RecursiveFinalize && (ThisFcb->OpenCount != 0 || ThisFcb->UncleanCount != 0 || References > 1))
+    /* If still referenced, don't mark it (broken caller) */
+    Node = (PNODE_TYPE_AND_SIZE)Instance;
+    if (Node->NodeReferenceCount > 1)
     {
-        return FALSE;
+        return;
     }
 
-    Freed = FALSE;
-    Status = STATUS_SUCCESS;
-    NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->pNetRoot;
-    ResourceAcquired = FALSE;
-    NetRootReferenced = FALSE;
-    /* If FCB isn't orphaned, it still have context attached */
-    if (!BooleanFlagOn(ThisFcb->FcbState, FCB_STATE_ORPHANED))
+    DeviceObject = RxGetDeviceObjectOfInstance(Instance);
+    Scavenger = DeviceObject->pRdbssScavenger;
+
+    /* Mark the node */
+    NodeType = NodeType(Instance);
+    SetFlag(NodeType(Node), RX_SCAVENGER_MASK);
+    DPRINT("Node %p has now the scavenger mark!\n", Instance);
+
+    /* Increase the count in the scavenger, and queue it */
+    ScavengerHead = NULL;
+    switch (NodeType)
     {
-        /* Don't let NetRoot go away before we're done */
-        RxReferenceNetRoot(NetRoot);
-        NetRootReferenced = TRUE;
+        case RDBSS_NTC_FOBX:
+            ++Scavenger->FobxsToBeFinalized;
+            ScavengerHead = &Scavenger->FobxFinalizationList;
+            InstEntry = &((PFOBX)Instance)->ScavengerFinalizationList;
+            break;
 
-        /* Try to acquire the table lock exclusively */
-        if (!RxIsFcbTableLockExclusive(&NetRoot->FcbTable))
-        {
-            RxReferenceNetFcb(ThisFcb);
+        case RDBSS_NTC_SRVCALL:
+            ++Scavenger->SrvCallsToBeFinalized;
+            ScavengerHead = &Scavenger->SrvCallFinalizationList;
+            InstEntry = &((PSRV_CALL)Instance)->ScavengerFinalizationList;
+            break;
 
-            if (!RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
-            {
-                if (RxContext != NULL && RxContext != (PVOID)-1 && RxContext != (PVOID)-2)
-                {
-                    RxContext->Flags |= RX_CONTEXT_FLAG_BYPASS_VALIDOP_CHECK;
-                }
+        case RDBSS_NTC_NETROOT:
+            ++Scavenger->NetRootsToBeFinalized;
+            ScavengerHead = &Scavenger->NetRootFinalizationList;
+            InstEntry = &((PNET_ROOT)Instance)->ScavengerFinalizationList;
+            break;
 
-                RxReleaseFcb(RxContext, ThisFcb);
+        case RDBSS_NTC_V_NETROOT:
+            ++Scavenger->VNetRootsToBeFinalized;
+            ScavengerHead = &Scavenger->VNetRootFinalizationList;
+            InstEntry = &((PV_NET_ROOT)Instance)->ScavengerFinalizationList;
+            break;
 
-                RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
+        case RDBSS_NTC_SRVOPEN:
+            ++Scavenger->SrvOpensToBeFinalized;
+            ScavengerHead = &Scavenger->SrvOpenFinalizationList;
+            InstEntry = &((PSRV_OPEN)Instance)->ScavengerFinalizationList;
+            break;
+    }
 
-                Status = RxAcquireExclusiveFcb(RxContext, ThisFcb);
-            }
+    /* Extra ref for scavenger */
+    InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
 
-            References = RxDereferenceNetFcb(ThisFcb);
+    /* If matching type */
+    if (ScavengerHead != NULL)
+    {
+        /* Insert in the scavenger list */
+        InsertTailList(ScavengerHead, InstEntry);
 
-            ResourceAcquired = TRUE;
+        /* And if it wasn't started, start it */
+        if (Scavenger->State == RDBSS_SCAVENGER_INACTIVE)
+        {
+            Scavenger->State = RDBSS_SCAVENGER_DORMANT;
+            RxPostOneShotTimerRequest(RxFileSystemDeviceObject, &Scavenger->WorkItem,
+                                      RxScavengerTimerRoutine, DeviceObject, Scavenger->TimeLimit);
         }
     }
+}
 
-    /* If locking was OK (or not needed!), attempt finalization */
-    if (NT_SUCCESS(Status))
-    {
-        Freed = RxFinalizeNetFcb(ThisFcb, RecursiveFinalize, ForceFinalize, References);
-    }
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+RxPostOneShotTimerRequest(
+    IN PRDBSS_DEVICE_OBJECT pDeviceObject,
+    IN PRX_WORK_ITEM pWorkItem,
+    IN PRX_WORKERTHREAD_ROUTINE Routine,
+    IN PVOID pContext,
+    IN LARGE_INTEGER TimeInterval)
+{
+    KIRQL OldIrql;
 
-    /* Release table lock if acquired */
-    if (ResourceAcquired)
-    {
-        RxReleaseFcbTableLock(&NetRoot->FcbTable);
-    }
+    ASSERT(pWorkItem != NULL);
 
-    /* We don't need the NetRoot anylonger */
-    if (NetRootReferenced)
+    /* Prepare the work item */
+    ExInitializeWorkItem(&pWorkItem->WorkQueueItem, Routine, pContext);
+    pWorkItem->WorkQueueItem.pDeviceObject = pDeviceObject;
+
+    /* Last tick can be computed with the number of times it was caller (timertickcount)
+     * and the interval between calls
+     */
+    KeAcquireSpinLock(&RxTimerLock, &OldIrql);
+    pWorkItem->LastTick = (TimeInterval.QuadPart / 550000) + RxTimerTickCount + 1;
+    /* Insert in work queue */
+    InsertTailList(&RxTimerQueueHead, &pWorkItem->WorkQueueItem.List);
+    KeReleaseSpinLock(&RxTimerLock, OldIrql);
+
+    /* If there are queued events, queue an execution */
+    if (IsListEmpty(&RxTimerQueueHead))
     {
-        RxDereferenceNetRoot(NetRoot, LHS_LockNotHeld);
+        KeSetTimer(&RxTimer, RxTimerInterval, &RxTimerDpc);
     }
 
-    return Freed;
+    return STATUS_SUCCESS;
 }
 
-LONG
-RxpDereferenceNetFcb(
-   PFCB Fcb)
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+RxPostToWorkerThread(
+    _In_ PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
+    _In_ WORK_QUEUE_TYPE WorkQueueType,
+    _In_ PRX_WORK_QUEUE_ITEM pWorkQueueItem,
+    _In_ PRX_WORKERTHREAD_ROUTINE Routine,
+    _In_ PVOID pContext)
+{
+    /* Initialize work queue item */
+    pWorkQueueItem->List.Flink = NULL;
+    pWorkQueueItem->WorkerRoutine = Routine;
+    pWorkQueueItem->Parameter = pContext;
+
+    /* And insert it in the work queue */
+    return RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, pWorkQueueItem);
+}
+
+VOID
+RxpProcessChangeBufferingStateRequests(
+    PSRV_CALL SrvCall,
+    BOOLEAN UpdateHandlerState)
 {
     UNIMPLEMENTED;
-    return 0;
 }
 
 /*
@@ -4488,56 +6086,147 @@ RxPrefixTableLookupName(
         RxReference(Container);
     }
 
-    return Container;
-}
-
-LONG
-RxpReferenceNetFcb(
-   PFCB Fcb)
-{
-    UNIMPLEMENTED;
-    return 0;
+    return Container;
+}
+
+/*
+ * @implemented
+ */
+LONG
+RxpReferenceNetFcb(
+   PFCB Fcb)
+{
+    LONG NewCount;
+
+    PAGED_CODE();
+
+    ASSERT(NodeTypeIsFcb(Fcb));
+
+    NewCount = InterlockedIncrement((volatile long *)&Fcb->NodeReferenceCount);
+
+    PRINT_REF_COUNT(NETFCB, Fcb->NodeReferenceCount);
+
+    return NewCount;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxpReleasePrefixTableLock(
+   PRX_PREFIX_TABLE pTable,
+   BOOLEAN ProcessBufferingStateChangeRequests)
+{
+    PAGED_CODE();
+
+    DPRINT("RxpReleasePrefixTableLock(%p, %d) -> %d\n", pTable, ProcessBufferingStateChangeRequests,
+           pTable->TableLock.ActiveEntries);
+
+    ExReleaseResourceLite(&pTable->TableLock);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxPrepareContextForReuse(
+   IN OUT PRX_CONTEXT RxContext)
+{
+    PAGED_CODE();
+
+    /* When we reach that point, make sure mandatory parts are null-ed */
+    if (RxContext->MajorFunction == IRP_MJ_CREATE)
+    {
+        ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
+        RxContext->Create.RdrFlags = 0;
+    }
+    else if (RxContext->MajorFunction == IRP_MJ_READ || RxContext->MajorFunction == IRP_MJ_WRITE)
+    {
+        ASSERT(RxContext->RxContextSerializationQLinks.Flink == NULL);
+        ASSERT(RxContext->RxContextSerializationQLinks.Blink == NULL);
+    }
+
+    RxContext->ReferenceCount = 0;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxPrepareRequestForReuse(
+    PCHANGE_BUFFERING_STATE_REQUEST Request)
+{
+    PSRV_OPEN SrvOpen;
+
+    PAGED_CODE();
+
+    SrvOpen = Request->SrvOpen;
+
+    /* If the request was already prepared for service */
+    if (BooleanFlagOn(Request->Flags, RX_REQUEST_PREPARED_FOR_HANDLING))
+    {
+        /* We have to dereference the associated SRV_OPEN depending on the lock */
+        if (RxIsFcbAcquiredExclusive(SrvOpen->pFcb))
+        {
+            RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
+        }
+        else
+        {
+            RxDereferenceSrvOpen(SrvOpen, LHS_LockNotHeld);
+        }
+    }
+    /* Otherwise, just dereference */
+    else if (SrvOpen != NULL)
+    {
+        RxDereferenceSrvOpen(SrvOpen, LHS_LockNotHeld);
+    }
+
+    Request->SrvOpen = NULL;
 }
 
 /*
  * @implemented
  */
 VOID
-RxpReleasePrefixTableLock(
-   PRX_PREFIX_TABLE pTable,
-   BOOLEAN ProcessBufferingStateChangeRequests)
+NTAPI
+RxProcessChangeBufferingStateRequests(
+    _In_ PVOID SrvCall)
 {
-    PAGED_CODE();
-
-    DPRINT("RxpReleasePrefixTableLock(%p, %d) -> %d\n", pTable, ProcessBufferingStateChangeRequests,
-           pTable->TableLock.ActiveEntries);
-
-    ExReleaseResourceLite(&pTable->TableLock);
+    /* Call internal routine */
+    RxUndoScavengerFinalizationMarking(SrvCall);
+    RxpProcessChangeBufferingStateRequests(SrvCall, TRUE);
 }
 
 /*
  * @implemented
  */
 VOID
-NTAPI
-RxPrepareContextForReuse(
-   IN OUT PRX_CONTEXT RxContext)
+RxProcessChangeBufferingStateRequestsForSrvOpen(
+    PSRV_OPEN SrvOpen)
 {
-    PAGED_CODE();
+    LONG NumberOfBufferingChangeRequests, OldBufferingToken;
 
-    /* When we reach that point, make sure mandatory parts are null-ed */
-    if (RxContext->MajorFunction == IRP_MJ_CREATE)
+    /* Get the current number of change requests */
+    NumberOfBufferingChangeRequests = ((PSRV_CALL)SrvOpen->pVNetRoot->pNetRoot->pSrvCall)->BufferingManager.CumulativeNumberOfBufferingChangeRequests;
+    /* Get our old token */
+    OldBufferingToken = InterlockedCompareExchange(&SrvOpen->BufferingToken,
+                                                   NumberOfBufferingChangeRequests, NumberOfBufferingChangeRequests);
+    /* Do we have stuff to process? */
+    if (OldBufferingToken != SrvOpen->BufferingToken)
     {
-        ASSERT(RxContext->Create.CanonicalNameBuffer == NULL);
-        RxContext->Create.RdrFlags = 0;
-    }
-    else if (RxContext->MajorFunction == IRP_MJ_READ || RxContext->MajorFunction == IRP_MJ_WRITE)
-    {
-        ASSERT(RxContext->RxContextSerializationQLinks.Flink == NULL);
-        ASSERT(RxContext->RxContextSerializationQLinks.Blink == NULL);
-    }
+        PFCB Fcb;
+        NTSTATUS Status;
 
-    RxContext->ReferenceCount = 0;
+        /* Acquire the FCB and start processing */
+        Fcb = (PFCB)SrvOpen->pFcb;
+        Status = RxAcquireExclusiveFcb(NULL, Fcb);
+        if (Status == STATUS_SUCCESS)
+        {
+            RxProcessFcbChangeBufferingStateRequest(Fcb);
+            RxReleaseFcb(NULL, Fcb);
+        }
+    }
 }
 
 VOID
@@ -4554,8 +6243,15 @@ RxpTrackDereference(
     _In_ ULONG Line,
     _In_ PVOID Instance)
 {
+    PAGED_CODE();
+
+    if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+    {
+        return TRUE;
+    }
+
     UNIMPLEMENTED;
-    return FALSE;
+    return TRUE;
 }
 
 VOID
@@ -4565,27 +6261,150 @@ RxpTrackReference(
     _In_ ULONG Line,
     _In_ PVOID Instance)
 {
+    if (!BooleanFlagOn(RdbssReferenceTracingValue, TraceType))
+    {
+        return;
+    }
+
     UNIMPLEMENTED;
 }
 
+/*
+ * @implemented
+ */
 VOID
 RxpUndoScavengerFinalizationMarking(
    PVOID Instance)
 {
+    PLIST_ENTRY ListEntry;
     PNODE_TYPE_AND_SIZE Node;
+    PRDBSS_SCAVENGER Scavenger;
 
     PAGED_CODE();
 
     Node = (PNODE_TYPE_AND_SIZE)Instance;
     /* There's no marking - nothing to do */
-    if (!BooleanFlagOn(Node->NodeTypeCode, RX_SCAVENGER_MASK))
+    if (!BooleanFlagOn(NodeType(Node), RX_SCAVENGER_MASK))
     {
         return;
     }
 
-    UNIMPLEMENTED;
+    /* First of all, remove the mark */
+    ClearFlag(NodeType(Node), RX_SCAVENGER_MASK);
+    DPRINT("Node %p no longer has the scavenger mark\n");
+
+    /* And now, remove from the scavenger */
+    Scavenger = RxGetDeviceObjectOfInstance(Instance)->pRdbssScavenger;
+    switch (NodeType(Node))
+    {
+        case RDBSS_NTC_FOBX:
+            --Scavenger->FobxsToBeFinalized;
+            ListEntry = &((PFOBX)Instance)->ScavengerFinalizationList;
+            break;
+
+        case RDBSS_NTC_SRVCALL:
+            --Scavenger->SrvCallsToBeFinalized;
+            ListEntry = &((PSRV_CALL)Instance)->ScavengerFinalizationList;
+            break;
+
+        case RDBSS_NTC_NETROOT:
+            --Scavenger->NetRootsToBeFinalized;
+            ListEntry = &((PNET_ROOT)Instance)->ScavengerFinalizationList;
+            break;
+
+        case RDBSS_NTC_V_NETROOT:
+            --Scavenger->VNetRootsToBeFinalized;
+            ListEntry = &((PV_NET_ROOT)Instance)->ScavengerFinalizationList;
+            break;
+
+        case RDBSS_NTC_SRVOPEN:
+            --Scavenger->SrvOpensToBeFinalized;
+            ListEntry = &((PSRV_OPEN)Instance)->ScavengerFinalizationList;
+            break;
+    }
+
+    /* Also, remove the extra ref from the scavenger */
+    RemoveEntryList(ListEntry);
+    InterlockedDecrement((volatile long *)&Node->NodeReferenceCount);
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxPurgeChangeBufferingStateRequestsForSrvOpen(
+    PSRV_OPEN SrvOpen)
+{
+    PSRV_CALL SrvCall;
+    LIST_ENTRY Discarded;
+
+    PAGED_CODE();
+
+    ASSERT(RxIsFcbAcquiredExclusive(SrvOpen->Fcb));
+
+    /* Initialize our discarded list */
+    InitializeListHead(&Discarded);
+
+    SrvCall = (PSRV_CALL)SrvOpen->Fcb->VNetRoot->pNetRoot->pSrvCall;
+    RxAcquireBufferingManagerMutex(&SrvCall->BufferingManager);
+
+    /* Set the flag, and get the requests */
+    InitializeListHead(&SrvOpen->SrvOpenKeyList);
+    SetFlag(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_REQUESTS_PURGED);
+    RxGatherRequestsForSrvOpen(SrvCall, SrvOpen, &Discarded);
+
+    RxReleaseBufferingManagerMutex(&SrvCall->BufferingManager);
+
+    /* If there were discarded requests */
+    if (!IsListEmpty(&Discarded))
+    {
+        /* And a pending buffering state change */
+        if (BooleanFlagOn(SrvOpen->Flags, SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING))
+        {
+            /* Clear the flag, and set the associated event - job done */
+            RxAcquireSerializationMutex();
+            ClearFlag(SrvOpen->Fcb->FcbState, FCB_STATE_BUFFERING_STATE_CHANGE_PENDING);
+            if (SrvOpen->Fcb->pBufferingStateChangeCompletedEvent != NULL)
+            {
+                KeSetEvent(SrvOpen->Fcb->pBufferingStateChangeCompletedEvent, IO_NETWORK_INCREMENT, FALSE);
+            }
+            RxReleaseSerializationMutex();
+        }
+
+        /* Drop the discarded requests */
+        RxpDiscardChangeBufferingStateRequests(&Discarded);
+    }
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxPurgeFcb(
+    IN  PFCB Fcb)
+{
+    PAGED_CODE();
+
+    ASSERT(RxIsFcbAcquiredExclusive(Fcb));
+
+    /* Reference our FCB so that it doesn't disappear */
+    RxReferenceNetFcb(Fcb);
+    /* Purge Cc if required */
+    if (Fcb->OpenCount != 0)
+    {
+        RxPurgeFcbInSystemCache(Fcb, NULL, 0, TRUE, TRUE);
+    }
+
+    /* If it wasn't freed, release the lock */
+    if (!RxDereferenceAndFinalizeNetFcb(Fcb, NULL, FALSE, FALSE))
+    {
+        RxReleaseFcb(NULL, Fcb);
+    }
 }
 
+/*
+ * @implemented
+ */
 NTSTATUS
 RxPurgeFcbInSystemCache(
     IN PFCB Fcb,
@@ -4594,8 +6413,92 @@ RxPurgeFcbInSystemCache(
     IN BOOLEAN UninitializeCacheMaps,
     IN BOOLEAN FlushFile)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    BOOLEAN Purged;
+    NTSTATUS Status;
+
+    PAGED_CODE();
+
+    ASSERT(RxIsFcbAcquiredExclusive(Fcb));
+
+    /* Try to flush first, if asked */
+    if (FlushFile)
+    {
+        /* If flushing failed, just make some noise */
+        Status = RxFlushFcbInSystemCache(Fcb, TRUE);
+        if (!NT_SUCCESS(Status))
+        {
+            PVOID CallersAddress, CallersCaller;
+
+            RtlGetCallersAddress(&CallersAddress, &CallersCaller);
+            DPRINT1("Flush failed with status %lx for FCB %p\n", Status, Fcb);
+            DPRINT1("Caller was %p %p\n", CallersAddress, CallersCaller);
+        }
+    }
+
+    /* Deal with Cc for purge */
+    Purged = CcPurgeCacheSection(&Fcb->NonPaged->SectionObjectPointers, FileOffset,
+                                 Length, UninitializeCacheMaps);
+    /* If purge failed, force section closing */
+    if (!Purged)
+    {
+        MmFlushImageSection(&Fcb->NonPaged->SectionObjectPointers, MmFlushForWrite);
+
+        RxReleaseFcb(NULL, Fcb);
+        Purged = MmForceSectionClosed(&Fcb->NonPaged->SectionObjectPointers, TRUE);
+        RxAcquireExclusiveFcb(NULL, Fcb);
+    }
+
+    /* Return appropriate status */
+    Status = (Purged ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
+    DPRINT("Purge for FCB %p returns %lx\n", Fcb, Status);
+
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+RxPurgeFobxFromCache(
+    PFOBX FobxToBePurged)
+{
+    NTSTATUS Status;
+    PFCB FcbToBePurged;
+
+    PAGED_CODE();
+
+    FcbToBePurged = (PFCB)FobxToBePurged->pSrvOpen->pFcb;
+    ASSERT(FcbToBePurged != NULL);
+
+    /* If we cannot have our FCB exclusively, give up */
+    Status = RxAcquireExclusiveFcb(NULL, FcbToBePurged);
+    if (Status != STATUS_SUCCESS)
+    {
+        RxDereferenceNetFobx(FobxToBePurged, LHS_LockNotHeld);
+        return Status;
+    }
+
+    /* Don't let the FCB disappear */
+    RxReferenceNetFcb(FcbToBePurged);
+
+    /* If the SRV_OPEN was already closed, or if there are unclean FOBX, give up */
+    if (BooleanFlagOn(FobxToBePurged->Flags, FOBX_FLAG_SRVOPEN_CLOSED) || FobxToBePurged->pSrvOpen->UncleanFobxCount != 0)
+    {
+        DPRINT("FCB purge skipped\n");
+    }
+    else
+    {
+        Status = RxPurgeFcbInSystemCache(FcbToBePurged, NULL, 0, FALSE, TRUE);
+    }
+
+    RxDereferenceNetFobx(FobxToBePurged, LHS_ExclusiveLockHeld);
+    /* Drop our extra reference */
+    if (!RxDereferenceAndFinalizeNetFcb(FcbToBePurged, NULL, FALSE, FALSE))
+    {
+        RxReleaseFcb(NULL, FcbToBePurged);
+    }
+
+    return Status;
 }
 
 /*
@@ -4617,7 +6520,7 @@ RxpWorkerThreadDispatcher(
 
     /* Reference ourselves */
     CurrentThread = PsGetCurrentThread();
-    Status = ObReferenceObjectByPointer(CurrentThread, THREAD_ALL_ACCESS, PsThreadType, KernelMode);
+    Status = ObReferenceObjectByPointer(CurrentThread, THREAD_ALL_ACCESS, *PsThreadType, KernelMode);
     ASSERT(NT_SUCCESS(Status));
 
     /* Infinite loop for worker */
@@ -4659,7 +6562,7 @@ RxpWorkerThreadDispatcher(
             {
                 PKEVENT TearDownEvent;
 
-                TearDownEvent = InterlockedExchangePointer((volatile PVOID)&DeviceObject->DispatcherContext.pTearDownEvent, NULL);
+                TearDownEvent = InterlockedExchangePointer((void * volatile*)&DeviceObject->DispatcherContext.pTearDownEvent, NULL);
                 if (TearDownEvent != NULL)
                 {
                     KeSetEvent(TearDownEvent, IO_NO_INCREMENT, FALSE);
@@ -4739,73 +6642,203 @@ RxpWorkerThreadDispatcher(
         KeReleaseSpinLock(&WorkQueue->SpinLock, OldIrql);
     } while (!KillThread);
 
-    DPRINT("Killed worker thread\n");
+    DPRINT("Killed worker thread\n");
+
+    /* Do we have to dereference ourselves? */
+    if (Dereference)
+    {
+        ObDereferenceObject(CurrentThread);
+    }
+
+    /* Dump last executed routine */
+    if (DumpDispatchRoutine)
+    {
+        DPRINT("Dispatch routine %p(%p) taken from %p\n", WorkerRoutine, Parameter, WorkQueueItem);
+    }
+
+    PsTerminateSystemThread(STATUS_SUCCESS);
+}
+
+VOID
+RxReference(
+    IN OUT PVOID Instance)
+{
+    NODE_TYPE_CODE NodeType;
+    PNODE_TYPE_AND_SIZE Node;
+
+    PAGED_CODE();
+
+    RxAcquireScavengerMutex();
+
+    /* We can only reference a few structs */
+    NodeType = NodeType(Instance) & ~RX_SCAVENGER_MASK;
+    ASSERT((NodeType == RDBSS_NTC_SRVCALL) || (NodeType == RDBSS_NTC_NETROOT) ||
+           (NodeType == RDBSS_NTC_V_NETROOT) || (NodeType == RDBSS_NTC_SRVOPEN) ||
+           (NodeType == RDBSS_NTC_FOBX));
+
+    Node = (PNODE_TYPE_AND_SIZE)Instance;
+    InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
+
+    /* Trace refcount if asked */
+    switch (NodeType)
+    {
+        case RDBSS_NTC_SRVCALL:
+            PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
+            break;
+
+        case RDBSS_NTC_NETROOT:
+            PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
+            break;
+
+        case RDBSS_NTC_V_NETROOT:
+            PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
+            break;
+
+        case RDBSS_NTC_SRVOPEN:
+            PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
+            break;
+
+        case RDBSS_NTC_FOBX:
+            PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
+            break;
+
+        default:
+            ASSERT(FALSE);
+            break;
+    }
+
+    RxpUndoScavengerFinalizationMarking(Instance);
+    RxReleaseScavengerMutex();
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxRemoveNameNetFcb(
+    OUT PFCB ThisFcb)
+{
+    PNET_ROOT NetRoot;
+
+    PAGED_CODE();
+
+    ASSERT(NodeTypeIsFcb(ThisFcb));
+
+    /* Just remove the entry from the FCB_TABLE */
+    NetRoot = (PNET_ROOT)ThisFcb->VNetRoot->pNetRoot;
+    ASSERT(RxIsFcbTableLockExclusive(&NetRoot->FcbTable));
+    ASSERT(RxIsFcbAcquiredExclusive(ThisFcb));
+
+    RxFcbTableRemoveFcb(&NetRoot->FcbTable, ThisFcb);
+    DPRINT("FCB (%p) %wZ removed\n", ThisFcb, &ThisFcb->FcbTableEntry.Path);
+    /* Mark, so that we don't try to do it twice */
+    SetFlag(ThisFcb->FcbState, FCB_STATE_NAME_ALREADY_REMOVED);
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxRemovePrefixTableEntry(
+    IN OUT PRX_PREFIX_TABLE ThisTable,
+    IN OUT PRX_PREFIX_ENTRY Entry)
+{
+    PAGED_CODE();
+
+    ASSERT(NodeType(Entry) == RDBSS_NTC_PREFIX_ENTRY);
+    ASSERT(RxIsPrefixTableLockExclusive(ThisTable));
 
-    /* Do we have to dereference ourselves? */
-    if (Dereference)
+    /* Check whether we're asked to remove null entry */
+    if (Entry->Prefix.Length == 0)
     {
-        ObDereferenceObject(CurrentThread);
+        ThisTable->TableEntryForNull = NULL;
     }
-
-    /* Dump last executed routine */
-    if (DumpDispatchRoutine)
+    else
     {
-        DPRINT("Dispatch routine %p(%p) taken from %p\n", WorkerRoutine, Parameter, WorkQueueItem);
+        RemoveEntryList(&Entry->HashLinks);
     }
 
-    PsTerminateSystemThread(STATUS_SUCCESS);
+    Entry->ContainingRecord = NULL;
+
+    /* Also remove it from global list */
+    RemoveEntryList(&Entry->MemberQLinks);
+
+    ++ThisTable->Version;
 }
 
+/*
+ * @implemented
+ */
 VOID
-RxReference(
-    IN OUT PVOID Instance)
+RxRemoveVirtualNetRootFromNetRoot(
+    PNET_ROOT NetRoot,
+    PV_NET_ROOT VNetRoot)
 {
-    NODE_TYPE_CODE NodeType;
-    PNODE_TYPE_AND_SIZE Node;
+    PRX_PREFIX_TABLE PrefixTable;
 
     PAGED_CODE();
 
-    RxAcquireScavengerMutex();
+    PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+    ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
 
-    /* We can only reference a few structs */
-    NodeType = NodeType(Instance) & ~RX_SCAVENGER_MASK;
-    ASSERT((NodeType == RDBSS_NTC_SRVCALL) || (NodeType == RDBSS_NTC_NETROOT) ||
-           (NodeType == RDBSS_NTC_V_NETROOT) || (NodeType == RDBSS_NTC_SRVOPEN) ||
-           (NodeType == RDBSS_NTC_FOBX));
+    /* Remove the VNetRoot from the list in the NetRoot */
+    --NetRoot->NumberOfVirtualNetRoots;
+    RemoveEntryList(&VNetRoot->NetRootListEntry);
 
-    Node = (PNODE_TYPE_AND_SIZE)Instance;
-    InterlockedIncrement((volatile long *)&Node->NodeReferenceCount);
+    /* Fix the NetRoot if we were the default VNetRoot */
+    if (NetRoot->DefaultVNetRoot == VNetRoot)
+    {
+        /* Put the first one available */
+        if (!IsListEmpty(&NetRoot->VirtualNetRoots))
+        {
+            NetRoot->DefaultVNetRoot = CONTAINING_RECORD(NetRoot->VirtualNetRoots.Flink, V_NET_ROOT, NetRootListEntry);
+        }
+        /* Otherwise, none */
+        else
+        {
+            NetRoot->DefaultVNetRoot = NULL;
+        }
+    }
 
-    /* Trace refcount if asked */
-    switch (NodeType)
+    /* If there are still other VNetRoot available, we're done */
+    if (!IsListEmpty(&NetRoot->VirtualNetRoots))
     {
-        case RDBSS_NTC_SRVCALL:
-            PRINT_REF_COUNT(SRVCALL, Node->NodeReferenceCount);
-            break;
+        return;
+    }
 
-        case RDBSS_NTC_NETROOT:
-            PRINT_REF_COUNT(NETROOT, Node->NodeReferenceCount);
-            break;
+    /* Otherwise, initiate NetRoot finalization */
+    if (!BooleanFlagOn(NetRoot->Flags, NETROOT_FLAG_NAME_ALREADY_REMOVED))
+    {
+        RxRemovePrefixTableEntry(PrefixTable, &NetRoot->PrefixEntry);
+        SetFlag(NetRoot->Flags, NETROOT_FLAG_NAME_ALREADY_REMOVED);
+    }
 
-        case RDBSS_NTC_V_NETROOT:
-            PRINT_REF_COUNT(VNETROOT, Node->NodeReferenceCount);
-            break;
+    /* Notify mini-rdr */
+    if (NetRoot->pSrvCall != NULL && NetRoot->pSrvCall->RxDeviceObject != NULL)
+    {
+        NTSTATUS Status;
 
-        case RDBSS_NTC_SRVOPEN:
-            PRINT_REF_COUNT(SRVOPEN, Node->NodeReferenceCount);
-            break;
+        MINIRDR_CALL_THROUGH(Status, NetRoot->pSrvCall->RxDeviceObject->Dispatch,
+                             MRxFinalizeNetRoot, ((PMRX_NET_ROOT)NetRoot, FALSE));
+        (void)Status;
+    }
+}
 
-        case RDBSS_NTC_FOBX:
-            PRINT_REF_COUNT(NETFOBX, Node->NodeReferenceCount);
-            break;
+VOID
+RxResumeBlockedOperations_ALL(
+    IN OUT PRX_CONTEXT RxContext)
+{
+    LIST_ENTRY BlockedOps;
 
-        default:
-            ASSERT(FALSE);
-            break;
-    }
+    PAGED_CODE();
 
-    RxpUndoScavengerFinalizationMarking(Instance);
-    RxReleaseScavengerMutex();
+    /* Get the blocked operations */
+    RxTransferListWithMutex(&BlockedOps, &RxContext->BlockedOperations, RxContext->BlockedOpsMutex);
+
+    if (!IsListEmpty(&BlockedOps))
+    {
+        UNIMPLEMENTED;
+    }
 }
 
 VOID
@@ -4830,12 +6863,147 @@ RxResumeBlockedOperations_Serially(
     RxReleaseSerializationMutex();
 }
 
+/*
+ * @implemented
+ */
 BOOLEAN
 RxScavengeRelatedFobxs(
     PFCB Fcb)
+{
+    PFOBX Fobx;
+    LIST_ENTRY LocalList;
+    PLIST_ENTRY NextEntry;
+    PRDBSS_SCAVENGER Scavenger;
+
+    PAGED_CODE();
+
+    /* First of all, check whether there are FOBX to scavenge */
+    Scavenger = Fcb->RxDeviceObject->pRdbssScavenger;
+    RxAcquireScavengerMutex();
+    if (Scavenger->FobxsToBeFinalized <= 0)
+    {
+        RxReleaseScavengerMutex();
+        return FALSE;
+    }
+
+    /* Initialize our local list which will hold all the FOBX to scavenge so
+     * that we don't acquire the scavenger mutex too long
+     */
+    InitializeListHead(&LocalList);
+
+    /* Technically, that condition should all be true... */
+    if (!IsListEmpty(&Scavenger->FobxFinalizationList))
+    {
+        PLIST_ENTRY NextEntry, LastEntry;
+
+        /* Browse all the FCBs to find the matching ones */
+        NextEntry = Scavenger->FobxFinalizationList.Flink;
+        LastEntry = &Scavenger->FobxFinalizationList;
+        while (NextEntry != LastEntry)
+        {
+            Fobx = CONTAINING_RECORD(NextEntry, FOBX, ScavengerFinalizationList);
+            NextEntry = NextEntry->Flink;
+            /* Matching our FCB? Let's finalize it */
+            if (Fobx->pSrvOpen != NULL && Fobx->pSrvOpen->pFcb == RX_GET_MRX_FCB(Fcb))
+            {
+                RxpUndoScavengerFinalizationMarking(Fobx);
+                ASSERT(NodeType(Fobx) == RDBSS_NTC_FOBX);
+                InsertTailList(&LocalList, &Fobx->ScavengerFinalizationList);
+            }
+        }
+    }
+
+    RxReleaseScavengerMutex();
+
+    /* Nothing to scavenge? Quit */
+    if (IsListEmpty(&LocalList))
+    {
+        return FALSE;
+    }
+
+    /* Now, finalize all the extracted FOBX */
+    while (!IsListEmpty(&LocalList))
+    {
+        NextEntry = RemoveHeadList(&LocalList);
+        Fobx = CONTAINING_RECORD(NextEntry, FOBX, ScavengerFinalizationList);
+        RxFinalizeNetFobx(Fobx, TRUE, TRUE);
+    }
+
+    return TRUE;
+}
+
+VOID
+RxScavengerFinalizeEntries(
+    PRDBSS_DEVICE_OBJECT DeviceObject)
 {
     UNIMPLEMENTED;
-    return FALSE;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxScavengerTimerRoutine(
+    PVOID Context)
+{
+    BOOLEAN Requeue;
+    PRDBSS_DEVICE_OBJECT DeviceObject;
+    PRDBSS_SCAVENGER Scavenger;
+
+    PAGED_CODE();
+
+    DeviceObject = Context;
+    Scavenger = DeviceObject->pRdbssScavenger;
+
+    Requeue = FALSE;
+    RxAcquireScavengerMutex();
+    /* If the scavenger was dormant, wake it up! */
+    if (Scavenger->State == RDBSS_SCAVENGER_DORMANT)
+    {
+        /* Done */
+        Scavenger->State = RDBSS_SCAVENGER_ACTIVE;
+        KeResetEvent(&Scavenger->ScavengeEvent);
+
+        /* Scavenger the entries */
+        RxReleaseScavengerMutex();
+        RxScavengerFinalizeEntries(DeviceObject);
+        RxAcquireScavengerMutex();
+
+        /* If we're still active (race) */
+        if (Scavenger->State == RDBSS_SCAVENGER_ACTIVE)
+        {
+            /* If there are new entries to scavenge, stay dormant and requeue a run */
+            if (Scavenger->NumberOfDormantFiles + Scavenger->SrvCallsToBeFinalized +
+                Scavenger->NetRootsToBeFinalized + Scavenger->VNetRootsToBeFinalized +
+                Scavenger->FcbsToBeFinalized + Scavenger->SrvOpensToBeFinalized +
+                Scavenger->FobxsToBeFinalized != 0)
+            {
+                Requeue = TRUE;
+                Scavenger->State = RDBSS_SCAVENGER_DORMANT;
+            }
+            /* Otherwise, we're inactive again */
+            else
+            {
+                Scavenger->State == RDBSS_SCAVENGER_INACTIVE;
+            }
+        }
+
+        RxReleaseScavengerMutex();
+
+        /* Requeue an execution */
+        if (Requeue)
+        {
+            RxPostOneShotTimerRequest(RxFileSystemDeviceObject, &Scavenger->WorkItem,
+                                      RxScavengerTimerRoutine, DeviceObject, Scavenger->TimeLimit);
+        }
+    }
+    else
+    {
+        RxReleaseScavengerMutex();
+    }
+
+    KeSetEvent(&Scavenger->ScavengeEvent, IO_NO_INCREMENT, FALSE);
 }
 
 BOOLEAN
@@ -4857,7 +7025,7 @@ RxSpinUpRequestsDispatcher(
     NTSTATUS Status;
     PRX_DISPATCHER RxDispatcher;
 
-    Status = ObReferenceObjectByPointer(PsGetCurrentThread(), THREAD_ALL_ACCESS, PsThreadType, KernelMode);
+    Status = ObReferenceObjectByPointer(PsGetCurrentThread(), THREAD_ALL_ACCESS, *PsThreadType, KernelMode);
     if (!NT_SUCCESS(Status))
     {
         PsTerminateSystemThread(STATUS_SUCCESS);
@@ -4896,7 +7064,7 @@ RxSpinUpRequestsDispatcher(
 
             InterlockedDecrement(&WorkQueue->WorkQueueItemForSpinUpWorkerThreadInUse);
 
-            DPRINT1("WORKQ:SR %lx %lx\n", WorkItem->WorkerRoutine, WorkItem->Parameter);
+            DPRINT("Workqueue: calling %p(%p)\n", WorkItem->WorkerRoutine, WorkItem->Parameter);
             WorkItem->WorkerRoutine(WorkItem->Parameter);
         }
     } while (RxDispatcher->State == RxDispatcherActive);
@@ -5060,6 +7228,9 @@ RxTableComputePathHashValue(
     return Hash;
 }
 
+/*
+ * @implemented
+ */
 PVOID
 RxTableLookupName(
     IN PRX_PREFIX_TABLE ThisTable,
@@ -5122,10 +7293,34 @@ RxTableLookupName(
         ASSERT(Entry->ContainingRecord != NULL);
         Container = Entry->ContainingRecord;
 
-        /* Need to handle NetRoot specific case... */
+        /* If we have a NET_ROOT, let's return a V_NET_ROOT */
         if ((NodeType(Entry->ContainingRecord) & ~RX_SCAVENGER_MASK) == RDBSS_NTC_NETROOT)
         {
-            UNIMPLEMENTED;
+            PNET_ROOT NetRoot;
+
+            NetRoot = (PNET_ROOT)Entry->ContainingRecord;
+            /* If there's a default one, perfect, that's a match */
+            if (NetRoot->DefaultVNetRoot != NULL)
+            {
+                Container = NetRoot->DefaultVNetRoot;
+            }
+            /* If none (that shouldn't happen!), try to find one */
+            else
+            {
+                /* Use the first one in the list */
+                if (!IsListEmpty(&NetRoot->VirtualNetRoots))
+                {
+                    Container = CONTAINING_RECORD(NetRoot->VirtualNetRoots.Flink, V_NET_ROOT, NetRootListEntry);
+                }
+                /* Really, really, shouldn't happen */
+                else
+                {
+                    ASSERT(FALSE);
+                    Entry = NULL;
+                    Container = NULL;
+                }
+            }
+
             break;
         }
         else if ((NodeType(Entry->ContainingRecord) & ~RX_SCAVENGER_MASK) == RDBSS_NTC_V_NETROOT)
@@ -5265,6 +7460,91 @@ RxTableLookupName_ExactLengthMatch(
     return NULL;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+RxTearDownBufferingManager(
+   PSRV_CALL SrvCall)
+{
+    PAGED_CODE();
+
+    /* Nothing to do */
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxTimerDispatch(
+    _In_ struct _KDPC *Dpc,
+    _In_opt_ PVOID DeferredContext,
+    _In_opt_ PVOID SystemArgument1,
+    _In_opt_ PVOID SystemArgument2)
+{
+    BOOLEAN Set;
+    LIST_ENTRY LocalList;
+    PLIST_ENTRY ListEntry;
+    PRX_WORK_ITEM WorkItem;
+
+    InitializeListHead(&LocalList);
+
+    KeAcquireSpinLockAtDpcLevel(&RxTimerLock);
+    ++RxTimerTickCount;
+
+    /* Find any entry matching */
+    if (!IsListEmpty(&RxTimerQueueHead))
+    {
+        ListEntry = RxTimerQueueHead.Flink;
+        do
+        {
+            WorkItem = CONTAINING_RECORD(ListEntry, RX_WORK_ITEM, WorkQueueItem.List);
+            if (WorkItem->LastTick == RxTimerTickCount)
+            {
+                ListEntry = ListEntry->Flink;
+
+                RemoveEntryList(&WorkItem->WorkQueueItem.List);
+                InsertTailList(&LocalList, &WorkItem->WorkQueueItem.List);
+            }
+            else
+            {
+                ListEntry = ListEntry->Flink;
+            }
+        } while (ListEntry != &RxTimerQueueHead);
+    }
+    /* Do we have to requeue a later execution? */
+    Set = !IsListEmpty(&RxTimerQueueHead);
+
+    KeReleaseSpinLockFromDpcLevel(&RxTimerLock);
+
+    /* Requeue if list wasn't empty */
+    if (Set)
+    {
+        KeSetTimer(&RxTimer, RxTimerInterval, &RxTimerDpc);
+    }
+
+    /* If we had matching entries */
+    if (!IsListEmpty(&LocalList))
+    {
+        /* Post them, one after another */
+        ListEntry = LocalList.Flink;
+        do
+        {
+            WorkItem = CONTAINING_RECORD(ListEntry, RX_WORK_ITEM, WorkQueueItem.List);
+            ListEntry = ListEntry->Flink;
+
+            WorkItem->WorkQueueItem.List.Flink = NULL;
+            WorkItem->WorkQueueItem.List.Blink = NULL;
+            RxPostToWorkerThread(WorkItem->WorkQueueItem.pDeviceObject, CriticalWorkQueue,
+                                 &WorkItem->WorkQueueItem, WorkItem->WorkQueueItem.WorkerRoutine,
+                                 WorkItem->WorkQueueItem.Parameter);
+        }
+        while (ListEntry != &LocalList);
+    }
+}
+
 /*
  * @implemented
  */
@@ -5357,6 +7637,19 @@ RxTrackPagingIoResource(
     UNIMPLEMENTED;
 }
 
+/*
+ * @implemented
+ */
+VOID
+RxUndoScavengerFinalizationMarking(
+    PVOID Instance)
+{
+    /* Just call internal routine with mutex held */
+    RxAcquireScavengerMutex();
+    RxpUndoScavengerFinalizationMarking(Instance);
+    RxReleaseScavengerMutex();
+}
+
 /*
  * @implemented
  */
@@ -5372,17 +7665,17 @@ RxUninitializeVNetRootParameters(
     /* Only free what could have been allocated */
     if (UserName != NULL)
     {
-        ExFreePool(UserName);
+        RxFreePool(UserName);
     }
 
     if (UserDomainName != NULL)
     {
-        ExFreePool(UserDomainName);
+        RxFreePool(UserDomainName);
     }
 
     if (Password != NULL)
     {
-        ExFreePool(Password);
+        RxFreePool(Password);
     }
 
     /* And remove the possibly set CSC agent flag */
@@ -5614,7 +7907,43 @@ RxWorkItemDispatcher(
 
     DispatchItem->DispatchRoutine(DispatchItem->DispatchRoutineParameter);
 
-    ExFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+    RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
+}
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+_RxAllocatePoolWithTag(
+    _In_ POOL_TYPE PoolType,
+    _In_ SIZE_T NumberOfBytes,
+    _In_ ULONG Tag)
+{
+    return ExAllocatePoolWithTagPriority(PoolType, NumberOfBytes, Tag, LowPoolPriority);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+_RxFreePool(
+    _In_ PVOID Buffer)
+{
+    ExFreePoolWithTag(Buffer, 0);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+_RxFreePoolWithTag(
+    _In_ PVOID Buffer,
+    _In_ ULONG Tag)
+{
+    ExFreePoolWithTag(Buffer, Tag);
 }
 
 NTSTATUS
@@ -5658,25 +7987,27 @@ __RxAcquireFcb(
         UNIMPLEMENTED;
     }
 
-    /* Nor missing contexts... */
+    /* If we don't have a context, assume we can wait! */
     if (RxContext == NULL)
     {
-        UNIMPLEMENTED;
+        CanWait = TRUE;
     }
+    else
+    {
+        /* That said: we have a real context! */
+        ContextIsPresent = TRUE;
 
-    /* That said: we have a real context! */
-    ContextIsPresent = TRUE;
+        /* If we've been cancelled in between, give up */
+        Status = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED) ? STATUS_CANCELLED : STATUS_SUCCESS;
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
 
-    /* If we've been cancelled in between, give up */
-    Status = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_CANCELLED) ? STATUS_CANCELLED : STATUS_SUCCESS;
-    if (!NT_SUCCESS(Status))
-    {
-        return Status;
+        /* Can we wait? */
+        CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
     }
 
-    /* Can we wait? */
-    CanWait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
-
     while (TRUE)
     {
         /* Assume we cannot lock */