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=7... ============================================================================== --- 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?re... ============================================================================== --- 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?re... ============================================================================== --- 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?r... ============================================================================== --- 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?r... ============================================================================== --- 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.c... ============================================================================== --- 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(); }
/*