Author: pschweitzer
Date: Sun Jun 25 11:55:37 2017
New Revision: 75195
URL:
http://svn.reactos.org/svn/reactos?rev=75195&view=rev
Log:
[RXCE]
- Implemented RxCompleteSrvOpenKeyAssociation(), RxInitiateSrvOpenKeyAssociation(),
RxProcessChangeBufferingStateRequests()
- Implemented RxFinalizeFcbTable(), RxFinalizeNetFobx(), RxFinalizeNetRoot(),
RxFinalizeSrvCall(), RxFinalizeVNetRoot(), RxFreeObject(), RxpDestroySrvCall(),
RxRemovePrefixTableEntry(), RxRemoveVirtualNetRootFromNetRoot(), RxScavengeRelatedFobxs(),
RxTearDownBufferingManager(), RxUndoScavengerFinalizationMarking()
- Implemented RxPostToWorkerThread()
- Implemented RxFlushFcbInSystemCache(), RxPurgeFcb(), RxPurgeFcbInSystemCache()
- Stubbed RxOrphanSrvOpens(), RxpDiscardChangeBufferingStateRequests(),
RxpDispatchChangeBufferingStateRequests(), RxpProcessChangeBufferingStateRequests()
- Continued implementation of RxDereference() so that it supports more objects than just
SRV_CALL
- Reworked RxInsertWorkQueueItem() implementation so that it accepts any work item, and
not just dispatch work items
- Finished implementation of RxTableLookupName() so that it properly returns a V_NET_ROOT
on NET_ROOT match
Notable effects of this commit are:
- RXCE/RDBSS leak less memory; now objects without references are properly deleted from
the system
- This means that stale objects are also deleted; this fixes CORE-13483 were same stale
SRV_CALL was used again and again
- Because in prefix table NET_ROOT are correctly handled, it's now possible to mount
several path from the same prefix; this fixes CORE-13482
CORE-8204
CORE-11327
CORE-13482
CORE-13483
Modified:
trunk/reactos/sdk/include/ddk/buffring.h
trunk/reactos/sdk/include/ddk/fcb.h
trunk/reactos/sdk/include/ddk/fcbtable.h
trunk/reactos/sdk/include/ddk/mrxfcb.h
trunk/reactos/sdk/include/ddk/prefix.h
trunk/reactos/sdk/include/ddk/rxprocs.h
trunk/reactos/sdk/include/ddk/rxworkq.h
trunk/reactos/sdk/lib/drivers/rxce/rxce.c
Modified: trunk/reactos/sdk/include/ddk/buffring.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/buffring.h…
==============================================================================
--- trunk/reactos/sdk/include/ddk/buffring.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/buffring.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -22,6 +22,29 @@
LIST_ENTRY SrvOpenLists[1];
} RX_BUFFERING_MANAGER, *PRX_BUFFERING_MANAGER;
+#if (_WIN32_WINNT >= 0x0600)
+#define RxAcquireBufferingManagerMutex(BufMan)
ExAcquireFastMutex(&(BufMan)->Mutex)
+#else
+#define RxAcquireBufferingManagerMutex(BufMan) \
+ { \
+ if (!ExTryToAcquireFastMutex(&(BufMan)->Mutex)) \
+ { \
+ ExAcquireFastMutex(&(BufMan)->Mutex); \
+ } \
+ }
+#endif
+#define RxReleaseBufferingManagerMutex(BufMan)
ExReleaseFastMutex(&(BufMan)->Mutex)
+
+VOID
+RxpProcessChangeBufferingStateRequests(
+ PSRV_CALL SrvCall,
+ BOOLEAN UpdateHandlerState);
+
+VOID
+NTAPI
+RxProcessChangeBufferingStateRequests(
+ _In_ PVOID SrvCall);
+
VOID
RxProcessFcbChangeBufferingStateRequest(
_In_ PFCB Fcb);
@@ -39,6 +62,15 @@
_In_ PSRV_CALL SrvCall);
NTSTATUS
+RxTearDownBufferingManager(
+ _In_ PSRV_CALL SrvCall);
+
+NTSTATUS
+RxFlushFcbInSystemCache(
+ _In_ PFCB Fcb,
+ _In_ BOOLEAN SynchronizeWithLazyWriter);
+
+NTSTATUS
RxPurgeFcbInSystemCache(
_In_ PFCB Fcb,
_In_ PLARGE_INTEGER FileOffset OPTIONAL,
Modified: trunk/reactos/sdk/include/ddk/fcb.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/fcb.h?rev=…
==============================================================================
--- trunk/reactos/sdk/include/ddk/fcb.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/fcb.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -26,6 +26,9 @@
PURGE_SYNCHRONIZATION_CONTEXT PurgeSyncronizationContext;
RX_BUFFERING_MANAGER BufferingManager;
} SRV_CALL, *PSRV_CALL;
+
+#define NETROOT_FLAG_FINALIZATION_IN_PROGRESS 0x00040000
+#define NETROOT_FLAG_NAME_ALREADY_REMOVED 0x00080000
typedef struct _NET_ROOT
{
@@ -270,6 +273,7 @@
#define FOBX_FLAG_MATCH_ALL 0x10000
#define FOBX_FLAG_FREE_UNICODE 0x20000
#define FOBX_FLAG_DELETE_ON_CLOSE 0x800000
+#define FOBX_FLAG_SRVOPEN_CLOSED 0x1000000
#define FOBX_FLAG_UNC_NAME 0x2000000
#define FOBX_FLAG_ENCLOSED_ALLOCATED 0x4000000
@@ -463,6 +467,12 @@
_In_ PUNICODE_STRING FilePath,
_In_ PRX_CONNECTION_ID RxConnectionId);
+BOOLEAN
+RxFinalizeVNetRoot(
+ _Out_ PV_NET_ROOT ThisVNetRoot,
+ _In_ BOOLEAN RecursiveFinalize,
+ _In_ BOOLEAN ForceFinalize);
+
#define RxWaitForStableVNetRoot(V, R) RxWaitForStableCondition(&(V)->Condition,
&(V)->TransitionWaitList, (R), NULL)
#define RxTransitionVNetRoot(V, C) RxUpdateCondition((C), &(V)->Condition,
&(V)->TransitionWaitList)
@@ -577,6 +587,12 @@
RxCreateNetFobx(
_Out_ PRX_CONTEXT RxContext,
_In_ PMRX_SRV_OPEN MrxSrvOpen);
+
+BOOLEAN
+RxFinalizeNetFobx(
+ _Out_ PFOBX ThisFobx,
+ _In_ BOOLEAN RecursiveFinalize,
+ _In_ BOOLEAN ForceFinalize);
#ifdef __REACTOS__
#define FILL_IN_FCB(Fcb, a, nl, ct, lat, lwt, lct, as, fs, vdl) \
Modified: trunk/reactos/sdk/include/ddk/fcbtable.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/fcbtable.h…
==============================================================================
--- trunk/reactos/sdk/include/ddk/fcbtable.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/fcbtable.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -32,6 +32,10 @@
_Inout_ PRX_FCB_TABLE FcbTable,
_In_ BOOLEAN CaseInsensitiveMatch);
+VOID
+RxFinalizeFcbTable(
+ _Inout_ PRX_FCB_TABLE FcbTable);
+
PFCB
RxFcbTableLookupFcb(
_In_ PRX_FCB_TABLE FcbTable,
Modified: trunk/reactos/sdk/include/ddk/mrxfcb.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/mrxfcb.h?r…
==============================================================================
--- trunk/reactos/sdk/include/ddk/mrxfcb.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/mrxfcb.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -11,6 +11,7 @@
#define SRVCALL_FLAG_CASE_INSENSITIVE_NETROOTS 0x4
#define SRVCALL_FLAG_CASE_INSENSITIVE_FILENAMES 0x8
#define SRVCALL_FLAG_DFS_AWARE_SERVER 0x10
+#define SRVCALL_FLAG_FORCE_FINALIZED 0x20
typedef struct _MRX_SRV_CALL_
{
Modified: trunk/reactos/sdk/include/ddk/prefix.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/prefix.h?r…
==============================================================================
--- trunk/reactos/sdk/include/ddk/prefix.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/prefix.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -29,6 +29,11 @@
_In_ PULONG ContainerRefCount,
_In_ USHORT CaseInsensitiveLength,
_In_ PRX_CONNECTION_ID ConnectionId);
+
+VOID
+RxRemovePrefixTableEntry(
+ _Inout_ PRX_PREFIX_TABLE ThisTable,
+ _Inout_ PRX_PREFIX_ENTRY Entry);
VOID
RxInitializePrefixTable(
Modified: trunk/reactos/sdk/include/ddk/rxprocs.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/rxprocs.h?…
==============================================================================
--- trunk/reactos/sdk/include/ddk/rxprocs.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/rxprocs.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -528,6 +528,14 @@
RxGetNetworkProviderPriority(
_In_ PUNICODE_STRING DeviceName);
+VOID
+RxpDiscardChangeBufferingStateRequests(
+ _Inout_ PLIST_ENTRY DiscardedRequests);
+
+VOID
+RxUndoScavengerFinalizationMarking(
+ PVOID Instance);
+
ULONG
RxTableComputePathHashValue(
_In_ PUNICODE_STRING Name);
@@ -560,6 +568,11 @@
VOID
RxAddVirtualNetRootToNetRoot(
+ _In_ PNET_ROOT NetRoot,
+ _In_ PV_NET_ROOT VNetRoot);
+
+VOID
+RxRemoveVirtualNetRootFromNetRoot(
_In_ PNET_ROOT NetRoot,
_In_ PV_NET_ROOT VNetRoot);
@@ -575,6 +588,10 @@
RxFreeFcbObject(
_In_ PVOID Object);
+VOID
+RxPurgeFcb(
+ _In_ PFCB Fcb);
+
BOOLEAN
RxFinalizeNetFcb(
_Out_ PFCB ThisFcb,
@@ -642,6 +659,10 @@
_In_opt_ PRX_CONNECTION_ID RxConnectionId);
VOID
+RxOrphanSrvOpens(
+ _In_ PV_NET_ROOT ThisVNetRoot);
+
+VOID
RxOrphanThisFcb(
_In_ PFCB Fcb);
Modified: trunk/reactos/sdk/include/ddk/rxworkq.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/include/ddk/rxworkq.h?…
==============================================================================
--- trunk/reactos/sdk/include/ddk/rxworkq.h [iso-8859-1] (original)
+++ trunk/reactos/sdk/include/ddk/rxworkq.h [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -82,6 +82,15 @@
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);
+
+NTSTATUS
+NTAPI
RxDispatchToWorkerThread(
_In_ PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
_In_ WORK_QUEUE_TYPE WorkQueueType,
Modified: trunk/reactos/sdk/lib/drivers/rxce/rxce.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/rxce/rxce.…
==============================================================================
--- trunk/reactos/sdk/lib/drivers/rxce/rxce.c [iso-8859-1] (original)
+++ trunk/reactos/sdk/lib/drivers/rxce/rxce.c [iso-8859-1] Sun Jun 25 11:55:37 2017
@@ -58,11 +58,22 @@
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
@@ -730,11 +741,71 @@
}
}
+/*
+ * @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);
+ }
}
/*
@@ -1795,7 +1866,7 @@
RxReleaseScavengerMutex();
- /* TODO: Really deallocate stuff - we're leaking as hell! */
+ /* Now, deallocate the memory */
switch (NodeType)
{
case RDBSS_NTC_SRVCALL:
@@ -1811,20 +1882,53 @@
}
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;
+ }
}
}
@@ -1938,7 +2042,7 @@
DispatchItem->WorkQueueItem.Parameter = DispatchItem;
/* Insert item */
- Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType, DispatchItem);
+ Status = RxInsertWorkQueueItem(pMRxDeviceObject, WorkQueueType,
&DispatchItem->WorkQueueItem);
if (!NT_SUCCESS(Status))
{
RxFreePoolWithTag(DispatchItem, RX_WORKQ_POOLTAG);
@@ -2148,6 +2252,27 @@
/*
* @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
+ */
BOOLEAN
RxFinalizeNetFcb(
OUT PFCB ThisFcb,
@@ -2277,25 +2402,294 @@
return TRUE;
}
+/*
+ * @implemented
+ */
+BOOLEAN
+RxFinalizeNetFobx(
+ _Out_ PFOBX ThisFobx,
+ _In_ BOOLEAN RecursiveFinalize,
+ _In_ BOOLEAN ForceFinalize)
+{
+ PFCB Fcb;
+ PSRV_OPEN SrvOpen;
+
+ PAGED_CODE();
+
+ ASSERT(NodeType(ThisFobx) == RDBSS_NTC_FOBX);
+
+ /* Only finalize if forced or if there's no ref left */
+ if (ThisFobx->NodeReferenceCount != 0 &&
+ !ForceFinalize)
+ {
+ return FALSE;
+ }
+
+ DPRINT("Finalize Fobx: %p (with %d ref), forced: %d\n", ThisFobx,
ThisFobx->NodeReferenceCount, ForceFinalize);
+
+ SrvOpen = ThisFobx->SrvOpen;
+ Fcb = SrvOpen->Fcb;
+ /* If it wasn't finalized yet, do it */
+ if (!ThisFobx->UpperFinalizationDone)
+ {
+ 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))
+ {
+ RxFreePoolWithTag(ThisFobx->UnicodeQueryTemplate.Buffer,
RX_DIRCTL_POOLTAG);
+ }
+
+ /* Notify the mini-rdr */
+ if (Fcb->MRxDispatch != NULL &&
Fcb->MRxDispatch->MRxDeallocateForFobx != NULL)
+ {
+ Fcb->MRxDispatch->MRxDeallocateForFobx((PMRX_FOBX)ThisFobx);
+ }
+
+ /* If the SRV_OPEN wasn't closed yet, do it */
+ if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_SRVOPEN_CLOSED))
+ {
+ NTSTATUS Status;
+
+ 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)
+ {
+ return FALSE;
+ }
+
+ /* At that point, everything should be closed */
+ ASSERT(IsListEmpty(&ThisFobx->ClosePendingList));
+
+ /* 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);
+ }
+
+ ThisFobx->pSrvOpen = NULL;
+
+ /* A FOBX less */
+ InterlockedDecrement((volatile long *)&SrvOpen->pVNetRoot->NumberOfFobxs);
+
+ RxDereferenceSrvOpen(SrvOpen, LHS_ExclusiveLockHeld);
+
+ /* If it wasn't allocated with another object, free the FOBX */
+ if (!BooleanFlagOn(ThisFobx->Flags, FOBX_FLAG_ENCLOSED_ALLOCATED))
+ {
+ RxFreeFcbObject(ThisFobx);
+ }
+
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
BOOLEAN
RxFinalizeNetRoot(
OUT PNET_ROOT ThisNetRoot,
IN BOOLEAN RecursiveFinalize,
- IN BOOLEAN ForceFinalize
- )
-{
- UNIMPLEMENTED;
- return FALSE;
-}
-
+ IN BOOLEAN ForceFinalize)
+{
+ PSRV_CALL SrvCall;
+ PRX_FCB_TABLE FcbTable;
+ PRX_PREFIX_TABLE PrefixTable;
+
+ PAGED_CODE();
+
+ ASSERT(NodeType(ThisNetRoot) == RDBSS_NTC_NETROOT);
+
+ PrefixTable = ThisNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+ ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
+
+ /* If sme finalization is already ongoing, leave */
+ if (BooleanFlagOn(ThisNetRoot->Flags, NETROOT_FLAG_FINALIZATION_IN_PROGRESS))
+ {
+ return FALSE;
+ }
+
+ /* Mark we're finalizing */
+ SetFlag(ThisNetRoot->Flags, NETROOT_FLAG_FINALIZATION_IN_PROGRESS);
+
+ FcbTable = &ThisNetRoot->FcbTable;
+ /* Did caller asked us to finalize any associated FCB? */
+ if (RecursiveFinalize)
+ {
+ USHORT Bucket;
+
+ /* Browse all the FCBs in our FCB table */
+ RxAcquireFcbTableLockExclusive(FcbTable, TRUE);
+ for (Bucket = 0; Bucket < FcbTable->NumberOfBuckets; ++Bucket)
+ {
+ PLIST_ENTRY HashBucket, ListEntry;
+
+ HashBucket = &FcbTable->HashBuckets[Bucket];
+ ListEntry = HashBucket->Flink;
+ while (ListEntry != HashBucket)
+ {
+ PFCB Fcb;
+
+ 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);
+ }
+ }
+ }
+ RxReleaseFcbTableLock(FcbTable);
+ }
+
+ /* Only finalize if forced or if there's a single ref left */
+ if (ThisNetRoot->NodeReferenceCount != 1 && !ForceFinalize)
+ {
+ return FALSE;
+ }
+
+ 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)
+ {
+ return FALSE;
+ }
+
+ /* Finalize the FCB table (and make sure it's empty!) */
+ RxFinalizeFcbTable(FcbTable);
+
+ /* If name wasn't remove already, do it now */
+ if (!BooleanFlagOn(ThisNetRoot->Flags, NETROOT_FLAG_NAME_ALREADY_REMOVED))
+ {
+ RxRemovePrefixTableEntry(PrefixTable, &ThisNetRoot->PrefixEntry);
+ }
+
+ /* Delete the object */
+ SrvCall = (PSRV_CALL)ThisNetRoot->pSrvCall;
+ RxFreeObject(ThisNetRoot);
+
+ /* And dereference the associated SRV_CALL */
+ if (SrvCall != NULL)
+ {
+ RxDereferenceSrvCall(SrvCall, LHS_ExclusiveLockHeld);
+ }
+
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
BOOLEAN
RxFinalizeSrvCall(
OUT PSRV_CALL ThisSrvCall,
IN BOOLEAN RecursiveFinalize,
IN BOOLEAN ForceFinalize)
{
- UNIMPLEMENTED;
- return FALSE;
+ PRX_PREFIX_TABLE PrefixTable;
+
+ PAGED_CODE();
+
+ ASSERT(NodeType(ThisSrvCall) == RDBSS_NTC_SRVCALL);
+
+ PrefixTable = ThisSrvCall->RxDeviceObject->pRxNetNameTable;
+ ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
+
+ /* Only finalize if forced or if there's a single ref left */
+ if (ThisSrvCall->NodeReferenceCount != 1 &&
+ !ForceFinalize)
+ {
+ return FALSE;
+ }
+
+ DPRINT("Finalizing SrvCall %p for %wZ\n", ThisSrvCall,
&ThisSrvCall->PrefixEntry.Prefix);
+
+ /* 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)
+ {
+ SetFlag(ThisSrvCall->Flags, SRVCALL_FLAG_FORCE_FINALIZED);
+ }
+
+ /* And done */
+ ThisSrvCall->UpperFinalizationDone = TRUE;
+
+ /* Would defered execution free the object? */
+ WillFree = (ThisSrvCall->NodeReferenceCount == 1);
+
+ /* If we have a device object */
+ if (ThisSrvCall->RxDeviceObject != NULL)
+ {
+ NTSTATUS Status;
+
+ /* If we're not executing in the RDBSS thread, queue for execution within
the thread */
+ if (RxGetRDBSSProcess() != IoGetCurrentProcess())
+ {
+ /* Extra ref, as usual */
+ InterlockedIncrement((volatile long
*)&ThisSrvCall->NodeReferenceCount);
+ /* And dispatch */
+ RxDispatchToWorkerThread(ThisSrvCall->RxDeviceObject,
DelayedWorkQueue, RxpDestroySrvCall, ThisSrvCall);
+
+ /* 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;
+ }
+ }
+
+ /* If we're still referenced, don't go any further! */
+ if (ThisSrvCall->NodeReferenceCount != 1)
+ {
+ return FALSE;
+ }
+
+ /* Don't leak */
+ if (ThisSrvCall->pDomainName != NULL)
+ {
+ RxFreePool(ThisSrvCall->pDomainName);
+ }
+
+ /* And free! */
+ RxTearDownBufferingManager(ThisSrvCall);
+ RxFreeObject(ThisSrvCall);
+
+ return TRUE;
}
BOOLEAN
@@ -2306,6 +2700,83 @@
{
UNIMPLEMENTED;
return FALSE;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+RxFinalizeVNetRoot(
+ OUT PV_NET_ROOT ThisVNetRoot,
+ IN BOOLEAN RecursiveFinalize,
+ IN BOOLEAN ForceFinalize)
+{
+ PNET_ROOT NetRoot;
+ PRX_PREFIX_TABLE PrefixTable;
+
+ PAGED_CODE();
+
+ ASSERT(NodeType(ThisVNetRoot) == RDBSS_NTC_V_NETROOT);
+
+ PrefixTable =
ThisVNetRoot->pNetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+ ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
+
+ /* Only finalize if forced or if there's a single ref left */
+ if (ThisVNetRoot->NodeReferenceCount != 1 &&
+ !ForceFinalize)
+ {
+ return FALSE;
+ }
+
+ DPRINT("Finalizing VNetRoot %p for %wZ\n", ThisVNetRoot,
&ThisVNetRoot->PrefixEntry.Prefix);
+
+ NetRoot = (PNET_ROOT)ThisVNetRoot->pNetRoot;
+ /* If it wasn't finalized yet, do it */
+ if (!ThisVNetRoot->UpperFinalizationDone)
+ {
+ ASSERT(NodeType(NetRoot) == RDBSS_NTC_NETROOT);
+
+ /* 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);
+
+ /* Remove ourselves from prefix table */
+ RxRemovePrefixTableEntry(PrefixTable, &ThisVNetRoot->PrefixEntry);
+
+ /* Finalization done */
+ ThisVNetRoot->UpperFinalizationDone = TRUE;
+ }
+
+ /* If we're still referenced, don't go any further! */
+ if (ThisVNetRoot->NodeReferenceCount != 1)
+ {
+ return FALSE;
+ }
+
+ /* If there's an associated device, notify mini-rdr */
+ if (NetRoot->pSrvCall->RxDeviceObject != NULL)
+ {
+ NTSTATUS Status;
+
+ 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;
}
NTSTATUS
@@ -3109,6 +3580,31 @@
}
}
+/*
+ * @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;
+}
+
VOID
RxFreeFcbObject(
PVOID Object)
@@ -3116,11 +3612,46 @@
UNIMPLEMENTED;
}
+/*
+ * @implemented
+ */
VOID
RxFreeObject(
PVOID pObject)
{
- UNIMPLEMENTED;
+ 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);
}
/*
@@ -3749,12 +4280,24 @@
return Status;
}
-VOID
-RxInitiateSrvOpenKeyAssociation (
- IN OUT PSRV_OPEN SrvOpen
- )
-{
- UNIMPLEMENTED;
+/*
+ * @implemented
+ */
+VOID
+RxInitiateSrvOpenKeyAssociation(
+ IN OUT PSRV_OPEN SrvOpen)
+{
+ PRX_BUFFERING_MANAGER BufferingManager;
+
+ PAGED_CODE();
+
+ SrvOpen->Key = NULL;
+
+ /* Just keep track of the opening request */
+ BufferingManager =
&((PSRV_CALL)((PFCB)SrvOpen->pFcb)->VNetRoot->pNetRoot->pSrvCall)->BufferingManager;
+ InterlockedIncrement(&BufferingManager->NumberOfOutstandingOpens);
+
+ InitializeListHead(&SrvOpen->SrvOpenKeyList);
}
/*
@@ -3764,7 +4307,7 @@
RxInsertWorkQueueItem(
PRDBSS_DEVICE_OBJECT pMRxDeviceObject,
WORK_QUEUE_TYPE WorkQueueType,
- PRX_WORK_DISPATCH_ITEM DispatchItem)
+ PRX_WORK_QUEUE_ITEM WorkQueueItem)
{
KIRQL OldIrql;
NTSTATUS Status;
@@ -3789,7 +4332,7 @@
else
{
SpinUpThreads = FALSE;
- DispatchItem->WorkQueueItem.pDeviceObject = pMRxDeviceObject;
+ WorkQueueItem->pDeviceObject = pMRxDeviceObject;
InterlockedIncrement(&pMRxDeviceObject->DispatcherContext.NumberOfWorkerThreads);
WorkQueue->CumulativeQueueLength +=
WorkQueue->NumberOfWorkItemsToBeDispatched;
InterlockedIncrement(&WorkQueue->NumberOfWorkItemsToBeDispatched);
@@ -3814,7 +4357,7 @@
}
/* All fine, insert the item */
- KeInsertQueue(&WorkQueue->Queue, &DispatchItem->WorkQueueItem.List);
+ KeInsertQueue(&WorkQueue->Queue, &WorkQueueItem->List);
/* And start a new worker thread if needed */
if (SpinUpThreads)
@@ -3833,7 +4376,7 @@
CscAgent = FALSE;
- /* Client Side Caching is DFS stuff - we don't support it */
+ /* Client Side Caching is DFS stuff - we don't support it */
if (RxContext->Create.EaLength != 0)
{
UNIMPLEMENTED;
@@ -4279,6 +4822,13 @@
UNIMPLEMENTED;
}
+VOID
+RxOrphanSrvOpens(
+ IN PV_NET_ROOT ThisVNetRoot)
+{
+ UNIMPLEMENTED;
+}
+
/*
* @implemented
*/
@@ -4418,6 +4968,86 @@
PRINT_REF_COUNT(NETFCB, NewCount);
return NewCount;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxpDestroySrvCall(
+ IN PVOID Context)
+{
+ 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);
+}
+
+VOID
+RxpDiscardChangeBufferingStateRequests(
+ _Inout_ PLIST_ENTRY DiscardedRequests)
+{
+ UNIMPLEMENTED;
+}
+
+VOID
+RxpDispatchChangeBufferingStateRequests(
+ PSRV_CALL SrvCall,
+ PSRV_OPEN SrvOpen,
+ PLIST_ENTRY DiscardedRequests)
+{
+ UNIMPLEMENTED;
+}
+
+/*
+ * @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;
}
/*
@@ -4597,6 +5227,19 @@
RxContext->ReferenceCount = 0;
}
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+RxProcessChangeBufferingStateRequests(
+ _In_ PVOID SrvCall)
+{
+ /* Call internal routine */
+ RxUndoScavengerFinalizationMarking(SrvCall);
+ RxpProcessChangeBufferingStateRequests(SrvCall, TRUE);
+}
+
VOID
RxProcessFcbChangeBufferingStateRequest(
PFCB Fcb)
@@ -4655,6 +5298,35 @@
UNIMPLEMENTED;
}
+/*
+ * @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,
@@ -4663,8 +5335,46 @@
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;
}
/*
@@ -4877,6 +5587,95 @@
RxReleaseScavengerMutex();
}
+/*
+ * @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));
+
+ /* Check whether we're asked to remove null entry */
+ if (Entry->Prefix.Length == 0)
+ {
+ ThisTable->TableEntryForNull = NULL;
+ }
+ else
+ {
+ RemoveEntryList(&Entry->HashLinks);
+ }
+
+ Entry->ContainingRecord = NULL;
+
+ /* Also remove it from global list */
+ RemoveEntryList(&Entry->MemberQLinks);
+
+ ++ThisTable->Version;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxRemoveVirtualNetRootFromNetRoot(
+ PNET_ROOT NetRoot,
+ PV_NET_ROOT VNetRoot)
+{
+ PRX_PREFIX_TABLE PrefixTable;
+
+ PAGED_CODE();
+
+ PrefixTable = NetRoot->pSrvCall->RxDeviceObject->pRxNetNameTable;
+ ASSERT(RxIsPrefixTableLockAcquired(PrefixTable));
+
+ /* Remove the VNetRoot from the list in the NetRoot */
+ --NetRoot->NumberOfVirtualNetRoots;
+ RemoveEntryList(&VNetRoot->NetRootListEntry);
+
+ /* 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;
+ }
+ }
+
+ /* If there are still other VNetRoot available, we're done */
+ if (!IsListEmpty(&NetRoot->VirtualNetRoots))
+ {
+ return;
+ }
+
+ /* 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);
+ }
+
+ /* Notify mini-rdr */
+ if (NetRoot->pSrvCall != NULL && NetRoot->pSrvCall->RxDeviceObject
!= NULL)
+ {
+ NTSTATUS Status;
+
+ MINIRDR_CALL_THROUGH(Status,
NetRoot->pSrvCall->RxDeviceObject->Dispatch,
+ MRxFinalizeNetRoot, ((PMRX_NET_ROOT)NetRoot, FALSE));
+ (void)Status;
+ }
+}
+
VOID
NTAPI
RxResumeBlockedOperations_Serially(
@@ -4899,12 +5698,73 @@
RxReleaseSerializationMutex();
}
+/*
+ * @implemented
+ */
BOOLEAN
RxScavengeRelatedFobxs(
PFCB Fcb)
{
- UNIMPLEMENTED;
- return FALSE;
+ 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;
}
BOOLEAN
@@ -4965,7 +5825,7 @@
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);
@@ -5129,6 +5989,9 @@
return Hash;
}
+/*
+ * @implemented
+ */
PVOID
RxTableLookupName(
IN PRX_PREFIX_TABLE ThisTable,
@@ -5191,10 +6054,34 @@
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)
@@ -5337,6 +6224,19 @@
/*
* @implemented
*/
+NTSTATUS
+RxTearDownBufferingManager(
+ PSRV_CALL SrvCall)
+{
+ PAGED_CODE();
+
+ /* Nothing to do */
+ return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
VOID
RxTrackerUpdateHistory(
_Inout_opt_ PRX_CONTEXT RxContext,
@@ -5424,6 +6324,19 @@
_In_ PCSTR File)
{
UNIMPLEMENTED;
+}
+
+/*
+ * @implemented
+ */
+VOID
+RxUndoScavengerFinalizationMarking(
+ PVOID Instance)
+{
+ /* Just call internal routine with mutex held */
+ RxAcquireScavengerMutex();
+ RxpUndoScavengerFinalizationMarking(Instance);
+ RxReleaseScavengerMutex();
}
/*