📄 deviosup.c
字号:
OutputBufferLength,
InternalDeviceIoControl,
&Event,
IosbToUse );
if (Irp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
if (OverrideVerify) {
SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
Status = IoCallDriver( Device, Irp );
//
// We check for device not ready by first checking Status
// and then if status pending was returned, the Iosb status
// value.
//
if (Status == STATUS_PENDING) {
(VOID) KeWaitForSingleObject( &Event,
Executive,
KernelMode,
FALSE,
(PLARGE_INTEGER)NULL );
Status = IosbToUse->Status;
}
ASSERT( !(OverrideVerify && (STATUS_VERIFY_REQUIRED == Status)));
return Status;
}
NTSTATUS
FASTCALL
CdPerformDevIoCtrl (
IN PIRP_CONTEXT IrpContext,
IN ULONG IoControlCode,
IN PDEVICE_OBJECT Device,
OUT OPTIONAL PVOID OutputBuffer,
IN ULONG OutputBufferLength,
IN BOOLEAN InternalDeviceIoControl,
IN BOOLEAN OverrideVerify,
OUT OPTIONAL PIO_STATUS_BLOCK Iosb
)
{
return CdPerformDevIoCtrlEx( IrpContext,
IoControlCode,
Device,
NULL,
0,
OutputBuffer,
OutputBufferLength,
InternalDeviceIoControl,
OverrideVerify,
Iosb);
}
//
// Local support routine
//
BOOLEAN
CdPrepareBuffers (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB Fcb,
IN PVOID UserBuffer,
IN ULONG UserBufferOffset,
IN LONGLONG StartingOffset,
IN ULONG ByteCount,
IN PIO_RUN IoRuns,
IN PULONG RunCount,
IN PULONG ThisByteCount
)
/*++
Routine Description:
This routine is the worker routine which looks up each run of an IO
request and stores an entry for it in the IoRuns array. If the run
begins on an unaligned disk boundary then we will allocate a buffer
and Mdl for the unaligned portion and put it in the IoRuns entry.
This routine will raise CANT_WAIT if an unaligned transfer is encountered
and this request can't wait.
Arguments:
Irp - Originating Irp for this request.
Fcb - This is the Fcb for this data stream. It may be a file, directory,
path table or the volume file.
UserBuffer - Current position in the user's buffer.
UserBufferOffset - Offset from the start of the original user buffer.
StartingOffset - Offset in the stream to begin the read.
ByteCount - Number of bytes to read. We will fill the IoRuns array up
to this point. We will stop early if we exceed the maximum number
of parallel Ios we support.
IoRuns - Pointer to the IoRuns array. The entire array is zeroes when
this routine is called.
RunCount - Number of entries in the IoRuns array filled here.
ThisByteCount - Number of bytes described by the IoRun entries. Will
not exceed the ByteCount passed in.
Return Value:
BOOLEAN - TRUE if one of the entries in an unaligned buffer (provided
this is synchronous). FALSE otherwise.
--*/
{
BOOLEAN FoundUnaligned = FALSE;
PIO_RUN ThisIoRun = IoRuns;
//
// Following indicate where we are in the current transfer. Current
// position in the file and number of bytes yet to transfer from
// this position.
//
ULONG RemainingByteCount = ByteCount;
LONGLONG CurrentFileOffset = StartingOffset;
//
// Following indicate the state of the user's buffer. We have
// the destination of the next transfer and its offset in the
// buffer. We also have the next available position in the buffer
// available for a scratch buffer. We will align this up to a sector
// boundary.
//
PVOID CurrentUserBuffer = UserBuffer;
ULONG CurrentUserBufferOffset = UserBufferOffset;
PVOID ScratchUserBuffer = UserBuffer;
ULONG ScratchUserBufferOffset = UserBufferOffset;
//
// The following is the next contiguous bytes on the disk to
// transfer. Read from the allocation package.
//
LONGLONG DiskOffset;
ULONG CurrentByteCount;
PAGED_CODE();
//
// Initialize the RunCount and ByteCount.
//
*RunCount = 0;
*ThisByteCount = 0;
//
// Loop while there are more bytes to process or there are
// available entries in the IoRun array.
//
while (TRUE) {
*RunCount += 1;
//
// Initialize the current position in the IoRuns array.
// Find the user's buffer for this portion of the transfer.
//
ThisIoRun->UserBuffer = CurrentUserBuffer;
//
// Find the allocation information for the current offset in the
// stream.
//
CdLookupAllocation( IrpContext,
Fcb,
CurrentFileOffset,
&DiskOffset,
&CurrentByteCount );
//
// Limit ourselves to the data requested.
//
if (CurrentByteCount > RemainingByteCount) {
CurrentByteCount = RemainingByteCount;
}
//
// Handle the case where this is an unaligned transfer. The
// following must all be true for this to be an aligned transfer.
//
// Disk offset on a 2048 byte boundary (Start of transfer)
//
// Byte count is a multiple of 2048 (Length of transfer)
//
// Current buffer offset is also on a 2048 byte boundary.
//
// If the ByteCount is at least one sector then do the
// unaligned transfer only for the tail. We can use the
// user's buffer for the aligned portion.
//
if (FlagOn( (ULONG) DiskOffset, SECTOR_MASK ) ||
FlagOn( CurrentUserBufferOffset, SECTOR_MASK ) ||
(FlagOn( (ULONG) CurrentByteCount, SECTOR_MASK ) &&
(CurrentByteCount < SECTOR_SIZE))) {
ASSERT( SafeNodeType(Fcb) != CDFS_NTC_FCB_INDEX);
//
// If we can't wait then raise.
//
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
//
// Remember the offset and the number of bytes out of
// the transfer buffer to copy into the user's buffer.
// We will truncate the current read to end on a sector
// boundary.
//
ThisIoRun->TransferBufferOffset = SectorOffset( DiskOffset );
//
// Make sure this transfer ends on a sector boundary.
//
ThisIoRun->DiskOffset = LlSectorTruncate( DiskOffset );
//
// Check if we can use a free portion of the user's buffer.
// If we can copy the bytes to an earlier portion of the
// buffer then read into that location and slide the bytes
// up.
//
// We can use the user's buffer if:
//
// The temporary location in the buffer is before the
// final destination.
//
// There is at least one sector of data to read.
//
if ((ScratchUserBufferOffset + ThisIoRun->TransferBufferOffset < CurrentUserBufferOffset) &&
(ThisIoRun->TransferBufferOffset + CurrentByteCount >= SECTOR_SIZE)) {
ThisIoRun->DiskByteCount = SectorTruncate( ThisIoRun->TransferBufferOffset + CurrentByteCount );
CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
ThisIoRun->TransferByteCount = CurrentByteCount;
//
// Point to the user's buffer and Mdl for this transfer.
//
ThisIoRun->TransferBuffer = ScratchUserBuffer;
ThisIoRun->TransferMdl = Irp->MdlAddress;
ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
ScratchUserBufferOffset,
PVOID );
ScratchUserBuffer = Add2Ptr( ScratchUserBuffer,
ThisIoRun->DiskByteCount,
PVOID );
ScratchUserBufferOffset += ThisIoRun->DiskByteCount;
//
// Otherwise we need to allocate an auxilary buffer for the next sector.
//
} else {
//
// Read up to a page containing the partial data
//
ThisIoRun->DiskByteCount = SectorAlign( ThisIoRun->TransferBufferOffset + CurrentByteCount );
if (ThisIoRun->DiskByteCount > PAGE_SIZE) {
ThisIoRun->DiskByteCount = PAGE_SIZE;
}
if (ThisIoRun->TransferBufferOffset + CurrentByteCount > ThisIoRun->DiskByteCount) {
CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
}
ThisIoRun->TransferByteCount = CurrentByteCount;
//
// Allocate a buffer for the non-aligned transfer.
//
ThisIoRun->TransferBuffer = FsRtlAllocatePoolWithTag( CdNonPagedPool, PAGE_SIZE, TAG_IO_BUFFER );
//
// Allocate and build the Mdl to describe this buffer.
//
ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer,
PAGE_SIZE,
FALSE,
FALSE,
NULL );
ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer;
if (ThisIoRun->TransferMdl == NULL) {
IrpContext->Irp->IoStatus.Information = 0;
CdRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
}
MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl );
}
//
// Remember we found an unaligned transfer.
//
FoundUnaligned = TRUE;
//
// Otherwise we use the buffer and Mdl from the original request.
//
} else {
//
// Truncate the read length to a sector-aligned value. We know
// the length must be at least one sector or we wouldn't be
// here now.
//
CurrentByteCount = SectorTruncate( CurrentByteCount );
//
// Read these sectors from the disk.
//
ThisIoRun->DiskOffset = DiskOffset;
ThisIoRun->DiskByteCount = CurrentByteCount;
//
// Use the user's buffer and Mdl as our transfer buffer
// and Mdl.
//
ThisIoRun->TransferBuffer = CurrentUserBuffer;
ThisIoRun->TransferMdl = Irp->MdlAddress;
ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
CurrentUserBufferOffset,
PVOID );
ScratchUserBuffer = Add2Ptr( CurrentUserBuffer,
CurrentByteCount,
PVOID );
ScratchUserBufferOffset += CurrentByteCount;
}
//
// Update our position in the transfer and the RunCount and
// ByteCount for the user.
//
RemainingByteCount -= CurrentByteCount;
//
// Break out if no more positions in the IoRuns array or
// we have all of the bytes accounted for.
//
*ThisByteCount += CurrentByteCount;
if ((RemainingByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) {
break;
}
//
// Update our pointers for the user's buffer.
//
ThisIoRun += 1;
CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID );
CurrentUserBufferOffset += CurrentByteCount;
CurrentFileOffset += CurrentByteCount;
}
return FoundUnaligned;
}
//
// Local support routine
//
VOID
CdPrepareXABuffers (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFCB Fcb,
IN PVOID UserBuffer,
IN ULONG UserBufferOffset,
IN LONGLONG StartingOffset,
IN ULONG ByteCount,
IN PIO_RUN IoRuns,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -