📄 read.c
字号:
IrpContext->FatIoContext = NULL;
FatDeleteIrpContext( IrpContext );
DebugTrace(-1, Dbg, "FatNonCachedIo -> STATUS_PENDING\n", 0);
return STATUS_PENDING;
}
FatWaitSync( IrpContext );
//
// If the call didn't succeed, raise the error status
//
if (!NT_SUCCESS( Status = Irp->IoStatus.Status )) {
ASSERT( KeGetCurrentThread() != Vcb->VerifyThread || Status != STATUS_VERIFY_REQUIRED );
FatNormalizeAndRaiseStatus( IrpContext, Status );
}
//
// Update the current file position
//
if (SynchronousIo && !PagingIo) {
FileObject->CurrentByteOffset.QuadPart =
StartingLbo + Irp->IoStatus.Information;
}
DebugTrace(-1, Dbg, "CommonRead -> %08lx\n", Status );
FatCompleteRequest( IrpContext, Irp, Status );
return Status;
}
//
// At this point we know there is an Fcb/Dcb.
//
ASSERT( FcbOrDcb != NULL );
//
// Check for a non-zero high part offset
//
if ( StartingByte.HighPart != 0 ) {
Irp->IoStatus.Information = 0;
FatCompleteRequest( IrpContext, Irp, STATUS_END_OF_FILE );
return STATUS_END_OF_FILE;
}
//
// Use a try-finally to free Fcb/Dcb and buffers on the way out.
//
try {
//
// This case corresponds to a normal user read file.
//
if ( TypeOfOpen == UserFileOpen) {
ULONG FileSize;
ULONG ValidDataLength;
DebugTrace(0, Dbg, "Type of read is user file open\n", 0);
//
// If this is a noncached transfer and is not a paging I/O, and
// the file has a data section, then we will do a flush here
// to avoid stale data problems. Note that we must flush before
// acquiring the Fcb shared since the write may try to acquire
// it exclusive.
//
if (!PagingIo && NonCachedIo
&&
(FileObject->SectionObjectPointer->DataSectionObject != NULL)) {
#ifndef REDUCE_SYNCHRONIZATION
if (!FatAcquireExclusiveFcb( IrpContext, FcbOrDcb )) {
try_return( PostIrp = TRUE );
}
ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
#endif //REDUCE_SYNCHRONIZATION
CcFlushCache( FileObject->SectionObjectPointer,
&StartingByte,
ByteCount,
&Irp->IoStatus );
#ifndef REDUCE_SYNCHRONIZATION
ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
FatReleaseFcb( IrpContext, FcbOrDcb );
#endif //REDUCE_SYNCHRONIZATION
if (!NT_SUCCESS( Irp->IoStatus.Status)) {
try_return( Irp->IoStatus.Status );
}
#ifndef REDUCE_SYNCHRONIZATION
ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
#endif //REDUCE_SYNCHRONIZATION
}
//
// We need shared access to the Fcb/Dcb before proceeding.
//
if ( PagingIo ) {
if (!ExAcquireResourceSharedLite( FcbOrDcb->Header.PagingIoResource,
Wait )) {
DebugTrace( 0, Dbg, "Cannot acquire FcbOrDcb = %08lx shared without waiting\n", FcbOrDcb );
try_return( PostIrp = TRUE );
}
if (!Wait) {
IrpContext->FatIoContext->Wait.Async.Resource =
FcbOrDcb->Header.PagingIoResource;
}
} else {
//
// If this is async I/O, we will wait if there is an
// exclusive waiter.
//
if (!Wait && NonCachedIo) {
if (!FatAcquireSharedFcbWaitForEx( IrpContext, FcbOrDcb )) {
DebugTrace( 0,
Dbg,
"Cannot acquire FcbOrDcb = %08lx shared without waiting\n",
FcbOrDcb );
try_return( PostIrp = TRUE );
}
IrpContext->FatIoContext->Wait.Async.Resource =
FcbOrDcb->Header.Resource;
} else {
if (!FatAcquireSharedFcb( IrpContext, FcbOrDcb )) {
DebugTrace( 0,
Dbg,
"Cannot acquire FcbOrDcb = %08lx shared without waiting\n",
FcbOrDcb );
try_return( PostIrp = TRUE );
}
}
}
FcbOrDcbAcquired = TRUE;
//
// Make sure the FcbOrDcb is still good
//
FatVerifyFcb( IrpContext, FcbOrDcb );
//
// We now check whether we can proceed based on the state of
// the file oplocks.
//
if (!PagingIo) {
Status = FsRtlCheckOplock( &FcbOrDcb->Specific.Fcb.Oplock,
Irp,
IrpContext,
FatOplockComplete,
FatPrePostIrp );
if (Status != STATUS_SUCCESS) {
OplockPostIrp = TRUE;
PostIrp = TRUE;
try_return( NOTHING );
}
//
// Reset the flag indicating if Fast I/O is possible since the oplock
// check could have broken existing (conflicting) oplocks.
//
FcbOrDcb->Header.IsFastIoPossible = FatIsFastIoPossible( FcbOrDcb );
//
// We have to check for read access according to the current
// state of the file locks, and set FileSize from the Fcb.
//
if (!PagingIo &&
!FsRtlCheckLockForReadAccess( &FcbOrDcb->Specific.Fcb.FileLock,
Irp )) {
try_return( Status = STATUS_FILE_LOCK_CONFLICT );
}
}
//
// Pick up our sizes and check/trim the IO.
//
FileSize = FcbOrDcb->Header.FileSize.LowPart;
ValidDataLength = FcbOrDcb->Header.ValidDataLength.LowPart;
//
// If the read starts beyond End of File, return EOF.
//
if (StartingVbo >= FileSize) {
DebugTrace( 0, Dbg, "End of File\n", 0 );
try_return ( Status = STATUS_END_OF_FILE );
}
//
// If the read extends beyond EOF, truncate the read
//
if (ByteCount > FileSize - StartingVbo) {
ByteCount = RequestedByteCount = FileSize - StartingVbo;
if (NonCachedIo && !Wait) {
IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
RequestedByteCount;
}
}
//
// HANDLE THE NON-CACHED CASE
//
if ( NonCachedIo ) {
ULONG SectorSize;
ULONG BytesToRead;
DebugTrace(0, Dbg, "Non cached read.\n", 0);
//
// Get the sector size
//
SectorSize = (ULONG)Vcb->Bpb.BytesPerSector;
//
// Start by zeroing any part of the read after Valid Data
//
if (ValidDataLength < FcbOrDcb->ValidDataToDisk) {
ValidDataLength = FcbOrDcb->ValidDataToDisk;
}
if ( StartingVbo + ByteCount > ValidDataLength ) {
SystemBuffer = FatMapUserBuffer( IrpContext, Irp );
if (StartingVbo < ValidDataLength) {
ULONG ZeroingOffset;
//
// Now zero out the user's request sector aligned beyond
// vdl. We will handle the straddling sector at completion
// time via the bytecount reduction which immediately
// follows this check.
//
// Note that we used to post in this case for async requests.
// Note also that if the request was wholly beyond VDL that
// we did not post, therefore this is consistent. Synchronous
// zeroing is fine for async requests.
//
ZeroingOffset = ((ValidDataLength - StartingVbo) + (SectorSize - 1))
& ~(SectorSize - 1);
//
// If the offset is at or above the byte count, no harm: just means
// that the read ends in the last sector and the zeroing will be
// done at completion.
//
if (ByteCount > ZeroingOffset) {
SafeZeroMemory( (PUCHAR) SystemBuffer + ZeroingOffset,
ByteCount - ZeroingOffset);
}
} else {
//
// All we have to do now is sit here and zero the
// user's buffer, no reading is required.
//
SafeZeroMemory( (PUCHAR)SystemBuffer, ByteCount );
Irp->IoStatus.Information = ByteCount;
try_return ( Status = STATUS_SUCCESS );
}
}
//
// Reduce the byte count to actually read if it extends beyond
// Valid Data Length
//
ByteCount = (ValidDataLength - StartingVbo < ByteCount) ?
ValidDataLength - StartingVbo : ByteCount;
//
// Round up to a sector boundary, and remember that if we are
// reading extra bytes we will zero them out during completion.
//
BytesToRead = (ByteCount + (SectorSize - 1))
& ~(SectorSize - 1);
//
// Just to help alleviate confusion. At this point:
//
// RequestedByteCount - is the number of bytes originally
// taken from the Irp, but constrained
// to filesize.
//
// ByteCount - is RequestedByteCount constrained to
// ValidDataLength.
//
// BytesToRead - is ByteCount rounded up to sector
// boundry. This is the number of bytes
// that we must physically read.
//
//
// If this request is not properly aligned, or extending
// to a sector boundary would overflow the buffer, send it off
// on a special-case path.
//
if ( (StartingVbo & (SectorSize - 1)) ||
(BytesToRead > IrpSp->Parameters.Read.Length) ) {
//
// If we can't wait, we must post this.
//
if (!Wait) {
try_return( PostIrp = TRUE );
}
//
// Do the physical read
//
FatNonCachedNonAlignedRead( IrpContext,
Irp,
FcbOrDcb,
StartingVbo,
ByteCount );
//
// Set BytesToRead to ByteCount to satify the following ASSERT.
//
BytesToRead = ByteCount;
} else {
//
// Perform the actual IO
//
if (FatNonCachedIo( IrpContext,
Irp,
FcbOrDcb,
StartingVbo,
BytesToRead,
ByteCount ) == STATUS_PENDING) {
IrpContext->FatIoContext = NULL;
Irp = NULL;
try_return( Status = STATUS_PENDING );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -