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

📄 cdrom.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
            // Build SRB and CDB for this IRP.
            //

            ScsiClassBuildRequest(DeviceObject, Irp);

        }


    } else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {

        //
        // Allocate an irp, srb and associated structures.
        //

        irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
                              FALSE);

        if (!irp2) {
            Irp->IoStatus.Information = 0;
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(Irp, IO_DISK_INCREMENT);
            IoStartNextPacket(DeviceObject, FALSE);
            DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
            return;
        }

        srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
        if (!srb) {
            Irp->IoStatus.Information = 0;
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(Irp, IO_DISK_INCREMENT);
            IoFreeIrp(irp2);
            IoStartNextPacket(DeviceObject, FALSE);
            DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
            return;
        }

        RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));

        cdb = (PCDB)srb->Cdb;

        //
        // Allocate sense buffer.
        //

        senseBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

        if (!senseBuffer) {
            Irp->IoStatus.Information = 0;
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest(Irp, IO_DISK_INCREMENT);
            ExFreePool(srb);
            IoFreeIrp(irp2);
            IoStartNextPacket(DeviceObject, FALSE);
            DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
            return;
        }

        //
        // Set up the irp.
        //

        IoSetNextIrpStackLocation(irp2);
        irp2->IoStatus.Status = STATUS_SUCCESS;
        irp2->IoStatus.Information = 0;
        irp2->Flags = 0;
        irp2->UserBuffer = NULL;

        //
        // Save the device object and irp in a private stack location.
        //

        irpStack = IoGetCurrentIrpStackLocation(irp2);
        irpStack->DeviceObject = deviceExtension->DeviceObject;
        irpStack->Parameters.Others.Argument2 = (PVOID) Irp;

        //
        // The retry count will be in the real Irp, as the retry logic will
        // recreate our private irp.
        //

        if (!(nextIrpStack->Parameters.Others.Argument1)) {

            //
            // Only jam this in if it doesn't exist. The completion routines can
            // call StartIo directly in the case of retries and resetting it will
            // cause infinite loops.
            //

            nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
        }

        //
        // Construct the IRP stack for the lower level driver.
        //

        irpStack = IoGetNextIrpStackLocation(irp2);
        irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
        irpStack->Parameters.Scsi.Srb = srb;

        IoSetCompletionRoutine(irp2,
                               CdRomDeviceControlCompletion,
                               srb,
                               TRUE,
                               TRUE,
                               TRUE);
        //
        // Setup those fields that are generic to all requests.
        //

        srb->Length = SCSI_REQUEST_BLOCK_SIZE;
        srb->PathId = deviceExtension->PathId;
        srb->TargetId = deviceExtension->TargetId;
        srb->Lun = deviceExtension->Lun;
        srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
        srb->Cdb[1] |= deviceExtension->Lun << 5;
        srb->SrbStatus = srb->ScsiStatus = 0;
        srb->NextSrb = 0;
        srb->OriginalRequest = irp2;
        srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        srb->SenseInfoBuffer = senseBuffer;

        switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {

        case IOCTL_CDROM_RAW_READ: {

            //
            // Determine whether the drive is currently in raw or cooked mode,
            // and which command to use to read the data.
            //

            if (!(cdData->XAFlags & XA_USE_READ_CD)) {

                PRAW_READ_INFO rawReadInfo =
                                   (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
                ULONG          maximumTransferLength;
                ULONG          transferPages;

                if (cdData->RawAccess) {

                    ULONG  startingSector;
                    UCHAR  min, sec, frame;

                    //
                    // Free the recently allocated irp, as we don't need it.
                    //

                    IoFreeIrp(irp2);

                    cdb = (PCDB)srb->Cdb;
                    RtlZeroMemory(cdb, 12);

                    //
                    // Calculate starting offset.
                    //

                    startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
                    transferByteCount  = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
                    maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
                    transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
                                                                   transferByteCount);

                    //
                    // Determine if request is within limits imposed by miniport.
                    //

                    if (transferByteCount > maximumTransferLength ||
                        transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {

                        //
                        // The claim is that this won't happen, and is backed up by
                        // ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet
                        // we get only 4 sector requests.
                        //


                        Irp->IoStatus.Information = 0;
                        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
                        ExFreePool(senseBuffer);
                        ExFreePool(srb);
                        IoStartNextPacket(DeviceObject, FALSE);
                        return;

                    }

                    srb->OriginalRequest = Irp;
                    srb->SrbFlags = deviceExtension->SrbFlags;
                    srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN);
                    srb->DataTransferLength = transferByteCount;
                    srb->TimeOutValue = deviceExtension->TimeOutValue;
                    srb->CdbLength = 10;
                    srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);

                    if (rawReadInfo->TrackMode == CDDA) {
                        if (cdData->XAFlags & PLEXTOR_CDDA) {

                            srb->CdbLength = 12;

                            cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
                            cdb->PLXTR_READ_CDDA.LogicalBlockByte3  = (UCHAR) (startingSector & 0xFF);
                            cdb->PLXTR_READ_CDDA.LogicalBlockByte2  = (UCHAR) ((startingSector >>  8) & 0xFF);
                            cdb->PLXTR_READ_CDDA.LogicalBlockByte1  = (UCHAR) ((startingSector >> 16) & 0xFF);
                            cdb->PLXTR_READ_CDDA.LogicalBlockByte0  = (UCHAR) ((startingSector >> 24) & 0xFF);

                            cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
                            cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
                            cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
                            cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;

                            cdb->PLXTR_READ_CDDA.SubCode = 0;
                            cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;

                        } else if (cdData->XAFlags & NEC_CDDA) {

                            cdb->NEC_READ_CDDA.LogicalBlockByte3  = (UCHAR) (startingSector & 0xFF);
                            cdb->NEC_READ_CDDA.LogicalBlockByte2  = (UCHAR) ((startingSector >>  8) & 0xFF);
                            cdb->NEC_READ_CDDA.LogicalBlockByte1  = (UCHAR) ((startingSector >> 16) & 0xFF);
                            cdb->NEC_READ_CDDA.LogicalBlockByte0  = (UCHAR) ((startingSector >> 24) & 0xFF);

                            cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
                            cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);

                            cdb->NEC_READ_CDDA.OperationCode = 0xD4;
                        }
                    } else {

                        cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;

                        cdb->CDB10.TransferBlocksMsb  = (UCHAR) (rawReadInfo->SectorCount >> 8);
                        cdb->CDB10.TransferBlocksLsb  = (UCHAR) (rawReadInfo->SectorCount & 0xFF);

                        cdb->CDB10.LogicalBlockByte3  = (UCHAR) (startingSector & 0xFF);
                        cdb->CDB10.LogicalBlockByte2  = (UCHAR) ((startingSector >>  8) & 0xFF);
                        cdb->CDB10.LogicalBlockByte1  = (UCHAR) ((startingSector >> 16) & 0xFF);
                        cdb->CDB10.LogicalBlockByte0  = (UCHAR) ((startingSector >> 24) & 0xFF);

                        cdb->CDB10.OperationCode = SCSIOP_READ;
                    }

                    srb->SrbStatus = srb->ScsiStatus = 0;

                    nextIrpStack->MajorFunction = IRP_MJ_SCSI;
                    nextIrpStack->Parameters.Scsi.Srb = srb;

                    if (!(nextIrpStack->Parameters.Others.Argument1)) {

                        //
                        // Only jam this in if it doesn't exist. The completion routines can
                        // call StartIo directly in the case of retries and resetting it will
                        // cause infinite loops.
                        //

                        nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
                    }

                    //
                    // Set up IoCompletion routine address.
                    //

                    IoSetCompletionRoutine(Irp,
                                           CdRomXACompletion,
                                           srb,
                                           TRUE,
                                           TRUE,
                                           TRUE);

                    IoCallDriver(deviceExtension->PortDeviceObject, Irp);
                    return;

                } else {

                    transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
                    dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
                    if (!dataBuffer) {
                        Irp->IoStatus.Information = 0;
                        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
                        ExFreePool(senseBuffer);
                        ExFreePool(srb);
                        IoFreeIrp(irp2);
                        IoStartNextPacket(DeviceObject, FALSE);
                        return;

                    }

                    irp2->MdlAddress = IoAllocateMdl(dataBuffer,
                                                    transferByteCount,
                                                    FALSE,
                                                    FALSE,
                                                    (PIRP) NULL);

                    if (!irp2->MdlAddress) {
                        Irp->IoStatus.Information = 0;
                        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
                        ExFreePool(senseBuffer);
                        ExFreePool(srb);
                        ExFreePool(dataBuffer);
                        IoFreeIrp(irp2);
                        IoStartNextPacket(DeviceObject, FALSE);
                        return;
                    }

                    //
                    // Prepare the MDL
                    //

                    MmBuildMdlForNonPagedPool(irp2->MdlAddress);

                    srb->DataBuffer = dataBuffer;

                    //
                    // Set the new block size in the descriptor.
                    //

                    cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF;
                    cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >>  8) & 0xFF;
                    cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF);


                    //
                    // TODO: Set density code, based on operation
                    //

                    cdData->u1.BlockDescriptor.DensityCode = 0;


                    //
                    // Move error page into dataBuffer.
                    //

                    RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);


                    //
                    // Build and send a mode select to switch into raw mode.
                    //

                    srb->SrbFlags = deviceExtension->SrbFlags;
                    srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_OUT);
                    srb->DataTransferLength = transferByteCount;
                    srb->TimeOutValue = deviceExtension->TimeOutValue * 2;

                    if (use6Byte) {
                        srb->CdbLength = 6;
                        cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
                        cdb->MODE_SELECT.PFBit = 1;
                        cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
                    } else {

                        srb->CdbLength = 10;
                        cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
                        cdb->MODE_SELECT10.PFBit = 1;
                        cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
                        cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
                    }

                    //
                    // Update completion routine.
                    //

                    IoSetCompletionRoutine(irp2,
                                           CdRomSwitchModeCompletion,
                                           srb,
                                           TRUE,
                                           TRUE,
                                           TRUE);

                }

            } else {

                PRAW_READ_INFO rawReadInfo =
                                   (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
                ULONG  startingSector;

                //
                // Free the recently allocated irp, as we don't need it.
                //

                IoFreeIrp(irp2);

                cdb = (PCDB)srb->Cdb;
                RtlZeroMemory(cdb, 12);


                //
                // Calculate starting offset.
                //

                startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
                transferByteCount  = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;


                srb->OriginalRequest = Irp;
                srb->SrbFlags = deviceExtension->SrbFlags;
                srb->SrbFlags |= (SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN);
                srb->DataTransferLength = transferByteCount;
                srb->TimeOutValue = deviceExtension->TimeOutValue;
                srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
                srb->CdbLength = 12;
                srb->SrbStatus = srb->ScsiStatus = 0;

                //
                // Fill in CDB fields.
                //

                cdb = (PCDB)srb->Cdb;


                cdb->READ_CD.TransferBlocks[2]  = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
                cdb->READ_CD.TransferBlocks[1]  = (UCHAR) (rawReadInfo->SectorCount >> 8 );
                cdb->READ_CD.TransferBlocks[0]  = (UCHAR) (rawReadInfo->SectorCount >> 16);


                cdb->READ_CD.StartingLBA[3]  = (UCHAR) (startingSector & 0

⌨️ 快捷键说明

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