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

📄 generic.c

📁 可以在不启动LINUX的情况下直接访问EXT2和EXT3格式的磁盘
💻 C
📖 第 1 页 / 共 5 页
字号:
            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 + -