📄 deviosup.c
字号:
&EndOnMax,
&LastIndex );
//
// Since we already added the allocation for the whole
// write, assert that we find runs until ByteCount == 0
// Otherwise this file is corrupt.
//
if ( !LastIsAllocated ) {
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
if (LastIndex - FirstIndex + 1 > FAT_MAX_IO_RUNS_ON_STACK) {
IoRuns = FsRtlAllocatePoolWithTag( PagedPool,
(LastIndex - FirstIndex + 1) * sizeof(IO_RUN),
TAG_IO_RUNS );
} else {
IoRuns = StackIoRuns;
}
ASSERT( LastIndex != FirstIndex );
CurrentIndex = FirstIndex;
//
// Loop while there are still byte writes to satisfy.
//
while (CurrentIndex <= LastIndex) {
ASSERT( NextByteCount != 0);
ASSERT( ByteCount != 0);
//
// If next run is larger than we need, "ya get what you need".
//
if (NextByteCount > ByteCount) {
NextByteCount = ByteCount;
}
//
// Now that we have properly bounded this piece of the
// transfer, it is time to write it.
//
// We remember each piece of a parallel run by saving the
// essential information in the IoRuns array. The tranfers
// are started up in parallel below.
//
IoRuns[NextRun].Vbo = StartingVbo;
IoRuns[NextRun].Lbo = NextLbo;
IoRuns[NextRun].Offset = BufferOffset;
IoRuns[NextRun].ByteCount = NextByteCount;
NextRun += 1;
//
// Now adjust everything for the next pass through the loop.
//
StartingVbo += NextByteCount;
BufferOffset += NextByteCount;
ByteCount -= NextByteCount;
//
// Try to lookup the next run (if we are not done).
//
CurrentIndex += 1;
if ( CurrentIndex <= LastIndex ) {
ASSERT( ByteCount != 0 );
FatGetNextMcbEntry( FcbOrDcb->Vcb, &FcbOrDcb->Mcb,
CurrentIndex,
&NextVbo,
&NextLbo,
&NextByteCount );
ASSERT( NextVbo == StartingVbo );
}
} // while ( CurrentIndex <= LastIndex )
//
// Now set up the Irp->IoStatus. It will be modified by the
// multi-completion routine in case of error or verify required.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = OriginalByteCount;
if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
CollectDiskIoStats(FcbOrDcb->Vcb, IrpContext->MajorFunction,
FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO), NextRun);
}
//
// OK, now do the I/O.
//
try {
DebugTrace( 0, Dbg, "Passing Multiple Irps on to Disk Driver\n", 0 );
FatMultipleAsync( IrpContext,
FcbOrDcb->Vcb,
Irp,
NextRun,
IoRuns );
} finally {
if (IoRuns != StackIoRuns) {
ExFreePool( IoRuns );
}
}
}
if (!Wait) {
DebugTrace(-1, Dbg, "FatNonCachedIo -> STATUS_PENDING\n", 0);
return STATUS_PENDING;
}
FatWaitSync( IrpContext );
DebugTrace(-1, Dbg, "FatNonCachedIo -> 0x%08lx\n", Irp->IoStatus.Status);
return Irp->IoStatus.Status;
}
VOID
FatNonCachedNonAlignedRead (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB FcbOrDcb,
IN ULONG StartingVbo,
IN ULONG ByteCount
)
/*++
Routine Description:
This routine performs the non-cached disk io described in its parameters.
This routine differs from the above in that the range does not have to be
sector aligned. This accomplished with the use of intermediate buffers.
Arguments:
IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
Irp - Supplies the requesting Irp.
FcbOrDcb - Supplies the file to act on.
StartingVbo - The starting point for the operation.
ByteCount - The lengh of the operation.
Return Value:
None.
--*/
{
//
// Declare some local variables for enumeration through the
// runs of the file, and an array to store parameters for
// parallel I/Os
//
LBO NextLbo;
ULONG NextByteCount;
BOOLEAN NextIsAllocated;
ULONG SectorSize;
ULONG BytesToCopy;
ULONG OriginalByteCount;
ULONG OriginalStartingVbo;
BOOLEAN EndOnMax;
PUCHAR UserBuffer;
PUCHAR DiskBuffer = NULL;
PMDL Mdl;
PMDL SavedMdl;
PVOID SavedUserBuffer;
DebugTrace(+1, Dbg, "FatNonCachedNonAlignedRead\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
DebugTrace( 0, Dbg, "FcbOrDcb = %08lx\n", FcbOrDcb );
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo );
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount );
//
// Initialize some locals.
//
OriginalByteCount = ByteCount;
OriginalStartingVbo = StartingVbo;
SectorSize = FcbOrDcb->Vcb->Bpb.BytesPerSector;
ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
//
// For nonbuffered I/O, we need the buffer locked in all
// cases.
//
// This call may raise. If this call succeeds and a subsequent
// condition is raised, the buffers are unlocked automatically
// by the I/O system when the request is completed, via the
// Irp->MdlAddress field.
//
FatLockUserBuffer( IrpContext,
Irp,
IoWriteAccess,
ByteCount );
UserBuffer = FatMapUserBuffer( IrpContext, Irp );
//
// Allocate the local buffer
//
DiskBuffer = FsRtlAllocatePoolWithTag( NonPagedPoolCacheAligned,
(ULONG) ROUND_TO_PAGES( SectorSize ),
TAG_IO_BUFFER );
//
// We use a try block here to ensure the buffer is freed, and to
// fill in the correct byte count in the Iosb.Information field.
//
try {
//
// If the beginning of the request was not aligned correctly, read in
// the first part first.
//
if ( StartingVbo & (SectorSize - 1) ) {
VBO Hole;
//
// Try to lookup the first run.
//
FatLookupFileAllocation( IrpContext,
FcbOrDcb,
StartingVbo,
&NextLbo,
&NextByteCount,
&NextIsAllocated,
&EndOnMax,
NULL );
//
// We just added the allocation, thus there must be at least
// one entry in the mcb corresponding to our write, ie.
// NextIsAllocated must be true. If not, the pre-existing file
// must have an allocation error.
//
if ( !NextIsAllocated ) {
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
FatSingleNonAlignedSync( IrpContext,
FcbOrDcb->Vcb,
DiskBuffer,
NextLbo & ~((LONG)SectorSize - 1),
SectorSize,
Irp );
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
try_return( NOTHING );
}
//
// Now copy the part of the first sector that we want to the user
// buffer.
//
Hole = StartingVbo & (SectorSize - 1);
BytesToCopy = ByteCount >= SectorSize - Hole ?
SectorSize - Hole : ByteCount;
RtlCopyMemory( UserBuffer, DiskBuffer + Hole, BytesToCopy );
StartingVbo += BytesToCopy;
ByteCount -= BytesToCopy;
if ( ByteCount == 0 ) {
try_return( NOTHING );
}
}
ASSERT( (StartingVbo & (SectorSize - 1)) == 0 );
//
// If there is a tail part that is not sector aligned, read it.
//
if ( ByteCount & (SectorSize - 1) ) {
VBO LastSectorVbo;
LastSectorVbo = StartingVbo + (ByteCount & ~(SectorSize - 1));
//
// Try to lookup the last part of the requested range.
//
FatLookupFileAllocation( IrpContext,
FcbOrDcb,
LastSectorVbo,
&NextLbo,
&NextByteCount,
&NextIsAllocated,
&EndOnMax,
NULL );
//
// We just added the allocation, thus there must be at least
// one entry in the mcb corresponding to our write, ie.
// NextIsAllocated must be true. If not, the pre-existing file
// must have an allocation error.
//
if ( !NextIsAllocated ) {
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
FatSingleNonAlignedSync( IrpContext,
FcbOrDcb->Vcb,
DiskBuffer,
NextLbo,
SectorSize,
Irp );
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
try_return( NOTHING );
}
//
// Now copy over the part of this last sector that we need.
//
BytesToCopy = ByteCount & (SectorSize - 1);
UserBuffer += LastSectorVbo - OriginalStartingVbo;
RtlCopyMemory( UserBuffer, DiskBuffer, BytesToCopy );
ByteCount -= BytesToCopy;
if ( ByteCount == 0 ) {
try_return( NOTHING );
}
}
ASSERT( ((StartingVbo | ByteCount) & (SectorSize - 1)) == 0 );
//
// Now build a Mdl describing the sector aligned balance of the transfer,
// and put it in the Irp, and read that part.
//
SavedMdl = Irp->MdlAddress;
Irp->MdlAddress = NULL;
SavedUserBuffer = Irp->UserBuffer;
Irp->UserBuffer = (PUCHAR)MmGetMdlVirtualAddress( SavedMdl ) +
(StartingVbo - OriginalStartingVbo);
Mdl = IoAllocateMdl( Irp->UserBuffer,
ByteCount,
FALSE,
FALSE,
Irp );
if (Mdl == NULL) {
Irp->MdlAddress = SavedMdl;
Irp->UserBuffer = SavedUserBuffer;
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
IoBuildPartialMdl( SavedMdl,
Mdl,
Irp->UserBuffer,
ByteCount );
//
// Try to read in the pages.
//
try {
FatNonCachedIo( IrpContext,
Irp,
FcbOrDcb,
StartingVbo,
ByteCount,
ByteCount );
} finally {
IoFreeMdl( Irp->MdlAddress );
Irp->MdlAddress = SavedMdl;
Irp->UserBuffer = SavedUserBuffer;
}
try_exit: NOTHING;
} finally {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -