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

📄 autorun.c

📁 This is the library for all storage drivers. It simplifies writing a storage driver by implementing
💻 C
📖 第 1 页 / 共 5 页
字号:

    /*
     *  Cache our device object in the extra top IRP stack location
     *  so we have it in our completion routine.
     */
    irpStack = IoGetCurrentIrpStackLocation(irp);
    irpStack->DeviceObject = FdoExtension->DeviceObject;

    //
    // If the irp is sent down when the volume needs to be
    // verified, CdRomUpdateGeometryCompletion won't complete
    // it since it's not associated with a thread.  Marking
    // it to override the verify causes it always be sent
    // to the port driver
    //

    irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;

    nextIrpStack = IoGetNextIrpStackLocation(irp);
    nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextIrpStack->Parameters.Scsi.Srb = &(Info->MediaChangeSrb);

    //
    // Prepare the SRB for execution.
    //

    srb    = nextIrpStack->Parameters.Scsi.Srb;
    buffer = Info->SenseBuffer;
    RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
    RtlZeroMemory(buffer, SENSE_BUFFER_SIZE);

    srb->QueueTag        = SP_UNTAGGED;
    srb->QueueAction     = SRB_SIMPLE_TAG_REQUEST;
    srb->Length          = sizeof(SCSI_REQUEST_BLOCK);
    srb->Function        = SRB_FUNCTION_EXECUTE_SCSI;
    srb->SenseInfoBuffer = buffer;
    srb->SrbStatus       = 0;
    srb->ScsiStatus      = 0;
    srb->OriginalRequest = irp;
    srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;

    srb->SrbFlags        = FdoExtension->SrbFlags;
    SET_FLAG(srb->SrbFlags, Info->SrbFlags);

    srb->TimeOutValue = FdoExtension->TimeOutValue * 2;

    if (srb->TimeOutValue == 0) {

        if (FdoExtension->TimeOutValue == 0) {

            KdPrintEx((DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
                       "ClassSendTestUnitIrp: FdoExtension->TimeOutValue "
                       "is set to zero?! -- resetting to 10\n"));
            srb->TimeOutValue = 10 * 2;  // reasonable default

        } else {

            KdPrintEx((DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
                       "ClassSendTestUnitIrp: Someone set "
                       "srb->TimeOutValue to zero?! -- resetting to %x\n",
                       FdoExtension->TimeOutValue * 2));
            srb->TimeOutValue = FdoExtension->TimeOutValue * 2;

        }

    }

    if (!UseGesn) {

        srb->CdbLength = 6;
        srb->DataTransferLength = 0;
        SET_FLAG(srb->SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER);
        nextIrpStack->Parameters.DeviceIoControl.IoControlCode =
                IOCTL_SCSI_EXECUTE_NONE;
        srb->DataBuffer = NULL;
        srb->DataTransferLength = 0;
        irp->MdlAddress = NULL;

        cdb = (PCDB) &srb->Cdb[0];
        cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;

    } else {

        ASSERT(Info->Gesn.Buffer);

        srb->TimeOutValue = GESN_TIMEOUT_VALUE; // much shorter timeout for GESN

        srb->CdbLength = 10;
        SET_FLAG(srb->SrbFlags, SRB_FLAGS_DATA_IN);
        nextIrpStack->Parameters.DeviceIoControl.IoControlCode =
                IOCTL_SCSI_EXECUTE_IN;
        srb->DataBuffer = Info->Gesn.Buffer;
        srb->DataTransferLength = Info->Gesn.BufferSize;
        irp->MdlAddress = Info->Gesn.Mdl;

        cdb = (PCDB) &srb->Cdb[0];
        cdb->GET_EVENT_STATUS_NOTIFICATION.OperationCode =
            SCSIOP_GET_EVENT_STATUS;
        cdb->GET_EVENT_STATUS_NOTIFICATION.Immediate = 1;
        cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[0] =
            (UCHAR)((Info->Gesn.BufferSize) >> 8);
        cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[1] =
            (UCHAR)((Info->Gesn.BufferSize) & 0xff);
        cdb->GET_EVENT_STATUS_NOTIFICATION.NotificationClassRequest =
            Info->Gesn.EventMask;

    }

    IoSetCompletionRoutine(irp,
                           ClasspMediaChangeDetectionCompletion,
                           srb,
                           TRUE,
                           TRUE,
                           TRUE);

    return irp;

}

/*++////////////////////////////////////////////////////////////////////////////

ClasspSendMediaStateIrp() - ISSUE-2000/02/20-henrygab - not documented

Routine Description:

    This routine

Arguments:

    DeviceObject -
    Irp -

Return Value:

--*/
VOID
ClasspSendMediaStateIrp(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
    IN PMEDIA_CHANGE_DETECTION_INFO Info,
    IN ULONG CountDown
    )
{
    BOOLEAN requestPending = FALSE;
    LONG irpInUse;
    LARGE_INTEGER zero;
    NTSTATUS status;

    DBGTRACE(ClassDebugMCN, ("> ClasspSendMediaStateIrp"));

    if (((FdoExtension->CommonExtension.CurrentState != IRP_MN_START_DEVICE) ||
         (FdoExtension->DevicePowerState != PowerDeviceD0)
         ) &&
        (!Info->MediaChangeIrpLost)) {

        //
        // the device may be stopped, powered down, or otherwise queueing io,
        // so should not timeout the autorun irp (yet) -- set to zero ticks.
        // scattered code relies upon this to not prematurely "lose" an
        // autoplay irp that was queued.
        //

        Info->MediaChangeIrpTimeInUse = 0;
    }

    //
    // if the irp is not in use, mark it as such.
    //

    irpInUse = InterlockedCompareExchange(&Info->MediaChangeIrpInUse, 1, 0);

    if (irpInUse) {

        LONG timeInUse;

        timeInUse = InterlockedIncrement(&Info->MediaChangeIrpTimeInUse);

        DebugPrint((ClassDebugMCN, "ClasspSendMediaStateIrp: irp in use for "
                    "%x seconds when synchronizing for MCD\n", timeInUse));

        if (Info->MediaChangeIrpLost == FALSE) {

            if (timeInUse > MEDIA_CHANGE_TIMEOUT_TIME) {

                //
                // currently set to five minutes.  hard to imagine a drive
                // taking that long to spin up.
                //

                DebugPrint((ClassDebugError,
                            "CdRom%d: Media Change Notification has lost "
                            "it's irp and doesn't know where to find it.  "
                            "Leave it alone and it'll come home dragging "
                            "it's stack behind it.\n",
                            FdoExtension->DeviceNumber));
                Info->MediaChangeIrpLost = TRUE;
            }
        }

        DBGTRACE(ClassDebugMCN, ("< ClasspSendMediaStateIrp - irpInUse"));
        return;

    }

    TRY {

        if (Info->MediaChangeDetectionDisableCount != 0) {
            DebugPrint((ClassDebugTrace, "ClassCheckMediaState: device %p has "
                        " detection disabled \n", FdoExtension->DeviceObject));
            LEAVE;
        }

        if (FdoExtension->DevicePowerState != PowerDeviceD0) {

            if (TEST_FLAG(Info->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE)) {
                DebugPrint((ClassDebugMCN,
                            "ClassCheckMediaState: device %p is powered "
                            "down and flags are set to let it sleep\n",
                            FdoExtension->DeviceObject));
                ClassResetMediaChangeTimer(FdoExtension);
                LEAVE;
            }

            //
            // NOTE: we don't increment the time in use until our power state
            // changes above.  this way, we won't "lose" the autoplay irp.
            // it's up to the lower driver to determine if powering up is a
            // good idea.
            //

            DebugPrint((ClassDebugMCN,
                        "ClassCheckMediaState: device %p needs to powerup "
                        "to handle this io (may take a few extra seconds).\n",
                        FdoExtension->DeviceObject));

        }

        Info->MediaChangeIrpTimeInUse = 0;
        Info->MediaChangeIrpLost = FALSE;

        if (CountDown == 0) {

            PIRP irp;

            DebugPrint((ClassDebugTrace,
                        "ClassCheckMediaState: timer expired\n"));

            if (Info->MediaChangeDetectionDisableCount != 0) {
                DebugPrint((ClassDebugTrace,
                            "ClassCheckMediaState: detection disabled\n"));
                LEAVE;
            }

            //
            // Prepare the IRP for the test unit ready
            //

            irp = ClasspPrepareMcnIrp(FdoExtension,
                                      Info,
                                      Info->Gesn.Supported);

            //
            // Issue the request.
            //

            DebugPrint((ClassDebugTrace,
                        "ClasspSendMediaStateIrp: Device %p getting TUR "
                        " irp %p\n", FdoExtension->DeviceObject, irp));

            if (irp == NULL) {
                LEAVE;
            }


            //
            // note: if we send it to the class dispatch routines, there is
            //       a timing window here (since they grab the remove lock)
            //       where we'd be removed. ELIMINATE the window by grabbing
            //       the lock ourselves above and sending it to the lower
            //       device object directly or to the device's StartIo
            //       routine (which doesn't acquire the lock).
            //

            requestPending = TRUE;

            DBGTRACE(ClassDebugMCN, ("  ClasspSendMediaStateIrp - calling IoCallDriver."));
            IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject, irp);
        }

    } FINALLY {

        if(requestPending == FALSE) {
            irpInUse = InterlockedCompareExchange(&Info->MediaChangeIrpInUse, 0, 1);
            #if _MSC_FULL_VER != 13009111        // This compiler always takes the wrong path here.
                ASSERT(irpInUse);
            #endif
        }

    }

    DBGTRACE(ClassDebugMCN, ("< ClasspSendMediaStateIrp"));

    return;
} // end ClasspSendMediaStateIrp()

/*++////////////////////////////////////////////////////////////////////////////

ClassCheckMediaState()

Routine Description:

    This routine is called by the class driver to test for a media change
    condition and/or poll for disk failure prediction.  It should be called
    from the class driver's IO timer routine once per second.

Arguments:

    FdoExtension - the device extension

Return Value:

    none

--*/
VOID
ClassCheckMediaState(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
    LONG countDown;

    if(info == NULL) {
        DebugPrint((ClassDebugTrace,
                    "ClassCheckMediaState: detection not enabled\n"));
        return;
    }

    //
    // Media change support is active and the IRP is waiting. Decrement the
    // timer.  There is no MP protection on the timer counter.  This code
    // is the only code that will manipulate the timer counter and only one
    // instance of it should be running at any given time.
    //

    countDown = InterlockedDecrement(&(info->MediaChangeCountDown));

    //
    // Try to acquire the media change event.  If we can't do it immediately
    // then bail out and assume the caller will try again later.
    //
    ClasspSendMediaStateIrp(FdoExtension,
                            info,
                            countDown);

    return;
} // end ClassCheckMediaState()

/*++////////////////////////////////////////////////////////////////////////////

ClassResetMediaChangeTimer()

Routine Description:

    Resets the media change count down timer to the default number of seconds.

Arguments:

    FdoExtension - the device to reset the timer for

Return Value:

    None

--*/
VOID
ClassResetMediaChangeTimer(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
    )
{
    PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;

    if(info != NULL) {
        InterlockedExchange(&(info->MediaChangeCountDown),
                            MEDIA_CHANGE_DEFAULT_TIME);
    }
    return;
} // end ClassResetMediaChangeTimer()

/*++////////////////////////////////////////////////////////////////////////////

ClasspInitializePolling() - ISSUE-2000/02/20-henrygab - not documented

Routine Description:

    This routine

⌨️ 快捷键说明

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