📄 read.c
字号:
/*
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
* FILE: read.c
* PURPOSE:
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brant閚.
* HOMEPAGE:
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "rfsd.h"
/* GLOBALS ***************************************************************/
extern PRFSD_GLOBAL RfsdGlobal;
/* DEFINITIONS *************************************************************/
NTSTATUS
RfsdReadComplete (IN PRFSD_IRP_CONTEXT IrpContext);
NTSTATUS
RfsdReadFile (IN PRFSD_IRP_CONTEXT IrpContext);
NTSTATUS
RfsdReadVolume (IN PRFSD_IRP_CONTEXT IrpContext);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdCompleteIrpContext)
#pragma alloc_text(PAGE, RfsdCopyRead)
#pragma alloc_text(PAGE, RfsdRead)
#pragma alloc_text(PAGE, RfsdReadVolume)
#pragma alloc_text(PAGE, RfsdReadInode)
#pragma alloc_text(PAGE, RfsdReadFile)
#pragma alloc_text(PAGE, RfsdReadComplete)
#endif
/* FUNCTIONS *************************************************************/
/** Proxy to CcCopyRead, which simply asserts the success of the IoStatus. */
BOOLEAN
RfsdCopyRead(
IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus
)
{
BOOLEAN bRet;
bRet= CcCopyRead(FileObject,
FileOffset,
Length,
Wait,
Buffer,
IoStatus );
if (bRet) {
ASSERT(NT_SUCCESS(IoStatus->Status));
}
return bRet;
/*
PVOID Bcb = NULL;
PVOID Buf = NULL;
if (CcMapData( FileObject,
FileOffset,
Length,
Wait,
&Bcb,
&Buf )) {
RtlCopyMemory(Buffer, Buf, Length);
IoStatus->Status = STATUS_SUCCESS;
IoStatus->Information = Length;
CcUnpinData(Bcb);
return TRUE;
} else {
// IoStatus->Status = STATUS_
return FALSE;
}
*/
}
NTSTATUS
RfsdReadVolume (IN PRFSD_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PRFSD_VCB Vcb;
PRFSD_CCB Ccb;
PRFSD_FCBVCB FcbOrVcb;
PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG Length;
LARGE_INTEGER ByteOffset;
BOOLEAN PagingIo;
BOOLEAN Nocache;
BOOLEAN SynchronousIo;
BOOLEAN MainResourceAcquired = FALSE;
BOOLEAN PagingIoResourceAcquired = FALSE;
PUCHAR Buffer = NULL;
PRFSD_BDL rfsd_bdl = NULL;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
FileObject = IrpContext->FileObject;
FcbOrVcb = (PRFSD_FCBVCB) FileObject->FsContext;
ASSERT(FcbOrVcb);
if (!(FcbOrVcb->Identifier.Type == RFSDVCB && (PVOID)FcbOrVcb == (PVOID)Vcb)) {
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Ccb = (PRFSD_CCB) FileObject->FsContext2;
Irp = IrpContext->Irp;
Irp->IoStatus.Information = 0;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
Length = IoStackLocation->Parameters.Read.Length;
ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
if (Length == 0) {
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
__leave;
}
if (Ccb != NULL) {
if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO)) {
if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart) {
Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
}
}
{
RFSD_BDL BlockArray;
if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
(Length & (SECTOR_SIZE - 1)) ) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (!NT_SUCCESS(Status)) {
__leave;
}
BlockArray.Irp = NULL;
BlockArray.Lba = ByteOffset.QuadPart;;
BlockArray.Offset = 0;
BlockArray.Length = Length;
Status = RfsdReadWriteBlocks(IrpContext,
Vcb,
&BlockArray,
Length,
1,
FALSE );
Irp = IrpContext->Irp;
__leave;
}
}
if (Nocache &&
( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
(Length & (SECTOR_SIZE - 1)) )) {
DbgBreak();
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
Status = STATUS_PENDING;
__leave;
}
if (!PagingIo) {
if (!ExAcquireResourceSharedLite(
&Vcb->MainResource,
IrpContext->IsSynchronous )) {
Status = STATUS_PENDING;
__leave;
}
MainResourceAcquired = TRUE;
} else {
if (!ExAcquireResourceSharedLite(
&Vcb->PagingIoResource,
IrpContext->IsSynchronous ))
{
Status = STATUS_PENDING;
__leave;
}
PagingIoResourceAcquired = TRUE;
}
if (ByteOffset.QuadPart >=
Vcb->PartitionInformation.PartitionLength.QuadPart ) {
Irp->IoStatus.Information = 0;
Status = STATUS_END_OF_FILE;
__leave;
}
if (!Nocache) {
if ((ByteOffset.QuadPart + Length) >
Vcb->PartitionInformation.PartitionLength.QuadPart ){
Length = (ULONG) (
Vcb->PartitionInformation.PartitionLength.QuadPart -
ByteOffset.QuadPart);
Length &= ~((ULONG)SECTOR_SIZE - 1);
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) {
CcMdlRead(
Vcb->StreamObj,
&ByteOffset,
Length,
&Irp->MdlAddress,
&Irp->IoStatus );
Status = Irp->IoStatus.Status;
} else {
Buffer = RfsdGetUserBuffer(Irp);
if (Buffer == NULL) {
DbgBreak();
Status = STATUS_INVALID_USER_BUFFER;
__leave;
}
if (!CcCopyRead(
Vcb->StreamObj,
(PLARGE_INTEGER)&ByteOffset,
Length,
IrpContext->IsSynchronous,
Buffer,
&Irp->IoStatus )) {
Status = STATUS_PENDING;
__leave;
}
Status = Irp->IoStatus.Status;
}
} else {
if ((ByteOffset.QuadPart + Length) >
Vcb->PartitionInformation.PartitionLength.QuadPart ) {
Length = (ULONG) (
Vcb->PartitionInformation.PartitionLength.QuadPart -
ByteOffset.QuadPart);
Length &= ~((ULONG)SECTOR_SIZE - 1);
}
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoWriteAccess );
if (!NT_SUCCESS(Status)) {
__leave;
}
#if DBG
Buffer = RfsdGetUserBuffer(Irp);
#endif
rfsd_bdl = ExAllocatePool(PagedPool, sizeof(RFSD_BDL));
if (!rfsd_bdl)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
rfsd_bdl->Irp = NULL;
rfsd_bdl->Lba = ByteOffset.QuadPart;
rfsd_bdl->Length = Length;
rfsd_bdl->Offset = 0;
Status = RfsdReadWriteBlocks(IrpContext,
Vcb,
rfsd_bdl,
Length,
1,
FALSE );
if (NT_SUCCESS(Status)) {
Irp->IoStatus.Information = Length;
}
Irp = IrpContext->Irp;
if (!Irp)
__leave;
}
} __finally {
if (PagingIoResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->PagingIoResource,
ExGetCurrentResourceThread());
}
if (MainResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (rfsd_bdl)
ExFreePool(rfsd_bdl);
if (!IrpContext->ExceptionInProgress) {
if (Irp) {
if (Status == STATUS_PENDING &&
!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED)) {
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoWriteAccess );
if (NT_SUCCESS(Status)) {
Status = RfsdQueueRequest(IrpContext);
} else {
RfsdCompleteIrpContext(IrpContext, Status);
}
} else {
if (NT_SUCCESS(Status)) {
if (!PagingIo) {
if (SynchronousIo) {
FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + Irp->IoStatus.Information;
}
FileObject->Flags |= FO_FILE_FAST_IO_READ;
}
}
RfsdCompleteIrpContext(IrpContext, Status);;
}
} else {
RfsdFreeIrpContext(IrpContext);
}
}
}
return Status;
}
// [mark] read some goop [from the file pt'd to by inode -- from whatever blocks buildbdl makes] into the buffer
NTSTATUS
RfsdReadInode (
IN PRFSD_IRP_CONTEXT IrpContext, // [may be null]
IN PRFSD_VCB Vcb,
IN PRFSD_KEY_IN_MEMORY Key, // Key that identifies the data on disk to be read. This is simply forwarded through to BuildBDL. (NOTE: IN THIS CASE, THE OFFSET AND TYPE FIELDS MATTER)
IN PRFSD_INODE Inode, // a filled Inode / stat data structure
IN ULONGLONG Offset, // User's requested offset to read within the file (relative to the file)
IN OUT PVOID Buffer, // buffer to read out to
IN ULONG Size, // size of destination buffer
OUT PULONG dwRet ) // some kind of size [probably bytes read?]
{
PRFSD_BDL Bdl = NULL;
ULONG blocks, i, j;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
IO_STATUS_BLOCK IoStatus;
ULONGLONG FileSize;
ULONGLONG AllocSize;
if (dwRet) {
*dwRet = 0;
}
//
// Calculate the inode size
//
FileSize = (ULONGLONG) Inode->i_size;
//KdPrint(("Rfsd: RfsdReadInode: file size = %I64u, offset = %I64u, length = %u\n", FileSize, Offset, Size));
// TODO: temporary hack to get correct alloc size for dir tails... but i doubt 8 works in all cases :-) [what i should really be using is the size of the direct item in the block header!]
// AllocSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);
// AllocSize = CEILING_ALIGNED(FileSize, (ULONGLONG) 8);
AllocSize = CEILING_ALIGNED(FileSize, (ULONGLONG) 1); // temp hack to ensure that i'll read out EXACTLY the # of bytes he requested
//
// Check inputed parameters: Offset / Size
//
if (Offset >= AllocSize) {
RfsdPrint((DBG_ERROR, "RfsdReadInode: beyond the file range.\n"));
return STATUS_SUCCESS;
}
if (Offset + Size > AllocSize) {
Size = (ULONG)(AllocSize - Offset);
}
//-----------------------------
//
// Build the scatterred block ranges to be read
//
Status = RfsdBuildBDL2(
Vcb, Key, Inode,
&(blocks), &(Bdl)
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -