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

📄 deviosup.c

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

            //
            //  If this is an async request and there aren't enough entries
            //  in the Io array then post the request.
            //

            if ((ThisByteCount < RemainingByteCount) &&
                !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {

                CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            //
            //  If the entire Io is contained in a single run then
            //  we can pass the Io down to the driver.  Send the driver down
            //  and wait on the result if this is synchronous.
            //

            if ((RunCount == 1) && !Unaligned && FirstPass) {

                CdSingleAsync( IrpContext,&IoRuns[0], Fcb );

                //
                //  No cleanup needed for the IoRuns array here.
                //

                CleanupRunCount = 0;

                //
                //  Wait if we are synchronous, otherwise return
                //

                if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {

                    CdWaitSync( IrpContext );

                    Status = IrpContext->Irp->IoStatus.Status;

                //
                //  Our completion routine will free the Io context but
                //  we do want to return STATUS_PENDING.
                //

                } else {

                    ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
                    Status = STATUS_PENDING;
                }

                try_return( NOTHING );
            }

            //
            //  Otherwise we will perform multiple Io to read in the data.
            //

            CdMultipleAsync( IrpContext, Fcb, RunCount, IoRuns );

            //
            //  If this is a synchronous request then perform any necessary
            //  post-processing.
            //

            if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {

                //
                //  Wait for the request to complete.
                //

                CdWaitSync( IrpContext );

                Status = IrpContext->Irp->IoStatus.Status;

                //
                //  Exit this loop if there is an error.
                //

                if (!NT_SUCCESS( Status )) {

                    try_return( NOTHING );
                }

                //
                //  Perform post read operations on the IoRuns if
                //  necessary.
                //

                if (Unaligned &&
                    CdFinishBuffers( IrpContext, IoRuns, RunCount, FALSE, FALSE )) {

                    FlushIoBuffers = TRUE;
                }
                
                CleanupRunCount = 0;

                //
                //  Exit this loop if there are no more bytes to transfer
                //  or we have any error.
                //

                RemainingByteCount -= ThisByteCount;
                CurrentOffset += ThisByteCount;
                UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
                UserBufferOffset += ThisByteCount;

            //
            //  Otherwise this is an asynchronous request.  Always return
            //  STATUS_PENDING.
            //

            } else {

                ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
                CleanupRunCount = 0;
                try_return( Status = STATUS_PENDING );
                break;
            }

            FirstPass = FALSE;
        } while (RemainingByteCount != 0);

        //
        //  Flush the hardware cache if we performed any copy operations.
        //

        if (FlushIoBuffers) {

            KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
        }

    try_exit:  NOTHING;
    } finally {

        //
        //  Perform final cleanup on the IoRuns if necessary.
        //

        if (CleanupRunCount != 0) {

            CdFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE, FALSE );
        }
    }

    return Status;
}


NTSTATUS
CdNonCachedXARead (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN LONGLONG StartingOffset,
    IN ULONG ByteCount
    )

/*++

Routine Description:

    This routine performs the non-cached reads for 'raw' sectors (2352 bytes
    per sector).  We also prepend a hard-coded RIFF header of 44 bytes to the file.
    All of this is already reflected in the file size.

    We start by checking whether to prepend any portion of the RIFF header.  Then we check
    if the last raw sector read was from the beginning portion of this file, deallocating
    that buffer if necessary.  Finally we do the following in a loop.

        Fill the IoRuns array for the next block of Io.
        Send the Io to the device driver.
        Perform any cleanup necessary on the IoRuns array.

    We will not do any async request in this path.  The request would have been
    posted to a worker thread before getting to this point.

Arguments:

    Fcb - Fcb representing the file to read.

    StartingOffset - Logical offset in the file to read from.

    ByteCount - Number of bytes to read.

Return Value:

    NTSTATUS - Status indicating the result of the operation.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    RIFF_HEADER LocalRiffHeader;
    PRIFF_HEADER RiffHeader;

    RAW_READ_INFO RawReads[MAX_PARALLEL_IOS];
    IO_RUN IoRuns[MAX_PARALLEL_IOS];
    ULONG RunCount = 0;
    ULONG CleanupRunCount = 0;

    PVOID UserBuffer;
    ULONG UserBufferOffset = 0;
    LONGLONG CurrentOffset = StartingOffset;
    ULONG RemainingByteCount = ByteCount;
    ULONG ThisByteCount;
    ULONG Address = 0;

    BOOLEAN TryingYellowbookMode2 = FALSE;

    TRACK_MODE_TYPE TrackMode;

    PAGED_CODE();

    //
    //  We want to make sure the user's buffer is locked in all cases.
    //

    if (IrpContext->Irp->MdlAddress == NULL) {

        CdCreateUserMdl( IrpContext, ByteCount, TRUE );
    }

    //
    //  The byte count was rounded up to a logical sector boundary.  It has
    //  nothing to do with the raw sectors on disk.  Limit the remaining
    //  byte count to file size.
    //

    if (CurrentOffset + RemainingByteCount > Fcb->FileSize.QuadPart) {

        RemainingByteCount = (ULONG) (Fcb->FileSize.QuadPart - CurrentOffset);
    }

    CdMapUserBuffer( IrpContext, &UserBuffer);

    //
    //  Use a try-finally to perform the final cleanup.
    //

    try {

        //
        //  If the initial offset lies within the RIFF header then copy the
        //  necessary bytes to the user's buffer.
        //

        if (CurrentOffset < sizeof( RIFF_HEADER )) {

            //
            //  Copy the appropriate RIFF header.
            //

            if (FlagOn( Fcb->FcbState, FCB_STATE_DA_FILE )) {

                //
                //  Create the pseudo entries for a music disk.
                //

                if (FlagOn( Fcb->Vcb->VcbState, VCB_STATE_AUDIO_DISK )) {

                    PAUDIO_PLAY_HEADER AudioPlayHeader;
                    PTRACK_DATA TrackData;

                    AudioPlayHeader = (PAUDIO_PLAY_HEADER) &LocalRiffHeader;
                    TrackData = &Fcb->Vcb->CdromToc->TrackData[Fcb->XAFileNumber];

                    //
                    //  Copy the data header into our local buffer.
                    //

                    RtlCopyMemory( AudioPlayHeader,
                                   CdAudioPlayHeader,
                                   sizeof( AUDIO_PLAY_HEADER ));

                    //
                    //  Copy the serial number into the Id field.  Also
                    //  the track number in the TOC.
                    //

                    AudioPlayHeader->DiskID = Fcb->Vcb->Vpb->SerialNumber;
                    AudioPlayHeader->TrackNumber = TrackData->TrackNumber;

                    //
                    //  One frame == One sector.
                    //  One second == 75 frames (winds up being a 44.1khz sample)
                    //
                    //  Note: LBN 0 == 0:2:0 (MSF)
                    //
                    
                    //
                    //  Fill in the address (both MSF and Lbn format) and length fields.
                    //
                    
                    SwapCopyUchar4( &Address, TrackData->Address);
                    CdLbnToMmSsFf( Address, AudioPlayHeader->TrackAddress);
                    
                    SwapCopyUchar4( &AudioPlayHeader->StartingSector, TrackData->Address);

                    //
                    //  Go to the next track and find the starting point.
                    //

                    TrackData = &Fcb->Vcb->CdromToc->TrackData[Fcb->XAFileNumber + 1];

                    SwapCopyUchar4( &AudioPlayHeader->SectorCount, TrackData->Address);

                    //
                    //  Now compute the difference.  If there is an error then use
                    //  a length of zero.
                    //

                    if (AudioPlayHeader->SectorCount < AudioPlayHeader->StartingSector) {

                        AudioPlayHeader->SectorCount = 0;

                    } else {

                        AudioPlayHeader->SectorCount -= AudioPlayHeader->StartingSector;
                    }

                    //
                    //  Use the sector count to determine the MSF length. Bias by 150 to make
                    //  it an "lbn" since the conversion routine corrects for Lbn 0 == 0:2:0;
                    //

                    Address = AudioPlayHeader->SectorCount - 150;
                    CdLbnToMmSsFf( Address, AudioPlayHeader->TrackLength);

                    ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;

                    RtlCopyMemory( UserBuffer,
                                   Add2Ptr( AudioPlayHeader,
                                            sizeof( RIFF_HEADER ) - ThisByteCount,
                                            PCHAR ),
                                   ThisByteCount );

                //
                //  CD-XA CDDA
                //

                } else {

                    //
                    //  The WAVE header format is actually much closer to an audio play
                    //  header in format but we only need to modify the filesize fields.
                    //

                    RiffHeader = &LocalRiffHeader;

                    //
                    //  Copy the data header into our local buffer and add the file size to it.
                    //

                    RtlCopyMemory( RiffHeader,
                                   CdXAAudioPhileHeader,
                                   sizeof( RIFF_HEADER ));

                    RiffHeader->ChunkSize += Fcb->FileSize.LowPart;
                    RiffHeader->RawSectors += Fcb->FileSize.LowPart;

                    ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;
                    RtlCopyMemory( UserBuffer,
                                   Add2Ptr( RiffHeader,
                                            sizeof( RIFF_HEADER ) - ThisByteCount,
                                            PCHAR ),
                                   ThisByteCount );
                }

            //
            //  CD-XA non-audio
            //
            
            } else { 
    
                ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_MODE2_FILE | FCB_STATE_MODE2FORM2_FILE ));

                RiffHeader = &LocalRiffHeader;

                //
                //  Copy the data header into our local buffer and add the file size to it.
                //

                RtlCopyMemory( RiffHeader,
                               CdXAFileHeader,
                               sizeof( RIFF_HEADER ));

                RiffHeader->ChunkSize += Fcb->FileSize.LowPart;
                RiffHeader->RawSectors += Fcb->FileSize.LowPart;

                RiffHeader->Attributes = (USHORT) Fcb->XAAttributes;
                RiffHeader->FileNumber = (UCHAR) Fcb->XAFileNumber;

                ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;
                RtlCopyMemory( UserBuffer,
                               Add2Ptr( RiffHeader,
                                        sizeof( RIFF_HEADER ) - ThisByteCount,
                                        PCHAR ),
                               ThisByteCount );
            }

            //
            //  Adjust the starting offset and byte count to reflect that
            //  we copied over the RIFF bytes.
            //

            UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
            UserBufferOffset += ThisByteCount;
            CurrentOffset += ThisByteCount;
            RemainingByteCount -= ThisByteCount;
        }

        //
        //  Set up the appropriate trackmode
        //

        TrackMode = CdFileTrackMode(Fcb);

        //
        //  Loop while there are more bytes to transfer.
        //

        while (RemainingByteCount != 0) {

            //
            //  Call prepare buffers to set up the next entries
            //  in the IoRuns array.  Remember if there are any
            //  unaligned entries.  If we're just retrying the previous
            //  runs with a different track mode,  then don't do anything here.
            //

            if (!TryingYellowbookMode2)  {
            
                RtlZeroMemory( IoRuns, sizeof( IoRuns ));
                RtlZeroMemory( RawReads, sizeof( RawReads ));

                CdPrepareXABuffers( IrpContext,

⌨️ 快捷键说明

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