📄 ext2.c
字号:
if (pData)
ExFreePool(pData);
if (bRet && dwRet)
*dwRet = dwNewBlk;
return bRet;
}
BOOLEAN
Ext2ExpandInode(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_FCB Fcb,
ULONG *dwRet )
{
ULONG dwSizes[4] = {EXT2_NDIR_BLOCKS, 1, 1, 1};
ULONG Index = 0;
ULONG dwTotal = 0;
ULONG dwBlk = 0, dwNewBlk = 0;
PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;
ULONG i;
BOOLEAN bRet = FALSE;
BOOLEAN bNewBlock = FALSE;
PEXT2_INODE Ext2Inode = Fcb->ext2_inode;
Index = Ext2Inode->i_blocks / (Vcb->ext2_block / 512);
for (i = 0; i < 4; i++)
{
dwSizes[i] = dwSizes[i] << ((10 + pExt2Sb->s_log_block_size - 2) * i);
dwTotal += dwSizes[i];
}
if (Index >= dwTotal)
{
Ext2DbgPrint(D_EXT2, "Ext2ExpandInode: beyond the maxinum size of an inode.\n");
return FALSE;
}
for (i = 0; i < 4; i++)
{
if (Index < dwSizes[i])
{
dwBlk = Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)];
if (dwBlk == 0)
{
if (!Ext2NewBlock(IrpContext,
Vcb,
Fcb->BlkHint ? 0 : ((Fcb->Ext2Mcb->Inode - 1) / Vcb->ext2_super_block->s_inodes_per_group),
Fcb->BlkHint,
&dwBlk ) )
{
Ext2DbgPrint(D_EXT2, "Ext2ExpandInode: get new block error.\n");
break;
}
Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)] = dwBlk;
bNewBlock = TRUE;
}
bRet = Ext2ExpandBlock(IrpContext, Vcb, Fcb, dwBlk, Index , i, bNewBlock, &dwNewBlk);
if (bRet)
{
Ext2Inode->i_blocks += (Vcb->ext2_block / SECTOR_SIZE);
Fcb->CommonFCBHeader.AllocationSize.QuadPart += Vcb->ext2_block;
bRet = Ext2SaveInode(IrpContext, Vcb, Fcb->Ext2Mcb->Inode, Ext2Inode);
}
break;
}
Index -= dwSizes[i];
}
if (bRet && dwNewBlk)
{
if (dwRet)
{
Fcb->BlkHint = dwNewBlk+1;
*dwRet = dwNewBlk;
Ext2DbgPrint(D_EXT2, "Ext2ExpandInode: %S (%xh) i=%2.2xh Index=%8.8xh New Block=%8.8xh\n", Fcb->Ext2Mcb->ShortName.Buffer, Fcb->Ext2Mcb->Inode, i, Index, dwNewBlk);
}
return TRUE;
}
else
return FALSE;
}
BOOLEAN
Ext2NewInode(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
ULONG GroupHint,
ULONG Type,
PULONG Inode )
{
RTL_BITMAP InodeBitmap;
PVOID BitmapCache;
PBCB BitmapBcb;
ULONG Group, i, j;
ULONG Average, Length;
LARGE_INTEGER Offset;
ULONG dwInode;
*Inode = dwInode = 0XFFFFFFFF;
repeat:
Group = i = 0;
if (Type == EXT2_FT_DIR)
{
Average = Vcb->ext2_super_block->s_free_inodes_count / Vcb->ext2_groups;
for (j = 0; j < Vcb->ext2_groups; j++)
{
i = (j + GroupHint) % (Vcb->ext2_groups);
if ((Vcb->ext2_group_desc[i].bg_used_dirs_count << 8) <
Vcb->ext2_group_desc[i].bg_free_inodes_count )
{
Group = i + 1;
break;
}
}
if (!Group)
{
for (j = 0; j < Vcb->ext2_groups; j++)
{
if (Vcb->ext2_group_desc[j].bg_free_inodes_count >= Average)
{
if (!Group || (Vcb->ext2_group_desc[j].bg_free_blocks_count > Vcb->ext2_group_desc[Group].bg_free_blocks_count ))
Group = j + 1;
}
}
}
}
else
{
/*
* Try to place the inode in its parent directory (GroupHint)
*/
if (Vcb->ext2_group_desc[GroupHint].bg_free_inodes_count)
{
Group = GroupHint + 1;
}
else
{
i = GroupHint;
/*
* Use a quadratic hash to find a group with a
* free inode
*/
for (j = 1; j < Vcb->ext2_groups; j <<= 1)
{
i += j;
if (i > Vcb->ext2_groups)
i -= Vcb->ext2_groups;
if (Vcb->ext2_group_desc[i].bg_free_inodes_count)
{
Group = i + 1;
break;
}
}
}
if (!Group) {
/*
* That failed: try linear search for a free inode
*/
i = GroupHint + 1;
for (j = 2; j < Vcb->ext2_groups; j++)
{
if (++i >= Vcb->ext2_groups) i = 0;
if (Vcb->ext2_group_desc[i].bg_free_inodes_count)
{
Group = i + 1;
break;
}
}
}
}
// Could not find a proper group.
if (!Group)
{
return FALSE;
}
else
{
Group--;
Offset.QuadPart = (LONGLONG) Vcb->ext2_block;
Offset.QuadPart = Offset.QuadPart * Vcb->ext2_group_desc[Group].bg_inode_bitmap;
if (Vcb->ext2_groups == 1)
{
Length = Vcb->ext2_super_block->s_inodes_count;
}
else
{
if (Group == Vcb->ext2_groups - 1)
Length = Vcb->ext2_super_block->s_inodes_count % Vcb->ext2_super_block->s_inodes_per_group;
else
Length = Vcb->ext2_super_block->s_inodes_per_group;
}
if (!CcPinRead( Vcb->StreamObj,
&Offset,
Vcb->ext2_block,
TRUE,
&BitmapBcb,
&BitmapCache ) )
{
Ext2DbgPrint(D_EXT2, "Ext2NewInode: PinReading error ...\n");
return FALSE;
}
RtlInitializeBitMap( &InodeBitmap,
BitmapCache,
Length );
dwInode = RtlFindClearBits(&InodeBitmap, 1, 0);
if (dwInode == 0xFFFFFFFF)
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
}
}
if (dwInode == 0xFFFFFFFF || dwInode >= Length)
{
if (Vcb->ext2_group_desc[Group].bg_free_inodes_count != 0)
{
Vcb->ext2_group_desc[Group].bg_free_inodes_count = 0;
Ext2SaveGroup(IrpContext, Vcb);
}
goto repeat;
}
else
{
RtlSetBits(&InodeBitmap, dwInode, 1);
CcSetDirtyPinnedData(BitmapBcb, NULL );
Ext2RepinBcb(IrpContext, BitmapBcb);
CcUnpinData(BitmapBcb);
Ext2AddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->ext2_block);
*Inode = dwInode + 1 + Group * Vcb->ext2_super_block->s_inodes_per_group;
//Updating Group Desc / Superblock
Vcb->ext2_group_desc[Group].bg_free_inodes_count--;
if (Type == EXT2_FT_DIR)
Vcb->ext2_group_desc[Group].bg_used_dirs_count++;
Ext2SaveGroup(IrpContext, Vcb);
Vcb->ext2_super_block->s_free_inodes_count--;
Ext2SaveSuper(IrpContext, Vcb);
return TRUE;
}
return FALSE;
}
BOOLEAN
Ext2FreeInode(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
ULONG Inode,
ULONG Type )
{
RTL_BITMAP InodeBitmap;
PVOID BitmapCache;
PBCB BitmapBcb;
ULONG Group;
ULONG Length;
LARGE_INTEGER Offset;
ULONG dwIno;
BOOLEAN bModified = FALSE;
Group = (Inode - 1) / Vcb->ext2_super_block->s_inodes_per_group;
dwIno = (Inode - 1) % (Vcb->ext2_super_block->s_inodes_per_group);
Ext2DbgPrint(D_EXT2, "Ext2FreeInode: Inode: %xh (Group/Off = %xh/%xh)\n", Inode, Group, dwIno);
{
Offset.QuadPart = (LONGLONG) Vcb->ext2_block;
Offset.QuadPart = Offset.QuadPart * Vcb->ext2_group_desc[Group].bg_inode_bitmap;
if (Group == Vcb->ext2_groups - 1)
Length = Vcb->ext2_super_block->s_inodes_count % Vcb->ext2_super_block->s_inodes_per_group;
else
Length = Vcb->ext2_super_block->s_inodes_per_group;
if (!CcPinRead( Vcb->StreamObj,
&Offset,
Vcb->ext2_block,
TRUE,
&BitmapBcb,
&BitmapCache ) )
{
Ext2DbgPrint(D_EXT2, "Ext2FreeInode: PinReading error ...\n");
return FALSE;
}
RtlInitializeBitMap( &InodeBitmap,
BitmapCache,
Length );
if (RtlCheckBit(&InodeBitmap, dwIno) == 0)
{
}
else
{
RtlClearBits(&InodeBitmap, dwIno, 1);
bModified = TRUE;
}
if (!bModified)
{
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
}
}
if (bModified)
{
CcSetDirtyPinnedData(BitmapBcb, NULL );
Ext2RepinBcb(IrpContext, BitmapBcb);
CcUnpinData(BitmapBcb);
Ext2AddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->ext2_block);
//Updating Group Desc / Superblock
if (Type == EXT2_FT_DIR)
Vcb->ext2_group_desc[Group].bg_used_dirs_count--;
Vcb->ext2_group_desc[Group].bg_free_inodes_count++;
Ext2SaveGroup(IrpContext, Vcb);
Vcb->ext2_super_block->s_free_inodes_count++;
Ext2SaveSuper(IrpContext, Vcb);
return TRUE;
}
return FALSE;
}
NTSTATUS
Ext2AddEntry (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_FCB Dcb,
IN ULONG FileType,
IN ULONG Inode,
IN PUNICODE_STRING FileName )
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_DIR_ENTRY2 pDir = NULL;
PEXT2_DIR_ENTRY2 pNewDir = NULL;
PEXT2_DIR_ENTRY2 pTarget = NULL;
ULONG Length = 0;
ULONG dwBytes = 0;
BOOLEAN bFound = FALSE;
BOOLEAN bAdding = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
ULONG dwRet;
if (!IsFlagOn(Dcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
Status = STATUS_INVALID_PARAMETER;
return Status;
}
MainResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
__try
{
ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
Dcb->ReferenceCount++;
ExReleaseResourceForThreadLite(
&Dcb->CountResource,
ExGetCurrentResourceThread());
pDir = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
if (!pDir)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
pTarget = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
if (!pTarget)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
if (IsFlagOn(Vcb->ext2_super_block->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE))
{
pDir->file_type = (UCHAR) FileType;
}
else
{
pDir->file_type = 0;
}
pDir->inode = Inode;
pDir->name_len = (UCHAR) ( FileName->Length > (EXT2_NAME_LEN * 2) ?
EXT2_NAME_LEN : (FileName->Length / 2) );
Ext2WcharToChar(
pDir->name,
FileName->Buffer,
pDir->name_len);
pDir->rec_len = (USHORT) (EXT2_DIR_REC_LEN(pDir->name_len));
dwBytes = 0;
Repeat:
while ((LONGLONG)dwBytes < Dcb->CommonFCBHeader.AllocationSize.QuadPart)
{
RtlZeroMemory(pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
// Reading the DCB contents
Status = Ext2ReadInode(
NULL,
Vcb,
Dcb->ext2_inode,
dwBytes,
(PVOID)pTarget,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
&dwRet);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -