📄 blockio.c
字号:
/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: blockio.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brant閚.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
typedef struct _RFSD_RW_CONTEXT {
PIRP MasterIrp;
KEVENT Event;
BOOLEAN Wait;
ULONG Blocks;
ULONG Length;
} RFSD_RW_CONTEXT, *PRFSD_RW_CONTEXT;
NTSTATUS
RfsdReadWriteBlockSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context );
NTSTATUS
RfsdReadWriteBlockAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context );
NTSTATUS
RfsdMediaEjectControlCompletion (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdLockUserBuffer)
#pragma alloc_text(PAGE, RfsdGetUserBuffer)
#pragma alloc_text(PAGE, RfsdReadSync)
#pragma alloc_text(PAGE, RfsdReadDisk)
#pragma alloc_text(PAGE, RfsdDiskIoControl)
#pragma alloc_text(PAGE, RfsdReadWriteBlocks)
#pragma alloc_text(PAGE, RfsdMediaEjectControl)
#pragma alloc_text(PAGE, RfsdDiskShutDown)
#endif
/* FUNCTIONS ***************************************************************/
NTSTATUS
RfsdLockUserBuffer (IN PIRP Irp,
IN ULONG Length,
IN LOCK_OPERATION Operation)
{
NTSTATUS Status;
ASSERT(Irp != NULL);
if (Irp->MdlAddress != NULL) {
return STATUS_SUCCESS;
}
IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
if (Irp->MdlAddress == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
__try {
MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
Status = STATUS_SUCCESS;
} __except (EXCEPTION_EXECUTE_HANDLER) {
IoFreeMdl(Irp->MdlAddress);
Irp->MdlAddress = NULL;
DbgBreak();
Status = STATUS_INVALID_USER_BUFFER;
}
return Status;
}
PVOID
RfsdGetUserBuffer (IN PIRP Irp )
{
ASSERT(Irp != NULL);
if (Irp->MdlAddress) {
#if (_WIN32_WINNT >= 0x0500)
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
#else
return MmGetSystemAddressForMdl(Irp->MdlAddress);
#endif
} else {
return Irp->UserBuffer;
}
}
NTSTATUS
RfsdReadWriteBlockSyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context )
{
PRFSD_RW_CONTEXT pContext = (PRFSD_RW_CONTEXT)Context;
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
DbgBreak(); // [mark]
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
IoFreeMdl( Irp->MdlAddress );
IoFreeIrp( Irp );
if (InterlockedDecrement(&pContext->Blocks) == 0) {
pContext->MasterIrp->IoStatus.Information = 0;
if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) {
pContext->MasterIrp->IoStatus.Information =
pContext->Length;
}
KeSetEvent( &pContext->Event, 0, FALSE );
}
UNREFERENCED_PARAMETER( DeviceObject );
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
RfsdReadWriteBlockAsyncCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PRFSD_RW_CONTEXT pContext = (PRFSD_RW_CONTEXT)Context;
if (!NT_SUCCESS( Irp->IoStatus.Status )) {
DbgBreak(); // [mark]
pContext->MasterIrp->IoStatus = Irp->IoStatus;
}
if (InterlockedDecrement(&pContext->Blocks) == 0) {
pContext->MasterIrp->IoStatus.Information = 0;
if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status)) {
pContext->MasterIrp->IoStatus.Information =
pContext->Length;
}
IoMarkIrpPending( pContext->MasterIrp );
ExFreePool(pContext);
}
UNREFERENCED_PARAMETER( DeviceObject );
return STATUS_SUCCESS;
}
// Looks like this is really just getting an MDL (memory descriptor list) from the MM and doing its business...
// ... but IoCallDriver is what will actually read from the disk device to furnish non-chached or paging IO operations!
// NOTE: It is vital that IoCallDriver use sector-aligned offset and length (otherwise, 0xc000000d = STATUS_INVALID_PARAMETER) will result!
NTSTATUS
RfsdReadWriteBlocks(
IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN PRFSD_BDL RfsdBDL, // The block-description list
IN ULONG Length, // Length of data to read
IN ULONG Count, // Count of blocks inside the BDL
IN BOOLEAN bVerify )
{
PMDL Mdl;
PIRP Irp;
PIRP MasterIrp = IrpContext->Irp;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_SUCCESS;
PRFSD_RW_CONTEXT pContext = NULL;
ULONG i;
BOOLEAN bBugCheck = FALSE;
ASSERT(MasterIrp);
__try {
pContext = ExAllocatePool(NonPagedPool, sizeof(RFSD_RW_CONTEXT));
if (!pContext) {
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(pContext, sizeof(RFSD_RW_CONTEXT));
pContext->Wait = IrpContext->IsSynchronous;
pContext->MasterIrp = MasterIrp;
pContext->Blocks = Count;
pContext->Length = 0;
if (pContext->Wait) {
KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);
}
for (i = 0; i < Count; i++) {
Irp = IoMakeAssociatedIrp(
MasterIrp,
(CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );
if (!Irp) {
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
RfsdBDL[i].Offset,
RfsdBDL[i].Length,
FALSE,
FALSE,
Irp );
if (!Mdl) {
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
IoBuildPartialMdl( MasterIrp->MdlAddress,
Mdl,
(PCHAR)MasterIrp->UserBuffer + RfsdBDL[i].Offset,
RfsdBDL[i].Length );
IoSetNextIrpStackLocation( Irp );
IrpSp = IoGetCurrentIrpStackLocation( Irp );
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = RfsdBDL[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = RfsdBDL[i].Lba;
IoSetCompletionRoutine(
Irp,
((IrpContext->IsSynchronous) ?
(&RfsdReadWriteBlockSyncCompletionRoutine) :
(&RfsdReadWriteBlockAsyncCompletionRoutine)),
(PVOID) pContext,
TRUE,
TRUE,
TRUE );
IrpSp = IoGetNextIrpStackLocation( Irp );
IrpSp->MajorFunction = IrpContext->MajorFunction;
IrpSp->Parameters.Read.Length = RfsdBDL[i].Length;
IrpSp->Parameters.Read.ByteOffset.QuadPart = RfsdBDL[i].Lba;
if (bVerify) {
SetFlag( IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
}
RfsdBDL[i].Irp = Irp;
}
MasterIrp->AssociatedIrp.IrpCount = Count;
if (IrpContext->IsSynchronous) {
MasterIrp->AssociatedIrp.IrpCount += 1;
}
pContext->Length = Length;
bBugCheck = TRUE;
for (i = 0; i < Count; i++) {
Status = IoCallDriver ( Vcb->TargetDeviceObject,
RfsdBDL[i].Irp);
}
if (IrpContext->IsSynchronous) {
KeWaitForSingleObject( &(pContext->Event),
Executive, KernelMode, FALSE, NULL );
KeClearEvent( &(pContext->Event) );
}
} __finally {
if (IrpContext->IsSynchronous) {
if (MasterIrp)
Status = MasterIrp->IoStatus.Status;
if (pContext)
ExFreePool(pContext);
} else {
IrpContext->Irp = NULL;
Status = STATUS_PENDING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -