ReactOS  0.4.14-dev-1233-gf5658fd
cleanup.c File Reference
#include "fatprocs.h"
Include dependency graph for cleanup.c:

Go to the source code of this file.

Macros

#define BugCheckFileId   (FAT_BUG_CHECK_CLEANUP)
 
#define Dbg   (DEBUG_TRACE_CLEANUP)
 

Functions

VOID FatAutoUnlock (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
 
 _Function_class_ (IRP_MJ_CLEANUP)
 
 _Requires_lock_held_ (_Global_critical_region_)
 

Macro Definition Documentation

◆ BugCheckFileId

#define BugCheckFileId   (FAT_BUG_CHECK_CLEANUP)

Definition at line 23 of file cleanup.c.

◆ Dbg

#define Dbg   (DEBUG_TRACE_CLEANUP)

Definition at line 29 of file cleanup.c.

Function Documentation

◆ _Function_class_()

_Function_class_ ( IRP_MJ_CLEANUP  )

Definition at line 47 of file cleanup.c.

76 {
78  PIRP_CONTEXT IrpContext = NULL;
79 
81 
82  PAGED_CODE();
83 
84  //
85  // If we were called with our file system device object instead of a
86  // volume device object, just complete this request with STATUS_SUCCESS
87  //
88 
89  if ( FatDeviceIsFatFsdo( VolumeDeviceObject)) {
90 
91  Irp->IoStatus.Status = STATUS_SUCCESS;
92  Irp->IoStatus.Information = FILE_OPENED;
93 
95 
96  return STATUS_SUCCESS;
97  }
98 
99  DebugTrace(+1, Dbg, "FatFsdCleanup\n", 0);
100 
101  //
102  // Call the common Cleanup routine, with blocking allowed.
103  //
104 
106 
108 
109  _SEH2_TRY {
110 
111  IrpContext = FatCreateIrpContext( Irp, TRUE );
112 
113  Status = FatCommonCleanup( IrpContext, Irp );
114 
116 
117  //
118  // We had some trouble trying to perform the requested
119  // operation, so we'll abort the I/O request with
120  // the error status that we get back from the
121  // execption code
122  //
123 
124  Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
125  } _SEH2_END;
126 
127  if (TopLevel) { IoSetTopLevelIrp( NULL ); }
128 
130 
131  //
132  // And return to our caller
133  //
134 
135  DebugTrace(-1, Dbg, "FatFsdCleanup -> %08lx\n", Status);
136 
137  UNREFERENCED_PARAMETER( VolumeDeviceObject );
138 
139  return Status;
140 }
#define TRUE
Definition: types.h:120
#define FsRtlEnterFileSystem
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
#define FsRtlExitFileSystem
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
LONG NTSTATUS
Definition: precomp.h:26
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3083
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define FILE_OPENED
Definition: nt_native.h:769
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2401
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2300
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define Dbg
Definition: cleanup.c:29
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:2938

◆ _Requires_lock_held_()

_Requires_lock_held_ ( _Global_critical_region_  )

Definition at line 143 of file cleanup.c.

178 {
180 
182 
184 
186  PVCB Vcb;
187  PFCB Fcb;
188  PCCB Ccb;
189 
190  BOOLEAN SendUnlockNotification = FALSE;
191 
193 
194  PLARGE_INTEGER TruncateSize = NULL;
195  LARGE_INTEGER LocalTruncateSize;
196 
197  BOOLEAN AcquiredVcb = FALSE;
198  BOOLEAN AcquiredFcb = FALSE;
199 
200 #if (NTDDI_VERSION >= NTDDI_WIN8)
201  BOOLEAN ProcessingDeleteOnClose = FALSE;
202 #endif
203 
204  PAGED_CODE();
205 
207 
208  DebugTrace(+1, Dbg, "FatCommonCleanup\n", 0);
209  DebugTrace( 0, Dbg, "Irp = %p\n", Irp);
210  DebugTrace( 0, Dbg, "->FileObject = %p\n", IrpSp->FileObject);
211 
212  //
213  // Extract and decode the file object
214  //
215 
218 
219  //
220  // Special case the unopened file object. This will occur only when
221  // we are initializing Vcb and IoCreateStreamFileObject is being
222  // called.
223  //
224 
226 
227  DebugTrace(0, Dbg, "Unopened File Object\n", 0);
228 
229  FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
230 
231  DebugTrace(-1, Dbg, "FatCommonCleanup -> STATUS_SUCCESS\n", 0);
232  return STATUS_SUCCESS;
233  }
234 
235  //
236  // If this is not our first time through (for whatever reason)
237  // only see if we have to flush the file.
238  //
239 
240  if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE )) {
241 
242  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
245  (TypeOfOpen == UserFileOpen)) {
246 
247  //
248  // Flush the file.
249  //
250 
251  Status = FatFlushFile( IrpContext, Fcb, Flush );
252 
253  if (!NT_SUCCESS(Status)) {
254 
255  FatNormalizeAndRaiseStatus( IrpContext, Status );
256  }
257  }
258 
259  FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
260 
261  DebugTrace(-1, Dbg, "FatCommonCleanup -> STATUS_SUCCESS\n", 0);
262  return STATUS_SUCCESS;
263  }
264 
265  //
266  // If we call change the allocation or call CcUninitialize,
267  // we have to take the Fcb exclusive
268  //
269 
271 
272  NT_ASSERT( Fcb != NULL );
273 
274  (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
275 
276  AcquiredFcb = TRUE;
277 
278  //
279  // Do a check here if this was a DELETE_ON_CLOSE FileObject, and
280  // set the Fcb flag appropriately.
281  //
282 
284 
286 
287  //
288  // Transfer the delete-on-close state to the FCB. We do this rather
289  // than leave the CCB_FLAG_DELETE_ON_CLOSE flag set so that if we
290  // end up breaking an oplock and come in again we won't try to break
291  // the oplock again (and again, and again...).
292  //
293 
296 
297 #if (NTDDI_VERSION >= NTDDI_WIN8)
298  ProcessingDeleteOnClose = TRUE;
299 #endif
300 
301  //
302  // Report this to the dir notify package for a directory.
303  //
304 
305  if (TypeOfOpen == UserDirectoryOpen) {
306 
307 #ifdef _MSC_VER
308 #pragma prefast( suppress:6309, "FullDirectoryName may be NULL if NotifyIrp is also NULL. this indicates the object is being deleted." )
309 #endif
310  FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
311  &Vcb->DirNotifyList,
312  FileObject->FsContext,
313  NULL,
314  FALSE,
315  FALSE,
316  0,
317  NULL,
318  NULL,
319  NULL );
320  }
321  }
322 
323  //
324  // Now if we may delete the file, drop the Fcb and acquire the Vcb
325  // first. Note that while we own the Fcb exclusive, a file cannot
326  // become DELETE_ON_CLOSE and cannot be opened via CommonCreate.
327  //
328 
329  if ((Fcb->UncleanCount == 1) &&
331  (Fcb->FcbCondition != FcbBad) &&
333 
334  FatReleaseFcb( IrpContext, Fcb );
335  AcquiredFcb = FALSE;
336 
337  (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
338  AcquiredVcb = TRUE;
339 
340  (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
341  AcquiredFcb = TRUE;
342  }
343  }
344 
345  //
346  // For user DASD cleanups, grab the Vcb exclusive.
347  //
348 
349  if (TypeOfOpen == UserVolumeOpen) {
350 
351  (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
352  AcquiredVcb = TRUE;
353  }
354 
355  //
356  // Complete any Notify Irps on this file handle.
357  //
358 
359  if (TypeOfOpen == UserDirectoryOpen) {
360 
361  FsRtlNotifyCleanup( Vcb->NotifySync,
362  &Vcb->DirNotifyList,
363  Ccb );
364  }
365 
366  //
367  // Determine the Fcb state, Good or Bad, for better or for worse.
368  //
369  // We can only read the volume file if VcbCondition is good.
370  //
371 
372  if ( Fcb != NULL) {
373 
374  //
375  // Stop any raises from FatVerifyFcb, unless it is REAL bad.
376  //
377 
378  _SEH2_TRY {
379 
380  _SEH2_TRY {
381 
382  FatVerifyFcb( IrpContext, Fcb );
383 
386 
387  FatResetExceptionState( IrpContext );
388  } _SEH2_END;
389 
390  } _SEH2_FINALLY {
391 
392  if ( _SEH2_AbnormalTermination() ) {
393 
394  //
395  // We will be raising out of here.
396  //
397 
398  if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
399  if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
400  }
401  } _SEH2_END;
402  }
403 
404  _SEH2_TRY {
405 
406 #if (NTDDI_VERSION >= NTDDI_WIN8)
407 
408  //
409  // See if this is a delete-on-close handle on a file or empty directory.
410  // If so we may need to break an oplock. We do this in the try block
411  // so that resources will be properly released.
412  //
413 
414  if (ProcessingDeleteOnClose &&
416  ((NodeType( Fcb ) != FAT_NTC_DCB) ||
417  FatIsDirectoryEmpty( IrpContext, Fcb ))) {
418 
419  Status = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
420  Irp,
421  OPLOCK_FLAG_CLOSING_DELETE_ON_CLOSE,
422  IrpContext,
424  FatPrePostIrp );
425 
426  if (Status != STATUS_SUCCESS) {
427 
428  if (Status == STATUS_PENDING) {
429 
431  try_return( Status );
432 
433  } else {
434 
435  FatNormalizeAndRaiseStatus( IrpContext, Status );
436  }
437  }
438  }
439 #endif
440 
441  //
442  // Case on the type of open that we are trying to cleanup.
443  // For all cases we need to set the share access to point to the
444  // share access variable (if there is one). After the switch
445  // we then remove the share access and complete the Irp.
446  // In the case of UserFileOpen we actually have a lot more work
447  // to do and we have the FsdLockControl complete the Irp for us.
448  //
449 
450  switch (TypeOfOpen) {
451 
452  case DirectoryFile:
453  case VirtualVolumeFile:
454 
455  DebugTrace(0, Dbg, "Cleanup VirtualVolumeFile/DirectoryFile\n", 0);
456 
457  ShareAccess = NULL;
458 
459  break;
460 
461 
462  case UserVolumeOpen:
463 
464  DebugTrace(0, Dbg, "Cleanup UserVolumeOpen\n", 0);
465 
467 
468  FatCheckForDismount( IrpContext, Vcb, TRUE );
469 
470  //
471  // If this handle had write access, and actually wrote something,
472  // flush the device buffers, and then set the verify bit now
473  // just to be safe (in case there is no dismount).
474  //
475 
476  } else if (FileObject->WriteAccess &&
478 
479  (VOID)FatHijackIrpAndFlushDevice( IrpContext,
480  Irp,
481  Vcb->TargetDeviceObject );
482 
483  SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
484  }
485 
486  //
487  // If the volume is locked by this file object then release
488  // the volume and send notification.
489  //
490 
491  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED) &&
492  (Vcb->FileObjectWithVcbLocked == FileObject)) {
493 
494  FatAutoUnlock( IrpContext, Vcb );
495  SendUnlockNotification = TRUE;
496  }
497 
498  ShareAccess = &Vcb->ShareAccess;
499 
500  break;
501 
502  case EaFile:
503 
504  DebugTrace(0, Dbg, "Cleanup EaFileObject\n", 0);
505 
506  ShareAccess = NULL;
507 
508  break;
509 
510  case UserDirectoryOpen:
511 
512  DebugTrace(0, Dbg, "Cleanup UserDirectoryOpen\n", 0);
513 
515 
516  //
517  // Determine here if we should try do delayed close.
518  //
519 
520  if ((Fcb->UncleanCount == 1) &&
521  (Fcb->OpenCount == 1) &&
522  (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0) &&
524  Fcb->FcbCondition == FcbGood) {
525 
526  //
527  // Delay our close.
528  //
529 
531  }
532 
533  //
534  // Clear the deny defrag bit, if the handle we're cleaning up was the one that set it.
535  //
536 
538 
541  }
542 
543  if ((VcbGood == Vcb->VcbCondition) &&
544  !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN)) {
545 
546  FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
547 
548  //
549  // If the directory has a unclean count of 1 then we know
550  // that this is the last handle for the file object. If
551  // we are supposed to delete it, do so.
552  //
553 
554  if ((Fcb->UncleanCount == 1) &&
555  (NodeType(Fcb) == FAT_NTC_DCB) &&
557  (Fcb->FcbCondition == FcbGood) &&
559 
560  if (!FatIsDirectoryEmpty(IrpContext, Fcb)) {
561 
562  //
563  // If there are files in the directory at this point,
564  // forget that we were trying to delete it.
565  //
566 
568 
569  } else {
570 
571 #if (NTDDI_VERSION >= NTDDI_WIN8)
572  NTSTATUS BreakStatus;
573 #endif
574 
575  //
576  // Even if something goes wrong, we cannot turn back!
577  //
578 
579  _SEH2_TRY {
580 
581  DELETE_CONTEXT DeleteContext;
582 
583 
584  //
585  // Before truncating file allocation remember this
586  // info for FatDeleteDirent.
587  //
588 
589  DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
590  DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
591 
592  //
593  // Synchronize here with paging IO
594  //
595 
596  (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
597  TRUE );
598 
599  Fcb->Header.FileSize.LowPart = 0;
600 
601  ExReleaseResourceLite( Fcb->Header.PagingIoResource );
602 
603  //
604  // Truncate the file allocation down to zero
605  //
606 
607  DebugTrace(0, Dbg, "Delete File allocation\n", 0);
608 
609  FatTruncateFileAllocation( IrpContext, Fcb, 0 );
610 
611  if (Fcb->Header.AllocationSize.LowPart == 0) {
612 
613  //
614  // Tunnel and remove the dirent for the directory
615  //
616 
617  DebugTrace(0, Dbg, "Delete the directory dirent\n", 0);
618 
620 
621  FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
622 
623  //
624  // Report that we have removed an entry.
625  //
626 
627  FatNotifyReportChange( IrpContext,
628  Vcb,
629  Fcb,
632  }
633 
636 
637  FatResetExceptionState( IrpContext );
638  } _SEH2_END;
639 
640  //
641  // Remove the entry from the name table.
642  // This will ensure that
643  // we will not collide with the Dcb if the user wants
644  // to recreate the same file over again before we
645  // get a close irp.
646  //
647 
648  FatRemoveNames( IrpContext, Fcb );
649 
650 #if (NTDDI_VERSION >= NTDDI_WIN8)
651  //
652  // We've removed the names so break any parent directory oplock.
653  // Directory oplock breaks are always advisory, so we will never
654  // block/get STATUS_PENDING here.
655  //
656 
657  BreakStatus = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
658  Irp,
659  (OPLOCK_FLAG_PARENT_OBJECT |
660  OPLOCK_FLAG_REMOVING_FILE_OR_LINK),
661  NULL,
662  NULL,
663  NULL );
664 
665  ASSERT( BreakStatus != STATUS_PENDING );
666 #endif
667  }
668  }
669  }
670 
671  //
672  // Decrement the unclean count.
673  //
674 
675  NT_ASSERT( Fcb->UncleanCount != 0 );
676  Fcb->UncleanCount -= 1;
677 
678  break;
679 
680  case UserFileOpen:
681 
682  DebugTrace(0, Dbg, "Cleanup UserFileOpen\n", 0);
683 
685 
686  //
687  // Determine here if we should do a delayed close.
688  //
689 
690  if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
691  (FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
692  (Fcb->UncleanCount == 1) &&
693  (Fcb->OpenCount == 1) &&
696  Fcb->FcbCondition == FcbGood) {
697 
698  //
699  // Delay our close.
700  //
701 
703  }
704 
705  //
706  // Clear the deny defrag bit, if the handle we're cleaning up was the one that set it.
707  //
708 
710 
713  }
714 
715  //
716  // Unlock all outstanding file locks.
717  //
718 
719  (VOID) FsRtlFastUnlockAll( &Fcb->Specific.Fcb.FileLock,
720  FileObject,
722  NULL );
723 
724 
725 
726  //
727  // We can proceed with on-disk updates only if the volume is mounted
728  // and we can still write to it if it hasn't been shutdown. Remember that
729  // we toss all sections in the failed-verify and dismount cases.
730  //
731 
732  if ((Vcb->VcbCondition == VcbGood) &&
733  !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN)) {
734 
735  if (Fcb->FcbCondition == FcbGood) {
736 
737 
738  FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
739 
740  }
741 
742  //
743  // If the file has a unclean count of 1 then we know
744  // that this is the last handle for the file object.
745  //
746 
747  if ( (Fcb->UncleanCount == 1) && (Fcb->FcbCondition == FcbGood) ) {
748 
749  DELETE_CONTEXT DeleteContext;
750 
751  //
752  // Check if we should be deleting the file. The
753  // delete operation really deletes the file but
754  // keeps the Fcb around for close to do away with.
755  //
756 
759 
760  //
761  // Before truncating file allocation remember this
762  // info for FatDeleteDirent.
763  //
764 
765  DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
766  DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
767 
768  DebugTrace(0, Dbg, "Delete File allocation\n", 0);
769 
770  //
771  // Synchronize here with paging IO
772  //
773 
774  (VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
775  TRUE );
776 
777  Fcb->Header.FileSize.LowPart = 0;
778  Fcb->Header.ValidDataLength.LowPart = 0;
779  Fcb->ValidDataToDisk = 0;
780 
781  ExReleaseResourceLite( Fcb->Header.PagingIoResource );
782 
783  _SEH2_TRY {
784 
785  FatSetFileSizeInDirent( IrpContext, Fcb, NULL );
786 
789 
790  FatResetExceptionState( IrpContext );
791  } _SEH2_END;
792 
794 
795  } else {
796 
797  //
798  // We must zero between ValidDataLength and FileSize
799  //
800 
802  (Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart)) {
803 
804  ULONG ValidDataLength;
805 
806  ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
807 
808  if (ValidDataLength < Fcb->ValidDataToDisk) {
809  ValidDataLength = Fcb->ValidDataToDisk;
810  }
811 
812  //
813  // Recheck, VDD can be >= FS
814  //
815 
816  if (ValidDataLength < Fcb->Header.FileSize.LowPart) {
817 
818  _SEH2_TRY {
819 
820  (VOID)FatZeroData( IrpContext,
821  Vcb,
822  FileObject,
823  ValidDataLength,
824  Fcb->Header.FileSize.LowPart -
825  ValidDataLength );
826 
827  //
828  // Since we just zeroed this, we can now bump
829  // up VDL in the Fcb.
830  //
831 
833  Fcb->Header.ValidDataLength.LowPart =
834  Fcb->Header.FileSize.LowPart;
835 
836  //
837  // We inform Cc of the motion so that the cache map is updated.
838  // This prevents optimized zero-page faults in case the cache
839  // structures are re-used for another handle before they are torn
840  // down by our soon-to-occur uninitialize. If they were, a noncached
841  // producer could write into the region we just zeroed and Cc would
842  // be none the wiser, then our async cached reader comes in and takes
843  // the optimized path, and we get bad (zero) data.
844  //
845  // If this was memory mapped, we don't have to (can't) tell Cc, it'll
846  // figure it out when a cached handle is opened.
847  //
848 
849  if (CcIsFileCached( FileObject )) {
850  CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
851  }
852 
855 
856  FatResetExceptionState( IrpContext );
857  } _SEH2_END;
858  }
859  }
860  }
861 
862  //
863  // See if we are supposed to truncate the file on the last
864  // close. If we cannot wait we'll ship this off to the fsp
865  //
866 
867  _SEH2_TRY {
868 
870 
871  DebugTrace(0, Dbg, "truncate file allocation\n", 0);
872 
873  if (Vcb->VcbCondition == VcbGood) {
874 
875 
876  FatTruncateFileAllocation( IrpContext,
877  Fcb,
878  Fcb->Header.FileSize.LowPart );
879 
880 
881  }
882 
883  //
884  // We also have to get rid of the Cache Map because
885  // this is the only way we have of trashing the
886  // truncated pages.
887  //
888 
889  LocalTruncateSize = Fcb->Header.FileSize;
890  TruncateSize = &LocalTruncateSize;
891 
892  //
893  // Mark the Fcb as having now been truncated, just incase
894  // we have to reship this off to the fsp.
895  //
896 
898  }
899 
900  //
901  // Now check again if we are to delete the file and if
902  // so then we remove the file from the disk.
903  //
904 
906  Fcb->Header.AllocationSize.LowPart == 0) {
907 
908  DebugTrace(0, Dbg, "Delete File\n", 0);
909 
910  //
911  // Now tunnel and delete the dirent
912  //
913 
915 
916  FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
917 
918  //
919  // Report that we have removed an entry.
920  //
921 
922  FatNotifyReportChange( IrpContext,
923  Vcb,
924  Fcb,
927  }
928 
931 
932  FatResetExceptionState( IrpContext );
933  } _SEH2_END;
934 
936 
937 #if (NTDDI_VERSION >= NTDDI_WIN8)
938  NTSTATUS BreakStatus;
939 #endif
940  //
941  // Remove the entry from the splay table. This will
942  // ensure that we will not collide with the Fcb if the
943  // user wants to recreate the same file over again
944  // before we get a close irp.
945  //
946  // Note that we remove the name even if we couldn't
947  // truncate the allocation and remove the dirent above.
948  //
949 
950  FatRemoveNames( IrpContext, Fcb );
951 
952 #if (NTDDI_VERSION >= NTDDI_WIN8)
953  //
954  // We've removed the names so break any parent directory oplock.
955  // Directory oplock breaks are always advisory, so we will never
956  // block/get STATUS_PENDING here.
957  //
958 
959  BreakStatus = FsRtlCheckOplockEx( FatGetFcbOplock(Fcb->ParentDcb),
960  Irp,
961  (OPLOCK_FLAG_PARENT_OBJECT |
962  OPLOCK_FLAG_REMOVING_FILE_OR_LINK),
963  NULL,
964  NULL,
965  NULL );
966 
967  ASSERT( BreakStatus != STATUS_PENDING );
968 #endif
969  }
970  }
971  }
972 
973  //
974  // We've just finished everything associated with an unclean
975  // fcb so now decrement the unclean count before releasing
976  // the resource.
977  //
978 
979  NT_ASSERT( Fcb->UncleanCount != 0 );
980  Fcb->UncleanCount -= 1;
981  if (!FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED )) {
984  }
985 
986  //
987  // If this was the last cached open, and there are open
988  // non-cached handles, attempt a flush and purge operation
989  // to avoid cache coherency overhead from these non-cached
990  // handles later. We ignore any I/O errors from the flush.
991  //
992 
993  if (FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED ) &&
994  (Fcb->NonCachedUncleanCount != 0) &&
997 
999 
1000  //
1001  // Grab and release PagingIo to serialize ourselves with the lazy writer.
1002  // This will work to ensure that all IO has completed on the cached
1003  // data and we will succesfully tear away the cache section.
1004  //
1005 
1006  ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
1007  ExReleaseResourceLite( Fcb->Header.PagingIoResource );
1008 
1010  NULL,
1011  0,
1012  FALSE );
1013  }
1014 
1015  //
1016  // If the file is invalid, hint to the cache that we should throw everything out.
1017  //
1018 
1019  if ( Fcb->FcbCondition == FcbBad ) {
1020 
1021  TruncateSize = &FatLargeZero;
1022  }
1023 
1024  //
1025  // Cleanup the cache map
1026  //
1027 
1028  CcUninitializeCacheMap( FileObject, TruncateSize, NULL );
1029 
1030  break;
1031 
1032  default:
1033 
1034 #ifdef _MSC_VER
1035 #pragma prefast( suppress: 28159, "if the type of open is unknown then things are very bad." )
1036 #endif
1037  FatBugCheck( TypeOfOpen, 0, 0 );
1038  }
1039 
1040  //
1041  // We must clean up the share access at this time, since we may not
1042  // get a Close call for awhile if the file was mapped through this
1043  // File Object.
1044  //
1045 
1046  if (ShareAccess != NULL) {
1047 
1048  DebugTrace(0, Dbg, "Cleanup the Share access\n", 0);
1050  }
1051 
1052  if ((TypeOfOpen == UserFileOpen)
1053 #if (NTDDI_VERSION >= NTDDI_WIN8)
1054  ||
1056 #endif
1057  ) {
1058 
1059  //
1060  // Coordinate the cleanup operation with the oplock state.
1061  // Cleanup operations can always cleanup immediately.
1062  //
1063 
1065  Irp,
1066  IrpContext,
1067  NULL,
1068  NULL );
1069 
1070  Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
1071  }
1072 
1073  //
1074  // First set the FO_CLEANUP_COMPLETE flag.
1075  //
1076 
1078 
1080 
1081  //
1082  // Now unpin any repinned Bcbs.
1083  //
1084 
1085  FatUnpinRepinnedBcbs( IrpContext );
1086 
1087  //
1088  // If this was deferred flush media, flush the volume.
1089  // We used to do this in lieu of write through for all removable
1090  // media.
1091  //
1092 
1093  if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
1094  !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
1095 
1096  //
1097  // Flush the file.
1098  //
1099 
1100  if ((TypeOfOpen == UserFileOpen) &&
1101  FlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
1102 
1103  Status = FatFlushFile( IrpContext, Fcb, Flush );
1104  }
1105 
1106  //
1107  // If that worked ok, then see if we should flush the FAT as well.
1108  //
1109 
1110  if (NT_SUCCESS(Status) && Fcb && !FatIsFat12( Vcb) &&
1112 
1113  Status = FatFlushFat( IrpContext, Vcb);
1114 
1115  //
1116  // Also flush the parent directory.
1117  //
1118 
1119  if (NT_SUCCESS(Status) && (Fcb->ParentDcb != NULL)) {
1120 
1121  Status = FatFlushFile( IrpContext, Fcb->ParentDcb, Flush );
1122  }
1123  }
1124 
1125  if (!NT_SUCCESS(Status)) {
1126 
1127  FatNormalizeAndRaiseStatus( IrpContext, Status );
1128  }
1129  }
1130 
1131 #if (NTDDI_VERSION >= NTDDI_WIN8)
1132 
1133  try_exit: NOTHING;
1134 
1135 #endif
1136 
1137  } _SEH2_FINALLY {
1138 
1139  DebugUnwind( FatCommonCleanup );
1140 
1141  if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
1142  if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
1143 
1144  if (SendUnlockNotification) {
1145 
1147  }
1148 
1149  //
1150  // If this is a normal termination then complete the request
1151  //
1152 
1153  if (!_SEH2_AbnormalTermination() &&
1154  (Status != STATUS_PENDING)) {
1155 
1156  FatCompleteRequest( IrpContext, Irp, Status );
1157  }
1158 
1159  DebugTrace(-1, Dbg, "FatCommonCleanup -> %08lx\n", Status);
1160  } _SEH2_END;
1161 
1162  return Status;
1163 }
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:384
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define TRUE
Definition: types.h:120
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2983
struct _FCB::@710::@713 Fcb
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
#define VCB_STATE_FLAG_DEFERRED_FLUSH
Definition: fatstruc.h:567
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:931
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2621
VOID NTAPI FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
Definition: notify.c:1458
_In_ PIRP Irp
Definition: csq.h:116
Definition: cdstruc.h:908
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
Definition: cdstruc.h:1073
#define FCB_STATE_FLUSH_FAT
Definition: fatstruc.h:1196
#define FatNotifyReportChange(I, V, F, FL, A)
Definition: fatprocs.h:2156
VOID NTAPI FatOplockComplete(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:35
#define FatIsFat12(VCB)
Definition: fatprocs.h:1439
LONG NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
Definition: cdstruc.h:504
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:569
#define FILE_NOTIFY_CHANGE_FILE_NAME
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: fatstruc.h:728
#define FILE_NOTIFY_CHANGE_DIR_NAME
struct _FCB * ParentDcb
Definition: fatstruc.h:835
#define CCB_FLAG_DELETE_ON_CLOSE
Definition: fatstruc.h:1288
ULONG FirstClusterOfFile
Definition: fatstruc.h:1663
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK _In_ USHORT ShareAccess
Definition: create.c:4157
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3477
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
VOID NTAPI FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:635
#define CCB_FLAG_DENY_DEFRAG
Definition: fatstruc.h:1351
#define FO_FILE_MODIFIED
Definition: iotypes.h:1745
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
Definition: Header.h:8
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1194
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1647
#define CcIsFileCached(FO)
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PNON_PAGED_FCB NonPaged
Definition: fatstruc.h:810
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FILE_ACTION_REMOVED
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
NodeType
Definition: Node.h:5
#define FCB_STATE_TRUNCATE_ON_CLOSE
Definition: fatstruc.h:1193
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define FCB_STATE_DENY_DEFRAG
Definition: fatstruc.h:1216
VOID FatRemoveNames(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: splaysup.c:222
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
#define NTDDI_VERSION
Definition: k32.h:33
#define CCB_FLAG_COMPLETE_DISMOUNT
Definition: fatstruc.h:1330
#define DebugUnwind(X)
Definition: fatdata.h:315
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1635
SHARE_ACCESS ShareAccess
Definition: cdstruc.h:1015
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
#define FatResetExceptionState(IRPCONTEXT)
Definition: fatprocs.h:2971
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:558
CLONG NonCachedUncleanCount
Definition: fatstruc.h:887
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1192
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define try_return(S)
Definition: cdprocs.h:2189
#define Vcb
Definition: cdprocs.h:1425
#define FCB_STATE_DELAY_CLOSE
Definition: fatstruc.h:1202
#define FatIsFileOplockable(F)
Definition: fatprocs.h:2839
FINISHED FatZeroData(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ULONG StartingZero, IN ULONG ByteCount)
Definition: cachesup.c:1659
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
* PFILE_OBJECT
Definition: iotypes.h:1955
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1738
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG Flags
Definition: ntfs.h:532
union _FCB::@710 Specific
#define VOID
Definition: acefi.h:82
CLONG UncleanCount
Definition: fatstruc.h:872
enum _TYPE_OF_OPEN TYPE_OF_OPEN
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:593
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1026
#define Dbg
Definition: cleanup.c:29
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
Status
Definition: gdiplustypes.h:24
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define VCB_STATE_FLAG_SHUTDOWN
Definition: fatstruc.h:562
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2813
_SEH2_END
Definition: create.c:4424
ULONG ValidDataToDisk
Definition: fatstruc.h:927
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:284
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1451
#define FatIsFastIoPossible(FCB)
Definition: fatprocs.h:2801
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1747
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:354
_SEH2_FINALLY
Definition: create.c:4395
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1631
CLONG OpenCount
Definition: fatstruc.h:880
#define FAT_NTC_DCB
Definition: nodetype.h:30
VOID FatTunnelFcbOrDcb(IN PFCB FcbOrDcb, IN PCCB Ccb OPTIONAL)
Definition: dirsup.c:652
ULONG FirstClusterOfFile
Definition: fatstruc.h:817
VOID FatAutoUnlock(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: cleanup.c:1166
unsigned int ULONG
Definition: retypes.h:1
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
NTSTATUS NTAPI FsRtlCheckOplock(IN POPLOCK Oplock, IN PIRP Irp, IN PVOID Context, IN POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine OPTIONAL, IN POPLOCK_FS_PREPOST_IRP PostIrpRoutine OPTIONAL)
Definition: oplock.c:1172
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define NTDDI_WIN8
Definition: sdkddkver.h:113
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2938
VOID NTAPI FatPrePostIrp(IN PVOID Context, IN PIRP Irp)
Definition: workque.c:91
#define IRP_CONTEXT_FLAG_CLEANUP_BREAKING_OPLOCK
Definition: fatstruc.h:1570
struct _FCB::@710::@712 Dcb
ULONG FcbState
Definition: cdstruc.h:977
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
#define NT_ASSERT
Definition: rtlfuncs.h:3312
FCB_CONDITION FcbCondition
Definition: fatstruc.h:849

◆ FatAutoUnlock()

VOID FatAutoUnlock ( IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb 
)

Definition at line 1166 of file cleanup.c.

1170 {
1171  KIRQL SavedIrql;
1172 
1173  //
1174  // Unlock the volume.
1175  //
1176 
1177  UNREFERENCED_PARAMETER( IrpContext );
1178 
1179  IoAcquireVpbSpinLock( &SavedIrql );
1180 
1181  ClearFlag( Vcb->Vpb->Flags, (VPB_LOCKED | VPB_DIRECT_WRITES_ALLOWED) );
1182 
1183  Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED;
1184  Vcb->FileObjectWithVcbLocked = NULL;
1185 
1186  IoReleaseVpbSpinLock( SavedIrql );
1187 }
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1209
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define VPB_LOCKED
Definition: iotypes.h:1765
smooth NULL
Definition: ftsmooth.c:416
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:558
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1769
#define Vcb
Definition: cdprocs.h:1425
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1220

Referenced by _Requires_lock_held_().