📄 generic.c
字号:
Ext2SaveGroup(IrpContext, Vcb, Group);
}
goto repeat;
} else {
RtlSetBits(&InodeBitmap, dwInode, 1);
Vcb->GroupDesc[Group].bg_free_inodes_count =
(USHORT)RtlNumberOfClearBits(&InodeBitmap);
CcSetDirtyPinnedData(BitmapBcb, NULL);
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
*Inode = dwInode + 1 + Group * INODES_PER_GROUP;
/* update group_desc / super_block */
if (Type == EXT2_FT_DIR) {
Vcb->GroupDesc[Group].bg_used_dirs_count++;
}
Ext2SaveGroup(IrpContext, Vcb, Group);
Ext2UpdateVcbStat(IrpContext, Vcb);
Status = STATUS_SUCCESS;
}
errorout:
ExReleaseResourceLite(&Vcb->MetaLock);
return Status;
}
NTSTATUS
Ext2FreeInode(
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN ULONG Inode,
IN ULONG Type
)
{
RTL_BITMAP InodeBitmap;
PVOID BitmapCache;
PBCB BitmapBcb;
ULONG Group;
ULONG Length;
LARGE_INTEGER Offset;
ULONG dwIno;
BOOLEAN bModified = FALSE;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);
Group = (Inode - 1) / INODES_PER_GROUP;
dwIno = (Inode - 1) % INODES_PER_GROUP;
DEBUG(DL_INF, ( "Ext2FreeInode: Inode: %xh (Group/Off = %xh/%xh)\n",
Inode, Group, dwIno));
if (Group < Vcb->NumOfGroups) {
/* check the block is valid or not */
if (Vcb->GroupDesc[Group].bg_inode_bitmap >= TOTAL_BLOCKS) {
DbgBreak();
Status = STATUS_DISK_CORRUPT_ERROR;
goto errorout;
}
Offset.QuadPart = (LONGLONG) Vcb->GroupDesc[Group].bg_inode_bitmap;
Offset.QuadPart = Offset.QuadPart << BLOCK_BITS ;
if (Group == Vcb->NumOfGroups - 1) {
Length = INODES_COUNT % INODES_PER_GROUP;
if (!Length) {
/* s_inodes_count is integer multiple of s_inodes_per_group */
Length = INODES_PER_GROUP;
}
} else {
Length = INODES_PER_GROUP;
}
if (!CcPinRead( Vcb->Volume,
&Offset,
Vcb->BlockSize,
PIN_WAIT,
&BitmapBcb,
&BitmapCache ) ) {
DEBUG(DL_ERR, ( "Ext2FreeInode: Failed to PinLock inode bitmap %xh ...\n",
Vcb->GroupDesc[Group].bg_inode_bitmap));
Status = STATUS_CANT_WAIT;
goto errorout;
}
RtlInitializeBitMap( &InodeBitmap,
BitmapCache,
Length );
if (RtlCheckBit(&InodeBitmap, dwIno) == 0) {
DbgBreak();
Status = STATUS_SUCCESS;
} else {
RtlClearBits(&InodeBitmap, dwIno, 1);
bModified = TRUE;
}
if (!bModified) {
CcUnpinData(BitmapBcb);
BitmapBcb = NULL;
BitmapCache = NULL;
RtlZeroMemory(&InodeBitmap, sizeof(RTL_BITMAP));
}
} else {
DbgBreak();
goto errorout;
}
if (bModified) {
/* update group free inodes */
Vcb->GroupDesc[Group].bg_free_inodes_count =
(USHORT)RtlNumberOfClearBits(&InodeBitmap);
/* set inode block dirty and add to vcb dirty range */
CcSetDirtyPinnedData(BitmapBcb, NULL );
CcUnpinData(BitmapBcb);
Ext2AddVcbExtent(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
/* update group_desc and super_block */
if (Type == EXT2_FT_DIR) {
Vcb->GroupDesc[Group].bg_used_dirs_count--;
}
Ext2SaveGroup(IrpContext, Vcb, Group);
Ext2UpdateVcbStat(IrpContext, Vcb);
Status = STATUS_SUCCESS;
}
errorout:
ExReleaseResourceLite(&Vcb->MetaLock);
return Status;
}
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,
OUT PULONG EntryOffset
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
OEM_STRING OemName;
PEXT2_DIR_ENTRY2 pDir = NULL;
PEXT2_DIR_ENTRY2 pNewDir = NULL;
PEXT2_DIR_ENTRY2 pTarget = NULL;
ULONG Length = 0;
ULONG ByteOffset = 0;
ULONG dwRet = 0;
ULONG RecLen = 0;
BOOLEAN bFound = FALSE;
BOOLEAN bAdding = FALSE;
BOOLEAN MainResourceAcquired = FALSE;
if (!IsDirectory(Dcb)) {
DbgBreak();
return STATUS_NOT_A_DIRECTORY;
}
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
MainResourceAcquired = TRUE;
__try {
Ext2ReferXcb(&Dcb->ReferenceCount);
pDir = (PEXT2_DIR_ENTRY2)
ExAllocatePoolWithTag(
PagedPool,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
EXT2_DENTRY_MAGIC
);
if (!pDir) {
DEBUG(DL_ERR, ( "Ex2AddEntry: failed to allocate pDir.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
pTarget = (PEXT2_DIR_ENTRY2)
ExAllocatePoolWithTag(
PagedPool,
2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
EXT2_DENTRY_MAGIC
);
if (!pTarget) {
DEBUG(DL_ERR, ( "Ex2AddEntry: failed to allocate pTarget.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
if (IsFlagOn( SUPER_BLOCK->s_feature_incompat,
EXT2_FEATURE_INCOMPAT_FILETYPE)) {
pDir->file_type = (UCHAR) FileType;
} else {
pDir->file_type = 0;
}
OemName.Buffer = pDir->name;
OemName.MaximumLength = EXT2_NAME_LEN;
OemName.Length = 0;
Status = Ext2UnicodeToOEM(Vcb, &OemName, FileName);
if (!NT_SUCCESS(Status)) {
__leave;
}
pDir->name_len = (CCHAR) OemName.Length;
pDir->inode = Inode;
pDir->rec_len = (USHORT) (EXT2_DIR_REC_LEN(pDir->name_len));
ByteOffset = 0;
Repeat:
while ((LONGLONG)ByteOffset < Dcb->Header.AllocationSize.QuadPart) {
RtlZeroMemory(pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
// Reading the DCB contents
Status = Ext2ReadInode(
IrpContext,
Vcb,
Dcb->Mcb,
(ULONGLONG)ByteOffset,
(PVOID)pTarget,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
FALSE,
&dwRet);
if (!NT_SUCCESS(Status)) {
DEBUG(DL_ERR, ( "Ext2AddDirectory: failed to read directory.\n"));
__leave;
}
if (pTarget->rec_len == 0) {
RecLen = BLOCK_SIZE - (ByteOffset & (BLOCK_SIZE - 1));
} else {
RecLen = pTarget->rec_len;
}
if (((pTarget->inode == 0) && RecLen >= pDir->rec_len) ||
(RecLen >= (ULONG)EXT2_DIR_REC_LEN(pTarget->name_len) + pDir->rec_len)) {
/* we get emply slot for this entry */
if (pTarget->inode) {
RtlZeroMemory(pTarget, 2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
/* read enough data from directory content */
Status = Ext2ReadInode(
IrpContext,
Vcb,
Dcb->Mcb,
(ULONGLONG)ByteOffset,
(PVOID)pTarget,
2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
FALSE,
&dwRet);
if (!NT_SUCCESS(Status)) {
DEBUG(DL_ERR, ( "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 = (USHORT)(RecLen - EXT2_DIR_REC_LEN(pTarget->name_len));
pTarget->rec_len = EXT2_DIR_REC_LEN(pTarget->name_len);
} else {
Length = 0;
pNewDir = pTarget;
}
/* update it's entry offset in parent directory */
if (EntryOffset) {
*EntryOffset = ByteOffset + Length;
}
/* set dir entry */
pNewDir->file_type = pDir->file_type;
pNewDir->inode = pDir->inode;
pNewDir->name_len = pDir->name_len;
memcpy(pNewDir->name, pDir->name, pDir->name_len);
/* update Length to be written to dir content */
Length += EXT2_DIR_REC_LEN(pDir->name_len);
bFound = TRUE;
break;
}
ByteOffset += RecLen;
}
if (bFound) {
/* update the reference link count */
if (FileType==EXT2_FT_DIR ) {
if(((pDir->name_len == 1) && (pDir->name[0] == '.')) ||
((pDir->name_len == 2) && (pDir->name[0] == '.') && (pDir->name[1] == '.')) ) {
} else {
Dcb->Inode->i_links_count++;
}
}
/* save the new entry */
Status = Ext2WriteInode(
IrpContext,
Vcb,
Dcb->Mcb,
(ULONGLONG)ByteOffset,
pTarget,
Length,
FALSE,
&dwRet );
} else {
// We should expand the size of the dir inode
if (!bAdding) {
/* allocate new block since there's no space for us */
ByteOffset = Dcb->Header.AllocationSize.LowPart;
Dcb->Header.AllocationSize.LowPart += BLOCK_SIZE;
Status = Ext2ExpandFile(
IrpContext,
Vcb,
Dcb->Mcb,
&(Dcb->Header.AllocationSize)
);
if (NT_SUCCESS(Status)) {
/* update Dcb */
Dcb->Inode->i_size = Dcb->Header.AllocationSize.LowPart;
Ext2SaveInode(IrpContext, Vcb, Dcb->Mcb->iNo, Dcb->Inode);
Dcb->Header.ValidDataLength = Dcb->Header.FileSize =
Dcb->Mcb->FileSize = Dcb->Header.AllocationSize;
/* save parent directory's inode */
Ext2SaveInode(
IrpContext,
Vcb,
Dcb->Mcb->iNo,
Dcb->Inode
);
bAdding = TRUE;
goto Repeat;
}
/* failed to allocate new block for this directory */
__leave;
} else {
/* Something must be error, since we already allocated new block ! */
__leave;
}
}
} __finally {
Ext2DerefXcb(&Dcb->ReferenceCount);
if(MainResourceAcquired) {
ExReleaseResourceLite(&Dcb->MainResource);
}
if (pTarget != NULL) {
ExFreePoolWithTag(pTarget, EXT2_DENTRY_MAGIC);
}
if (pDir) {
ExFreePoolWithTag(pDir, EXT2_DENTRY_MAGIC);
}
}
return Status;
}
NTSTATUS
Ext2RemoveEntry (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_FCB Dcb,
IN ULONG EntryOffset,
IN ULONG FileType,
IN ULONG Inode
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_DIR_ENTRY2 pTarget = NULL;
PEXT2_DIR_ENTRY2 pPrevDir = NULL;
ULONG Length = 0;
ULONG ByteOffset = 0;
ULONG dwRet;
ULONG RecLen;
USHORT PrevRecLen = 0;
BOOLEAN MainResourceAcquired = FALSE;
if (!IsDirectory(Dcb)) {
return STATUS_NOT_A_DIRECTORY;
}
ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);
MainResourceAcquired = TRUE;
__try {
Ext2ReferXcb(&Dcb->ReferenceCount);
pTarget = (PEXT2_DIR_ENTRY2)
ExAllocatePoolWithTag( PagedPool,
EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
EXT2_DENTRY_MAGIC
);
if (!pTarget) {
DEBUG(DL_ERR, ( "Ex2RemoveEntry: failed to allocate pTarget.\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
pPrevDir
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -