📄 read.c
字号:
Context - Supplies the IrpContext being processed
Event - Supplies the event to be signaled when we are done processing this
request.
Return Value:
None.
--*/
{
PIRP_CONTEXT IrpContext = Context;
PKTHREAD SavedVerifyThread = NULL;
PVCB Vcb;
//
// Make it now look like we can wait for I/O to complete
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
//
// If this read was as the result of a verify we have to fake out the
// the Vcb->VerifyThread field.
//
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) {
PFCB Fcb = (PFCB)IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp)->
FileObject->FsContext;
if (NodeType( Fcb ) == FAT_NTC_VCB) {
Vcb = (PVCB) Fcb;
} else {
Vcb = Fcb->Vcb;
}
ASSERT( Vcb->VerifyThread != NULL );
SavedVerifyThread = Vcb->VerifyThread;
Vcb->VerifyThread = KeGetCurrentThread();
}
//
// Do the read operation protected by a try-except clause
//
try {
(VOID) FatCommonRead( IrpContext, IrpContext->OriginatingIrp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
NTSTATUS ExceptionCode;
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
ExceptionCode = GetExceptionCode();
if (ExceptionCode == STATUS_FILE_DELETED) {
IrpContext->ExceptionStatus = ExceptionCode = STATUS_END_OF_FILE;
IrpContext->OriginatingIrp->IoStatus.Information = 0;
}
(VOID) FatProcessException( IrpContext, IrpContext->OriginatingIrp, ExceptionCode );
}
//
// Restore the original VerifyVolumeThread
//
if (SavedVerifyThread != NULL) {
ASSERT( Vcb->VerifyThread == KeGetCurrentThread() );
Vcb->VerifyThread = SavedVerifyThread;
}
//
// Set the stack overflow item's event to tell the original
// thread that we're done.
//
KeSetEvent( Event, 0, FALSE );
}
NTSTATUS
FatCommonRead (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common read routine for NtReadFile, called from both
the Fsd, or from the Fsp if a request could not be completed without
blocking in the Fsd. This routine has no code where it determines
whether it is running in the Fsd or Fsp. Instead, its actions are
conditionalized by the Wait input parameter, which determines whether
it is allowed to block or not. If a blocking condition is encountered
with Wait == FALSE, however, the request is posted to the Fsp, who
always calls with WAIT == TRUE.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
PVCB Vcb;
PFCB FcbOrDcb;
PCCB Ccb;
VBO StartingVbo;
ULONG ByteCount;
ULONG RequestedByteCount;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN PostIrp = FALSE;
BOOLEAN OplockPostIrp = FALSE;
BOOLEAN FcbOrDcbAcquired = FALSE;
BOOLEAN Wait;
BOOLEAN PagingIo;
BOOLEAN NonCachedIo;
BOOLEAN SynchronousIo;
NTSTATUS Status;
FAT_IO_CONTEXT StackFatIoContext;
//
// A system buffer is only used if we have to access the
// buffer directly from the Fsp to clear a portion or to
// do a synchronous I/O, or a cached transfer. It is
// possible that our caller may have already mapped a
// system buffer, in which case we must remember this so
// we do not unmap it on the way out.
//
PVOID SystemBuffer = NULL;
LARGE_INTEGER StartingByte;
//
// Get current Irp stack location.
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
FileObject = IrpSp->FileObject;
//
// Initialize the appropriate local variables.
//
Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
NonCachedIo = BooleanFlagOn(Irp->Flags,IRP_NOCACHE);
SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
DebugTrace(+1, Dbg, "CommonRead\n", 0);
DebugTrace( 0, Dbg, " Irp = %8lx\n", Irp);
DebugTrace( 0, Dbg, " ->ByteCount = %8lx\n", IrpSp->Parameters.Read.Length);
DebugTrace( 0, Dbg, " ->ByteOffset.LowPart = %8lx\n", IrpSp->Parameters.Read.ByteOffset.LowPart);
DebugTrace( 0, Dbg, " ->ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Read.ByteOffset.HighPart);
//
// Extract starting Vbo and offset.
//
StartingByte = IrpSp->Parameters.Read.ByteOffset;
StartingVbo = StartingByte.LowPart;
ByteCount = IrpSp->Parameters.Read.Length;
RequestedByteCount = ByteCount;
//
// Check for a null request, and return immediately
//
if (ByteCount == 0) {
Irp->IoStatus.Information = 0;
FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
return STATUS_SUCCESS;
}
//
// Extract the nature of the read from the file object, and case on it
//
TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &FcbOrDcb, &Ccb);
ASSERT( Vcb != NULL );
//
// Save callers who try to do cached IO to the raw volume from themselves.
//
if (TypeOfOpen == UserVolumeOpen) {
NonCachedIo = TRUE;
}
ASSERT(!(NonCachedIo == FALSE && TypeOfOpen == VirtualVolumeFile));
//
// Collect interesting statistics. The FLAG_USER_IO bit will indicate
// what type of io we're doing in the FatNonCachedIo function.
//
if (PagingIo) {
CollectReadStats(Vcb, TypeOfOpen, ByteCount);
if (TypeOfOpen == UserFileOpen) {
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
} else {
ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
}
}
ASSERT(!FlagOn( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT ));
//
// Allocate if necessary and initialize a FAT_IO_CONTEXT block for
// all non cached Io. For synchronous Io we use stack storage,
// otherwise we allocate pool.
//
if (NonCachedIo) {
if (IrpContext->FatIoContext == NULL) {
if (!Wait) {
IrpContext->FatIoContext =
FsRtlAllocatePoolWithTag( NonPagedPool,
sizeof(FAT_IO_CONTEXT),
TAG_FAT_IO_CONTEXT );
} else {
IrpContext->FatIoContext = &StackFatIoContext;
SetFlag( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT );
}
}
RtlZeroMemory( IrpContext->FatIoContext, sizeof(FAT_IO_CONTEXT) );
if (Wait) {
KeInitializeEvent( &IrpContext->FatIoContext->Wait.SyncEvent,
NotificationEvent,
FALSE );
} else {
IrpContext->FatIoContext->Wait.Async.ResourceThreadId =
ExGetCurrentResourceThread();
IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
ByteCount;
IrpContext->FatIoContext->Wait.Async.FileObject = FileObject;
}
}
//
// These two cases correspond to either a general opened volume, ie.
// open ("a:"), or a read of the volume file (boot sector + fat(s))
//
if ((TypeOfOpen == VirtualVolumeFile) ||
(TypeOfOpen == UserVolumeOpen)) {
LBO StartingLbo;
StartingLbo = StartingByte.QuadPart;
DebugTrace(0, Dbg, "Type of read is User Volume or virtual volume file\n", 0);
if (TypeOfOpen == UserVolumeOpen) {
//
// Verify that the volume for this handle is still valid
//
//
// Verify that the volume for this handle is still valid, permitting
// operations to proceed on dismounted volumes via the handle which
// performed the dismount.
//
if (!FlagOn( Ccb->Flags, CCB_FLAG_COMPLETE_DISMOUNT )) {
FatQuickVerifyVcb( IrpContext, Vcb );
}
if (!FlagOn( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE )) {
(VOID)ExAcquireResourceExclusiveLite( &Vcb->Resource, TRUE );
try {
//
// If the volume isn't locked, flush it.
//
if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {
FatFlushVolume( IrpContext, Vcb, Flush );
}
} finally {
ExReleaseResourceLite( &Vcb->Resource );
}
SetFlag( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE );
}
if (!FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {
LBO VolumeSize;
//
// Make sure we don't try to read past end of volume,
// reducing the byte count if necessary.
//
VolumeSize = (LBO) Vcb->Bpb.BytesPerSector *
(Vcb->Bpb.Sectors != 0 ? Vcb->Bpb.Sectors :
Vcb->Bpb.LargeSectors);
if (StartingLbo >= VolumeSize) {
Irp->IoStatus.Information = 0;
FatCompleteRequest( IrpContext, Irp, STATUS_END_OF_FILE );
return STATUS_END_OF_FILE;
}
if (ByteCount > VolumeSize - StartingLbo) {
ByteCount = RequestedByteCount = (ULONG) (VolumeSize - StartingLbo);
//
// For async reads we had set the byte count in the FatIoContext
// above, so fix that here.
//
if (!Wait) {
IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
ByteCount;
}
}
}
//
// For DASD we have to probe and lock the user's buffer
//
FatLockUserBuffer( IrpContext, Irp, IoWriteAccess, ByteCount );
} else {
//
// Virtual volume file open -- increment performance counters.
//
Vcb->Statistics[KeGetCurrentProcessorNumber()].Common.MetaDataDiskReads += 1;
}
//
// Read the data and wait for the results
//
FatSingleAsync( IrpContext,
Vcb,
StartingLbo,
ByteCount,
Irp );
if (!Wait) {
//
// We, nor anybody else, need the IrpContext any more.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -