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

📄 cdrom.c

📁 The CD ROM driver is used with Classpnp.sys to provide access to CD ROMs and DVD ROMs. It supports P
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    //
    // Save the device descriptors
    //

    fdoExtension->AdapterDescriptor = NULL;

    fdoExtension->DeviceDescriptor = NULL;

    //
    // Clear the SrbFlags and disable synchronous transfers
    //

    fdoExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;

    //
    // Finally, attach to the PDO
    //

    fdoExtension->LowerPdo = PhysicalDeviceObject;

    fdoExtension->CommonExtension.LowerDeviceObject =
        IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);

    if(fdoExtension->CommonExtension.LowerDeviceObject == NULL) {

        //
        // Uh - oh, we couldn't attach
        // cleanup and return
        //

        status = STATUS_UNSUCCESSFUL;
        goto CreateCdRomDeviceObjectExit;
    }

    //
    // CdRom uses an extra stack location for synchronizing it's start io
    // routine
    //

    deviceObject->StackSize++;

    //
    // cdData is used a few times below
    //

    cdData = fdoExtension->CommonExtension.DriverData;

    //
    // For NTMS to be able to easily determine drives-drv. letter matches.
    //

    status = CdRomCreateWellKnownName( deviceObject );

    if (!NT_SUCCESS(status)) {
        TraceLog((CdromDebugWarning,
                    "CdromCreateDeviceObjects: unable to create symbolic "
                    "link for device %wZ\n", &fdoExtension->CommonExtension.DeviceName));
        TraceLog((CdromDebugWarning,
                    "CdromCreateDeviceObjects: (non-fatal error)\n"));
    }

    ClassUpdateInformationInRegistry(deviceObject, "CdRom",
                                     fdoExtension->DeviceNumber, NULL, 0);

    //
    // from above IoGetAttachedDeviceReference
    //

    ObDereferenceObject(lowerDevice);

    //
    // need to init timerlist here in case a remove occurs
    // without a start, since we check the list is empty on remove.
    //

    cdData->DelayedRetryIrp = NULL;
    cdData->DelayedRetryInterval = 0;

    //
    // need this to be initialized for RPC Phase 1 drives (rpc0)
    //

    KeInitializeMutex(&cdData->Rpc0RegionMutex, 0);

    //
    // The device is initialized properly - mark it as such.
    //

    CLEAR_FLAG(deviceObject->Flags, DO_DEVICE_INITIALIZING);

    return(STATUS_SUCCESS);

CreateCdRomDeviceObjectExit:

    //
    // Release the device since an error occured.
    //

    // ClassClaimDevice(PortDeviceObject,
    //                      LunInfo,
    //                      TRUE,
    //                      NULL);

    //
    // from above IoGetAttachedDeviceReference
    //

    ObDereferenceObject(lowerDevice);

    if (deviceObject != NULL) {
        IoDeleteDevice(deviceObject);
    }

    return status;

} // end CreateCdRomDeviceObject()


NTSTATUS
CdRomInitDevice(
    IN PDEVICE_OBJECT Fdo
    )

/*++

Routine Description:

    This routine will complete the cd-rom initialization.  This includes
    allocating sense info buffers and srb s-lists, reading drive capacity
    and setting up Media Change Notification (autorun).

    This routine will not clean up allocate resources if it fails - that
    is left for device stop/removal

Arguments:

    Fdo - a pointer to the functional device object for this device

Return Value:

    status

--*/

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
    PCLASS_DRIVER_EXTENSION driverExtension = ClassGetDriverExtension(
                                                Fdo->DriverObject);

    PVOID senseData = NULL;

    ULONG timeOut;
    PCDROM_DATA cddata = (PCDROM_DATA)(commonExtension->DriverData);

    BOOLEAN changerDevice;
    BOOLEAN isMmcDevice = FALSE;

    ULONG bps;
    ULONG lastBit;


    NTSTATUS status;

    PAGED_CODE();

    //
    // Build the lookaside list for srb's for the physical disk.  Should only
    // need a couple.
    //

    ClassInitializeSrbLookasideList(&(fdoExtension->CommonExtension),
                                    CDROM_SRB_LIST_SIZE);

    //
    // Allocate request sense buffer.
    //

    senseData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
                                      SENSE_BUFFER_SIZE,
                                      CDROM_TAG_SENSE_INFO);

    if (senseData == NULL) {

        //
        // The buffer cannot be allocated.
        //

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CdRomInitDeviceExit;
    }

    //
    // Set the sense data pointer in the device extension.
    //

    fdoExtension->SenseData = senseData;

    //
    // CDROMs are not partitionable so starting offset is 0.
    //

    commonExtension->StartingOffset.LowPart = 0;
    commonExtension->StartingOffset.HighPart = 0;

    //
    // Set timeout value in seconds.
    //

    timeOut = ClassQueryTimeOutRegistryValue(Fdo);
    if ((timeOut != 0) && (timeOut <= 30 * 60)) { // 30 minutes
        fdoExtension->TimeOutValue = timeOut;
    } else {
        fdoExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
    }

    //
    // Set up media change support defaults.
    //

    KeInitializeSpinLock(&cddata->DelayedRetrySpinLock);

    cddata->DelayedRetryIrp = NULL;
    cddata->DelayedRetryInterval = 0;
    cddata->Mmc.WriteAllowed = FALSE;

    //
    // Scan for  controllers that require special processing.
    //

    ScanForSpecial(Fdo);

    //
    // Determine if the drive is MMC-Capable
    //

    CdRomIsDeviceMmcDevice(Fdo, &isMmcDevice);

    if (!isMmcDevice) {

        SET_FLAG(Fdo->Characteristics, FILE_READ_ONLY_DEVICE);

    } else {

        //
        // the drive supports at least a subset of MMC commands
        // (and therefore supports READ_CD, etc...)
        //

        cddata->Mmc.IsMmc = TRUE;

        //
        // allocate a buffer for all the capabilities and such
        //

        status = CdRomAllocateMmcResources(Fdo);
        if (!NT_SUCCESS(status)) {
            goto CdRomInitDeviceExit;
        }

        //
        // if the drive supports target defect management and sector-addressable
        // writes, then we should allow writes to the media.
        //

        if (CdRomFindFeaturePage(cddata->Mmc.CapabilitiesBuffer,
                                 cddata->Mmc.CapabilitiesBufferSize,
                                 FeatureDefectManagement) &&
            CdRomFindFeaturePage(cddata->Mmc.CapabilitiesBuffer,
                                 cddata->Mmc.CapabilitiesBufferSize,
                                 FeatureRandomWritable)) {

            //
            // the drive is target defect managed, and supports random writes
            // on sector-aligment.  allow writes to occur by setting the error
            // handler to point to a private media change detection handler.
            //

            KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures,
                       "Found a WRITE capable device: %p\n", Fdo));

            //
            // the write specific pages have been found --
            // set the error handler and set it to require an update!
            //

            cddata->Mmc.UpdateState = CdromMmcUpdateRequired;
            cddata->ErrorHandler = CdRomMmcErrorHandler;

        }

        //
        // ISSUE-2000/4/4-henrygab - mmc-compliant compliant drives should
        //                           be initialized based upon reported
        //                           capabilities, such as CSS, Analogue Audio,
        //                           READ_CD capabilities, and (possibly) even
        //                           drive capacity information.
        //

        TraceLog((CdromDebugWarning,
                  "Defaulting to READ_CD because device %p is MMC compliant\n",
                  Fdo));
        SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
        SET_FLAG(cddata->XAFlags, XA_USE_READ_CD);

    }


    //
    // Set the default geometry for the cdrom to match what NT 4 used.
    // Classpnp will use these values to compute the cylinder count rather
    // than using it's NT 5.0 defaults.
    //

    fdoExtension->DiskGeometry.TracksPerCylinder = 0x40;
    fdoExtension->DiskGeometry.SectorsPerTrack = 0x20;

    //
    // Do READ CAPACITY. This SCSI command returns the last sector address
    // on the device and the bytes per sector. These are used to calculate
    // the drive capacity in bytes.
    //
    // NOTE: This should be change to send the Srb synchronously, then
    // call CdRomInterpretReadCapacity() to properly setup the defaults.
    //

    status = ClassReadDriveCapacity(Fdo);

    bps = fdoExtension->DiskGeometry.BytesPerSector;

    if (!NT_SUCCESS(status) || !bps) {

        TraceLog((CdromDebugWarning,
                    "CdRomStartDevice: Can't read capacity for device %wZ\n",
                    &(fdoExtension->CommonExtension.DeviceName)));

        //
        // Set disk geometry to default values (per ISO 9660).
        //

        bps = 2048;
        fdoExtension->SectorShift = 11;
        commonExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);

    } else {

        //
        // Insure that bytes per sector is a power of 2
        // This corrects a problem with the HP 4020i CDR where it
        // returns an incorrect number for bytes per sector.
        //

        lastBit = (ULONG) -1;
        while (bps) {
            lastBit++;
            bps = bps >> 1;
        }

        bps = 1 << lastBit;
    }
    fdoExtension->DiskGeometry.BytesPerSector = bps;
    TraceLog((CdromDebugTrace, "CdRomInitDevice: Calc'd bps = %x\n", bps));


    ClassInitializeMediaChangeDetection(fdoExtension, "CdRom");


    //
    // test for audio read capabilities
    //

    TraceLog((CdromDebugWarning,
              "Detecting XA_READ capabilities\n"));

    if (CdRomGetDeviceType(Fdo) == FILE_DEVICE_DVD) {

        TraceLog((CdromDebugWarning,
                    "CdRomInitDevice: DVD Devices require START_UNIT\n"));


        //
        // all DVD devices must support the READ_CD command
        //

        TraceLog((CdromDebugWarning,
                    "CdRomDetermineRawReadCapabilities: DVD devices "
                    "support READ_CD command for FDO %p\n", Fdo));
        SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
        SET_FLAG(cddata->XAFlags, XA_USE_READ_CD);


        status = STATUS_SUCCESS;

    } else if ((fdoExtension->DeviceDescriptor->BusType != BusTypeScsi)  &&
               (fdoExtension->DeviceDescriptor->BusType != BusTypeAta)   &&
               (fdoExtension->DeviceDescriptor->BusType != BusTypeAtapi) &&
               (fdoExtension->DeviceDescriptor->BusType != BusTypeUnknown)
               ) {

        //
        // devices on the newer busses must support READ_CD command

⌨️ 快捷键说明

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