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

📄 generic.c

📁 可以在不启动LINUX的情况下直接访问EXT2和EXT3格式的磁盘
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * COPYRIGHT:        See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
 * FILE:             generic.c
 * PROGRAMMER:       Matt Wu <mattwu@163.com>
 * HOMEPAGE:         http://ext2.yeah.net
 * UPDATE HISTORY: 
 */

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

#include "ext2fs.h"

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

extern PEXT2_GLOBAL Ext2Global;

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

BOOLEAN
Ext2IsBlockEmpty(PULONG BlockArray, ULONG SizeArray);

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

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

#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, Ext2UpdateVcbStat)
#pragma alloc_text(PAGE, Ext2NewBlock)
#pragma alloc_text(PAGE, Ext2FreeBlock)
#pragma alloc_text(PAGE, Ext2ExpandLast)
#pragma alloc_text(PAGE, Ext2ExpandBlock)

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

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

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

#endif

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

NTSTATUS
Ext2LoadSuper(IN PEXT2_VCB      Vcb,
              IN BOOLEAN        bVerify,
              OUT PEXT2_SUPER_BLOCK * Sb)
{
    NTSTATUS          Status;
    PEXT2_SUPER_BLOCK Ext2Sb = NULL;
    
    Ext2Sb = (PEXT2_SUPER_BLOCK)
                ExAllocatePoolWithTag(
                    PagedPool,
                    SUPER_BLOCK_SIZE,
                    EXT2_SB_MAGIC
                );
    if (!Ext2Sb) {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto errorout;
    }

    Status = Ext2ReadDisk(
                Vcb,
                (ULONGLONG) SUPER_BLOCK_OFFSET,
                SUPER_BLOCK_SIZE,
                (PVOID) Ext2Sb,
                bVerify );

    if (!NT_SUCCESS(Status)) {

        DEBUG(DL_ERR, ( "Ext2ReadDisk: disk device error.\n"));

        ExFreePoolWithTag(Ext2Sb, EXT2_SB_MAGIC);
        Ext2Sb = NULL;
    }

errorout:

    *Sb = Ext2Sb;
    return Status;
}


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

    offset = (LONGLONG) SUPER_BLOCK_OFFSET;
    rc = Ext2SaveBuffer( IrpContext,
                         Vcb,
                         offset,
                         SUPER_BLOCK_SIZE,
                         Vcb->SuperBlock
                        );

    if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
        Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
    }

    return rc;
}


BOOLEAN
Ext2RefreshSuper (
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb
    )
{
    LONGLONG        offset;
    IO_STATUS_BLOCK iosb;

    offset = (LONGLONG) SUPER_BLOCK_OFFSET;
    if (!CcCopyRead(
            Vcb->Volume,
            (PLARGE_INTEGER)&offset,
            SUPER_BLOCK_SIZE,
            TRUE,
            (PVOID)Vcb->SuperBlock,
            &iosb )) {
        return FALSE;
    }

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

    return TRUE;
}

BOOLEAN
Ext2LoadGroup(IN PEXT2_VCB Vcb)
{
    ULONG       Size;
    PVOID       Buffer;
    LONGLONG    Lba = 0;
    NTSTATUS    Status;

    Size = sizeof(EXT2_GROUP_DESC) * Vcb->NumOfGroups;

    if (Vcb->BlockSize == EXT2_MIN_BLOCK) {
        Lba = (LONGLONG)2 * Vcb->BlockSize;
    }

    if (Vcb->BlockSize > EXT2_MIN_BLOCK) {
        Lba = (LONGLONG) (Vcb->BlockSize);
    }

    if (Lba == 0) {
        return FALSE;
    }

    Buffer = ExAllocatePoolWithTag(PagedPool, Size, EXT2_GD_MAGIC);
    if (!Buffer) {
        DEBUG(DL_ERR, ( "Ext2LoadSuper: no enough memory.\n"));
        return FALSE;
    }

    DEBUG(DL_INF, ( "Ext2LoadGroup: Lba=%I64xh Size=%xh\n", Lba, Size));

    Status = Ext2ReadDisk(  Vcb,
                            Lba,
                            Size,
                            Buffer,
                            FALSE );

    if (!NT_SUCCESS(Status)) {
        ExFreePoolWithTag(Buffer, EXT2_GD_MAGIC);
        Buffer = NULL;

        return FALSE;
    }

    Vcb->GroupDesc = (PEXT2_GROUP_DESC) Buffer;

    return TRUE;
}

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

    if (Vcb->BlockSize == EXT2_MIN_BLOCK) {

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

    } else {

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

    Offset += ((LONGLONG) sizeof(struct ext2_group_desc) * Group);

    bRet = Ext2SaveBuffer(
                    IrpContext,
                    Vcb,
                    Offset,
                    sizeof(struct ext2_group_desc),
                    &(Vcb->GroupDesc[Group]) );

    if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
        Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
    }

    return bRet;
}   


BOOLEAN
Ext2RefreshGroup(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb
    )
{
    IO_STATUS_BLOCK iosb;
    LONGLONG        offset;

    if (Vcb->BlockSize == EXT2_MIN_BLOCK) {
        offset = (LONGLONG) (2 * Vcb->BlockSize);
    } else {
        offset = (LONGLONG) (Vcb->BlockSize);
    }

    if (!CcCopyRead(
            Vcb->Volume,
            (PLARGE_INTEGER)&offset,
            sizeof(struct ext2_group_desc) *
            Vcb->NumOfGroups,
            TRUE,
            (PVOID)&Vcb->GroupDesc[0],
            &iosb)) {
        return FALSE;
    }

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

    return TRUE;
}       

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

    if (inode < 1 || inode > INODES_COUNT)  {
        DEBUG(DL_ERR, ( "Ext2GetInodeLba: Inode value %xh is invalid.\n",inode));
        *offset = 0;
        return FALSE;
    }

    loc = (Vcb->GroupDesc[(inode - 1) / INODES_PER_GROUP ].bg_inode_table);
    loc = loc * Vcb->BlockSize;
    loc = loc + ((inode - 1) % INODES_PER_GROUP) * INODE_SIZE;

    *offset = loc;

    return TRUE;
}

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

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

    if (!CcCopyRead(
            Vcb->Volume,
            (PLARGE_INTEGER)&Offset,
            INODE_SIZE,
            PIN_WAIT,
            (PVOID)Inode,
            &IoStatus )) {
        return FALSE;
    }

    if (!NT_SUCCESS(IoStatus.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;
    BOOLEAN         rc;

    DEBUG(DL_INF, ( "Ext2SaveInode: Saving Inode %xh: Mode=%xh Size=%xh\n",
                         Inode, Ext2Inode->i_mode, Ext2Inode->i_size));
    rc = Ext2GetInodeLba(Vcb, Inode, &Offset);
    if (!rc)  {
        DEBUG(DL_ERR, ( "Ext2SaveInode: error get inode(%xh)'s addr.\n", Inode));
        goto errorout;
    }

    rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, INODE_SIZE, Ext2Inode);

    if (rc && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
        Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
    }

errorout:
    return rc;
}


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

    Offset = (LONGLONG) Index;
    Offset = Offset * Vcb->BlockSize;

    if (!CcCopyRead(
            Vcb->Volume,
            (PLARGE_INTEGER)&Offset,
            Vcb->BlockSize,
            PIN_WAIT,
            Buffer,
            &IoStatus ));

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

    return TRUE;
}


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

    Offset = (LONGLONG) Index;
    Offset = Offset * Vcb->BlockSize;

    rc = Ext2SaveBuffer(IrpContext, Vcb, Offset, Vcb->BlockSize, Buf);

    if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
        Ext2StartFloppyFlushDpc(Vcb, NULL, NULL);
    }

    return rc;
}

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

    if( !CcPreparePinWrite(
                    Vcb->Volume,
                    (PLARGE_INTEGER) (&Offset),
                    Size,
                    FALSE,
                    Ext2CanIWait(),
                    &Bcb,
                    &Buffer )) {

        DEBUG(DL_ERR, ( "Ext2SaveBuffer: failed to PinLock offset %I64xh ...\n", Offset));
        return FALSE;
    }

    __try {

        RtlCopyMemory(Buffer, Buf, Size);
        CcSetDirtyPinnedData(Bcb, NULL );
        SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);

        rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Size);
        if (!rc) {
            DbgBreak();
            Ext2Sleep(100);
            rc = Ext2AddVcbExtent(Vcb, Offset, (LONGLONG)Size);
        }

    } __finally {
        CcUnpinData(Bcb);
    }


    return rc;
}

NTSTATUS
Ext2GetBlock(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONG                Base,
    IN ULONG                Layer,
    IN ULONG                Start,

⌨️ 快捷键说明

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