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

📄 write.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) 1989-2000 Microsoft Corporation

Module Name:

    Write.c

Abstract:

    This module implements the File Write routine for Write called by the
    dispatch driver.


--*/

#include "FatProcs.h"

//
//  The Bug check file id for this module
//

#define BugCheckFileId                   (FAT_BUG_CHECK_WRITE)

//
//  The local debug trace level
//

#define Dbg                              (DEBUG_TRACE_WRITE)

//
//  Macros to increment the appropriate performance counters.
//

#define CollectWriteStats(VCB,OPEN_TYPE,BYTE_COUNT) {                                        \
    PFILESYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber()].Common; \
    if (((OPEN_TYPE) == UserFileOpen)) {                                                     \
        Stats->UserFileWrites += 1;                                                          \
        Stats->UserFileWriteBytes += (ULONG)(BYTE_COUNT);                                    \
    } else if (((OPEN_TYPE) == VirtualVolumeFile || ((OPEN_TYPE) == DirectoryFile))) {       \
        Stats->MetaDataWrites += 1;                                                          \
        Stats->MetaDataWriteBytes += (ULONG)(BYTE_COUNT);                                    \
    }                                                                                        \
}

BOOLEAN FatNoAsync = FALSE;

//
//  Local support routines
//

VOID
FatDeferredFlushDpc (
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    );

VOID
FatDeferredFlush (
    PVOID Parameter
    );

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatDeferredFlush)
#pragma alloc_text(PAGE, FatCommonWrite)
#endif


NTSTATUS
FatFsdWrite (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine implements the FSD part of the NtWriteFile API call

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Write exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    PFCB Fcb;
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN ModWriter = FALSE;
    BOOLEAN TopLevel;

    DebugTrace(+1, Dbg, "FatFsdWrite\n", 0);

    //
    //  Call the common Write routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    //
    //  We are first going to do a quick check for paging file IO.  Since this
    //  is a fast path, we must replicate the check for the fsdo.
    //

    if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject))  {

        Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

        if ((NodeType(Fcb) == FAT_NTC_FCB) &&
            FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) {

            //
            //  Do the usual STATUS_PENDING things.
            //

            IoMarkIrpPending( Irp );

            //
            //  Perform the actual IO, it will be completed when the io finishes.
            //

            FatPagingFileIo( Irp, Fcb );

            FsRtlExitFileSystem();

            return STATUS_PENDING;
        }
    }

    try {

        TopLevel = FatIsIrpTopLevel( Irp );

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        //
        //  This is a kludge for the mod writer case.  The correct state
        //  of recursion is set in IrpContext, however, we much with the
        //  actual top level Irp field to get the correct WriteThrough
        //  behaviour.
        //

        if (IoGetTopLevelIrp() == (PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP) {

            ModWriter = TRUE;

            IoSetTopLevelIrp( Irp );
        }

        //
        //  If this is an Mdl complete request, don't go through
        //  common write.
        //

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

            DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 );
            Status = FatCompleteMdl( IrpContext, Irp );

        } else {

            Status = FatCommonWrite( IrpContext, Irp );
        }

    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

//  ASSERT( !(ModWriter && (Status == STATUS_CANT_WAIT)) );

    ASSERT( !(ModWriter && TopLevel) );

    if (ModWriter) { IoSetTopLevelIrp((PIRP)FSRTL_MOD_WRITE_TOP_LEVEL_IRP); }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdWrite -> %08lx\n", Status);

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}


NTSTATUS
FatCommonWrite (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common write routine for NtWriteFile, called from both
    the Fsd, or from the Fsp if a request could not be completed without
    blocking in the Fsd.  This routine's actions are
    conditionalized by the Wait input parameter, which determines whether
    it is allowed to block or not.  If a blocking condition is encountered
    with Wait == FALSE, however, the request is posted to the Fsp, who
    always calls with WAIT == TRUE.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PVCB Vcb;
    PFCB FcbOrDcb;
    PCCB Ccb;

    VBO StartingVbo;
    ULONG ByteCount;
    ULONG FileSize;
    ULONG InitialFileSize;
    ULONG InitialValidDataLength;

    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;
    TYPE_OF_OPEN TypeOfOpen;

    BOOLEAN PostIrp = FALSE;
    BOOLEAN OplockPostIrp = FALSE;
    BOOLEAN ExtendingFile = FALSE;
    BOOLEAN FcbOrDcbAcquired = FALSE;
    BOOLEAN SwitchBackToAsync = FALSE;
    BOOLEAN CalledByLazyWriter = FALSE;
    BOOLEAN ExtendingValidData = FALSE;
    BOOLEAN FcbAcquiredExclusive = FALSE;
    BOOLEAN FcbCanDemoteToShared = FALSE;
    BOOLEAN WriteFileSizeToDirent = FALSE;
    BOOLEAN RecursiveWriteThrough = FALSE;
    BOOLEAN UnwindOutstandingAsync = FALSE;
    BOOLEAN PagingIoResourceAcquired = FALSE;

    BOOLEAN SynchronousIo;
    BOOLEAN WriteToEof;
    BOOLEAN PagingIo;
    BOOLEAN NonCachedIo;
    BOOLEAN Wait;
    NTSTATUS Status;

    FAT_IO_CONTEXT StackFatIoContext;

    //
    // A system buffer is only used if we have to access the buffer directly
    // from the Fsp to clear a portion or to do a synchronous I/O, or a
    // cached transfer.  It is possible that our caller may have already
    // mapped a system buffer, in which case we must remember this so
    // we do not unmap it on the way out.
    //

    PVOID SystemBuffer = (PVOID) NULL;

    LARGE_INTEGER StartingByte;

    //
    // Get current Irp stack location and file object
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    FileObject = IrpSp->FileObject;


    DebugTrace(+1, Dbg, "FatCommonWrite\n", 0);
    DebugTrace( 0, Dbg, "Irp                 = %8lx\n", Irp);
    DebugTrace( 0, Dbg, "ByteCount           = %8lx\n", IrpSp->Parameters.Write.Length);
    DebugTrace( 0, Dbg, "ByteOffset.LowPart  = %8lx\n", IrpSp->Parameters.Write.ByteOffset.LowPart);
    DebugTrace( 0, Dbg, "ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Write.ByteOffset.HighPart);

    //
    // Initialize the appropriate local variables.
    //

    Wait          = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    PagingIo      = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
    NonCachedIo   = BooleanFlagOn(Irp->Flags,IRP_NOCACHE);
    SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

    //ASSERT( PagingIo || FileObject->WriteAccess );

    //
    //  Extract the bytecount and do our noop/throttle checking.
    //

    ByteCount = IrpSp->Parameters.Write.Length;

    //
    //  If there is nothing to write, return immediately.
    //

    if (ByteCount == 0) {

        Irp->IoStatus.Information = 0;
        FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    //  See if we have to defer the write.
    //

    if (!NonCachedIo &&
        !CcCanIWrite(FileObject,
                     ByteCount,
                     (BOOLEAN)(Wait && !BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_IN_FSP)),
                     BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE))) {

        BOOLEAN Retrying = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE);

        FatPrePostIrp( IrpContext, Irp );

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED_WRITE );

        CcDeferWrite( FileObject,
                      (PCC_POST_DEFERRED_WRITE)FatAddToWorkque,
                      IrpContext,
                      Irp,
                      ByteCount,
                      Retrying );

        return STATUS_PENDING;
    }

    //
    //  Determine our starting position and type.  If we are writing
    //  at EOF, then we will need additional synchronization before
    //  the IO is issued to determine where the data will go.
    //

    StartingByte = IrpSp->Parameters.Write.ByteOffset;
    StartingVbo = StartingByte.LowPart;

    WriteToEof = ( (StartingByte.LowPart == FILE_WRITE_TO_END_OF_FILE) &&
                   (StartingByte.HighPart == -1) );

    //
    //  Extract the nature of the write from the file object, and case on it
    //

    TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &FcbOrDcb, &Ccb);

⌨️ 快捷键说明

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