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

📄 create.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:        See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
 * FILE:             create.c
 * PROGRAMMER:       Matt Wu <mattwu@163.com>
 * HOMEPAGE:         http://ext2.yeah.net
 * UPDATE HISTORY: 
 */

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

#include "ntifs.h"
#include "ext2fs.h"

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

extern PEXT2_GLOBAL gExt2Global;

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

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2LookupFileName)
#pragma alloc_text(PAGE, Ext2SearchFcbList)
#pragma alloc_text(PAGE, Ext2ScanDir)
#pragma alloc_text(PAGE, Ext2CreateFile)
#pragma alloc_text(PAGE, Ext2CreateVolume)
#pragma alloc_text(PAGE, Ext2Create)
#pragma alloc_text(PAGE, Ext2CreateInode)
#endif

NTSTATUS
Ext2LookupFileName (IN PEXT2_VCB    Vcb,
            IN PUNICODE_STRING      FullFileName,
            IN PEXT2_FCB            ParentFcb,
            OUT PEXT2_MCB *         Ext2Mcb,
            IN OUT PEXT2_INODE      ext2_inode)
{
    NTSTATUS        Status;
    UNICODE_STRING  FileName;
    PEXT2_MCB       ParentMcb;
    PEXT2_MCB       Mcb;

    EXT2_DIR_ENTRY2 ext2_dir;
    int             i = 0;
    BOOLEAN         bRun = TRUE;
    BOOLEAN         bParent = FALSE;
    EXT2_INODE      in;
    ULONG           off = 0;

    Status = STATUS_OBJECT_NAME_NOT_FOUND;

    *Ext2Mcb = NULL;

    if (ParentFcb && FullFileName->Buffer[0] != L'\\')
    {
        ParentMcb = ParentFcb->Ext2Mcb;
        bParent = TRUE;
    }
    else
    {
        ParentMcb = Vcb->Ext2McbTree;
    }

    RtlZeroMemory(&ext2_dir, sizeof(EXT2_DIR_ENTRY2));

    if (FullFileName->Length == 0)
    {
        return Status;
    }

    if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
    {
        if (!Ext2LoadInode(Vcb, ParentMcb->Inode, ext2_inode))
        {
            return Status;      
        }

        *Ext2Mcb = Vcb->Ext2McbTree;

        return STATUS_SUCCESS;
    }

    while (bRun && i < FullFileName->Length/2)
    {
        int Length;
        ULONG FileAttr = FILE_ATTRIBUTE_NORMAL;

        if (bParent)
        {
            bParent = FALSE;
        }
        else
        {
            while(i < FullFileName->Length/2 && FullFileName->Buffer[i] == L'\\') i++;
        }

        Length = i;

        while(i < FullFileName->Length/2 && (FullFileName->Buffer[i] != L'\\')) i++;

        if (i - Length >0)
        {
            FileName = *FullFileName;
            FileName.Buffer += Length;
            FileName.Length = (USHORT)((i - Length) * 2);

            Mcb = Ext2SearchMcb(ParentMcb, &FileName);

            if (Mcb)
            {
                ParentMcb = Mcb;

                Status = STATUS_SUCCESS;

                if (!IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
                {
                    if (i < FullFileName->Length/2)
                    {
                        Status =  STATUS_OBJECT_NAME_NOT_FOUND;
                    }
                    break;
                }
            }
            else
            {
                if (!Ext2LoadInode(Vcb, ParentMcb->Inode, &in))
                {
                    Status = STATUS_OBJECT_NAME_NOT_FOUND;
                    break;
                }

                if (!S_ISDIR(in.i_mode))
                {
                    if (i < FullFileName->Length/2)
                    {
                        Status =  STATUS_OBJECT_NAME_NOT_FOUND;
                    }
                    break;
                }

                Status = Ext2ScanDir (
                    Vcb,
                    ParentMcb,
                    &FileName,
                    &off,
                    &in,
                    &ext2_dir);

                if (!NT_SUCCESS(Status))
                {
                    bRun = FALSE;
/*
                    if (i >= FullFileName->Length/2)
                    {
                        *Ext2Mcb = ParentMcb;
                    }
*/
                }
                else
                {
                    if (IsFlagOn(Vcb->ext2_super_block->s_feature_incompat, EXT2_FEATURE_INCOMPAT_FILETYPE))
                    {
                        if (ext2_dir.file_type == EXT2_FT_DIR)
                            SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
                    }
                    else
                    {
                        if (!Ext2LoadInode(Vcb, ext2_dir.inode, &in))
                        {
                            Status = STATUS_OBJECT_NAME_NOT_FOUND;
                            break;
                        }

                        if (S_ISDIR(in.i_mode))
                        {
                            SetFlag(FileAttr, FILE_ATTRIBUTE_DIRECTORY);
                        }
                    }

					Mcb = Ext2AllocateMcb(Vcb, &FileName, FileAttr);

					if (!Mcb)
					{
						Status = STATUS_OBJECT_NAME_NOT_FOUND;
						break;
					}

                    Mcb->Inode = ext2_dir.inode;
                    Mcb->DeOffset = off;
                    Ext2AddMcbNode(ParentMcb, Mcb);
                    ParentMcb = Mcb;
                }

            }
        }
        else
        {
            break;
        }
    }

    if (NT_SUCCESS(Status))
    {
        *Ext2Mcb = Mcb;
        if (ext2_inode)
        {
            if (!Ext2LoadInode(Vcb, Mcb->Inode, ext2_inode))
            {
                Ext2DbgPrint(D_CREATE, "Ext2LoopupFileName: error loading Inode %xh\n", Mcb->Inode);
                Status = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
    }

    return Status;
}


NTSTATUS
Ext2ScanDir (IN PEXT2_VCB       Vcb,
         IN PEXT2_MCB           ParentMcb,
         IN PUNICODE_STRING     FileName,
         IN OUT PULONG          Index,
         IN PEXT2_INODE         ext2_inode,
         IN OUT PEXT2_DIR_ENTRY2 ext2_dir)
{
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
    USHORT                  InodeFileNameLength;
    UNICODE_STRING          InodeFileName;

    PEXT2_DIR_ENTRY2        pDir = NULL;
    ULONG                   dwBytes = 0;
    BOOLEAN                 bFound = FALSE;
    PEXT2_FCB               Dcb = NULL;
    LONGLONG                Offset = 0;
    ULONG                   inode = ParentMcb->Inode;

    ULONG                   dwRet;

    __try
    {

        pDir = (PEXT2_DIR_ENTRY2) ExAllocatePool(PagedPool,
                                    sizeof(EXT2_DIR_ENTRY2));
        if (!pDir)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        InodeFileName.Buffer = ExAllocatePool(
                    PagedPool,
                    (EXT2_NAME_LEN + 1) * 2 );

        if (!InodeFileName.Buffer)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }


        Dcb = ParentMcb->Ext2Fcb;

        dwBytes = 0;

        while (!bFound && dwBytes < ext2_inode->i_size)
        {
            RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2));

            // Reading the DCB contents
            Status = Ext2ReadInode(
                        NULL,
                        Vcb,
                        ext2_inode,
                        dwBytes,
                        (PVOID)pDir,
                        sizeof(EXT2_DIR_ENTRY2),
                        &dwRet);


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

            if (pDir->inode)
            {
                InodeFileNameLength = pDir->name_len & 0xff;
                
                InodeFileName.Length = InodeFileName.MaximumLength =
                    InodeFileNameLength * 2;

                RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
                
                Ext2CharToWchar(
                    InodeFileName.Buffer,
                    pDir->name,
                    InodeFileNameLength );

                if (!RtlCompareUnicodeString(
                    FileName,
                    &InodeFileName,
                    TRUE ))
                {
                    bFound = TRUE;
                    *Index = dwBytes;
                    RtlCopyMemory(ext2_dir, pDir, pDir->rec_len > sizeof(EXT2_DIR_ENTRY2)
                        ? sizeof(EXT2_DIR_ENTRY2) : pDir->rec_len);
                    Status = STATUS_SUCCESS;
                    Ext2DbgPrint(D_CREATE, "Ext2ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->inode);
                }
                
                dwBytes +=pDir->rec_len;
                Offset = (LONGLONG)dwBytes;
            }
            else
            {
                break;
            }
        }

        if (!bFound)
            Status = STATUS_NO_SUCH_FILE;
    }

    __finally
    {
        if (InodeFileName.Buffer != NULL)
        {
            ExFreePool(InodeFileName.Buffer);
        }

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

/*

PEXT2_FCB
Ext2SearchFcbList(	IN PEXT2_VCB    Vcb,
				    IN ULONG        inode )
{
	BOOLEAN				bFound = FALSE;
	PLIST_ENTRY         Link;
	PEXT2_FCB           TmpFcb;

	Link = Vcb->FcbList.Flink;
	
	while (!bFound && Link != &Vcb->FcbList)
	{
		TmpFcb = CONTAINING_RECORD(Link, EXT2_FCB, Next);
		
		if (TmpFcb && TmpFcb->Identifier.Type == FCB)
		{
#if DBG
			Ext2DbgPrint(D_CREATE, "Ext2SearchFcbList: [%s,%xh]\n", 
                TmpFcb->AnsiFileName.Buffer, TmpFcb->Inode);
#endif			
			if (TmpFcb->Inode == inode)
			{
				Ext2DbgPrint(D_CREATE, "Ext2SearchMcb: Found FCB for %xh.\n", inode);
				bFound = TRUE;
			}
		}
		Link = Link->Flink;
	}

	if (bFound)
		return TmpFcb;
	else
		return NULL;
	
}
*/

NTSTATUS
Ext2CreateFile(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION  io_stack;
    PEXT2_FCB           Fcb = NULL;
    PEXT2_FCB           pParentFcb = NULL;
    BOOLEAN             bParentFcbCreated = FALSE;
    PEXT2_CCB           Ccb = NULL;
    PEXT2_INODE         ext2_inode;
    BOOLEAN             VcbResourceAcquired = FALSE;
    BOOLEAN             bDir = FALSE;
    BOOLEAN             bFcbAllocated = FALSE;
    BOOLEAN             bCreated = FALSE;
    UNICODE_STRING      FileName;
    PEXT2_MCB           Ext2Mcb = NULL;
    PIRP                Irp;

    ULONG               Options;
    ULONG               CreateDisposition;

    BOOLEAN             OpenDirectory;
    BOOLEAN             OpenTargetDirectory;
    BOOLEAN             CreateDirectory;
    BOOLEAN             SequentialOnly;
    BOOLEAN             NoIntermediateBuffering;
    BOOLEAN             IsPagingFile;
    BOOLEAN             DirectoryFile;
    BOOLEAN             NonDirectoryFile;
    BOOLEAN             NoEaKnowledge;
    BOOLEAN             DeleteOnClose;
    BOOLEAN             TemporaryFile;
    BOOLEAN             CaseSensitive;

    ACCESS_MASK         DesiredAccess;
    ULONG               ShareAccess;


    Irp = IrpContext->Irp;
    io_stack = IoGetCurrentIrpStackLocation(Irp);

    Options  = io_stack->Parameters.Create.Options;
    
    DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
    OpenTargetDirectory = IsFlagOn(io_stack->Flags, SL_OPEN_TARGET_DIRECTORY);

    NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
    SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
    NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
    NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
    DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);

    CaseSensitive = IsFlagOn(io_stack->Flags, SL_CASE_SENSITIVE);

    TemporaryFile = IsFlagOn(io_stack->Parameters.Create.FileAttributes,
                                   FILE_ATTRIBUTE_TEMPORARY );

    CreateDisposition = (Options >> 24) & 0x000000ff;

⌨️ 快捷键说明

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