📄 cleanup.c
字号:
//
if (!FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE) &&
(Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart)) {
ULONG ValidDataLength;
ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
if (ValidDataLength < Fcb->ValidDataToDisk) {
ValidDataLength = Fcb->ValidDataToDisk;
}
//
// Recheck, VDD can be >= FS
//
if (ValidDataLength < Fcb->Header.FileSize.LowPart) {
try {
(VOID)FatZeroData( IrpContext,
Vcb,
FileObject,
ValidDataLength,
Fcb->Header.FileSize.LowPart -
ValidDataLength );
//
// Since we just zeroed this, we can now bump
// up VDL in the Fcb.
//
Fcb->ValidDataToDisk =
Fcb->Header.ValidDataLength.LowPart =
Fcb->Header.FileSize.LowPart;
//
// We inform Cc of the motion so that the cache map is updated.
// This prevents optimized zero-page faults in case the cache
// structures are re-used for another handle before they are torn
// down by our soon-to-occur uninitialize. If they were, a noncached
// producer could write into the region we just zeroed and Cc would
// be none the wiser, then our async cached reader comes in and takes
// the optimized path, and we get bad (zero) data.
//
// If this was memory mapped, we don't have to (can't) tell Cc, it'll
// figure it out when a cached handle is opened.
//
if (CcIsFileCached( FileObject )) {
CcSetFileSizes( FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
}
} except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
}
}
}
//
// See if we are supposed to truncate the file on the last
// close. If we cannot wait we'll ship this off to the fsp
//
try {
if (FlagOn(Fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE)) {
DebugTrace(0, Dbg, "truncate file allocation\n", 0);
if (Vcb->VcbCondition == VcbGood) {
FatTruncateFileAllocation( IrpContext,
Fcb,
Fcb->Header.FileSize.LowPart );
}
//
// We also have to get rid of the Cache Map because
// this is the only way we have of trashing the
// truncated pages.
//
LocalTruncateSize = Fcb->Header.FileSize;
TruncateSize = &LocalTruncateSize;
//
// Mark the Fcb as having now been truncated, just incase
// we have to reship this off to the fsp.
//
Fcb->FcbState &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
}
//
// Now check again if we are to delete the file and if
// so then we remove the file from the disk.
//
if (FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Header.AllocationSize.LowPart == 0) {
DebugTrace(0, Dbg, "Delete File\n", 0);
//
// Now tunnel and delete the dirent
//
FatTunnelFcbOrDcb( Fcb, Ccb );
FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
//
// Report that we have removed an entry.
//
FatNotifyReportChange( IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED );
}
} except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
if (FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE)) {
//
// Remove the entry from the splay table. This will
// ensure that we will not collide with the Fcb if the
// user wants to recreate the same file over again
// before we get a close irp.
//
// Note that we remove the name even if we couldn't
// truncate the allocation and remove the dirent above.
//
FatRemoveNames( IrpContext, Fcb );
}
}
}
//
// We've just finished everything associated with an unclean
// fcb so now decrement the unclean count before releasing
// the resource.
//
ASSERT( Fcb->UncleanCount != 0 );
Fcb->UncleanCount -= 1;
if (!FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED )) {
ASSERT( Fcb->NonCachedUncleanCount != 0 );
Fcb->NonCachedUncleanCount -= 1;
}
//
// If this was the last cached open, and there are open
// non-cached handles, attempt a flush and purge operation
// to avoid cache coherency overhead from these non-cached
// handles later. We ignore any I/O errors from the flush.
//
if (FlagOn( FileObject->Flags, FO_CACHE_SUPPORTED ) &&
(Fcb->NonCachedUncleanCount != 0) &&
(Fcb->NonCachedUncleanCount == Fcb->UncleanCount) &&
(Fcb->NonPaged->SectionObjectPointers.DataSectionObject != NULL)) {
CcFlushCache( &Fcb->NonPaged->SectionObjectPointers, NULL, 0, NULL );
//
// Grab and release PagingIo to serialize ourselves with the lazy writer.
// This will work to ensure that all IO has completed on the cached
// data and we will succesfully tear away the cache section.
//
ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
ExReleaseResourceLite( Fcb->Header.PagingIoResource );
CcPurgeCacheSection( &Fcb->NonPaged->SectionObjectPointers,
NULL,
0,
FALSE );
}
//
// If the file is invalid, hint to the cache that we should throw everything out.
//
if ( Fcb->FcbCondition == FcbBad ) {
TruncateSize = &FatLargeZero;
}
//
// Cleanup the cache map
//
CcUninitializeCacheMap( FileObject, TruncateSize, NULL );
break;
default:
FatBugCheck( TypeOfOpen, 0, 0 );
}
//
// We must clean up the share access at this time, since we may not
// get a Close call for awhile if the file was mapped through this
// File Object.
//
if (ShareAccess != NULL) {
DebugTrace(0, Dbg, "Cleanup the Share access\n", 0);
IoRemoveShareAccess( FileObject, ShareAccess );
}
if (TypeOfOpen == UserFileOpen) {
//
// Coordinate the cleanup operation with the oplock state.
// Cleanup operations can always cleanup immediately.
//
FsRtlCheckOplock( &Fcb->Specific.Fcb.Oplock,
Irp,
IrpContext,
NULL,
NULL );
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
}
//
// First set the FO_CLEANUP_COMPLETE flag.
//
SetFlag( FileObject->Flags, FO_CLEANUP_COMPLETE );
Status = STATUS_SUCCESS;
//
// Now unpin any repinned Bcbs.
//
FatUnpinRepinnedBcbs( IrpContext );
//
// If this was deferred flush media, flush the volume.
// We used to do this in lieu of write through for all removable
// media.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
//
// Flush the file.
//
if ((TypeOfOpen == UserFileOpen) &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
Status = FatFlushFile( IrpContext, Fcb, Flush );
}
//
// If that worked ok, then see if we should flush the FAT as well.
//
if (NT_SUCCESS(Status) && Fcb && !FatIsFat12( Vcb) &&
FlagOn( Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {
Status = FatFlushFat( IrpContext, Vcb);
}
if (!NT_SUCCESS(Status)) {
FatNormalizeAndRaiseStatus( IrpContext, Status );
}
}
} finally {
DebugUnwind( FatCommonCleanup );
if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
if (SendUnlockNotification) {
FsRtlNotifyVolumeEvent( FileObject, FSRTL_VOLUME_UNLOCK );
}
//
// If this is a normal termination then complete the request
//
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatCommonCleanup -> %08lx\n", Status);
}
return Status;
}
VOID
FatAutoUnlock (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb
)
{
KIRQL SavedIrql;
//
// Unlock the volume.
//
IoAcquireVpbSpinLock( &SavedIrql );
ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED );
Vcb->VcbState &= ~VCB_STATE_FLAG_LOCKED;
Vcb->FileObjectWithVcbLocked = NULL;
IoReleaseVpbSpinLock( SavedIrql );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -