📄 ext2.c
字号:
if (!NT_SUCCESS(Status))
{
Ext2DbgPrint(D_EXT2, "Ext2AddDirectory: Reading Directory Content error.\n");
__leave;
}
if ((pTarget->inode == 0) || (pTarget->rec_len >= EXT2_DIR_REC_LEN(pTarget->name_len) + pDir->rec_len))
{
if (pTarget->inode)
{
RtlZeroMemory(pTarget, 2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
// Reading the DCB contents
Status = Ext2ReadInode(
NULL,
Vcb,
Dcb->ext2_inode,
dwBytes,
(PVOID)pTarget,
2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
&dwRet);
if (!NT_SUCCESS(Status))
{
Ext2DbgPrint(D_EXT2, "Ext2AddDirectory: Reading Directory Content error.\n");
__leave;
}
Length = EXT2_DIR_REC_LEN(pTarget->name_len);
pNewDir = (PEXT2_DIR_ENTRY2) ((PUCHAR)pTarget + EXT2_DIR_REC_LEN(pTarget->name_len));
pNewDir->rec_len = pTarget->rec_len - EXT2_DIR_REC_LEN(pTarget->name_len);
pTarget->rec_len = EXT2_DIR_REC_LEN(pTarget->name_len);
}
else
{
pNewDir = pTarget;
pNewDir->rec_len = (USHORT)((ULONG)(Dcb->CommonFCBHeader.AllocationSize.QuadPart) - dwBytes);
}
pNewDir->file_type = pDir->file_type;
pNewDir->inode = pDir->inode;
pNewDir->name_len = pDir->name_len;
memcpy(pNewDir->name, pDir->name, pDir->name_len);
Length += EXT2_DIR_REC_LEN(pDir->name_len);
bFound = TRUE;
break;
}
dwBytes += pTarget->rec_len;
}
if (bFound) // Here we fininish the searching journel ...
{
ULONG dwRet;
if ( (!((pDir->name_len == 1) && (pDir->name[0] == '.'))) &&
(!((pDir->name_len == 2) && (pDir->name[0] == '.') && (pDir->name[1] == '.'))) )
Dcb->ext2_inode->i_links_count++;
if (Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes, pTarget, Length, FALSE, &dwRet))
Status = STATUS_SUCCESS;
}
else
{
// We should expand the size of the dir inode
if (!bAdding)
{
ULONG dwRet;
bAdding = Ext2ExpandInode(IrpContext, Vcb, Dcb, &dwRet);
if (bAdding) {
Dcb->ext2_inode->i_size = Dcb->ext2_inode->i_blocks * SECTOR_SIZE;
Ext2SaveInode(IrpContext, Vcb, Dcb->Ext2Mcb->Inode, Dcb->ext2_inode);
Dcb->CommonFCBHeader.FileSize = Dcb->CommonFCBHeader.AllocationSize;
goto Repeat;
}
__leave;
}
else // Something must be error!
{
__leave;
}
}
}
__finally
{
ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
Dcb->ReferenceCount--;
ExReleaseResourceForThreadLite(
&Dcb->CountResource,
ExGetCurrentResourceThread());
if(MainResourceAcquired)
ExReleaseResourceForThreadLite(
&Dcb->MainResource,
ExGetCurrentResourceThread());
if (pTarget != NULL)
{
ExFreePool(pTarget);
}
if (pDir)
ExFreePool(pDir);
}
return Status;
}
NTSTATUS
Ext2RemoveEntry (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_FCB Dcb,
IN ULONG Inode )
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_DIR_ENTRY2 pTarget = NULL;
PEXT2_DIR_ENTRY2 pPrevDir = NULL;
USHORT PrevRecLen;
ULONG Length = 0;
ULONG dwBytes = 0;
BOOLEAN bRet = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
ULONG dwRet;
if (!IsFlagOn(Dcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
return FALSE;
MainResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
__try
{
ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
Dcb->ReferenceCount++;
ExReleaseResourceForThreadLite(
&Dcb->CountResource,
ExGetCurrentResourceThread());
pTarget = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
if (!pTarget)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
pPrevDir = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
if (!pPrevDir)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
dwBytes = 0;
while ((LONGLONG)dwBytes < Dcb->CommonFCBHeader.AllocationSize.QuadPart)
{
RtlZeroMemory(pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
Status = Ext2ReadInode(
NULL,
Vcb,
Dcb->ext2_inode,
dwBytes,
(PVOID)pTarget,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
&dwRet);
if (!NT_SUCCESS(Status))
{
Ext2DbgPrint(D_EXT2, "Ext2RemoveEntry: Reading Directory Content error.\n");
__leave;
}
if (pTarget->inode == Inode)
{
ULONG dwRet;
ULONG RecLen;
pPrevDir->rec_len += pTarget->rec_len;
RecLen = EXT2_DIR_REC_LEN(pTarget->name_len);
RtlZeroMemory(pTarget, RecLen);
Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes - PrevRecLen, pPrevDir, 8, FALSE, &dwRet);
Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes, pTarget, RecLen, FALSE, &dwRet);
// . / .. could not be removed.
Dcb->ext2_inode->i_links_count--;
Ext2SaveInode(IrpContext, Vcb, Dcb->Ext2Mcb->Inode, Dcb->ext2_inode);
bRet = TRUE;
break;
}
else
{
RtlCopyMemory(pPrevDir, pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
PrevRecLen = pTarget->rec_len;
}
dwBytes += pTarget->rec_len;
}
}
__finally
{
ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
Dcb->ReferenceCount--;
ExReleaseResourceForThreadLite(
&Dcb->CountResource,
ExGetCurrentResourceThread());
if(MainResourceAcquired)
ExReleaseResourceForThreadLite(
&Dcb->MainResource,
ExGetCurrentResourceThread());
if (pTarget != NULL)
{
ExFreePool(pTarget);
}
if (pPrevDir)
ExFreePool(pPrevDir);
}
return bRet;
}
BOOLEAN Ext2TruncateBlock(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
ULONG dwContent,
ULONG Index,
ULONG layer,
BOOLEAN *bFreed )
{
ULONG *pData = NULL;
ULONG i = 0, j = 0, temp = 1;
BOOLEAN bDirty = FALSE;
BOOLEAN bRet = FALSE;
ULONG dwBlk;
LONGLONG Offset;
PBCB Bcb;
PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;
*bFreed = FALSE;
if (layer == 0)
{
if (dwContent > 0 && dwContent < (Vcb->ext2_super_block->s_blocks_per_group * Vcb->ext2_groups))
bRet = Ext2FreeBlock(IrpContext, Vcb, dwContent);
else
bRet = TRUE;
*bFreed = bRet;
}
else if (layer <= 3)
{
Offset = (LONGLONG) dwContent;
Offset = Offset * Vcb->ext2_block;
if( !CcPinRead( Vcb->StreamObj,
(PLARGE_INTEGER) (&Offset),
Vcb->ext2_block,
TRUE,
&Bcb,
&pData ))
{
Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: PinReading error ...\n");
goto errorout;
}
temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));
i = Index / temp;
j = Index % temp;
dwBlk = pData[i];
if(!Ext2TruncateBlock(IrpContext, Vcb, dwBlk, j, layer - 1, &bDirty))
goto errorout;
if (bDirty)
pData[i] = 0;
if (i == 0 && j == 0)
{
CcUnpinData(Bcb);
pData = NULL;
*bFreed = TRUE;
bRet = Ext2FreeBlock(IrpContext, Vcb, dwContent);
}
else
{
CcSetDirtyPinnedData(Bcb, NULL );
Ext2RepinBcb(IrpContext, Bcb);
Ext2AddMcbEntry(Vcb, Offset, (LONGLONG)Vcb->ext2_block);
bRet = TRUE;
*bFreed = FALSE;
}
}
errorout:
if (pData)
{
CcUnpinData(Bcb);
}
return bRet;
}
BOOLEAN
Ext2TruncateInode(
PEXT2_IRP_CONTEXT IrpContext,
PEXT2_VCB Vcb,
PEXT2_FCB Fcb )
{
ULONG dwSizes[4] = {EXT2_NDIR_BLOCKS, 1, 1, 1};
ULONG Index = 0;
ULONG dwTotal = 0;
ULONG dwBlk = 0;
ULONG i;
BOOLEAN bRet = FALSE;
BOOLEAN bFreed = FALSE;
PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;
PEXT2_INODE Ext2Inode = Fcb->ext2_inode;
Index = Ext2Inode->i_blocks / (Vcb->ext2_block / 512);
if (Index > 0) { Index--; } else { return TRUE; }
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 TRUE;
}
for (i = 0; i < 4; i++)
{
if (Index < dwSizes[i])
{
dwBlk = Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)];
bRet = Ext2TruncateBlock(IrpContext, Vcb, dwBlk, Index , i, &bFreed);
if (bRet)
{
Ext2Inode->i_blocks -= (Vcb->ext2_block / SECTOR_SIZE);
Fcb->CommonFCBHeader.AllocationSize.QuadPart -= Vcb->ext2_block;
if (bFreed)
{
Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)] = 0;
// Inode struct saving is done externally.
bRet = Ext2SaveInode(IrpContext, Vcb, Fcb->Ext2Mcb->Inode, Ext2Inode);
}
}
break;
}
Index -= dwSizes[i];
}
return bRet;
}
BOOLEAN
Ext2AddMcbEntry (
IN PEXT2_VCB Vcb,
IN LONGLONG Lba,
IN LONGLONG Length)
{
LONGLONG Offset;
LONGLONG DirtyLba;
LONGLONG DirtyLen;
Offset = Lba & (~(SECTOR_SIZE - 1));
Length = (Length + Lba - Offset + SECTOR_SIZE - 1) & (~(SECTOR_SIZE - 1));
ASSERT ((Offset & (SECTOR_SIZE - 1)) == 0);
ASSERT ((Length & (SECTOR_SIZE - 1)) == 0);
if (Ext2LookupMcbEntry(Vcb, Offset, &DirtyLba, &DirtyLen, NULL, NULL, NULL))
{
if (DirtyLba == Offset && DirtyLen >= Length)
return TRUE;
}
Ext2DbgPrint(D_EXT2, "Ext2AddMcbEntry: Range Lba/Len = %I64xh/%I64xh to be added.\n", Offset, Length);
#if DBG
Ext2DbgPrint(D_EXT2, "Ext2AddMcbEntry: Number Runs in Mcb: %xh\n", FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) );
#endif
return FsRtlAddLargeMcbEntry(&(Vcb->DirtyMcbs), Offset, Offset, Length);
}
VOID
Ext2RemoveMcbEntry (
IN PEXT2_VCB Vcb,
IN LONGLONG Lba,
IN LONGLONG Length)
{
FsRtlRemoveLargeMcbEntry(&(Vcb->DirtyMcbs), Lba, Length);
}
BOOLEAN
Ext2LookupMcbEntry (
IN PEXT2_VCB Vcb,
IN LONGLONG Offset,
OUT PLONGLONG Lba,
OUT PLONGLONG Length,
OUT PLONGLONG RunStart,
OUT PLONGLONG RunLength,
OUT PULONG Index)
{
BOOLEAN bReturn;
bReturn = FsRtlLookupLargeMcbEntry(
&(Vcb->DirtyMcbs), Offset, Lba, Length,
RunStart, RunLength, Index );
return bReturn;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -