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

📄 generic.c

📁 可以在不启动LINUX的情况下直接访问EXT2和EXT3格式的磁盘
💻 C
📖 第 1 页 / 共 5 页
字号:
    IN ULONG                SizeArray,
    IN PULONG               BlockArray,
    IN BOOLEAN              bAlloc,
    IN OUT PULONG           Hint,
    OUT PULONG              Block,
    OUT PULONG              Number
    )
{
    NTSTATUS    Status = STATUS_SUCCESS;
    PBCB        Bcb = NULL;    
    PULONG      pData = NULL;
    ULONG       Slot = 0, i = 0;
    ULONG       Unit = 1;

    LARGE_INTEGER Offset;

    if (Layer == 0) {

        *Number = 1;
        if (BlockArray[0] == 0 && bAlloc) {

            /* now allocate new block */
            Status = Ext2ExpandLast(
                        IrpContext,
                        Vcb,
                        Mcb,
                        Base,
                        Layer,
                        NULL,
                        Hint,
                        &BlockArray[0],
                        Number
                        );

            if (!NT_SUCCESS(Status)) {
                 goto errorout;
             }
        }

        *Block = BlockArray[0];
        for (i=1; i < SizeArray; i++) {
            if (BlockArray[i] == BlockArray[i-1] + 1) {
                *Number = *Number + 1;
            } else {
                break;
            }
        }
        *Hint = BlockArray[*Number - 1];

    } else if (Layer <= 3) {

        /* check the block is valid or not */
        if (BlockArray[0] >= TOTAL_BLOCKS) {
            DbgBreak();
            return STATUS_DISK_CORRUPT_ERROR;
        }

        /* map memory in cache for the index block */
        Offset.QuadPart = ((LONGLONG)BlockArray[0]) << BLOCK_BITS;
        if( !CcPinRead( Vcb->Volume,
                    (PLARGE_INTEGER) (&Offset),
                    BLOCK_SIZE,
                    Ext2CanIWait(),
                    &Bcb,
                    &pData )) {

            DEBUG(DL_ERR, ( "Ext2GetBlock: Failed to PinLock block: %xh ...\n",
                                   BlockArray[0] ));
            Status = STATUS_CANT_WAIT;
            goto errorout;
        }
 

        if (Layer > 1) {
            Unit = Vcb->NumBlocks[Layer - 1];
        } else {
            Unit = 1; 
        }

        Slot  = Start / Unit;
        Start = Start % Unit;
       
        if (pData[Slot] == 0) {

            if (bAlloc) {

                /* we need allocate new block and zero all data in case
                   it's an in-direct block. Index stores the new block no. */
                ULONG   Count = 1;
                Status = Ext2ExpandLast(
                            IrpContext,
                            Vcb,
                            Mcb,
                            Base,
                            Layer,
                            NULL,
                            Hint,
                            &pData[Slot],
                            &Count
                            );

                if (!NT_SUCCESS(Status)) {
                    goto errorout;
                }

                /* refresh hint block */
                *Hint = pData[Slot];

                /* set dirty bit to notify system to flush */
                CcSetDirtyPinnedData(Bcb, NULL );
                SetFlag(Vcb->Volume->Flags, FO_FILE_MODIFIED);
                if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
                                     (LONGLONG)BLOCK_SIZE)) {
                    DbgBreak();
                    Ext2Sleep(100);
                    if (!Ext2AddVcbExtent(Vcb, Offset.QuadPart,
                                     (LONGLONG)BLOCK_SIZE)) {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        goto errorout;
                    }
                }

                /* save inode information here */
                Ext2SaveInode(IrpContext, Vcb, Mcb->iNo,  Mcb->Inode);
  
            } else {

                *Number = 1;

                if (Layer == 1) {
                    for (i = Slot + 1; i < BLOCK_SIZE/4; i++) {
                        if (pData[i] == 0) {
                            *Number = *Number + 1;
                        } else {
                            break;
                        }
                    }
                } else if (Layer == 2) {
                    *Number = BLOCK_SIZE/4 - Start;
                } else {
                    *Number = BLOCK_SIZE/4;
                }

                goto errorout;
            }
        }

        /* transfer to next recursion call */
        Status = Ext2GetBlock(
                    IrpContext,
                    Vcb,
                    Mcb,
                    Base,
                    Layer - 1,
                    Start,
                    BLOCK_SIZE/4 - Slot,
                    &pData[Slot],
                    bAlloc,
                    Hint,
                    Block,
                    Number
                    );

        if (!NT_SUCCESS(Status)) {
            goto errorout;
        }
    }

errorout:

    /* free the memory of pData */
    if (Bcb) {
        CcUnpinData(Bcb);
    }

    if (!NT_SUCCESS(Status)) {
        *Block = 0;
    }

    return Status;
}

NTSTATUS
Ext2BlockMap(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_MCB            Mcb,
    IN ULONG                Index,
    IN BOOLEAN              bAlloc,
    OUT PULONG              pBlock,
    OUT PULONG              Number
    )
{
    ULONG   Layer;
    ULONG   Slot;

    ULONG   Base = Index;

    NTSTATUS Status = STATUS_SUCCESS;

    *pBlock = 0;
    *Number = 0;

    for (Layer = 0; Layer < EXT2_BLOCK_TYPES; Layer++) {

        if (Index < Vcb->NumBlocks[Layer]) {

            ULONG   dwRet = 0;
            ULONG   dwBlk = 0;
            ULONG   dwHint = 0;

            Slot = (Layer==0) ? (Index):(Layer + EXT2_NDIR_BLOCKS - 1);
            dwBlk = Mcb->Inode->i_block[Slot];

            if (dwBlk == 0) {

                if (!bAlloc) {

                    *Number = 1;
                    goto errorout;

                } else {

                    if (Slot) {
                        dwHint = Mcb->Inode->i_block[Slot - 1];
                    }

                    /* allocate and zero block if necessary */
                    *Number = 1;
                    Status = Ext2ExpandLast(
                                IrpContext,
                                Vcb,
                                Mcb,
                                Base,
                                Layer,
                                NULL,
                                &dwHint,
                                &dwBlk,
                                Number
                                );

                    if (!NT_SUCCESS(Status)) {
                        goto errorout;
                    }

                    /* save the it into inode*/
                    Mcb->Inode->i_block[Slot] = dwBlk;

                    /* save the inode */
                    if (!Ext2SaveInode( IrpContext,
                                        Vcb,
                                        Mcb->iNo,
                                        Mcb->Inode)) {

                        Status = STATUS_UNSUCCESSFUL;
                        Ext2FreeBlock(IrpContext, Vcb, dwBlk, 1);

                        goto errorout;
                    }
                }
            }

            /* querying block number of the index-th file block */
           Status = Ext2GetBlock(
                        IrpContext,
                        Vcb,
                        Mcb,
                        Base,
                        Layer,
                        Index,
                        (Layer == 0) ? (Vcb->NumBlocks[Layer] - Index) : 1,
                        &Mcb->Inode->i_block[Slot],
                        bAlloc,
                        &dwHint,
                        &dwRet,
                        Number
                        );

            if (NT_SUCCESS(Status)) {
                *pBlock = dwRet;
            }

            break;
        }

        Index -= Vcb->NumBlocks[Layer];
    }

errorout:

    return Status;
}

VOID
Ext2UpdateVcbStat(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb
    )
{
    ULONG i;

    Vcb->SuperBlock->s_free_blocks_count = 0;
    Vcb->SuperBlock->s_free_inodes_count = 0;
    
    for (i = 0; i < Vcb->NumOfGroups; i++) {
        Vcb->SuperBlock->s_free_blocks_count +=
            Vcb->GroupDesc[i].bg_free_blocks_count;
        Vcb->SuperBlock->s_free_inodes_count +=
            Vcb->GroupDesc[i].bg_free_inodes_count;
    }

    Ext2SaveSuper(IrpContext, Vcb);
}

NTSTATUS
Ext2NewBlock(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN ULONG                GroupHint,
    IN ULONG                BlockHint,  
    OUT PULONG              Block,
    IN OUT PULONG           Number
    )
{
    RTL_BITMAP              BlockBitmap;
    LARGE_INTEGER           Offset;

    PBCB                    BitmapBcb;
    PVOID                   BitmapCache;

    ULONG                   Group = 0;
    ULONG                   Index = 0xFFFFFFFF;
    ULONG                   dwHint = 0;
    ULONG                   Count = 0;
    ULONG                   Length = 0;

    NTSTATUS                Status = STATUS_DISK_FULL;

    *Block = 0;

    ExAcquireResourceExclusiveLite(&Vcb->MetaLock, TRUE);

    /* validate the hint group and hint block */ 
    if (GroupHint >= Vcb->NumOfGroups) {
        DbgBreak();
        GroupHint = Vcb->NumOfGroups - 1;
    }

    if (BlockHint != 0) {
        GroupHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;
        dwHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;
    }

    Group = GroupHint;

Again:

    if (Vcb->GroupDesc[Group].bg_free_blocks_count) {

        /* check the block is valid or not */
        if (Vcb->GroupDesc[Group].bg_block_bitmap >= TOTAL_BLOCKS) {
            DbgBreak();
            Status = STATUS_DISK_CORRUPT_ERROR;
            goto errorout;
        }

        Offset.QuadPart = Vcb->GroupDesc[Group].bg_block_bitmap;
        Offset.QuadPart = Offset.QuadPart << BLOCK_BITS;

        if (Group == Vcb->NumOfGroups - 1) {

            Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;

            /* s_blocks_count is integer multiple of s_blocks_per_group */
            if (Length == 0) {
                Length = BLOCKS_PER_GROUP;
            }
        } else {
            Length = BLOCKS_PER_GROUP;
        }

        if (!CcPinRead( Vcb->Volume,
                        &Offset,
                        Vcb->BlockSize,
                        Ext2CanIWait(),
                        &BitmapBcb,
                        &BitmapCache ) ) {

            DEBUG(DL_ERR, ("Ext2NewBlock: failed to PinLock bitmap block %xh ...\n",
                            Vcb->GroupDesc[Group].bg_block_bitmap ));
            Status = STATUS_CANT_WAIT;
            DbgBreak();
            goto errorout;
        }

        /* initialize bitmap buffer */
        RtlInitializeBitMap(&BlockBitmap, BitmapCache, Length);

        /* try to find a clear bit range */
        Index = RtlFindClearBits(&BlockBitmap, *Number, dwHint);

        /* We could not get new block in the prefered group */
        if (Index == 0xFFFFFFFF) {

            /* search clear bits from the hint block */
            Count = RtlFindNextForwardRunClear(&BlockBitmap, dwHint, &Index);
            if (dwHint != 0 && Count == 0) {
                /* search clear bits from the very beginning */
                Count = RtlFindNextForwardRunClear(&BlockBitmap, 0, &Index);
            }

            if (Count == 0) {

                /* release bitmap */
                CcUnpinData(BitmapBcb);
                BitmapBcb = NULL;
                BitmapCache = NULL;
                RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));

                /* no blocks found: set bg_free_blocks_count to 0 */
                Vcb->GroupDesc[Group].bg_free_blocks_count = 0;
                Ext2SaveGroup(IrpContext, Vcb, Group);

               /* will try next group */
                goto Again;

            } else {

                /* we got free blocks */
                if (Count <= *Number) {
                    *Number = Count;
                }
            }
        }

    } else {

        /* try next group */
        dwHint = 0;
        Group = (Group + 1) % Vcb->NumOfGroups;
        if (Group != GroupHint) {
            goto Again;
        }

        Index = 0xFFFFFFFF;
    }

    if (Index < Length) {

        /* mark block bits as allocated */
        RtlSetBits(&BlockBitmap, Index, *Number);

        /* update group description */
        Vcb->GroupDesc[Group].bg_free_blocks_count =
                (USHORT)RtlNumberOfClearBits(&BlockBitmap);

        /* set block bitmap dirty in cache */

⌨️ 快捷键说明

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