📄 fatdata.c
字号:
return ExceptionCode;
} else {
//
// Generate a pop-up
//
PDEVICE_OBJECT RealDevice;
PVPB Vpb;
PETHREAD Thread;
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL) {
Vpb = IoGetCurrentIrpStackLocation(Irp)->FileObject->Vpb;
} else {
Vpb = NULL;
}
//
// The device to verify is either in my thread local storage
// or that of the thread that owns the Irp.
//
Thread = Irp->Tail.Overlay.Thread;
RealDevice = IoGetDeviceToVerify( Thread );
if ( RealDevice == NULL ) {
Thread = PsGetCurrentThread();
RealDevice = IoGetDeviceToVerify( Thread );
ASSERT( RealDevice != NULL );
}
//
// Let's not BugCheck just because the driver messed up.
//
if (RealDevice == NULL) {
FatCompleteRequest( IrpContext, Irp, ExceptionCode );
return ExceptionCode;
}
//
// This routine actually causes the pop-up. It usually
// does this by queuing an APC to the callers thread,
// but in some cases it will complete the request immediately,
// so it is very important to IoMarkIrpPending() first.
//
IoMarkIrpPending( Irp );
IoRaiseHardError( Irp, Vpb, RealDevice );
//
// We will be handing control back to the caller here, so
// reset the saved device object.
//
IoSetDeviceToVerify( Thread, NULL );
//
// The Irp will be completed by Io or resubmitted. In either
// case we must clean up the IrpContext here.
//
FatDeleteIrpContext( IrpContext );
return STATUS_PENDING;
}
}
//
// This is just a run of the mill error. If is a STATUS that we
// raised ourselves, and the information would be use for the
// user, raise an informational pop-up.
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
Vcb = IrpContext->Vcb;
//
// Now, if the Vcb is unknown to us this means that the error was raised
// in the process of a mount and before we even had a chance to build
// a full Vcb - and was really handled there.
//
if (Vcb != NULL) {
if ( !FatDeviceIsFatFsdo( IrpSp->DeviceObject) &&
!NT_SUCCESS(ExceptionCode) &&
!FsRtlIsTotalDeviceFailure(ExceptionCode) ) {
TransitionState = VolumeDirtyWithSurfaceTest;
}
//
// If this was a STATUS_FILE_CORRUPT or similar error indicating some
// nastiness out on the media, then mark the volume permanently dirty.
//
if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS) &&
( TransitionState == VolumeDirtyWithSurfaceTest ||
(ExceptionCode == STATUS_FILE_CORRUPT_ERROR) ||
(ExceptionCode == STATUS_DISK_CORRUPT_ERROR) ||
(ExceptionCode == STATUS_EA_CORRUPT_ERROR) ||
(ExceptionCode == STATUS_INVALID_EA_NAME) ||
(ExceptionCode == STATUS_EA_LIST_INCONSISTENT) ||
(ExceptionCode == STATUS_NO_EAS_ON_FILE) )) {
ASSERT( NodeType(Vcb) == FAT_NTC_VCB );
ASSERT( !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL));
SetFlag( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY );
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
//
// Do the "dirty" work, ignoring any error. We need to take the Vcb here
// to synchronize against the verify path tearing things down, since
// we dropped all synchronization when backing up due to the exception.
//
FatAcquireExclusiveVcbNoOpCheck( IrpContext, Vcb);
try {
if (VcbGood == Vcb->VcbCondition) {
FatMarkVolume( IrpContext, Vcb, TransitionState );
}
}
except( FatExceptionFilter( IrpContext, GetExceptionInformation() ) ) {
NOTHING;
}
FatReleaseVcb( IrpContext, Vcb);
}
}
FatCompleteRequest( IrpContext, Irp, ExceptionCode );
return ExceptionCode;
}
VOID
FatCompleteRequest_Real (
IN PIRP_CONTEXT IrpContext OPTIONAL,
IN PIRP Irp OPTIONAL,
IN NTSTATUS Status
)
/*++
Routine Description:
This routine completes a Irp
Arguments:
Irp - Supplies the Irp being processed
Status - Supplies the status to complete the Irp with
Return Value:
None.
--*/
{
//
// If we have an Irp Context then unpin all of the repinned bcbs
// we might have collected.
//
if (IrpContext != NULL) {
ASSERT( IrpContext->Repinned.Bcb[0] == NULL );
FatUnpinRepinnedBcbs( IrpContext );
}
//
// Delete the Irp context before completing the IRP so if
// we run into some of the asserts, we can still backtrack
// through the IRP.
//
if (IrpContext != NULL) {
FatDeleteIrpContext( IrpContext );
}
//
// If we have an Irp then complete the irp.
//
if (Irp != NULL) {
//
// We got an error, so zero out the information field before
// completing the request if this was an input operation.
// Otherwise IopCompleteRequest will try to copy to the user's buffer.
//
if ( NT_ERROR(Status) &&
FlagOn(Irp->Flags, IRP_INPUT_OPERATION) ) {
Irp->IoStatus.Information = 0;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
}
return;
}
BOOLEAN
FatIsIrpTopLevel (
IN PIRP Irp
)
/*++
Routine Description:
This routine detects if an Irp is the Top level requestor, ie. if it os OK
to do a verify or pop-up now. If TRUE is returned, then no file system
resources are held above us.
Arguments:
Irp - Supplies the Irp being processed
Status - Supplies the status to complete the Irp with
Return Value:
None.
--*/
{
if ( IoGetTopLevelIrp() == NULL ) {
IoSetTopLevelIrp( Irp );
return TRUE;
} else {
return FALSE;
}
}
BOOLEAN
FatFastIoCheckIfPossible (
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine checks if fast i/o is possible for a read/write operation
Arguments:
FileObject - Supplies the file object used in the query
FileOffset - Supplies the starting byte offset for the read/write operation
Length - Supplies the length, in bytes, of the read/write operation
Wait - Indicates if we can wait
LockKey - Supplies the lock key
CheckForReadOperation - Indicates if this is a check for a read or write
operation
IoStatus - Receives the status of the operation if our return value is
FastIoReturnError
Return Value:
BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
to take the long route.
--*/
{
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
LARGE_INTEGER LargeLength;
//
// Decode the file object to get our fcb, the only one we want
// to deal with is a UserFileOpen
//
if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) {
return FALSE;
}
LargeLength.QuadPart = Length;
//
// Based on whether this is a read or write operation we call
// fsrtl check for read/write
//
if (CheckForReadOperation) {
if (FsRtlFastCheckLockForRead( &Fcb->Specific.Fcb.FileLock,
FileOffset,
&LargeLength,
LockKey,
FileObject,
PsGetCurrentProcess() )) {
return TRUE;
}
} else {
//
// Also check for a write-protected volume here.
//
if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED) &&
FsRtlFastCheckLockForWrite( &Fcb->Specific.Fcb.FileLock,
FileOffset,
&LargeLength,
LockKey,
FileObject,
PsGetCurrentProcess() )) {
return TRUE;
}
}
return FALSE;
}
BOOLEAN
FatFastQueryBasicInfo (
IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
IN OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is for the fast query call for basic file information.
Arguments:
FileObject - Supplies the file object used in this operation
Wait - Indicates if we are allowed to wait for the information
Buffer - Supplies the output buffer to receive the basic information
IoStatus - Receives the final status of the operation
Return Value:
BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
needs to take the long route.
--*/
{
BOOLEAN Results = FALSE;
IRP_CONTEXT IrpContext;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
BOOLEAN FcbAcquired = FALSE;
//
// Prepare the dummy irp context
//
RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
IrpContext.NodeByteSize = sizeof(IRP_CONTEXT);
if (Wait) {
SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
} else {
ClearFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
}
//
// Determine the type of open for the input file object and only accept
// the user file or directory open
//
TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );
if ((TypeOfOpen != UserFileOpen) && (TypeOfOpen != UserDirectoryOpen)) {
return Results;
}
FsRtlEnterFileSystem();
//
// Get access to the Fcb but only if it is not the paging file
//
if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
if (!ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait )) {
FsRtlExitFileSystem();
return Results;
}
FcbAcquired = TRUE;
}
try {
//
// If the Fcb is not in a good state, return FALSE.
//
if (Fcb->FcbCondition != FcbGood) {
try_return( Results );
}
Buffer->FileAttributes = 0;
//
// If the fcb is not the root dcb then we will fill in the
// buffer otherwise it is all setup for us.
//
if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -