ReactOS 0.4.15-dev-7906-g1b85a5f
autorun.c File Reference
#include "classp.h"
#include "debug.h"
Include dependency graph for autorun.c:

Go to the source code of this file.

Macros

#define GESN_TIMEOUT_VALUE   (0x4)
 
#define GESN_BUFFER_SIZE   (0x8)
 
#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS   (2)
 
#define MAXIMUM_IMMEDIATE_MCN_RETRIES   (0x20)
 
#define MCN_REG_SUBKEY_NAME   (L"MediaChangeNotification")
 
#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME   (L"AlwaysDisableMCN")
 
#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME   (L"AlwaysEnableMCN")
 
#define TICK_TIMER_PERIOD_IN_MSEC   1000
 
#define TICK_TIMER_DELAY_IN_MSEC   1000
 

Functions

static BOOLEAN ClasspCanSendPollingIrp (_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension)
 
BOOLEAN ClasspIsMediaChangeDisabledDueToHardwareLimitation (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PUNICODE_STRING RegistryPath)
 
NTSTATUS ClasspMediaChangeDeviceInstanceOverride (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, OUT PBOOLEAN Enabled)
 
BOOLEAN ClasspIsMediaChangeDisabledForClass (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PUNICODE_STRING RegistryPath)
 
VOID ClasspSetMediaChangeStateEx (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN Wait, IN BOOLEAN KnownStateChange)
 
VOID ClasspSendMediaStateIrp (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN ULONG CountDown)
 
NTSTATUS ClasspInitializePolling (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN BOOLEAN AllowDriveToSleep)
 
VOID ClassSendEjectionNotification (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
 _IRQL_requires_max_ (DISPATCH_LEVEL)
 
NTSTATUS ClasspInterpretGesnData (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PNOTIFICATION_EVENT_STATUS_HEADER Header, OUT PBOOLEAN ResendImmediately)
 
VOID ClasspInternalSetMediaChangeState (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN KnownStateChange)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
NTSTATUS NTAPI ClasspMediaChangeDetectionCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
 
PIRP ClasspPrepareMcnIrp (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
 
VOID NTAPI ClassCheckMediaState (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID NTAPI ClassResetMediaChangeTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspInitializeGesn (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info)
 
VOID NTAPI ClasspDisableGesn (IN PDEVICE_OBJECT Fdo, IN PVOID Context)
 
NTSTATUS ClasspMcnControl (IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb)
 
 _Function_class_ (RTL_QUERY_REGISTRY_ROUTINE)
 
VOID ClasspTimerTickEx (_In_ PEX_TIMER Timer, _In_opt_ PVOID Context)
 
 _Function_class_ (KDEFERRED_ROUTINE)
 
BOOLEAN ClasspUpdateTimerNoWakeTolerance (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
NTSTATUS ClasspInitializeTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspDeleteTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspEnableTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID ClasspDisableTimer (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 
VOID NTAPI ClasspFailurePredict (IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
 
BOOLEAN ClasspFailurePredictionPeriodMissed (_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
 

Variables

const GUID StoragePredictFailureEventGuid = WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID
 
RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack
 
IO_WORKITEM_ROUTINE ClasspFailurePredict
 
IO_WORKITEM_ROUTINE ClasspDisableGesn
 
IO_COMPLETION_ROUTINE ClasspMediaChangeDetectionCompletion
 
KDEFERRED_ROUTINE ClasspTimerTick
 
EXT_CALLBACK ClasspTimerTickEx
 
BOOLEAN ClasspScreenOff = FALSE
 
ULONG BreakOnMcnDisable = FALSE
 

Macro Definition Documentation

◆ GESN_BUFFER_SIZE

#define GESN_BUFFER_SIZE   (0x8)

Definition at line 32 of file autorun.c.

◆ GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS

#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS   (2)

Definition at line 33 of file autorun.c.

◆ GESN_TIMEOUT_VALUE

#define GESN_TIMEOUT_VALUE   (0x4)

Definition at line 31 of file autorun.c.

◆ MAXIMUM_IMMEDIATE_MCN_RETRIES

#define MAXIMUM_IMMEDIATE_MCN_RETRIES   (0x20)

Definition at line 35 of file autorun.c.

◆ MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME

#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME   (L"AlwaysDisableMCN")

Definition at line 37 of file autorun.c.

◆ MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME

#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME   (L"AlwaysEnableMCN")

Definition at line 38 of file autorun.c.

◆ MCN_REG_SUBKEY_NAME

#define MCN_REG_SUBKEY_NAME   (L"MediaChangeNotification")

Definition at line 36 of file autorun.c.

◆ TICK_TIMER_DELAY_IN_MSEC

#define TICK_TIMER_DELAY_IN_MSEC   1000

Definition at line 130 of file autorun.c.

◆ TICK_TIMER_PERIOD_IN_MSEC

#define TICK_TIMER_PERIOD_IN_MSEC   1000

Definition at line 129 of file autorun.c.

Function Documentation

◆ _Function_class_() [1/2]

_Function_class_ ( KDEFERRED_ROUTINE  )

Definition at line 3496 of file autorun.c.

3509{
3511 PCOMMON_DEVICE_EXTENSION commonExtension;
3513 ULONG isRemoved;
3514
3518
3519 NT_ASSERT(fdoExtension != NULL);
3520 _Analysis_assume_(fdoExtension != NULL);
3521
3522 commonExtension = &fdoExtension->CommonExtension;
3523 DeviceObject = fdoExtension->DeviceObject;
3524 NT_ASSERT(commonExtension->IsFdo);
3525
3526 //
3527 // Do any media change work
3528 //
3529#ifdef _MSC_VER
3530#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
3531#endif
3533
3534 //
3535 // We stop the timer before deleting the device. It's safe to keep going
3536 // if the flag value is REMOVE_PENDING because the removal thread will be
3537 // blocked trying to stop the timer.
3538 //
3539
3540 NT_ASSERT(isRemoved != REMOVE_COMPLETE);
3541
3542 //
3543 // This routine is reasonably safe even if the device object has a pending
3544 // remove
3545
3546 if (!isRemoved) {
3547
3549
3550 //
3551 // Do any media change detection work
3552 //
3553
3554 if ((fdoExtension->MediaChangeDetectionInfo != NULL) &&
3555 (fdoExtension->FunctionSupportInfo->AsynchronousNotificationSupported == FALSE)) {
3556
3557 ClassCheckMediaState(fdoExtension);
3558
3559 }
3560
3561 //
3562 // Do any failure prediction work
3563 //
3564 if ((info != NULL) && (info->Method != FailurePredictionNone)) {
3565
3566 ULONG countDown;
3567
3568 if (ClasspCanSendPollingIrp(fdoExtension)) {
3569
3570 //
3571 // Synchronization is not required here since the Interlocked
3572 // locked instruction guarantees atomicity. Other code that
3573 // resets CountDown uses InterlockedExchange which is also
3574 // atomic.
3575 //
3576 countDown = InterlockedDecrement((volatile LONG *)&info->CountDown);
3577 if (countDown == 0) {
3578
3579 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspTimerTick: Send FP irp for %p\n",
3580 DeviceObject));
3581
3582 if(info->WorkQueueItem == NULL) {
3583
3584 info->WorkQueueItem =
3585 IoAllocateWorkItem(fdoExtension->DeviceObject);
3586
3587 if(info->WorkQueueItem == NULL) {
3588
3589 //
3590 // Set the countdown to one minute in the future.
3591 // we'll try again then in the hopes there's more
3592 // free memory.
3593 //
3594
3595 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClassTimerTick: Couldn't allocate "
3596 "item - try again in one minute\n"));
3597 InterlockedExchange((volatile LONG *)&info->CountDown, 60);
3598
3599 } else {
3600
3601 //
3602 // Grab the remove lock so that removal will block
3603 // until the work item is done.
3604 //
3605
3607 info->WorkQueueItem);
3608
3609 IoQueueWorkItem(info->WorkQueueItem,
3612 info);
3613 }
3614
3615 } else {
3616
3617 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspTimerTick: Failure "
3618 "Prediction work item is "
3619 "already active for device %p\n",
3620 DeviceObject));
3621
3622 }
3623 } // end (countdown == 0)
3624
3625 } else {
3626 //
3627 // If device is sleeping then just rearm polling timer
3628 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassTimerTick, SHHHH!!! device is %p is sleeping\n",
3629 DeviceObject));
3630 }
3631
3632 } // end failure prediction polling
3633
3634 //
3635 // Give driver a chance to do its own specific work
3636 //
3637
3638 if (commonExtension->DriverExtension->InitData.ClassTick != NULL) {
3639
3641
3642 } // end device specific tick handler
3643 } // end check for removed
3644
3645#ifdef _MSC_VER
3646#pragma warning(suppress:4054) // okay to type cast function pointer to PIRP for this use case
3647#endif
3649} // end ClasspTimerTick()
#define InterlockedExchange
Definition: armddk.h:54
#define InterlockedDecrement
Definition: armddk.h:52
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
static BOOLEAN ClasspCanSendPollingIrp(_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension)
Definition: autorun.c:61
IO_WORKITEM_ROUTINE ClasspFailurePredict
Definition: autorun.c:105
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
#define REMOVE_COMPLETE
Definition: classpnp.h:98
@ FailurePredictionNone
Definition: classpnp.h:234
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
long LONG
Definition: pedump.c:60
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
PCLASS_TICK ClassTick
Definition: classpnp.h:545
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
uint32_t ULONG
Definition: typedefs.h:59
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
@ DelayedWorkQueue
Definition: extypes.h:190
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
#define NT_ASSERT
Definition: rtlfuncs.h:3310

◆ _Function_class_() [2/2]

_Function_class_ ( RTL_QUERY_REGISTRY_ROUTINE  )

Definition at line 3380 of file autorun.c.

3393{
3394 PULONG valueFound;
3395 PUNICODE_STRING deviceString;
3396 PWSTR keyValue;
3397
3398 PAGED_CODE();
3400
3401 if (ValueData == NULL ||
3402 Context == NULL ||
3403 EntryContext == NULL) {
3405 }
3406
3407 //
3408 // if we have already set the value to true, exit
3409 //
3410
3411 valueFound = EntryContext;
3412 if ((*valueFound) != 0) {
3413 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMcnRegCB: already set to true\n"));
3414 return STATUS_SUCCESS;
3415 }
3416
3417 if (ValueLength == sizeof(WCHAR)) {
3418 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspMcnRegCB: NULL string should "
3419 "never be passed to registry call-back!\n"));
3420 return STATUS_SUCCESS;
3421 }
3422
3423
3424 //
3425 // if the data is not a terminated string, exit
3426 //
3427
3428 if (ValueType != REG_SZ) {
3429 return STATUS_SUCCESS;
3430 }
3431
3432 deviceString = Context;
3433 keyValue = ValueData;
3434 ValueLength -= sizeof(WCHAR); // ignore the null character
3435
3436 //
3437 // do not compare more memory than is in deviceString
3438 //
3439
3440 if (ValueLength > deviceString->Length) {
3441 ValueLength = deviceString->Length;
3442 }
3443
3444 //
3445 // if the strings match, disable autorun
3446 //
3447
3448 if (RtlCompareMemory(deviceString->Buffer, keyValue, ValueLength) == ValueLength) {
3449 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspRegMcnCB: Match found\n"));
3450 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspRegMcnCB: DeviceString at %p\n",
3451 deviceString->Buffer));
3452 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspRegMcnCB: KeyValue at %p\n",
3453 keyValue));
3454 (*valueFound) = TRUE;
3455 }
3456
3457 return STATUS_SUCCESS;
3458} // end ClasspMediaChangeRegistryCallBack()
#define PAGED_CODE()
#define TRUE
Definition: types.h:120
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define REG_SZ
Definition: layer.c:22
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4207
#define STATUS_SUCCESS
Definition: shellext.h:65
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ _IRQL_requires_max_() [1/2]

_IRQL_requires_max_ ( DISPATCH_LEVEL  )

Definition at line 188 of file autorun.c.

197{
199 ULONG requiredSize;
201
202 status = RtlULongAdd((sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) - sizeof(UCHAR)),
204 &requiredSize);
205
206 if (!(NT_SUCCESS(status)) || (requiredSize > 0x0000ffff)) {
207 // MAX_USHORT, max total size for these events!
208 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
209 "Error sending event: size too large! (%x)\n",
210 requiredSize));
211 return;
212 }
213
214 notification = ExAllocatePoolWithTag(NonPagedPoolNx,
215 requiredSize,
216 'oNcS');
217
218 //
219 // if none allocated, exit
220 //
221
222 if (notification == NULL) {
223 return;
224 }
225
226 //
227 // Prepare and send the request!
228 //
229
230 RtlZeroMemory(notification, requiredSize);
231 notification->Version = 1;
232 notification->Size = (USHORT)(requiredSize);
233 notification->FileObject = NULL;
234 notification->NameBufferOffset = -1;
235 notification->Event = *Guid;
236
237 if (ExtraData != NULL && ExtraDataSize != 0) {
238 RtlCopyMemory(notification->CustomDataBuffer, ExtraData, ExtraDataSize);
239 }
240
243 NULL, NULL);
244
246 return;
247}
LONG NTSTATUS
Definition: precomp.h:26
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
_In_ const GUID _In_ ULONG ExtraDataSize
Definition: classpnp.h:1430
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
@ FdoExtension
Definition: precomp.h:48
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned short USHORT
Definition: pedump.c:61
NTSTATUS NTAPI IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure, IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, IN PVOID Context OPTIONAL)
Definition: pnpreport.c:498
Definition: ps.c:97
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
unsigned char UCHAR
Definition: xmlstorage.h:181

◆ _IRQL_requires_max_() [2/2]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 1012 of file autorun.c.

1020{
1022 return;
1023}
VOID ClasspSetMediaChangeStateEx(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN Wait, IN BOOLEAN KnownStateChange)
Definition: autorun.c:950
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170

◆ ClassCheckMediaState()

VOID NTAPI ClassCheckMediaState ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 1752 of file autorun.c.

1755{
1756 PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
1757 LONG countDown;
1758
1759 if(info == NULL) {
1760 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1761 "ClassCheckMediaState: detection not enabled\n"));
1762 return;
1763 }
1764
1765 //
1766 // Media change support is active and the IRP is waiting. Decrement the
1767 // timer. There is no MP protection on the timer counter. This code
1768 // is the only code that will manipulate the timer counter and only one
1769 // instance of it should be running at any given time.
1770 //
1771
1772 countDown = InterlockedDecrement(&(info->MediaChangeCountDown));
1773
1774 //
1775 // Try to acquire the media change event. If we can't do it immediately
1776 // then bail out and assume the caller will try again later.
1777 //
1779 info,
1780 countDown);
1781
1782 return;
1783} // end ClassCheckMediaState()
VOID ClasspSendMediaStateIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN ULONG CountDown)
Definition: autorun.c:1559

Referenced by _Function_class_(), and ClasspStorageEventNotification().

◆ ClasspCanSendPollingIrp()

static BOOLEAN ClasspCanSendPollingIrp ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  fdoExtension)
static

Definition at line 61 of file autorun.c.

64{
65 return ((fdoExtension->DevicePowerState == PowerDeviceD0) &&
66 (fdoExtension->PowerDownInProgress == FALSE) &&
68}
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
@ PowerDeviceD0
Definition: ntpoapi.h:49

Referenced by _Function_class_(), and ClasspFailurePredict().

◆ ClasspDeleteTimer()

VOID ClasspDeleteTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3798 of file autorun.c.

3817{
3818 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3819
3820 if (FdoExtension->CommonExtension.IsFdo) {
3821 fdoData = FdoExtension->PrivateFdoData;
3822 if (fdoData != NULL) {
3823#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3824 if (fdoData->TickTimer != NULL) {
3825 EXT_DELETE_PARAMETERS parameters;
3826 ExInitializeDeleteTimerParameters(&parameters);
3827 ExDeleteTimer(fdoData->TickTimer, TRUE, FALSE, &parameters);
3828 fdoData->TickTimer = NULL;
3829 }
3830#endif
3831 fdoData->TimerInitialized = FALSE;
3832 fdoData->TickTimerEnabled = FALSE;
3833 }
3834 }
3835}
BOOLEAN TickTimerEnabled
Definition: classp.h:813
PEX_TIMER TickTimer
Definition: classp.h:676
BOOLEAN TimerInitialized
Definition: classp.h:752
NTKERNELAPI BOOLEAN NTAPI ExDeleteTimer(_In_ PEX_TIMER Timer, _In_ BOOLEAN Cancel, _In_ BOOLEAN Wait, _In_opt_ PEXT_DELETE_PARAMETERS Parameters)

Referenced by ClassPnpStartDevice().

◆ ClasspDisableGesn()

VOID NTAPI ClasspDisableGesn ( IN PDEVICE_OBJECT  Fdo,
IN PVOID  Context 
)

Definition at line 2373 of file autorun.c.

2377{
2378 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
2380
2381 PAGED_CODE();
2382
2383 //
2384 // Set the hack flag in the registry
2385 //
2386 ClassSetDeviceParameter(fdoExtension,
2392}
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: cdromp.h:123
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
@ ClassDetectionUnsupported
Definition: classp.h:446
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:115
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:506

◆ ClasspDisableTimer()

VOID ClasspDisableTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3956 of file autorun.c.

3959{
3960 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3961
3962 if (FdoExtension->CommonExtension.IsFdo) {
3963 fdoData = FdoExtension->PrivateFdoData;
3964 }
3965
3966 if (fdoData && fdoData->TimerInitialized == TRUE) {
3967
3968 //
3969 // we are only going to stop the actual timer in remove device routine
3970 // or when done transitioning to D3 (timer will be started again when
3971 // done transitioning to D0).
3972 //
3973 // it is the responsibility of the code within the timer routine to
3974 // check if the device is removed and not processing io for the final
3975 // call.
3976 // this keeps the code clean and prevents lots of bugs.
3977 //
3978#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3979 NT_ASSERT(fdoData->TickTimer != NULL);
3980 ExCancelTimer(fdoData->TickTimer, NULL);
3981#else
3982 KeCancelTimer(&fdoData->TickTimer);
3983#endif
3984 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspDisableTimer: Periodic tick timer disabled "
3985 "for device %p\n", FdoExtension->DeviceObject));
3986 fdoData->TickTimerEnabled = FALSE;
3987
3988 } else {
3989
3990 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspDisableTimer: Timer never initialized\n"));
3991
3992 }
3993
3994 return;
3995} // end ClasspDisableTimer()
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
NTKERNELAPI BOOLEAN NTAPI ExCancelTimer(_Inout_ PEX_TIMER Timer, _In_opt_ PEXT_CANCEL_PARAMETERS Parameters)

Referenced by ClassDispatchPnp(), and ClasspPowerHandler().

◆ ClasspEnableTimer()

VOID ClasspEnableTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3857 of file autorun.c.

3860{
3861 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3862
3863 if (FdoExtension->CommonExtension.IsFdo) {
3864 fdoData = FdoExtension->PrivateFdoData;
3865 }
3866
3867 if (fdoData != NULL) {
3868 //
3869 // The timer should have already been initialized, but if that's not
3870 // the case it's not the end of the world. We can attempt to
3871 // initialize it now.
3872 //
3873 NT_ASSERT(fdoData->TimerInitialized);
3874 if (fdoData->TimerInitialized == FALSE) {
3877 if (NT_SUCCESS(status) == FALSE) {
3878 return;
3879 }
3880 }
3881
3882#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3883 if (fdoData->TickTimer != NULL) {
3884 EXT_SET_PARAMETERS parameters;
3885 LONGLONG period = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000); // Convert to units of 100ns.
3886 LONGLONG dueTime = period * (-1); // Negative sign indicates dueTime is relative.
3887
3888 ExInitializeSetTimerParameters(&parameters);
3889
3890 //
3891 // Set the no-wake tolerance to "unlimited" if the conditions below
3892 // are met. An "unlimited" no-wake tolerance means that the timer
3893 // will *never* wake the processor if the processor is in a
3894 // low-power state.
3895 // 1. The screen is off.
3896 // 2. The class driver is *not* a consumer of the tick timer (ClassTick is NULL).
3897 // 3. This is a disk device.
3898 // Otherwise the tolerance is set to the normal tolerable delay.
3899 //
3900 if (ClasspScreenOff &&
3901 FdoExtension->CommonExtension.DriverExtension->InitData.ClassTick == NULL &&
3902 FdoExtension->DeviceObject->DeviceType == FILE_DEVICE_DISK) {
3904 } else {
3905 parameters.NoWakeTolerance = TICK_TIMER_DELAY_IN_MSEC * (10 * 1000);
3906 }
3907
3908 fdoData->CurrentNoWakeTolerance = parameters.NoWakeTolerance;
3909
3910 ExSetTimer(fdoData->TickTimer,
3911 dueTime,
3912 period,
3913 &parameters);
3914
3915 fdoData->TickTimerEnabled = TRUE;
3916 } else {
3917 NT_ASSERT(fdoData->TickTimer != NULL);
3918 }
3919#else
3920 //
3921 // Start the periodic tick timer using a coalescable timer with some delay
3922 //
3923 {
3925 timeout.QuadPart = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000) * (-1);
3926 KeSetCoalescableTimer(&fdoData->TickTimer,
3928 &fdoData->TickTimerDpc);
3929 fdoData->TickTimerEnabled = TRUE;
3930 }
3931#endif
3932
3933 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspEnableTimer: Periodic tick timer enabled "
3934 "for device %p\n", FdoExtension->DeviceObject));
3935
3936 }
3937
3938} // end ClasspEnableTimer()
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
#define TICK_TIMER_DELAY_IN_MSEC
Definition: autorun.c:130
#define TICK_TIMER_PERIOD_IN_MSEC
Definition: autorun.c:129
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
LONGLONG CurrentNoWakeTolerance
Definition: classp.h:677
LONGLONG NoWakeTolerance
Definition: extypes.h:286
Definition: dhcpd.h:245
int64_t LONGLONG
Definition: typedefs.h:68
NTKERNELAPI BOOLEAN NTAPI ExSetTimer(_In_ PEX_TIMER Timer, _In_ LONGLONG DueTime, _In_ LONGLONG Period, _In_opt_ PEXT_SET_PARAMETERS Parameters)
#define EX_TIMER_UNLIMITED_TOLERANCE
Definition: exfuncs.h:957
FORCEINLINE VOID ExInitializeSetTimerParameters(_Out_ PEXT_SET_PARAMETERS Parameters)
Definition: exfuncs.h:995

Referenced by ClasspDeviceLockFailurePowerIrpCompletion(), and ClasspPowerUpCompletion().

◆ ClasspFailurePredict()

VOID NTAPI ClasspFailurePredict ( IN PDEVICE_OBJECT  DeviceObject,
IN PVOID  Context 
)

Definition at line 4017 of file autorun.c.

4021{
4022 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
4023 PIO_WORKITEM workItem;
4024 STORAGE_PREDICT_FAILURE checkFailure = {0};
4025 SCSI_ADDRESS scsiAddress = {0};
4027
4029
4030 if (Info == NULL) {
4031 NT_ASSERT(Info != NULL);
4032 return;
4033 }
4034
4035 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "ClasspFailurePredict: Polling for failure\n"));
4036
4037 //
4038 // Mark the work item as inactive and reset the countdown timer. we
4039 // can't risk freeing the work item until we've released the remove-lock
4040 // though - if we do it might get reused as a tag before we can release
4041 // the lock.
4042 //
4043
4044 InterlockedExchange((volatile LONG *)&Info->CountDown, Info->Period);
4045 workItem = InterlockedExchangePointer((volatile PVOID *)&(Info->WorkQueueItem), NULL);
4046
4047 if (ClasspCanSendPollingIrp(fdoExtension)) {
4048
4049 KEVENT event;
4050 PDEVICE_OBJECT topOfStack;
4051 PIRP irp = NULL;
4052 IO_STATUS_BLOCK ioStatus;
4053 NTSTATUS activateStatus = STATUS_UNSUCCESSFUL;
4054
4055 //
4056 // Take an active reference on the device to ensure it is powered up
4057 // while we do the failure prediction query.
4058 //
4059 if (fdoExtension->FunctionSupportInfo->IdlePower.IdlePowerEnabled) {
4060 activateStatus = ClasspPowerActivateDevice(DeviceObject);
4061 }
4062
4064
4066
4067 //
4068 // Send down irp to see if drive is predicting failure
4069 //
4070
4073 topOfStack,
4074 NULL,
4075 0,
4076 &checkFailure,
4078 FALSE,
4079 &event,
4080 &ioStatus);
4081
4082
4083 if (irp != NULL) {
4084
4085
4086 status = IoCallDriver(topOfStack, irp);
4087 if (status == STATUS_PENDING) {
4089 status = ioStatus.Status;
4090 }
4091
4092
4093 } else {
4095 }
4096
4097 if (NT_SUCCESS(status) && (checkFailure.PredictFailure)) {
4098
4099 checkFailure.PredictFailure = 512;
4100
4101 //
4102 // Send down irp to get scsi address
4103 //
4105
4106 RtlZeroMemory(&scsiAddress, sizeof(SCSI_ADDRESS));
4109 topOfStack,
4110 NULL,
4111 0,
4112 &scsiAddress,
4113 sizeof(SCSI_ADDRESS),
4114 FALSE,
4115 &event,
4116 &ioStatus);
4117
4118 if (irp != NULL) {
4119
4120
4121 status = IoCallDriver(topOfStack, irp);
4122 if (status == STATUS_PENDING) {
4124 }
4125
4126 }
4127
4128 ClassNotifyFailurePredicted(fdoExtension,
4129 (PUCHAR)&checkFailure,
4130 sizeof(checkFailure),
4131 (BOOLEAN)(fdoExtension->FailurePredicted == FALSE),
4132 2,
4133 scsiAddress.PathId,
4134 scsiAddress.TargetId,
4135 scsiAddress.Lun);
4136
4137 fdoExtension->FailurePredicted = TRUE;
4138
4139 }
4140
4141 ObDereferenceObject(topOfStack);
4142
4143 //
4144 // Update the failure prediction query time and release the active
4145 // reference.
4146 //
4147
4148 KeQuerySystemTime(&(Info->LastFailurePredictionQueryTime));
4149
4150 if (NT_SUCCESS(activateStatus)) {
4151 ClasspPowerIdleDevice(DeviceObject);
4152 }
4153 }
4154
4156 IoFreeWorkItem(workItem);
4157 return;
4158} // end ClasspFailurePredict()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
struct _FAILURE_PREDICTION_INFO * PFAILURE_PREDICTION_INFO
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
FxIrp * irp
struct _cl_event * event
Definition: glext.h:7739
#define KernelMode
Definition: asm.h:34
#define IOCTL_STORAGE_PREDICT_FAILURE
Definition: ntddstor.h:146
@ SynchronizationEvent
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
UCHAR PathId
Definition: scsi_port.h:149
UCHAR TargetId
Definition: scsi_port.h:150
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
@ Executive
Definition: ketypes.h:415
#define ObDereferenceObject
Definition: obfuncs.h:203

◆ ClasspFailurePredictionPeriodMissed()

BOOLEAN ClasspFailurePredictionPeriodMissed ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 4391 of file autorun.c.

4412{
4413 LARGE_INTEGER currentTime;
4414 LARGE_INTEGER timeDifference;
4415 BOOLEAN missedPeriod = FALSE;
4416
4418 NT_ASSERT(FdoExtension->FailurePredictionInfo);
4419 NT_ASSERT(FdoExtension->FailurePredictionInfo->Method != FailurePredictionNone);
4420
4421 //
4422 // Find the difference between the last failure prediction
4423 // query and the current time and convert it to seconds.
4424 //
4425 KeQuerySystemTime(&currentTime);
4426 timeDifference.QuadPart = currentTime.QuadPart - FdoExtension->FailurePredictionInfo->LastFailurePredictionQueryTime.QuadPart;
4427 timeDifference.QuadPart /= (10LL * 1000LL * 1000LL);
4428
4429 if (timeDifference.QuadPart >= FdoExtension->FailurePredictionInfo->Period) {
4430 missedPeriod = TRUE;
4431 }
4432
4433 return missedPeriod;
4434}
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by _Function_class_(), ClasspDeviceLockFailurePowerIrpCompletion(), and ClasspPowerUpCompletion().

◆ ClasspInitializeGesn()

NTSTATUS ClasspInitializeGesn ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO  Info 
)

Definition at line 1990 of file autorun.c.

1994{
1997 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
1999 PIRP irp;
2000 KEVENT event;
2001 BOOLEAN retryImmediately;
2002 ULONG i;
2003 ULONG atapiResets;
2004 ULONG srbFlags;
2005
2006 PAGED_CODE();
2007 NT_ASSERT(Info == FdoExtension->MediaChangeDetectionInfo);
2008
2009 //
2010 // read if we already know the abilities of the device
2011 //
2012
2013 ClassGetDeviceParameter(FdoExtension,
2016 (PULONG)&detectionState);
2017
2018 if (detectionState == ClassDetectionUnsupported) {
2019 goto ExitWithError;
2020 }
2021
2022 //
2023 // check if the device has a hack flag saying never to try this.
2024 //
2025
2026 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
2028
2029 ClassSetDeviceParameter(FdoExtension,
2033 goto ExitWithError;
2034
2035 }
2036
2037
2038 //
2039 // else go through the process since we allocate buffers and
2040 // get all sorts of device settings.
2041 //
2042
2043 if (Info->Gesn.Buffer == NULL) {
2044 Info->Gesn.Buffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
2046 '??cS');
2047 }
2048 if (Info->Gesn.Buffer == NULL) {
2050 goto ExitWithError;
2051 }
2052 if (Info->Gesn.Mdl != NULL) {
2053 IoFreeMdl(Info->Gesn.Mdl);
2054 }
2055 Info->Gesn.Mdl = IoAllocateMdl(Info->Gesn.Buffer,
2057 FALSE, FALSE, NULL);
2058 if (Info->Gesn.Mdl == NULL) {
2060 goto ExitWithError;
2061 }
2062
2064 Info->Gesn.BufferSize = GESN_BUFFER_SIZE;
2065 Info->Gesn.EventMask = 0;
2066
2067 //
2068 // all items are prepared to use GESN (except the event mask, so don't
2069 // optimize this part out!).
2070 //
2071 // now see if it really works. we have to loop through this because
2072 // many SAMSUNG (and one COMPAQ) drives timeout when requesting
2073 // NOT_READY events, even when the IMMEDIATE bit is set. :(
2074 //
2075 // using a drive list is cumbersome, so this might fix the problem.
2076 //
2077
2078 deviceDescriptor = FdoExtension->DeviceDescriptor;
2079 atapiResets = 0;
2080 retryImmediately = TRUE;
2081 for (i = 0; i < 16 && retryImmediately == TRUE; i++) {
2082
2084 if (irp == NULL) {
2086 goto ExitWithError;
2087 }
2088
2089 if (Info->MediaChangeSrb.Srb.Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) {
2090 srbFlags = Info->MediaChangeSrb.SrbEx.SrbFlags;
2091 } else {
2092 srbFlags = Info->MediaChangeSrb.Srb.SrbFlags;
2093 }
2095
2096 //
2097 // replace the completion routine with a different one this time...
2098 //
2099
2103 &event,
2104 TRUE, TRUE, TRUE);
2105
2106 status = IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject, irp);
2107
2108 if (status == STATUS_PENDING) {
2110 Executive,
2111 KernelMode,
2112 FALSE,
2113 NULL);
2115 }
2116 ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
2117
2118 if (SRB_STATUS(Info->MediaChangeSrb.Srb.SrbStatus) != SRB_STATUS_SUCCESS) {
2119
2121 irp,
2122 &(Info->MediaChangeSrb.Srb),
2124 0,
2125 0,
2126 &status,
2127 NULL);
2128 }
2129
2130 if ((deviceDescriptor->BusType == BusTypeAtapi) &&
2131 (Info->MediaChangeSrb.Srb.SrbStatus == SRB_STATUS_BUS_RESET)
2132 ) {
2133
2134 //
2135 // ATAPI unfortunately returns SRB_STATUS_BUS_RESET instead
2136 // of SRB_STATUS_TIMEOUT, so we cannot differentiate between
2137 // the two. if we get this status four time consecutively,
2138 // stop trying this command. it is too late to change ATAPI
2139 // at this point, so special-case this here. (07/10/2001)
2140 // NOTE: any value more than 4 may cause the device to be
2141 // marked missing.
2142 //
2143
2144 atapiResets++;
2145 if (atapiResets >= 4) {
2147 goto ExitWithError;
2148 }
2149 }
2150
2151 if (status == STATUS_DATA_OVERRUN) {
2153 }
2154
2156 (status == STATUS_TIMEOUT) ||
2159 ) {
2160
2161 //
2162 // with these error codes, we don't ever want to try this command
2163 // again on this device, since it reacts poorly.
2164 //
2165
2166 ClassSetDeviceParameter(FdoExtension,
2170 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2171 "Classpnp => GESN test failed %x for fdo %p\n",
2172 status, FdoExtension->DeviceObject));
2173 goto ExitWithError;
2174
2175
2176 }
2177
2178 if (!NT_SUCCESS(status)) {
2179
2180 //
2181 // this may be other errors that should not disable GESN
2182 // for all future start_device calls.
2183 //
2184
2185 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2186 "Classpnp => GESN test failed %x for fdo %p\n",
2187 status, FdoExtension->DeviceObject));
2188 goto ExitWithError;
2189 }
2190
2191 if (i == 0) {
2192
2193 //
2194 // the first time, the request was just retrieving a mask of
2195 // available bits. use this to mask future requests.
2196 //
2197
2199
2200 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2201 "Classpnp => Fdo %p supports event mask %x\n",
2202 FdoExtension->DeviceObject, header->SupportedEventClasses));
2203
2204
2205 if (TEST_FLAG(header->SupportedEventClasses,
2207 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2208 "Classpnp => GESN supports MCN\n"));
2209 }
2210 if (TEST_FLAG(header->SupportedEventClasses,
2212 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2213 "Classpnp => GESN supports DeviceBusy\n"));
2214 }
2215 if (TEST_FLAG(header->SupportedEventClasses,
2217
2218 if (TEST_FLAG(FdoExtension->PrivateFdoData->HackFlags,
2220 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2221 "Classpnp => GESN supports OpChange, but "
2222 "must ignore these events for compatibility\n"));
2223 CLEAR_FLAG(header->SupportedEventClasses,
2225 } else {
2226 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2227 "Classpnp => GESN supports OpChange\n"));
2228 }
2229 }
2230 Info->Gesn.EventMask = header->SupportedEventClasses;
2231
2232 //
2233 // realistically, we are only considering the following events:
2234 // EXTERNAL REQUEST - this is being tested for play/stop/etc.
2235 // MEDIA STATUS - autorun and ejection requests.
2236 // DEVICE BUSY - to allow us to predict when media will be ready.
2237 // therefore, we should not bother querying for the other,
2238 // unknown events. clear all but the above flags.
2239 //
2240
2241 Info->Gesn.EventMask &=
2246
2247
2248 //
2249 // HACKHACK - REF #0001
2250 // Some devices will *never* report an event if we've also requested
2251 // that it report lower-priority events. this is due to a
2252 // misunderstanding in the specification wherein a "No Change" is
2253 // interpreted to be a real event. what should occur is that the
2254 // device should ignore "No Change" events when multiple event types
2255 // are requested unless there are no other events waiting. this
2256 // greatly reduces the number of requests that the host must send
2257 // to determine if an event has occurred. Since we must work on all
2258 // drives, default to enabling the hack until we find evidence of
2259 // proper firmware.
2260 //
2261 if (Info->Gesn.EventMask == 0) {
2262
2263 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2264 "Classpnp => GESN supported, but not mask we care "
2265 "about (%x) for FDO %p\n",
2266 header->SupportedEventClasses,
2267 FdoExtension->DeviceObject));
2268 goto ExitWithError;
2269
2270 } else if (CountOfSetBitsUChar(Info->Gesn.EventMask) == 1) {
2271
2272 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2273 "Classpnp => GESN hack not required for FDO %p\n",
2274 FdoExtension->DeviceObject));
2275
2276 } else {
2277
2278 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2279 "Classpnp => GESN hack enabled for FDO %p\n",
2280 FdoExtension->DeviceObject));
2281 Info->Gesn.HackEventMask = 1;
2282
2283 }
2284
2285 } else {
2286
2287 //
2288 // not the first time looping through, so interpret the results.
2289 //
2290
2292 (PVOID)Info->Gesn.Buffer,
2293 &retryImmediately);
2294
2295 if (!NT_SUCCESS(status)) {
2296
2297 //
2298 // This drive does not support GESN correctly
2299 //
2300
2301 ClassSetDeviceParameter(FdoExtension,
2305 goto ExitWithError;
2306 }
2307 }
2308
2309 } // end loop of GESN requests....
2310
2311 //
2312 // we can only use this if it can be relied upon for media changes,
2313 // since we are (by definition) no longer going to be polling via
2314 // a TEST_UNIT_READY irp, and drives will not report UNIT ATTENTION
2315 // for this command (although a filter driver, such as one for burning
2316 // cd's, might still fake those errors).
2317 //
2318 // since we also rely upon NOT_READY events to change the cursor
2319 // into a "wait" cursor; GESN is still more reliable than other
2320 // methods, and includes eject button requests, so we'll use it
2321 // without DEVICE_BUSY in Windows Vista.
2322 //
2323
2324 if (TEST_FLAG(Info->Gesn.EventMask, NOTIFICATION_MEDIA_STATUS_CLASS_MASK)) {
2325
2326 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2327 "Classpnp => Enabling GESN support for fdo %p\n",
2328 FdoExtension->DeviceObject));
2329 Info->Gesn.Supported = TRUE;
2330
2331 ClassSetDeviceParameter(FdoExtension,
2335
2336 return STATUS_SUCCESS;
2337
2338 }
2339
2340 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2341 "Classpnp => GESN available but not enabled for fdo %p\n",
2342 FdoExtension->DeviceObject));
2343 goto ExitWithError;
2344
2345 // fall through...
2346
2347ExitWithError:
2348 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2349 "Classpnp => GESN support detection failed for fdo %p with status %08x\n",
2350 FdoExtension->DeviceObject, status));
2351
2352
2353 if (Info->Gesn.Mdl) {
2354 IoFreeMdl(Info->Gesn.Mdl);
2355 Info->Gesn.Mdl = NULL;
2356 }
2357 FREE_POOL(Info->Gesn.Buffer);
2358 Info->Gesn.Supported = 0;
2359 Info->Gesn.EventMask = 0;
2360 Info->Gesn.BufferSize = 0;
2361 return STATUS_NOT_SUPPORTED;
2362
2363}
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
FORCEINLINE ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: cdrom.h:1500
#define FDO_HACK_GESN_IGNORE_OPCHANGE
Definition: cdromp.h:136
#define FDO_HACK_GESN_IS_BAD
Definition: cdromp.h:134
enum _CLASS_DETECTION_STATE CLASS_DETECTION_STATE
@ ClassDetectionUnknown
Definition: classp.h:445
@ ClassDetectionSupported
Definition: classp.h:447
#define GESN_BUFFER_SIZE
Definition: autorun.c:32
PIRP ClasspPrepareMcnIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
Definition: autorun.c:1310
NTSTATUS ClasspInterpretGesnData(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PNOTIFICATION_EVENT_STATUS_HEADER Header, OUT PBOOLEAN ResendImmediately)
Definition: autorun.c:251
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
BOOLEAN InterpretSenseInfoWithoutHistory(_In_ PDEVICE_OBJECT Fdo, _In_opt_ PIRP OriginalRequest, _In_ PSCSI_REQUEST_BLOCK Srb, UCHAR MajorFunctionCode, ULONG IoDeviceCode, ULONG PreviousRetryCount, _Out_ NTSTATUS *Status, _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS) LONGLONG *RetryIn100nsUnits)
Definition: class.c:12844
#define SRB_STATUS_BUS_RESET
Definition: srb.h:353
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:404
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
@ BusTypeAtapi
Definition: ntddstor.h:440
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:576
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define NOTIFICATION_MEDIA_STATUS_CLASS_MASK
Definition: scsi.h:37
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK
Definition: scsi.h:36
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK
Definition: scsi.h:34
struct _NOTIFICATION_EVENT_STATUS_HEADER * PNOTIFICATION_EVENT_STATUS_HEADER
#define NOTIFICATION_DEVICE_BUSY_CLASS_MASK
Definition: scsi.h:39
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:108
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define IRP_MJ_SCSI

Referenced by ClasspInitializePolling().

◆ ClasspInitializePolling()

NTSTATUS ClasspInitializePolling ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN BOOLEAN  AllowDriveToSleep 
)

Definition at line 1834 of file autorun.c.

1838{
1839 PDEVICE_OBJECT fdo = FdoExtension->DeviceObject;
1840
1842 PIRP irp;
1843
1844 PAGED_CODE();
1845
1846 if (FdoExtension->MediaChangeDetectionInfo != NULL) {
1847 return STATUS_SUCCESS;
1848 }
1849
1850 info = ExAllocatePoolWithTag(NonPagedPoolNx,
1853
1854 if (info != NULL) {
1856
1857 FdoExtension->KernelModeMcnContext.FileObject = (PVOID)-1;
1858 FdoExtension->KernelModeMcnContext.DeviceObject = (PVOID)-1;
1859 FdoExtension->KernelModeMcnContext.LockCount = 0;
1860 FdoExtension->KernelModeMcnContext.McnDisableCount = 0;
1861
1862 /*
1863 * Allocate an IRP to carry the Test-Unit-Ready.
1864 * Allocate an extra IRP stack location
1865 * so we can cache our device object in the top location.
1866 */
1867 irp = IoAllocateIrp((CCHAR)(fdo->StackSize+1), FALSE);
1868
1869 if (irp != NULL) {
1870
1871 PVOID buffer;
1872 BOOLEAN GesnSupported = FALSE;
1873
1875 NonPagedPoolNxCacheAligned,
1878
1879 if (buffer != NULL) {
1880
1881 info->MediaChangeIrp = irp;
1882 info->SenseBuffer = buffer;
1883 info->SenseBufferLength = SENSE_BUFFER_SIZE_EX;
1884
1885 //
1886 // Set default values for the media change notification
1887 // configuration.
1888 //
1889
1890 info->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME;
1891 info->MediaChangeDetectionDisableCount = 0;
1892
1893 //
1894 // Assume that there is initially no media in the device
1895 // only notify upper layers if there is something there
1896 //
1897
1898 info->MediaChangeDetectionState = MediaUnknown;
1899
1900 info->MediaChangeIrpTimeInUse = 0;
1901 info->MediaChangeIrpLost = FALSE;
1902
1903 //
1904 // setup all extra flags we'll be setting for this irp
1905 //
1906 info->SrbFlags = 0;
1907 if (AllowDriveToSleep) {
1909 }
1913
1914 KeInitializeMutex(&info->MediaChangeMutex, 0x100);
1915
1916 //
1917 // It is ok to support media change events on this
1918 // device.
1919 //
1920
1921 FdoExtension->MediaChangeDetectionInfo = info;
1922
1923 //
1924 // NOTE: the DeviceType is FILE_DEVICE_CD_ROM even
1925 // when the device supports DVD (no need to
1926 // check for FILE_DEVICE_DVD, as it's not a
1927 // valid check).
1928 //
1929
1930 if (FdoExtension->DeviceObject->DeviceType == FILE_DEVICE_CD_ROM) {
1931
1933
1934 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1935 "ClasspInitializePolling: Testing for GESN\n"));
1937 if (NT_SUCCESS(status)) {
1938 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1939 "ClasspInitializePolling: GESN available "
1940 "for %p\n", FdoExtension->DeviceObject));
1941 NT_ASSERT(info->Gesn.Supported );
1942 NT_ASSERT(info->Gesn.Buffer != NULL);
1943 NT_ASSERT(info->Gesn.BufferSize != 0);
1944 NT_ASSERT(info->Gesn.EventMask != 0);
1945 GesnSupported = TRUE;
1946 } else {
1947 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1948 "ClasspInitializePolling: GESN *NOT* available "
1949 "for %p\n", FdoExtension->DeviceObject));
1950 }
1951 }
1952
1953 if (GesnSupported == FALSE) {
1954 NT_ASSERT(info->Gesn.Supported == 0);
1955 NT_ASSERT(info->Gesn.Buffer == NULL);
1956 NT_ASSERT(info->Gesn.BufferSize == 0);
1957 NT_ASSERT(info->Gesn.EventMask == 0);
1958 info->Gesn.Supported = 0; // just in case....
1959 }
1960
1961 //
1962 // Register for screen state notification. Will use this to
1963 // determine user presence.
1964 //
1967 &GUID_CONSOLE_DISPLAY_STATE,
1969 NULL,
1971 }
1972
1973 return STATUS_SUCCESS;
1974 }
1975
1976 IoFreeIrp(irp);
1977 }
1978
1979 FREE_POOL(info);
1980 }
1981
1982 //
1983 // nothing to free here
1984 //
1986
1987} // end ClasspInitializePolling()
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
NTSTATUS ClasspInitializeGesn(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info)
Definition: autorun.c:1990
#define MEDIA_CHANGE_DEFAULT_TIME
Definition: classpnp.h:132
#define CLASS_TAG_MEDIA_CHANGE_DETECTION
Definition: classpnp.h:79
_In_ BOOLEAN AllowDriveToSleep
Definition: classpnp.h:1275
PVOID ScreenStateNotificationHandle
Definition: class.c:124
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:412
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
GLuint buffer
Definition: glext.h:5915
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
NTKRNLVISTAAPI NTSTATUS NTAPI PoRegisterPowerSettingCallback(_In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LPCGUID SettingGuid, _In_ PPOWER_SETTING_CALLBACK Callback, _In_opt_ PVOID Context, _Outptr_opt_ PVOID *Handle)
Definition: po.c:14
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
void * PVOID
Definition: typedefs.h:50
char CCHAR
Definition: typedefs.h:51
@ MediaUnknown
Definition: udf_common.h:10

◆ ClasspInitializeTimer()

NTSTATUS ClasspInitializeTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3737 of file autorun.c.

3764{
3765 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3766
3767 if (FdoExtension->CommonExtension.IsFdo) {
3768 fdoData = FdoExtension->PrivateFdoData;
3769 }
3770
3771 if (fdoData == NULL) {
3772 return STATUS_UNSUCCESSFUL;
3773 }
3774
3775 if (fdoData->TimerInitialized == FALSE) {
3776#if (NTDDI_VERSION >= NTDDI_WINBLUE)
3777 NT_ASSERT(fdoData->TickTimer == NULL);
3778 //
3779 // The tick timer is a no-wake timer, which means it will not wake
3780 // the processor while the processor is in a low power state until
3781 // the timer's no-wake tolerance is reached.
3782 //
3784 if (fdoData->TickTimer == NULL) {
3786 }
3787#else
3788 KeInitializeDpc(&fdoData->TickTimerDpc, ClasspTimerTick, FdoExtension);
3789 KeInitializeTimer(&fdoData->TickTimer);
3790#endif
3791 fdoData->TimerInitialized = TRUE;
3792 }
3793
3794 return STATUS_SUCCESS;
3795}
EXT_CALLBACK ClasspTimerTickEx
Definition: autorun.c:121
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define EX_TIMER_NO_WAKE
Definition: exfuncs.h:956
NTKERNELAPI PEX_TIMER NTAPI ExAllocateTimer(_In_opt_ PEXT_CALLBACK Callback, _In_opt_ PVOID CallbackContext, _In_ ULONG Attributes)

Referenced by ClasspEnableTimer(), and ClassPnpStartDevice().

◆ ClasspInternalSetMediaChangeState()

VOID ClasspInternalSetMediaChangeState ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN MEDIA_CHANGE_DETECTION_STATE  NewState,
IN BOOLEAN  KnownStateChange 
)

Definition at line 798 of file autorun.c.

803{
804#if DBG
805 PCSZ states[] = {"Unknown", "Present", "Not Present", "Unavailable"};
806#endif
807 MEDIA_CHANGE_DETECTION_STATE oldMediaState;
808 PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
810 PIO_WORKITEM workItem;
811
812 if (!((NewState >= MediaUnknown) && (NewState <= MediaUnavailable))) {
813 return;
814 }
815
816 if(info == NULL) {
817 return;
818 }
819
820 oldMediaState = InterlockedExchange(
821 (PLONG)(&info->MediaChangeDetectionState),
822 (LONG)NewState);
823
824 if((oldMediaState == MediaUnknown) && (!KnownStateChange)) {
825
826 //
827 // The media was in an indeterminate state before - don't notify for
828 // this change.
829 //
830
831 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
832 "ClassSetMediaChangeState: State was unknown - this may "
833 "not be a change\n"));
834 return;
835
836 } else if(oldMediaState == NewState) {
837
838 //
839 // Media is in the same state it was before.
840 //
841
842 return;
843 }
844
845 //
846 // Inform PartMgr that the media changed. It will need to propagate
847 // DO_VERIFY_VOLUME to each partition. Ensure that only one work item
848 // updates the disk's properties at any given time.
849 //
850 if (InterlockedCompareExchange((volatile LONG *)&FdoExtension->PrivateFdoData->UpdateDiskPropertiesWorkItemActive, 1, 0) == 0) {
851
852 workItem = IoAllocateWorkItem(FdoExtension->DeviceObject);
853
854 if (workItem) {
855
857
858 } else {
859
860 InterlockedExchange((volatile LONG *)&FdoExtension->PrivateFdoData->UpdateDiskPropertiesWorkItemActive, 0);
861 }
862 }
863
864 if(info->MediaChangeDetectionDisableCount != 0) {
865#if DBG
866 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
867 "ClassSetMediaChangeState: MCN not enabled, state "
868 "changed from %s to %s\n",
869 states[oldMediaState], states[NewState]));
870#endif
871 return;
872
873 }
874#if DBG
875 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
876 "ClassSetMediaChangeState: State change from %s to %s\n",
877 states[oldMediaState], states[NewState]));
878#endif
879
880 //
881 // make the data useful -- it used to always be zero.
882 //
883 mcnContext.MediaChangeCount = FdoExtension->MediaChangeCount;
884 mcnContext.NewState = NewState;
885
886 if (NewState == MediaPresent) {
887
888 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspInternalSetMediaChangeState: media ARRIVAL"));
889 ClassSendNotification(FdoExtension,
890 &GUID_IO_MEDIA_ARRIVAL,
892 &mcnContext);
893
894 }
895 else if ((NewState == MediaNotPresent) || (NewState == MediaUnavailable)) {
896
897 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspInternalSetMediaChangeState: media REMOVAL"));
898 ClassSendNotification(FdoExtension,
899 &GUID_IO_MEDIA_REMOVAL,
901 &mcnContext);
902
903 } else {
904
905 //
906 // Don't notify of changed going to unknown.
907 //
908
909 return;
910 }
911
912 return;
913} // end ClasspInternalSetMediaChangeState()
@ MediaPresent
Definition: cdromp.h:82
@ MediaNotPresent
Definition: cdromp.h:83
@ MediaUnavailable
Definition: cdromp.h:84
enum _MEDIA_CHANGE_DETECTION_STATE MEDIA_CHANGE_DETECTION_STATE
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
Definition: classp.h:1714
#define InterlockedCompareExchange
Definition: interlocked.h:104
int32_t * PLONG
Definition: typedefs.h:58
CONST char * PCSZ
Definition: umtypes.h:125

Referenced by ClasspSetMediaChangeStateEx().

◆ ClasspInterpretGesnData()

NTSTATUS ClasspInterpretGesnData ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PNOTIFICATION_EVENT_STATUS_HEADER  Header,
OUT PBOOLEAN  ResendImmediately 
)

Definition at line 251 of file autorun.c.

312{
315 LONG requiredLength;
317
318 info = FdoExtension->MediaChangeDetectionInfo;
319
320 //
321 // note: don't allocate anything in this routine so that we can
322 // always just 'return'.
323 //
324
325 *ResendImmediately = FALSE;
326 if (Header->NEA) {
327 return status;
328 }
329 if (Header->NotificationClass == NOTIFICATION_NO_CLASS_EVENTS) {
330 return status;
331 }
332
333 //
334 // HACKHACK - REF #0001
335 // This loop is only taken initially, due to the inability to reliably
336 // auto-detect drives that report events correctly at boot. When we
337 // detect this behavior during the normal course of running, we will
338 // disable the hack, allowing more efficient use of the system. This
339 // should occur "nearly" instantly, as the drive should have multiple
340 // events queue'd (ie. power, morphing, media).
341 //
342
343 if (info->Gesn.HackEventMask) {
344
345 //
346 // all events use the low four bytes of zero to indicate
347 // that there was no change in status.
348 //
349
350 UCHAR thisEvent = Header->ClassEventData[0] & 0xf;
351 UCHAR lowestSetBit;
352 UCHAR thisEventBit = (1 << Header->NotificationClass);
353
354 if (!TEST_FLAG(info->Gesn.EventMask, thisEventBit)) {
355
356 //
357 // The drive is reporting an event that wasn't requested
358 //
359
361 }
362
363 //
364 // some bit magic here... this results in the lowest set bit only
365 //
366
367 lowestSetBit = info->Gesn.EventMask;
368 lowestSetBit &= (info->Gesn.EventMask - 1);
369 lowestSetBit ^= (info->Gesn.EventMask);
370
371 if (thisEventBit != lowestSetBit) {
372
373 //
374 // HACKHACK - REF #0001
375 // the first time we ever see an event set that is not the lowest
376 // set bit in the request (iow, highest priority), we know that the
377 // hack is no longer required, as the device is ignoring "no change"
378 // events when a real event is waiting in the other requested queues.
379 //
380
381 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
382 "Classpnp => GESN::NONE: Compliant drive found, "
383 "removing GESN hack (%x, %x)\n",
384 thisEventBit, info->Gesn.EventMask));
385
386 info->Gesn.HackEventMask = FALSE;
387
388 } else if (thisEvent == 0) { // NOTIFICATION_*_EVENT_NO_CHANGE
389
390 //
391 // HACKHACK - REF #0001
392 // note: this hack prevents poorly implemented firmware from constantly
393 // returning "No Event". we do this by cycling through the
394 // supported list of events here.
395 //
396
397 SET_FLAG(info->Gesn.NoChangeEventMask, thisEventBit);
398 CLEAR_FLAG(info->Gesn.EventMask, thisEventBit);
399
400 //
401 // if we have cycled through all supported event types, then
402 // we need to reset the events we are asking about. else we
403 // want to resend this request immediately in case there was
404 // another event pending.
405 //
406
407 if (info->Gesn.EventMask == 0) {
408 info->Gesn.EventMask = info->Gesn.NoChangeEventMask;
409 info->Gesn.NoChangeEventMask = 0;
410 } else {
411 *ResendImmediately = TRUE;
412 }
413 return status;
414 }
415
416 } // end if (info->Gesn.HackEventMask)
417
418 dataLength =
419 (Header->EventDataLength[0] << 8) |
420 (Header->EventDataLength[1] & 0xff);
421 dataLength -= 2;
422 requiredLength = 4; // all events are four bytes
423
424 if (dataLength < requiredLength) {
425 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
426 "Classpnp => GESN returned only %x bytes data for fdo %p\n",
427 dataLength, FdoExtension->DeviceObject));
428
430 }
431 if (dataLength != requiredLength) {
432 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
433 "Classpnp => GESN returned too many (%x) bytes data for fdo %p\n",
434 dataLength, FdoExtension->DeviceObject));
435 // dataLength = 4;
436 }
437
438 NT_ASSERT(dataLength == 4);
439
440 if ((Header->ClassEventData[0] & 0xf) == 0)
441 {
442 // a zero event is a "no change event, so do not retry
443 return status;
444 }
445
446 // because a event other than "no change" occurred,
447 // we should immediately resend this request.
448 *ResendImmediately = TRUE;
449
450
451/*
452 ClassSendNotification(FdoExtension,
453 &GUID_IO_GENERIC_GESN_EVENT,
454 sizeof(NOTIFICATION_EVENT_STATUS_HEADER) + dataLength,
455 Header)
456*/
457
458
459
460 switch (Header->NotificationClass) {
461
463
465 (PNOTIFICATION_OPERATIONAL_STATUS)(Header->ClassEventData);
466 ULONG event;
467
469 break;
470 }
471
472 event = (opChangeInfo->Operation[0] << 8) |
473 (opChangeInfo->Operation[1] ) ;
474
475 // Workaround some hardware that is buggy but prevalent in the market
476 // This hardware has the property that it will report OpChange events repeatedly,
477 // causing us to retry immediately so quickly that we will eventually disable
478 // GESN to prevent an infinite loop.
479 // (only one valid OpChange event type now, only two ever defined)
480 if (info->MediaChangeRetryCount >= 4) {
481
482 //
483 // HACKHACK - REF #0002
484 // Some drives incorrectly report OpChange/Change (001b/0001h) events
485 // continuously when the tray has been ejected. This causes this routine
486 // to set ResendImmediately to "TRUE", and that results in our cycling
487 // 32 times immediately resending. At that point, we give up detecting
488 // the infinite retry loop, and disable GESN on these drives. This
489 // prevents Media Eject Request (from eject button) from being reported.
490 // Thus, instead we should attempt to workaround this issue by detecting
491 // this behavior.
492 //
493
494 static UCHAR const OpChangeMask = 0x02;
495
496 // At least one device reports "temporarily busy" (which is useless) on eject
497 // At least one device reports "OpChange" repeatedly when re-inserting media
498 // All seem to work well using this workaround
499
500 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_MCN,
501 "Classpnp => GESN OpChange events are broken. Working around this "
502 "problem in software (for fdo %p)\n",
503 FdoExtension->DeviceObject));
504
505
506 // OpChange is not the only bit set -- Media class is required....
507 NT_ASSERT(CountOfSetBitsUChar(info->Gesn.EventMask) != 1);
508
509 //
510 // Force the use of the hackhack (ref #0001) to workaround the
511 // issue noted this hackhack (ref #0002).
512 //
513 SET_FLAG(info->Gesn.NoChangeEventMask, OpChangeMask);
514 CLEAR_FLAG(info->Gesn.EventMask, OpChangeMask);
515 info->Gesn.HackEventMask = TRUE;
516
517 //
518 // don't request the opChange event again. use the method
519 // defined by hackhack (ref #0001) as the workaround.
520 //
521
522 if (info->Gesn.EventMask == 0) {
523 info->Gesn.EventMask = info->Gesn.NoChangeEventMask;
524 info->Gesn.NoChangeEventMask = 0;
525 *ResendImmediately = FALSE;
526 } else {
527 *ResendImmediately = TRUE;
528 }
529
530 break;
531 }
532
533
536
537 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
538 "Classpnp => GESN says features added/changedfor fdo %p\n",
539 FdoExtension->DeviceObject));
540
541 // don't notify that new media arrived, just set the
542 // DO_VERIFY to force a FS reload.
543
544 if (TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
546 (ClassGetVpb(FdoExtension->DeviceObject) != NULL) &&
547 (ClassGetVpb(FdoExtension->DeviceObject)->Flags & VPB_MOUNTED)
548 ) {
549
550 SET_FLAG(FdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
551 }
552
553 //
554 // If there is a class specific error handler, call it with
555 // a "fake" media change error in case it needs to update
556 // internal structures as though a media change occurred.
557 //
558
559 if (FdoExtension->CommonExtension.DevInfo->ClassError != NULL) {
560
561 SCSI_REQUEST_BLOCK srb = {0};
562 UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0};
564 PSCSI_REQUEST_BLOCK srbPtr;
565
566 SENSE_DATA sense = {0};
567 NTSTATUS tempStatus;
568 BOOLEAN retry;
569
570 tempStatus = STATUS_MEDIA_CHANGED;
571 retry = FALSE;
572
574
575 sense.AdditionalSenseLength = sizeof(SENSE_DATA) -
576 RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength);
577
580
581 //
582 // Send the right type of SRB to the class driver
583 //
584 if ((FdoExtension->CommonExtension.DriverExtension->SrbSupport &
586#ifdef _MSC_VER
587 #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded")
588#endif
592 1,
594 if (NT_SUCCESS(status)) {
595 SrbSetCdbLength(srbEx, 6);
596 srbEx->SrbStatus = SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_ERROR;
597 SrbSetSenseInfoBuffer(srbEx, &sense);
598 SrbSetSenseInfoBufferLength(srbEx, sizeof(sense));
599 srbPtr = (PSCSI_REQUEST_BLOCK)srbEx;
600 } else {
601 // should not happen. Revert to legacy SRB.
603 srb.CdbLength = 6;
604 srb.Length = sizeof(SCSI_REQUEST_BLOCK);
606 srb.SenseInfoBuffer = &sense;
607 srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
608 srbPtr = &srb;
609 }
610 } else {
611 srb.CdbLength = 6;
612 srb.Length = sizeof(SCSI_REQUEST_BLOCK);
614 srb.SenseInfoBuffer = &sense;
615 srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
616 srbPtr = &srb;
617 }
618
619 FdoExtension->CommonExtension.DevInfo->ClassError(FdoExtension->DeviceObject,
620 srbPtr,
621 &tempStatus,
622 &retry);
623
624 } // end class error handler
625
626 }
627 break;
628 }
629
631
632 PNOTIFICATION_EXTERNAL_STATUS externalInfo =
633 (PNOTIFICATION_EXTERNAL_STATUS)(Header->ClassEventData);
634 DEVICE_EVENT_EXTERNAL_REQUEST externalData = {0};
635
636 //
637 // unfortunately, due to time constraints, we will only notify
638 // about keys being pressed, and not released. this makes keys
639 // single-function, but simplifies the code significantly.
640 //
641
643 break;
644 }
645
646 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
647 "Classpnp => GESN::EXTERNAL: Event: %x Status %x Req %x\n",
648 externalInfo->ExternalEvent, externalInfo->ExternalStatus,
649 (externalInfo->Request[0] << 8) | externalInfo->Request[1]
650 ));
651
652 externalData.Version = 1;
653 externalData.DeviceClass = 0;
654 externalData.ButtonStatus = externalInfo->ExternalEvent;
655 externalData.Request =
656 (externalInfo->Request[0] << 8) |
657 (externalInfo->Request[1] & 0xff);
658 KeQuerySystemTime(&(externalData.SystemTime));
660
661 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspInterpretGesnData: media DEVICE_EXTERNAL_REQUEST"));
662 ClassSendNotification(FdoExtension,
663 &GUID_IO_DEVICE_EXTERNAL_REQUEST,
665 &externalData);
666 return status;
667 }
668
670
672 (PNOTIFICATION_MEDIA_STATUS)(Header->ClassEventData);
673
674 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
675 "Classpnp => GESN::MEDIA: Event: %x Status %x\n",
676 mediaInfo->MediaEvent, mediaInfo->MediaStatus));
677
680
681
682 if (TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
684 (ClassGetVpb(FdoExtension->DeviceObject) != NULL) &&
685 (ClassGetVpb(FdoExtension->DeviceObject)->Flags & VPB_MOUNTED)
686 ) {
687
688 SET_FLAG(FdoExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
689
690 }
691 InterlockedIncrement((volatile LONG *)&FdoExtension->MediaChangeCount);
694 FALSE,
695 TRUE);
696
697 } else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL) {
698
701 FALSE,
702 TRUE);
703
704 } else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST) {
705
706 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
707 "Classpnp => GESN Ejection request received!\n"));
709
710 }
711 break;
712
713 }
714
715 case NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS: { // lowest priority events...
716
718 (PNOTIFICATION_BUSY_STATUS)(Header->ClassEventData);
719 DEVICE_EVENT_BECOMING_READY busyData = {0};
720
721 //
722 // NOTE: we never actually need to immediately retry for these
723 // events: if one exists, the device is busy, and if not,
724 // we still don't want to retry.
725 //
726
727 *ResendImmediately = FALSE;
728
729 //
730 // else we want to report the approximated time till it's ready.
731 //
732
733 busyData.Version = 1;
734 busyData.Reason = busyInfo->DeviceBusyStatus;
735 busyData.Estimated100msToReady = (busyInfo->Time[0] << 8) |
736 (busyInfo->Time[1] & 0xff);
737
738 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
739 "Classpnp => GESN::BUSY: Event: %x Status %x Time %x\n",
740 busyInfo->DeviceBusyEvent, busyInfo->DeviceBusyStatus,
741 busyData.Estimated100msToReady
742 ));
743
744 //
745 // Ignore the notification if the time is small
746 //
748 break;
749 }
750
751
752 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspInterpretGesnData: media BECOMING_READY"));
753 ClassSendNotification(FdoExtension,
754 &GUID_IO_DEVICE_BECOMING_READY,
756 &busyData);
757 break;
758 }
759
760 default: {
761
762 break;
763
764 }
765
766 } // end switch on notification class
767 return status;
768}
#define InterlockedIncrement
Definition: armddk.h:53
#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS
Definition: autorun.c:41
struct _SENSE_DATA SENSE_DATA
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
Definition: Header.h:9
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
VOID ClassSendEjectionNotification(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:155
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define CLASS_SRB_STORAGE_REQUEST_BLOCK
Definition: classpnp.h:573
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define SRB_STATUS_ERROR
Definition: srb.h:344
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:672
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
#define NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS
Definition: scsi.h:48
#define NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE
Definition: scsi.h:97
struct _NOTIFICATION_OPERATIONAL_STATUS * PNOTIFICATION_OPERATIONAL_STATUS
struct _NOTIFICATION_EXTERNAL_STATUS * PNOTIFICATION_EXTERNAL_STATUS
#define NOTIFICATION_MEDIA_EVENT_NEW_MEDIA
Definition: scsi.h:95
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE
Definition: scsi.h:59
#define NOTIFICATION_NO_CLASS_EVENTS
Definition: scsi.h:42
#define SCSI_SENSE_ERRORCODE_FIXED_CURRENT
Definition: scsi.h:623
#define NOTIFICATION_EXTERNAL_EVENT_BUTTON_DOWN
Definition: scsi.h:76
struct _NOTIFICATION_MEDIA_STATUS * PNOTIFICATION_MEDIA_STATUS
#define NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST
Definition: scsi.h:94
#define NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS
Definition: scsi.h:46
struct _NOTIFICATION_BUSY_STATUS * PNOTIFICATION_BUSY_STATUS
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS
Definition: scsi.h:45
#define NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL
Definition: scsi.h:96
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED
Definition: scsi.h:60
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS
Definition: scsi.h:43
ULONG dataLength
Definition: scsi.h:3751
#define NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED
Definition: scsi.h:51
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:666
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:661
@ SrbExDataTypeScsiCdb16
Definition: srb.h:459
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
LARGE_INTEGER SystemTime
Definition: ioevent.h:92
UCHAR SenseInfoBufferLength
Definition: srb.h:259
UCHAR CdbLength
Definition: srb.h:258
PVOID SenseInfoBuffer
Definition: srb.h:264
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR ErrorCode
Definition: cdrw_hw.h:1164
UCHAR SenseKey
Definition: cdrw_hw.h:1167
USHORT Flags
Definition: iotypes.h:192
#define VPB_MOUNTED
Definition: iotypes.h:1807

Referenced by ClasspInitializeGesn(), and ClasspMediaChangeDetectionCompletion().

◆ ClasspIsMediaChangeDisabledDueToHardwareLimitation()

BOOLEAN ClasspIsMediaChangeDisabledDueToHardwareLimitation ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PUNICODE_STRING  RegistryPath 
)

Definition at line 2727 of file autorun.c.

2731{
2732 PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor = FdoExtension->DeviceDescriptor;
2733 OBJECT_ATTRIBUTES objectAttributes = {0};
2734 HANDLE serviceKey = NULL;
2735 RTL_QUERY_REGISTRY_TABLE parameters[2] = {0};
2736
2737 UNICODE_STRING deviceUnicodeString;
2738 ANSI_STRING deviceString;
2739 ULONG mediaChangeNotificationDisabled = FALSE;
2740
2742
2743
2744 PAGED_CODE();
2745
2746 //
2747 // open the service key.
2748 //
2749
2750 InitializeObjectAttributes(&objectAttributes,
2753 NULL,
2754 NULL);
2755
2756 status = ZwOpenKey(&serviceKey,
2757 KEY_READ,
2758 &objectAttributes);
2759
2761
2762
2763 if(!NT_SUCCESS(status)) {
2764
2765 //
2766 // always take the safe path. if we can't open the service key,
2767 // disable autorun
2768 //
2769
2770 return TRUE;
2771
2772 }
2773
2774 TRY {
2775 //
2776 // Determine if drive is in a list of those requiring
2777 // autorun to be disabled. this is stored in a REG_MULTI_SZ
2778 // named AutoRunAlwaysDisable. this is required as some autochangers
2779 // must load the disc to reply to ChkVerify request, causing them
2780 // to cycle discs continuously.
2781 //
2782
2783 PWSTR nullMultiSz;
2784 PUCHAR vendorId;
2785 PUCHAR productId;
2786 PUCHAR revisionId;
2787 ULONG length;
2788 ULONG offset;
2789
2790 deviceString.Buffer = NULL;
2791 deviceUnicodeString.Buffer = NULL;
2792
2793 //
2794 // there may be nothing to check against
2795 //
2796
2797 if ((deviceDescriptor->VendorIdOffset == 0) &&
2798 (deviceDescriptor->ProductIdOffset == 0)) {
2799 LEAVE;
2800 }
2801
2802 length = 0;
2803
2804 if (deviceDescriptor->VendorIdOffset == 0) {
2805 vendorId = NULL;
2806 } else {
2807 vendorId = (PUCHAR) deviceDescriptor + deviceDescriptor->VendorIdOffset;
2808 length = (ULONG)strlen((PCSZ)vendorId);
2809 }
2810
2811 if ( deviceDescriptor->ProductIdOffset == 0 ) {
2812 productId = NULL;
2813 } else {
2814 productId = (PUCHAR)deviceDescriptor + deviceDescriptor->ProductIdOffset;
2815 length += (ULONG)strlen((PCSZ)productId);
2816 }
2817
2818 if ( deviceDescriptor->ProductRevisionOffset == 0 ) {
2819 revisionId = NULL;
2820 } else {
2821 revisionId = (PUCHAR) deviceDescriptor + deviceDescriptor->ProductRevisionOffset;
2822 length += (ULONG)strlen((PCSZ)revisionId);
2823 }
2824
2825 //
2826 // allocate a buffer for the string
2827 //
2828
2829 deviceString.Length = (USHORT)( length );
2830 deviceString.MaximumLength = deviceString.Length + 1;
2831 deviceString.Buffer = (PCHAR)ExAllocatePoolWithTag( NonPagedPoolNx,
2832 deviceString.MaximumLength,
2834 );
2835 if (deviceString.Buffer == NULL) {
2836 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2837 "ClassMediaChangeDisabledForHardware: Unable to alloc "
2838 "string buffer\n" ));
2839 LEAVE;
2840 }
2841
2842 //
2843 // copy strings to the buffer
2844 //
2845 offset = 0;
2846
2847 if (vendorId != NULL) {
2848 RtlCopyMemory(deviceString.Buffer + offset,
2849 vendorId,
2850 strlen((PCSZ)vendorId));
2851 offset += (ULONG)strlen((PCSZ)vendorId);
2852 }
2853
2854 if ( productId != NULL ) {
2855 RtlCopyMemory(deviceString.Buffer + offset,
2856 productId,
2857 strlen((PCSZ)productId));
2858 offset += (ULONG)strlen((PCSZ)productId);
2859 }
2860 if ( revisionId != NULL ) {
2861 RtlCopyMemory(deviceString.Buffer + offset,
2862 revisionId,
2863 strlen((PCSZ)revisionId));
2864 offset += (ULONG)strlen((PCSZ)revisionId);
2865 }
2866
2867 NT_ASSERT(offset == deviceString.Length);
2868
2869#ifdef _MSC_VER
2870 #pragma warning(suppress:6386) // Not an issue as deviceString.Buffer is of size deviceString.MaximumLength, which is equal to (deviceString.Length + 1)
2871#endif
2872 deviceString.Buffer[deviceString.Length] = '\0'; // Null-terminated
2873
2874 //
2875 // convert to unicode as registry deals with unicode strings
2876 //
2877
2878 status = RtlAnsiStringToUnicodeString( &deviceUnicodeString,
2879 &deviceString,
2880 TRUE
2881 );
2882 if (!NT_SUCCESS(status)) {
2883 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2884 "ClassMediaChangeDisabledForHardware: cannot convert "
2885 "to unicode %lx\n", status));
2886 LEAVE;
2887 }
2888
2889 //
2890 // query the value, setting valueFound to true if found
2891 //
2892 nullMultiSz = L"\0";
2894 parameters[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
2895 parameters[0].Name = L"AutoRunAlwaysDisable";
2896 parameters[0].EntryContext = &mediaChangeNotificationDisabled;
2897 parameters[0].DefaultType = REG_MULTI_SZ;
2898 parameters[0].DefaultData = nullMultiSz;
2899 parameters[0].DefaultLength = 0;
2900
2902 serviceKey,
2903 parameters,
2904 &deviceUnicodeString,
2905 NULL);
2906
2907 if ( !NT_SUCCESS(status) ) {
2908 LEAVE;
2909 }
2910
2911 } FINALLY {
2912
2913 FREE_POOL( deviceString.Buffer );
2914 if (deviceUnicodeString.Buffer != NULL) {
2915 RtlFreeUnicodeString( &deviceUnicodeString );
2916 }
2917
2918 ZwClose(serviceKey);
2919 }
2920
2921 if (mediaChangeNotificationDisabled) {
2922 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassMediaChangeDisabledForHardware: "
2923 "Device is on disable list\n"));
2924 return TRUE;
2925 }
2926 return FALSE;
2927
2928} // end ClasspIsMediaChangeDisabledDueToHardwareLimitation()
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack
Definition: autorun.c:96
#define FINALLY
Definition: classpnp.h:116
#define LEAVE
Definition: classpnp.h:115
#define CLASS_TAG_AUTORUN_DISABLE
Definition: classpnp.h:77
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLintptr offset
Definition: glext.h:5920
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define PCHAR
Definition: match.c:90
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define REG_MULTI_SZ
Definition: nt_native.h:1501
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define L(x)
Definition: ntvdm.h:50
USHORT MaximumLength
Definition: env_spec_w32.h:377
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
#define TRY(sps, bps)
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215

◆ ClasspIsMediaChangeDisabledForClass()

BOOLEAN ClasspIsMediaChangeDisabledForClass ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PUNICODE_STRING  RegistryPath 
)

Definition at line 2956 of file autorun.c.

2960{
2961 OBJECT_ATTRIBUTES objectAttributes = {0};
2962 HANDLE serviceKey = NULL;
2963 HANDLE parametersKey = NULL;
2964 RTL_QUERY_REGISTRY_TABLE parameters[3] = {0};
2965
2966 UNICODE_STRING paramStr;
2967
2968 //
2969 // Default to ENABLING MediaChangeNotification (!)
2970 //
2971
2972 ULONG mcnRegistryValue = 1;
2973
2975
2976
2977 PAGED_CODE();
2978
2979 //
2980 // open the service key.
2981 //
2982
2983 InitializeObjectAttributes(&objectAttributes,
2986 NULL,
2987 NULL);
2988
2989 status = ZwOpenKey(&serviceKey,
2990 KEY_READ,
2991 &objectAttributes);
2992
2994
2995 if(!NT_SUCCESS(status)) {
2996
2997 //
2998 // return the default value, which is the
2999 // inverse of the registry setting default
3000 // since this routine asks if it's disabled
3001 //
3002
3003 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassCheckServiceMCN: Defaulting to %s\n",
3004 (mcnRegistryValue ? "Enabled" : "Disabled")));
3005 return (BOOLEAN)(!mcnRegistryValue);
3006
3007 }
3008
3009 //
3010 // Open the parameters key (if any) beneath the services key.
3011 //
3012
3013 RtlInitUnicodeString(&paramStr, L"Parameters");
3014
3015 InitializeObjectAttributes(&objectAttributes,
3016 &paramStr,
3018 serviceKey,
3019 NULL);
3020
3021 status = ZwOpenKey(&parametersKey,
3022 KEY_READ,
3023 &objectAttributes);
3024
3025 if (!NT_SUCCESS(status)) {
3026 parametersKey = NULL;
3027 }
3028
3029
3030
3031 //
3032 // Check for the Autorun value.
3033 //
3034
3035 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
3036 parameters[0].Name = L"Autorun";
3037 parameters[0].EntryContext = &mcnRegistryValue;
3039 parameters[0].DefaultData = &mcnRegistryValue;
3040 parameters[0].DefaultLength = sizeof(ULONG);
3041
3042 // ignore failures
3044 serviceKey,
3045 parameters,
3046 NULL,
3047 NULL);
3048
3049 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassCheckServiceMCN: "
3050 "<Service>/Autorun flag = %d\n", mcnRegistryValue));
3051
3052 if(parametersKey != NULL) {
3053
3054 // ignore failures
3056 parametersKey,
3057 parameters,
3058 NULL,
3059 NULL);
3060 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassCheckServiceMCN: "
3061 "<Service>/Parameters/Autorun flag = %d\n",
3062 mcnRegistryValue));
3063 ZwClose(parametersKey);
3064
3065 }
3066 ZwClose(serviceKey);
3067
3068 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassCheckServiceMCN: "
3069 "Autoplay for device %p is %s\n",
3070 FdoExtension->DeviceObject,
3071 (mcnRegistryValue ? "on" : "off")
3072 ));
3073
3074 //
3075 // return if it is _disabled_, which is the
3076 // inverse of the registry setting
3077 //
3078
3079 return (BOOLEAN)(!mcnRegistryValue);
3080} // end ClasspIsMediaChangeDisabledForClass()
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
#define REG_DWORD
Definition: sdbapi.c:596
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT

◆ ClasspMcnControl()

NTSTATUS ClasspMcnControl ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PIRP  Irp,
IN PSCSI_REQUEST_BLOCK  Srb 
)

Definition at line 3276 of file autorun.c.

3281{
3282 PCOMMON_DEVICE_EXTENSION commonExtension =
3284
3286 PPREVENT_MEDIA_REMOVAL request = Irp->AssociatedIrp.SystemBuffer;
3287
3288 PFILE_OBJECT fileObject = irpStack->FileObject;
3289 PFILE_OBJECT_EXTENSION fsContext = NULL;
3290
3292
3293 PAGED_CODE();
3294
3295 //
3296 // Check to make sure we have a file object extension to keep track of this
3297 // request. If not we'll fail it before synchronizing.
3298 //
3299
3300 TRY {
3301
3302 if(fileObject != NULL) {
3303 fsContext = ClassGetFsContext(commonExtension, fileObject);
3304 }else if(Irp->RequestorMode == KernelMode) { // && fileObject == NULL
3305 fsContext = &FdoExtension->KernelModeMcnContext;
3306 }
3307
3308 if (fsContext == NULL) {
3309
3310 //
3311 // This handle isn't setup correctly. We can't let the
3312 // operation go.
3313 //
3314
3316 LEAVE;
3317 }
3318
3319 if(request->PreventMediaRemoval) {
3320
3321 //
3322 // This is a lock command. Reissue the command in case bus or
3323 // device was reset and the lock was cleared.
3324 //
3325
3326 ClassDisableMediaChangeDetection(FdoExtension);
3327 InterlockedIncrement((volatile LONG *)&(fsContext->McnDisableCount));
3328
3329 } else {
3330
3331 if(fsContext->McnDisableCount == 0) {
3333 LEAVE;
3334 }
3335
3336 InterlockedDecrement((volatile LONG *)&(fsContext->McnDisableCount));
3337 ClassEnableMediaChangeDetection(FdoExtension);
3338 }
3339
3340 } FINALLY {
3341
3342 Irp->IoStatus.Status = status;
3343
3344 FREE_POOL(Srb);
3345
3346 ClassReleaseRemoveLock(FdoExtension->DeviceObject, Irp);
3347 ClassCompleteRequest(FdoExtension->DeviceObject,
3348 Irp,
3350 }
3351 return status;
3352} // end ClasspMcnControl(
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
_In_ PIRP Irp
Definition: csq.h:116
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
Definition: tftpd.h:86
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define IO_NO_INCREMENT
Definition: iotypes.h:598
* PFILE_OBJECT
Definition: iotypes.h:1998

Referenced by ClassDeviceControl().

◆ ClasspMediaChangeDetectionCompletion()

NTSTATUS NTAPI ClasspMediaChangeDetectionCompletion ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp,
PVOID  Context 
)

Definition at line 1049 of file autorun.c.

1054{
1055 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
1059 BOOLEAN retryImmediately = FALSE;
1061
1063
1064 //
1065 // Since the class driver created this request, it's completion routine
1066 // will not get a valid device object handed in. Use the one in the
1067 // irp stack instead
1068 //
1069
1071 fdoExtension = DeviceObject->DeviceExtension;
1072 fdoData = fdoExtension->PrivateFdoData;
1073 info = fdoExtension->MediaChangeDetectionInfo;
1074
1075 NT_ASSERT(info->MediaChangeIrp != NULL);
1077 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "> ClasspMediaChangeDetectionCompletion: Device %p completed MCN irp %p.", DeviceObject, Irp));
1078
1079 /*
1080 * HACK for IoMega 2GB Jaz drive:
1081 * This drive spins down on its own to preserve the media.
1082 * When spun down, TUR fails with 2/4/0 (SCSI_SENSE_NOT_READY/SCSI_ADSENSE_LUN_NOT_READY/?).
1083 * InterpretSenseInfo routine would then call ClassSendStartUnit to spin the media up, which defeats the
1084 * purpose of the spindown.
1085 * So in this case, make this into a successful TUR.
1086 * This allows the drive to stay spun down until it is actually accessed again.
1087 * (If the media were actually removed, TUR would fail with 2/3a/0 ).
1088 * This hack only applies to drives with the CAUSE_NOT_REPORTABLE_HACK bit set; this
1089 * is set by disk.sys when HackCauseNotReportableHack is set for the drive in its BadControllers list.
1090 */
1091
1094
1095 PVOID senseData = SrbGetSenseInfoBuffer(Srb);
1096
1097 if (senseData) {
1098
1100 UCHAR senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb);
1101 UCHAR senseKey = 0;
1103
1104 validSense = ScsiGetSenseKeyAndCodes(senseData,
1105 senseInfoBufferLength,
1107 &senseKey,
1109 NULL);
1110
1111 if (validSense &&
1115 }
1116 }
1117 }
1118
1119 //
1120 // use InterpretSenseInfo routine to check for media state, and also
1121 // to call ClassError() with correct parameters.
1122 //
1125
1126 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - failed - srb status=%s, sense=%s/%s/%s.",
1128
1130 Irp,
1133 0,
1134 0,
1135 &status,
1136 NULL);
1137 }
1138 else {
1139
1141
1142 if (!info->Gesn.Supported) {
1143
1144 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - succeeded and GESN NOT supported, setting MediaPresent."));
1145
1146 //
1147 // success != media for GESN case
1148 //
1149
1150 ClassSetMediaChangeState(fdoExtension, MediaPresent, FALSE);
1151
1152 }
1153 else {
1154 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - succeeded (GESN supported)."));
1155 }
1156 }
1157
1158 if (info->Gesn.Supported) {
1159
1160 if (status == STATUS_DATA_OVERRUN) {
1161 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - Overrun"));
1163 }
1164
1165 if (!NT_SUCCESS(status)) {
1166 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion: GESN failed with status %x", status));
1167 } else {
1168
1169 //
1170 // for GESN, need to interpret the results of the data.
1171 // this may also require an immediate retry
1172 //
1173
1174 if (Irp->IoStatus.Information == 8 ) {
1175 ClasspInterpretGesnData(fdoExtension,
1176 (PVOID)info->Gesn.Buffer,
1177 &retryImmediately);
1178 }
1179
1180 } // end of NT_SUCCESS(status)
1181
1182 } // end of Info->Gesn.Supported
1183
1184 //
1185 // free port-allocated sense buffer, if any.
1186 //
1187
1188 if (PORT_ALLOCATED_SENSE_EX(fdoExtension, Srb)) {
1190 }
1191
1192 //
1193 // Remember the IRP and SRB for use the next time.
1194 //
1195
1198
1199 //
1200 // Reset the MCN timer.
1201 //
1202
1203 ClassResetMediaChangeTimer(fdoExtension);
1204
1205 //
1206 // run a sanity check to make sure we're not recursing continuously
1207 //
1208
1209 if (retryImmediately) {
1210
1211 info->MediaChangeRetryCount++;
1212
1213 if (info->MediaChangeRetryCount > MAXIMUM_IMMEDIATE_MCN_RETRIES) {
1214
1215 //
1216 // Disable GESN on this device.
1217 // Create a work item to set the value in the registry
1218 //
1219
1220 PIO_WORKITEM workItem;
1221
1222 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion: Disabling GESN for device %p", DeviceObject));
1223
1224 workItem = IoAllocateWorkItem(DeviceObject);
1225
1226 if (workItem) {
1228 }
1229
1230 info->Gesn.Supported = 0;
1231 info->Gesn.EventMask = 0;
1232 info->Gesn.BufferSize = 0;
1233 info->MediaChangeRetryCount = 0;
1234 retryImmediately = FALSE;
1235 }
1236
1237 } else {
1238
1239 info->MediaChangeRetryCount = 0;
1240
1241 }
1242
1243
1244 //
1245 // release the remove lock....
1246 //
1247
1248 {
1249 UCHAR uniqueValue = 0;
1250 ClassAcquireRemoveLock(DeviceObject, (PVOID)(&uniqueValue));
1252
1253
1254 //
1255 // set the irp as not in use
1256 //
1257 {
1258#if DBG
1259 volatile LONG irpWasInUse;
1260 irpWasInUse = InterlockedCompareExchange(&info->MediaChangeIrpInUse, 0, 1);
1261 #if _MSC_FULL_VER != 13009111 // This compiler always takes the wrong path here.
1262 NT_ASSERT(irpWasInUse);
1263 #endif
1264#else
1265 InterlockedCompareExchange(&info->MediaChangeIrpInUse, 0, 1);
1266#endif
1267 }
1268
1269 //
1270 // now send it again before we release our last remove lock
1271 //
1272
1273 if (retryImmediately) {
1274 ClasspSendMediaStateIrp(fdoExtension, info, 0);
1275 }
1276 else {
1277 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - not retrying immediately"));
1278 }
1279
1280 //
1281 // release the temporary remove lock
1282 //
1283
1284 ClassReleaseRemoveLock(DeviceObject, (PVOID)(&uniqueValue));
1285 }
1286
1287 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "< ClasspMediaChangeDetectionCompletion"));
1288
1290}
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
FORCEINLINE BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
FORCEINLINE VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
VOID NTAPI ClassResetMediaChangeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1804
IO_WORKITEM_ROUTINE ClasspDisableGesn
Definition: autorun.c:114
#define MAXIMUM_IMMEDIATE_MCN_RETRIES
Definition: autorun.c:35
#define DBGGETADSENSECODESTR(_pSrb)
Definition: debug.h:29
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
Definition: debug.h:30
#define DBGGETSRBSTATUSSTR(_pSrb)
Definition: debug.h:27
#define DBGGETSENSECODESTR(_pSrb)
Definition: debug.h:28
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK
Definition: scsi_port.h:175
UCHAR additionalSenseCode
Definition: scsi.h:4020
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3839
UCHAR senseKey
Definition: scsi.h:4019
BOOLEAN validSense
Definition: scsi.h:4018
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695

◆ ClasspMediaChangeDeviceInstanceOverride()

NTSTATUS ClasspMediaChangeDeviceInstanceOverride ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
OUT PBOOLEAN  Enabled 
)

Definition at line 2563 of file autorun.c.

2567{
2568 HANDLE deviceParameterHandle = NULL; // cdrom instance key
2569 HANDLE driverParameterHandle = NULL; // cdrom specific key
2570 RTL_QUERY_REGISTRY_TABLE queryTable[3];
2571 OBJECT_ATTRIBUTES objectAttributes;
2572 UNICODE_STRING subkeyName;
2574 ULONG alwaysEnable = FALSE;
2575 ULONG alwaysDisable = FALSE;
2576 ULONG i;
2577
2578 PAGED_CODE();
2579
2580 TRY {
2581
2585 &deviceParameterHandle
2586 );
2587 if (!NT_SUCCESS(status)) {
2588
2589 //
2590 // this can occur when a new device is added to the system
2591 // this is due to cdrom.sys being an 'essential' driver
2592 //
2593 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2594 "ClassMediaChangeDeviceInstanceDisabled: "
2595 "Could not open device registry key [%lx]\n", status));
2596 LEAVE;
2597 }
2598
2600 InitializeObjectAttributes(&objectAttributes,
2601 &subkeyName,
2603 deviceParameterHandle,
2605
2606 status = ZwCreateKey(&driverParameterHandle,
2607 KEY_READ,
2608 &objectAttributes,
2609 0,
2612 NULL);
2613
2614 if (!NT_SUCCESS(status)) {
2615 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2616 "ClassMediaChangeDeviceInstanceDisabled: "
2617 "subkey could not be created. %lx\n", status));
2618 LEAVE;
2619 }
2620
2621 //
2622 // Default to not changing autorun behavior, based upon setting
2623 // registryValue to zero.
2624 //
2625
2626 for (i=0;i<2;i++) {
2627
2628 RtlZeroMemory(&queryTable[0], sizeof(queryTable));
2629
2632 queryTable[0].DefaultLength = 0;
2633
2634 if (i==0) {
2636 queryTable[0].EntryContext = &alwaysDisable;
2637 queryTable[0].DefaultData = &alwaysDisable;
2638 } else {
2640 queryTable[0].EntryContext = &alwaysEnable;
2641 queryTable[0].DefaultData = &alwaysEnable;
2642 }
2643
2644 //
2645 // don't care if it succeeds, since we set defaults above
2646 //
2647
2649 (PWSTR)driverParameterHandle,
2650 queryTable,
2651 NULL,
2652 NULL);
2653 }
2654
2655 } FINALLY {
2656
2657 if (driverParameterHandle) ZwClose(driverParameterHandle);
2658 if (deviceParameterHandle) ZwClose(deviceParameterHandle);
2659
2660 }
2661
2662 if (alwaysEnable && alwaysDisable) {
2663
2664 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2665 "ClassMediaChangeDeviceInstanceDisabled: %s selected\n",
2666 "Both Enable and Disable set -- DISABLE"));
2669 *Enabled = FALSE;
2670
2671 } else if (alwaysDisable) {
2672
2673 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2674 "ClassMediaChangeDeviceInstanceDisabled: %s selected\n",
2675 "DISABLE"));
2678 *Enabled = FALSE;
2679
2680 } else if (alwaysEnable) {
2681
2682 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2683 "ClassMediaChangeDeviceInstanceDisabled: %s selected\n",
2684 "ENABLE"));
2687 *Enabled = TRUE;
2688
2689 } else {
2690
2691 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2692 "ClassMediaChangeDeviceInstanceDisabled: %s selected\n",
2693 "DEFAULT"));
2695
2696 }
2697
2698 return status;
2699
2700} // end ClasspMediaChangeDeviceInstanceOverride()
#define MCN_REG_SUBKEY_NAME
Definition: autorun.c:36
#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME
Definition: autorun.c:38
#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME
Definition: autorun.c:37
@ Enabled
Definition: mountmgr.h:159
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define REG_NONE
Definition: nt_native.h:1492
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:1621
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2786
#define RTL_QUERY_REGISTRY_TYPECHECK

◆ ClasspPrepareMcnIrp()

PIRP ClasspPrepareMcnIrp ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO  Info,
IN BOOLEAN  UseGesn 
)

Definition at line 1310 of file autorun.c.

1315{
1318 PIO_STACK_LOCATION irpStack;
1319 PIO_STACK_LOCATION nextIrpStack;
1321 PCDB cdb;
1322 PIRP irp;
1323 PVOID buffer;
1325 ULONG srbFlags;
1326 ULONG timeOutValue;
1327 UCHAR cdbLength;
1329 ULONG dataTransferLength;
1330
1331 //
1332 // Setup the IRP to perform a test unit ready.
1333 //
1334
1335 irp = Info->MediaChangeIrp;
1336
1337 if (irp == NULL) {
1338 NT_ASSERT(irp);
1339 return NULL;
1340 }
1341
1342 //
1343 // don't keep sending this if the device is being removed.
1344 //
1345
1347 if (status == REMOVE_COMPLETE) {
1349 return NULL;
1350 }
1351 else if (status == REMOVE_PENDING) {
1352 ClassReleaseRemoveLock(FdoExtension->DeviceObject, irp);
1353 return NULL;
1354 }
1355 else {
1357 }
1358
1360
1361 /*
1362 * For the driver that creates an IRP, there is no 'current' stack location.
1363 * Step down one IRP stack location so that the extra top one
1364 * becomes our 'current' one.
1365 */
1367
1368 /*
1369 * Cache our device object in the extra top IRP stack location
1370 * so we have it in our completion routine.
1371 */
1373 irpStack->DeviceObject = FdoExtension->DeviceObject;
1374
1375 //
1376 // If the irp is sent down when the volume needs to be
1377 // verified, CdRomUpdateGeometryCompletion won't complete
1378 // it since it's not associated with a thread. Marking
1379 // it to override the verify causes it always be sent
1380 // to the port driver
1381 //
1382
1383 irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1384
1385 nextIrpStack = IoGetNextIrpStackLocation(irp);
1387 nextIrpStack->Parameters.Scsi.Srb = &(Info->MediaChangeSrb.Srb);
1388
1389 //
1390 // Prepare the SRB for execution.
1391 //
1392
1393 buffer = Info->SenseBuffer;
1394 bufferLength = Info->SenseBufferLength;
1395
1398
1399 srbFlags = FdoExtension->SrbFlags;
1400 SET_FLAG(srbFlags, Info->SrbFlags);
1401
1402 timeOutValue = FdoExtension->TimeOutValue * 2;
1403 if (timeOutValue == 0) {
1404
1405 if (FdoExtension->TimeOutValue == 0) {
1406
1407 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
1408 "ClassSendTestUnitIrp: FdoExtension->TimeOutValue "
1409 "is set to zero?! -- resetting to 10\n"));
1410 timeOutValue = 10 * 2; // reasonable default
1411
1412 } else {
1413
1414 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
1415 "ClassSendTestUnitIrp: Someone set "
1416 "srb->TimeOutValue to zero?! -- resetting to %x\n",
1417 FdoExtension->TimeOutValue * 2));
1418 timeOutValue = FdoExtension->TimeOutValue * 2;
1419
1420 }
1421
1422 }
1423
1424 if (!UseGesn) {
1425 nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_NONE;
1426 irp->MdlAddress = NULL;
1427
1429
1430 //
1431 // Set SRB_FLAGS_NO_KEEP_AWAKE for non-cdrom devices if these requests should
1432 // not prevent devices from going to sleep.
1433 //
1434 if ((FdoExtension->DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) &&
1435 (ClasspScreenOff == TRUE)) {
1437 }
1438
1439 cdbLength = 6;
1440 dataBuffer = NULL;
1441 dataTransferLength = 0;
1442
1443 } else {
1444 NT_ASSERT(Info->Gesn.Buffer);
1445
1446 nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1447 irp->MdlAddress = Info->Gesn.Mdl;
1448
1449 SET_FLAG(srbFlags, SRB_FLAGS_DATA_IN);
1450 cdbLength = 10;
1451 dataBuffer = Info->Gesn.Buffer;
1452 dataTransferLength = Info->Gesn.BufferSize;
1453 timeOutValue = GESN_TIMEOUT_VALUE; // much shorter timeout for GESN
1454
1455 }
1456
1457 //
1458 // SRB used here is the MediaChangeSrb in _MEDIA_CHANGE_DETECTION_INFO.
1459 //
1460 srb = nextIrpStack->Parameters.Scsi.Srb;
1461 if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1462 srbEx = (PSTORAGE_REQUEST_BLOCK)nextIrpStack->Parameters.Scsi.Srb;
1463
1467 1,
1469 if (!NT_SUCCESS(status)) {
1470 // should not happen
1472 return NULL;
1473 }
1474
1475 srbEx->RequestTag = SP_UNTAGGED;
1476 srbEx->RequestAttribute = SRB_SIMPLE_TAG_REQUEST;
1477 srbEx->SrbFunction = SRB_FUNCTION_EXECUTE_SCSI;
1478 srbEx->SrbStatus = 0;
1479 srbEx->OriginalRequest = irp;
1480 srbEx->SrbFlags = srbFlags;
1481 srbEx->TimeOutValue = timeOutValue;
1482 srbEx->DataBuffer = dataBuffer;
1483 srbEx->DataTransferLength = dataTransferLength;
1484
1485 SrbSetScsiStatus(srbEx, 0);
1488 SrbSetCdbLength(srbEx, cdbLength);
1489
1490 cdb = SrbGetCdb(srbEx);
1491
1492 } else {
1493 RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1494
1495 srb->QueueTag = SP_UNTAGGED;
1497 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1499 srb->SenseInfoBuffer = buffer;
1501 srb->SrbStatus = 0;
1502 srb->ScsiStatus = 0;
1503 srb->OriginalRequest = irp;
1504
1505 srb->SrbFlags = srbFlags;
1506 srb->TimeOutValue = timeOutValue;
1507 srb->CdbLength = cdbLength;
1508 srb->DataBuffer = dataBuffer;
1509 srb->DataTransferLength = dataTransferLength;
1510
1511 cdb = (PCDB) &srb->Cdb[0];
1512
1513 }
1514
1515 if (cdb) {
1516 if (!UseGesn) {
1517 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1518 } else {
1519 cdb->GET_EVENT_STATUS_NOTIFICATION.OperationCode =
1521 cdb->GET_EVENT_STATUS_NOTIFICATION.Immediate = 1;
1522 cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[0] =
1523 (UCHAR)((Info->Gesn.BufferSize) >> 8);
1524 cdb->GET_EVENT_STATUS_NOTIFICATION.EventListLength[1] =
1525 (UCHAR)((Info->Gesn.BufferSize) & 0xff);
1526 cdb->GET_EVENT_STATUS_NOTIFICATION.NotificationClassRequest =
1527 Info->Gesn.EventMask;
1528 }
1529 }
1530
1533 srb,
1534 TRUE,
1535 TRUE,
1536 TRUE);
1537
1538 return irp;
1539
1540}
_In_ BOOLEAN UseGesn
Definition: cdrom.h:1363
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SCSIOP_GET_EVENT_STATUS
Definition: cdrw_hw.h:934
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
union _CDB * PCDB
#define GESN_TIMEOUT_VALUE
Definition: autorun.c:31
IO_COMPLETION_ROUTINE ClasspMediaChangeDetectionCompletion
Definition: autorun.c:116
#define NO_REMOVE
Definition: classpnp.h:96
#define REMOVE_PENDING
Definition: classpnp.h:97
#define SP_UNTAGGED
Definition: srb.h:233
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:402
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:423
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
PVOID dataBuffer
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:664
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
UCHAR QueueTag
Definition: srb.h:256
ULONG TimeOutValue
Definition: srb.h:262
PVOID OriginalRequest
Definition: srb.h:266
PVOID DataBuffer
Definition: srb.h:263
UCHAR QueueAction
Definition: srb.h:257
UCHAR Cdb[16]
Definition: srb.h:279
UCHAR Function
Definition: srb.h:250
UCHAR ScsiStatus
Definition: srb.h:252
ULONG DataTransferLength
Definition: srb.h:261
ULONG SrbFlags
Definition: srb.h:260
Definition: cdrw_hw.h:28
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _CDB::_GET_EVENT_STATUS_NOTIFICATION GET_EVENT_STATUS_NOTIFICATION
#define SrbGetCdb(srb)
Definition: usbstor.h:18
_In_opt_ PVOID _In_ ULONG bufferLength
Definition: wdfdriver.h:109
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IRP_MJ_INTERNAL_DEVICE_CONTROL

Referenced by ClasspInitializeGesn(), and ClasspSendMediaStateIrp().

◆ ClasspSendMediaStateIrp()

VOID ClasspSendMediaStateIrp ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN PMEDIA_CHANGE_DETECTION_INFO  Info,
IN ULONG  CountDown 
)

Definition at line 1559 of file autorun.c.

1564{
1565 BOOLEAN requestPending = FALSE;
1566 LONG irpInUse;
1567
1568 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "> ClasspSendMediaStateIrp"));
1569
1570 if (((FdoExtension->CommonExtension.CurrentState != IRP_MN_START_DEVICE) ||
1571 (FdoExtension->DevicePowerState != PowerDeviceD0)
1572 ) &&
1573 (!Info->MediaChangeIrpLost)) {
1574
1575 //
1576 // the device may be stopped, powered down, or otherwise queueing io,
1577 // so should not timeout the autorun irp (yet) -- set to zero ticks.
1578 // scattered code relies upon this to not prematurely "lose" an
1579 // autoplay irp that was queued.
1580 //
1581
1582 Info->MediaChangeIrpTimeInUse = 0;
1583 }
1584
1585 //
1586 // if the irp is not in use, mark it as such.
1587 //
1588
1589 irpInUse = InterlockedCompareExchange(&Info->MediaChangeIrpInUse, 1, 0);
1590
1591 if (irpInUse) {
1592
1593 LONG timeInUse;
1594
1595 timeInUse = InterlockedIncrement(&Info->MediaChangeIrpTimeInUse);
1596
1597 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "ClasspSendMediaStateIrp: irp in use for "
1598 "%x seconds when synchronizing for MCD\n", timeInUse));
1599
1600 if (Info->MediaChangeIrpLost == FALSE) {
1601
1602 if (timeInUse > MEDIA_CHANGE_TIMEOUT_TIME) {
1603
1604 //
1605 // currently set to five minutes. hard to imagine a drive
1606 // taking that long to spin up.
1607 //
1608
1609 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
1610 "CdRom%d: Media Change Notification has lost "
1611 "it's irp and doesn't know where to find it. "
1612 "Leave it alone and it'll come home dragging "
1613 "it's stack behind it.\n",
1614 FdoExtension->DeviceNumber));
1615 Info->MediaChangeIrpLost = TRUE;
1616 }
1617 }
1618
1619 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "< ClasspSendMediaStateIrp - irpInUse"));
1620 return;
1621
1622 }
1623
1624 TRY {
1625
1626 if (Info->MediaChangeDetectionDisableCount != 0) {
1627 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassCheckMediaState: device %p has "
1628 " detection disabled \n", FdoExtension->DeviceObject));
1629 LEAVE;
1630 }
1631
1632 if (FdoExtension->DevicePowerState != PowerDeviceD0) {
1633
1634 //
1635 // It's possible that the device went to D3 while the screen was
1636 // off so we need to make sure that we send the IRP regardless
1637 // of the device's power state in order to wake the device back
1638 // up when the screen comes back on.
1639 // When the screen is off we set the SRB_FLAG_NO_KEEP_AWAKE flag
1640 // so that the lower driver does not power-up the device for this
1641 // request. When the screen comes back on, however, we want to
1642 // resume checking for media presence so we no longer set the flag.
1643 // When the device is in D3 we also stop the polling timer as well.
1644 //
1645
1646 //
1647 // NOTE: we don't increment the time in use until our power state
1648 // changes above. this way, we won't "lose" the autoplay irp.
1649 // it's up to the lower driver to determine if powering up is a
1650 // good idea.
1651 //
1652
1653 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1654 "ClassCheckMediaState: device %p needs to powerup "
1655 "to handle this io (may take a few extra seconds).\n",
1656 FdoExtension->DeviceObject));
1657 }
1658
1659 Info->MediaChangeIrpTimeInUse = 0;
1660 Info->MediaChangeIrpLost = FALSE;
1661
1662 if (CountDown == 0) {
1663
1664 PIRP irp;
1665
1666 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1667 "ClassCheckMediaState: timer expired\n"));
1668
1669 if (Info->MediaChangeDetectionDisableCount != 0) {
1670 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1671 "ClassCheckMediaState: detection disabled\n"));
1672 LEAVE;
1673 }
1674
1675 //
1676 // Prepare the IRP for the test unit ready
1677 //
1678
1680 Info,
1681 Info->Gesn.Supported);
1682
1683 //
1684 // Issue the request.
1685 //
1686
1687 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN,
1688 "ClasspSendMediaStateIrp: Device %p getting TUR "
1689 " irp %p\n", FdoExtension->DeviceObject, irp));
1690
1691 if (irp == NULL) {
1692 LEAVE;
1693 }
1694
1695
1696 //
1697 // note: if we send it to the class dispatch routines, there is
1698 // a timing window here (since they grab the remove lock)
1699 // where we'd be removed. ELIMINATE the window by grabbing
1700 // the lock ourselves above and sending it to the lower
1701 // device object directly or to the device's StartIo
1702 // routine (which doesn't acquire the lock).
1703 //
1704
1705 requestPending = TRUE;
1706
1707 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, " ClasspSendMediaStateIrp - calling IoCallDriver."));
1708 IoCallDriver(FdoExtension->CommonExtension.LowerDeviceObject, irp);
1709 }
1710
1711 } FINALLY {
1712
1713 if(requestPending == FALSE) {
1714#if DBG
1715 irpInUse = InterlockedCompareExchange(&Info->MediaChangeIrpInUse, 0, 1);
1716 #if _MSC_FULL_VER != 13009111 // This compiler always takes the wrong path here.
1717 NT_ASSERT(irpInUse);
1718 #endif
1719#else
1720 InterlockedCompareExchange(&Info->MediaChangeIrpInUse, 0, 1);
1721#endif
1722 }
1723
1724 }
1725
1726 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "< ClasspSendMediaStateIrp"));
1727
1728 return;
1729} // end ClasspSendMediaStateIrp()
#define MEDIA_CHANGE_TIMEOUT_TIME
Definition: cdrom.h:135
#define IRP_MN_START_DEVICE

Referenced by ClassCheckMediaState(), and ClasspMediaChangeDetectionCompletion().

◆ ClasspSetMediaChangeStateEx()

VOID ClasspSetMediaChangeStateEx ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension,
IN MEDIA_CHANGE_DETECTION_STATE  NewState,
IN BOOLEAN  Wait,
IN BOOLEAN  KnownStateChange 
)

Definition at line 950 of file autorun.c.

956{
957 PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
960
961 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "> ClasspSetMediaChangeStateEx"));
962
963 //
964 // Reset SMART status on media removal as the old status may not be
965 // valid when there is no media in the device or when new media is
966 // inserted.
967 //
968
969 if (NewState == MediaNotPresent) {
970
971 FdoExtension->FailurePredicted = FALSE;
972 FdoExtension->FailureReason = 0;
973
974 }
975
976
977 zero.QuadPart = 0;
978
979 if(info == NULL) {
980 return;
981 }
982
983 status = KeWaitForMutexObject(&info->MediaChangeMutex,
984 Executive,
986 FALSE,
987 ((Wait == TRUE) ? NULL : &zero));
988
989 if(status == STATUS_TIMEOUT) {
990
991 //
992 // Someone else is in the process of setting the media state
993 //
994
995 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspSetMediaChangeStateEx - timed out waiting for mutex"));
996 return;
997 }
998
999 //
1000 // Change the media present state and signal an event, if applicable
1001 //
1002
1003 ClasspInternalSetMediaChangeState(FdoExtension, NewState, KnownStateChange);
1004
1005 KeReleaseMutex(&info->MediaChangeMutex, FALSE);
1006
1007 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "< ClasspSetMediaChangeStateEx"));
1008
1009 return;
1010} // end ClassSetMediaChangeStateEx()
VOID ClasspInternalSetMediaChangeState(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN KnownStateChange)
Definition: autorun.c:798
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
int zero
Definition: sehframes.cpp:29
#define KeWaitForMutexObject
Definition: kefuncs.h:543

Referenced by _IRQL_requires_max_(), and ClasspInterpretGesnData().

◆ ClasspTimerTickEx()

VOID ClasspTimerTickEx ( _In_ PEX_TIMER  Timer,
_In_opt_ PVOID  Context 
)

Definition at line 3462 of file autorun.c.

3466{
3467 KDPC dummyDpc = { 0 };
3468
3470 //
3471 // This is just a wrapper around ClasspTimerTick that allows us to make
3472 // the TickTimer a no-wake EX_TIMER.
3473 // We pass in a dummy DPC b/c ClasspTimerTick expects a non-NULL parameter
3474 // for the DPC. However, ClasspTimerTick does not actually reference it.
3475 //
3476 ClasspTimerTick(&dummyDpc, Context, NULL, NULL);
3477}
Definition: ketypes.h:699

◆ ClasspUpdateTimerNoWakeTolerance()

BOOLEAN ClasspUpdateTimerNoWakeTolerance ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 3653 of file autorun.c.

3680{
3681 PCLASS_PRIVATE_FDO_DATA fdoData = NULL;
3682
3683 if (FdoExtension->CommonExtension.IsFdo) {
3684 fdoData = FdoExtension->PrivateFdoData;
3685 }
3686
3687 if (fdoData != NULL &&
3688 fdoData->TickTimer != NULL &&
3689 fdoData->TimerInitialized &&
3690 fdoData->TickTimerEnabled) {
3691
3692 LONGLONG noWakeTolerance = TICK_TIMER_DELAY_IN_MSEC * (10 * 1000);
3693
3694 //
3695 // Set the no-wake tolerance to "unlimited" if the conditions below
3696 // are met. An "unlimited" no-wake tolerance means that the timer
3697 // will *never* wake the processor if the processor is in a
3698 // low-power state.
3699 // 1. The screen is off.
3700 // 2. The class driver is *not* a consumer of the tick timer (ClassTick is NULL).
3701 // 3. This is a disk device.
3702 // Otherwise the tolerance is set to the normal, default tolerable delay.
3703 //
3704 if (ClasspScreenOff &&
3705 FdoExtension->CommonExtension.DriverExtension->InitData.ClassTick == NULL &&
3706 FdoExtension->DeviceObject->DeviceType == FILE_DEVICE_DISK) {
3707 noWakeTolerance = EX_TIMER_UNLIMITED_TOLERANCE;
3708 }
3709
3710 //
3711 // The new tolerance is different from the current tolerance so we need
3712 // to set/reset the timer with the new tolerance value.
3713 //
3714 if (fdoData->CurrentNoWakeTolerance != noWakeTolerance) {
3715 EXT_SET_PARAMETERS parameters;
3716 LONGLONG period = TICK_TIMER_PERIOD_IN_MSEC * (10 * 1000); // Convert to units of 100ns.
3717 LONGLONG dueTime = period * (-1); // Negative sign indicates dueTime is relative.
3718
3719 ExInitializeSetTimerParameters(&parameters);
3720 parameters.NoWakeTolerance = noWakeTolerance;
3721 fdoData->CurrentNoWakeTolerance = noWakeTolerance;
3722
3723 ExSetTimer(fdoData->TickTimer,
3724 dueTime,
3725 period,
3726 &parameters);
3727
3728 return TRUE;
3729 }
3730 }
3731
3732 return FALSE;
3733}

Referenced by _Function_class_().

◆ ClassResetMediaChangeTimer()

VOID NTAPI ClassResetMediaChangeTimer ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 1804 of file autorun.c.

1807{
1808 PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
1809
1810 if(info != NULL) {
1811 InterlockedExchange(&(info->MediaChangeCountDown),
1813 }
1814 return;
1815} // end ClassResetMediaChangeTimer()

Referenced by ClasspMediaChangeDetectionCompletion().

◆ ClassSendEjectionNotification()

VOID ClassSendEjectionNotification ( IN PFUNCTIONAL_DEVICE_EXTENSION  FdoExtension)

Definition at line 155 of file autorun.c.

158{
159 //
160 // For post-NT5.1 work, need to move EjectSynchronizationEvent
161 // to be a MUTEX so we can attempt to grab it here and benefit
162 // from deadlock detection. This will allow checking if the media
163 // has been locked by programs before broadcasting these events.
164 // (what's the point of broadcasting if the media is not locked?)
165 //
166 // This would currently only be a slight optimization. For post-NT5.1,
167 // it would allow us to send a single PERSISTENT_PREVENT to MMC devices,
168 // thereby cleaning up a lot of the ejection code. Then, when the
169 // ejection request occured, we could see if any locks for the media
170 // existed. if locked, broadcast. if not, we send the eject irp.
171 //
172
173 //
174 // for now, just always broadcast. make this a public routine,
175 // so class drivers can add special hacks to broadcast this for their
176 // non-MMC-compliant devices also from sense codes.
177 //
178
179 TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassSendEjectionNotification: media EJECT_REQUEST"));
180 ClassSendNotification(FdoExtension,
181 &GUID_IO_MEDIA_EJECT_REQUEST,
182 0,
183 NULL);
184 return;
185}

Referenced by ClassInterpretSenseInfo(), and ClasspInterpretGesnData().

Variable Documentation

◆ BreakOnMcnDisable

ULONG BreakOnMcnDisable = FALSE

Definition at line 3183 of file autorun.c.

◆ ClasspDisableGesn

IO_WORKITEM_ROUTINE ClasspDisableGesn

Definition at line 114 of file autorun.c.

Referenced by ClasspMediaChangeDetectionCompletion().

◆ ClasspFailurePredict

IO_WORKITEM_ROUTINE ClasspFailurePredict

Definition at line 105 of file autorun.c.

Referenced by _Function_class_().

◆ ClasspMediaChangeDetectionCompletion

IO_COMPLETION_ROUTINE ClasspMediaChangeDetectionCompletion

Definition at line 116 of file autorun.c.

Referenced by ClasspPrepareMcnIrp().

◆ ClasspMediaChangeRegistryCallBack

RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack

Definition at line 96 of file autorun.c.

Referenced by ClasspIsMediaChangeDisabledDueToHardwareLimitation().

◆ ClasspScreenOff

◆ ClasspTimerTick

KDEFERRED_ROUTINE ClasspTimerTick

Definition at line 118 of file autorun.c.

Referenced by _Function_class_(), ClasspInitializeTimer(), and ClasspTimerTickEx().

◆ ClasspTimerTickEx

EXT_CALLBACK ClasspTimerTickEx

Definition at line 121 of file autorun.c.

Referenced by ClasspInitializeTimer().

◆ StoragePredictFailureEventGuid

const GUID StoragePredictFailureEventGuid = WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID

Definition at line 40 of file autorun.c.