+ /* Report the fact that file could be set as delete on close */
+ if (BooleanFlagOn(Fobx->Flags, FOBX_FLAG_DELETE_ON_CLOSE))
+ {
+ SetFlag(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE);
+ }
+
+ /* Cancel any pending notification */
+ RxCancelNotifyChangeDirectoryRequestsForFobx(Fobx);
+
+ /* Backup open count before we start playing with it */
+ OpenCount = Fcb->ShareAccess.OpenCount;
+
+ NetRoot = (PNET_ROOT)Fcb->pNetRoot;
+ FcbTableAcquired = FALSE;
+ OneLeft = FALSE;
+
+ _SEH2_TRY
+ {
+ /* Unclean count and delete on close? Verify whether we're the one */
+ if (Fcb->UncleanCount == 1 && BooleanFlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE))
+ {
+ if (RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, FALSE))
+ {
+ FcbTableAcquired = TRUE;
+ }
+ else
+ {
+ RxReleaseFcb(Context, Fcb);
+
+ RxAcquireFcbTableLockExclusive(&NetRoot->FcbTable, TRUE);
+
+ Status = RxAcquireExclusiveFcb(Context, Fcb);
+ if (Status != STATUS_SUCCESS)
+ {
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ return Status;
+ }
+
+ FcbTableAcquired = TRUE;
+ }
+
+ if (Fcb->UncleanCount == 1)
+ {
+ OneLeft = TRUE;
+ }
+ else
+ {
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ FcbTableAcquired = FALSE;
+ }
+ }
+
+ IsFile = FALSE;
+ TruncateSize = NULL;
+ /* Handle cleanup for pipes and printers */
+ if (NetRoot->Type == NET_ROOT_PIPE || NetRoot->Type == NET_ROOT_PRINT)
+ {
+ UNIMPLEMENTED;
+ }
+ /* Handle cleanup for files */
+ else if (NetRoot->Type == NET_ROOT_DISK || NetRoot->Type == NET_ROOT_WILD)
+ {
+ if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE)
+ {
+ UNIMPLEMENTED;
+ IsFile = TRUE;
+ }
+ }
+
+ /* We have to still be there! */
+ ASSERT(Fcb->UncleanCount != 0);
+ InterlockedDecrement((volatile long *)&Fcb->UncleanCount);
+
+ if (BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
+ {
+ --Fcb->UncachedUncleanCount;
+ }
+
+ /* Inform mini-rdr about ongoing cleanup */
+ MINIRDR_CALL(Status, Context, Fcb->MRxDispatch, MRxCleanupFobx, (Context));
+
+ ASSERT(Fobx->SrvOpen->UncleanFobxCount != 0);
+ --Fobx->SrvOpen->UncleanFobxCount;
+
+ /* Flush cache */
+ if (DisableFlushOnCleanup)
+ {
+ /* Only if we're the last standing */
+ if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL &&
+ Fcb->UncleanCount == Fcb->UncachedUncleanCount)
+ {
+ DPRINT1("Flushing %p due to last cached handle cleanup\n", Context);
+ RxFlushFcbInSystemCache(Fcb, TRUE);
+ }
+ }
+ else
+ {
+ /* Always */
+ if (Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
+ {
+ DPRINT1("Flushing %p on cleanup\n", Context);
+ RxFlushFcbInSystemCache(Fcb, TRUE);
+ }
+ }
+
+ /* If only remaining uncached & unclean, then flush and purge */
+ if (!BooleanFlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
+ {
+ if (Fcb->UncachedUncleanCount != 0)
+ {
+ if (Fcb->UncachedUncleanCount == Fcb->UncleanCount &&
+ Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)
+ {
+ DPRINT1("Flushing FCB in system cache for %p\n", Context);
+ RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, TRUE);
+ }
+ }
+ }
+
+ /* If purge required, flush */
+ if (!OneLeft && NeedPurge)
+ {
+ DPRINT1("Flushing FCB in system cache for %p\n", Context);
+ RxFlushFcbInSystemCache(Fcb, TRUE);
+ }
+
+ /* If it was a file, drop cache */
+ if (IsFile)
+ {
+ DPRINT1("Uninit cache map for file\n");
+ RxUninitializeCacheMap(Context, FileObject, TruncateSize);
+ }
+
+ /* If that's the one left, or if it needs purge, flush */
+ if (OneLeft || NeedPurge)
+ {
+ RxPurgeFcbInSystemCache(Fcb, NULL, 0, FALSE, !OneLeft);
+ /* Also remove from FCB table */
+ if (OneLeft)
+ {
+ RxRemoveNameNetFcb(Fcb);
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ FcbTableAcquired = FALSE;
+ }
+ }
+
+ /* Remove any share access */
+ if (OpenCount != 0 && NetRoot->Type == NET_ROOT_DISK)
+ {
+ RxRemoveShareAccess(FileObject, &Fcb->ShareAccess, "Cleanup the share access", "ClnUpShr");
+ }
+
+ /* In case there's caching, on a file, update file metadata */
+ if (NodeType(Fcb) == RDBSS_NTC_STORAGE_TYPE_FILE && BooleanFlagOn(Fobx->Flags, 0x20000000) &&
+ BooleanFlagOn(Fcb->FcbState, FCB_STATE_WRITECACHING_ENABLED) && !BooleanFlagOn(Fobx->pSrvOpen->Flags, SRVOPEN_FLAG_DONTUSE_WRITE_CACHING))
+ {
+ UNIMPLEMENTED;
+ }
+
+ /* We're clean! */
+ SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
+
+ FcbAcquired = FALSE;
+ RxReleaseFcb(Context, Fcb);
+ }
+ _SEH2_FINALLY
+ {
+ if (FcbAcquired)
+ {
+ RxReleaseFcb(Context, Fcb);
+ }
+
+ if (FcbTableAcquired)
+ {
+ RxReleaseFcbTableLock(&NetRoot->FcbTable);
+ }
+ }
+ _SEH2_END;
+
+ return Status;