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

📄 ext2.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
            if (!NT_SUCCESS(Status))
            {
                Ext2DbgPrint(D_EXT2, "Ext2AddDirectory: Reading Directory Content error.\n");
                __leave;
            }

            if ((pTarget->inode == 0) || (pTarget->rec_len >= EXT2_DIR_REC_LEN(pTarget->name_len) + pDir->rec_len))
            {
                if (pTarget->inode)
                {
                    RtlZeroMemory(pTarget, 2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN));

                    // Reading the DCB contents
                     Status = Ext2ReadInode(
                                NULL,
                                Vcb,
                                Dcb->ext2_inode,
                                dwBytes,
                                (PVOID)pTarget,
                                2 * EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
                                &dwRet);

                    if (!NT_SUCCESS(Status))
                    {
                        Ext2DbgPrint(D_EXT2, "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 = pTarget->rec_len - EXT2_DIR_REC_LEN(pTarget->name_len);

                    pTarget->rec_len = EXT2_DIR_REC_LEN(pTarget->name_len);
                }
                else
                {
                    pNewDir = pTarget;
                    pNewDir->rec_len = (USHORT)((ULONG)(Dcb->CommonFCBHeader.AllocationSize.QuadPart) - dwBytes);
                }

                pNewDir->file_type = pDir->file_type;
                pNewDir->inode = pDir->inode;
                pNewDir->name_len = pDir->name_len;
                memcpy(pNewDir->name, pDir->name, pDir->name_len);
                Length += EXT2_DIR_REC_LEN(pDir->name_len);

                bFound = TRUE;
                break;
            }
            
            dwBytes += pTarget->rec_len;
        }

        if (bFound) // Here we fininish the searching journel ...
        {
            ULONG   dwRet;

            if ( (!((pDir->name_len == 1) && (pDir->name[0] == '.'))) &&
                 (!((pDir->name_len == 2) && (pDir->name[0] == '.') && (pDir->name[1] == '.'))) )
                Dcb->ext2_inode->i_links_count++;

            if (Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes, pTarget, Length, FALSE, &dwRet))
                Status = STATUS_SUCCESS;
        }
        else
        {
            // We should expand the size of the dir inode 
            if (!bAdding)
            {
                ULONG dwRet;

                bAdding = Ext2ExpandInode(IrpContext, Vcb, Dcb, &dwRet);

                if (bAdding) {

                    Dcb->ext2_inode->i_size = Dcb->ext2_inode->i_blocks * SECTOR_SIZE;

                    Ext2SaveInode(IrpContext, Vcb, Dcb->Ext2Mcb->Inode, Dcb->ext2_inode);

                    Dcb->CommonFCBHeader.FileSize = Dcb->CommonFCBHeader.AllocationSize;

                     goto Repeat;
                }

                __leave;

            }
            else  // Something must be error!
            {
                __leave;
            }
        }
    }

    __finally
    {

        ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
        Dcb->ReferenceCount--;
        ExReleaseResourceForThreadLite(
                    &Dcb->CountResource,
                    ExGetCurrentResourceThread());

        if(MainResourceAcquired)
            ExReleaseResourceForThreadLite(
                    &Dcb->MainResource,
                    ExGetCurrentResourceThread());

        if (pTarget != NULL)
        {
            ExFreePool(pTarget);
        }

        if (pDir)
            ExFreePool(pDir);
    }
    
    return Status;
}


NTSTATUS
Ext2RemoveEntry (
         IN PEXT2_IRP_CONTEXT   IrpContext,
         IN PEXT2_VCB           Vcb,
         IN PEXT2_FCB           Dcb,
         IN ULONG               Inode )
{
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;

    PEXT2_DIR_ENTRY2        pTarget = NULL;
    PEXT2_DIR_ENTRY2        pPrevDir = NULL;

    USHORT                  PrevRecLen;

    ULONG                   Length = 0;
    ULONG                   dwBytes = 0;

    BOOLEAN                 bRet = FALSE;
    BOOLEAN                 MainResourceAcquired = FALSE;

    ULONG                   dwRet;

    if (!IsFlagOn(Dcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
        return FALSE;

    MainResourceAcquired = ExAcquireResourceExclusiveLite(&Dcb->MainResource, TRUE);


    __try
    {

        ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
        Dcb->ReferenceCount++;
        ExReleaseResourceForThreadLite(
                    &Dcb->CountResource,
                    ExGetCurrentResourceThread());

        pTarget = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
                                     EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
        if (!pTarget)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }
        
        pPrevDir = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
                                     EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
        if (!pPrevDir)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        dwBytes = 0;


        while ((LONGLONG)dwBytes < Dcb->CommonFCBHeader.AllocationSize.QuadPart)
        {
            RtlZeroMemory(pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));

            Status = Ext2ReadInode(
                        NULL,
                        Vcb,
                        Dcb->ext2_inode,
                        dwBytes,
                        (PVOID)pTarget,
                        EXT2_DIR_REC_LEN(EXT2_NAME_LEN),
                        &dwRet);

            if (!NT_SUCCESS(Status))
            {
                Ext2DbgPrint(D_EXT2, "Ext2RemoveEntry: Reading Directory Content error.\n");
                __leave;
            }

            if (pTarget->inode == Inode)
            {
                ULONG   dwRet;
                ULONG   RecLen;

                pPrevDir->rec_len += pTarget->rec_len;
                RecLen = EXT2_DIR_REC_LEN(pTarget->name_len);

                RtlZeroMemory(pTarget, RecLen);

                Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes - PrevRecLen, pPrevDir, 8, FALSE, &dwRet);
                Ext2WriteInode(IrpContext, Vcb, Dcb->ext2_inode, dwBytes, pTarget, RecLen, FALSE, &dwRet);

                // . / .. could not be removed.
                Dcb->ext2_inode->i_links_count--;

                Ext2SaveInode(IrpContext, Vcb, Dcb->Ext2Mcb->Inode, Dcb->ext2_inode);

                bRet = TRUE;
                
                break;
            }
            else
            {
                RtlCopyMemory(pPrevDir, pTarget, EXT2_DIR_REC_LEN(EXT2_NAME_LEN));
                PrevRecLen = pTarget->rec_len;
            }

            dwBytes += pTarget->rec_len;
        }
    }

    __finally
    {

        ExAcquireResourceExclusiveLite(&Dcb->CountResource, TRUE);
        Dcb->ReferenceCount--;
        ExReleaseResourceForThreadLite(
                    &Dcb->CountResource,
                    ExGetCurrentResourceThread());


        if(MainResourceAcquired)
            ExReleaseResourceForThreadLite(
                    &Dcb->MainResource,
                    ExGetCurrentResourceThread());


        if (pTarget != NULL)
        {
            ExFreePool(pTarget);
        }

        if (pPrevDir)
            ExFreePool(pPrevDir);
    }
    
    return bRet;
}

BOOLEAN Ext2TruncateBlock(
                        PEXT2_IRP_CONTEXT IrpContext,
                        PEXT2_VCB Vcb,
                        ULONG   dwContent,
                        ULONG   Index,
                        ULONG   layer,
                        BOOLEAN *bFreed )
{
	ULONG		*pData = NULL;
	ULONG		i = 0, j = 0, temp = 1;
    BOOLEAN     bDirty = FALSE;
    BOOLEAN     bRet = FALSE;
    ULONG       dwBlk;

    LONGLONG    Offset;

    PBCB        Bcb;

    PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;

    *bFreed = FALSE;

	if (layer == 0)
	{
        if (dwContent > 0 && dwContent < (Vcb->ext2_super_block->s_blocks_per_group * Vcb->ext2_groups))
            bRet = Ext2FreeBlock(IrpContext, Vcb, dwContent);
        else
            bRet = TRUE;
        *bFreed = bRet;
	}
	else if (layer <= 3)
	{
        Offset = (LONGLONG) dwContent;
        Offset = Offset * Vcb->ext2_block;

        if( !CcPinRead( Vcb->StreamObj,
                        (PLARGE_INTEGER) (&Offset),
                        Vcb->ext2_block,
                        TRUE,
                        &Bcb,
                        &pData ))
        {
            Ext2DbgPrint(D_EXT2, "Ext2SaveBuffer: PinReading error ...\n");
            goto errorout;
        }

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

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

        dwBlk = pData[i];

        if(!Ext2TruncateBlock(IrpContext, Vcb, dwBlk, j, layer - 1, &bDirty))
            goto errorout;

        if (bDirty)
            pData[i] = 0;

        if (i == 0 && j == 0)
        {
            CcUnpinData(Bcb);
            pData = NULL;

            *bFreed = TRUE;
            bRet = Ext2FreeBlock(IrpContext, Vcb, dwContent);
        }
        else
        {
            CcSetDirtyPinnedData(Bcb, NULL );
            Ext2RepinBcb(IrpContext, Bcb);

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

            bRet = TRUE;
            *bFreed = FALSE;
        }
	}

errorout:

    if (pData)
    {
        CcUnpinData(Bcb);
    }

	return bRet;
}


BOOLEAN
Ext2TruncateInode(
                PEXT2_IRP_CONTEXT IrpContext,
                PEXT2_VCB   Vcb,
                PEXT2_FCB   Fcb )
{
	ULONG   dwSizes[4] = {EXT2_NDIR_BLOCKS, 1, 1, 1};
    ULONG   Index = 0;
    ULONG   dwTotal = 0;
    ULONG   dwBlk = 0;

	ULONG    i;
    BOOLEAN  bRet = FALSE;
    BOOLEAN  bFreed = FALSE;

    PEXT2_SUPER_BLOCK pExt2Sb = Vcb->ext2_super_block;
    PEXT2_INODE Ext2Inode = Fcb->ext2_inode;

    Index = Ext2Inode->i_blocks / (Vcb->ext2_block / 512);

    if (Index > 0) {  Index--; } else { return TRUE; }

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

	if (Index >= dwTotal)
	{
		Ext2DbgPrint(D_EXT2, "Ext2ExpandInode: beyond the maxinum size of an inode.\n");
		return TRUE;
	}

	for (i = 0; i < 4; i++)
	{
		if (Index < dwSizes[i])
		{
            dwBlk = Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)];

			bRet = Ext2TruncateBlock(IrpContext, Vcb, dwBlk, Index , i, &bFreed); 

            if (bRet)
            {
                Ext2Inode->i_blocks -= (Vcb->ext2_block / SECTOR_SIZE);
                Fcb->CommonFCBHeader.AllocationSize.QuadPart -= Vcb->ext2_block;
            
                if (bFreed)
                {
                    Ext2Inode->i_block[i==0 ? (Index):(i + EXT2_NDIR_BLOCKS - 1)] = 0;

                    // Inode struct saving is done externally.
                    bRet = Ext2SaveInode(IrpContext, Vcb, Fcb->Ext2Mcb->Inode, Ext2Inode);
                }
            }

            break;
		}

		Index -= dwSizes[i];
	}

    return bRet;
}

BOOLEAN
Ext2AddMcbEntry (
    IN PEXT2_VCB Vcb,
    IN LONGLONG  Lba,
    IN LONGLONG  Length)
{
    LONGLONG    Offset;
    LONGLONG    DirtyLba;
    LONGLONG    DirtyLen;


    Offset = Lba & (~(SECTOR_SIZE - 1));

    Length = (Length + Lba - Offset + SECTOR_SIZE - 1) & (~(SECTOR_SIZE - 1));

    ASSERT ((Offset & (SECTOR_SIZE - 1)) == 0);
    ASSERT ((Length & (SECTOR_SIZE - 1)) == 0);

    if (Ext2LookupMcbEntry(Vcb, Offset, &DirtyLba, &DirtyLen, NULL, NULL, NULL))
    {
        if (DirtyLba == Offset && DirtyLen >= Length)
            return TRUE;
    }

    Ext2DbgPrint(D_EXT2, "Ext2AddMcbEntry: Range Lba/Len = %I64xh/%I64xh to be added.\n", Offset, Length);

#if DBG
    Ext2DbgPrint(D_EXT2, "Ext2AddMcbEntry: Number Runs in Mcb: %xh\n", FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) );
#endif


    return FsRtlAddLargeMcbEntry(&(Vcb->DirtyMcbs), Offset, Offset, Length);
}

VOID
Ext2RemoveMcbEntry (
    IN PEXT2_VCB Vcb,
    IN LONGLONG  Lba,
    IN LONGLONG  Length)
{

    FsRtlRemoveLargeMcbEntry(&(Vcb->DirtyMcbs), Lba, Length);
}

BOOLEAN
Ext2LookupMcbEntry (
    IN PEXT2_VCB    Vcb,
    IN LONGLONG     Offset,
    OUT PLONGLONG   Lba,
    OUT PLONGLONG   Length,
    OUT PLONGLONG   RunStart,
    OUT PLONGLONG   RunLength,
    OUT PULONG      Index)
{
    BOOLEAN     bReturn;

    bReturn = FsRtlLookupLargeMcbEntry(
                &(Vcb->DirtyMcbs), Offset, Lba, Length,
                RunStart, RunLength, Index );

    return bReturn;
}

⌨️ 快捷键说明

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