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

📄 ext2.c

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

    nBeg = offset / Vcb->ext2_block;
    nEnd = (size + offset + Vcb->ext2_block - 1) / Vcb->ext2_block;

    nBlocks = 0;

    if ((nEnd - nBeg) > 0)
    {
        ext2bdl = ExAllocatePool(PagedPool, sizeof(EXT2_BDL) * (nEnd - nBeg));

        if (ext2bdl)
        {

            RtlZeroMemory(ext2bdl, sizeof(EXT2_BDL) * (nEnd - nBeg));
            
            for (i = nBeg; i < nEnd; i++)
            {
                dwBlk = Ext2BlockMap(Vcb, ext2_inode, i);

                if (dwBlk > 0)
                {
                
                    lba = (LONGLONG) dwBlk;
                    lba = lba * Vcb->ext2_block;
                
                    if (nBeg == nEnd - 1) // ie. (nBeg == nEnd - 1)
                    {
                        dwBytes = size;
                        ext2bdl[nBlocks].Lba = lba + (LONGLONG)(offset % (Vcb->ext2_block));
                        ext2bdl[nBlocks].Length = dwBytes;
                        ext2bdl[nBlocks].Offset = 0;

                        nBlocks++;
                    }
                    else
                    {
                        if (i == nBeg)
                        {
                            dwBytes = Vcb->ext2_block - (offset % (Vcb->ext2_block));
                            ext2bdl[nBlocks].Lba = lba + (LONGLONG)(offset % (Vcb->ext2_block));
                            ext2bdl[nBlocks].Length = dwBytes;
                            ext2bdl[nBlocks].Offset = 0;

                            nBlocks++;
                        }
                        else if (i == nEnd - 1)
                        {
                            if (ext2bdl[nBlocks - 1].Lba + ext2bdl[nBlocks - 1].Length == lba)
                            {
                                ext2bdl[nBlocks - 1].Length += size - dwBytes;
                            }
                            else
                            {
                                ext2bdl[nBlocks].Lba = lba;
                                ext2bdl[nBlocks].Length = size - dwBytes;
                                ext2bdl[nBlocks].Offset = dwBytes;
                                nBlocks++;
                            }

                            dwBytes = size;

                        }
                        else
                        {
                            if (ext2bdl[nBlocks - 1].Lba + ext2bdl[nBlocks - 1].Length == lba)
                            {
                                ext2bdl[nBlocks - 1].Length += Vcb->ext2_block;
                            }
                            else
                            {
                                ext2bdl[nBlocks].Lba = lba;
                                ext2bdl[nBlocks].Length = Vcb->ext2_block;
                                ext2bdl[nBlocks].Offset = dwBytes;
                                nBlocks++;
                            }

                            dwBytes +=  Vcb->ext2_block;
                        }
                    }
                }
                else
                {
                    break;
                }
            }

            *ext2_bdl = ext2bdl;
            return nBlocks;
        }
    }

    // Error
    return 0;
}

BOOLEAN Ext2NewBlock(   PEXT2_IRP_CONTEXT IrpContext,
                        PEXT2_VCB Vcb,
                        ULONG     GroupHint,
                        ULONG     BlockHint,  
                        PULONG    dwRet )
{
    RTL_BITMAP      BlockBitmap;
    LARGE_INTEGER   Offset;
    ULONG           Length;

    PBCB            BitmapBcb;
    PVOID           BitmapCache;

    ULONG           Group = 0, dwBlk, dwHint = 0;

    *dwRet = 0;
    dwBlk = 0XFFFFFFFF;

    if (GroupHint > Vcb->ext2_groups)
        GroupHint = Vcb->ext2_groups - 1;

    if (BlockHint != 0)
    {
        GroupHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) / Vcb->ext2_super_block->s_blocks_per_group;
        dwHint = (BlockHint - EXT2_FIRST_DATA_BLOCK) % Vcb->ext2_super_block->s_blocks_per_group;
    }
  
ScanBitmap:
  
    // Perform Prefered Group
    if (Vcb->ext2_group_desc[GroupHint].bg_free_blocks_count)
    {
        Offset.QuadPart = (LONGLONG) Vcb->ext2_block;
        Offset.QuadPart = Offset.QuadPart * Vcb->ext2_group_desc[GroupHint].bg_block_bitmap;

        if (GroupHint == Vcb->ext2_groups - 1)
            Length = Vcb->ext2_super_block->s_blocks_count % Vcb->ext2_super_block->s_blocks_per_group;
        else
            Length = Vcb->ext2_super_block->s_blocks_per_group;

        if (!CcPinRead( Vcb->StreamObj,
                        &Offset,
                        Vcb->ext2_block,
                        TRUE,
                        &BitmapBcb,
                        &BitmapCache ) )
        {
            Ext2DbgPrint(D_EXT2, "Ext2NewBlock: PinReading error ...\n");
            return FALSE;
        }

        RtlInitializeBitMap( &BlockBitmap,
                             BitmapCache,
                             Length );

        Group = GroupHint;

        if (RtlCheckBit(&BlockBitmap, dwHint) == 0)
        {
            dwBlk = dwHint;
        }
        else
        {
            dwBlk = RtlFindClearBits(&BlockBitmap, 1, dwHint);
        }

        // We could not get new block in the prefered group.
        if (dwBlk == 0xFFFFFFFF)
        {
            CcUnpinData(BitmapBcb);
            BitmapBcb = NULL;
            BitmapCache = NULL;

            RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
        }
    }

    if (dwBlk == 0xFFFFFFFF)
    {
        for(Group = 0; Group < Vcb->ext2_groups; Group++)
        if (Vcb->ext2_group_desc[Group].bg_free_blocks_count)
        {

            if (Group == GroupHint)
                continue;

            Offset.QuadPart = (LONGLONG) Vcb->ext2_block;
            Offset.QuadPart = Offset.QuadPart * Vcb->ext2_group_desc[Group].bg_block_bitmap;

            if (Vcb->ext2_groups == 1)
            {
                Length = Vcb->ext2_super_block->s_blocks_count;
            }
            else
            {
                if (Group == Vcb->ext2_groups - 1)
                    Length = Vcb->ext2_super_block->s_blocks_count % Vcb->ext2_super_block->s_blocks_per_group;
                else
                    Length = Vcb->ext2_super_block->s_blocks_per_group;
            }

            if (!CcPinRead( Vcb->StreamObj,
                            &Offset,
                            Vcb->ext2_block,
                            TRUE,
                            &BitmapBcb,
                            &BitmapCache ) )
            {
                Ext2DbgPrint(D_EXT2, "Ext2NewBlock: PinReading error ...\n");
                return FALSE;
            }

            RtlInitializeBitMap( &BlockBitmap,
                                 BitmapCache,
                                 Length );

            dwBlk = RtlFindClearBits(&BlockBitmap, 1, 0);

            if (dwBlk != 0xFFFFFFFF)
            {
                break;
            }
            else
            {
                CcUnpinData(BitmapBcb);
                BitmapBcb = NULL;
                BitmapCache = NULL;

                RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
            }
        }
    }
        
    if (dwBlk < Length)
    {
        RtlSetBits(&BlockBitmap, dwBlk, 1);

	    CcSetDirtyPinnedData(BitmapBcb, NULL );

        Ext2RepinBcb(IrpContext, BitmapBcb);

        CcUnpinData(BitmapBcb);

        Ext2AddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->ext2_block);

        *dwRet = dwBlk + EXT2_FIRST_DATA_BLOCK + Group * Vcb->ext2_super_block->s_blocks_per_group;

        //Updating Group Desc / Superblock
        Vcb->ext2_group_desc[Group].bg_free_blocks_count--;
        Ext2SaveGroup(IrpContext, Vcb);

        Vcb->ext2_super_block->s_free_blocks_count--;
        Ext2SaveSuper(IrpContext, Vcb);

        {
            ULONG i=0;
            for (i=0; i < Vcb->ext2_groups; i++)
            {
                if ((Vcb->ext2_group_desc[i].bg_block_bitmap == *dwRet) ||
                    (Vcb->ext2_group_desc[i].bg_inode_bitmap == *dwRet) ||
                    (Vcb->ext2_group_desc[i].bg_inode_table == *dwRet) )
                {
                    Ext2DbgBreakPoint();
                    GroupHint = Group;
                    goto ScanBitmap;
                }
            }
        }

        return TRUE;
    }

    return FALSE;
}

BOOLEAN Ext2FreeBlock(  PEXT2_IRP_CONTEXT IrpContext,
                        PEXT2_VCB Vcb,
                        ULONG     Block )
{
    RTL_BITMAP      BlockBitmap;
    LARGE_INTEGER   Offset;
    ULONG           Length;

    PBCB            BitmapBcb;
    PVOID           BitmapCache;

    ULONG           Group, dwBlk;
    BOOLEAN         bModified = FALSE;

    if (Block < EXT2_FIRST_DATA_BLOCK || Block > (Vcb->ext2_super_block->s_blocks_per_group * Vcb->ext2_groups))
    {
        Ext2DbgBreakPoint();
        return TRUE;
    }

    Ext2DbgPrint(D_EXT2, "Ext2FreeBlock: Block %xh to be freed.\n", Block);

    Group = (Block - EXT2_FIRST_DATA_BLOCK) / (Vcb->ext2_super_block->s_blocks_per_group);

    dwBlk = (Block - EXT2_FIRST_DATA_BLOCK) % Vcb->ext2_super_block->s_blocks_per_group;
    
    {
        Offset.QuadPart = (LONGLONG) Vcb->ext2_block;
        Offset.QuadPart = Offset.QuadPart * Vcb->ext2_group_desc[Group].bg_block_bitmap;

        if (Group == Vcb->ext2_groups - 1)
            Length = Vcb->ext2_super_block->s_blocks_count % Vcb->ext2_super_block->s_blocks_per_group;
        else
            Length = Vcb->ext2_super_block->s_blocks_per_group;

        if (!CcPinRead( Vcb->StreamObj,
                        &Offset,
                        Vcb->ext2_block,
                        TRUE,
                        &BitmapBcb,
                        &BitmapCache ) )
        {
            Ext2DbgPrint(D_EXT2, "Ext2DeleteBlock: PinReading error ...\n");
            return FALSE;
        }

        RtlInitializeBitMap( &BlockBitmap,
                             BitmapCache,
                             Length );

        if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
        {
            
        }
        else
        {
            RtlClearBits(&BlockBitmap, dwBlk, 1);
            bModified = TRUE;
        }

        if (!bModified)
        {
            CcUnpinData(BitmapBcb);
            BitmapBcb = NULL;
            BitmapCache = NULL;

            RtlZeroMemory(&BlockBitmap, 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
        Vcb->ext2_group_desc[Group].bg_free_blocks_count++;
        Ext2SaveGroup(IrpContext, Vcb);

        Vcb->ext2_super_block->s_free_blocks_count++;
        Ext2SaveSuper(IrpContext, Vcb);

        return TRUE;
    }

    return FALSE;
}


BOOLEAN Ext2ExpandBlock(PEXT2_IRP_CONTEXT IrpContext,
                        PEXT2_VCB   Vcb,
                        PEXT2_FCB   Fcb,
                        ULONG   dwContent,
                        ULONG   Index,
                        ULONG   layer,
                        BOOLEAN bNew,
                        ULONG   *dwRet)
{
	ULONG		*pData = NULL;
	ULONG		i = 0, j = 0, temp = 1;
	ULONG		dwNewBlk = 0, dwBlk = 0;
    BOOLEAN     bDirty = FALSE;
    BOOLEAN     bRet = TRUE;

    PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;

    pData = (ULONG *) ExAllocatePool(PagedPool, Vcb->ext2_block);

    if (!pData)
    {
        return FALSE;
    }

    RtlZeroMemory(pData, Vcb->ext2_block);

    if (bNew)
    {
        if (layer == 0 && !IsFlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
        {
            LARGE_INTEGER   Offset;
            
            Offset.QuadPart  = (LONGLONG) dwContent;
            Offset.QuadPart = Offset.QuadPart * Vcb->ext2_block;

            Ext2RemoveMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->ext2_block);

/*
            if (Vcb->SectionObject)
            {
                CcFlushCache(   &(Vcb->SectionObject),
                                (PLARGE_INTEGER)&(Offset),
                                Vcb->ext2_block,
                                NULL);

                if (Vcb->SectionObject.DataSectionObject != NULL)
                {
                    ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
                    ExReleaseResource(&Vcb->PagingIoResource);
                           
   			        CcPurgeCacheSection( &(Vcb->SectionObject),
                                         (PLARGE_INTEGER)(&Offset),
								         Vcb->ext2_block,
                                         FALSE );
                }
            }
*/
        }
        else
        {
          if (!Ext2SaveBlock(IrpContext, Vcb, dwContent, (PVOID)pData))
            {
                bRet = FALSE;
                goto errorout;
            }
        }
    }

	if (layer == 0)
	{
		dwNewBlk = dwContent;
	}
	else if (layer <= 3)
	{
        if (!bNew)
        {
            bRet = Ext2LoadBlock(Vcb, dwContent, (void *)pData);
            if (!bRet) goto errorout;
        }

        temp = 1 << ((10 + pExt2Sb->s_log_block_size - 2) * (layer - 1));

		i = Index / temp;
		j = Index % temp;

        dwBlk = pData[i];

        if (dwBlk == 0)
        {
            if (!Ext2NewBlock(IrpContext, Vcb, 0, dwContent, &dwBlk))
            {
                bRet = FALSE;
                Ext2DbgPrint(D_EXT2, "Ext2ExpandBlock: get new block error.\n");
                goto errorout;
            }

            pData[i] = dwBlk;
            bDirty = TRUE;
        }

		if (!Ext2ExpandBlock(IrpContext, Vcb, Fcb, dwBlk, j, layer - 1, bDirty, &dwNewBlk))
        {
            bRet = FALSE;
            Ext2DbgPrint(D_EXT2, "Ext2ExpandBlockk: ... error recuise...\n");
            goto errorout;
        }
        
        if (bDirty)
        {
            bRet = Ext2SaveBlock(IrpContext, Vcb, dwContent, (void *)pData);
        }
	}

errorout:

⌨️ 快捷键说明

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