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

📄 autorun.c

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

    } // end if (info->Gesn.HackEventMask)

    dataLength =
        (Header->EventDataLength[0] << 8) |
        (Header->EventDataLength[1] & 0xff);
    dataLength -= 2;
    requiredLength = 4; // all events are four bytes

    if (dataLength < requiredLength) {
        KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugWarning,
                   "Classpnp => GESN returned only %x bytes data for fdo %p\n",
                   dataLength, FdoExtension->DeviceObject));

        return STATUS_DEVICE_PROTOCOL_ERROR;
    }
    if (dataLength != requiredLength) {
        KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugWarning,
                   "Classpnp => GESN returned too many (%x) bytes data for fdo %p\n",
                   dataLength, FdoExtension->DeviceObject));
        dataLength = 4;
    }

    if ((Header->ClassEventData[0] & 0xf) == 0)
    {
        // a zero event is a "no change event, so do not retry
        return status;
    }

    // because a event other than "no change" occurred,
    // we should immediately resend this request.
    *ResendImmediately = TRUE;


/*
    ClasspSendNotification(FdoExtension,
                           &GUID_IO_GENERIC_GESN_EVENT,
                           sizeof(NOTIFICATION_EVENT_STATUS_HEADER) + dataLength,
                           Header)
*/



    switch (Header->NotificationClass) {

    case NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS: { // 0x01

        PNOTIFICATION_OPERATIONAL_STATUS opChangeInfo =
            (PNOTIFICATION_OPERATIONAL_STATUS)(Header->ClassEventData);
        ULONG event;

        if (opChangeInfo->OperationalEvent == NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED) {
            break;
        }

        event = (opChangeInfo->Operation[0] << 8) |
                (opChangeInfo->Operation[1]     ) ;

        if ((event == NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED) |
            (event == NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE)) {

            KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugMCN,
                       "Classpnp => GESN says features added/changedfor fdo %p\n",
                       FdoExtension->DeviceObject));

            // don't notify that new media arrived, just set the
            // DO_VERIFY to force a FS reload.

            if (TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
                          FILE_REMOVABLE_MEDIA) &&
                (ClassGetVpb(FdoExtension->DeviceObject) != NULL) &&
                (ClassGetVpb(FdoExtension->DeviceObject)->Flags & VPB_MOUNTED)
                ) {

                SET_FLAG(FdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);

            }

            //
            // If there is a class specific error handler, call it with
            // a "fake" media change error in case it needs to update
            // internal structures as though a media change occurred.
            //

            if (FdoExtension->CommonExtension.DevInfo->ClassError != NULL) {

                SCSI_REQUEST_BLOCK srb = {0};
                SENSE_DATA sense = {0};
                NTSTATUS tempStatus;
                BOOLEAN retry;

                tempStatus = STATUS_MEDIA_CHANGED;
                retry = FALSE;

                srb.CdbLength = 6;
                srb.Length    = sizeof(SCSI_REQUEST_BLOCK);
                srb.SrbStatus = SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_ERROR;
                srb.SenseInfoBuffer = &sense;
                srb.SenseInfoBufferLength = sizeof(SENSE_DATA);

                sense.AdditionalSenseLength = sizeof(SENSE_DATA) -
                    RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength);

                sense.SenseKey = SCSI_SENSE_UNIT_ATTENTION;
                sense.AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;

                FdoExtension->CommonExtension.DevInfo->ClassError(FdoExtension->DeviceObject,
                                                                  &srb,
                                                                  &tempStatus,
                                                                  &retry);
            } // end class error handler

        }
        break;
    }

    case NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS: { // 0x3

        PNOTIFICATION_EXTERNAL_STATUS externalInfo =
            (PNOTIFICATION_EXTERNAL_STATUS)(Header->ClassEventData);
        DEVICE_EVENT_EXTERNAL_REQUEST externalData = {0};

        //
        // unfortunately, due to time constraints, we will only notify
        // about keys being pressed, and not released.  this makes keys
        // single-function, but simplifies the code significantly.
        //

        if (externalInfo->ExternalEvent != NOTIFICATION_EXTERNAL_EVENT_BUTTON_DOWN) {
            break;
        }

        KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugMCN,
                   "Classpnp => GESN::EXTERNAL: Event: %x Status %x Req %x\n",
                   externalInfo->ExternalEvent, externalInfo->ExternalStatus,
                   (externalInfo->Request[0] << 8) | externalInfo->Request[1]
                   ));

        externalData.Version = 1;
        externalData.DeviceClass = 0;
        externalData.ButtonStatus = externalInfo->ExternalEvent;
        externalData.Request =
            (externalInfo->Request[0] << 8) |
            (externalInfo->Request[1] & 0xff);
        KeQuerySystemTime(&(externalData.SystemTime));
        externalData.SystemTime.QuadPart *= (LONGLONG)KeQueryTimeIncrement();

        DBGTRACE(ClassDebugTrace, ("ClasspInterpretGesnData: media DEVICE_EXTERNAL_REQUEST"));
        ClasspSendNotification(FdoExtension,
                               &GUID_IO_DEVICE_EXTERNAL_REQUEST,
                               sizeof(DEVICE_EVENT_EXTERNAL_REQUEST),
                               &externalData);
        return status;
    }

    case NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS: { // 0x4

        PNOTIFICATION_MEDIA_STATUS mediaInfo =
            (PNOTIFICATION_MEDIA_STATUS)(Header->ClassEventData);

        KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugMCN,
                   "Classpnp => GESN::MEDIA: Event: %x Status %x\n",
                   mediaInfo->MediaEvent, mediaInfo->MediaStatus));

        if ((mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_NEW_MEDIA) ||
            (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE)) {


            if (TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
                          FILE_REMOVABLE_MEDIA) &&
                (ClassGetVpb(FdoExtension->DeviceObject) != NULL) &&
                (ClassGetVpb(FdoExtension->DeviceObject)->Flags & VPB_MOUNTED)
                ) {

                SET_FLAG(FdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);

            }
            InterlockedIncrement(&FdoExtension->MediaChangeCount);
            ClasspSetMediaChangeStateEx(FdoExtension,
                                        MediaPresent,
                                        FALSE,
                                        TRUE);

        } else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL) {

            ClasspSetMediaChangeStateEx(FdoExtension,
                                        MediaNotPresent,
                                        FALSE,
                                        TRUE);

        } else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST) {

            KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugError,
                       "Classpnp => GESN Ejection request received!\n"));
            ClassSendEjectionNotification(FdoExtension);

        }
        break;

    }

    case NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS: { // lowest priority events...

        PNOTIFICATION_BUSY_STATUS busyInfo =
            (PNOTIFICATION_BUSY_STATUS)(Header->ClassEventData);
        DEVICE_EVENT_BECOMING_READY busyData = {0};

        //
        // NOTE: we never actually need to immediately retry for these
        //       events: if one exists, the device is busy, and if not,
        //       we still don't want to retry.
        //

        *ResendImmediately = FALSE;

        //
        // else we want to report the approximated time till it's ready.
        //

        busyData.Version = 1;
        busyData.Reason = busyInfo->DeviceBusyStatus;
        busyData.Estimated100msToReady = (busyInfo->Time[0] << 8) |
                                         (busyInfo->Time[1] & 0xff);

        KdPrintEx((DPFLTR_CLASSPNP_ID, ClassDebugMCN,
                   "Classpnp => GESN::BUSY: Event: %x Status %x Time %x\n",
                   busyInfo->DeviceBusyEvent, busyInfo->DeviceBusyStatus,
                   busyData.Estimated100msToReady
                   ));

        //
        // Ignore the notification if the time is small
        //
        if (busyData.Estimated100msToReady < GESN_DEVICE_BUSY_LOWER_THRESHOLD_MS) {
            break;
        }


        DBGTRACE(ClassDebugTrace, ("ClasspInterpretGesnData: media BECOMING_READY"));
        ClasspSendNotification(FdoExtension,
                               &GUID_IO_DEVICE_BECOMING_READY,
                               sizeof(DEVICE_EVENT_BECOMING_READY),
                               &busyData);
        break;
    }

    default: {

        break;

    }

    } // end switch on notification class
    return status;
}

/*++////////////////////////////////////////////////////////////////////////////

ClasspInternalSetMediaChangeState()

Routine Description:

    This routine will (if appropriate) set the media change event for the
    device.  The event will be set if the media state is changed and
    media change events are enabled.  Otherwise the media state will be
    tracked but the event will not be set.

    This routine will lock out the other media change routines if possible
    but if not a media change notification may be lost after the enable has
    been completed.

Arguments:

    FdoExtension - the device

    MediaPresent - indicates whether the device has media inserted into it
                   (TRUE) or not (FALSE).

Return Value:

    none

--*/
VOID
ClasspInternalSetMediaChangeState(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
    IN MEDIA_CHANGE_DETECTION_STATE NewState,
    IN BOOLEAN KnownStateChange // can ignore oldstate == unknown
    )
{
#if DBG
    PUCHAR states[] = {"Unknown", "Present", "Not Present", "Unavailable"};
#endif
    MEDIA_CHANGE_DETECTION_STATE oldMediaState;
    PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
    CLASS_MEDIA_CHANGE_CONTEXT mcnContext;
    NTSTATUS status;
    ASSERT((NewState >= MediaUnknown) && (NewState <= MediaUnavailable));

    if(info == NULL) {
        return;
    }

    oldMediaState = InterlockedExchange(
        (PLONG)(&info->MediaChangeDetectionState),
        (LONG)NewState);

    if((oldMediaState == MediaUnknown) && (!KnownStateChange)) {

        //
        // The media was in an indeterminate state before - don't notify for
        // this change.
        //

        DebugPrint((ClassDebugMCN,
                    "ClassSetMediaChangeState: State was unknown - this may "
                    "not be a change\n"));
        return;

    } else if(oldMediaState == NewState) {

        //
        // Media is in the same state it was before.
        //

        return;
    }

    if(info->MediaChangeDetectionDisableCount != 0) {

        DBGTRACE(ClassDebugMCN,
                    ("ClassSetMediaChangeState: MCN not enabled, state "
                    "changed from %s to %s\n",
                    states[oldMediaState], states[NewState]));
        return;

    }

    DBGTRACE(ClassDebugMCN,
                ("ClassSetMediaChangeState: State change from %s to %s\n",
                states[oldMediaState], states[NewState]));

    //
    // make the data useful -- it used to always be zero.
    //
    mcnContext.MediaChangeCount = FdoExtension->MediaChangeCount;
    mcnContext.NewState = NewState;

    if (NewState == MediaPresent) {

        DBGTRACE(ClassDebugTrace, ("ClasspInternalSetMediaChangeState: media ARRIVAL"));
        ClasspSendNotification(FdoExtension,
                               &GUID_IO_MEDIA_ARRIVAL,
                               sizeof(CLASS_MEDIA_CHANGE_CONTEXT),
                               &mcnContext);

    }
    else if ((NewState == MediaNotPresent) || (NewState == MediaUnavailable)) {

        DBGTRACE(ClassDebugTrace, ("ClasspInternalSetMediaChangeState: media REMOVAL"));
        ClasspSendNotification(FdoExtension,
                               &GUID_IO_MEDIA_REMOVAL,
                               sizeof(CLASS_MEDIA_CHANGE_CONTEXT),
                               &mcnContext);

    } else {

        //
        // Don't notify of changed going to unknown.
        //

        return;
    }

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

ClassSetMediaChangeState()

Routine Description:

    This routine will (if appropriate) set the media change event for the
    device.  The event will be set if the media state is changed and
    media change events are enabled.  Otherwise the media state will be
    tracked but the event will not be set.

    This routine will lock out the other media change routines if possible
    but if not a media change notification may be lost after the enable has
    been completed.

Arguments:

    FdoExtension - the device

⌨️ 快捷键说明

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