📄 ext2fs.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System for NT
* FILE: Ext2fs.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ntifs.h"
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
PEXT2_GLOBAL Ext2Global = NULL;
/* FUNCTIONS ***************************************************************/
LARGE_INTEGER
Ext2SysTime (IN ULONG i_time)
{
LARGE_INTEGER SysTime;
SysTime.QuadPart = (LONGLONG)(i_time) * 10000000;
SysTime.QuadPart += Ext2Global->TimeZone.QuadPart;
return SysTime;
}
ULONG
Ext2InodeTime (IN LARGE_INTEGER SysTime)
{
return (ULONG)((SysTime.QuadPart - Ext2Global->TimeZone.QuadPart) / 10000000);
}
NTSTATUS
Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN PVOID Buffer)
{
LARGE_INTEGER sectorNumber;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS Status;
ULONG sectorSize;
// KdPrint(("Ext2ReadSectors(pDeviceObject %xh, lba %xh, sectors: %xh Buffer %xh)\n",
// pDeviceObject,DiskSector, SectorCount, Buffer));
sectorNumber.u.HighPart = 0;
sectorNumber.u.LowPart = DiskSector * SECTOR_SIZE;
KeInitializeEvent(&event, NotificationEvent, FALSE);
sectorSize = SECTOR_SIZE * SectorCount;
irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
pDeviceObject,
Buffer,
sectorSize,
§orNumber,
&event,
&ioStatus );
if (irp == NULL)
{
return STATUS_UNSUCCESSFUL;
}
Status = IoCallDriver(pDeviceObject, irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);
Status = ioStatus.Status;
}
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2ReadSectors IO failed!!! Error code: %d(%x)\n", Status, Status));
return Status;
}
return Status;
}
NTSTATUS
Ext2WriteSectors(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN PVOID Buffer)
{
LARGE_INTEGER sectorNumber;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS Status;
ULONG sectorSize;
KdPrint(("Ext2WriteSectors(pDeviceObject %xh, lba %xh, sectors: %xh Buffer %xh)\n",
pDeviceObject,DiskSector, SectorCount, Buffer));
sectorNumber.u.HighPart = 0;
sectorNumber.u.LowPart = DiskSector * SECTOR_SIZE;
KeInitializeEvent(&event, NotificationEvent, FALSE);
sectorSize = SECTOR_SIZE * SectorCount;
irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
pDeviceObject,
Buffer,
sectorSize,
§orNumber,
&event,
&ioStatus );
if (irp == NULL)
{
KdPrint(("Ext2WriteSectors: WRITE failed!!!\n"));
return STATUS_UNSUCCESSFUL;
}
Status = IoCallDriver(pDeviceObject,
irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);
Status = ioStatus.Status;
}
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2WriteSectors: IO failed!!! Error code: %d(%x)\n", Status, Status));
return Status;
}
KdPrint(("Ext2WriteSectors: Block request succeeded.\n"));
return Status;
}
NTSTATUS
Ext2ReadDisk(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG lba,
IN ULONG offset,
IN ULONG Size,
IN PVOID Buffer)
{
ULONG Sectors;
NTSTATUS Status;
PUCHAR Buf;
ULONG off = 0;
if (offset >= SECTOR_SIZE)
lba += offset / SECTOR_SIZE;
off = offset % SECTOR_SIZE;
Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;
// KdPrint(("Ext2ReadDisk: lba %xh, offset: %xh size: %xh Sectors:%xh.\n",
// lba, offset, Size, Sectors));
Buf = ExAllocatePool(NonPagedPool, Sectors * SECTOR_SIZE);
if (!Buf)
{
KdPrint(("Ext2ReadDisk: no enough memory.\n"));
return STATUS_UNSUCCESSFUL;
}
Status = Ext2ReadSectors(pDeviceObject, lba, Sectors, Buf);
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2ReadDisk: Read Block Device error.\n"));
ExFreePool(Buf);
return Status;
}
RtlCopyMemory(Buffer, &Buf[off], Size);
ExFreePool(Buf);
return Status;
}
NTSTATUS
Ext2WriteDisk(IN PDEVICE_OBJECT pDeviceObject,
IN ULONG lba,
IN ULONG offset,
IN ULONG Size,
IN PVOID Buffer)
{
ULONG Sectors;
NTSTATUS Status;
PUCHAR Buf;
ULONG off = 0;
if (offset >= SECTOR_SIZE)
lba += offset / SECTOR_SIZE;
off = offset % SECTOR_SIZE;
Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;
Sectors = (off + Size + SECTOR_SIZE - 1) / SECTOR_SIZE;
Buf = ExAllocatePool(NonPagedPool, Sectors * SECTOR_SIZE);
if (!Buf)
{
KdPrint(("Ext2WriteDisk: no enough memory.\n"));
return STATUS_UNSUCCESSFUL;
}
if (off)
{
Ext2ReadSectors(pDeviceObject, lba, 1, Buf);
}
if (((off + Size) % SECTOR_SIZE) != 0)
{
if ((Sectors != 1) || offset == 0)
Ext2ReadSectors(pDeviceObject, lba + Sectors - 1, 1, Buf);
}
RtlCopyMemory(&Buf[off], Buffer, Size);
Status = Ext2WriteSectors(pDeviceObject, lba, Sectors, Buf);
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2WriteDisk: Write Block Device error.\n"));
}
ExFreePool(Buf);
return Status;
}
NTSTATUS
Ext2DiskIoControl (IN PDEVICE_OBJECT pDeviceObject,
IN ULONG IoctlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer,
IN OUT PULONG OutputBufferSize)
{
ULONG OutBufferSize = 0;
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
PAGED_CODE();
ASSERT(pDeviceObject != NULL);
if (OutputBufferSize)
{
OutBufferSize = *OutputBufferSize;
}
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(
IoctlCode,
pDeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutBufferSize,
FALSE,
&Event,
&IoStatus
);
if (Irp == NULL)
{
KdPrint(("Ext2DiskIoControl: Building IRQ error!\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(pDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = IoStatus.Information;
}
return Status;
}
NTSTATUS
Ext2ReadDiskOverrideVerify (IN PDEVICE_OBJECT pDeviceObject,
IN ULONG DiskSector,
IN ULONG SectorCount,
IN OUT PUCHAR Buffer)
{
PIO_STACK_LOCATION IoStackLocation;
LARGE_INTEGER sectorNumber;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
KEVENT event;
NTSTATUS Status;
ULONG sectorSize;
PAGED_CODE();
sectorNumber.u.LowPart = DiskSector << 9;
sectorNumber.u.HighPart = DiskSector >> 23;
KeInitializeEvent (&event, NotificationEvent, FALSE);
sectorSize = SECTOR_SIZE * SectorCount;
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ,
pDeviceObject,
Buffer,
sectorSize,
§orNumber,
&event,
&IoStatus);
if (!Irp)
{
KdPrint(("Ext2ReadDiskOverrideVerify: IoBuildSynchronousFsdRequest failed\n"));
return(STATUS_UNSUCCESSFUL);;
}
IoStackLocation = IoGetNextIrpStackLocation(Irp);
IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
Status = IoCallDriver (pDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (!NT_SUCCESS (Status))
{
KdPrint(("Ext2ReadDiskOverrideVerify: IO failed! Error code: %x\n", Status));
return (Status);
}
return (STATUS_SUCCESS);
}
struct ext2_super_block *
Ext2LoadSuper(IN PDEVICE_OBJECT pDeviceObject)
{
PVOID Buffer;
NTSTATUS Status;
Buffer = ExAllocatePool(NonPagedPool, 2 * SECTOR_SIZE);
if (!Buffer)
{
KdPrint(("Ext2LoadSuper: no enough memory.\n"));
return NULL;
}
Status = Ext2ReadDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, Buffer);
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2ReadDisk: Read Block Device error.\n"));
ExFreePool(Buffer);
return NULL;
}
return (struct ext2_super_block *)Buffer;
}
NTSTATUS
Ext2SaveSuper(IN PDEVICE_OBJECT pDeviceObject,
IN struct ext2_super_block * sb)
{
return Ext2WriteDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, (PVOID)sb);
}
struct ext2_group_desc *
Ext2LoadGroup(IN PEXT2_VCB vcb)
{
ULONG size;
ULONG lba;
PVOID Buffer;
NTSTATUS Status;
PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;
struct ext2_super_block * sb = vcb->ext2_super_block;
vcb->ext2_block = EXT2_MIN_BLOCK << sb->s_log_block_size;
vcb->ext2_frag = EXT2_MIN_FRAG << sb->s_log_frag_size;
vcb->ext2_groups = (sb->s_blocks_count - sb->s_first_data_block +
sb->s_blocks_per_group - 1) / sb->s_blocks_per_group;
size = sizeof(struct ext2_group_desc) * vcb->ext2_groups;
Buffer = ExAllocatePool(NonPagedPool, size);
if (!Buffer)
{
KdPrint(("Ext2LoadSuper: no enough memory.\n"));
return NULL;
}
if (vcb->ext2_block == EXT2_MIN_BLOCK)
{
lba = 2 * (vcb->ext2_block / SECTOR_SIZE);
}
if (vcb->ext2_block > EXT2_MIN_BLOCK)
{
lba = vcb->ext2_block / SECTOR_SIZE;
}
Status = Ext2ReadDisk(pDeviceObject, lba, 0, size, Buffer);
if (!NT_SUCCESS(Status))
{
KdPrint(("Ext2LoadGroup: Read Block Device error.\n"));
ExFreePool(Buffer);
return NULL;
}
return (struct ext2_group_desc *)Buffer;
}
NTSTATUS
Ext2SaveGroup(IN PEXT2_VCB vcb,
IN struct ext2_group_desc * gd)
{
ULONG lba;
ULONG size;
PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;
size = vcb->ext2_groups * sizeof(struct ext2_group_desc);
if (vcb->ext2_block == EXT2_MIN_BLOCK)
{
lba = 2 * (vcb->ext2_block / SECTOR_SIZE);
}
if (vcb->ext2_block > EXT2_MIN_BLOCK)
{
lba = vcb->ext2_block / SECTOR_SIZE;
}
return Ext2WriteDisk(pDeviceObject, lba, 0, size, (PVOID)gd);
}
BOOLEAN
Ext2GetInodeLba (IN PEXT2_VCB vcb,
IN ULONG inode,
OUT PULONG lba,
OUT PULONG offset)
{
ULONG loc;
if (inode < 1 || inode > vcb->ext2_super_block->s_inodes_count)
{
KdPrint(("Ext2GetInodeLba: Inode value %xh is invalid.\n",inode));
*lba = 0;
*offset = 0;
return FALSE;
}
loc = vcb->ext2_group_desc[(inode - 1) / vcb->ext2_super_block->s_inodes_per_group].bg_inode_table * vcb->ext2_block +
((inode - 1) % vcb->ext2_super_block->s_inodes_per_group) * sizeof(struct ext2_inode);
*lba = loc / SECTOR_SIZE;
*offset = loc % SECTOR_SIZE;
// KdPrint(("Ext2GetInodeLba: inode=%xh lba=%xh offset=%xh\n",
// inode, *lba, *offset));
return TRUE;
}
BOOLEAN
Ext2LoadInode (IN PEXT2_VCB vcb,
IN ULONG inode,
IN struct ext2_inode *ext2_inode)
{
ULONG lba;
ULONG offset;
NTSTATUS Status;
if (!Ext2GetInodeLba(vcb, inode, &lba, &offset))
{
KdPrint(("Ext2LoadInode: error get inode(%xh)'s addr.\n", inode));
return FALSE;
}
Status = Ext2ReadDisk(vcb->TargetDeviceObject,
lba,
offset,
sizeof(EXT2_INODE),
(PVOID)ext2_inode);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
BOOLEAN
Ext2SaveInode (IN PEXT2_VCB vcb,
IN ULONG inode,
IN struct ext2_inode *ext2_inode)
{
ULONG lba;
ULONG offset;
NTSTATUS Status;
if (!Ext2GetInodeLba(vcb, inode, &lba, &offset))
{
KdPrint(("Ext2LoadInode: error get inode(%xh)'s addr.\n", inode));
return FALSE;
}
Status = Ext2WriteDisk(vcb->TargetDeviceObject,
lba,
offset,
sizeof(EXT2_INODE),
(PVOID)ext2_inode);
if (!NT_SUCCESS(Status))
{
return FALSE;
}
return TRUE;
}
ULONG Ext2GetBlock(IN PEXT2_VCB vcb,
ULONG dwContent,
ULONG Index,
int layer )
{
ULONG *pData = NULL;
ULONG lba = 0;
ULONG i = 0, j = 0, temp = 1;
ULONG dwBlk = 0;
lba = dwContent * vcb->ext2_block / SECTOR_SIZE;
if (layer == 0)
{
dwBlk = dwContent;
}
else if (layer <= 3)
{
pData = (ULONG *)ExAllocatePool(NonPagedPool,
vcb->ext2_block);
if (!pData)
{
KdPrint(("Ext2GetBlock: no enough memory.\n"));
return dwBlk;
}
Ext2ReadDisk(vcb->TargetDeviceObject, lba, 0, vcb->ext2_block, (PVOID)pData);
for (i=0; i<(ULONG)(layer - 1); i++)
{
temp *= (vcb->ext2_block/4);
}
i = Index / temp;
j = Index % temp;
dwBlk = Ext2GetBlock(vcb, pData[i], j, layer - 1);
ExFreePool(pData);
}
return dwBlk;
}
ULONG Ext2BlockMap(IN PEXT2_VCB vcb,
IN struct ext2_inode* ext2_inode,
IN ULONG Index)
{
ULONG dwSizes[3] = {vcb->ext2_block / 4, 0, 0};
int i;
if (Index >= ext2_inode->i_blocks)
{
KdPrint(("Ext2BlockMap: error input paramters.\n"));
return 0;
}
if (Index < 12)
{
return ext2_inode->i_block[Index];
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -