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

📄 read.c

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

            IrpContext->FatIoContext = NULL;

            FatDeleteIrpContext( IrpContext );

            DebugTrace(-1, Dbg, "FatNonCachedIo -> STATUS_PENDING\n", 0);

            return STATUS_PENDING;
        }

        FatWaitSync( IrpContext );

        //
        //  If the call didn't succeed, raise the error status
        //

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

            ASSERT( KeGetCurrentThread() != Vcb->VerifyThread || Status != STATUS_VERIFY_REQUIRED );
            FatNormalizeAndRaiseStatus( IrpContext, Status );
        }

        //
        //  Update the current file position
        //

        if (SynchronousIo && !PagingIo) {
            FileObject->CurrentByteOffset.QuadPart =
                StartingLbo + Irp->IoStatus.Information;
        }

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

        FatCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  At this point we know there is an Fcb/Dcb.
    //

    ASSERT( FcbOrDcb != NULL );

    //
    //  Check for a non-zero high part offset
    //

    if ( StartingByte.HighPart != 0 ) {

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

    //
    //  Use a try-finally to free Fcb/Dcb and buffers on the way out.
    //

    try {

        //
        // This case corresponds to a normal user read file.
        //

        if ( TypeOfOpen == UserFileOpen) {

            ULONG FileSize;
            ULONG ValidDataLength;

            DebugTrace(0, Dbg, "Type of read is user file open\n", 0);

            //
            //  If this is a noncached transfer and is not a paging I/O, and
            //  the file has a data section, then we will do a flush here
            //  to avoid stale data problems.  Note that we must flush before
            //  acquiring the Fcb shared since the write may try to acquire
            //  it exclusive.
            //

            if (!PagingIo && NonCachedIo

                    &&

                (FileObject->SectionObjectPointer->DataSectionObject != NULL)) {

#ifndef REDUCE_SYNCHRONIZATION
                if (!FatAcquireExclusiveFcb( IrpContext, FcbOrDcb )) {

                    try_return( PostIrp = TRUE );
                }

                ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
#endif //REDUCE_SYNCHRONIZATION

                CcFlushCache( FileObject->SectionObjectPointer,
                              &StartingByte,
                              ByteCount,
                              &Irp->IoStatus );

#ifndef REDUCE_SYNCHRONIZATION
                ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
                FatReleaseFcb( IrpContext, FcbOrDcb );
#endif //REDUCE_SYNCHRONIZATION

                if (!NT_SUCCESS( Irp->IoStatus.Status)) {

                    try_return( Irp->IoStatus.Status );
                }

#ifndef REDUCE_SYNCHRONIZATION
                ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
                ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
#endif //REDUCE_SYNCHRONIZATION
            }

            //
            // We need shared access to the Fcb/Dcb before proceeding.
            //

            if ( PagingIo ) {

                if (!ExAcquireResourceSharedLite( FcbOrDcb->Header.PagingIoResource,
                                              Wait )) {

                    DebugTrace( 0, Dbg, "Cannot acquire FcbOrDcb = %08lx shared without waiting\n", FcbOrDcb );

                    try_return( PostIrp = TRUE );
                }

                if (!Wait) {

                    IrpContext->FatIoContext->Wait.Async.Resource =
                        FcbOrDcb->Header.PagingIoResource;
                }

            } else {

                //
                //  If this is async I/O, we will wait if there is an
                //  exclusive waiter.
                //

                if (!Wait && NonCachedIo) {

                    if (!FatAcquireSharedFcbWaitForEx( IrpContext, FcbOrDcb )) {

                        DebugTrace( 0,
                                    Dbg,
                                    "Cannot acquire FcbOrDcb = %08lx shared without waiting\n",
                                    FcbOrDcb );

                        try_return( PostIrp = TRUE );
                    }

                    IrpContext->FatIoContext->Wait.Async.Resource =
                        FcbOrDcb->Header.Resource;

                } else {

                    if (!FatAcquireSharedFcb( IrpContext, FcbOrDcb )) {

                        DebugTrace( 0,
                                    Dbg,
                                    "Cannot acquire FcbOrDcb = %08lx shared without waiting\n",
                                    FcbOrDcb );

                        try_return( PostIrp = TRUE );
                    }
                }
            }

            FcbOrDcbAcquired = TRUE;

            //
            //  Make sure the FcbOrDcb is still good
            //

            FatVerifyFcb( IrpContext, FcbOrDcb );

            //
            //  We now check whether we can proceed based on the state of
            //  the file oplocks.  
            //

            if (!PagingIo) {
                
                Status = FsRtlCheckOplock( &FcbOrDcb->Specific.Fcb.Oplock,
                                           Irp,
                                           IrpContext,
                                           FatOplockComplete,
                                           FatPrePostIrp );

                if (Status != STATUS_SUCCESS) {

                    OplockPostIrp = TRUE;
                    PostIrp = TRUE;
                    try_return( NOTHING );
                }

                //
                //  Reset the flag indicating if Fast I/O is possible since the oplock
                //  check could have broken existing (conflicting) oplocks.
                //

                FcbOrDcb->Header.IsFastIoPossible = FatIsFastIoPossible( FcbOrDcb );

                //
                // We have to check for read access according to the current
                // state of the file locks, and set FileSize from the Fcb.
                //

                if (!PagingIo &&
                    !FsRtlCheckLockForReadAccess( &FcbOrDcb->Specific.Fcb.FileLock,
                                                  Irp )) {

                    try_return( Status = STATUS_FILE_LOCK_CONFLICT );
                }
            }

            //
            //  Pick up our sizes and check/trim the IO.
            //

            FileSize = FcbOrDcb->Header.FileSize.LowPart;
            ValidDataLength = FcbOrDcb->Header.ValidDataLength.LowPart;

            //
            // If the read starts beyond End of File, return EOF.
            //

            if (StartingVbo >= FileSize) {

                DebugTrace( 0, Dbg, "End of File\n", 0 );

                try_return ( Status = STATUS_END_OF_FILE );
            }

            //
            //  If the read extends beyond EOF, truncate the read
            //

            if (ByteCount > FileSize - StartingVbo) {

                ByteCount = RequestedByteCount = FileSize - StartingVbo;

                if (NonCachedIo && !Wait) {

                    IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                        RequestedByteCount;

                }
            }

            //
            // HANDLE THE NON-CACHED CASE
            //

            if ( NonCachedIo ) {

                ULONG SectorSize;
                ULONG BytesToRead;

                DebugTrace(0, Dbg, "Non cached read.\n", 0);

                //
                //  Get the sector size
                //

                SectorSize = (ULONG)Vcb->Bpb.BytesPerSector;

                //
                //  Start by zeroing any part of the read after Valid Data
                //

                if (ValidDataLength < FcbOrDcb->ValidDataToDisk) {

                    ValidDataLength = FcbOrDcb->ValidDataToDisk;
                }

                if ( StartingVbo + ByteCount > ValidDataLength ) {

                    SystemBuffer = FatMapUserBuffer( IrpContext, Irp );

                    if (StartingVbo < ValidDataLength) {

                        ULONG ZeroingOffset;
                        
                        //
                        //  Now zero out the user's request sector aligned beyond
                        //  vdl.  We will handle the straddling sector at completion
                        //  time via the bytecount reduction which immediately
                        //  follows this check.
                        //
                        //  Note that we used to post in this case for async requests.
                        //  Note also that if the request was wholly beyond VDL that
                        //  we did not post, therefore this is consistent.  Synchronous
                        //  zeroing is fine for async requests.
                        //

                        ZeroingOffset = ((ValidDataLength - StartingVbo) + (SectorSize - 1))
                                                                        & ~(SectorSize - 1);

                        //
                        //  If the offset is at or above the byte count, no harm: just means
                        //  that the read ends in the last sector and the zeroing will be
                        //  done at completion.
                        //
                        
                        if (ByteCount > ZeroingOffset) {
                            
                            SafeZeroMemory( (PUCHAR) SystemBuffer + ZeroingOffset,
                                            ByteCount - ZeroingOffset);
                        }

                    } else {

                        //
                        //  All we have to do now is sit here and zero the
                        //  user's buffer, no reading is required.
                        //

                        SafeZeroMemory( (PUCHAR)SystemBuffer, ByteCount );

                        Irp->IoStatus.Information = ByteCount;

                        try_return ( Status = STATUS_SUCCESS );
                    }
                }

                //
                //  Reduce the byte count to actually read if it extends beyond
                //  Valid Data Length
                //

                ByteCount = (ValidDataLength - StartingVbo < ByteCount) ?
                             ValidDataLength - StartingVbo : ByteCount;
                //
                //  Round up to a sector boundary, and remember that if we are
                //  reading extra bytes we will zero them out during completion.
                //

                BytesToRead = (ByteCount + (SectorSize - 1))
                                        & ~(SectorSize - 1);

                //
                //  Just to help alleviate confusion.  At this point:
                //
                //  RequestedByteCount - is the number of bytes originally
                //                       taken from the Irp, but constrained
                //                       to filesize.
                //
                //  ByteCount -          is RequestedByteCount constrained to
                //                       ValidDataLength.
                //
                //  BytesToRead -        is ByteCount rounded up to sector
                //                       boundry.  This is the number of bytes
                //                       that we must physically read.
                //

                //
                //  If this request is not properly aligned, or extending
                //  to a sector boundary would overflow the buffer, send it off
                //  on a special-case path.
                //

                if ( (StartingVbo & (SectorSize - 1)) ||
                     (BytesToRead > IrpSp->Parameters.Read.Length) ) {

                    //
                    //  If we can't wait, we must post this.
                    //

                    if (!Wait) {

                        try_return( PostIrp = TRUE );
                    }

                    //
                    //  Do the physical read
                    //

                    FatNonCachedNonAlignedRead( IrpContext,
                                                Irp,
                                                FcbOrDcb,
                                                StartingVbo,
                                                ByteCount );

                    //
                    //  Set BytesToRead to ByteCount to satify the following ASSERT.
                    //

                    BytesToRead = ByteCount;

                } else {

                    //
                    //  Perform the actual IO
                    //

                    if (FatNonCachedIo( IrpContext,
                                        Irp,
                                        FcbOrDcb,
                                        StartingVbo,
                                        BytesToRead,
                                        ByteCount ) == STATUS_PENDING) {

                        IrpContext->FatIoContext = NULL;

                        Irp = NULL;

                        try_return( Status = STATUS_PENDING );
                    }

⌨️ 快捷键说明

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