ReactOS  0.4.15-dev-985-gd905dd5
autorun.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4 
5 Module Name:
6 
7  autorun.c
8 
9 Abstract:
10 
11  Code for support of media change detection in the class driver
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #include "classp.h"
25 #include "debug.h"
26 
27 #ifdef DEBUG_USE_WPP
28 #include "autorun.tmh"
29 #endif
30 
31 #define GESN_TIMEOUT_VALUE (0x4)
32 #define GESN_BUFFER_SIZE (0x8)
33 #define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS (2)
34 
35 #define MAXIMUM_IMMEDIATE_MCN_RETRIES (0x20)
36 #define MCN_REG_SUBKEY_NAME (L"MediaChangeNotification")
37 #define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME (L"AlwaysDisableMCN")
38 #define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME (L"AlwaysEnableMCN")
39 
41 
42 //
43 // Only send polling irp when device is fully powered up, a
44 // power down irp is not in progress, and the screen is on.
45 //
46 // NOTE: This helps close a window in time where a polling irp could cause
47 // a drive to spin up right after it has powered down. The problem is
48 // that SCSIPORT, ATAPI and SBP2 will be in the process of powering
49 // down (which may take a few seconds), but won't know that. It would
50 // then get a polling irp which will be put into its queue since it
51 // the disk isn't powered down yet. Once the disk is powered down it
52 // will find the polling irp in the queue and then power up the
53 // device to do the poll. They do not want to check if the polling
54 // irp has the SRB_NO_KEEP_AWAKE flag here since it is in a critical
55 // path and would slow down all I/Os. A better way to fix this
56 // would be to serialize the polling and power down irps so that
57 // only one of them is sent to the device at a time.
58 //
59 __inline
60 BOOLEAN
63  )
64 {
65  return ((fdoExtension->DevicePowerState == PowerDeviceD0) &&
66  (fdoExtension->PowerDownInProgress == FALSE) &&
67  (ClasspScreenOff == FALSE));
68 }
69 
70 BOOLEAN
74  );
75 
80  );
81 
82 BOOLEAN
86  );
87 
88 VOID
92  IN BOOLEAN Wait,
93  IN BOOLEAN KnownStateChange // can ignore oldstate == unknown
94  );
95 
96 RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack;
97 
98 VOID
102  IN ULONG CountDown
103  );
104 
105 IO_WORKITEM_ROUTINE ClasspFailurePredict;
106 
107 NTSTATUS
111  );
112 
113 
114 IO_WORKITEM_ROUTINE ClasspDisableGesn;
115 
117 
118 KDEFERRED_ROUTINE ClasspTimerTick;
119 
120 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
121 EXT_CALLBACK ClasspTimerTickEx;
122 #endif
123 
125 
126 //
127 // Tick timer related defines.
128 //
129 #define TICK_TIMER_PERIOD_IN_MSEC 1000
130 #define TICK_TIMER_DELAY_IN_MSEC 1000
131 
132 #if ALLOC_PRAGMA
133 
134 #pragma alloc_text(PAGE, ClassInitializeMediaChangeDetection)
135 #pragma alloc_text(PAGE, ClassEnableMediaChangeDetection)
136 #pragma alloc_text(PAGE, ClassDisableMediaChangeDetection)
137 #pragma alloc_text(PAGE, ClassCleanupMediaChangeDetection)
138 #pragma alloc_text(PAGE, ClasspMediaChangeRegistryCallBack)
139 #pragma alloc_text(PAGE, ClasspInitializePolling)
140 #pragma alloc_text(PAGE, ClasspDisableGesn)
141 
142 #pragma alloc_text(PAGE, ClasspIsMediaChangeDisabledDueToHardwareLimitation)
143 #pragma alloc_text(PAGE, ClasspMediaChangeDeviceInstanceOverride)
144 #pragma alloc_text(PAGE, ClasspIsMediaChangeDisabledForClass)
145 
146 #pragma alloc_text(PAGE, ClassSetFailurePredictionPoll)
147 
148 #pragma alloc_text(PAGE, ClasspInitializeGesn)
149 #pragma alloc_text(PAGE, ClasspMcnControl)
150 
151 #endif
152 
153 // ISSUE -- make this public?
154 VOID
157  )
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 }
186 
187 
189 VOID
190 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
191 ClassSendNotification(
193  _In_ const GUID * Guid,
196  )
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 }
248 
249 
250 NTSTATUS
254  OUT PBOOLEAN ResendImmediately
255  )
256 
257 /*++
258 
259 Routine Description:
260 
261  This routine will interpret the data returned for a GESN command, and
262  (if appropriate) set the media change event, and broadcast the
263  appropriate events to user mode for applications who care.
264 
265 Arguments:
266 
267  FdoExtension - the device
268 
269  DataBuffer - the resulting data from a GESN event.
270  requires at least EIGHT valid bytes (header == 4, data == 4)
271 
272  ResendImmediately - whether or not to immediately resend the request.
273  this should be FALSE if there was no event, FALSE if the reported
274  event was of the DEVICE BUSY class, else true.
275 
276 Return Value:
277 
278  STATUS_SUCCESS if successful, an error code otherwise
279 
280 Notes:
281 
282  DataBuffer must be at least four bytes of valid data (header == 4 bytes),
283  and have at least eight bytes of allocated memory (all events == 4 bytes).
284 
285  The call to StartNextPacket may occur before this routine is completed.
286  the operational change notifications are informational in nature, and
287  while useful, are not neccessary to ensure proper operation. For example,
288  if the device morphs to no longer supporting WRITE commands, all further
289  write commands will fail. There exists a small timing window wherein
290  IOCTL_IS_DISK_WRITABLE may be called and get an incorrect response. If
291  a device supports software write protect, it is expected that the
292  application can handle such a case.
293 
294  NOTE: perhaps setting the updaterequired byte to one should be done here.
295  if so, it relies upon the setting of a 32-byte value to be an atomic
296  operation. unfortunately, there is no simple way to notify a class driver
297  which wants to know that the device behavior requires updating.
298 
299  Not ready events may be sent every second. For example, if we were
300  to minimize the number of asynchronous notifications, an application may
301  register just after a large busy time was reported. This would then
302  prevent the application from knowing the device was busy until some
303  arbitrarily chosen timeout has occurred. Also, the GESN request would
304  have to still occur, since it checks for non-busy events (such as user
305  keybutton presses and media change events) as well. The specification
306  states that the lower-numered events get reported first, so busy events,
307  while repeating, will only be reported when all other events have been
308  cleared from the device.
309 
310 --*/
311 
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 }
769 
770 /*++////////////////////////////////////////////////////////////////////////////
771 
772 ClasspInternalSetMediaChangeState()
773 
774 Routine Description:
775 
776  This routine will (if appropriate) set the media change event for the
777  device. The event will be set if the media state is changed and
778  media change events are enabled. Otherwise the media state will be
779  tracked but the event will not be set.
780 
781  This routine will lock out the other media change routines if possible
782  but if not a media change notification may be lost after the enable has
783  been completed.
784 
785 Arguments:
786 
787  FdoExtension - the device
788 
789  MediaPresent - indicates whether the device has media inserted into it
790  (TRUE) or not (FALSE).
791 
792 Return Value:
793 
794  none
795 
796 --*/
797 VOID
801  IN BOOLEAN KnownStateChange // can ignore oldstate == unknown
802  )
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()
914 
915 /*++////////////////////////////////////////////////////////////////////////////
916 
917 ClassSetMediaChangeState()
918 
919 Routine Description:
920 
921  This routine will (if appropriate) set the media change event for the
922  device. The event will be set if the media state is changed and
923  media change events are enabled. Otherwise the media state will be
924  tracked but the event will not be set.
925 
926  This routine will lock out the other media change routines if possible
927  but if not a media change notification may be lost after the enable has
928  been completed.
929 
930 Arguments:
931 
932  FdoExtension - the device
933 
934  MediaPresent - indicates whether the device has media inserted into it
935  (TRUE) or not (FALSE).
936 
937  Wait - indicates whether the function should wait until it can acquire
938  the synchronization lock or not.
939 
940 Return Value:
941 
942  none
943 
944 --*/
945 
946 VOID
947 #ifdef _MSC_VER
948 #pragma prefast(suppress:26165, "The mutex won't be acquired in the case of a timeout.")
949 #endif
953  IN BOOLEAN Wait,
954  IN BOOLEAN KnownStateChange // can ignore oldstate == unknown
955  )
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()
1011 
1013 VOID
1014 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1015 ClassSetMediaChangeState(
1018  _In_ BOOLEAN Wait
1019  )
1020 {
1022  return;
1023 }
1024 
1025 /*++////////////////////////////////////////////////////////////////////////////
1026 
1027 ClasspMediaChangeDetectionCompletion()
1028 
1029 Routine Description:
1030 
1031  This routine handles the completion of the test unit ready irps used to
1032  determine if the media has changed. If the media has changed, this code
1033  signals the named event to wake up other system services that react to
1034  media change (aka AutoPlay).
1035 
1036 Arguments:
1037 
1038  DeviceObject - the object for the completion
1039  Irp - the IRP being completed
1040  Context - the SRB from the IRP
1041 
1042 Return Value:
1043 
1044  NTSTATUS
1045 
1046 --*/
1047 NTSTATUS
1048 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1051  PIRP Irp,
1052  PVOID Context
1053  )
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 }
1291 
1292 /*++////////////////////////////////////////////////////////////////////////////
1293 
1294 ClasspSendTestUnitIrp() - ISSUE-2000/02/20-henrygab - not documented
1295 
1296 Routine Description:
1297 
1298  This routine
1299 
1300 Arguments:
1301 
1302  DeviceObject -
1303  Irp -
1304 
1305 Return Value:
1306 
1307 
1308 --*/
1309 PIRP
1313  IN BOOLEAN UseGesn
1314 )
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 }
1541 
1542 /*++////////////////////////////////////////////////////////////////////////////
1543 
1544 ClasspSendMediaStateIrp() - ISSUE-2000/02/20-henrygab - not documented
1545 
1546 Routine Description:
1547 
1548  This routine
1549 
1550 Arguments:
1551 
1552  DeviceObject -
1553  Irp -
1554 
1555 Return Value:
1556 
1557 --*/
1558 VOID
1562  IN ULONG CountDown
1563  )
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()
1730 
1731 /*++////////////////////////////////////////////////////////////////////////////
1732 
1733 ClassCheckMediaState()
1734 
1735 Routine Description:
1736 
1737  This routine is called by the class driver to test for a media change
1738  condition and/or poll for disk failure prediction. It should be called
1739  from the class driver's IO timer routine once per second.
1740 
1741 Arguments:
1742 
1743  FdoExtension - the device extension
1744 
1745 Return Value:
1746 
1747  none
1748 
1749 --*/
1750 VOID
1751 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1754  )
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()
1784 
1785 /*++////////////////////////////////////////////////////////////////////////////
1786 
1787 ClassResetMediaChangeTimer()
1788 
1789 Routine Description:
1790 
1791  Resets the media change count down timer to the default number of seconds.
1792 
1793 Arguments:
1794 
1795  FdoExtension - the device to reset the timer for
1796 
1797 Return Value:
1798 
1799  None
1800 
1801 --*/
1802 VOID
1803 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1806  )
1807 {
1808  PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
1809 
1810  if(info != NULL) {
1811  InterlockedExchange(&(info->MediaChangeCountDown),
1813  }
1814  return;
1815 } // end ClassResetMediaChangeTimer()
1816 
1817 /*++////////////////////////////////////////////////////////////////////////////
1818 
1819 ClasspInitializePolling() - ISSUE-2000/02/20-henrygab - not documented
1820 
1821 Routine Description:
1822 
1823  This routine
1824 
1825 Arguments:
1826 
1827  DeviceObject -
1828  Irp -
1829 
1830 Return Value:
1831 
1832 --*/
1833 NTSTATUS
1837  )
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()
1988 
1989 NTSTATUS
1993  )
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 }
2364 
2365 
2366 //
2367 // Work item to set the hack flag in the registry to disable GESN
2368 // on devices that sends too many events
2369 //
2370 
2371 VOID
2372 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2374  IN PDEVICE_OBJECT Fdo,
2375  IN PVOID Context
2376  )
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 }
2393 
2394 /*++////////////////////////////////////////////////////////////////////////////
2395 
2396 ClassInitializeTestUnitPolling()
2397 
2398 Routine Description:
2399 
2400  This routine will initialize MCN regardless of the settings stored
2401  in the registry. This should be used with caution, as some devices
2402  react badly to constant io. (i.e. never spin down, continuously cycling
2403  media in changers, ejection of media, etc.) It is highly suggested to
2404  use ClassInitializeMediaChangeDetection() instead.
2405 
2406 Arguments:
2407 
2408  FdoExtension is the device to poll
2409 
2410  AllowDriveToSleep says whether to attempt to allow the drive to sleep
2411  or not. This only affects system-known spin down states, so if a
2412  drive spins itself down, this has no effect until the system spins
2413  it down.
2414 
2415 Return Value:
2416 
2417 --*/
2419 NTSTATUS
2420 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2421 ClassInitializeTestUnitPolling(
2424  )
2425 {
2427 } // end ClassInitializeTestUnitPolling()
2428 
2429 /*++////////////////////////////////////////////////////////////////////////////
2430 
2431 ClassInitializeMediaChangeDetection()
2432 
2433 Routine Description:
2434 
2435  This routine checks to see if it is safe to initialize MCN (the back end
2436  to autorun) for a given device. It will then check the device-type wide
2437  key "Autorun" in the service key (for legacy reasons), and then look in
2438  the device-specific key to potentially override that setting.
2439 
2440  If MCN is to be enabled, all neccessary structures and memory are
2441  allocated and initialized.
2442 
2443  This routine MUST be called only from the ClassInit() callback.
2444 
2445 Arguments:
2446 
2447  FdoExtension - the device to initialize MCN for, if appropriate
2448 
2449  EventPrefix - unused, legacy argument. Set to zero.
2450 
2451 Return Value:
2452 
2453 --*/
2455 VOID
2456 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2457 ClassInitializeMediaChangeDetection(
2460  )
2461 {
2462  PDEVICE_OBJECT fdo = FdoExtension->DeviceObject;
2463  NTSTATUS status;
2464 
2465  PCLASS_DRIVER_EXTENSION driverExtension = ClassGetDriverExtension(
2466  fdo->DriverObject);
2467 
2468  BOOLEAN disabledForBadHardware;
2469  BOOLEAN disabled;
2470  BOOLEAN instanceOverride;
2471 
2473 
2474  PAGED_CODE();
2475 
2476  //
2477  // NOTE: This assumes that ClassInitializeMediaChangeDetection is always
2478  // called in the context of the ClassInitDevice callback. If called
2479  // after then this check will have already been made and the
2480  // once a second timer will not have been enabled.
2481  //
2482 
2483  disabledForBadHardware = ClasspIsMediaChangeDisabledDueToHardwareLimitation(
2484  FdoExtension,
2485  &(driverExtension->RegistryPath)
2486  );
2487 
2488  if (disabledForBadHardware) {
2489  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2490  "ClassInitializeMCN: Disabled due to hardware"
2491  "limitations for this device"));
2492  return;
2493  }
2494 
2495  //
2496  // autorun should now be enabled by default for all media types.
2497  //
2498 
2500  FdoExtension,
2501  &(driverExtension->RegistryPath)
2502  );
2503 
2504  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2505  "ClassInitializeMCN: Class MCN is %s\n",
2506  (disabled ? "disabled" : "enabled")));
2507 
2509  FdoExtension,
2510  &instanceOverride); // default value
2511 
2512  if (!NT_SUCCESS(status)) {
2513  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2514  "ClassInitializeMCN: Instance using default\n"));
2515  } else {
2516  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2517  "ClassInitializeMCN: Instance override: %s MCN\n",
2518  (instanceOverride ? "Enabling" : "Disabling")));
2519  disabled = !instanceOverride;
2520  }
2521 
2522  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
2523  "ClassInitializeMCN: Instance MCN is %s\n",
2524  (disabled ? "disabled" : "enabled")));
2525 
2526  if (disabled) {
2527  return;
2528  }
2529 
2530  //
2531  // Do not allow drive to sleep for all types of devices initially.
2532  // For non-cdrom devices, allow devices to go to sleep if it's
2533  // unlikely a media change will occur (e.g. user not present).
2534  //
2536 
2537  return;
2538 } // end ClassInitializeMediaChangeDetection()
2539 
2540 /*++////////////////////////////////////////////////////////////////////////////
2541 
2542 ClasspMediaChangeDeviceInstanceOverride()
2543 
2544 Routine Description:
2545 
2546  The user can override the global setting to enable or disable Autorun on a
2547  specific cdrom device via the control panel. This routine checks and/or
2548  sets this value.
2549 
2550 Arguments:
2551 
2552  FdoExtension - the device to set/get the value for
2553  Value - the value to use in a set
2554  SetValue - whether to set the value
2555 
2556 Return Value:
2557 
2558  TRUE - Autorun is disabled
2559  FALSE - Autorun is not disabled (Default)
2560 
2561 --*/
2562 NTSTATUS
2566  )
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()
2701 
2702 /*++////////////////////////////////////////////////////////////////////////////
2703 
2704 ClasspIsMediaChangeDisabledDueToHardwareLimitation()
2705 
2706 Routine Description:
2707 
2708  The key AutoRunAlwaysDisable contains a MULTI_SZ of hardware IDs for
2709  which to never enable MediaChangeNotification.
2710 
2711  The user can override the global setting to enable or disable Autorun on a
2712  specific cdrom device via the control panel.
2713 
2714 Arguments:
2715 
2716  FdoExtension -
2717  RegistryPath - pointer to the unicode string inside
2718  ...\CurrentControlSet\Services\Cdrom
2719 
2720 Return Value:
2721 
2722  TRUE - no autorun.
2723  FALSE - Autorun may be enabled
2724 
2725 --*/
2726 BOOLEAN
2730  )
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()
2929 
2930 /*++////////////////////////////////////////////////////////////////////////////
2931 
2932 ClasspIsMediaChangeDisabledForClass()
2933 
2934 Routine Description:
2935 
2936  The user must specify that AutoPlay is to run on the platform
2937  by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
2938  Services<SERVICE>\Autorun:REG_DWORD:1.
2939 
2940  The user can override the global setting to enable or disable Autorun on a
2941  specific cdrom device via the control panel.
2942 
2943 Arguments:
2944 
2945  FdoExtension -
2946  RegistryPath - pointer to the unicode string inside
2947  ...\CurrentControlSet\Services\Cdrom
2948 
2949 Return Value:
2950 
2951  TRUE - Autorun is disabled for this class
2952  FALSE - Autorun is enabled for this class
2953 
2954 --*/
2955 BOOLEAN
2959  )
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()
3081 
3082 /*++////////////////////////////////////////////////////////////////////////////
3083 
3084 ClassEnableMediaChangeDetection() ISSUE-2000/02/20-henrygab - why public?
3085 ClassEnableMediaChangeDetection() ISSUE-2000/02/20-henrygab - not documented
3086 
3087 Routine Description:
3088 
3089  This routine
3090 
3091 Arguments:
3092 
3093  DeviceObject -
3094  Irp -
3095 
3096 Return Value:
3097 
3098 --*/
3100 VOID
3101 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3102 ClassEnableMediaChangeDetection(
3104  )
3105 {
3106  PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
3107  LONG oldCount;
3108 
3109  PAGED_CODE();
3110 
3111  if(info == NULL) {
3112  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN,
3113  "ClassEnableMediaChangeDetection: not initialized\n"));
3114  return;
3115  }
3116 
3117  (VOID)KeWaitForMutexObject(&info->MediaChangeMutex,
3118  UserRequest,
3119  KernelMode,
3120  FALSE,
3121  NULL);
3122 
3123  oldCount = --info->MediaChangeDetectionDisableCount;
3124 
3125  NT_ASSERT(oldCount >= 0);
3126 
3127  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassEnableMediaChangeDetection: Disable count "
3128  "reduced to %d - ",
3129  info->MediaChangeDetectionDisableCount));
3130 
3131  if(oldCount == 0) {
3132 
3133  //
3134  // We don't know what state the media is in anymore.
3135  //
3136 
3138  MediaUnknown,
3139  FALSE
3140  );
3141 
3142  //
3143  // Reset the MCN timer.
3144  //
3145 
3147 
3148  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCD is enabled\n"));
3149 
3150  } else {
3151 
3152  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "MCD still disabled\n"));
3153 
3154  }
3155 
3156 
3157  //
3158  // Let something else run.
3159  //
3160 
3161  KeReleaseMutex(&info->MediaChangeMutex, FALSE);
3162 
3163  return;
3164 } // end ClassEnableMediaChangeDetection()
3165 
3166 /*++////////////////////////////////////////////////////////////////////////////
3167 
3168 ClassDisableMediaChangeDetection() ISSUE-2000/02/20-henrygab - why public?
3169 ClassDisableMediaChangeDetection() ISSUE-2000/02/20-henrygab - not documented
3170 
3171 Routine Description:
3172 
3173  This routine
3174 
3175 Arguments:
3176 
3177  DeviceObject -
3178  Irp -
3179 
3180 Return Value:
3181 
3182 --*/
3184 
3186 VOID
3187 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3188 ClassDisableMediaChangeDetection(
3190  )
3191 {
3192  PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
3193 
3194  PAGED_CODE();
3195 
3196  if(info == NULL) {
3197  return;
3198  }
3199 
3200  (VOID)KeWaitForMutexObject(&info->MediaChangeMutex,
3201  UserRequest,
3202  KernelMode,
3203  FALSE,
3204  NULL);
3205 
3206  info->MediaChangeDetectionDisableCount++;
3207 
3208  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_MCN, "ClassDisableMediaChangeDetection: "
3209  "disable count is %d\n",
3210  info->MediaChangeDetectionDisableCount));
3211 
3212  KeReleaseMutex(&info->MediaChangeMutex, FALSE);
3213 
3214  return;
3215 } // end ClassDisableMediaChangeDetection()
3216 
3217 /*++////////////////////////////////////////////////////////////////////////////
3218 
3219 ClassCleanupMediaChangeDetection() ISSUE-2000/02/20-henrygab - why public?!
3220 
3221 Routine Description:
3222 
3223  This routine will cleanup any resources allocated for MCN. It is called
3224  by classpnp during remove device, and therefore is not typically required
3225  by external drivers.
3226 
3227 Arguments:
3228 
3229 Return Value:
3230 
3231 --*/
3233 VOID
3234 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3235 ClassCleanupMediaChangeDetection(
3237  )
3238 {
3239  PMEDIA_CHANGE_DETECTION_INFO info = FdoExtension->MediaChangeDetectionInfo;
3240 
3241  PAGED_CODE()
3242 
3243  if(info == NULL) {
3244  return;
3245  }
3246 
3247  FdoExtension->MediaChangeDetectionInfo = NULL;
3248 
3249  if (info->Gesn.Mdl) {
3250  IoFreeMdl(info->Gesn.Mdl);
3251  }
3252  FREE_POOL(info->Gesn.Buffer);
3253  IoFreeIrp(info->MediaChangeIrp);
3254  FREE_POOL(info->SenseBuffer);
3255  FREE_POOL(info);
3256  return;
3257 } // end ClassCleanupMediaChangeDetection()
3258 
3259 /*++////////////////////////////////////////////////////////////////////////////
3260 
3261 ClasspMcnControl() - ISSUE-2000/02/20-henrygab - not documented
3262 
3263 Routine Description:
3264 
3265  This routine
3266 
3267 Arguments:
3268 
3269  DeviceObject -
3270  Irp -
3271 
3272 Return Value:
3273 
3274 --*/
3275 NTSTATUS
3278  IN PIRP Irp,
3280  )
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(
3353 
3354 /*++////////////////////////////////////////////////////////////////////////////
3355 
3356 ClasspMediaChangeRegistryCallBack()
3357 
3358 Routine Description:
3359 
3360  This callback for a registry SZ or MULTI_SZ is called once for each
3361  SZ in the value. It will attempt to match the data with the
3362  UNICODE_STRING passed in as Context, and modify EntryContext if a
3363  match is found. Written for ClasspCheckRegistryForMediaChangeCompletion
3364 
3365 Arguments:
3366 
3367  ValueName - name of the key that was opened
3368  ValueType - type of data stored in the value (REG_SZ for this routine)
3369  ValueData - data in the registry, in this case a wide string
3370  ValueLength - length of the data including the terminating null
3371  Context - unicode string to compare against ValueData
3372  EntryContext - should be initialized to 0, will be set to 1 if match found
3373 
3374 Return Value:
3375 
3376  STATUS_SUCCESS
3377  EntryContext will be 1 if found
3378 
3379 --*/
3380 _Function_class_(RTL_QUERY_REGISTRY_ROUTINE)
3383 NTSTATUS
3384 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3392  )
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()
3459 
3460 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
3461 VOID
3463  _In_ PEX_TIMER Timer,
3465 )
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 }
3478 #endif
3479 
3480 /*++////////////////////////////////////////////////////////////////////////////
3481 
3482 ClasspTimerTick() - ISSUE-2000/02/20-henrygab - not documented
3483 
3484 Routine Description:
3485 
3486  This routine
3487 
3488 Arguments:
3489 
3490  DeviceObject -
3491  Irp -
3492 
3493 Return Value:
3494 
3495 --*/
3496 _Function_class_(KDEFERRED_ROUTINE)
3501 VOID
3502 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3504  _In_ PKDPC Dpc,
3508  )
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()
3650 
3651 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
3652 BOOLEAN
3655 )
3656 /*
3657 Routine Description:
3658 
3659  Updates the no-wake timer's tolerance based on system state.
3660 
3661  If the timer is not allocated, initialized, or enabled then this function
3662  does nothing.
3663 
3664  If the timer is enabled but the no-wake tolerance has *not* changed from
3665  its previous value then this function does nothing.
3666 
3667  If the timer is enabled and the no-wake tolerance has changed from its
3668  previous value then this function *will* set/reset the tick timer.
3669 
3670 Arguments:
3671 
3672  FdoExtension for the device that has the timer whose tolerance needs updating.
3673 
3674 Returns:
3675 
3676  TRUE if the timer was set/reset.
3677  FALSE if the timer was not set/reset.
3678 
3679 */
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 }
3734 #endif
3735 
3736 NTSTATUS
3739 )
3740 /*
3741 Routine Description:
3742 
3743  This routine will attempt to initialize the tick timer.
3744  The caller should call ClasspEnableTmer() to actually start the timer.
3745 
3746  If the caller just needs to check if the timer is initialized, the caller
3747  should simply check FdoExtension->PrivateFdoData->TimerInitialized rather
3748  than call this function.
3749 
3750  The caller should subsequently call ClasspDeleteTimer() when they are done
3751  with the timer.
3752 
3753 Arguments:
3754 
3755  FdoExtension
3756 
3757 Return Value:
3758 
3759  STATUS_SUCCESS if the timer is initialized (the timer may already have been
3760  initialized by a previous call).
3761  A non-success status if the timer is not initialized.
3762 
3763 */
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 }
3796 
3797 VOID
3800 )
3801 /*
3802 Routine Description:
3803 
3804  This routine will attempt to de-initialize and free the tick timer.
3805  This routine should only be called after a successful call to
3806  ClasspInitializeTimer().
3807 
3808 Arguments:
3809 
3810  FdoExtension
3811 
3812 Return Value:
3813 
3814  None.
3815 
3816 */
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 }
3836 
3837 /*++////////////////////////////////////////////////////////////////////////////
3838 
3839 ClasspEnableTimer() - ISSUE-2000/02/20-henrygab - not documented
3840 
3841 Routine Description:
3842 
3843  This routine will enable the tick timer. ClasspInitializeTimer() should
3844  first be called to initialize the timer. Use ClasspDisableTimer() to
3845  disable the timer and then call this function to re-enable it.
3846 
3847 Arguments:
3848 
3849  FdoExtension
3850 
3851 Return Value:
3852 
3853  None.
3854 
3855 --*/
3856 VOID
3859  )
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()
3939 
3940 /*++////////////////////////////////////////////////////////////////////////////
3941 
3942 ClasspDisableTimer() - ISSUE-2000/02/20-henrygab - not documented
3943 
3944 Routine Description:
3945 
3946  This routine
3947 
3948 Arguments:
3949 
3950  FdoExtension
3951 
3952 Return Value:
3953 
3954 --*/
3955 VOID
3958  )
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()
3996 
3997 /*++////////////////////////////////////////////////////////////////////////////
3998 
3999 ClasspFailurePredict() - ISSUE-2000/02/20-henrygab - not documented
4000 
4001 Routine Description:
4002 
4003  This routine
4004 
4005 Arguments:
4006 
4007  DeviceObject - Device object
4008  Context - Context (PFAILURE_PREDICTION_INFO)
4009 
4010 Return Value:
4011 
4012 Note: this function can be called (via the workitem callback) after the paging device is shut down,
4013  so it must be PAGE LOCKED.
4014 --*/
4015 VOID
4016 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4019  IN PVOID Context
4020  )
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()
4159 
4160 /*++////////////////////////////////////////////////////////////////////////////
4161 
4162 ClassNotifyFailurePredicted() ISSUE-alanwar-2000/02/20 - not documented
4163 
4164 Routine Description:
4165 
4166 Arguments:
4167 
4168 Return Value:
4169 
4170 --*/
4172 VOID
4173 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4174 ClassNotifyFailurePredicted(
4180  _In_ UCHAR PathId,
4182  _In_ UCHAR Lun
4183  )
4184 {
4185  PIO_ERROR_LOG_PACKET logEntry;
4186  EVENT_DESCRIPTOR eventDescriptor;
4187  PCLASS_DRIVER_EXTENSION driverExtension;
4188 
4189  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "ClasspFailurePredictPollCompletion: Failure predicted for device %p\n", FdoExtension->DeviceObject));
4190 
4191  //
4192  // Fire off a WMI event
4193  //
4194  ClassWmiFireEvent(FdoExtension->DeviceObject,
4196  0,
4197  BufferSize,
4198  Buffer);
4199  //
4200  // Log an error into the eventlog
4201  //
4202 
4203  if (LogError)
4204  {
4205  logEntry = IoAllocateErrorLogEntry(
4206  FdoExtension->DeviceObject,
4207  sizeof(IO_ERROR_LOG_PACKET) + (3 * sizeof(ULONG)));
4208 
4209  if (logEntry != NULL)
4210  {
4211 
4212  logEntry->FinalStatus = STATUS_SUCCESS;
4213  logEntry->ErrorCode = IO_WRN_FAILURE_PREDICTED;
4214  logEntry->SequenceNumber = 0;
4217  logEntry->RetryCount = 0;
4218  logEntry->UniqueErrorValue = UniqueErrorValue;
4219  logEntry->DumpDataSize = 3;
4220 
4221  logEntry->DumpData[0] = PathId;
4222  logEntry->DumpData[1] = TargetId;
4223  logEntry->DumpData[2] = Lun;
4224 
4225  //
4226  // Write the error log packet.
4227  //
4228 
4229  IoWriteErrorLogEntry(logEntry);
4230  }
4231  }
4232 
4233  //
4234  // Send ETW event if LogError is TRUE. ClassInterpretSenseInfo sets this
4235  // to FALSE. So if failure is predicted for the first time and UniqueErrorValue
4236  // is 4 (used by ClassInterpretSenseInfo) then send ETW event.
4237  //
4238 
4239  if ((LogError == TRUE) ||
4240  ((FdoExtension->FailurePredicted == FALSE) && (UniqueErrorValue == 4))) {
4241 
4242 #ifdef _MSC_VER
4243 #pragma warning(suppress:4054) // okay to type cast function pointer as data pointer for this use case
4244 #endif
4245  driverExtension = IoGetDriverObjectExtension(FdoExtension->DeviceObject->DriverObject, CLASS_DRIVER_EXTENSION_KEY);
4246 
4247  if ((driverExtension != NULL) && (driverExtension->EtwHandle != 0)) {
4248  EventDescCreate(&eventDescriptor,
4249  1, // Id
4250  0, // Version
4251  0, // Channel
4252  0, // Level
4253  0, // Task
4254  0, // OpCode
4255  0); // Keyword
4256 
4257  EtwWrite(driverExtension->EtwHandle,
4258  &eventDescriptor,
4259  NULL,
4260  0,
4261  NULL);
4262  }
4263  }
4264 
4265 } // end ClassNotifyFailurePredicted()
4266 
4267 /*++////////////////////////////////////////////////////////////////////////////
4268 
4269 ClassSetFailurePredictionPoll()
4270 
4271 Routine Description:
4272 
4273  This routine enables polling for failure prediction, setting the timer
4274  to fire every N seconds as specified by the PollingPeriod.
4275 
4276 Arguments:
4277 
4278  FdoExtension - the device to setup failure prediction for.
4279 
4280  FailurePredictionMethod - specific failure prediction method to use
4281  if set to FailurePredictionNone, will disable failure detection
4282 
4283  PollingPeriod - if 0 then no change to current polling timer
4284 
4285 Return Value:
4286 
4287  NT Status
4288 
4289 --*/
4291 NTSTATUS
4292 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4293 ClassSetFailurePredictionPoll(
4297  )
4298 {
4300  NTSTATUS status;
4301 
4302  PAGED_CODE();
4303 
4304  if (FdoExtension->FailurePredictionInfo == NULL) {
4305 
4307 
4308  info = ExAllocatePoolWithTag(NonPagedPoolNx,
4309  sizeof(FAILURE_PREDICTION_INFO),
4311 
4312  if (info == NULL) {
4313 
4315 
4316  }
4317 
4319 
4320  info->WorkQueueItem = NULL;
4322 
4323  KeQuerySystemTime(&(info->LastFailurePredictionQueryTime));
4324 
4325  } else {
4326 
4327  //
4328  // FaultPrediction has not been previously initialized, nor
4329  // is it being initialized now. No need to do anything.
4330  //
4331  return STATUS_SUCCESS;
4332 
4333  }
4334 
4335  FdoExtension->FailurePredictionInfo = info;
4336 
4337  } else {
4338 
4339  info = FdoExtension->FailurePredictionInfo;
4340 
4341  }
4342 
4343  /*
4344  * Make sure the user-mode thread is not suspended while we hold the synchronization event.
4345  */
4347 
4348  (VOID)KeWaitForSingleObject(&info->Event,
4349  UserRequest,
4350  KernelMode,
4351  FALSE,
4352  NULL);
4353 
4354 
4355  //
4356  // Reset polling period and counter. Setup failure detection type
4357  //
4358 
4359  if (PollingPeriod != 0) {
4360 
4361  InterlockedExchange((volatile LONG *)&info->Period, PollingPeriod);
4362  }
4363 
4364  InterlockedExchange((volatile LONG *)&info->CountDown, info->Period);
4365 
4366  info->Method = FailurePredictionMethod;
4368 
4370 
4371  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "ClassEnableFailurePredictPoll: Enabled for "
4372  "device %p\n", FdoExtension->DeviceObject));
4373 
4374  } else {
4375 
4377  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_WMI, "ClassEnableFailurePredictPoll: Disabled for "
4378  "device %p\n", FdoExtension->DeviceObject));
4379  }
4381 
4382 
4383  KeSetEvent(&info->Event, IO_NO_INCREMENT, FALSE);
4384 
4386 
4387  return status;
4388 } // end ClassSetFailurePredictionPoll()
4389 
4390 BOOLEAN
4393  )
4394 /*
4395 Routine Description:
4396  This routine can be used to determine if a failure prediction polling
4397  period has been missed. That is, the time since the last failure
4398  prediction IOCTL has been sent is greater than the failure prediction
4399  polling period. This can happen if failure prediction polling was
4400  disabled, such as when the device is in D3 or when the screen is off.
4401 
4402 Parameters:
4403  FdoExtension - FDO extension. The caller should make sure the FDO
4404  extension is valid. The FailurePredictionInfo structure should also
4405  be valid and the failure prediction method should not be "none".
4406 
4407 Returns:
4408  TRUE if there was one or more failure prediction polling periods that was
4409  missed.
4410  FALSE otherwise.
4411 */
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 }
4435 
4436 
UCHAR PathId
Definition: scsi_port.h:149
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
_In_ ULONG _In_ BOOLEAN _In_ ULONG UniqueErrorValue
Definition: classpnp.h:1310
#define NOTIFICATION_NO_CLASS_EVENTS
Definition: scsi.h:42
#define FINALLY
Definition: classpnp.h:116
_Function_class_(RTL_QUERY_REGISTRY_ROUTINE)
Definition: autorun.c:3380
CONST char * PCSZ
Definition: umtypes.h:125
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
#define CLASS_DRIVER_EXTENSION_KEY
Definition: classpnp.h:94
#define SRB_STATUS_BUS_RESET
Definition: srb.h:345
#define _IRQL_requires_same_
Definition: no_sal2.h:652
UCHAR SenseKey
Definition: cdrw_hw.h:1167
PEX_TIMER TickTimer
Definition: classp.h:676
#define IN
Definition: typedefs.h:39
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
enum _MEDIA_CHANGE_DETECTION_STATE MEDIA_CHANGE_DETECTION_STATE
struct _NOTIFICATION_OPERATIONAL_STATUS * PNOTIFICATION_OPERATIONAL_STATUS
IO_COMPLETION_ROUTINE ClasspMediaChangeDetectionCompletion
Definition: autorun.c:116
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
BOOLEAN ClasspFailurePredictionPeriodMissed(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:4391
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID ClasspSendMediaStateIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN ULONG CountDown)
Definition: autorun.c:1559
#define LL
Definition: tui.h:84
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS ClasspInitializePolling(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN BOOLEAN AllowDriveToSleep)
Definition: autorun.c:1834
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
ULONG SrbFlags
Definition: srb.h:252
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR _In_ UCHAR _In_ UCHAR Lun
Definition: classpnp.h:1310
#define SCSIOP_GET_EVENT_STATUS
Definition: cdrw_hw.h:934
PVOID OriginalRequest
Definition: srb.h:258
UCHAR senseKey
Definition: scsi.h:4018
UCHAR Cdb[16]
Definition: srb.h:271
#define GESN_TIMEOUT_VALUE
Definition: autorun.c:31
USHORT Flags
Definition: iotypes.h:171
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define KeWaitForMutexObject
Definition: kefuncs.h:555
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: classpnp.h:905
_In_ ULONG _In_ BOOLEAN LogError
Definition: classpnp.h:1310
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define REMOVE_COMPLETE
Definition: classpnp.h:98
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#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_ const GUID _In_ ULONG ExtraDataSize
Definition: classpnp.h:1429
#define NOTIFICATION_MEDIA_STATUS_CLASS_MASK
Definition: scsi.h:37
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define MEDIA_CHANGE_TIMEOUT_TIME
Definition: classpnp.h:133
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR PathId
Definition: classpnp.h:1310
NTSTATUS FinalStatus
Definition: iotypes.h:1973
#define PLUGPLAY_REGKEY_DEVICE
Definition: iofuncs.h:2782
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
PVOID DataBuffer
Definition: srb.h:255
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
NTSTATUS InitializeStorageRequestBlock(_Inout_bytecount_(ByteSize) PSTORAGE_REQUEST_BLOCK Srb, _In_ USHORT AddressType, _In_ ULONG ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:206
_In_ ULONG _In_ BOOLEAN _In_ ULONG _In_ UCHAR _In_ UCHAR TargetId
Definition: classpnp.h:1310
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_MASK
Definition: scsi.h:36
unsigned char * PUCHAR
Definition: retypes.h:3
#define NOTIFICATION_EXTERNAL_EVENT_BUTTON_DOWN
Definition: scsi.h:76
ULONG DataTransferLength
Definition: srb.h:253
#define NOTIFICATION_MEDIA_EVENT_NEW_MEDIA
Definition: scsi.h:95
#define _In_reads_bytes_opt_(size)
Definition: no_sal2.h:230
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4154
#define CLASS_SPECIAL_CAUSE_NOT_REPORTABLE_HACK
Definition: scsi_port.h:175
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define LEAVE
Definition: classpnp.h:115
GLintptr offset
Definition: glext.h:5920
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
#define TRY(sps, bps)
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define InterlockedCompareExchange
Definition: interlocked.h:104
UCHAR CdbLength
Definition: srb.h:250
GLuint buffer
Definition: glext.h:5915
#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
Definition: dhcpd.h:245
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define CLASS_TAG_FAILURE_PREDICT
Definition: classpnp.h:84
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
#define NOTIFICATION_MEDIA_EVENT_MEDIA_CHANGE
Definition: scsi.h:97
UCHAR QueueAction
Definition: srb.h:249
#define FDO_HACK_GESN_IGNORE_OPCHANGE
Definition: classp.h:139
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define MAXIMUM_IMMEDIATE_MCN_RETRIES
Definition: autorun.c:35
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
UNICODE_STRING RegistryPath
Definition: kbdclass.h:25
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
LONG NTAPI KeReleaseMutex(IN PKMUTEX Mutex, IN BOOLEAN Wait)
Definition: mutex.c:189
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
#define NOTIFICATION_DEVICE_BUSY_CLASS_MASK
Definition: scsi.h:39
ULONG TimeOutValue
Definition: srb.h:254
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
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 OBJ_KERNEL_HANDLE
Definition: winternl.h:231
UCHAR TargetId
Definition: scsi_port.h:150
UCHAR SrbStatus
Definition: srb.h:243
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define SRB_STATUS(Status)
Definition: srb.h:381
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:620
GLbitfield GLuint64 timeout
Definition: glext.h:7164
struct TraceInfo Info
#define _In_opt_
Definition: no_sal2.h:213
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
struct _test_info info[]
Definition: SetCursorPos.c:19
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
PCLASS_TICK ClassTick
Definition: classpnp.h:545
#define SP_UNTAGGED
Definition: srb.h:225
#define IRP_MJ_SCSI
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
struct SRB_ALIGN _STORAGE_REQUEST_BLOCK_HEADER * PSTORAGE_REQUEST_BLOCK_HEADER
#define SRB_STATUS_ERROR
Definition: srb.h:336
#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 STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_DEVICE_PROTOCOL_ERROR
Definition: ntstatus.h:623
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
NTSTATUS ErrorCode
Definition: iotypes.h:1971
#define _IRQL_requires_min_(irql)
Definition: no_sal2.h:651
#define STATUS_MEDIA_CHANGED
Definition: ntstatus.h:207
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
__inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
#define NOTIFICATION_MEDIA_STATUS_CLASS_EVENTS
Definition: scsi.h:46
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
* PSTORAGE_DEVICE_DESCRIPTOR
Definition: ntddstor.h:565
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define SRB_CLASS_FLAGS_LOW_PRIORITY
Definition: classpnp.h:19
#define TICK_TIMER_PERIOD_IN_MSEC
Definition: autorun.c:129
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
#define FALSE
Definition: types.h:117
__inline ULONG CountOfSetBitsUChar(UCHAR _X)
Definition: tools.h:150
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
Definition: Header.h:8
long LONG
Definition: pedump.c:60
ULONG dataLength
Definition: scsi.h:3750
VOID NTAPI ClassCheckMediaState(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1752
#define CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE
Definition: classpnp.h:695
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_MASK
Definition: scsi.h:34
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
UCHAR ScsiStatus
Definition: srb.h:244
#define CLEAR_FLAG(Flags, Bit)
Definition: classpnp.h:158
struct _SENSE_DATA SENSE_DATA
#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
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4142
static GUID * Guid
Definition: apphelp.c:93
smooth NULL
Definition: ftsmooth.c:416
struct _NOTIFICATION_MEDIA_STATUS * PNOTIFICATION_MEDIA_STATUS
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
#define MCN_REG_AUTORUN_ENABLE_INSTANCE_NAME
Definition: autorun.c:38
union _CDB * PCDB
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1787
Definition: bufpool.h:45
#define RTL_QUERY_REGISTRY_TYPECHECK
VOID ClasspInternalSetMediaChangeState(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN KnownStateChange)
Definition: autorun.c:798
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
void * PVOID
Definition: retypes.h:9
UCHAR QueueTag
Definition: srb.h:248
#define MCN_REG_AUTORUN_DISABLE_INSTANCE_NAME
Definition: autorun.c:37
VOID ClasspEnableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3857
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define NOTIFICATION_MEDIA_EVENT_EJECT_REQUEST
Definition: scsi.h:94
#define NOTIFICATION_MEDIA_EVENT_MEDIA_REMOVAL
Definition: scsi.h:96
UCHAR additionalSenseCode
Definition: scsi.h:4019
VOID NTAPI ClassResetMediaChangeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:1804
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
#define PCHAR
Definition: match.c:90
IO_WORKITEM_ROUTINE ClasspUpdateDiskProperties
Definition: classp.h:1714
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:520
BOOLEAN TimerInitialized
Definition: classp.h:752
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
USHORT MaximumLength
Definition: env_spec_w32.h:377
int64_t LONGLONG
Definition: typedefs.h:68
NTSTATUS ClasspInitializeTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3737
NTSTATUS ClasspMcnControl(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PIRP Irp, IN PSCSI_REQUEST_BLOCK Srb)
Definition: autorun.c:3276
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:511
_In_z_ PWSTR RegistryPath
Definition: classp.h:1930
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define _IRQL_requires_(irql)
Definition: no_sal2.h:649
#define TICK_TIMER_DELAY_IN_MSEC
Definition: autorun.c:130
#define NOTIFICATION_OPERATIONAL_EVENT_CHANGE_REQUESTED
Definition: scsi.h:51
enum _CLASS_DETECTION_STATE CLASS_DETECTION_STATE
if(!(yy_init))
Definition: macro.lex.yy.c:714
KDEFERRED_ROUTINE ClasspTimerTick
Definition: autorun.c:118
_In_ PUCHAR EventPrefix
Definition: classpnp.h:1267
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
VOID ClasspDisableTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3956
char CCHAR
Definition: typedefs.h:51
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
ULONG BreakOnMcnDisable
Definition: autorun.c:3183
_IRQL_requires_max_(DISPATCH_LEVEL)
Definition: autorun.c:188
UCHAR Function
Definition: srb.h:242
#define IRP_MN_START_DEVICE
VOID ClasspDeleteTimer(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3798
struct _COMMON_DEVICE_EXTENSION * PCOMMON_DEVICE_EXTENSION
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:595
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
#define BufferSize
Definition: classpnp.h:436
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_CHANGE
Definition: scsi.h:59
#define SRB_FLAGS_NO_KEEP_AWAKE
Definition: srb.h:404
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2874
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
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:679
USHORT Length
Definition: srb.h:241
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
#define _Inout_
Definition: no_sal2.h:244
PVPB NTAPI ClassGetVpb(_In_ PDEVICE_OBJECT DeviceObject)
Definition: class.c:11473
#define STORAGE_ADDRESS_TYPE_BTL8
Definition: srb.h:657
* PFILE_OBJECT
Definition: iotypes.h:1962
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
POWER_SETTING_CALLBACK ClasspPowerSettingCallback
Definition: classp.h:1619
struct _NOTIFICATION_EXTERNAL_STATUS * PNOTIFICATION_EXTERNAL_STATUS
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
PDEVICE_OBJECT DeviceObject
Definition: classpnp.h:871
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define CLASS_TAG_AUTORUN_DISABLE
Definition: classpnp.h:77
#define CLASSP_REG_SUBKEY_NAME
Definition: classp.h:112
#define NO_REMOVE
Definition: classpnp.h:96
#define SRB_FUNCTION_STORAGE_REQUEST_BLOCK
Definition: srb.h:99
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
static double zero
Definition: j0_y0.c:96
char * PBOOLEAN
Definition: retypes.h:11
LONGLONG CurrentNoWakeTolerance
Definition: classp.h:677
VOID NTAPI KeInitializeMutex(IN PKMUTEX Mutex, IN ULONG Level)
Definition: mutex.c:67
#define NOTIFICATION_OPERATIONAL_OPCODE_FEATURE_ADDED
Definition: scsi.h:60
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
static const WCHAR L[]
Definition: oid.c:1250
#define InterlockedDecrement
Definition: armddk.h:52
Definition: ketypes.h:687
#define NOTIFICATION_DEVICE_BUSY_CLASS_EVENTS
Definition: scsi.h:48
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
#define VOID
Definition: acefi.h:82
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1869
EXT_CALLBACK ClasspTimerTickEx
Definition: autorun.c:121
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
VOID ClasspSetMediaChangeStateEx(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN MEDIA_CHANGE_DETECTION_STATE NewState, IN BOOLEAN Wait, IN BOOLEAN KnownStateChange)
Definition: autorun.c:950
BOOLEAN TickTimerEnabled
Definition: classp.h:813
BOOLEAN ClasspScreenOff
Definition: autorun.c:124
#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 PASSIVE_LEVEL
Definition: env_spec_w32.h:693
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define GESN_DEVICE_BUSY_LOWER_THRESHOLD_100_MS
Definition: autorun.c:33
#define REMOVE_PENDING
Definition: classpnp.h:97
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define InterlockedExchange
Definition: armddk.h:54
#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
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define IOCTL_SCSI_EXECUTE_NONE
Definition: cdrw_hw.h:1453
BOOLEAN ClasspIsMediaChangeDisabledForClass(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PUNICODE_STRING RegistryPath)
Definition: autorun.c:2956
_In_ FAILURE_PREDICTION_METHOD _In_ ULONG PollingPeriod
Definition: classpnp.h:1301
#define FDO_HACK_GESN_IS_BAD
Definition: classp.h:136
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
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 _In_
Definition: no_sal2.h:204
#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
UCHAR SenseInfoBufferLength
Definition: srb.h:251
#define IOCTL_STORAGE_PREDICT_FAILURE
Definition: ntddstor.h:135
#define WMI_STORAGE_PREDICT_FAILURE_EVENT_GUID
Definition: wmidata.h:336
BOOLEAN ClasspUpdateTimerNoWakeTolerance(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:3653
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME
Definition: classp.h:115
#define NOTIFICATION_EXTERNAL_REQUEST_CLASS_EVENTS
Definition: scsi.h:45
PFILE_OBJECT FileObject
Definition: iotypes.h:2820
PIRP ClasspPrepareMcnIrp(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PMEDIA_CHANGE_DETECTION_INFO Info, IN BOOLEAN UseGesn)
Definition: autorun.c:1310
#define CLASS_TAG_MEDIA_CHANGE_DETECTION
Definition: classpnp.h:79
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
IO_WORKITEM_ROUTINE ClasspFailurePredict
Definition: autorun.c:105
struct _FAILURE_PREDICTION_INFO * FailurePredictionInfo
Definition: classpnp.h:919
const GUID StoragePredictFailureEventGuid
Definition: autorun.c:40
unsigned short USHORT
Definition: pedump.c:61
#define _In_z_
Definition: no_sal2.h:239
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define MEDIA_CHANGE_DEFAULT_TIME
Definition: cdrom.c:176
#define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
struct _CDB::_CDB6GENERIC CDB6GENERIC
struct _NOTIFICATION_EVENT_STATUS_HEADER * PNOTIFICATION_EVENT_STATUS_HEADER
FORCEINLINE VOID EventDescCreate(_Out_ PEVENT_DESCRIPTOR EventDescriptor, _In_ USHORT Id, _In_ UCHAR Version, _In_ UCHAR Channel, _In_ UCHAR Level, _In_ USHORT Task, _In_ UCHAR Opcode, _In_ ULONGLONG Keyword)
Definition: evntprov.h:192
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define DBGGETSRBSTATUSSTR(_pSrb)
Definition: debug.h:27
BOOLEAN ClasspIsMediaChangeDisabledDueToHardwareLimitation(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, IN PUNICODE_STRING RegistryPath)
Definition: autorun.c:2727
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
FAILURE_PREDICTION_METHOD
Definition: classpnp.h:233
#define DEFAULT_FAILURE_PREDICTION_PERIOD
Definition: classpnp.h:190
_In_ BOOLEAN AllowDriveToSleep
Definition: classpnp.h:1275
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
NTSTATUS NTAPI IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, IN ULONG DevInstKeyType, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DevInstRegKey)
Definition: pnpmgr.c:2327
PVOID ScreenStateNotificationHandle
Definition: class.c:124
Definition: tftpd.h:85
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
PVOID SenseInfoBuffer
Definition: srb.h:256
#define OUT
Definition: typedefs.h:40
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define NOTIFICATION_OPERATIONAL_CHANGE_CLASS_EVENTS
Definition: scsi.h:43
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
struct tagContext Context
Definition: acpixf.h:1034
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:570
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
UCHAR AdditionalSenseLength
Definition: cdrw_hw.h:1173
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS ClasspMediaChangeDeviceInstanceOverride(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, OUT PBOOLEAN Enabled)
Definition: autorun.c:2563
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
__inline BOOLEAN ClasspCanSendPollingIrp(_In_ PFUNCTIONAL_DEVICE_EXTENSION fdoExtension)
Definition: autorun.c:61
struct _NOTIFICATION_BUSY_STATUS * PNOTIFICATION_BUSY_STATUS
#define REG_NONE
Definition: nt_native.h:1492
LARGE_INTEGER SystemTime
Definition: ioevent.h:92
IN PSCSI_REQUEST_BLOCK Srb
Definition: class2.h:49
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2779
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
_In_ FAILURE_PREDICTION_METHOD FailurePredictionMethod
Definition: classpnp.h:1301
struct _CDB::_GET_EVENT_STATUS_NOTIFICATION GET_EVENT_STATUS_NOTIFICATION
IO_WORKITEM_ROUTINE ClasspDisableGesn
Definition: autorun.c:114
#define IO_WRN_FAILURE_PREDICTED
Definition: ntiologc.h:78
return STATUS_SUCCESS
Definition: btrfs.c:3014
VOID ClassSendEjectionNotification(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: autorun.c:155
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
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
struct _FAILURE_PREDICTION_INFO * PFAILURE_PREDICTION_INFO
#define REG_DWORD
Definition: sdbapi.c:596
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
signed int * PLONG
Definition: retypes.h:5
#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
struct _IO_WORKITEM * PIO_WORKITEM
Definition: iotypes.h:478
#define MCN_REG_SUBKEY_NAME
Definition: autorun.c:36
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2676
RTL_QUERY_REGISTRY_ROUTINE ClasspMediaChangeRegistryCallBack
Definition: autorun.c:96
struct CFHEADER header
Definition: fdi.c:101
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
UCHAR ErrorCode
Definition: cdrw_hw.h:1164
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
LONGLONG QuadPart
Definition: typedefs.h:114
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
BOOLEAN validSense
Definition: scsi.h:4017
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
#define PAGED_CODE()
IN BOOLEAN Wait
Definition: fatprocs.h:1538
#define NT_ASSERT
Definition: rtlfuncs.h:3312
#define REG_SZ
Definition: layer.c:22
Definition: ps.c:97
#define SCSI_SENSE_ERRORCODE_FIXED_CURRENT
Definition: scsi.h:622
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675