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

📄 cdaudio.c

📁 The CD Audio sample allows some non-SCSI2 CD ROMs to support audio operations by intercepting the re
💻 C
📖 第 1 页 / 共 5 页
字号:

        if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
            ((ULONG)FIELD_OFFSET(CDROM_TOC, TrackData[0]))
            ) {
            status = STATUS_BUFFER_TOO_SMALL;
            // we have transferred zero bytes
            Irp->IoStatus.Information = 0;
            break;
        }

        //
        // Allocate storage to hold TOC from disc
        //

        Toc = (PUCHAR)ExAllocatePool( NonPagedPoolCacheAligned,
                                      NEC_CDROM_TOC_SIZE
                                    );

        if ( Toc == NULL ) {

            status = STATUS_INSUFFICIENT_RESOURCES;
            Irp->IoStatus.Information = 0;
            goto SetStatusAndReturn;

        }

        CdDump(( 4,
                 "NECDeviceControl => Toc = %p  cdaudioDataOut = %p\n",
                 Toc, cdaudioDataOut
               ));

        //
        // Set up defaults
        //

        RtlZeroMemory( Toc, NEC_CDROM_TOC_SIZE );
        srb.CdbLength = 10;

        //
        // Fill in CDB
        //

        cdb->NEC_READ_TOC.OperationCode = NEC_READ_TOC_CODE;
        cdb->NEC_READ_TOC.Type          = NEC_TRANSFER_WHOLE_TOC;
        srb.TimeOutValue      = AUDIO_TIMEOUT;
        status = SendSrbSynchronous(
                                   deviceExtension,
                                   &srb,
                                   Toc,
                                   NEC_CDROM_TOC_SIZE
                                   );

        if (!NT_SUCCESS(status) && (status!=STATUS_DATA_OVERRUN)) {

            CdDump(( 1,
                     "NECDeviceControl => READ_TOC error (%lx)\n",
                     status ));


            if (status != STATUS_DATA_OVERRUN) {

                CdDump(( 1, "NECDeviceControl => SRB ERROR (%lx)\n",
                         status ));
                Irp->IoStatus.Information = 0;
                ExFreePool( Toc );
                goto SetStatusAndReturn;
            }

        } else {

            status = STATUS_SUCCESS;
        }

        //
        // Translate data into our format.
        //

        bytesTransfered =
            currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength >
            sizeof(CDROM_TOC) ?
            sizeof(CDROM_TOC) :
            currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

        cdaudioDataOut->FirstTrack = BCD_TO_DEC(Toc[9]);
        cdaudioDataOut->LastTrack  = BCD_TO_DEC(Toc[19]);

        CdDump(( 4,
                 "NECDeviceControl => Tracks %d - %d, (%x bytes)\n",
                 cdaudioDataOut->FirstTrack,
                 cdaudioDataOut->LastTrack,
                 bytesTransfered
               ));

        //
        // Return only N number of tracks, where N is the number of
        // full tracks of info we can stuff into the user buffer
        // if tracks from 1 to 2, that means there are two tracks,
        // so let i go from 0 to 1 (two tracks of info)
        //
        {
            //
            // tracksToReturn == Number of real track info to return
            // tracksInBuffer == How many fit into the user-supplied buffer
            // tracksOnCd     == Number of tracks on the CD (not including lead-out)
            //

            ULONG tracksToReturn;
            ULONG tracksOnCd;
            ULONG tracksInBuffer;
            ULONG dataLength;
            tracksOnCd = (cdaudioDataOut->LastTrack - cdaudioDataOut->FirstTrack) + 1;

            dataLength = ((ULONG)FIELD_OFFSET(CDROM_TOC, TrackData[tracksOnCd])) - 2;
            cdaudioDataOut->Length[0]  = (UCHAR)(dataLength >> 8);
            cdaudioDataOut->Length[1]  = (UCHAR)(dataLength & 0xFF);


            tracksInBuffer = currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength -
                             ((ULONG)FIELD_OFFSET(CDROM_TOC, TrackData[0]));
            tracksInBuffer /= sizeof(TRACK_DATA);

            // take the lesser of the two
            tracksToReturn = (tracksInBuffer < tracksOnCd) ?
                             tracksInBuffer :
                             tracksOnCd;

            for( i=0; i < tracksToReturn; i++ ) {

                //
                // Grab Information for each track
                //

                cdaudioDataOut->TrackData[i].Reserved = 0;
                cdaudioDataOut->TrackData[i].Control =
                    ((Toc[(i*10)+32] & 0x0F) << 4) | (Toc[(i*10)+32] >> 4);
                cdaudioDataOut->TrackData[i].TrackNumber =
                    (UCHAR)(i + cdaudioDataOut->FirstTrack);

                cdaudioDataOut->TrackData[i].Reserved1  = 0;
                cdaudioDataOut->TrackData[i].Address[0] = 0;
                cdaudioDataOut->TrackData[i].Address[1] =
                    BCD_TO_DEC((Toc[(i*10)+39]));
                cdaudioDataOut->TrackData[i].Address[2] =
                    BCD_TO_DEC((Toc[(i*10)+40]));
                cdaudioDataOut->TrackData[i].Address[3] =
                    BCD_TO_DEC((Toc[(i*10)+41]));

                CdDump(( 4,
                            "CdAudioNecDeviceControl: Track %d  %d:%d:%d\n",
                            cdaudioDataOut->TrackData[i].TrackNumber,
                            cdaudioDataOut->TrackData[i].Address[1],
                            cdaudioDataOut->TrackData[i].Address[2],
                            cdaudioDataOut->TrackData[i].Address[3]
                        ));
            }

            //
            // Fake "lead out track" info
            // Only if all tracks have been copied...
            //

            if ( tracksInBuffer > tracksOnCd ) {
                cdaudioDataOut->TrackData[i].Reserved    = 0;
                cdaudioDataOut->TrackData[i].Control     = 0x10;
                cdaudioDataOut->TrackData[i].TrackNumber = 0xaa;
                cdaudioDataOut->TrackData[i].Reserved1   = 0;
                cdaudioDataOut->TrackData[i].Address[0]  = 0;
                cdaudioDataOut->TrackData[i].Address[1]  = BCD_TO_DEC(Toc[29]);
                cdaudioDataOut->TrackData[i].Address[2]  = BCD_TO_DEC(Toc[30]);
                cdaudioDataOut->TrackData[i].Address[3]  = BCD_TO_DEC(Toc[31]);

                CdDump(( 4,
                         "NECDeviceControl => Track %d  %d:%d:%d\n",
                         cdaudioDataOut->TrackData[i].TrackNumber,
                         cdaudioDataOut->TrackData[i].Address[1],
                         cdaudioDataOut->TrackData[i].Address[2],
                         cdaudioDataOut->TrackData[i].Address[3]
                       ));
                i++;
            }

            Irp->IoStatus.Information  = ((ULONG)FIELD_OFFSET(CDROM_TOC, TrackData[i]));

        }


        //
        // Free storage now that we've stored it elsewhere
        //

        ExFreePool( Toc );
        break;

    case IOCTL_CDROM_STOP_AUDIO:

        deviceExtension->PlayActive = FALSE;

        //
        // Same as scsi-2 spec, so just send to default driver
        //

        return CdAudioSendToNextDriver( DeviceObject, Irp );
        break;

    case IOCTL_CDROM_PLAY_AUDIO_MSF:
        {

            PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;

            CdDump(( 3,
                     "NECDeviceControl => IOCTL_CDROM_PLAY_AUDIO_MSF recv'd.\n"
                   ));

            if (currentIrpStack->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(CDROM_PLAY_AUDIO_MSF)
                ) {
                status = STATUS_INFO_LENGTH_MISMATCH;
                Irp->IoStatus.Information = 0;
                break;
            }


            //
            // First, seek to Starting MSF and enter play mode.
            //

            srb.CdbLength                     = 10;
            srb.TimeOutValue                  = AUDIO_TIMEOUT;
            cdb->NEC_PLAY_AUDIO.OperationCode = NEC_AUDIO_TRACK_SEARCH_CODE;
            cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_ENTER_PLAY_MODE;
            cdb->NEC_PLAY_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->StartingM);
            cdb->NEC_PLAY_AUDIO.Second        = DEC_TO_BCD(inputBuffer->StartingS);
            cdb->NEC_PLAY_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->StartingF);
            cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_ATIME;

            CdDump(( 3,
                     "NECDeviceControl => play start MSF is BCD(%x:%x:%x)\n",
                     cdb->NEC_PLAY_AUDIO.Minute,
                     cdb->NEC_PLAY_AUDIO.Second,
                     cdb->NEC_PLAY_AUDIO.Frame
                   ));


            status = SendSrbSynchronous(deviceExtension,
                                        &srb,
                                        NULL,
                                        0
                                       );
            if (NT_SUCCESS(status)) {

                //
                // Indicate the play actition is active.
                //

                deviceExtension->PlayActive = TRUE;

                //
                // Now, set the termination point for the play operation
                //

                RtlZeroMemory( cdb, MAXIMUM_CDB_SIZE );
                cdb->NEC_PLAY_AUDIO.OperationCode = NEC_PLAY_AUDIO_CODE;
                cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_PLAY_STEREO;
                cdb->NEC_PLAY_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->EndingM);
                cdb->NEC_PLAY_AUDIO.Second        = DEC_TO_BCD(inputBuffer->EndingS);
                cdb->NEC_PLAY_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->EndingF);
                cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_ATIME;

                CdDump(( 3,
                         "NECDeviceControl => play end MSF is BCD(%x:%x:%x)\n",
                         cdb->NEC_PLAY_AUDIO.Minute,
                         cdb->NEC_PLAY_AUDIO.Second,
                         cdb->NEC_PLAY_AUDIO.Frame
                       ));

                status = SendSrbSynchronous(
                                           deviceExtension,
                                           &srb,
                                           NULL,
                                           0
                                           );


            }
        }
        break;

    case IOCTL_CDROM_SEEK_AUDIO_MSF:
        {

            PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;

            CdDump(( 3,
                     "NECDeviceControl => IOCTL_CDROM_SEEK_AUDIO_MSF recv'd.\n"
                   ));

            //
            // Must have allocated at least enough buffer space
            // to store how many tracks are on the disc
            //

            if (currentIrpStack->Parameters.DeviceIoControl.InputBufferLength <
                sizeof(CDROM_SEEK_AUDIO_MSF)
                ) {
                status = STATUS_INFO_LENGTH_MISMATCH;
                Irp->IoStatus.Information = 0;
                break;
            }


            //
            // seek to MSF and enter pause (still) mode.
            //

            srb.CdbLength                 = 10;
            srb.TimeOutValue              = AUDIO_TIMEOUT;
            cdb->NEC_SEEK_AUDIO.OperationCode = NEC_AUDIO_TRACK_SEARCH_CODE;
            cdb->NEC_SEEK_AUDIO.Minute        = DEC_TO_BCD(inputBuffer->M);
            cdb->NEC_SEEK_AUDIO.Second        = DEC_TO_BCD(inputBuffer->S);
            cdb->NEC_SEEK_AUDIO.Frame         = DEC_TO_BCD(inputBuffer->F);
            cdb->NEC_SEEK_AUDIO.Control       = NEC_TYPE_ATIME;
            CdDump(( 4,
                     "NECDeviceControl => seek MSF is %d:%d:%d\n",
                     cdb->NEC_SEEK_AUDIO.Minute,
                     cdb->NEC_SEEK_AUDIO.Second,
                     cdb->NEC_SEEK_AUDIO.Frame
                   ));

            status = SendSrbSynchronous(
                                       deviceExtension,
                                       &srb,
                                       NULL,
                                       0
                                       );

        }
        break;

    case IOCTL_CDROM_PAUSE_AUDIO:

        CdDump(( 3,
                 "NECDeviceControl => IOCTL_CDROM_PAUSE_AUDIO recv'd.\n"
               ));

        deviceExtension->PlayActive = FALSE;

        //
        // Enter pause (still ) mode
        //

        srb.CdbLength                  = 10;
        srb.TimeOutValue               = AUDIO_TIMEOUT;
        cdb->NEC_PAUSE_AUDIO.OperationCode = NEC_STILL_CODE;
        status = SendSrbSynchronous(
                                   deviceExtension,
                                   &srb,
                                   NULL,
                                   0
                                   );

        break;

    case IOCTL_CDROM_RESUME_AUDIO:

        CdDump(( 3,
                 "NECDeviceControl => IOCTL_CDROM_RESUME_AUDIO recv'd.\n"
               ));

        //
        // Resume play
        //

        srb.CdbLength                 = 10;
        srb.TimeOutValue              = AUDIO_TIMEOUT;
        cdb->NEC_PLAY_AUDIO.OperationCode = NEC_PLAY_AUDIO_CODE;
        cdb->NEC_PLAY_AUDIO.PlayMode      = NEC_PLAY_STEREO;
        cdb->NEC_PLAY_AUDIO.Control       = NEC_TYPE_NO_CHANGE;
        status = SendSrbSynchronous(
                                   deviceExtension,
                                   &srb,
                                   NULL,
                                   0
                                   );
        break;

    case IOCTL_CDROM_READ_Q_CHANNEL:
        {

            PSUB_Q_CURRENT_POSITION userPtr =
                Irp->AssociatedIrp.SystemBuffer;
            PUCHAR SubQPtr =
                ExAllocatePool( NonPagedPoolCacheAligned,
                                NEC_Q_CHANNEL_TRANSFER_SIZE
                              );

            if (currentIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
                sizeof(SUB_Q_CURRENT_POSITION)
                ) {
                status = STATUS_BUFFER_TOO_SMALL;
                // we have transferred zero bytes
                Irp->IoStatus.Information = 0;
                if (SubQPtr) ExFreePool(SubQPtr);
                break;
            }


            CdDump(( 5,
                     "NECDeviceControl => IOCTL_CDROM_READ_Q_CHANNEL recv'd.\n"
                   ));

            if (SubQPtr==NULL) {

                CdDump(( 1,
                         "NECDeviceControl !! READ_Q_CHANNEL, SubQPtr==NULL!\n"
                       ));

                status = STATUS_INSUFFICIENT_RESOURCES;
                Irp->IoStatus.Information = 0;
                goto SetStatusAndReturn;

            }

            RtlZeroMemory( SubQPtr, NEC_Q_CHANNEL_TRANSFER_SIZE );

            if ( ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format!=
                 IOCTL_CDROM_CURRENT_POSITION) {

                CdDump((1,
                    "NECDeviceControl !! READ_Q_CHANNEL, illegal Format (%d)\n",
                    ((PCDROM_SUB_Q_DATA_FORMAT)userPtr)->Format
                    ));

                ExFreePool( SubQPtr );
                status = STATUS_UNSUCCESSFUL;
                Irp->IoStatus.Information = 0;
                goto SetStatusAndReturn;
            }

            NECSeek:

            //
            // Set up to read Q Channel
            //

            srb.CdbLength                     = 10;
            srb.TimeOutValue                  = AUDIO_TIMEOUT;
            cdb->NEC_READ_Q_CHANNEL.OperationCode = NEC_READ_SUB_Q_CHANNEL_CODE;
            // Transfer Length
            cdb->NEC_READ_Q_CHANNEL.TransferSize  = NEC_Q_CHANNEL_TRANSFER_SIZE;
            CdDump(( 4, "NECDeviceControl => cdb = %p  srb = %p  SubQPtr = %p\n",
                     cdb,
                     &srb,
      

⌨️ 快捷键说明

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