+/*
+ * @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
+ */