⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext2.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:

    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 + -