📄 generic.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: generic.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
BOOLEAN
Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LoadSuper)
#pragma alloc_text(PAGE, Ext2SaveSuper)
#pragma alloc_text(PAGE, Ext2RefreshSuper)
#pragma alloc_text(PAGE, Ext2LoadGroup)
#pragma alloc_text(PAGE, Ext2SaveGroup)
#pragma alloc_text(PAGE, Ext2RefreshGroup)
#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, Ext2UpdateVcbStat)
#pragma alloc_text(PAGE, Ext2NewBlock)
#pragma alloc_text(PAGE, Ext2FreeBlock)
#pragma alloc_text(PAGE, Ext2ExpandLast)
#pragma alloc_text(PAGE, Ext2ExpandBlock)
#pragma alloc_text(PAGE, Ext2IsBlockEmpty)
#pragma alloc_text(PAGE, Ext2TruncateBlock)
#pragma alloc_text(PAGE, Ext2NewInode)
#pragma alloc_text(PAGE, Ext2FreeInode)
#pragma alloc_text(PAGE, Ext2AddEntry)
#pragma alloc_text(PAGE, Ext2RemoveEntry)
#pragma alloc_text(PAGE, Ext2SetParentEntry)
#endif
/* FUNCTIONS ***************************************************************/
NTSTATUS
Ext2LoadSuper(IN PEXT2_VCB Vcb,
IN BOOLEAN bVerify,
OUT PEXT2_SUPER_BLOCK * Sb)
{
NTSTATUS Status;
PEXT2_SUPER_BLOCK Ext2Sb = NULL;
Ext2Sb = (PEXT2_SUPER_BLOCK)
ExAllocatePoolWithTag(
PagedPool,
SUPER_BLOCK_SIZE,
EXT2_SB_MAGIC
);
if (!Ext2Sb) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto errorout;
}
Status = Ext2ReadDisk(
Vcb,
(ULONGLONG) SUPER_BLOCK_OFFSET,
SUPER_BLOCK_SIZE,
(PVOID) Ext2Sb,
bVerify );
if (!NT_SUCCESS(Status)) {
DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));
ExFreePoolWithTag(Ext2Sb, EXT2_SB_MAGIC);
Ext2Sb = NULL;
}
errorout:
*Sb = Ext2Sb;
return Status;
}
BOOLEAN
Ext2SaveSuper(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb
)
{
LONGLONG offset;
BOOLEAN rc;
offset = (LONGLONG) SUPER_BLOCK_OFFSET;
rc = Ext2SaveBuffer( IrpContext,
Vcb,
offset,
SUPER_BLOCK_SIZE,
Vcb->SuperBlock
);
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
}
return rc;
}
BOOLEAN
Ext2RefreshSuper (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb
)
{
LONGLONG offset;
IO_STATUS_BLOCK iosb;
offset = (LONGLONG) SUPER_BLOCK_OFFSET;
if (!CcCopyRead(
Vcb->Volume,
(PLARGE_INTEGER)&offset,
SUPER_BLOCK_SIZE,
TRUE,
(PVOID)Vcb->SuperBlock,
&iosb )) {
return FALSE;
}
if (!NT_SUCCESS(iosb.Status)) {
return FALSE;
}
return TRUE;
}
BOOLEAN
Ext2LoadGroup(IN PEXT2_VCB Vcb)
{
ULONG Size;
PVOID Buffer;
LONGLONG Lba = 0;
NTSTATUS Status;
Size = sizeof(EXT2_GROUP_DESC) * Vcb->NumOfGroups;
if (Vcb->BlockSize == EXT2_MIN_BLOCK) {
Lba = (LONGLONG)2 * Vcb->BlockSize;
}
if (Vcb->BlockSize > EXT2_MIN_BLOCK) {
Lba = (LONGLONG) (Vcb->BlockSize);
}
if (Lba == 0) {
return FALSE;
}
Buffer = ExAllocatePoolWithTag(PagedPool, Size, EXT2_GD_MAGIC);
if (!Buffer) {
DEBUG(DL_ERR, ( "Ext2LoadSuper: no enough memory.\n"));
return FALSE;
}
DEBUG(DL_INF, ( "Ext2LoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size));
Status = Ext2ReadDisk( Vcb,
Lba,
Size,
Buffer,
FALSE );
if (!NT_SUCCESS(Status)) {
ExFreePoolWithTag(Buffer, EXT2_GD_MAGIC);
Buffer = NULL;
return FALSE;
}
Vcb->GroupDesc = (PEXT2_GROUP_DESC) Buffer;
return TRUE;
}
BOOLEAN
Ext2SaveGroup(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG Group
)
{
LONGLONG Offset;
BOOLEAN bRet;
if (Vcb->BlockSize == EXT2_MIN_BLOCK) {
Offset = (LONGLONG) (2 * Vcb->BlockSize);
} else {
Offset = (LONGLONG) (Vcb->BlockSize);
}
Offset += ((LONGLONG) sizeof(struct ext2_group_desc) * Group);
bRet = Ext2SaveBuffer(
IrpContext,
Vcb,
Offset,
sizeof(struct ext2_group_desc),
&(Vcb->GroupDesc[Group]) );
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
}
return bRet;
}
BOOLEAN
Ext2RefreshGroup(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb
)
{
IO_STATUS_BLOCK iosb;
LONGLONG offset;
if (Vcb->BlockSize == EXT2_MIN_BLOCK) {
offset = (LONGLONG) (2 * Vcb->BlockSize);
} else {
offset = (LONGLONG) (Vcb->BlockSize);
}
if (!CcCopyRead(
Vcb->Volume,
(PLARGE_INTEGER)&offset,
sizeof(struct ext2_group_desc) *
Vcb->NumOfGroups,
TRUE,
(PVOID)&Vcb->GroupDesc[0],
&iosb)) {
return FALSE;
}
if (!NT_SUCCESS(iosb.Status)) {
return FALSE;
}
return TRUE;
}
BOOLEAN
Ext2GetInodeLba (
IN PEXT2_VCB Vcb,
IN ULONG inode,
OUT PLONGLONG offset
)
{
LONGLONG loc;
if (inode < 1 || inode > INODES_COUNT) {
DEBUG(DL_ERR, ( "Ext2GetInodeLba: Inode value %xh is invalid.\n",inode));
*offset = 0;
return FALSE;
}
loc = (Vcb->GroupDesc[(inode - 1) / INODES_PER_GROUP ].bg_inode_table);
loc = loc * Vcb->BlockSize;
loc = loc + ((inode - 1) % INODES_PER_GROUP) * INODE_SIZE;
*offset = loc;
return TRUE;
}
BOOLEAN
Ext2LoadInode (IN PEXT2_VCB Vcb,
IN ULONG inode,
IN PEXT2_INODE Inode)
{
IO_STATUS_BLOCK IoStatus;
LONGLONG Offset;
if (!Ext2GetInodeLba(Vcb, inode, &Offset)) {
DEBUG(DL_ERR, ( "Ext2LoadInode: error get inode(%xh)'s addr.\n", inode));
return FALSE;
}
if (!CcCopyRead(
Vcb->Volume,
(PLARGE_INTEGER)&Offset,
INODE_SIZE,
PIN_WAIT,
(PVOID)Inode,
&IoStatus )) {
return FALSE;
}
if (!NT_SUCCESS(IoStatus.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;
BOOLEAN rc;
DEBUG(DL_INF, ( "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
Inode, Ext2Inode->i_mode, Ext2Inode->i_size));
rc = Ext2GetInodeLba(Vcb, Inode, &Offset);
if (!rc) {
DEBUG(DL_ERR, ( "Ext2SaveInode: error get inode(%xh)'s addr.\n", Inode));
goto errorout;
}
rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, INODE_SIZE, Ext2Inode);
if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
}
errorout:
return rc;
}
BOOLEAN
Ext2LoadBlock (IN PEXT2_VCB Vcb,
IN ULONG Index,
IN PVOID Buffer )
{
IO_STATUS_BLOCK IoStatus;
LONGLONG Offset;
Offset = (LONGLONG) Index;
Offset = Offset * Vcb->BlockSize;
if (!CcCopyRead(
Vcb->Volume,
(PLARGE_INTEGER)&Offset,
Vcb->BlockSize,
PIN_WAIT,
Buffer,
&IoStatus ));
if (!NT_SUCCESS(IoStatus.Status)) {
return FALSE;
}
return TRUE;
}
BOOLEAN
Ext2SaveBlock ( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG Index,
IN PVOID Buf )
{
LONGLONG Offset;
BOOLEAN rc;
Offset = (LONGLONG) Index;
Offset = Offset * Vcb->BlockSize;
rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf);
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
}
return rc;
}
BOOLEAN
Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN LONGLONG Offset,
IN ULONG Size,
IN PVOID Buf )
{
PBCB Bcb;
PVOID Buffer;
BOOLEAN rc;
if( !CcPreparePinWrite(
Vcb->Volume,
(PLARGE_INTEGER) (&Offset),
Size,
FALSE,
Ext2CanIWait(),
&Bcb,
&Buffer )) {
DEBUG(DL_ERR, ( "Ext2SaveBuffer: failed to PinLock offset %I64xh ...\n", Offset));
return FALSE;
}
__try {
RtlCopyMemory(Buffer, Buf, Size);
CcSetDirtyPinnedData(Bcb, NULL );
SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Size);
if (!rc) {
DbgBreak();
Ext2Sleep(100);
rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Size);
}
} __finally {
CcUnpinData(Bcb);
}
return rc;
}
NTSTATUS
Ext2GetBlock(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_MCB Mcb,
IN ULONG Base,
IN ULONG Layer,
IN ULONG Start,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -