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

📄 read.c

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

Copyright (c) 1989-2000 Microsoft Corporation

Module Name:

    Read.c

Abstract:

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


--*/

#include "FatProcs.h"

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

#define BugCheckFileId                   (FAT_BUG_CHECK_READ)

//
//  The local debug trace level
//

#define Dbg                              (DEBUG_TRACE_READ)

//
//  Define stack overflow read threshhold.  For the x86 we'll use a smaller
//  threshold than for a risc platform.
//
//  Empirically, the limit is a result of the (large) amount of stack
//  neccesary to throw an exception.
//

#if defined(_M_IX86)
#define OVERFLOW_READ_THRESHHOLD         (0xE00)
#else
#define OVERFLOW_READ_THRESHHOLD         (0x1000)
#endif // defined(_M_IX86)


//
//  The following procedures handles read stack overflow operations.
//

VOID
FatStackOverflowRead (
    IN PVOID Context,
    IN PKEVENT Event
    );

NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
    );

VOID
FatOverflowPagingFileRead (
    IN PVOID Context,
    IN PKEVENT Event
    );

//
//  VOID
//  SafeZeroMemory (
//      IN PUCHAR At,
//      IN ULONG ByteCount
//      );
//

//
//  This macro just puts a nice little try-except around RtlZeroMemory
//

#define SafeZeroMemory(AT,BYTE_COUNT) {                            \
    try {                                                          \
        RtlZeroMemory((AT), (BYTE_COUNT));                         \
    } except(EXCEPTION_EXECUTE_HANDLER) {                          \
         FatRaiseStatus( IrpContext, STATUS_INVALID_USER_BUFFER ); \
    }                                                              \
}

//
//  Macro to increment appropriate performance counters.
//

#define CollectReadStats(VCB,OPEN_TYPE,BYTE_COUNT) {                                         \
    PFILESYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber()].Common; \
    if (((OPEN_TYPE) == UserFileOpen)) {                                                     \
        Stats->UserFileReads += 1;                                                           \
        Stats->UserFileReadBytes += (ULONG)(BYTE_COUNT);                                     \
    } else if (((OPEN_TYPE) == VirtualVolumeFile || ((OPEN_TYPE) == DirectoryFile))) {       \
        Stats->MetaDataReads += 1;                                                           \
        Stats->MetaDataReadBytes += (ULONG)(BYTE_COUNT);                                     \
    }                                                                                        \
}


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatStackOverflowRead)
#pragma alloc_text(PAGE, FatPostStackOverflowRead)
#pragma alloc_text(PAGE, FatCommonRead)
#endif


NTSTATUS
FatFsdRead (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the driver entry to the common read routine for NtReadFile calls.
    For synchronous requests, the CommonRead is called with Wait == TRUE,
    which means the request will always be completed in the current thread,
    and never passed to the Fsp.  If it is not a synchronous request,
    CommonRead is called with Wait == FALSE, which means the request
    will be passed to the Fsp only if there is a need to block.

Arguments:

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

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

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

    BOOLEAN TopLevel;

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

    //
    //  Call the common Read 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 );

            //
            //  If there is not enough stack to do this read, then post this
            //  read to the overflow queue.
            //

            if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

                KEVENT Event;
                PAGING_FILE_OVERFLOW_PACKET Packet;

                Packet.Irp = Irp;
                Packet.Fcb = Fcb;

                KeInitializeEvent( &Event, NotificationEvent, FALSE );

                FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead );

                //
                //  And wait for the worker thread to complete the item
                //

                (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

            } else {

                //
                //  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 ) );

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

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

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

        //
        //  Check if we have enough stack space to process this request.  If there
        //  isn't enough then we will pass the request off to the stack overflow thread.
        //

        if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

            DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 );
            try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) );
        }

        Status = FatCommonRead( IrpContext, Irp );

    try_exit: NOTHING;
    } 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() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

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

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}


//
//  Internal support routine
//

NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine posts a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Irp - Supplies the request to process.

    Fcb - Supplies the file.

Return Value:

    STATUS_PENDING.

--*/

{
    KEVENT Event;
    PERESOURCE Resource;
    PVCB Vcb;

    DebugTrace(0, Dbg, "Getting too close to stack limit pass request to Fsp\n", 0 );

    //
    //  Initialize an event and get shared on the resource we will
    //  be later using the common read.
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );

    //
    //  Preacquire the resource the read path will require so we know the
    //  worker thread can proceed without waiting.
    //
    
    if (FlagOn(Irp->Flags, IRP_PAGING_IO) && (Fcb->Header.PagingIoResource != NULL)) {

        Resource = Fcb->Header.PagingIoResource;

    } else {

        Resource = Fcb->Header.Resource;
    }
    
    //
    //  If there are no resources assodicated with the file (case: the virtual
    //  volume file), it is OK.  No resources will be acquired on the other side
    //  as well.
    //

    if (Resource) {
        
        ExAcquireResourceSharedLite( Resource, TRUE );
    }

    if (NodeType( Fcb ) == FAT_NTC_VCB) {

        Vcb = (PVCB) Fcb;
    
    } else {

        Vcb = Fcb->Vcb;
    }
    
    try {
        
        //
        //  Make the Irp just like a regular post request and
        //  then send the Irp to the special overflow thread.
        //  After the post we will wait for the stack overflow
        //  read routine to set the event that indicates we can
        //  now release the scb resource and return.
        //

        FatPrePostIrp( IrpContext, Irp );

        //
        //  If this read is the result of a verify, we have to
        //  tell the overflow read routne to temporarily
        //  hijack the Vcb->VerifyThread field so that reads
        //  can go through.
        //

        if (Vcb->VerifyThread == KeGetCurrentThread()) {

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ);
        }

        FsRtlPostStackOverflow( IrpContext, &Event, FatStackOverflowRead );

        //
        //  And wait for the worker thread to complete the item
        //

        KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

    } finally {

        if (Resource) {

            ExReleaseResourceLite( Resource );
        }
    }

    return STATUS_PENDING;
}


//
//  Internal support routine
//

VOID
FatStackOverflowRead (
    IN PVOID Context,
    IN PKEVENT Event
    )

/*++

Routine Description:

    This routine processes a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

⌨️ 快捷键说明

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