📄 deviosup.c
字号:
ExFreePool( DiskBuffer );
if ( !AbnormalTermination() && NT_SUCCESS(Irp->IoStatus.Status) ) {
Irp->IoStatus.Information = OriginalByteCount;
//
// We now flush the user's buffer to memory.
//
KeFlushIoBuffers( Irp->MdlAddress, TRUE, FALSE );
}
}
DebugTrace(-1, Dbg, "FatNonCachedNonAlignedRead -> VOID\n", 0);
return;
}
VOID
FatMultipleAsync (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PIRP MasterIrp,
IN ULONG MultipleIrpCount,
IN PIO_RUN IoRuns
)
/*++
Routine Description:
This routine first does the initial setup required of a Master IRP that is
going to be completed using associated IRPs. This routine should not
be used if only one async request is needed, instead the single read/write
async routines should be called.
A context parameter is initialized, to serve as a communications area
between here and the common completion routine. This initialization
includes allocation of a spinlock. The spinlock is deallocated in the
FatWaitSync routine, so it is essential that the caller insure that
this routine is always called under all circumstances following a call
to this routine.
Next this routine reads or writes one or more contiguous sectors from
a device asynchronously, and is used if there are multiple reads for a
master IRP. A completion routine is used to synchronize with the
completion of all of the I/O requests started by calls to this routine.
Also, prior to calling this routine the caller must initialize the
IoStatus field in the Context, with the correct success status and byte
count which are expected if all of the parallel transfers complete
successfully. After return this status will be unchanged if all requests
were, in fact, successful. However, if one or more errors occur, the
IoStatus will be modified to reflect the error status and byte count
from the first run (by Vbo) which encountered an error. I/O status
from all subsequent runs will not be indicated.
Arguments:
IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
Vcb - Supplies the device to be read
MasterIrp - Supplies the master Irp.
MulitpleIrpCount - Supplies the number of multiple async requests
that will be issued against the master irp.
IoRuns - Supplies an array containing the Vbo, Lbo, BufferOffset, and
ByteCount for all the runs to executed in parallel.
Return Value:
None.
--*/
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PMDL Mdl;
BOOLEAN Wait;
PFAT_IO_CONTEXT Context;
ULONG UnwindRunCount = 0;
BOOLEAN ExceptionExpected = TRUE;
BOOLEAN CalledByFatVerifyVolume = FALSE;
DebugTrace(+1, Dbg, "FatMultipleAsync\n", 0);
DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb );
DebugTrace( 0, Dbg, "MasterIrp = %08lx\n", MasterIrp );
DebugTrace( 0, Dbg, "MultipleIrpCount = %08lx\n", MultipleIrpCount );
DebugTrace( 0, Dbg, "IoRuns = %08lx\n", IoRuns );
//
// If this I/O originating during FatVerifyVolume, bypass the
// verify logic.
//
if ( Vcb->VerifyThread == KeGetCurrentThread() ) {
CalledByFatVerifyVolume = TRUE;
}
//
// Set up things according to whether this is truely async.
//
Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
Context = IrpContext->FatIoContext;
//
// Finish initializing Context, for use in Read/Write Multiple Asynch.
//
Context->MasterIrp = MasterIrp;
try {
//
// Itterate through the runs, doing everything that can fail
//
for ( UnwindRunCount = 0;
UnwindRunCount < MultipleIrpCount;
UnwindRunCount++ ) {
//
// Create an associated IRP, making sure there is one stack entry for
// us, as well.
//
IoRuns[UnwindRunCount].SavedIrp = 0;
Irp = IoMakeAssociatedIrp( MasterIrp,
(CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );
if (Irp == NULL) {
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
IoRuns[UnwindRunCount].SavedIrp = Irp;
//
// Allocate and build a partial Mdl for the request.
//
Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
IoRuns[UnwindRunCount].Offset,
IoRuns[UnwindRunCount].ByteCount,
FALSE,
FALSE,
Irp );
if (Mdl == NULL) {
FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
//
// Sanity Check
//
ASSERT( Mdl == Irp->MdlAddress );
IoBuildPartialMdl( MasterIrp->MdlAddress,
Mdl,
(PCHAR)MasterIrp->UserBuffer +
IoRuns[UnwindRunCount].Offset,
IoRuns[UnwindRunCount].ByteCount );
//
// Get the first IRP stack location in the associated Irp
//
IoSetNextIrpStackLocation( Irp );
IrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// Setup the Stack location to describe our read.
//
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].ByteCount;
IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].Vbo;
//
// Set up the completion routine address in our stack frame.
//
IoSetCompletionRoutine( Irp,
Wait ?
&FatMultiSyncCompletionRoutine :
&FatMultiAsyncCompletionRoutine,
Context,
TRUE,
TRUE,
TRUE );
//
// Setup the next IRP stack location in the associated Irp for the disk
// driver beneath us.
//
IrpSp = IoGetNextIrpStackLocation( Irp );
//
// Setup the Stack location to do a read from the disk driver.
//
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].ByteCount;
IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].Lbo;
//
// If this Irp is the result of a WriteThough operation,
// tell the device to write it through.
//
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
SetFlag( IrpSp->Flags, SL_WRITE_THROUGH );
}
//
// If this I/O originating during FatVerifyVolume, bypass the
// verify logic.
//
if ( CalledByFatVerifyVolume ) {
SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
}
//
// Now we no longer expect an exception. If the driver raises, we
// must bugcheck, because we do not know how to recover from that
// case.
//
ExceptionExpected = FALSE;
//
// We only need to set the associated IRP count in the master irp to
// make it a master IRP. But we set the count to one more than our
// caller requested, because we do not want the I/O system to complete
// the I/O. We also set our own count.
//
Context->IrpCount = MultipleIrpCount;
MasterIrp->AssociatedIrp.IrpCount = MultipleIrpCount;
if (Wait) {
MasterIrp->AssociatedIrp.IrpCount += 1;
}
//
// Now that all the dangerous work is done, issue the read requests
//
for (UnwindRunCount = 0;
UnwindRunCount < MultipleIrpCount;
UnwindRunCount++) {
Irp = IoRuns[UnwindRunCount].SavedIrp;
DebugDoit( FatIoCallDriverCount += 1);
//
// If IoCallDriver returns an error, it has completed the Irp
// and the error will be caught by our completion routines
// and dealt with as a normal IO error.
//
(VOID)FatLowLevelReadWrite( IrpContext,
Vcb->TargetDeviceObject,
Irp,
Vcb );
}
} finally {
ULONG i;
DebugUnwind( FatMultipleAsync );
//
// Only allocating the spinlock, making the associated Irps
// and allocating the Mdls can fail.
//
if ( AbnormalTermination() ) {
//
// If the driver raised, we are hosed. He is not supposed to raise,
// and it is impossible for us to figure out how to clean up.
//
if (!ExceptionExpected) {
ASSERT( ExceptionExpected );
FatBugCheck( 0, 0, 0 );
}
//
// Unwind
//
for (i = 0; i <= UnwindRunCount; i++) {
if ( (Irp = IoRuns[i].SavedIrp) != NULL ) {
if ( Irp->MdlAddress != NULL ) {
IoFreeMdl( Irp->MdlAddress );
}
IoFreeIrp( Irp );
}
}
}
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatMultipleAsync -> VOID\n", 0);
}
return;
}
VOID
FatSingleAsync (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN LBO Lbo,
IN ULONG ByteCount,
IN PIRP Irp
)
/*++
Routine Description:
This routine reads or writes one or more contiguous sectors from a device
asynchronously, and is used if there is only one read necessary to
complete the IRP. It implements the read by simply filling
in the next stack frame in the Irp, and passing it on. The transfer
occurs to the single buffer originally specified in the user request.
Arguments:
IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
Vcb - Supplies the device to read
Lbo - Supplies the starting Logical Byte Offset to begin reading from
ByteCount - Supplies the number of bytes to read from the device
Irp - Supplies the master Irp to associated with the async
request.
Return Value:
None.
--*/
{
PIO_STACK_LOCATION IrpSp;
DebugTrace(+1, Dbg, "FatSingleAsync\n", 0);
DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb );
DebugTrace( 0, Dbg, "Lbo = %08lx\n", Lbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
//
// Set up the completion routine address in our stack frame.
//
IoSetCompletionRoutine( Irp,
FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ?
&FatSingleSyncCompletionRoutine :
&FatSingleAsyncCompletionRoutine,
IrpContext->FatIoContext,
TRUE,
TRUE,
TRUE );
//
// Setup the next IRP stack location in the associated Irp for the disk
// driver beneath us.
//
IrpSp = IoGetNextIrpStackLocation( Irp );
//
// Setup the Stack location to do a read from the disk driver.
//
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = ByteCount;
IrpSp->Parameters.Read.ByteOffset.QuadPart = Lbo;
//
// If this Irp is the result of a WriteThough operation,
// tell the device to write it through.
//
if (FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
SetFlag( IrpSp->Flags, SL_WRITE_THROUGH );
}
//
// If this I/O originating during FatVerifyVolume, bypass the
// verify logic.
//
if ( Vcb->VerifyThread == KeGetCurrentThread() ) {
SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
//
// Issue the read request
//
DebugDoit( FatIoCallDriverCount += 1);
//
// If IoCallDriver returns an error, it has completed the Irp
// and the error will be caught by our completion routines
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -