ReactOS  0.4.15-dev-1374-g8d3e80e
autorun.c File Reference
#include "stddef.h"
#include "string.h"
#include "ntddk.h"
#include "ntddstor.h"
#include "cdrom.h"
#include "mmc.h"
#include "ioctl.h"
#include "ntstrsafe.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")
 

Functions

 _IRQL_requires_max_ (_IRQL_requires_max_() BOOLEANDeviceIsMediaChangeDisabledForClass(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension) PASSIVE_LEVEL)
 
VOID DeviceInternalSetMediaChangeState (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
 
VOID DeviceSetMediaChangeStateEx (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
 
 _IRQL_requires_max_ (APC_LEVEL)
 
VOID NTAPI DeviceDisableGesn (_In_ WDFWORKITEM WorkItem)
 
 _IRQL_requires_max_ (PASSIVE_LEVEL)
 
NTSTATUS NTAPI DeviceMediaChangeRegistryCallBack (_In_z_ PWSTR ValueName, _In_ ULONG ValueType, _In_reads_bytes_opt_(ValueLength) PVOID ValueData, _In_ ULONG ValueLength, _In_opt_ PVOID Context, _In_opt_ PVOID EntryContext)
 
NTSTATUS NTAPI RequestMcnSyncIrpCompletion (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Context)
 
VOID RequestSetupMcnSyncIrp (_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
 
VOID NTAPI DeviceMainTimerTickHandler (_In_ WDFTIMER Timer)
 

Variables

IO_COMPLETION_ROUTINE RequestMcnSyncIrpCompletion
 

Macro Definition Documentation

◆ GESN_BUFFER_SIZE

#define GESN_BUFFER_SIZE   (0x8)

Definition at line 40 of file autorun.c.

◆ GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS

#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS   (2)

Definition at line 41 of file autorun.c.

◆ GESN_TIMEOUT_VALUE

#define GESN_TIMEOUT_VALUE   (0x4)

Definition at line 39 of file autorun.c.

◆ MAXIMUM_IMMEDIATE_MCN_RETRIES

#define MAXIMUM_IMMEDIATE_MCN_RETRIES   (0x20)

Definition at line 43 of file autorun.c.

◆ MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME

#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME   (L"AlwaysDisableMCN")

Definition at line 45 of file autorun.c.

◆ MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME

#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME   (L"AlwaysEnableMCN")

Definition at line 46 of file autorun.c.

◆ MCN_REG_SUBKEY_NAME

#define MCN_REG_SUBKEY_NAME   (L"MediaChangeNotification")

Definition at line 44 of file autorun.c.

Function Documentation

◆ _IRQL_requires_max_() [1/3]

_IRQL_requires_max_ ( _IRQL_requires_max_()BOOLEANDeviceIsMediaChangeDisabledForClass( _In_ PCDROM_DEVICE_EXTENSION DeviceExtension )  PASSIVE_LEVEL)

Definition at line 66 of file autorun.c.

146  :4152) // nonstandard extension, function/data pointer conversion in expression
147 
148 
150 NTSTATUS
151 GesnDataInterpret(
152  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
154  _Out_ PBOOLEAN ResendImmediately
155  )
156 /*++
157 
158 Routine Description:
159 
160  This routine will interpret the data returned for a GESN command, and
161  (if appropriate) set the media change event, and broadcast the
162  appropriate events to user mode for applications who care.
163 
164 Arguments:
165 
166  DeviceExtension - the device extension
167 
168  Header - the resulting data from a GESN event.
169  requires at least EIGHT valid bytes (header == 4, data == 4)
170 
171  ResendImmediately - whether or not to immediately resend the request.
172  this should be FALSE if there was no event, FALSE if the reported
173  event was of the DEVICE BUSY class, else true.
174 
175 Return Value:
176 
177  STATUS_SUCCESS if successful, an error code otherwise
178 
179 Notes:
180 
181  DataBuffer must be at least four bytes of valid data (header == 4 bytes),
182  and have at least eight bytes of allocated memory (all events == 4 bytes).
183 
184  The call to StartNextPacket may occur before this routine is completed.
185  the operational change notifications are informational in nature, and
186  while useful, are not neccessary to ensure proper operation. For example,
187  if the device morphs to no longer supporting WRITE commands, all further
188  write commands will fail. There exists a small timing window wherein
189  IOCTL_IS_DISK_WRITABLE may be called and get an incorrect response. If
190  a device supports software write protect, it is expected that the
191  application can handle such a case.
192 
193  NOTE: perhaps setting the updaterequired byte to one should be done here.
194  if so, it relies upon the setting of a 32-byte value to be an atomic
195  operation. unfortunately, there is no simple way to notify a class driver
196  which wants to know that the device behavior requires updating.
197 
198  Not ready events may be sent every second. For example, if we were
199  to minimize the number of asynchronous notifications, an application may
200  register just after a large busy time was reported. This would then
201  prevent the application from knowing the device was busy until some
202  arbitrarily chosen timeout has occurred. Also, the GESN request would
203  have to still occur, since it checks for non-busy events (such as user
204  keybutton presses and media change events) as well. The specification
205  states that the lower-numered events get reported first, so busy events,
206  while repeating, will only be reported when all other events have been
207  cleared from the device.
208 
209 --*/
210 {
212  PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
213  LONG dataLength = 0;
214  LONG requiredLength = 0;
215  BOOLEAN inHomePosition = FALSE;
216 
217  PAGED_CODE();
218 
219  // note: don't allocate anything in this routine so that we can
220  // always just 'return'.
221  *ResendImmediately = FALSE;
222 
223  if (Header->NEA)
224  {
225  return status;
226  }
227  if (Header->NotificationClass == NOTIFICATION_NO_CLASS_EVENTS)
228  {
229  return status;
230  }
231 
232  // HACKHACK - REF #0001
233  // This loop is only taken initially, due to the inability to reliably
234  // auto-detect drives that report events correctly at boot. When we
235  // detect this behavior during the normal course of running, we will
236  // disable the hack, allowing more efficient use of the system. This
237  // should occur "nearly" instantly, as the drive should have multiple
238  // events queue'd (ie. power, morphing, media).
239  if (info->Gesn.HackEventMask)
240  {
241  // all events use the low four bytes of zero to indicate
242  // that there was no change in status.
243  UCHAR thisEvent = Header->ClassEventData[0] & 0xf;
244  UCHAR lowestSetBit;
245  UCHAR thisEventBit = (1 << Header->NotificationClass);
246 
247  if (!TEST_FLAG(info->Gesn.EventMask, thisEventBit))
248  {
249  // The drive is reporting an event that wasn't requested
251  }
252 
253  // some bit magic here... this results in the lowest set bit only
254  lowestSetBit = info->Gesn.EventMask;
255  lowestSetBit &= (info->Gesn.EventMask - 1);
256  lowestSetBit ^= (info->Gesn.EventMask);
257 
258  if (thisEventBit != lowestSetBit)
259  {
260  // HACKHACK - REF #0001
261  // the first time we ever see an event set that is not the lowest
262  // set bit in the request (iow, highest priority), we know that the
263  // hack is no longer required, as the device is ignoring "no change"
264  // events when a real event is waiting in the other requested queues.
265  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
266  "GESN::NONE: Compliant drive found, "
267  "removing GESN hack (%x, %x)\n",
268  thisEventBit, info->Gesn.EventMask));
269 
270  info->Gesn.HackEventMask = FALSE;
271  }
272  else if (thisEvent == 0) // NOTIFICATION_*_EVENT_NO_CHANGE
273  {
274  // HACKHACK - REF #0001
275  // note: this hack prevents poorly implemented firmware from constantly
276  // returning "No Event". we do this by cycling through the
277  // supported list of events here.
278  SET_FLAG(info->Gesn.NoChangeEventMask, thisEventBit);
279  CLEAR_FLAG(info->Gesn.EventMask, thisEventBit);
280 
281  // if we have cycled through all supported event types, then
282  // we need to reset the events we are asking about. else we
283  // want to resend this request immediately in case there was
284  // another event pending.
285  if (info->Gesn.EventMask == 0)
286  {
287  info->Gesn.EventMask = info->Gesn.NoChangeEventMask;
288  info->Gesn.NoChangeEventMask = 0;
289  }
290  else
291  {
292  *ResendImmediately = TRUE;
293  }
294  return status;
295  }
296 
297  } // end if (info->Gesn.HackEventMask)
298 
299  dataLength = (Header->EventDataLength[0] << 8) |
300  (Header->EventDataLength[1] & 0xff);
301  dataLength -= 2;
302  requiredLength = 4; // all events are four bytes
303 
304  if (dataLength < requiredLength)
305  {
306  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
307  "error - GESN returned only %x bytes data for fdo %p\n",
308  dataLength, DeviceExtension->DeviceObject));
309 
311  }
312 
313  if (dataLength > requiredLength)
314  {
315  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
316  "error - GESN returned too many (%x) bytes data for fdo %p\n",
317  dataLength, DeviceExtension->DeviceObject));
318  }
319 
320  if ((Header->ClassEventData[0] & 0xf) == 0)
321  {
322  // a zero event is a "no change event, so do not retry
323  return status;
324  }
325 
326  // because a event other than "no change" occurred,
327  // we should immediately resend this request.
328  *ResendImmediately = TRUE;
329 
330  switch (Header->NotificationClass)
331  {
332 
334  {
335  PNOTIFICATION_OPERATIONAL_STATUS opChangeInfo =
336  (PNOTIFICATION_OPERATIONAL_STATUS)(Header->ClassEventData);
337  ULONG event;
338 
340  {
341  break;
342  }
343 
344  event = (opChangeInfo->Operation[0] << 8) |
345  (opChangeInfo->Operation[1] ) ;
346 
347  // Workaround some hardware that is buggy but prevalent in the market
348  // This hardware has the property that it will report OpChange events repeatedly,
349  // causing us to retry immediately so quickly that we will eventually disable
350  // GESN to prevent an infinite loop.
351  // (only one valid OpChange event type now, only two ever defined)
352  if (info->MediaChangeRetryCount >= 4)
353  {
354  //
355  // HACKHACK - REF #0002
356  // Some drives incorrectly report OpChange/Change (001b/0001h) events
357  // continuously when the tray has been ejected. This causes this routine
358  // to set ResendImmediately to "TRUE", and that results in our cycling
359  // 32 times immediately resending. At that point, we give up detecting
360  // the infinite retry loop, and disable GESN on these drives. This
361  // prevents Media Eject Request (from eject button) from being reported.
362  // Thus, instead we should attempt to workaround this issue by detecting
363  // this behavior.
364  //
365 
366  static UCHAR const OpChangeMask = 0x02;
367 
368  // At least one device reports "temporarily busy" (which is useless) on eject
369  // At least one device reports "OpChange" repeatedly when re-inserting media
370  // All seem to work well using this workaround
371 
372  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_MCN,
373  "GESN OpChange events are broken. Working around this problem in software (for WDFDEVICE %p)\n",
374  DeviceExtension->Device));
375 
376  // OpChange is not the only bit set -- Media class is required....
377  NT_ASSERT(CountOfSetBitsUChar(info->Gesn.EventMask) != 1);
378 
379  // Force the use of the hackhack (ref #0001) to workaround the
380  // issue noted this hackhack (ref #0002).
381  SET_FLAG(info->Gesn.NoChangeEventMask, OpChangeMask);
382  CLEAR_FLAG(info->Gesn.EventMask, OpChangeMask);
383  info->Gesn.HackEventMask = TRUE;
384 
385  // don't request the opChange event again. use the method
386  // defined by hackhack (ref #0001) as the workaround.
387  if (info->Gesn.EventMask == 0)
388  {
389  info->Gesn.EventMask = info->Gesn.NoChangeEventMask;
390  info->Gesn.NoChangeEventMask = 0;
391  *ResendImmediately = FALSE;
392  }
393  else
394  {
395  *ResendImmediately = TRUE;
396  }
397 
398  break;
399  }
400 
401 
404  {
405  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
406  "GESN says features added/changed for WDFDEVICE %p\n",
407  DeviceExtension->Device));
408 
409  // don't notify that new media arrived, just set the
410  // DO_VERIFY to force a FS reload.
411 
412  if (IsVolumeMounted(DeviceExtension->DeviceObject))
413  {
414  SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
415  }
416 
417  // Call error handler with
418  // a "fake" media change error in case it needs to update
419  // internal structures as though a media change occurred.
420  {
421  SCSI_REQUEST_BLOCK srb = {0};
422  SENSE_DATA sense = {0};
423  NTSTATUS tempStatus;
424  BOOLEAN retry;
425 
426  tempStatus = STATUS_MEDIA_CHANGED;
427  retry = FALSE;
428 
429  srb.CdbLength = 6;
430  srb.Length = sizeof(SCSI_REQUEST_BLOCK);
432  srb.SenseInfoBuffer = &sense;
433  srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
434 
435  sense.AdditionalSenseLength = sizeof(SENSE_DATA) -
436  RTL_SIZEOF_THROUGH_FIELD(SENSE_DATA, AdditionalSenseLength);
437 
440 
441  if (DeviceExtension->DeviceAdditionalData.ErrorHandler)
442  {
443  DeviceExtension->DeviceAdditionalData.ErrorHandler(DeviceExtension,
444  &srb,
445  &tempStatus,
446  &retry);
447  }
448  } // end error handler
449 
450  }
451  break;
452  }
453 
455  {
456  PNOTIFICATION_EXTERNAL_STATUS externalInfo =
457  (PNOTIFICATION_EXTERNAL_STATUS)(Header->ClassEventData);
458  DEVICE_EVENT_EXTERNAL_REQUEST externalData = {0};
459 
460  // unfortunately, due to time constraints, we will only notify
461  // about keys being pressed, and not released. this makes keys
462  // single-function, but simplifies the code significantly.
464  {
465  break;
466  }
467 
468  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
469  "GESN::EXTERNAL: Event: %x Status %x Req %x\n",
470  externalInfo->ExternalEvent, externalInfo->ExternalStatus,
471  (externalInfo->Request[0] << 8) | externalInfo->Request[1]
472  ));
473 
474  externalData.Version = 1;
475  externalData.DeviceClass = 0;
476  externalData.ButtonStatus = externalInfo->ExternalEvent;
477  externalData.Request = (externalInfo->Request[0] << 8) |
478  (externalInfo->Request[1] & 0xff);
479  KeQuerySystemTime(&(externalData.SystemTime));
481 
482  DeviceSendNotification(DeviceExtension,
483  &GUID_IO_DEVICE_EXTERNAL_REQUEST,
485  &externalData);
486 
487  return status;
488  }
489 
491  {
492  PNOTIFICATION_MEDIA_STATUS mediaInfo =
493  (PNOTIFICATION_MEDIA_STATUS)(Header->ClassEventData);
494 
495  if ((mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_NEW_MEDIA) ||
497  {
498  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
499  "GESN::MEDIA ARRIVAL, Status %x\n",
500  mediaInfo->MediaStatus));
501 
502  if (IsVolumeMounted(DeviceExtension->DeviceObject))
503  {
504  SET_FLAG(DeviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
505  }
506  DeviceSetMediaChangeStateEx(DeviceExtension,
507  MediaPresent,
508  NULL);
509 
510  // If media is inserted into slot loading type, mark the device active
511  // to not power off.
512  if ((DeviceExtension->ZeroPowerODDInfo != NULL) &&
513  (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_CADDY) &&
514  (DeviceExtension->ZeroPowerODDInfo->Load == 0)) // Slot
515  {
516  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
517  "GesnDataInterpret: MediaArrival event detected, device marked as active\n"));
518 
519  DeviceMarkActive(DeviceExtension, TRUE, FALSE);
520  }
521  }
522  else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL)
523  {
524  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
525  "GESN::MEDIA REMOVAL, Status %x\n",
526  mediaInfo->MediaStatus));
527 
528  DeviceSetMediaChangeStateEx(DeviceExtension,
530  NULL);
531 
532  // If media is removed from slot loading type, start powering off the device
533  // if it is ZPODD capable.
534  if ((DeviceExtension->ZeroPowerODDInfo != NULL) &&
535  (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_CADDY) &&
536  (DeviceExtension->ZeroPowerODDInfo->Load == 0)) // Slot
537  {
538  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
539  "GesnDataInterpret: MediaRemoval event detected, device marked as idle\n"));
540 
541  DeviceMarkActive(DeviceExtension, FALSE, FALSE);
542  }
543  }
544  else if (mediaInfo->MediaEvent == NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST)
545  {
546  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
547  "GESN::MEDIA EJECTION, Status %x\n",
548  mediaInfo->MediaStatus));
549 
550  DeviceSendNotification(DeviceExtension,
551  &GUID_IO_MEDIA_EJECT_REQUEST,
552  0,
553  NULL);
554  }
555 
556  break;
557  }
558 
559  case NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS: // lowest priority events...
560  {
561  PNOTIFICATION_BUSY_STATUS busyInfo =
562  (PNOTIFICATION_BUSY_STATUS)(Header->ClassEventData);
563  DEVICE_EVENT_BECOMING_READY busyData = {0};
564 
565  // else we want to report the approximated time till it's ready.
566  busyData.Version = 1;
567  busyData.Reason = busyInfo->DeviceBusyStatus;
568  busyData.Estimated100msToReady = (busyInfo->Time[0] << 8) |
569  (busyInfo->Time[1] & 0xff);
570 
571  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
572  "GESN::BUSY: Event: %x Status %x Time %x\n",
573  busyInfo->DeviceBusyEvent, busyInfo->DeviceBusyStatus,
574  busyData.Estimated100msToReady
575  ));
576 
577  // Ignore the notification if the time is small
579  {
580  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
581  "GesnDataInterpret: media BECOMING_READY\n"));
582 
583  DeviceSendNotification(DeviceExtension,
584  &GUID_IO_DEVICE_BECOMING_READY,
586  &busyData);
587  }
588 
589  // If manual loading operation is observed for slot loading type, start powering off the device
590  // if it is ZPODD capable.
591  if ((DeviceExtension->ZeroPowerODDInfo != NULL) &&
592  (DeviceExtension->ZeroPowerODDInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) &&
593  (DeviceExtension->ZeroPowerODDInfo->Load == 0) && // Drawer
596  {
597  inHomePosition = DeviceZPODDIsInHomePosition(DeviceExtension);
598 
599  if (inHomePosition == FALSE)
600  {
601  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
602  "GesnDataInterpret: LoChange event detected, device marked as active\n"));
603 
604  DeviceMarkActive(DeviceExtension, TRUE, FALSE);
605  }
606  else
607  {
608  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
609  "GesnDataInterpret: LoChange event detected, device marked as idle\n"));
610 
611  DeviceMarkActive(DeviceExtension, FALSE, FALSE);
612  }
613  }
614 
615  break;
616  }
617 
618  default:
619  {
620  break;
621  }
622 
623  } // end switch on notification class
624 
625  return status;
626 }
#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
#define LOADING_MECHANISM_CADDY
Definition: scsi.h:971
VOID DeviceSetMediaChangeStateEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:751
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define TRUE
Definition: types.h:120
__inline BOOLEAN IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)
Definition: cdrom.h:1514
#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
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UCHAR SrbStatus
Definition: srb.h:243
#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 LOADING_MECHANISM_TRAY
Definition: scsi.h:972
#define NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS
Definition: scsi.h:46
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
#define FALSE
Definition: types.h:117
Definition: Header.h:8
_IRQL_requires_max_(_IRQL_requires_max_() BOOLEANDeviceIsMediaChangeDisabledForClass(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension) PASSIVE_LEVEL)
Definition: autorun.c:66
long LONG
Definition: pedump.c:60
struct _SENSE_DATA SENSE_DATA
unsigned char BOOLEAN
struct _NOTIFICATION_MEDIA_STATUS * PNOTIFICATION_MEDIA_STATUS
#define _Out_
Definition: no_sal2.h:160
#define CLEAR_FLAG(Flags, Bit)
Definition: cdrom.h:1494
#define NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST
Definition: scsi.h:94
#define NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL
Definition: scsi.h:96
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
int64_t LONGLONG
Definition: typedefs.h:68
#define NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED
Definition: scsi.h:51
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE
Definition: scsi.h:59
ULONG dataLength
Definition: scsi.h:3751
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
struct _NOTIFICATION_EXTERNAL_STATUS * PNOTIFICATION_EXTERNAL_STATUS
unsigned char UCHAR
Definition: xmlstorage.h:181
char * PBOOLEAN
Definition: retypes.h:11
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED
Definition: scsi.h:60
#define NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS
Definition: scsi.h:48
__inline ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: cdrom.h:1500
struct _cl_event * event
Definition: glext.h:7739
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define NOTIFICATION_BUSY_EVENT_LO_CHANGE
Definition: scsi.h:116
#define _In_
Definition: no_sal2.h:158
UCHAR SenseInfoBufferLength
Definition: srb.h:251
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS
Definition: scsi.h:45
#define NOTIFICATION_BUSY_STATUS_NO_EVENT
Definition: scsi.h:118
#define NULL
Definition: types.h:112
PVOID SenseInfoBuffer
Definition: srb.h:256
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS
Definition: scsi.h:43
unsigned int ULONG
Definition: retypes.h:1
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _NOTIFICATION_BUSY_STATUS * PNOTIFICATION_BUSY_STATUS
LARGE_INTEGER SystemTime
Definition: ioevent.h:92
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
static SERVICE_STATUS status
Definition: service.c:31
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS
Definition: autorun.c:41
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
LONGLONG QuadPart
Definition: typedefs.h:114
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ _IRQL_requires_max_() [2/3]

_IRQL_requires_max_ ( APC_LEVEL  )

Definition at line 812 of file autorun.c.

836 {
837  PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
840 
841  PAGED_CODE();
842 
843  zero.QuadPart = 0;
844 
845  if (info == NULL)
846  {
847  return;
848  }
849 
850  status = KeWaitForMutexObject(&info->MediaChangeMutex,
851  Executive,
852  KernelMode,
853  FALSE,
854  &zero);
855 
856  if (status == STATUS_TIMEOUT)
857  {
858  // Someone else is in the process of setting the media state.
859  // That's totally okay, we'll send delayed notifications later.
860  return;
861  }
862 
863  // If the last reported state and the last known state are different and
864  // MCN is enabled, generate a notification based on the last known state.
865  if ((info->LastKnownMediaDetectionState != info->LastReportedMediaDetectionState) &&
866  (info->MediaChangeDetectionDisableCount == 0))
867  {
868  DeviceInternalSetMediaChangeState(DeviceExtension, info->LastKnownMediaDetectionState, NULL);
869  }
870 
871  KeReleaseMutex(&info->MediaChangeMutex, FALSE);
872 
873  return;
874 }
#define KeWaitForMutexObject
Definition: kefuncs.h:555
LONG NTSTATUS
Definition: precomp.h:26
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
VOID DeviceInternalSetMediaChangeState(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:630
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define FALSE
Definition: types.h:117
int zero
Definition: sehframes.cpp:29
#define NULL
Definition: types.h:112
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
Definition: ps.c:97

◆ _IRQL_requires_max_() [3/3]

_IRQL_requires_max_ ( PASSIVE_LEVEL  )

Definition at line 1258 of file autorun.c.

1280 {
1282  PMEDIA_CHANGE_DETECTION_INFO mediaChangeInfo = NULL;
1283  PIRP irp = NULL;
1284  PVOID senseBuffer = NULL;
1285  WDF_OBJECT_ATTRIBUTES attributes;
1286 
1287  PAGED_CODE();
1288 
1289  if (DeviceExtension->MediaChangeDetectionInfo != NULL)
1290  {
1291  //Already initialized.
1292  return STATUS_SUCCESS;
1293  }
1294 
1295  DeviceExtension->KernelModeMcnContext.FileObject = (PVOID)-1;
1296  DeviceExtension->KernelModeMcnContext.DeviceObject = (PVOID)-1;
1297  DeviceExtension->KernelModeMcnContext.LockCount = 0;
1298  DeviceExtension->KernelModeMcnContext.McnDisableCount = 0;
1299 
1300  mediaChangeInfo = ExAllocatePoolWithTag(NonPagedPoolNx,
1303 
1304  if (mediaChangeInfo == NULL)
1305  {
1307  }
1308  else
1309  {
1310  RtlZeroMemory(mediaChangeInfo, sizeof(MEDIA_CHANGE_DETECTION_INFO));
1311  }
1312 
1313  if (NT_SUCCESS(status))
1314  {
1315  if ((DeviceExtension->PowerDescriptor != NULL) &&
1316  (DeviceExtension->PowerDescriptor->AsynchronousNotificationSupported != FALSE) &&
1317  (!TEST_FLAG(DeviceExtension->PrivateFdoData->HackFlags, FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION)))
1318  {
1319  mediaChangeInfo->AsynchronousNotificationSupported = TRUE;
1320  }
1321  }
1322 
1323  // Allocate an IRP to carry the IOCTL_MCN_SYNC_FAKE_IOCTL.
1324  if (NT_SUCCESS(status))
1325  {
1326  irp = IoAllocateIrp(DeviceExtension->DeviceObject->StackSize, FALSE);
1327 
1328  if (irp == NULL)
1329  {
1331  }
1332  }
1333 
1334  if (NT_SUCCESS(status))
1335  {
1338  attributes.ParentObject = DeviceExtension->Device;
1339  status = WdfRequestCreate(&attributes,
1340  DeviceExtension->IoTarget,
1341  &mediaChangeInfo->MediaChangeRequest);
1342  }
1343 
1344  if (NT_SUCCESS(status))
1345  {
1346  // Preformat the media change request. With this being done, we never need to worry about
1347  // WdfIoTargetFormatRequestForInternalIoctlOthers ever failing later.
1348  status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget,
1349  mediaChangeInfo->MediaChangeRequest,
1351  NULL, NULL,
1352  NULL, NULL,
1353  NULL, NULL);
1354  }
1355 
1356  if (NT_SUCCESS(status))
1357  {
1358  senseBuffer = ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
1361  if (senseBuffer == NULL)
1362  {
1364  }
1365  }
1366 
1367  if (NT_SUCCESS(status))
1368  {
1369  mediaChangeInfo->MediaChangeSyncIrp = irp;
1370  mediaChangeInfo->SenseBuffer = senseBuffer;
1371 
1372  // Set default values for the media change notification
1373  // configuration.
1374  mediaChangeInfo->MediaChangeDetectionDisableCount = 0;
1375 
1376  // Assume that there is initially no media in the device
1377  // only notify upper layers if there is something there
1378  mediaChangeInfo->LastKnownMediaDetectionState = MediaUnknown;
1379  mediaChangeInfo->LastReportedMediaDetectionState = MediaUnknown;
1380 
1381  // setup all extra flags we'll be setting for this irp
1382  mediaChangeInfo->SrbFlags = 0;
1383 
1384  SET_FLAG(mediaChangeInfo->SrbFlags, SRB_CLASS_FLAGS_LOW_PRIORITY);
1385  SET_FLAG(mediaChangeInfo->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
1387 
1388  if (AllowDriveToSleep) //FALSE for CD/DVD devices
1389  {
1390  SET_FLAG(mediaChangeInfo->SrbFlags, SRB_FLAGS_NO_KEEP_AWAKE);
1391  }
1392 
1393  KeInitializeMutex(&mediaChangeInfo->MediaChangeMutex, 0x100);
1394 
1395  // It is ok to support media change events on this device.
1396  DeviceExtension->MediaChangeDetectionInfo = mediaChangeInfo;
1397 
1398  // check the device supports GESN or not, initialize GESN structure if it supports.
1399  {
1400  // This is only valid for type5 devices.
1401  NTSTATUS tempStatus = STATUS_SUCCESS;
1402 
1403  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1404  "DeviceInitializeMcn: Testing for GESN\n"));
1405  tempStatus = DeviceInitializeGesn(DeviceExtension);
1406 
1407  if (NT_SUCCESS(tempStatus))
1408  {
1409  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1410  "DeviceInitializeMcn: GESN available for %p\n",
1411  DeviceExtension->DeviceObject));
1412  NT_ASSERT(mediaChangeInfo->Gesn.Supported );
1413  NT_ASSERT(mediaChangeInfo->Gesn.Buffer != NULL);
1414  NT_ASSERT(mediaChangeInfo->Gesn.BufferSize != 0);
1415  NT_ASSERT(mediaChangeInfo->Gesn.EventMask != 0);
1416  }
1417  else
1418  {
1419  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
1420  "DeviceInitializeMcn: GESN *NOT* available for %p\n",
1421  DeviceExtension->DeviceObject));
1422  NT_ASSERT(!mediaChangeInfo->Gesn.Supported);
1423  NT_ASSERT(mediaChangeInfo->Gesn.Buffer == NULL);
1424  NT_ASSERT(mediaChangeInfo->Gesn.BufferSize == 0);
1425  NT_ASSERT(mediaChangeInfo->Gesn.EventMask == 0);
1426  mediaChangeInfo->Gesn.Supported = FALSE; // just in case....
1427  }
1428  }
1429  }
1430 
1431  if (NT_SUCCESS(status))
1432  {
1433  // Register for display state change on AOAC capable systems so we can put the
1434  // device to low power state when not required.
1435  if (mediaChangeInfo->DisplayStateCallbackHandle == NULL)
1436  {
1437  POWER_PLATFORM_INFORMATION PlatformInfo = {0};
1438 
1439  status = ZwPowerInformation(PlatformInformation,
1440  NULL,
1441  0,
1442  &PlatformInfo,
1443  sizeof(PlatformInfo));
1444 
1445  if (NT_SUCCESS(status) && PlatformInfo.AoAc)
1446  {
1447  PoRegisterPowerSettingCallback(DeviceExtension->DeviceObject,
1448  &GUID_CONSOLE_DISPLAY_STATE,
1450  DeviceExtension,
1451  &mediaChangeInfo->DisplayStateCallbackHandle);
1452  }
1453 
1454  // Ignore any failures above.
1456  }
1457  }
1458 
1459  if (!NT_SUCCESS(status))
1460  {
1461  if (irp != NULL)
1462  {
1463  IoFreeIrp(irp);
1464  }
1465  FREE_POOL(senseBuffer);
1466  FREE_POOL(mediaChangeInfo);
1467  }
1468 
1469  return status;
1470 
1471 } // end DeviceInitializeMcn()
BOOLEAN AsynchronousNotificationSupported
Definition: cdromp.h:178
#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
#define FDO_HACK_NO_ASYNCHRONOUS_NOTIFICATION
Definition: cdromp.h:138
LONG NTSTATUS
Definition: precomp.h:26
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: cdrom.h:162
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
void * PVOID
Definition: retypes.h:9
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:404
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
struct _MEDIA_CHANGE_DETECTION_INFO::@1028 Gesn
MEDIA_CHANGE_DETECTION_STATE LastReportedMediaDetectionState
Definition: cdromp.h:203
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define CDROM_TAG_MEDIA_CHANGE_DETECTION
Definition: cdrom.h:725
WDFOBJECT ParentObject
Definition: wdfobject.h:130
POWER_SETTING_CALLBACK DevicePowerSettingCallback
Definition: cdrom.h:1395
#define NULL
Definition: types.h:112
_In_ BOOLEAN AllowDriveToSleep
Definition: classpnp.h:1275
MEDIA_CHANGE_DETECTION_STATE LastKnownMediaDetectionState
Definition: cdromp.h:199
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
WDFREQUEST MediaChangeRequest
Definition: cdromp.h:246
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define STATUS_SUCCESS
Definition: shellext.h:65
static SERVICE_STATUS status
Definition: service.c:31
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
FxIrp * irp
NTKRNLVISTAAPI NTSTATUS NTAPI PoRegisterPowerSettingCallback(_In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LPCGUID SettingGuid, _In_ PPOWER_SETTING_CALLBACK Callback, _In_opt_ PVOID Context, _Outptr_opt_ PVOID *Handle)
Definition: po.c:14
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3312
Definition: ps.c:97

◆ DeviceDisableGesn()

VOID NTAPI DeviceDisableGesn ( _In_ WDFWORKITEM  WorkItem)

Definition at line 1019 of file autorun.c.

1036 {
1037  WDFDEVICE device = WdfWorkItemGetParentObject(WorkItem);
1038  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1039 
1040  PAGED_CODE();
1041 
1042  //
1043  // Set the hack flag in the registry
1044  //
1045  DeviceSetParameter(deviceExtension,
1049 
1050  WdfObjectDelete(WorkItem);
1051 
1052  return;
1053 }
#define CLASSP_REG_SUBKEY_NAME
Definition: cdromp.h:120
Definition: devices.h:37
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: cdromp.h:123
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
#define PAGED_CODE()

◆ DeviceInternalSetMediaChangeState()

VOID DeviceInternalSetMediaChangeState ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ MEDIA_CHANGE_DETECTION_STATE  NewState,
_Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE  OldState 
)

Definition at line 630 of file autorun.c.

661 {
662 #if DBG
663  LPCSTR states[] = {"Unknown", "Present", "Not Present", "Unavailable"};
664 #endif
665  MEDIA_CHANGE_DETECTION_STATE oldMediaState;
666  PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
667  CLASS_MEDIA_CHANGE_CONTEXT mcnContext;
668 
669  if (!((NewState >= MediaUnknown) && (NewState <= MediaUnavailable)))
670  {
671  return;
672  }
673 
674  if (info == NULL)
675  {
676  return;
677  }
678 
679  oldMediaState = info->LastKnownMediaDetectionState;
680  if (OldState)
681  {
682  *OldState = oldMediaState;
683  }
684 
685  info->LastKnownMediaDetectionState = NewState;
686 
687  // Increment MediaChangeCount on transition to MediaPresent
688  if (NewState == MediaPresent && oldMediaState != NewState)
689  {
690  InterlockedIncrement((PLONG)&DeviceExtension->MediaChangeCount);
691  }
692 
693  if (info->MediaChangeDetectionDisableCount != 0)
694  {
695 #if DBG
696  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
697  "DeviceInternalSetMediaChangeState: MCN not enabled, state "
698  "changed from %s to %s\n",
699  states[oldMediaState], states[NewState]));
700 #endif
701  return;
702  }
703 #if DBG
704  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
705  "DeviceInternalSetMediaChangeState: State change from %s to %s\n",
706  states[oldMediaState], states[NewState]));
707 #endif
708 
709  if (info->LastReportedMediaDetectionState == info->LastKnownMediaDetectionState)
710  {
711  // Media is in the same state as we reported last time, no need to report again.
712  return;
713  }
714 
715  // make the data useful -- it used to always be zero.
716  mcnContext.MediaChangeCount = DeviceExtension->MediaChangeCount;
717  mcnContext.NewState = NewState;
718 
719  if (NewState == MediaPresent)
720  {
721  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
722  "DeviceInternalSetMediaChangeState: Reporting media ARRIVAL\n"));
723 
724  DeviceSendNotification(DeviceExtension,
725  &GUID_IO_MEDIA_ARRIVAL,
727  &mcnContext);
728  }
729  else if ((NewState == MediaNotPresent) || (NewState == MediaUnavailable))
730  {
731  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
732  "DeviceInternalSetMediaChangeState: Reporting media REMOVAL\n"));
733  DeviceSendNotification(DeviceExtension,
734  &GUID_IO_MEDIA_REMOVAL,
736  &mcnContext);
737  }
738  else
739  {
740  // Don't notify of changed going to unknown.
741  return;
742  }
743 
744  info->LastReportedMediaDetectionState = info->LastKnownMediaDetectionState;
745 
746  return;
747 } // end DeviceInternalSetMediaChangeState()
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
VOID DeviceSendNotification(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ const GUID *Guid, _In_ ULONG ExtraDataSize, _In_opt_ PVOID ExtraData)
Definition: common.c:799
const char * LPCSTR
Definition: xmlstorage.h:183
enum _MEDIA_CHANGE_DETECTION_STATE MEDIA_CHANGE_DETECTION_STATE
#define InterlockedIncrement
Definition: armddk.h:53
#define NULL
Definition: types.h:112
signed int * PLONG
Definition: retypes.h:5

Referenced by _IRQL_requires_max_(), and DeviceSetMediaChangeStateEx().

◆ DeviceMainTimerTickHandler()

VOID NTAPI DeviceMainTimerTickHandler ( _In_ WDFTIMER  Timer)

Definition at line 2820 of file autorun.c.

2838 {
2839  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
2840  size_t dataLength = 0;
2841 
2842  deviceExtension = WdfObjectGetTypedContext(WdfTimerGetParentObject(Timer), CDROM_DEVICE_EXTENSION);
2843 
2844  (void) RequestHandleEventNotification(deviceExtension, NULL, NULL, &dataLength);
2845 
2846  return;
2847 } // end DeviceMainTimerTickHandler()
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
ULONG dataLength
Definition: scsi.h:3751
#define WdfObjectGetTypedContext(handle, type)
Definition: wdfobject.h:404
#define NULL
Definition: types.h:112

◆ DeviceMediaChangeRegistryCallBack()

NTSTATUS NTAPI DeviceMediaChangeRegistryCallBack ( _In_z_ PWSTR  ValueName,
_In_ ULONG  ValueType,
_In_reads_bytes_opt_(ValueLength) PVOID  ValueData,
_In_ ULONG  ValueLength,
_In_opt_ PVOID  Context,
_In_opt_ PVOID  EntryContext 
)

Definition at line 2058 of file autorun.c.

2090 {
2091  PULONG valueFound;
2092  PUNICODE_STRING deviceString;
2093  PWSTR keyValue;
2094 
2095  PAGED_CODE();
2096 
2098 
2099  if ((Context == NULL) || (EntryContext == NULL))
2100  {
2101  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2102  "DeviceMediaChangeRegistryCallBack: NULL context should never be passed to registry call-back!\n"));
2103 
2104  return STATUS_SUCCESS;
2105  }
2106 
2107  // if we have already set the value to true, exit
2108  valueFound = EntryContext;
2109  if ((*valueFound) != 0)
2110  {
2111  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2112  "DeviceMediaChangeRegistryCallBack: already set to true\n"));
2113  return STATUS_SUCCESS;
2114  }
2115 
2116  if (ValueLength == sizeof(WCHAR))
2117  {
2118  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_MCN,
2119  "DeviceMediaChangeRegistryCallBack: NULL string should never be passed to registry call-back!\n"));
2120  return STATUS_SUCCESS;
2121  }
2122 
2123  // if the data is not a terminated string, exit
2124  if (ValueType != REG_SZ)
2125  {
2126  return STATUS_SUCCESS;
2127  }
2128 
2129  deviceString = Context;
2130  keyValue = ValueData;
2131  ValueLength -= sizeof(WCHAR); // ignore the null character
2132 
2133  // do not compare more memory than is in deviceString
2134  if (ValueLength > deviceString->Length)
2135  {
2136  ValueLength = deviceString->Length;
2137  }
2138 
2139  if (keyValue == NULL)
2140  {
2141  return STATUS_SUCCESS;
2142  }
2143 
2144  // if the strings match, disable autorun
2145  if (RtlCompareMemory(deviceString->Buffer, keyValue, ValueLength) == ValueLength)
2146  {
2147  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "DeviceMediaChangeRegistryCallBack: Match found\n"));
2148  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN, "DeviceMediaChangeRegistryCallBack: DeviceString at %p\n",
2149  deviceString->Buffer));
2150  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_MCN,
2151  "DeviceMediaChangeRegistryCallBack: KeyValue at %p\n",
2152  keyValue));
2153  (*valueFound) = TRUE;
2154  }
2155 
2156  return STATUS_SUCCESS;
2157 } // end DeviceMediaChangeRegistryCallBack()
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
uint16_t * PWSTR
Definition: typedefs.h:56
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:279
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4142
__wchar_t WCHAR
Definition: xmlstorage.h:180
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:240
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
struct tagContext Context
Definition: acpixf.h:1034
#define STATUS_SUCCESS
Definition: shellext.h:65
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define PAGED_CODE()
#define REG_SZ
Definition: layer.c:22
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:271

◆ DeviceSetMediaChangeStateEx()

VOID DeviceSetMediaChangeStateEx ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
_In_ MEDIA_CHANGE_DETECTION_STATE  NewState,
_Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE  OldState 
)

Definition at line 751 of file autorun.c.

778 {
779  PMEDIA_CHANGE_DETECTION_INFO info = DeviceExtension->MediaChangeDetectionInfo;
782 
783  // timeout value must be 0, as this function can be called at DISPATCH_LEVEL.
784  zero.QuadPart = 0;
785 
786  if (info == NULL)
787  {
788  return;
789  }
790 
791  status = KeWaitForMutexObject(&info->MediaChangeMutex,
792  Executive,
793  KernelMode,
794  FALSE,
795  &zero);
796 
797  if (status == STATUS_TIMEOUT)
798  {
799  // Someone else is in the process of setting the media state.
800  return;
801  }
802 
803  // Change the media present state and signal an event, if applicable
804  DeviceInternalSetMediaChangeState(DeviceExtension, NewState, OldState);
805 
806  KeReleaseMutex(&info->MediaChangeMutex, FALSE);
807 
808  return;
809 } // end DeviceSetMediaChangeStateEx()
#define KeWaitForMutexObject
Definition: kefuncs.h:555
LONG NTSTATUS
Definition: precomp.h:26
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
VOID DeviceInternalSetMediaChangeState(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ MEDIA_CHANGE_DETECTION_STATE NewState, _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState)
Definition: autorun.c:630
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define FALSE
Definition: types.h:117
int zero
Definition: sehframes.cpp:29
#define NULL
Definition: types.h:112
static SERVICE_STATUS status
Definition: service.c:31
Definition: ps.c:97

Referenced by DeviceEvtSelfManagedIoInit(), and SenseInfoInterpretByAdditionalSenseCode().

◆ RequestMcnSyncIrpCompletion()

NTSTATUS NTAPI RequestMcnSyncIrpCompletion ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp,
_In_reads_opt_(_Inexpressible_("varies")) PVOID  Context 
)

Definition at line 2695 of file autorun.c.

2719 {
2720  PCDROM_DEVICE_EXTENSION DeviceExtension = NULL;
2722 
2723  if (Context == NULL)
2724  {
2725  // this will never happen, but code must be there to prevent OACR warnings.
2727  }
2728 
2729  DeviceExtension = (PCDROM_DEVICE_EXTENSION) Context;
2730  info = DeviceExtension->MediaChangeDetectionInfo;
2731 
2732 #ifndef DEBUG
2734 #endif
2736 
2737  NT_ASSERT(Irp == info->MediaChangeSyncIrp);
2738 
2739  IoReuseIrp(info->MediaChangeSyncIrp, STATUS_NOT_SUPPORTED);
2740 
2741  // reset the value to let timer routine be able to send the next request.
2742  InterlockedCompareExchange((PLONG)&(info->MediaChangeRequestInUse), 0, 1);
2743 
2745 }
return STATUS_NOT_SUPPORTED
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define InterlockedCompareExchange
Definition: interlocked.h:104
struct _CDROM_DEVICE_EXTENSION * PCDROM_DEVICE_EXTENSION
Definition: cdrom.h:216
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: cdrom.h:563
signed int * PLONG
Definition: retypes.h:5
#define NT_ASSERT
Definition: rtlfuncs.h:3312

◆ RequestSetupMcnSyncIrp()

VOID RequestSetupMcnSyncIrp ( _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension)

Definition at line 2749 of file autorun.c.

2766 {
2767  PIRP irp = NULL;
2768  PIO_STACK_LOCATION irpStack = NULL;
2769  PIO_STACK_LOCATION nextIrpStack = NULL;
2770 
2771  irp = DeviceExtension->MediaChangeDetectionInfo->MediaChangeSyncIrp;
2772  NT_ASSERT(irp != NULL);
2773 
2774  //
2775  // For the driver that creates an IRP, there is no 'current' stack location.
2776  // Step down one IRP stack location so that the extra top one
2777  // becomes our 'current' one.
2778  //
2780 
2781  /*
2782  * Cache our device object in the extra top IRP stack location
2783  * so we have it in our completion routine.
2784  */
2785  irpStack = IoGetCurrentIrpStackLocation(irp);
2786  irpStack->DeviceObject = DeviceExtension->DeviceObject;
2787 
2788  //
2789  // If the irp is sent down when the volume needs to be
2790  // verified, CdRomUpdateGeometryCompletion won't complete
2791  // it since it's not associated with a thread. Marking
2792  // it to override the verify causes it always be sent
2793  // to the port driver
2794  //
2795  nextIrpStack = IoGetNextIrpStackLocation(irp);
2796 
2797  SET_FLAG(nextIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
2798 
2799  nextIrpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
2800  // pick up this IOCTL code as it's not normaly seen for CD/DVD drive and does not require input.
2801  // set other fields to make this IOCTL recognizable by CDROM.SYS
2802  nextIrpStack->Parameters.Others.Argument1 = RequestSetupMcnSyncIrp;
2803  nextIrpStack->Parameters.Others.Argument2 = RequestSetupMcnSyncIrp;
2804  nextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_MCN_SYNC_FAKE_IOCTL; //Argument3.
2805  nextIrpStack->Parameters.Others.Argument4 = RequestSetupMcnSyncIrp;
2806 
2809  DeviceExtension,
2810  TRUE,
2811  TRUE,
2812  TRUE);
2813 
2814  return;
2815 }
#define TRUE
Definition: types.h:120
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1803
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3202
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
#define NULL
Definition: types.h:112
#define IOCTL_MCN_SYNC_FAKE_IOCTL
Definition: cdrom.h:181
IO_COMPLETION_ROUTINE RequestMcnSyncIrpCompletion
Definition: autorun.c:2691
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
FxIrp * irp
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define NT_ASSERT
Definition: rtlfuncs.h:3312

Referenced by RequestDispatchSpecialIoctls(), and RequestSetupMcnSyncIrp().

Variable Documentation

◆ RequestMcnSyncIrpCompletion

IO_COMPLETION_ROUTINE RequestMcnSyncIrpCompletion

Definition at line 2691 of file autorun.c.

Referenced by RequestSetupMcnSyncIrp().