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

📄 write.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                    {
                        Status = Ext2QueueRequest(IrpContext);
                    }
                    else
                    {
                        IrpContext->Irp->IoStatus.Status = Status;
                        Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
                        Ext2FreeIrpContext(IrpContext);
                    }
                }
                else
                {
                    IrpContext->Irp->IoStatus.Status = Status;
                    
                    if (SynchronousIo && !PagingIo && NT_SUCCESS(Status))
                    {
                        FileObject->CurrentByteOffset.QuadPart =
                            ByteOffset.QuadPart + Irp->IoStatus.Information;
                    }
                    
                    if (!PagingIo && NT_SUCCESS(Status))
                    {
                        SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
                    }
                    
                    Ext2CompleteRequest(
                            IrpContext->Irp,
                            (CCHAR)
                            (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
                
                    Ext2FreeIrpContext(IrpContext);
                }
            }
            else
            {
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }

    return Status;
}

NTSTATUS
Ext2WriteInode (
            IN PEXT2_IRP_CONTEXT    IrpContext,
            IN PEXT2_VCB            Vcb,
            IN PEXT2_INODE          ext2_inode,
            IN ULONG                offset,
            IN PVOID                Buffer,
            IN ULONG                size,
            IN BOOLEAN              bWriteToDisk,
            OUT PULONG              dwReturn)
{
    PEXT2_BDL   ext2_bdl = NULL;
    ULONG       blocks, i;
    NTSTATUS    Status = STATUS_UNSUCCESSFUL;

    blocks = Ext2BuildBDL(IrpContext, Vcb, ext2_inode, offset, size, &ext2_bdl);

    if (blocks <= 0)
        return  Status;

#if DBG
    {
        ULONG   dwTotal = 0;
        Ext2DbgPrint(D_WRITE, "Ext2WriteInode: BDLCount = %xh Size=%xh Off=%xh\n", blocks, size, offset);
        for(i=0;i<blocks;i++)
        {
            Ext2DbgPrint(D_WRITE, "Ext2WriteInode: Lba=%I64xh Len=%xh Off=%xh\n", ext2_bdl[i].Lba, ext2_bdl[i].Length, ext2_bdl[i].Offset);
            dwTotal += ext2_bdl[i].Length;
        }

        if (dwTotal != size)
        {
            Ext2DbgBreakPoint();
        }
        Ext2DbgPrint(D_WRITE, "Ext2WriteInode: Total = %xh (WriteToDisk=%x)\n", dwTotal, bWriteToDisk);
    }
#endif
    
    if (bWriteToDisk)
    {

#if 0
        for(i=0; i<blocks; i++)
        {
            {
                CcFlushCache(   &(Vcb->SectionObject),
                                (PLARGE_INTEGER)&(ext2_bdl[i].Lba),
                                ext2_bdl[i].Length,
                                NULL);

                if (Vcb->SectionObject.DataSectionObject != NULL)
                {
                    ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
                    ExReleaseResource(&Vcb->PagingIoResource);
                           
   			        CcPurgeCacheSection( &(Vcb->SectionObject),
                                         (PLARGE_INTEGER)&(ext2_bdl[i].Lba),
								         ext2_bdl[i].Length,
                                         FALSE );
                }
            }
        }
#endif

        // assume offset is aligned.
        Status = Ext2ReadWriteBlocks(IrpContext, Vcb, ext2_bdl, size, blocks, FALSE);
    }
    else
    {
        for(i = 0; i < blocks; i++)
        {
            if(!Ext2SaveBuffer(IrpContext, Vcb, ext2_bdl[i].Lba, ext2_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ext2_bdl[i].Offset)))
                goto errorout;
        }

        Status = STATUS_SUCCESS;
    }

errorout:

    if (ext2_bdl)
        ExFreePool(ext2_bdl);

    return Status;
}

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

    PEXT2_VCB           Vcb;
    PEXT2_FCB           Fcb;
    PEXT2_CCB           Ccb;
    PFILE_OBJECT        FileObject;
    PFILE_OBJECT        CacheObject;

    PDEVICE_OBJECT      DeviceObject;

    PIRP                Irp;
    PIO_STACK_LOCATION  IoStackLocation;

    ULONG               Length;
    ULONG               ReturnedLength;
    LARGE_INTEGER       ByteOffset;

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

    BOOLEAN             bNeedExtending = FALSE;
    BOOLEAN             bAppendFile = 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;
        
        Fcb = (PEXT2_FCB) FileObject->FsContext;
        
        ASSERT(Fcb);
    
        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
            (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        Ccb = (PEXT2_CCB) FileObject->FsContext2;

        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, "Ext2WriteFile: 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 (IsEndOfFile(ByteOffset))
        {
            bAppendFile = TRUE;
            ByteOffset.QuadPart = Fcb->CommonFCBHeader.FileSize.QuadPart;
        }

        if ( FlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
        {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

		//
		//	Do flushing for such cases
		//
		if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) 
		{
            ExAcquireResourceExclusive(&Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
            MainResourceAcquired = TRUE;

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

			CcFlushCache( &(Fcb->SectionObject),
                          &ByteOffset,
                          Length,
                          &(Irp->IoStatus));
            ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

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

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

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

            ExReleaseResource(&Fcb->MainResource);
            MainResourceAcquired = FALSE;
		}
        
        if (!PagingIo)
        {
            if (!ExAcquireResourceSharedLite(
                &Fcb->MainResource,
                IrpContext->IsSynchronous ))
            {
                Status = STATUS_PENDING;
                __leave;
            }
            
            MainResourceAcquired = TRUE;
        }
        else
        {
            if (!ExAcquireResourceSharedLite(
                &Fcb->PagingIoResource,
                IrpContext->IsSynchronous ))
            {
                Status = STATUS_PENDING;
                __leave;
            }
            
            PagingIoResourceAcquired = TRUE;
        }
        
        if (!PagingIo)
        {
            if (!FsRtlCheckLockForWriteAccess(
                &Fcb->FileLockAnchor,
                Irp         ))
            {
                Status = STATUS_FILE_LOCK_CONFLICT;
                __leave;
            }
        }

        if (Nocache)
        {
            if (ByteOffset.QuadPart + Length > Fcb->CommonFCBHeader.AllocationSize.QuadPart)
            {
                if (ByteOffset.QuadPart >= Fcb->CommonFCBHeader.AllocationSize.QuadPart)
                {
                    Status = STATUS_SUCCESS;
                    Irp->IoStatus.Information = 0;
                    __leave;
                }
                else
                {
                    if (Length > (ULONG)(Fcb->CommonFCBHeader.AllocationSize.QuadPart - ByteOffset.QuadPart))
                        Length = (ULONG)(Fcb->CommonFCBHeader.AllocationSize.QuadPart - ByteOffset.QuadPart);
                }
            }
        }

        if (!Nocache)
        {
            if (FlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
            {
                __leave;
            }

            {
                if (FileObject->PrivateCacheMap == NULL)
                {
                    CcInitializeCacheMap(
                        FileObject,
                        (PCC_FILE_SIZES)(&Fcb->CommonFCBHeader.AllocationSize),
                        FALSE,
                        &gExt2Global->CacheManagerCallbacks,
                        Fcb );

                    CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY);
                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->CommonFCBHeader.AllocationSize)));
                }

                CacheObject = FileObject;
            }

            //
            //  Need extending the size of inode ?
            //
            if (bAppendFile || ((ULONG)(ByteOffset.QuadPart + Length) >
                (ULONG)(Fcb->CommonFCBHeader.FileSize.QuadPart)))
            {

                LARGE_INTEGER   ExtendSize;
                LARGE_INTEGER   FileSize;

                bNeedExtending = TRUE;
                FileSize = Fcb->CommonFCBHeader.FileSize;
                ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);

                if (ExtendSize.QuadPart > Fcb->CommonFCBHeader.AllocationSize.QuadPart)
                {
                    if (!Ext2ExpandFileAllocation(IrpContext, Vcb, Fcb, &ExtendSize))
                    {
                        Status = STATUS_INSUFFICIENT_RESOURCES;
                        __leave;
                    }
                }

                {
                    Fcb->CommonFCBHeader.FileSize.QuadPart = ExtendSize.QuadPart;
                    Fcb->ext2_inode->i_size = (ULONG) ExtendSize.QuadPart;
                }

                if (FileObject->PrivateCacheMap)
                {
                    CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->CommonFCBHeader.AllocationSize)));

                    if (ByteOffset.QuadPart > FileSize.QuadPart)
                    {
                        Ext2ZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, ByteOffset.QuadPart - FileSize.QuadPart);
                    }

                    if (Fcb->CommonFCBHeader.AllocationSize.QuadPart > ExtendSize.QuadPart)
                    {
                        Ext2ZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, Fcb->CommonFCBHeader.AllocationSize.QuadPart - ExtendSize.QuadPart);
                    }
                }

                if (Ext2SaveInode(IrpContext, Vcb, Fcb->Ext2Mcb->Inode, Fcb->ext2_inode))
                    Status = STATUS_SUCCESS;
            }


            if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
            {
                CcPrepareMdlWrite(
                    CacheObject,
                    (&ByteOffset),
                    Length,
                    &Irp->MdlAddress,
                    &Irp->IoStatus );
                
                Status = Irp->IoStatus.Status;
            }
            else
            {
                Buffer = Ext2GetUserBuffer(Irp);
                
                if (Buffer == NULL)
                {
                    Status = STATUS_INVALID_USER_BUFFER;
                    __leave;
                }
                
                if (!CcCopyWrite(
                    CacheObject,
                    (PLARGE_INTEGER)&ByteOffset,
                    Length,
                    IrpContext->IsSynchronous,
                    Buffer  ))
                {
                    Status = STATUS_PENDING;
                    __leave;
                }
                
                Status = Irp->IoStatus.Status;
            }

            if (NT_SUCCESS(Status))
                Irp->IoStatus.Information = Length;

        }
        else
        {
            ReturnedLength = Length;

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

⌨️ 快捷键说明

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