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

📄 ext2.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * COPYRIGHT:        See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
 * FILE:             Ext2.c
 * PROGRAMMER:       Matt Wu <mattwu@163.com>
 * HOMEPAGE:         http://ext2.yeah.net
 * UPDATE HISTORY: 
 */

/* INCLUDES *****************************************************************/

#include "ntifs.h"
#include "ext2fs.h"

/* GLOBALS ***************************************************************/

extern PEXT2_GLOBAL g_gExt2Global;

/* DEFINITIONS *************************************************************/

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LoadSuper)
#pragma alloc_text(PAGE, Ext2SaveSuper)

#pragma alloc_text(PAGE, Ext2LoadGroup)
#pragma alloc_text(PAGE, Ext2SaveGroup)

#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, Ext2BuildBDL)

#pragma alloc_text(PAGE, Ext2NewBlock)
#pragma alloc_text(PAGE, Ext2FreeBlock)

#pragma alloc_text(PAGE, Ext2ExpandBlock)
#pragma alloc_text(PAGE, Ext2ExpandInode)

#pragma alloc_text(PAGE, Ext2NewInode)
#pragma alloc_text(PAGE, Ext2FreeInode)

#pragma alloc_text(PAGE, Ext2AddEntry)
#pragma alloc_text(PAGE, Ext2RemoveEntry)

#pragma alloc_text(PAGE, Ext2TruncateBlock)
#pragma alloc_text(PAGE, Ext2TruncateInode)

#pragma alloc_text(PAGE, Ext2AddMcbEntry)
#pragma alloc_text(PAGE, Ext2RemoveMcbEntry)
#pragma alloc_text(PAGE, Ext2LookupMcbEntry)

#endif

/* FUNCTIONS ***************************************************************/

PEXT2_SUPER_BLOCK
Ext2LoadSuper(IN PDEVICE_OBJECT pDeviceObject)
{
    PVOID       Buffer;
    NTSTATUS    Status;
    
    Buffer = ExAllocatePool(NonPagedPool, 2 * SECTOR_SIZE);
    if (!Buffer)
    {
        Ext2DbgPrint(D_EXT2, "Ext2LoadSuper: no enough memory.\n");
        return NULL;
    }

    Status = Ext2ReadDisk(pDeviceObject, 2, 0, SECTOR_SIZE * 2, Buffer);
    if (!NT_SUCCESS(Status))
    {
        Ext2DbgPrint(D_EXT2, "Ext2ReadDisk: Read Block Device error.\n");
                ExFreePool(Buffer);
        return NULL;
    }

    return (struct ext2_super_block *)Buffer;
}


BOOLEAN
Ext2SaveSuper(  IN PEXT2_IRP_CONTEXT    IrpContext,
                IN PEXT2_VCB            Vcb )
{
    LONGLONG    Offset;

    Offset = (LONGLONG) (2 * SECTOR_SIZE);

    return Ext2SaveBuffer(IrpContext, Vcb, Offset, (2 * SECTOR_SIZE), Vcb->ext2_super_block);
}

PEXT2_GROUP_DESC
Ext2LoadGroup(IN PEXT2_VCB vcb)
{
    ULONG       size;
    PVOID       Buffer;
    LONGLONG    lba;
    NTSTATUS    Status;

    PDEVICE_OBJECT pDeviceObject = vcb->TargetDeviceObject;
    struct ext2_super_block * sb = vcb->ext2_super_block;

    vcb->ext2_block = EXT2_MIN_BLOCK_SIZE << sb->s_log_block_size;
    vcb->ext2_frag = EXT2_MIN_FRAG_SIZE << sb->s_log_frag_size;

    vcb->ext2_groups = (sb->s_blocks_count - sb->s_first_data_block +
        sb->s_blocks_per_group - 1) / sb->s_blocks_per_group;

    size = sizeof(struct ext2_group_desc) * vcb->ext2_groups;

    Buffer = ExAllocatePool(PagedPool, size);
    if (!Buffer)
    {
        Ext2DbgPrint(D_EXT2, "Ext2LoadSuper: no enough memory.\n");
        return NULL;
    }

    if (vcb->ext2_block == EXT2_MIN_BLOCK_SIZE)
    {
        lba = (LONGLONG)2 * vcb->ext2_block;
    }

    if (vcb->ext2_block > EXT2_MIN_BLOCK_SIZE)
    {
        lba = (LONGLONG) (vcb->ext2_block);
    }

    Status = Ext2ReadDisk(vcb->TargetDeviceObject, (ULONG)(lba / SECTOR_SIZE), 0, size, Buffer);

    if (!NT_SUCCESS(Status))
    {
        ExFreePool(Buffer);
        Buffer = NULL;
    }

    return (PEXT2_GROUP_DESC)Buffer;
}


BOOLEAN
Ext2SaveGroup(  IN PEXT2_IRP_CONTEXT    IrpContext,
                IN PEXT2_VCB            Vcb )
{
    LONGLONG    Offset;
    ULONG       Len;

    if (Vcb->ext2_block == EXT2_MIN_BLOCK_SIZE) {

        Offset = (LONGLONG) (2 * Vcb->ext2_block);

    } else {

        Offset = (LONGLONG) (Vcb->ext2_block);
    }

    Len = (ULONG)(sizeof(struct ext2_group_desc) * Vcb->ext2_groups);

    return Ext2SaveBuffer(IrpContext, Vcb, Offset, Len, Vcb->ext2_group_desc);
}

BOOLEAN
Ext2GetInodeLba (IN PEXT2_VCB   vcb,
         IN  ULONG  inode,
         OUT PLONGLONG offset)
{
    LONGLONG loc;

    if (inode < 1 || inode > vcb->ext2_super_block->s_inodes_count)
    {
        Ext2DbgPrint(D_EXT2, "Ext2GetInodeLba: Inode value %xh is invalid.\n",inode);
        *offset = 0;
        return FALSE;
    }

    loc = (vcb->ext2_group_desc[(inode - 1) / vcb->ext2_super_block->s_inodes_per_group].bg_inode_table);
    loc = loc * vcb->ext2_block;
    loc = loc + ((inode - 1) % (vcb->ext2_super_block->s_inodes_per_group)) * sizeof(EXT2_INODE);

    *offset = loc;

//  Ext2DbgPrint(D_EXT2, "Ext2GetInodeLba: inode=%xh lba=%xh offset=%xh\n",
//      inode, *lba, *offset);
    return TRUE;
}

BOOLEAN
Ext2LoadInode (IN PEXT2_VCB vcb,
           IN ULONG     inode,
           IN PEXT2_INODE ext2_inode)
{
    IO_STATUS_BLOCK     IoStatus;
    LONGLONG            Offset; 

    if (!Ext2GetInodeLba(vcb, inode, &Offset))
    {
        Ext2DbgPrint(D_EXT2, "Ext2LoadInode: error get inode(%xh)'s addr.\n", inode);
        return FALSE;
    }

    if (!Ext2CopyRead(
            vcb->StreamObj,
            (PLARGE_INTEGER)&Offset,
            sizeof(EXT2_INODE),
            TRUE,
            (PVOID)ext2_inode,
            &IoStatus ));

    if (!NT_SUCCESS(IoStatus.Status))
    {
        return FALSE;
    }

    return TRUE;
}

/*
BOOLEAN
Ext2SaveInode (IN PEXT2_VCB vcb,
           IN ULONG inode,
           IN struct ext2_inode *ext2_inode)
{
    ULONG       lba;
    ULONG       offset;
    NTSTATUS    Status;

    if (!Ext2GetInodeLba(vcb, inode, &lba, &offset))
    {
        Ext2DbgPrint(D_EXT2, "Ext2LoadInode: error get inode(%xh)'s addr.\n", inode);
        return FALSE;
    }

    Status = Ext2WriteDisk(vcb->TargetDeviceObject,
        lba,
        offset,
        sizeof(EXT2_INODE),
        (PVOID)ext2_inode);

    if (!NT_SUCCESS(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;
    LARGE_INTEGER   CurrentTime;

    KeQuerySystemTime(&CurrentTime);
    Ext2Inode->i_mtime = Ext2Inode->i_atime = 
                      (ULONG)(Ext2InodeTime(CurrentTime));
#if 0
    Ext2DbgPrint(D_EXT2, "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n", Inode, Ext2Inode->i_mode, Ext2Inode->i_size);
#endif

    if (!Ext2GetInodeLba(Vcb, Inode, &Offset))
    {
        Ext2DbgPrint(D_EXT2, "Ext2SaveInode: error get inode(%xh)'s addr.\n", Inode);
        return FALSE;
    }

    return Ext2SaveBuffer(IrpContext, Vcb, Offset, sizeof(EXT2_INODE), Ext2Inode);
}


BOOLEAN
Ext2LoadBlock (IN PEXT2_VCB Vcb,
           IN ULONG     dwBlk,
           IN PVOID     Buffer )
{
    IO_STATUS_BLOCK     IoStatus;
    LONGLONG            Offset; 

    Offset = (LONGLONG) dwBlk;
    Offset = Offset * Vcb->ext2_block;

    if (!Ext2CopyRead(
            Vcb->StreamObj,
            (PLARGE_INTEGER)&Offset,
            Vcb->ext2_block,
            TRUE,
            Buffer,
            &IoStatus ));

    if (!NT_SUCCESS(IoStatus.Status))
    {
        return FALSE;
    }

    return TRUE;
}


BOOLEAN
Ext2SaveBlock ( IN PEXT2_IRP_CONTEXT    IrpContext,
                IN PEXT2_VCB            Vcb,
                IN ULONG                dwBlk,
                IN PVOID                Buf )
{
    LONGLONG Offset;

    Offset = (LONGLONG) dwBlk;
    Offset = Offset * Vcb->ext2_block;

    return Ext2SaveBuffer(IrpContext, Vcb, Offset, Vcb->ext2_block, Buf);
}


BOOLEAN
Ext2SaveBuffer( IN PEXT2_IRP_CONTEXT    IrpContext,
                IN PEXT2_VCB            Vcb,
                IN LONGLONG             Offset,
                IN ULONG                Size,
                IN PVOID                Buf )
{
    PBCB        Bcb;
    PVOID       Buffer;

    if( !CcPinRead( Vcb->StreamObj,
                    (PLARGE_INTEGER) (&Offset),
                    Size,
                    TRUE,
                    &Bcb,
                    &Buffer ))
    {
        Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: PinReading error ...\n");
        return FALSE;
    }

#if 0
    Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: Off=%I64xh Len=%xh Bcb=%xh\n", Offset, Size, (ULONG)Bcb);
#endif

    RtlCopyMemory(Buffer, Buf, Size);
    CcSetDirtyPinnedData(Bcb, NULL );

    Ext2RepinBcb(IrpContext, Bcb);

    CcUnpinData(Bcb);

    SetFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);

    Ext2AddMcbEntry(Vcb, Offset, (LONGLONG)Size);

    return TRUE;
}

ULONG Ext2GetBlock(IN PEXT2_VCB vcb,
           ULONG dwContent,
           ULONG Index,
           int   layer )
{
    ULONG       *pData = NULL;
    ULONG       i = 0, j = 0, temp = 1;
    ULONG       dwBlk = 0;

    if (layer == 0)
    {
        dwBlk = dwContent;
    }
    else if (layer <= 3)
    {
        pData = (ULONG *)ExAllocatePool(PagedPool,
                    vcb->ext2_block);
        if (!pData)
        {
            Ext2DbgPrint(D_EXT2, "Ext2GetBlock: no enough memory.\n");
            return dwBlk;
        }

        if (!Ext2LoadBlock(vcb, dwContent, pData))
        {
            return 0;
        }

        temp = 1 << ((10 + vcb->ext2_super_block->s_log_block_size - 2) * (layer - 1));
        
        i = Index / temp;
        j = Index % temp;

        dwBlk = pData[i];

        ExFreePool(pData);

        dwBlk = Ext2GetBlock(vcb, dwBlk, j, layer - 1);
    }
    
    return dwBlk;
}

ULONG Ext2BlockMap(IN PEXT2_VCB vcb,
           IN PEXT2_INODE ext2_inode,
           IN ULONG Index)
{
    ULONG   dwSizes[4] = {EXT2_NDIR_BLOCKS, 1, 1, 1};
    int     i;
    ULONG   dwBlk;

    for (i = 0; i < 4; i++)
    {
        dwSizes[i] = dwSizes[i] << ((10 + vcb->ext2_super_block->s_log_block_size - 2) * i);
    }

    if ((Index * (vcb->ext2_block / SECTOR_SIZE)) >= ext2_inode->i_blocks)
    {
        Ext2DbgPrint(D_EXT2, "Ext2BlockMap: error input paramters.\n");
        return 0;
    }

    for (i = 0; i < 4; i++)
    {
        if (Index < dwSizes[i])
        {
            dwBlk = ext2_inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)];
#if DBG
            {   
                ULONG dwRet = Ext2GetBlock(vcb, dwBlk, Index , i);

                Ext2DbgPrint(D_EXT2, "Ext2BlockMap: i=%xh index=%xh dwBlk=%xh (%xh)\n", i, Index, dwRet, dwBlk);

                return dwRet;
            }
#else
            return Ext2GetBlock(vcb, dwBlk, Index , i);
#endif
        }
	Index -= dwSizes[i];
    }

    return 0;
}


ULONG Ext2BuildBDL( IN PEXT2_IRP_CONTEXT    IrpContext,
                    IN PEXT2_VCB Vcb,
                    IN PEXT2_INODE ext2_inode,
                    IN ULONG offset, 
                    IN ULONG size, 
                    OUT PEXT2_BDL *ext2_bdl )
{
    ULONG   nBeg, nEnd, nBlocks;
    ULONG   dwBlk;
    ULONG   i;
    ULONG   dwBytes = 0;
    LONGLONG lba;

    PEXT2_BDL   ext2bdl;

    *ext2_bdl = NULL;

    if (offset >= ext2_inode->i_size)
    {
        Ext2DbgPrint(D_EXT2, "Ext2BuildBDL: beyond the file range.\n");
        return 0;
    }

/*
    if (offset + size > ext2_inode->i_size)
    {
        size = ext2_inode->i_size - offset;
    }
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -