⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 * FFS File System Driver for Windows
 *
 * read.c
 *
 * 2004.5.6 ~
 *
 * Lee Jae-Hong, http://www.pyrasis.com
 *
 * See License.txt
 *
 */

#include "ntifs.h"
#include "ffsdrv.h"

/* Globals */

extern PFFS_GLOBAL FFSGlobal;


/* Definitions */

NTSTATUS
FFSReadComplete(
	IN PFFS_IRP_CONTEXT IrpContext);

NTSTATUS
FFSReadFile(
	IN PFFS_IRP_CONTEXT IrpContext);

NTSTATUS
FFSReadVolume(
	IN PFFS_IRP_CONTEXT IrpContext);

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSCompleteIrpContext)
#pragma alloc_text(PAGE, FFSCopyRead)
#pragma alloc_text(PAGE, FFSRead)
#pragma alloc_text(PAGE, FFSReadVolume)
#pragma alloc_text(PAGE, FFSv1ReadInode)
#pragma alloc_text(PAGE, FFSReadFile)
#pragma alloc_text(PAGE, FFSReadComplete)

#endif


NTSTATUS
FFSCompleteIrpContext(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN NTSTATUS         Status)
{
	PIRP    Irp = NULL;
	BOOLEAN bPrint;

	Irp = IrpContext->Irp;

	if (Irp != NULL)
	{
		if (NT_ERROR(Status))
		{
			Irp->IoStatus.Information = 0;
		}

		Irp->IoStatus.Status = Status;
		bPrint = !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

		FFSCompleteRequest(
				Irp, bPrint, (CCHAR)(NT_SUCCESS(Status)?
					IO_DISK_INCREMENT : IO_NO_INCREMENT));

		IrpContext->Irp = NULL;               
	}

	FFSFreeIrpContext(IrpContext);

	return Status;
}


BOOLEAN 
FFSCopyRead(
	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
FFSReadVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb;
	PFFS_CCB            Ccb;
	PFFS_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;
	PFFS_BDL            ffs_bdl = NULL;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;

		ASSERT(FcbOrVcb);

		if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		Ccb = (PFFS_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);
				}
			}

			{
				FFS_BDL BlockArray;

				if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
						(Length & (SECTOR_SIZE - 1)))
				{
					Status = STATUS_INVALID_PARAMETER;
					__leave;
				}

				Status = FFSLockUserBuffer(
							IrpContext->Irp,
							Length,
							IoReadAccess);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				BlockArray.Irp = NULL;
				BlockArray.Lba = ByteOffset.QuadPart;;
				BlockArray.Offset = 0;
				BlockArray.Length = Length;

				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							&BlockArray,
							Length,
							1,
							FALSE);
				Irp = IrpContext->Irp;

				__leave;
			}
		}

		if (Nocache &&
				((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
				  (Length & (SECTOR_SIZE - 1))))
		{
			FFSBreakPoint();

			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 = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();
					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 = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoWriteAccess);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

#if DBG
			Buffer = FFSGetUserBuffer(Irp);
#endif
			ffs_bdl = ExAllocatePool(PagedPool, sizeof(FFS_BDL));

			if (!ffs_bdl)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			ffs_bdl->Irp = NULL;
			ffs_bdl->Lba = ByteOffset.QuadPart;
			ffs_bdl->Length = Length;
			ffs_bdl->Offset = 0;

			Status = FFSReadWriteBlocks(IrpContext,
						Vcb,
						ffs_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 (ffs_bdl)
			ExFreePool(ffs_bdl);

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING &&
						!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED))
				{
					Status = FFSLockUserBuffer(
								IrpContext->Irp,
								Length,
								IoWriteAccess);

					if (NT_SUCCESS(Status))
					{
						Status = FFSQueueRequest(IrpContext);
					}
					else
					{
						FFSCompleteIrpContext(IrpContext, Status);
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							FileObject->Flags &= ~FO_FILE_FAST_IO_READ;
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);;
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;
}


NTSTATUS
FFSv1ReadInode(
	IN PFFS_IRP_CONTEXT     IrpContext,
	IN PFFS_VCB             Vcb,
	IN PFFSv1_INODE         dinode1,
	IN ULONGLONG            offset,
	IN PVOID                Buffer,
	IN ULONG                size,
	OUT PULONG              dwRet)
{
	PFFS_BDL    ffs_bdl = NULL;
	ULONG       blocks, i;
	NTSTATUS    Status = STATUS_UNSUCCESSFUL;
	IO_STATUS_BLOCK IoStatus;

	ULONG       Totalblocks;
	LONGLONG    AllocSize;

	if (dwRet)
	{
		*dwRet = 0;
	}

	Totalblocks = (dinode1->di_blocks);
	AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);

	if ((LONGLONG)offset >= AllocSize)
	{
		FFSPrint((DBG_ERROR, "FFSv1ReadInode: beyond the file range.\n"));
		return STATUS_SUCCESS;
	}

	if ((LONGLONG)offset + size > AllocSize)
	{
		size = (ULONG)(AllocSize - offset);
	}

	blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);

	if (blocks <= 0)
	{
		FFSBreakPoint();
		goto errorout;
	}

	if (IrpContext)
	{
		// assume offset is aligned.
		Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
	}
	else
	{
		for(i = 0; i < blocks; i++)
		{
			IoStatus.Information = 0;

#if DBG
			KdPrint(("FFSv1ReadInode() i : %d, Lba : %x, Length : %x, Offset : %x\n", 
				i, ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
#endif

			FFSCopyRead(
					Vcb->StreamObj, 
					(PLARGE_INTEGER)(&(ffs_bdl[i].Lba)), 
					ffs_bdl[i].Length,
					PIN_WAIT,
					(PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset), 
					&IoStatus);

			Status = IoStatus.Status;
		}
	}

errorout:

	if (ffs_bdl)
		ExFreePool(ffs_bdl);

	if (NT_SUCCESS(Status))
	{
		if (dwRet) *dwRet = size;
	}

	return Status;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -