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

📄 write.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:        See COPYRIGHT.TXT
 * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
 * FILE:             write.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 *************************************************************/

NTSTATUS
Ext2WriteComplete (IN PEXT2_IRP_CONTEXT IrpContext);

NTSTATUS
Ext2WriteFile (IN PEXT2_IRP_CONTEXT IrpContext);

NTSTATUS
Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext);

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2ZeroHoles)

#pragma alloc_text(PAGE, Ext2Write)

#pragma alloc_text(PAGE, Ext2WriteVolume)
#pragma alloc_text(PAGE, Ext2WriteInode)
#pragma alloc_text(PAGE, Ext2WriteFile)
#pragma alloc_text(PAGE, Ext2WriteComplete)

#pragma alloc_text(PAGE, Ext2SupersedeOrOverWriteFile)
#pragma alloc_text(PAGE, Ext2IsDirectoryEmpty)
#pragma alloc_text(PAGE, Ext2DeleteFile)
#endif

/* FUNCTIONS *************************************************************/

BOOLEAN
Ext2ZeroHoles (
    IN PEXT2_IRP_CONTEXT IrpContext,
    IN PEXT2_VCB Vcb,
    IN PFILE_OBJECT FileObject,
    IN LONGLONG Offset,
    IN LONGLONG Count
    )
{
    LARGE_INTEGER StartAddr = {0,0};
    LARGE_INTEGER EndAddr = {0,0};

    StartAddr.QuadPart = (Offset + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);

    EndAddr.QuadPart = (Offset + Count + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);

    if (StartAddr.QuadPart < EndAddr.QuadPart)
    {
        return CcZeroData( FileObject,
                       &StartAddr,
                       &EndAddr,
                       IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
    }

    return TRUE;
}


NTSTATUS
Ext2WriteVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;

    PEXT2_VCB           Vcb;
    PEXT2_FCBVCB        FcbOrVcb;
    PFILE_OBJECT        FileObject;

    PDEVICE_OBJECT      DeviceObject;

    PIRP                Irp;
    PIO_STACK_LOCATION  IoStackLocation;

    ULONG               Length;
    LARGE_INTEGER       ByteOffset;

    BOOLEAN             PagingIo;
    BOOLEAN             Nocache;
    BOOLEAN             SynchronousIo;
    BOOLEAN             MainResourceAcquired = FALSE;
    BOOLEAN             PagingIoResourceAcquired = FALSE;

    PUCHAR              Buffer;

    __try
    {
        ASSERT(IrpContext);
        
        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
            (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
        
        DeviceObject = IrpContext->DeviceObject;
    
        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
        
        ASSERT(Vcb != NULL);
        
        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
            (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
        
        FileObject = IrpContext->FileObject;

        FcbOrVcb = (PEXT2_FCBVCB) FileObject->FsContext;
        
        ASSERT(FcbOrVcb);
        
        if (!(FcbOrVcb->Identifier.Type == EXT2VCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
        {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Irp = IrpContext->Irp;
            
        IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
            
        Length = IoStackLocation->Parameters.Write.Length;
        ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
            
        PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
        Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
        SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

        Ext2DbgPrint(D_WRITE, "Ext2WriteVolume: Len=%xh Off=%I64x Paging=%xh Nocache=%xh\n", Length, ByteOffset.QuadPart, PagingIo, Nocache);

        if (Length == 0)
        {
            Irp->IoStatus.Information = 0;
            Status = STATUS_SUCCESS;
            __leave;
        }
      
        if (Nocache &&
           (ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
            Length & (SECTOR_SIZE - 1)))
        {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
        {
            ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
            Status = STATUS_PENDING;
            __leave;
        }
        
        if (ByteOffset.QuadPart >=
            Vcb->PartitionInformation.PartitionLength.QuadPart  )
        {
            Irp->IoStatus.Information = 0;
            Status = STATUS_END_OF_FILE;
            __leave;
        }

		if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
		{

            ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
            MainResourceAcquired = TRUE;

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResource(&Vcb->PagingIoResource);

			CcFlushCache( &(Vcb->SectionObject),
                          &ByteOffset,
                          Length,
                          &(Irp->IoStatus));

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
                Status = Irp->IoStatus.Status;
				__leave;
			}

            ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
            ExReleaseResource(&Vcb->PagingIoResource);

			CcPurgeCacheSection( &(Vcb->SectionObject),
                                 (PLARGE_INTEGER)&(ByteOffset),
								 Length,
                                 FALSE );

            ExReleaseResource(&Vcb->MainResource);
            MainResourceAcquired = FALSE;
		}

        if (!PagingIo)
        {
            if (!ExAcquireResourceSharedLite(
                &Vcb->MainResource,
                IrpContext->IsSynchronous ))
            {
                Status = STATUS_PENDING;
                __leave;
            }
            
            MainResourceAcquired = TRUE;
        }
        else
        {
            if (!ExAcquireResourceSharedLite(
                &Vcb->PagingIoResource,
                IrpContext->IsSynchronous ))
            {
                Status = STATUS_PENDING;
                __leave;
            }
            
            PagingIoResourceAcquired = TRUE;
        }
        
        if (!Nocache)
        {
            if ((ByteOffset.QuadPart + Length) >
                    Vcb->PartitionInformation.PartitionLength.QuadPart
            )
            {
                Length = (ULONG) (
                    Vcb->PartitionInformation.PartitionLength.QuadPart -
                    ByteOffset.QuadPart);
                Length &= ~(SECTOR_SIZE - 1);
            }

            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
            {

                CcPrepareMdlWrite (
                    Vcb->StreamObj,
                    &ByteOffset,
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );
                
                Status = Irp->IoStatus.Status;
            }
            else
            {
                PBCB    Bcb;
                PVOID   Buf;

                Buffer = Ext2GetUserBuffer(Irp);
                    
                if (Buffer == NULL)
                {
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }

				CcPreparePinWrite( 
					Vcb->StreamObj,
					&ByteOffset,
					Length,
					FALSE,
					TRUE,
					&Bcb,
					&Buf );

                RtlCopyMemory(Buf, Buffer, Length);

                CcUnpinData(Bcb);

                Status = STATUS_SUCCESS;
            }

            if (NT_SUCCESS(Status))
                Irp->IoStatus.Information = Length;
        }
        else
        {
            PEXT2_BDL           ext2_bdl = NULL;
            ULONG               Blocks = 0;

            LONGLONG            DirtyStart;
            LONGLONG            DirtyLba;
            LONGLONG            DirtyLength;
            LONGLONG            RemainLength;

            if ((ByteOffset.QuadPart + Length) >
                    Vcb->PartitionInformation.PartitionLength.QuadPart )
            {
                Length = (ULONG) (
                    Vcb->PartitionInformation.PartitionLength.QuadPart -
                    ByteOffset.QuadPart);

                Length &= ~(SECTOR_SIZE - 1);
            }

            Status = Ext2LockUserBuffer(
                IrpContext->Irp,
                Length,
                IoReadAccess );
                
            if (!NT_SUCCESS(Status))
            {
                __leave;
            }

            ext2_bdl = ExAllocatePool(PagedPool, (Length / Vcb->ext2_block) * sizeof(EXT2_BDL));

            if (!ext2_bdl)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            DirtyLba = ByteOffset.QuadPart;
            RemainLength = (LONGLONG) Length;

            while (RemainLength > 0)
            {
                DirtyStart = DirtyLba;

                if (Ext2LookupMcbEntry(Vcb, DirtyStart, &DirtyLba, &DirtyLength,
                                        (PLONGLONG)NULL, (PLONGLONG)NULL, (PULONG)NULL))
                {

                    if (DirtyLba == -1)
                    {
                        DirtyLba = DirtyStart + DirtyLength;

                        RemainLength = ByteOffset.QuadPart + (LONGLONG)Length - DirtyLba;
                        continue;
                    }
            
                    ext2_bdl[Blocks].Irp = NULL;
                    ext2_bdl[Blocks].Lba = DirtyLba;
                    ext2_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length - RemainLength - (DirtyLba - DirtyStart));

                    if (DirtyLba + DirtyLength > DirtyStart + RemainLength)
                    {
                        ext2_bdl[Blocks].Length = (ULONG)(DirtyStart + RemainLength - DirtyLba);
                        RemainLength = 0;
                    }
                    else
                    {
                        ext2_bdl[Blocks].Length = (ULONG)DirtyLength;
                        RemainLength = (DirtyStart + RemainLength) - (DirtyLba + DirtyLength);
                    }

                    DirtyLba = DirtyStart + DirtyLength;
                    Blocks++;
                }
                else
                {
                    if (Blocks == 0)
                    {
                        if (ext2_bdl)
                            ExFreePool(ext2_bdl);

                        // Lookup fails at the first time, ie. no dirty blocks in the run
                        if (RemainLength == (LONGLONG)Length)
                            Status = STATUS_SUCCESS;
                        else
                            Status = STATUS_UNSUCCESSFUL;

                        __leave;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (Blocks > 0)
            {
                Status = Ext2ReadWriteBlocks(IrpContext,
                                    Vcb,
                                    ext2_bdl,
                                    Length,
                                    Blocks,
                                    FALSE   );
                Irp = IrpContext->Irp;

                if (NT_SUCCESS(Status))
                {
                    ULONG   i;

                    for (i=0; i<Blocks;i++)
                        Ext2RemoveMcbEntry(Vcb, ext2_bdl[i].Lba, ext2_bdl[i].Length);
                }

                if (ext2_bdl)
                    ExFreePool(ext2_bdl);

                if (!Irp)
                    __leave;

            }
            else
            {
                if (ext2_bdl)
                    ExFreePool(ext2_bdl);

                Status = STATUS_SUCCESS;
                __leave;
            }
        }
    }

    __finally
    {
        if (PagingIoResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Vcb->PagingIoResource,
                ExGetCurrentResourceThread());
        }
        
        if (MainResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Vcb->MainResource,
                ExGetCurrentResourceThread());
        }

        if (!IrpContext->ExceptionInProgress)
        {
            if (Irp)
            {
                if (Status == STATUS_PENDING)
                {
                    Status = Ext2LockUserBuffer(
                        IrpContext->Irp,
                        Length,
                        IoReadAccess );
                    
                    if (NT_SUCCESS(Status))

⌨️ 快捷键说明

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