📄 ext2.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: Ext2.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ntifs.h"
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL g_gExt2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LoadSuper)
#pragma alloc_text(PAGE, Ext2SaveSuper)
#pragma alloc_text(PAGE, Ext2LoadGroup)
#pragma alloc_text(PAGE, Ext2SaveGroup)
#pragma alloc_text(PAGE, Ext2GetInodeLba)
#pragma alloc_text(PAGE, Ext2LoadInode)
#pragma alloc_text(PAGE, Ext2SaveInode)
#pragma alloc_text(PAGE, Ext2LoadBlock)
#pragma alloc_text(PAGE, Ext2SaveBlock)
#pragma alloc_text(PAGE, Ext2SaveBuffer)
#pragma alloc_text(PAGE, Ext2GetBlock)
#pragma alloc_text(PAGE, Ext2BlockMap)
#pragma alloc_text(PAGE, Ext2BuildBDL)
#pragma alloc_text(PAGE, Ext2NewBlock)
#pragma alloc_text(PAGE, Ext2FreeBlock)
#pragma alloc_text(PAGE, Ext2ExpandBlock)
#pragma alloc_text(PAGE, Ext2ExpandInode)
#pragma alloc_text(PAGE, Ext2NewInode)
#pragma alloc_text(PAGE, Ext2FreeInode)
#pragma alloc_text(PAGE, Ext2AddEntry)
#pragma alloc_text(PAGE, Ext2RemoveEntry)
#pragma alloc_text(PAGE, Ext2TruncateBlock)
#pragma alloc_text(PAGE, Ext2TruncateInode)
#pragma alloc_text(PAGE, Ext2AddMcbEntry)
#pragma alloc_text(PAGE, Ext2RemoveMcbEntry)
#pragma alloc_text(PAGE, Ext2LookupMcbEntry)
#endif
/* FUNCTIONS ***************************************************************/
PEXT2_SUPER_BLOCK
Ext2LoadSuper(IN PDEVICE_OBJECT pDeviceObject)
{
PVOID Buffer;
NTSTATUS Status;
Buffer = ExAllocatePool(NonPagedPool, 2 * SECTOR_SIZE);
if (!Buffer)
{
Ext2DbgPrint(D_EXT2, "Ext2LoadSuper: no enough memory.\n");
return NULL;
}
Status = Ext2ReadDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, Buffer);
if (!NT_SUCCESS(Status))
{
Ext2DbgPrint(D_EXT2, "Ext2ReadDisk: Read Block Device error.\n");
ExFreePool(Buffer);
return NULL;
}
return (struct ext2_super_block *)Buffer;
}
BOOLEAN
Ext2SaveSuper( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb )
{
LONGLONG Offset;
Offset = (LONGLONG) (2 * SECTOR_SIZE);
return Ext2SaveBuffer(IrpContext, Vcb, Offset, (2 * SECTOR_SIZE), Vcb->ext2_super_block);
}
PEXT2_GROUP_DESC
Ext2LoadGroup(IN PEXT2_VCB vcb)
{
ULONG size;
PVOID Buffer;
LONGLONG lba;
NTSTATUS Status;
PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;
struct ext2_super_block * sb = vcb->ext2_super_block;
vcb->ext2_block = EXT2_MIN_BLOCK_SIZE << sb->s_log_block_size;
vcb->ext2_frag = EXT2_MIN_FRAG_SIZE << 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(PagedPool, size);
if (!Buffer)
{
Ext2DbgPrint(D_EXT2, "Ext2LoadSuper: no enough memory.\n");
return NULL;
}
if (vcb->ext2_block == EXT2_MIN_BLOCK_SIZE)
{
lba = (LONGLONG)2 * vcb->ext2_block;
}
if (vcb->ext2_block > EXT2_MIN_BLOCK_SIZE)
{
lba = (LONGLONG) (vcb->ext2_block);
}
Status = Ext2ReadDisk(vcb->TargetDeviceObject, (ULONG)(lba / SECTOR_SIZE), 0, size, Buffer);
if (!NT_SUCCESS(Status))
{
ExFreePool(Buffer);
Buffer = NULL;
}
return (PEXT2_GROUP_DESC)Buffer;
}
BOOLEAN
Ext2SaveGroup( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb )
{
LONGLONG Offset;
ULONG Len;
if (Vcb->ext2_block == EXT2_MIN_BLOCK_SIZE) {
Offset = (LONGLONG) (2 * Vcb->ext2_block);
} else {
Offset = (LONGLONG) (Vcb->ext2_block);
}
Len = (ULONG)(sizeof(struct ext2_group_desc) * Vcb->ext2_groups);
return Ext2SaveBuffer(IrpContext, Vcb, Offset, Len, Vcb->ext2_group_desc);
}
BOOLEAN
Ext2GetInodeLba (IN PEXT2_VCB vcb,
IN ULONG inode,
OUT PLONGLONG offset)
{
LONGLONG loc;
if (inode < 1 || inode > vcb->ext2_super_block->s_inodes_count)
{
Ext2DbgPrint(D_EXT2, "Ext2GetInodeLba: Inode value %xh is invalid.\n",inode);
*offset = 0;
return FALSE;
}
loc = (vcb->ext2_group_desc[(inode - 1) / vcb->ext2_super_block->s_inodes_per_group].bg_inode_table);
loc = loc * vcb->ext2_block;
loc = loc + ((inode - 1) % (vcb->ext2_super_block->s_inodes_per_group)) * sizeof(EXT2_INODE);
*offset = loc;
// Ext2DbgPrint(D_EXT2, "Ext2GetInodeLba: inode=%xh lba=%xh offset=%xh\n",
// inode, *lba, *offset);
return TRUE;
}
BOOLEAN
Ext2LoadInode (IN PEXT2_VCB vcb,
IN ULONG inode,
IN PEXT2_INODE ext2_inode)
{
IO_STATUS_BLOCK IoStatus;
LONGLONG Offset;
if (!Ext2GetInodeLba(vcb, inode, &Offset))
{
Ext2DbgPrint(D_EXT2, "Ext2LoadInode: error get inode(%xh)'s addr.\n", inode);
return FALSE;
}
if (!Ext2CopyRead(
vcb->StreamObj,
(PLARGE_INTEGER)&Offset,
sizeof(EXT2_INODE),
TRUE,
(PVOID)ext2_inode,
&IoStatus ));
if (!NT_SUCCESS(IoStatus.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))
{
Ext2DbgPrint(D_EXT2, "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;
}
*/
BOOLEAN
Ext2SaveInode ( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG Inode,
IN PEXT2_INODE Ext2Inode)
{
LONGLONG Offset = 0;
LARGE_INTEGER CurrentTime;
KeQuerySystemTime(&CurrentTime);
Ext2Inode->i_mtime = Ext2Inode->i_atime =
(ULONG)(Ext2InodeTime(CurrentTime));
#if 0
Ext2DbgPrint(D_EXT2, "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n", Inode, Ext2Inode->i_mode, Ext2Inode->i_size);
#endif
if (!Ext2GetInodeLba(Vcb, Inode, &Offset))
{
Ext2DbgPrint(D_EXT2, "Ext2SaveInode: error get inode(%xh)'s addr.\n", Inode);
return FALSE;
}
return Ext2SaveBuffer(IrpContext, Vcb, Offset, sizeof(EXT2_INODE), Ext2Inode);
}
BOOLEAN
Ext2LoadBlock (IN PEXT2_VCB Vcb,
IN ULONG dwBlk,
IN PVOID Buffer )
{
IO_STATUS_BLOCK IoStatus;
LONGLONG Offset;
Offset = (LONGLONG) dwBlk;
Offset = Offset * Vcb->ext2_block;
if (!Ext2CopyRead(
Vcb->StreamObj,
(PLARGE_INTEGER)&Offset,
Vcb->ext2_block,
TRUE,
Buffer,
&IoStatus ));
if (!NT_SUCCESS(IoStatus.Status))
{
return FALSE;
}
return TRUE;
}
BOOLEAN
Ext2SaveBlock ( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG dwBlk,
IN PVOID Buf )
{
LONGLONG Offset;
Offset = (LONGLONG) dwBlk;
Offset = Offset * Vcb->ext2_block;
return Ext2SaveBuffer(IrpContext, Vcb, Offset, Vcb->ext2_block, Buf);
}
BOOLEAN
Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN LONGLONG Offset,
IN ULONG Size,
IN PVOID Buf )
{
PBCB Bcb;
PVOID Buffer;
if( !CcPinRead( Vcb->StreamObj,
(PLARGE_INTEGER) (&Offset),
Size,
TRUE,
&Bcb,
&Buffer ))
{
Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: PinReading error ...\n");
return FALSE;
}
#if 0
Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: Off=%I64xh Len=%xh Bcb=%xh\n", Offset, Size, (ULONG)Bcb);
#endif
RtlCopyMemory(Buffer, Buf, Size);
CcSetDirtyPinnedData(Bcb, NULL );
Ext2RepinBcb(IrpContext, Bcb);
CcUnpinData(Bcb);
SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
Ext2AddMcbEntry(Vcb, Offset, (LONGLONG)Size);
return TRUE;
}
ULONG Ext2GetBlock(IN PEXT2_VCB vcb,
ULONG dwContent,
ULONG Index,
int layer )
{
ULONG *pData = NULL;
ULONG i = 0, j = 0, temp = 1;
ULONG dwBlk = 0;
if (layer == 0)
{
dwBlk = dwContent;
}
else if (layer <= 3)
{
pData = (ULONG *)ExAllocatePool(PagedPool,
vcb->ext2_block);
if (!pData)
{
Ext2DbgPrint(D_EXT2, "Ext2GetBlock: no enough memory.\n");
return dwBlk;
}
if (!Ext2LoadBlock(vcb, dwContent, pData))
{
return 0;
}
temp = 1 << ((10 + vcb->ext2_super_block->s_log_block_size - 2) * (layer - 1));
i = Index / temp;
j = Index % temp;
dwBlk = pData[i];
ExFreePool(pData);
dwBlk = Ext2GetBlock(vcb, dwBlk, j, layer - 1);
}
return dwBlk;
}
ULONG Ext2BlockMap(IN PEXT2_VCB vcb,
IN PEXT2_INODE ext2_inode,
IN ULONG Index)
{
ULONG dwSizes[4] = {EXT2_NDIR_BLOCKS, 1, 1, 1};
int i;
ULONG dwBlk;
for (i = 0; i < 4; i++)
{
dwSizes[i] = dwSizes[i] << ((10 + vcb->ext2_super_block->s_log_block_size - 2) * i);
}
if ((Index * (vcb->ext2_block / SECTOR_SIZE)) >= ext2_inode->i_blocks)
{
Ext2DbgPrint(D_EXT2, "Ext2BlockMap: error input paramters.\n");
return 0;
}
for (i = 0; i < 4; i++)
{
if (Index < dwSizes[i])
{
dwBlk = ext2_inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)];
#if DBG
{
ULONG dwRet = Ext2GetBlock(vcb, dwBlk, Index , i);
Ext2DbgPrint(D_EXT2, "Ext2BlockMap: i=%xh index=%xh dwBlk=%xh (%xh)\n", i, Index, dwRet, dwBlk);
return dwRet;
}
#else
return Ext2GetBlock(vcb, dwBlk, Index , i);
#endif
}
Index -= dwSizes[i];
}
return 0;
}
ULONG Ext2BuildBDL( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_INODE ext2_inode,
IN ULONG offset,
IN ULONG size,
OUT PEXT2_BDL *ext2_bdl )
{
ULONG nBeg, nEnd, nBlocks;
ULONG dwBlk;
ULONG i;
ULONG dwBytes = 0;
LONGLONG lba;
PEXT2_BDL ext2bdl;
*ext2_bdl = NULL;
if (offset >= ext2_inode->i_size)
{
Ext2DbgPrint(D_EXT2, "Ext2BuildBDL: beyond the file range.\n");
return 0;
}
/*
if (offset + size > ext2_inode->i_size)
{
size = ext2_inode->i_size - offset;
}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -