📄 cleanup.c
字号:
if ( Fcb != NULL) {
//
// Stop any raises from FatVerifyFcb, unless it is REAL bad.
//
try {
try {
FatVerifyFcb( IrpContext, Fcb );
} except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
} finally {
if ( AbnormalTermination() ) {
//
// We will be raising out of here.
//
if (AcquiredFcb) { FatReleaseFcb( IrpContext, Fcb ); }
if (AcquiredVcb) { FatReleaseVcb( IrpContext, Vcb ); }
}
}
}
try {
//
// Case on the type of open that we are trying to cleanup.
// For all cases we need to set the share access to point to the
// share access variable (if there is one). After the switch
// we then remove the share access and complete the Irp.
// In the case of UserFileOpen we actually have a lot more work
// to do and we have the FsdLockControl complete the Irp for us.
//
switch (TypeOfOpen) {
case DirectoryFile:
case VirtualVolumeFile:
DebugTrace(0, Dbg, "Cleanup VirtualVolumeFile/DirectoryFile\n", 0);
ShareAccess = NULL;
break;
case UserVolumeOpen:
DebugTrace(0, Dbg, "Cleanup UserVolumeOpen\n", 0);
if (FlagOn( Ccb->Flags, CCB_FLAG_COMPLETE_DISMOUNT )) {
FatCheckForDismount( IrpContext, Vcb, TRUE );
//
// If this handle had write access, and actually wrote something,
// flush the device buffers, and then set the verify bit now
// just to be safe (in case there is no dismount).
//
} else if (FileObject->WriteAccess &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED)) {
(VOID)FatHijackIrpAndFlushDevice( IrpContext,
Irp,
Vcb->TargetDeviceObject );
SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
}
//
// If the volume is locked by this file object then release
// the volume and send notification.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED) &&
(Vcb->FileObjectWithVcbLocked == FileObject)) {
FatAutoUnlock( IrpContext, Vcb );
SendUnlockNotification = TRUE;
}
ShareAccess = &Vcb->ShareAccess;
break;
case EaFile:
DebugTrace(0, Dbg, "Cleanup EaFileObject\n", 0);
ShareAccess = NULL;
break;
case UserDirectoryOpen:
DebugTrace(0, Dbg, "Cleanup UserDirectoryOpen\n", 0);
ShareAccess = &Fcb->ShareAccess;
//
// Determine here if we should try do delayed close.
//
if ((Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
(Fcb->Specific.Dcb.DirectoryFileOpenCount == 0) &&
!FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->FcbCondition == FcbGood) {
//
// Delay our close.
//
SetFlag( Fcb->FcbState, FCB_STATE_DELAY_CLOSE );
}
if (VcbGood == Vcb->VcbCondition) {
FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
}
//
// If the directory has a unclean count of 1 then we know
// that this is the last handle for the file object. If
// we are supposed to delete it, do so.
//
if ((Fcb->UncleanCount == 1) &&
(NodeType(Fcb) == FAT_NTC_DCB) &&
(FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE)) &&
(Fcb->FcbCondition != FcbBad) &&
!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
if (!FatIsDirectoryEmpty(IrpContext, Fcb)) {
//
// If there are files in the directory at this point,
// forget that we were trying to delete it.
//
ClearFlag( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE );
} else {
//
// Even if something goes wrong, we cannot turn back!
//
try {
DELETE_CONTEXT DeleteContext;
//
// Before truncating file allocation remember this
// info for FatDeleteDirent.
//
DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
//
// Synchronize here with paging IO
//
(VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
TRUE );
Fcb->Header.FileSize.LowPart = 0;
ExReleaseResourceLite( Fcb->Header.PagingIoResource );
if (Vcb->VcbCondition == VcbGood) {
//
// Truncate the file allocation down to zero
//
DebugTrace(0, Dbg, "Delete File allocation\n", 0);
FatTruncateFileAllocation( IrpContext, Fcb, 0 );
if (Fcb->Header.AllocationSize.LowPart == 0) {
//
// Tunnel and remove the dirent for the directory
//
DebugTrace(0, Dbg, "Delete the directory dirent\n", 0);
FatTunnelFcbOrDcb( Fcb, NULL );
FatDeleteDirent( IrpContext, Fcb, &DeleteContext, TRUE );
//
// Report that we have removed an entry.
//
FatNotifyReportChange( IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_DIR_NAME,
FILE_ACTION_REMOVED );
}
}
} except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
//
// Remove the entry from the name table.
// This will ensure that
// we will not collide with the Dcb if the user wants
// to recreate the same file over again before we
// get a close irp.
//
FatRemoveNames( IrpContext, Fcb );
}
}
//
// Decrement the unclean count.
//
ASSERT( Fcb->UncleanCount != 0 );
Fcb->UncleanCount -= 1;
break;
case UserFileOpen:
DebugTrace(0, Dbg, "Cleanup UserFileOpen\n", 0);
ShareAccess = &Fcb->ShareAccess;
//
// Determine here if we should do a delayed close.
//
if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
(FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
(Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
!FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->FcbCondition == FcbGood) {
//
// Delay our close.
//
SetFlag( Fcb->FcbState, FCB_STATE_DELAY_CLOSE );
}
//
// Unlock all outstanding file locks.
//
(VOID) FsRtlFastUnlockAll( &Fcb->Specific.Fcb.FileLock,
FileObject,
IoGetRequestorProcess( Irp ),
NULL );
//
// We can proceed with on-disk updates only if the volume is mounted.
// Remember that we toss all sections in the failed-verify and dismount
// cases.
//
if (Vcb->VcbCondition == VcbGood) {
if (Fcb->FcbCondition != FcbBad) {
FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
}
//
// If the file has a unclean count of 1 then we know
// that this is the last handle for the file object.
//
if ( (Fcb->UncleanCount == 1) && (Fcb->FcbCondition != FcbBad) ) {
DELETE_CONTEXT DeleteContext;
//
// Check if we should be deleting the file. The
// delete operation really deletes the file but
// keeps the Fcb around for close to do away with.
//
if (FlagOn(Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE) &&
!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
//
// Before truncating file allocation remember this
// info for FatDeleteDirent.
//
DeleteContext.FileSize = Fcb->Header.FileSize.LowPart;
DeleteContext.FirstClusterOfFile = Fcb->FirstClusterOfFile;
DebugTrace(0, Dbg, "Delete File allocation\n", 0);
//
// Synchronize here with paging IO
//
(VOID)ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource,
TRUE );
Fcb->Header.FileSize.LowPart = 0;
Fcb->Header.ValidDataLength.LowPart = 0;
Fcb->ValidDataToDisk = 0;
ExReleaseResourceLite( Fcb->Header.PagingIoResource );
try {
FatSetFileSizeInDirent( IrpContext, Fcb, NULL );
} except( FsRtlIsNtstatusExpected(GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) {
FatResetExceptionState( IrpContext );
}
Fcb->FcbState |= FCB_STATE_TRUNCATE_ON_CLOSE;
} else {
//
// We must zero between ValidDataLength and FileSize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -