ReactOS  0.4.15-dev-980-ge160524
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

__inline 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_ ( 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) {
3404  return STATUS_INVALID_PARAMETER;
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 TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:56
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4154
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4142
smooth NULL
Definition: ftsmooth.c:416
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
unsigned int * PULONG
Definition: retypes.h:1
struct tagContext Context
Definition: acpixf.h:1034
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define PAGED_CODE()
#define REG_SZ
Definition: layer.c:22

◆ _Function_class_() [2/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 
3606  ClassAcquireRemoveLock(fdoExtension->DeviceObject,
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 
3640  commonExtension->DriverExtension->InitData.ClassTick(DeviceObject);
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 ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
#define REMOVE_COMPLETE
Definition: classpnp.h:98
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
PCLASS_TICK ClassTick
Definition: classpnp.h:545
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:511
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
#define InterlockedDecrement
Definition: armddk.h:52
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
#define InterlockedExchange
Definition: armddk.h:54
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
IO_WORKITEM_ROUTINE ClasspFailurePredict
Definition: autorun.c:105
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
unsigned int ULONG
Definition: retypes.h:1
__inline BOOLEAN ClasspCanSendPollingIrp(_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension)
Definition: autorun.c:61
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
#define NT_ASSERT
Definition: rtlfuncs.h:3312
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675

◆ _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 
242  notification,
243  NULL, NULL);
244 
246  return;
247 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
_In_ const GUID _In_ ULONG ExtraDataSize
Definition: classpnp.h:1429
LONG NTSTATUS
Definition: precomp.h:26
static GUID * Guid
Definition: apphelp.c:93
smooth NULL
Definition: ftsmooth.c:416
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
unsigned short USHORT
Definition: pedump.c:61
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
NTSTATUS NTAPI IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PVOID NotificationStructure, IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, IN PVOID Context OPTIONAL)
Definition: pnpreport.c:515
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

◆ _IRQL_requires_max_() [2/2]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 1012 of file autorun.c.

1020 {
1022  return;
1023 }
#define FALSE
Definition: types.h:117
VOID ClasspSetMediaChangeStateEx(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN Wait, IN BOOLEAN KnownStateChange)
Definition: autorun.c:950
IN BOOLEAN Wait
Definition: fatprocs.h:1538

◆ 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
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
long LONG
Definition: pedump.c:60
smooth NULL
Definition: ftsmooth.c:416
#define InterlockedDecrement
Definition: armddk.h:52

Referenced by _Function_class_(), and ClasspStorageEventNotification().

◆ ClasspCanSendPollingIrp()

__inline BOOLEAN ClasspCanSendPollingIrp ( _In_ PFUNCTIONAL_DEVICE_EXTENSION  fdoExtension)

Definition at line 61 of file autorun.c.

64 {
65  return ((fdoExtension->DevicePowerState == PowerDeviceD0) &&
66  (fdoExtension->PowerDownInProgress == FALSE) &&
67  (ClasspScreenOff == FALSE));
68 }
#define FALSE
Definition: types.h:117
BOOLEAN ClasspScreenOff
Definition: autorun.c:124

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 }
PEX_TIMER TickTimer
Definition: classp.h:676
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN TimerInitialized
Definition: classp.h:752
BOOLEAN TickTimerEnabled
Definition: classp.h:813

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;
2379  PIO_WORKITEM WorkItem = (PIO_WORKITEM)Context;
2380 
2381  PAGED_CODE();
2382 
2383  //
2384  // Set the hack flag in the registry
2385  //
2386  ClassSetDeviceParameter(fdoExtension,
2390  _Analysis_assume_(WorkItem != NULL);
2391  IoFreeWorkItem(WorkItem);
2392 }
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
smooth NULL
Definition: ftsmooth.c:416
#define CLASSP_REG_SUBKEY_NAME
Definition: classp.h:112
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: classp.h:115
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:478
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
#define PAGED_CODE()

◆ 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()
PEX_TIMER TickTimer
Definition: classp.h:676
#define TRUE
Definition: types.h:120
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN TimerInitialized
Definition: classp.h:752
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
BOOLEAN TickTimerEnabled
Definition: classp.h:813
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define NT_ASSERT
Definition: rtlfuncs.h:3312

Referenced by ClassDispatchPnp(), ClassPnpStartDevice(), 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) {
3875  NTSTATUS status;
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) {
3903  parameters.NoWakeTolerance = EX_TIMER_UNLIMITED_TOLERANCE;
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()
PEX_TIMER TickTimer
Definition: classp.h:676
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
Definition: dhcpd.h:245
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
GLbitfield GLuint64 timeout
Definition: glext.h:7164
#define TICK_TIMER_PERIOD_IN_MSEC
Definition: autorun.c:129
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN TimerInitialized
Definition: classp.h:752
int64_t LONGLONG
Definition: typedefs.h:68
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
#define TICK_TIMER_DELAY_IN_MSEC
Definition: autorun.c:130
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LONGLONG CurrentNoWakeTolerance
Definition: classp.h:677
BOOLEAN TickTimerEnabled
Definition: classp.h:813
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
static SERVICE_STATUS status
Definition: service.c:31
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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

◆ ClasspFailurePredict()

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

Definition at line 4017 of file autorun.c.

4021 {
4023  PIO_WORKITEM workItem;
4024  STORAGE_PREDICT_FAILURE checkFailure = {0};
4025  SCSI_ADDRESS scsiAddress = {0};
4027 
4028  NTSTATUS status;
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,
4077  sizeof(STORAGE_PREDICT_FAILURE),
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()
UCHAR PathId
Definition: scsi_port.h:149
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
UCHAR TargetId
Definition: scsi_port.h:150
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
struct TraceInfo Info
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define VOID
Definition: acefi.h:82
struct _cl_event * event
Definition: glext.h:7739
#define InterlockedExchange
Definition: armddk.h:54
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
#define IOCTL_STORAGE_PREDICT_FAILURE
Definition: ntddstor.h:135
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
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 RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
__inline BOOLEAN ClasspCanSendPollingIrp(_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension)
Definition: autorun.c:61
struct _FAILURE_PREDICTION_INFO * PFAILURE_PREDICTION_INFO
static SERVICE_STATUS status
Definition: service.c:31
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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 }
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define LL
Definition: tui.h:84
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
LONGLONG QuadPart
Definition: typedefs.h:114
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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 
2063  MmBuildMdlForNonPagedPool(Info->Gesn.Mdl);
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),
2123  IRP_MJ_SCSI,
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 
2198  header = (PNOTIFICATION_EVENT_STATUS_HEADER)(Info->Gesn.Buffer);
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 
2347 ExitWithError:
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 SRB_STATUS_BUS_RESET
Definition: srb.h:345
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:159
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 NOTIFICATION_MEDIA_STATUS_CLASS_MASK
Definition: scsi.h:37
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK
Definition: scsi.h:36
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define FDO_HACK_GESN_IGNORE_OPCHANGE
Definition: classp.h:139
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define NOTIFICATION_DEVICE_BUSY_CLASS_MASK
Definition: scsi.h:39
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define SRB_STATUS(Status)
Definition: srb.h:381
struct TraceInfo Info
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define IRP_MJ_SCSI
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
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
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:565
#define FALSE
Definition: types.h:117
__inline ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: tools.h:150
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK
Definition: scsi.h:34
#define CLEAR_FLAG(Flags, Bit)
Definition: classpnp.h:158
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
enum _CLASS_DETECTION_STATE CLASS_DETECTION_STATE
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define CLASSP_REG_SUBKEY_NAME
Definition: classp.h:112
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:99
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
NTSTATUS ClasspInterpretGesnData(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PNOTIFICATION_EVENT_STATUS_HEADER Header, OUT PBOOLEAN ResendImmediately)
Definition: autorun.c:251
struct _cl_event * event
Definition: glext.h:7739
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define FDO_HACK_GESN_IS_BAD
Definition: classp.h:136
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: classp.h:115
PIRP ClasspPrepareMcnIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
Definition: autorun.c:1310
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
struct _NOTIFICATION_EVENT_STATUS_HEADER * PNOTIFICATION_EVENT_STATUS_HEADER
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define GESN_BUFFER_SIZE
Definition: autorun.c:32
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
return STATUS_SUCCESS
Definition: btrfs.c:3014
struct CFHEADER header
Definition: fdi.c:101
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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 
1932  NTSTATUS status;
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 STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
GLuint buffer
Definition: glext.h:5915
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
struct _test_info info[]
Definition: SetCursorPos.c:19
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:107
NTSTATUS ClasspInitializeGesn(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info)
Definition: autorun.c:1990
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: classpnp.h:19
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
void * PVOID
Definition: retypes.h:9
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char CCHAR
Definition: typedefs.h:51
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:595
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:404
NTKERNELAPI 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
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:157
#define CLASS_TAG_MEDIA_CHANGE_DETECTION
Definition: classpnp.h:79
#define MEDIA_CHANGE_DEFAULT_TIME
Definition: cdrom.c:176
_In_ BOOLEAN AllowDriveToSleep
Definition: classpnp.h:1275
PVOID ScreenStateNotificationHandle
Definition: class.c:124
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
return STATUS_SUCCESS
Definition: btrfs.c:3014
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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  //
3783  fdoData->TickTimer = ExAllocateTimer(ClasspTimerTickEx, FdoExtension, EX_TIMER_NO_WAKE);
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 }
PEX_TIMER TickTimer
Definition: classp.h:676
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
BOOLEAN TimerInitialized
Definition: classp.h:752
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
EXT_CALLBACK ClasspTimerTickEx
Definition: autorun.c:121
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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;
809  CLASS_MEDIA_CHANGE_CONTEXT mcnContext;
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()
CONST char * PCSZ
Definition: umtypes.h:125
enum _MEDIA_CHANGE_DETECTION_STATE MEDIA_CHANGE_DETECTION_STATE
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
long LONG
Definition: pedump.c:60
smooth NULL
Definition: ftsmooth.c:416
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
Definition: classp.h:1714
#define InterlockedExchange
Definition: armddk.h:54
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
signed int * PLONG
Definition: retypes.h:5

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 
464  PNOTIFICATION_OPERATIONAL_STATUS opChangeInfo =
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};
563  PSTORAGE_REQUEST_BLOCK srbEx = (PSTORAGE_REQUEST_BLOCK)srbExBuffer;
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.
602  NT_ASSERT(FALSE);
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 
671  PNOTIFICATION_MEDIA_STATUS mediaInfo =
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 
678  if ((mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_NEW_MEDIA) ||
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);
693  MediaPresent,
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 
717  PNOTIFICATION_BUSY_STATUS busyInfo =
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 KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define NOTIFICATION_NO_CLASS_EVENTS
Definition: scsi.h:42
UCHAR SenseKey
Definition: cdrw_hw.h:1167
struct _NOTIFICATION_OPERATIONAL_STATUS * PNOTIFICATION_OPERATIONAL_STATUS
USHORT Flags
Definition: iotypes.h:171
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:159
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
#define NOTIFICATION_EXTERNAL_EVENT_BUTTON_DOWN
Definition: scsi.h:76
#define NOTIFICATION_MEDIA_EVENT_NEW_MEDIA
Definition: scsi.h:95
LONG NTSTATUS
Definition: precomp.h:26
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
UCHAR CdbLength
Definition: srb.h:250
#define NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE
Definition: scsi.h:97
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR SrbStatus
Definition: srb.h:243
struct _test_info info[]
Definition: SetCursorPos.c:19
#define SRB_STATUS_ERROR
Definition: srb.h:336
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
#define NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS
Definition: scsi.h:46
#define FALSE
Definition: types.h:117
__inline ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: tools.h:150
Definition: Header.h:8
long LONG
Definition: pedump.c:60
ULONG dataLength
Definition: scsi.h:3750
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define CLEAR_FLAG(Flags, Bit)
Definition: classpnp.h:158
struct _SENSE_DATA SENSE_DATA
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _NOTIFICATION_MEDIA_STATUS * PNOTIFICATION_MEDIA_STATUS
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST
Definition: scsi.h:94
#define NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL
Definition: scsi.h:96
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
int64_t LONGLONG
Definition: typedefs.h:68
#define NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED
Definition: scsi.h:51
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE
Definition: scsi.h:59
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:679
USHORT Length
Definition: srb.h:241
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
struct _NOTIFICATION_EXTERNAL_STATUS * PNOTIFICATION_EXTERNAL_STATUS
unsigned char UCHAR
Definition: xmlstorage.h:181
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED
Definition: scsi.h:60
#define NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS
Definition: scsi.h:48
VOID ClasspSetMediaChangeStateEx(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN Wait, IN BOOLEAN KnownStateChange)
Definition: autorun.c:950
struct _cl_event * event
Definition: glext.h:7739
#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS
Definition: autorun.c:33
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:157
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
UCHAR SenseInfoBufferLength
Definition: srb.h:251
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS
Definition: scsi.h:45
#define InterlockedIncrement
Definition: armddk.h:53
PVOID SenseInfoBuffer
Definition: srb.h:256
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS
Definition: scsi.h:43
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
struct _NOTIFICATION_BUSY_STATUS * PNOTIFICATION_BUSY_STATUS
LARGE_INTEGER SystemTime
Definition: ioevent.h:92
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID ClassSendEjectionNotification(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:155
#define VPB_MOUNTED
Definition: iotypes.h:1771
static SERVICE_STATUS status
Definition: service.c:31
#define CLASS_SRB_STORAGE_REQUEST_BLOCK
Definition: classpnp.h:573
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
UCHAR ErrorCode
Definition: cdrw_hw.h:1164
LONGLONG QuadPart
Definition: typedefs.h:114
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97
#define SCSI_SENSE_ERRORCODE_FIXED_CURRENT
Definition: scsi.h:622

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 
2741  NTSTATUS status;
2742 
2743 
2744  PAGED_CODE();
2745 
2746  //
2747  // open the service key.
2748  //
2749 
2750  InitializeObjectAttributes(&objectAttributes,
2751  RegistryPath,
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()
#define FINALLY
Definition: classpnp.h:116
CONST char * PCSZ
Definition: umtypes.h:125
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
#define LEAVE
Definition: classpnp.h:115
GLintptr offset
Definition: glext.h:5920
#define TRY(sps, bps)
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:565
#define FALSE
Definition: types.h:117
#define REG_MULTI_SZ
Definition: nt_native.h:1501
smooth NULL
Definition: ftsmooth.c:416
#define PCHAR
Definition: match.c:90
USHORT MaximumLength
Definition: env_spec_w32.h:377
_In_z_ PWSTR RegistryPath
Definition: classp.h:1930
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define CLASS_TAG_AUTORUN_DISABLE
Definition: classpnp.h:77
static const WCHAR L[]
Definition: oid.c:1250
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
static SERVICE_STATUS status
Definition: service.c:31
RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack
Definition: autorun.c:96
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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 
2974  NTSTATUS status;
2975 
2976 
2977  PAGED_CODE();
2978 
2979  //
2980  // open the service key.
2981  //
2982 
2983  InitializeObjectAttributes(&objectAttributes,
2984  RegistryPath,
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 NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
LONG NTSTATUS
Definition: precomp.h:26
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
_In_z_ PWSTR RegistryPath
Definition: classp.h:1930
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR L[]
Definition: oid.c:1250
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define REG_DWORD
Definition: sdbapi.c:596
static SERVICE_STATUS status
Definition: service.c:31
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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,
3349  IO_NO_INCREMENT);
3350  }
3351  return status;
3352 } // end ClasspMcnControl(
#define FINALLY
Definition: classpnp.h:116
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
#define LEAVE
Definition: classpnp.h:115
#define TRY(sps, bps)
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
long LONG
Definition: pedump.c:60
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
* PFILE_OBJECT
Definition: iotypes.h:1962
#define InterlockedDecrement
Definition: armddk.h:52
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
PFILE_OBJECT FileObject
Definition: iotypes.h:2820
#define InterlockedIncrement
Definition: armddk.h:53
Definition: tftpd.h:85
#define IO_NO_INCREMENT
Definition: iotypes.h:570
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
Definition: ps.c:97

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;
1056  PCLASS_PRIVATE_FDO_DATA fdoData;
1058  NTSTATUS status;
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 
1092  if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
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 &&
1114  Srb->SrbStatus = SRB_STATUS_SUCCESS;
1115  }
1116  }
1117  }
1118 
1119  //
1120  // use InterpretSenseInfo routine to check for media state, and also
1121  // to call ClassError() with correct parameters.
1122  //
1124  if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
1125 
1126  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN, "ClasspMediaChangeDetectionCompletion - failed - srb status=%s, sense=%s/%s/%s.",
1128 
1130  Irp,
1132  IRP_MJ_SCSI,
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) {
1227  IoQueueWorkItem(workItem, ClasspDisableGesn, DelayedWorkQueue, 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 }
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
VOID ClasspSendMediaStateIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN ULONG CountDown)
Definition: autorun.c:1559
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
UCHAR senseKey
Definition: scsi.h:4018
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:159
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
_In_ PIRP Irp
Definition: csq.h:116
#define TRUE
Definition: types.h:120
#define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK
Definition: scsi_port.h:175
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define DBGGETSENSECODESTR(_pSrb)
Definition: debug.h:28
#define SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED
Definition: scsi.h:3838
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define MAXIMUM_IMMEDIATE_MCN_RETRIES
Definition: autorun.c:35
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SRB_STATUS(Status)
Definition: srb.h:381
struct _test_info info[]
Definition: SetCursorPos.c:19
#define IRP_MJ_SCSI
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
__inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
#define FALSE
Definition: types.h:117
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
long LONG
Definition: pedump.c:60
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
Definition: debug.h:30
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
UCHAR additionalSenseCode
Definition: scsi.h:4019
VOID NTAPI ClassResetMediaChangeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1804
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2874
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
NTSTATUS ClasspInterpretGesnData(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PNOTIFICATION_EVENT_STATUS_HEADER Header, OUT PBOOLEAN ResendImmediately)
Definition: autorun.c:251
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
VOID NTAPI IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
Definition: iowork.c:40
#define DBGGETADSENSECODESTR(_pSrb)
Definition: debug.h:29
__inline BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
#define DBGGETSRBSTATUSSTR(_pSrb)
Definition: debug.h:27
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2779
IO_WORKITEM_ROUTINE ClasspDisableGesn
Definition: autorun.c:114
return STATUS_SUCCESS
Definition: btrfs.c:3014
static SERVICE_STATUS status
Definition: service.c:31
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
BOOLEAN validSense
Definition: scsi.h:4017
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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 FINALLY
Definition: classpnp.h:116
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2782
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
#define LEAVE
Definition: classpnp.h:115
#define TRY(sps, bps)
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
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 FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME
Definition: autorun.c:38
#define RTL_QUERY_REGISTRY_TYPECHECK
#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME
Definition: autorun.c:37
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:2327
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define REG_NONE
Definition: nt_native.h:1492
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define REG_DWORD
Definition: sdbapi.c:596
static SERVICE_STATUS status
Definition: service.c:31
#define MCN_REG_SUBKEY_NAME
Definition: autorun.c:36
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ 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 {
1316  PSCSI_REQUEST_BLOCK srb;
1317  PSTORAGE_REQUEST_BLOCK srbEx;
1318  PIO_STACK_LOCATION irpStack;
1319  PIO_STACK_LOCATION nextIrpStack;
1320  NTSTATUS status;
1321  PCDB cdb;
1322  PIRP irp;
1323  PVOID buffer;
1324  UCHAR bufferLength;
1325  ULONG srbFlags;
1326  ULONG timeOutValue;
1327  UCHAR cdbLength;
1328  PVOID dataBuffer;
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 
1346  status = ClassAcquireRemoveLock(FdoExtension->DeviceObject, irp);
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  */
1372  irpStack = IoGetCurrentIrpStackLocation(irp);
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 
1396  NT_ASSERT(bufferLength > 0);
1397  RtlZeroMemory(buffer, bufferLength);
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)) {
1436  SET_FLAG(srbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
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
1471  NT_ASSERT(FALSE);
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);
1486  SrbSetSenseInfoBuffer(srbEx, buffer);
1487  SrbSetSenseInfoBufferLength(srbEx, bufferLength);
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;
1500  srb->SenseInfoBufferLength = bufferLength;
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 }
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
IO_COMPLETION_ROUTINE ClasspMediaChangeDetectionCompletion
Definition: autorun.c:116
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
ULONG SrbFlags
Definition: srb.h:252
#define SCSIOP_GET_EVENT_STATUS
Definition: cdrw_hw.h:934
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
#define GESN_TIMEOUT_VALUE
Definition: autorun.c:31
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define REMOVE_COMPLETE
Definition: classpnp.h:98
#define TRUE
Definition: types.h:120
PVOID DataBuffer
Definition: srb.h:255
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
ULONG DataTransferLength
Definition: srb.h:253
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
UCHAR CdbLength
Definition: srb.h:250
GLuint buffer
Definition: glext.h:5915
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
UCHAR QueueAction
Definition: srb.h:249
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
ULONG TimeOutValue
Definition: srb.h:254
UCHAR SrbStatus
Definition: srb.h:243
struct TraceInfo Info
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define SP_UNTAGGED
Definition: srb.h:225
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:107
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
#define FALSE
Definition: types.h:117
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
UCHAR ScsiStatus
Definition: srb.h:244
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
union _CDB * PCDB
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1787
UCHAR QueueTag
Definition: srb.h:248
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UCHAR Function
Definition: srb.h:242
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:404
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2874
USHORT Length
Definition: srb.h:241
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define NO_REMOVE
Definition: classpnp.h:96
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define REMOVE_PENDING
Definition: classpnp.h:97
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:157
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
UCHAR SenseInfoBufferLength
Definition: srb.h:251
struct _CDB::_CDB6GENERIC CDB6GENERIC
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
PVOID SenseInfoBuffer
Definition: srb.h:256
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2779
struct _CDB::_GET_EVENT_STATUS_NOTIFICATION GET_EVENT_STATUS_NOTIFICATION
static SERVICE_STATUS status
Definition: service.c:31
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

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 FINALLY
Definition: classpnp.h:116
#define MEDIA_CHANGE_TIMEOUT_TIME
Definition: classpnp.h:133
#define TRUE
Definition: types.h:120
#define LEAVE
Definition: classpnp.h:115
#define TRY(sps, bps)
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
struct TraceInfo Info
#define FALSE
Definition: types.h:117
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
long LONG
Definition: pedump.c:60
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IRP_MN_START_DEVICE
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
PIRP ClasspPrepareMcnIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
Definition: autorun.c:1310
#define InterlockedIncrement
Definition: armddk.h:53
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define NT_ASSERT
Definition: rtlfuncs.h:3312

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,
985  KernelMode,
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()
#define KeWaitForMutexObject
Definition: kefuncs.h:555
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
VOID ClasspInternalSetMediaChangeState(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN KnownStateChange)
Definition: autorun.c:798
static double zero
Definition: j0_y0.c:96
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
static SERVICE_STATUS status
Definition: service.c:31
IN BOOLEAN Wait
Definition: fatprocs.h:1538
Definition: ps.c:97

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 }
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
smooth NULL
Definition: ftsmooth.c:416
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
Definition: ketypes.h:687

◆ 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 }
PEX_TIMER TickTimer
Definition: classp.h:676
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
#define TRUE
Definition: types.h:120
#define TICK_TIMER_PERIOD_IN_MSEC
Definition: autorun.c:129
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN TimerInitialized
Definition: classp.h:752
int64_t LONGLONG
Definition: typedefs.h:68
#define TICK_TIMER_DELAY_IN_MSEC
Definition: autorun.c:130
LONGLONG CurrentNoWakeTolerance
Definition: classp.h:677
BOOLEAN TickTimerEnabled
Definition: classp.h:813
BOOLEAN ClasspScreenOff
Definition: autorun.c:124

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()
smooth NULL
Definition: ftsmooth.c:416
#define InterlockedExchange
Definition: armddk.h:54
#define MEDIA_CHANGE_DEFAULT_TIME
Definition: cdrom.c:176

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 }
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
smooth NULL
Definition: ftsmooth.c:416

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.