ReactOS  0.4.15-dev-3331-g8ebe441
cdrom.c
Go to the documentation of this file.
1 /*--
2 
3 Copyright (C) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7  cdrom.c
8 
9 Abstract:
10 
11  The CDROM class driver tranlates IRPs to SRBs with embedded CDBs
12  and sends them to its devices through the port driver.
13 
14 Environment:
15 
16  kernel mode only
17 
18 Notes:
19 
20 
21 Revision History:
22 
23 --*/
24 
25 // this definition is used to link _StorDebugPrint() function.
26 #define DEBUG_MAIN_SOURCE 1
27 
28 
29 #include "ntddk.h"
30 #include "ntstrsafe.h"
31 
32 #include "ntddstor.h"
33 #include "ntddtape.h"
34 #include "wdfcore.h"
35 #include "devpkey.h"
36 
37 #include "cdrom.h"
38 #include "ioctl.h"
39 #include "mmc.h"
40 #include "scratch.h"
41 
42 
43 #ifdef DEBUG_USE_WPP
44 #include "cdrom.tmh"
45 #endif
46 
47 BOOLEAN
49  VOID
50  );
51 
52 #ifdef ALLOC_PRAGMA
53 
54 #pragma alloc_text(INIT, DriverEntry)
55 #pragma alloc_text(INIT, BootEnvironmentIsWinPE)
56 
57 #pragma alloc_text(PAGE, DriverEvtCleanup)
58 #pragma alloc_text(PAGE, DriverEvtDeviceAdd)
59 #pragma alloc_text(PAGE, DeviceEvtCleanup)
60 #pragma alloc_text(PAGE, DeviceEvtSelfManagedIoCleanup)
61 #pragma alloc_text(PAGE, DeviceEvtD0Exit)
62 #pragma alloc_text(PAGE, CreateQueueEvtIoDefault)
63 #pragma alloc_text(PAGE, DeviceEvtFileClose)
64 #pragma alloc_text(PAGE, DeviceCleanupProtectedLocks)
65 #pragma alloc_text(PAGE, DeviceCleanupDisableMcn)
66 #pragma alloc_text(PAGE, RequestProcessSerializedIoctl)
67 #pragma alloc_text(PAGE, ReadWriteWorkItemRoutine)
68 #pragma alloc_text(PAGE, IoctlWorkItemRoutine)
69 #pragma alloc_text(PAGE, DeviceEvtSurpriseRemoval)
70 
71 #endif
72 
74 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
78  )
79 /*++
80 
81 Routine Description:
82 
83  Installable driver initialization entry point.
84  This entry point is called directly by the I/O system.
85 
86 Arguments:
87 
88  DriverObject - pointer to the driver object
89 
90  RegistryPath - pointer to a unicode string representing the path,
91  to driver-specific key in the registry.
92 
93 Return Value:
94 
95  STATUS_SUCCESS if successful,
96  STATUS_UNSUCCESSFUL otherwise.
97 
98 --*/
99 {
102  WDF_OBJECT_ATTRIBUTES attributes;
103  WDFDRIVER driverObject = NULL;
104 
105  PAGED_CODE();
106 
107  // Initialize WPP Tracing
109 
110  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
111  "CDROM.SYS DriverObject %p loading\n",
112  DriverObject));
113 
114  // Register DeviceAdd and DriverEvtCleanup callback.
115  // WPP_CLEANUP will be called in DriverEvtCleanup
118 
120 
121  status = WdfDriverCreate(DriverObject,
122  RegistryPath,
123  &attributes,
124  &config,
125  &driverObject);
126 
127  if (!NT_SUCCESS(status))
128  {
129  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
130  "WdfDriverCreate failed. %x\n",
131  status));
132 
133  // Cleanup tracing here because DriverUnload will not be called
134  // as we have failed to create WDFDRIVER object itself.
136 
137  }
138  else
139  {
140  PCDROM_DRIVER_EXTENSION driverExtension = DriverGetExtension(driverObject);
141 
142  // Copy the registry path into the driver extension so we can use it later
143  driverExtension->Version = 0x01;
144  driverExtension->DriverObject = DriverObject;
145 
146  if (BootEnvironmentIsWinPE()) {
147 
148  SET_FLAG(driverExtension->Flags, CDROM_FLAG_WINPE_MODE);
149  }
150 
151  }
152 
153  return status;
154 }
155 
156 
157 BOOLEAN
159  VOID
160  )
161 /*++
162 
163 Routine Description:
164 
165  This routine determines if the boot enviroment is WinPE
166 
167 Arguments:
168 
169  None
170 
171 Return Value:
172 
173  BOOLEAN - TRUE if the environment is WinPE; FALSE otherwise
174 
175 --*/
176 {
178  WDFKEY registryKey = NULL;
179 
181 
182  PAGED_CODE();
183 
184  status = WdfRegistryOpenKey(NULL,
185  &registryKeyName,
186  KEY_READ,
188  &registryKey);
189 
190  if (!NT_SUCCESS(status))
191  {
192  return FALSE;
193  }
194 
195  WdfRegistryClose(registryKey);
196  return TRUE;
197 } // end BootEnvironmentIsWinPE()
198 
199 
200 VOID
201 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
204  )
205 /*++
206 Routine Description:
207 
208  Free all the resources allocated in DriverEntry.
209 
210 Arguments:
211 
212  Driver - handle to a WDF Driver object.
213 
214 Return Value:
215 
216  VOID.
217 
218 --*/
219 {
220  WDFDRIVER driver = (WDFDRIVER)Driver;
221 
222  PAGED_CODE ();
223 
224  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
225  "CDROM.SYS DriverObject %p cleanup. Will be unloaded soon\n",
226  driver));
227 
228  // Stop WPP Tracing
229  WPP_CLEANUP( WdfDriverWdmGetDriverObject(driver) );
230 
231 
232  return;
233 }
234 
235 
236 NTSTATUS
237 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
239  _In_ WDFDRIVER Driver,
241  )
242 /*++
243 
244 Routine Description:
245 
246  EvtDeviceAdd is called by the framework in response to AddDevice
247  call from the PnP manager.
248 
249 
250 Arguments:
251 
252  Driver - Handle to a framework driver object created in DriverEntry
253 
254  DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
255 
256 Return Value:
257 
258  NTSTATUS
259 
260 --*/
261 {
263  PCDROM_DRIVER_EXTENSION driverExtension = NULL;
264  WDFDEVICE device = NULL;
265  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
266  BOOLEAN deviceClaimed = FALSE;
267 
268  WDF_OBJECT_ATTRIBUTES attributes;
269  WDF_FILEOBJECT_CONFIG fileObjectConfig;
270  WDF_IO_TARGET_OPEN_PARAMS ioTargetOpenParams;
271  WDF_IO_QUEUE_CONFIG queueConfig;
272  WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
273  WDF_REMOVE_LOCK_OPTIONS removeLockOptions;
274  PWCHAR wideDeviceName = NULL;
275  UNICODE_STRING unicodeDeviceName;
276  PDEVICE_OBJECT lowerPdo = NULL;
277  ULONG deviceNumber = 0;
278  ULONG devicePropertySessionId = INVALID_SESSION;
279  ULONG devicePropertySize = 0;
280  DEVPROPTYPE devicePropertyType = DEVPROP_TYPE_EMPTY;
281 
282  PAGED_CODE();
283 
284  driverExtension = DriverGetExtension(Driver);
285 
286  // 0. Initialize the objects that we're going to use
287  RtlInitUnicodeString(&unicodeDeviceName, NULL);
288 
289  // 1. Register PnP&Power callbacks for any we are interested in.
290  // If a callback isn't set, Framework will take the default action by itself.
291  {
292  // Zero out the PnpPowerCallbacks structure.
293  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
294 
295  // Use this callback to init resources that are used by the device and only needs to be called once.
297 
298  // Use this callback to prepare device for coming back from a lower power mode to D0.
299  pnpPowerCallbacks.EvtDeviceD0Entry = DeviceEvtD0Entry;
300 
301  // Use this callback to prepare device for entering into a lower power mode.
302  pnpPowerCallbacks.EvtDeviceD0Exit = DeviceEvtD0Exit;
303 
304  // Use this callback to free any resources used by device and will be called when the device is
305  // powered down.
307 
309 
310  // Register the PnP and power callbacks.
311  WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
312  }
313 
314  // 2. Register the EvtIoInCallerContext to deal with IOCTLs that need to stay in original context.
315  WdfDeviceInitSetIoInCallerContextCallback(DeviceInit,
317 
318  // 3. Register PreprocessCallback for IRP_MJ_POWER, IRP_MJ_FLUSH_BUFFERS and IRP_MJ_SHUTDOWN
319  {
320  UCHAR minorFunctions[1];
321 
322  minorFunctions[0] = IRP_MN_SET_POWER;
323 
324  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
326  IRP_MJ_POWER,
327  minorFunctions,
328  RTL_NUMBER_OF(minorFunctions));
329  if (!NT_SUCCESS(status))
330  {
331  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
332  "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_POWER failed, "
333  "status: 0x%X\n", status));
334 
335  goto Exit;
336  }
337 
338  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
341  NULL,
342  0);
343  if (!NT_SUCCESS(status))
344  {
345  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
346  "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_FLUSH_BUFFERS failed, "
347  "status: 0x%X\n", status));
348 
349  goto Exit;
350  }
351 
352  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit,
355  NULL,
356  0);
357  if (!NT_SUCCESS(status))
358  {
359  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
360  "DriverEvtDeviceAdd: Assign IrpPreprocessCallback for IRP_MJ_SHUTDOWN failed, "
361  "status: 0x%X\n", status));
362 
363  goto Exit;
364  }
365  }
366 
367  // 4. Set attributes to create Request Context area.
368  {
369  //Reuse this structure.
373 
374  WdfDeviceInitSetRequestAttributes(DeviceInit,
375  &attributes);
376  }
377 
378  // 5. Register FileObject related callbacks
379  {
380  // Add FILE_OBJECT_EXTENSION as the context to the file object.
382 
383  // Set Entry points for Create and Close..
384 
385  // The framework doesn't sync the file create requests with pnp/power
386  // state. Re-direct all the file create requests to a dedicated
387  // queue, which will be purged manually during removal.
388  WDF_FILEOBJECT_CONFIG_INIT(&fileObjectConfig,
389  NULL, //CreateQueueEvtIoDefault,
391  WDF_NO_EVENT_CALLBACK); // No callback for Cleanup
392 
394 
395  // Since we are registering file events and fowarding create request
396  // ourself, we must also set AutoForwardCleanupClose so that cleanup
397  // and close can also get forwarded.
398  fileObjectConfig.AutoForwardCleanupClose = WdfTrue;
401 
402  // Indicate that file object is optional.
403  fileObjectConfig.FileObjectClass |= WdfFileObjectCanBeOptional;
404 
405  WdfDeviceInitSetFileObjectConfig(DeviceInit,
406  &fileObjectConfig,
407  &attributes);
408  }
409 
410  // 6. Initialize device-wide attributes
411  {
412  // Declare ourselves as NOT owning power policy.
413  // The power policy owner in storage stack is port driver.
414  WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE);
415 
416  // Set other DeviceInit attributes.
417  WdfDeviceInitSetExclusive(DeviceInit, FALSE);
418  WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CD_ROM);
419  WdfDeviceInitSetCharacteristics(DeviceInit, FILE_REMOVABLE_MEDIA, FALSE);
420  WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
421  WdfDeviceInitSetPowerPageable(DeviceInit);
422 
423  // We require the framework to acquire a remove lock before delivering all IRP types
424  WDF_REMOVE_LOCK_OPTIONS_INIT(&removeLockOptions,
426 
427  WdfDeviceInitSetRemoveLockOptions(DeviceInit, &removeLockOptions);
428 
429  // save the PDO for later reference
430  lowerPdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
431 
434 
435  // We have a parallel queue, so WdfSynchronizationScopeNone is our only choice.
438 
439  // Provide a cleanup callback which will release memory allocated with ExAllocatePool*
441  }
442 
443  // 7. Now, the device can be created.
444  {
445  wideDeviceName = ExAllocatePoolWithTag(NonPagedPoolNx,
446  64 * sizeof(WCHAR),
448 
449  if (wideDeviceName == NULL)
450  {
452  goto Exit;
453  }
454 
455  // Find the lowest device number currently available.
456  do {
457  status = RtlStringCchPrintfW((NTSTRSAFE_PWSTR)wideDeviceName,
458  64,
459  L"\\Device\\CdRom%d",
460  deviceNumber);
461 
462  if (!NT_SUCCESS(status)) {
463  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
464  "DriverEvtDeviceAdd: Format device name failed with error: 0x%X\n", status));
465 
466  goto Exit;
467  }
468 
469  RtlInitUnicodeString(&unicodeDeviceName, wideDeviceName);
470 
471  status = WdfDeviceInitAssignName(DeviceInit, &unicodeDeviceName);
472  if (!NT_SUCCESS(status))
473  {
474  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
475  "DriverEvtDeviceAdd: WdfDeviceInitAssignName() failed with error: 0x%X\n", status));
476 
477  goto Exit;
478  }
479 
480  status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
481 
482  deviceNumber++;
483 
485 
486  // When this loop exits the count is inflated by one - fix that.
487  deviceNumber--;
488 
489  if (!NT_SUCCESS(status))
490  {
491  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
492  "DriverEvtDeviceAdd: Can not create a new device, status: 0x%X\n",
493  status));
494 
495  goto Exit;
496  }
497  }
498 
499  // 8. Fill up basic Device Extension settings and create a remote I/O target for the next-lower driver.
500  // The reason why we do not use the local I/O target is because we want to be able to close the
501  // I/O target on surprise removal.
502  {
503  deviceExtension = DeviceGetExtension(device);
504 
505  deviceExtension->Version = 0x01;
506  deviceExtension->Size = sizeof(CDROM_DEVICE_EXTENSION);
507 
508  deviceExtension->DeviceObject = WdfDeviceWdmGetDeviceObject(device);
509  deviceExtension->Device = device;
510  deviceExtension->DriverExtension = driverExtension;
511 
512  deviceExtension->LowerPdo = lowerPdo;
513 
514  deviceExtension->DeviceType = FILE_DEVICE_CD_ROM; //Always a FILE_DEVICE_CD_ROM for all device it manages.
515  deviceExtension->DeviceName = unicodeDeviceName;
516 
517  deviceExtension->DeviceNumber = deviceNumber;
518  }
519  {
520  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
521  attributes.ParentObject = deviceExtension->Device;
522 
523  status = WdfIoTargetCreate(deviceExtension->Device,
524  &attributes,
525  &deviceExtension->IoTarget);
526 
527  if (!NT_SUCCESS(status))
528  {
529  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
530  "DriverEvtDeviceAdd: Can not create a remote I/O target object, status: 0x%X\n",
531  status));
532  goto Exit;
533  }
534 
536  WdfDeviceWdmGetAttachedDevice(deviceExtension->Device));
537 
538  status = WdfIoTargetOpen(deviceExtension->IoTarget,
539  &ioTargetOpenParams);
540  if (!NT_SUCCESS(status))
541  {
542  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
543  "DriverEvtDeviceAdd: Can not open a remote I/O target for the next-lower device, status: 0x%X\n",
544  status));
545 
546  WdfObjectDelete(deviceExtension->IoTarget);
547  deviceExtension->IoTarget = NULL;
548 
549  goto Exit;
550  }
551  }
552 
553  // 9. Claim the device, so that port driver will only accept the commands from CDROM.SYS for this device.
554  // NOTE: The I/O should be issued after the device is started. But we would like to claim
555  // the device as soon as possible, so this legacy behavior is kept.
556  status = DeviceClaimRelease(deviceExtension, FALSE);
557 
558  if (!NT_SUCCESS(status))
559  {
560  // Someone already had this device - we're in trouble
561  goto Exit;
562  }
563  else
564  {
565  deviceClaimed = TRUE;
566  }
567 
568  //
569  // CDROM Queueing Structure
570  //
571  // a. EvtIoInCallerContext (prior to queueing):
572  // This event will be used ONLY to forward down IOCTLs that come in at PASSIVE LEVEL
573  // and need to be forwarded down the stack in the original context.
574  //
575  // b. Main input queue: serial queue for main dispatching
576  // This queue will be used to do all dispatching of requests to serialize
577  // access to the device. Any request that was previously completed in
578  // the Dispatch routines will be completed here. Anything requiring device
579  // I/O will be sent through the serial I/O queue.
580  //
581  // 10. Set up IO queues after device being created.
582  //
583  {
586 
587  queueConfig.PowerManaged = WdfFalse;
588 
589 #pragma prefast(push)
590 #pragma prefast(disable: 28155, "a joint handler for read/write cannot be EVT_WDF_IO_QUEUE_IO_READ and EVT_WDF_IO_QUEUE_IO_WRITE simultaneously")
591 #pragma prefast(disable: 28023, "a joint handler for read/write cannot be EVT_WDF_IO_QUEUE_IO_READ and EVT_WDF_IO_QUEUE_IO_WRITE simultaneously")
594 #pragma prefast(pop)
595 
598 
599  status = WdfIoQueueCreate(device,
600  &queueConfig,
602  &(deviceExtension->SerialIOQueue));
603  if (!NT_SUCCESS(status))
604  {
605  goto Exit;
606  }
607 
608  // this queue is dedicated for file create requests.
610 
611  queueConfig.PowerManaged = WdfFalse;
613 
614  //Reuse this structure.
617 
620 
621  status = WdfIoQueueCreate(device,
622  &queueConfig,
623  &attributes,
624  &(deviceExtension->CreateQueue));
625 
626  if (!NT_SUCCESS(status))
627  {
628  goto Exit;
629  }
630 
631  // Configure the device to use driver created queue for dispatching create.
632  status = WdfDeviceConfigureRequestDispatching(device,
633  deviceExtension->CreateQueue,
635 
636  if (!NT_SUCCESS(status))
637  {
638  goto Exit;
639  }
640  }
641 
642  // 11. Set the alignment requirements for the device based on the host adapter requirements.
643  //
644  // NOTE: this should have been set when device is attached on device stack,
645  // by keeping this legacy code, we could avoid issue that this value was not correctly set at that time.
646  if (deviceExtension->LowerPdo->AlignmentRequirement > deviceExtension->DeviceObject->AlignmentRequirement)
647  {
648  WdfDeviceSetAlignmentRequirement(deviceExtension->Device,
649  deviceExtension->LowerPdo->AlignmentRequirement);
650  }
651 
652  // 12. Initialization of miscellaneous internal properties
653 
654  // CDROMs are not partitionable so starting offset is 0.
655  deviceExtension->StartingOffset.LowPart = 0;
656  deviceExtension->StartingOffset.HighPart = 0;
657 
658  // Set the default geometry for the cdrom to match what NT 4 used.
659  // these values will be used to compute the cylinder count rather
660  // than using it's NT 5.0 defaults.
661  deviceExtension->DiskGeometry.MediaType = RemovableMedia;
662  deviceExtension->DiskGeometry.TracksPerCylinder = 0x40;
663  deviceExtension->DiskGeometry.SectorsPerTrack = 0x20;
664 
666 
667  // Clear the SrbFlags and disable synchronous transfers
668  deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
669 
670  // Set timeout value in seconds.
671  deviceExtension->TimeOutValue = DeviceGetTimeOutValueFromRegistry();
672  if ((deviceExtension->TimeOutValue > 30 * 60) || // longer than 30 minutes
673  (deviceExtension->TimeOutValue == 0))
674  {
675  deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
676  }
677 
678  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
679  "DriverEvtDeviceAdd: device timeout is set to %x seconds",
680  deviceExtension->TimeOutValue
681  ));
682 
683 #if (NTDDI_VERSION >= NTDDI_WIN8)
684  deviceExtension->IsVolumeOnlinePending = TRUE;
685 
687 
688  queueConfig.PowerManaged = WdfFalse;
689 
690  status = WdfIoQueueCreate(device,
691  &queueConfig,
693  &deviceExtension->ManualVolumeReadyQueue);
694 
695  if (!NT_SUCCESS(status))
696  {
697  goto Exit;
698  }
699 #endif
700 
701  // 13. Initialize the stuff related to media locking
702  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
703  attributes.ParentObject = deviceExtension->Device;
704  status = WdfWaitLockCreate(&attributes,
705  &deviceExtension->EjectSynchronizationLock);
706 
707  deviceExtension->LockCount = 0;
708 
709  // 14. Initialize context structures needed for asynchronous release queue and power requests
710 
711  if (NT_SUCCESS(status))
712  {
713  status = DeviceInitReleaseQueueContext(deviceExtension);
714  }
715 
716  if (NT_SUCCESS(status))
717  {
718  status = DeviceInitPowerContext(deviceExtension);
719  }
720 
721  // 15. Create external access points other than device name.
722  if (NT_SUCCESS(status))
723  {
724  status = DeviceCreateWellKnownName(deviceExtension);
725  }
726 
727  // 16. Query session id from the PDO.
728  if (NT_SUCCESS(status))
729  {
730  status = IoGetDevicePropertyData(deviceExtension->LowerPdo,
731  &DEVPKEY_Device_SessionId,
732  0,
733  0,
734  sizeof(devicePropertySessionId),
735  &devicePropertySessionId,
736  &devicePropertySize,
737  &devicePropertyType);
738 
739  if (!NT_SUCCESS(status))
740  {
741  // The device is global.
742  devicePropertySessionId = INVALID_SESSION;
744  }
745  }
746 
747  // 17. Register interfaces for this device.
748  if (NT_SUCCESS(status))
749  {
750  status = DeviceRegisterInterface(deviceExtension, CdRomDeviceInterface);
751  }
752 
753  if (NT_SUCCESS(status))
754  {
755  // If this is a per-session DO, don't register for mount interface so that
756  // mountmgr will not automatically assign a drive letter.
757  if (devicePropertySessionId == INVALID_SESSION)
758  {
759  status = DeviceRegisterInterface(deviceExtension, MountedDeviceInterface);
760  }
761  }
762 
763  // 18. Initialize the shutdown/flush lock
764  if (NT_SUCCESS(status))
765  {
766  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
767  attributes.ParentObject = deviceExtension->Device;
768 
769  status = WdfWaitLockCreate(&attributes, &deviceExtension->ShutdownFlushWaitLock);
770  if (!NT_SUCCESS(status))
771  {
772  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_PNP,
773  "DriverEvtDeviceAdd: Cannot create shutdown/flush waitlock, status: 0x%X\n",
774  status));
775  }
776  }
777 
778  // 19. Initialize the work item that is used to initiate asynchronous reads/writes
779  if (NT_SUCCESS(status))
780  {
781  WDF_WORKITEM_CONFIG workItemConfig;
782  WDF_OBJECT_ATTRIBUTES workItemAttributes;
783 
784  WDF_WORKITEM_CONFIG_INIT(&workItemConfig,
786  );
787 
788  WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes);
789  workItemAttributes.ParentObject = deviceExtension->Device;
790 
791  status = WdfWorkItemCreate(&workItemConfig,
792  &workItemAttributes,
793  &deviceExtension->ReadWriteWorkItem
794  );
795 
796  if (!NT_SUCCESS(status))
797  {
798  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
799  "DriverEvtDeviceAdd: Cannot create read/write work item, status: 0x%X\n",
800  status));
801  }
802  }
803 
804  // 20. Initialize the work item that is used to process most IOCTLs at PASSIVE_LEVEL.
805  if (NT_SUCCESS(status))
806  {
807  WDF_WORKITEM_CONFIG workItemConfig;
808  WDF_OBJECT_ATTRIBUTES workItemAttributes;
809 
810  WDF_WORKITEM_CONFIG_INIT(&workItemConfig,
812  );
813 
814  WDF_OBJECT_ATTRIBUTES_INIT(&workItemAttributes);
815  workItemAttributes.ParentObject = deviceExtension->Device;
816 
817  status = WdfWorkItemCreate(&workItemConfig,
818  &workItemAttributes,
819  &deviceExtension->IoctlWorkItem
820  );
821 
822  if (!NT_SUCCESS(status))
823  {
824  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_INIT,
825  "DriverEvtDeviceAdd: Cannot create ioctl work item, status: 0x%X\n",
826  status));
827  }
828  }
829 
830 
831 Exit:
832 
833  if (!NT_SUCCESS(status))
834  {
835  FREE_POOL(wideDeviceName);
836 
837  if (deviceExtension != NULL)
838  {
839  RtlInitUnicodeString(&deviceExtension->DeviceName, NULL);
840  }
841 
842  // Release the device with the port driver, if it was claimed
843  if ((deviceExtension != NULL) && deviceClaimed)
844  {
845  DeviceClaimRelease(deviceExtension, TRUE);
846  }
847  deviceClaimed = FALSE;
848  }
849 
850  return status;
851 }
852 
853 
854 VOID
855 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
858  )
859 /*++
860 Routine Description:
861 
862  Free all the resources allocated in DriverEvtDeviceAdd.
863 
864 Arguments:
865 
866  Device - handle to a WDF Device object.
867 
868 Return Value:
869 
870  VOID.
871 
872 --*/
873 {
874  WDFDEVICE device = (WDFDEVICE)Device;
875  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
876 
877  PAGED_CODE ();
878 
879  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
880  "WDFDEVICE %p cleanup: The device is about to be destroyed.\n",
881  device));
882 
883  deviceExtension = DeviceGetExtension(device);
884 
885  FREE_POOL(deviceExtension->DeviceName.Buffer);
886  RtlInitUnicodeString(&deviceExtension->DeviceName, NULL);
887 
888  if (deviceExtension->DeviceAdditionalData.WellKnownName.Buffer != NULL)
889  {
891  }
892 
895 
896  return;
897 }
898 
899 
900 VOID
901 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
903  _In_ WDFDEVICE Device
904  )
905 /*++
906 
907 Routine Description:
908 
909  this function is called when the device is removed.
910  release the ownership of the device, release allocated resources.
911 
912 Arguments:
913 
914  Device - Handle to device object
915 
916 Return Value:
917 
918  None.
919 
920 --*/
921 {
923  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
924 
925  PAGED_CODE ();
926 
927  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP,
928  "DeviceEvtSelfManagedIoCleanup: WDFDEVICE %p is being stopped.\n",
929  Device));
930 
931  // extract the device and driver extensions
932  deviceExtension = DeviceGetExtension(Device);
933 
934  // Purge unprocessed requests, stop the IO queues.
935  // Incoming request will be completed with STATUS_INVALID_DEVICE_STATE status.
936  WdfIoQueuePurge(deviceExtension->SerialIOQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
937  WdfIoQueuePurge(deviceExtension->CreateQueue, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT);
938 
939  // Close the IoTarget so that we are sure there are no outstanding I/Os in the stack.
940  if (deviceExtension->IoTarget)
941  {
942  WdfIoTargetClose(deviceExtension->IoTarget);
943  }
944 
945  // Release the device
946  if (!deviceExtension->SurpriseRemoved)
947  {
948  status = DeviceClaimRelease(deviceExtension, TRUE); //status is mainly for debugging. we don't really care.
949  UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
950  }
951 
952  // Be sure to flush the DPCs as the READ/WRITE timer routine may still be running
953  // during device removal. This call may take a while to complete.
955 
956  // Release all the memory that we have allocated.
957 
958  DeviceDeallocateMmcResources(Device);
959  ScratchBuffer_Deallocate(deviceExtension);
960  RtlZeroMemory(&(deviceExtension->DeviceAdditionalData.Mmc), sizeof(CDROM_MMC_EXTENSION));
961 
962  FREE_POOL(deviceExtension->DeviceDescriptor);
963  FREE_POOL(deviceExtension->AdapterDescriptor);
964  FREE_POOL(deviceExtension->PowerDescriptor);
965  FREE_POOL(deviceExtension->SenseData);
966 
967  if (deviceExtension->DeviceAdditionalData.CachedInquiryData != NULL)
968  {
969  FREE_POOL(deviceExtension->DeviceAdditionalData.CachedInquiryData);
971  }
972 
973  FREE_POOL(deviceExtension->PrivateFdoData);
974 
975  DeviceReleaseMcnResources(deviceExtension);
976 
977  DeviceReleaseZPODDResources(deviceExtension);
978 
979  // Keep the system-wide CDROM count accurate, as programs use this info to
980  // know when they have found all the cdroms in a system.
982 
983  deviceExtension->PartitionLength.QuadPart = 0;
984 
985  // All WDF objects related to Device will be automatically released
986  // when the root object is deleted. No need to release them manually.
987 
988  return;
989 }
990 
991 NTSTATUS
992 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
994  _In_ WDFDEVICE Device,
996  )
997 /*++
998 
999 Routine Description:
1000 
1001  This function is called when the device is coming back from a lower power state to D0.
1002  This function cannot be placed in a pageable section.
1003 
1004 Arguments:
1005 
1006  Device - Handle to device object
1007  PreviousState - Power state the device was in.
1008 
1009 Return Value:
1010 
1011  NTSTATUS: alway STATUS_SUCCESS
1012 
1013 --*/
1014 {
1015  PCDROM_DEVICE_EXTENSION deviceExtension;
1017  PZERO_POWER_ODD_INFO zpoddInfo = NULL;
1018  STORAGE_IDLE_POWERUP_REASON powerupReason = {0};
1019 
1021  deviceExtension = DeviceGetExtension(Device);
1022 
1023  // Make certain not to do anything before properly initialized
1024  if (deviceExtension->IsInitialized)
1025  {
1026  zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1027 
1028  if (zpoddInfo != NULL)
1029  {
1030  if (zpoddInfo->InZeroPowerState != FALSE)
1031  {
1032  // We just woke up from Zero Power state
1033  zpoddInfo->InZeroPowerState = FALSE;
1034  zpoddInfo->RetryFirstCommand = TRUE;
1036 
1037  status = DeviceZPODDGetPowerupReason(deviceExtension, &powerupReason);
1038 
1039  if (NT_SUCCESS(status) &&
1040  (powerupReason.PowerupReason == StoragePowerupDeviceAttention))
1041  {
1042  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1043  "DeviceEvtD0Entry: Device has left zero power state due to eject button pressed\n"
1044  ));
1045 
1046  // This wake-up is caused by user pressing the eject button.
1047  // In case of drawer type, we need to soft eject the tray to emulate the effect.
1048  // Note that the first command to the device after power resumed will
1049  // be terminated with CHECK CONDITION status with sense code 6/29/00,
1050  // but we already have a retry logic to handle this.
1051  if ((zpoddInfo->LoadingMechanism == LOADING_MECHANISM_TRAY) && (zpoddInfo->Load == 0)) // Drawer
1052  {
1053  DeviceSendIoctlAsynchronously(deviceExtension, IOCTL_STORAGE_EJECT_MEDIA, deviceExtension->DeviceObject);
1054  }
1055  }
1056  else
1057  {
1058  // This wake-up is caused by non-cached CDB received or a 3rd-party driver
1059  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1060  "DeviceEvtD0Entry: Device has left zero power state due to IO received\n"
1061  ));
1062 
1063  }
1064  }
1065  }
1066 
1067  DeviceEnableMainTimer(deviceExtension);
1068  }
1069 
1070  return STATUS_SUCCESS;
1071 }
1072 
1073 NTSTATUS
1074 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1076  _In_ WDFDEVICE Device,
1078  )
1079 /*++
1080 
1081 Routine Description:
1082 
1083  This function is called when the device is entering lower powe state from D0 or it's removed.
1084  We only care about the case of device entering D3.
1085  The purpose of this function is to send SYNC CACHE command and STOP UNIT command if it's necessary.
1086 
1087 Arguments:
1088 
1089  Device - Handle to device object
1090  TargetState - Power state the device is entering.
1091 
1092 Return Value:
1093 
1094  NTSTATUS: alway STATUS_SUCCESS
1095 
1096 --*/
1097 {
1099  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
1100  PZERO_POWER_ODD_INFO zpoddInfo = NULL;
1101 
1102  PAGED_CODE ();
1103 
1104  deviceExtension = DeviceGetExtension(Device);
1105  zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1106 
1107  // we only process the situation that the device is going into D3.
1108  if ((TargetState != WdfPowerDeviceD3) &&
1110  {
1111  return STATUS_SUCCESS;
1112  }
1113 
1114  // Stop the main timer
1115  DeviceDisableMainTimer(deviceExtension);
1116 
1117  // note: do not stop CreateQueue as the create request can be handled by port driver even the device is in D3 status.
1118 
1119  // If initialization was not finished or the device was removed, we cannot interact
1120  // with it device, so we have to exit
1121  if ((!deviceExtension->IsInitialized) || deviceExtension->SurpriseRemoved)
1122  {
1123  return STATUS_SUCCESS;
1124  }
1125 
1126 
1127 #ifdef DBG
1128  #if (WINVER >= 0x0601)
1129  // this API is introduced in Windows7
1130  {
1131  ULONG secondsRemaining = 0;
1132  BOOLEAN watchdogTimeSupported = FALSE;
1133 
1134  watchdogTimeSupported = PoQueryWatchdogTime(deviceExtension->LowerPdo, &secondsRemaining);
1135  UNREFERENCED_PARAMETER(watchdogTimeSupported);
1136  }
1137  #endif
1138 #endif
1139 
1140  deviceExtension->PowerDownInProgress = TRUE;
1141 
1142  status = PowerContextBeginUse(deviceExtension);
1143 
1144  deviceExtension->PowerContext.Options.PowerDown = TRUE;
1145 
1146  // Step 1. LOCK QUEUE
1147  if (NT_SUCCESS(status) &&
1149  {
1150  status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1151 
1152  if (NT_SUCCESS(status))
1153  {
1154  deviceExtension->PowerContext.Options.LockQueue = TRUE;
1155  }
1156 
1157  // Ignore failure.
1159  }
1160 
1161  deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1162 
1163  // Step 2. QUIESCE QUEUE
1164  if (NT_SUCCESS(status) &&
1166  {
1167  status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1169  // We don't care about the status.
1171  }
1172 
1173  deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1174 
1175  // Step 3. SYNC CACHE command should be sent to drive if the media is currently writable.
1176  if (NT_SUCCESS(status) &&
1177  deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed)
1178  {
1179  status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1182  }
1183 
1184  deviceExtension->PowerContext.PowerChangeState.PowerDown++;
1185 
1186  // Step 4. STOP UNIT
1187  if (NT_SUCCESS(status) &&
1189  {
1190  status = DeviceSendPowerDownProcessRequest(deviceExtension, NULL, NULL);
1193  }
1194 
1196  {
1197  // We're done with the power context.
1198  PowerContextEndUse(deviceExtension);
1199  }
1200 
1201  // Bumping the media change count will force the file system to verify the volume when we resume
1202  SET_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME);
1203  InterlockedIncrement((PLONG)&deviceExtension->MediaChangeCount);
1204 
1205  // If this power down is caused by Zero Power ODD, we should mark the device as in ZPODD mode.
1206  if (zpoddInfo != NULL)
1207  {
1208  zpoddInfo->InZeroPowerState = TRUE;
1209 
1210  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_POWER,
1211  "Device has entered zero power state\n"
1212  ));
1213  }
1214 
1215  deviceExtension->PowerDownInProgress = FALSE;
1216 
1217  return STATUS_SUCCESS;
1218 }
1219 
1220 
1221 VOID
1222 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1224  _In_ WDFDEVICE Device
1225  )
1226 /*++
1227 
1228 Routine Description:
1229 
1230  this function is called when the device is surprisely removed.
1231  Stop all IO queues so that there will be no more request being sent down.
1232 
1233 Arguments:
1234 
1235  Device - Handle to device object
1236 
1237 Return Value:
1238 
1239  None.
1240 
1241 --*/
1242 {
1243  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
1244 
1245  PAGED_CODE();
1246 
1247  deviceExtension = DeviceGetExtension(Device);
1248 
1249  deviceExtension->SurpriseRemoved = TRUE;
1250 
1251  // Stop the main timer
1252  DeviceDisableMainTimer(deviceExtension);
1253 
1254  // legacy behavior to set partition length to be 0.
1255  deviceExtension->PartitionLength.QuadPart = 0;
1256 
1257  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1258  "Surprisely remove a WDFDEVICE %p\n", Device));
1259 
1260  return;
1261 }
1262 
1263 
1264 VOID
1265 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1267  _In_ WDFQUEUE Queue,
1268  _In_ WDFREQUEST Request
1269  )
1270 /*++
1271 
1272 Routine Description:
1273 
1274  this function is called when CREATE irp comes.
1275  setup FileObject context fields, so it can be used to track MCN or exclusive lock/unlock.
1276 
1277 Arguments:
1278 
1279  Queue - Handle to device queue
1280 
1281  Request - the creation request
1282 
1283 Return Value:
1284 
1285  None
1286 
1287 --*/
1288 {
1289  WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request);
1290  WDFDEVICE device = WdfIoQueueGetDevice(Queue);
1292  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1293  PFILE_OBJECT_CONTEXT fileObjectContext = NULL;
1294 
1295  PAGED_CODE();
1296 
1297  if (fileObject == NULL) {
1298 
1299  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_QUEUE,
1300  "Error: received a file create request with file object set to NULL\n"));
1301 
1302  RequestCompletion(deviceExtension, Request, STATUS_INTERNAL_ERROR, 0);
1303  return;
1304  }
1305 
1306  fileObjectContext = FileObjectGetContext(fileObject);
1307 
1308  // Initialize this WDFFILEOBJECT's context
1309  fileObjectContext->DeviceObject = device;
1310  fileObjectContext->FileObject = fileObject;
1311  fileObjectContext->LockCount = 0;
1312  fileObjectContext->McnDisableCount = 0;
1313  fileObjectContext->EnforceStreamingRead = FALSE;
1314  fileObjectContext->EnforceStreamingWrite = FALSE;
1315 
1316  // send down the create synchronously
1317  status = DeviceSendRequestSynchronously(device, Request, FALSE);
1318 
1319  // Need to complete the request in this routine.
1320  RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
1321 
1322  return;
1323 }
1324 
1325 VOID
1326 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1328  _In_ WDFFILEOBJECT FileObject
1329  )
1330 /*++
1331 
1332 Routine Description:
1333 
1334  this function is called when CLOSE irp comes.
1335  clean up MCN / Lock if necessary
1336 
1337 Arguments:
1338 
1339  FileObject - WDF file object created for the irp.
1340 
1341 Return Value:
1342 
1343  None
1344 
1345 --*/
1346 {
1348 
1349  PAGED_CODE();
1350 
1351  if (FileObject != NULL)
1352  {
1353  WDFDEVICE device = WdfFileObjectGetDevice(FileObject);
1354  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
1355  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
1356  PFILE_OBJECT_CONTEXT fileObjectContext = FileObjectGetContext(FileObject);
1357 
1358  // cleanup locked media tray
1359  status = DeviceCleanupProtectedLocks(deviceExtension, fileObjectContext);
1360  if (!NT_SUCCESS(status))
1361  {
1362  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1363  "Failed to cleanup protected locks for WDFDEVICE %p, %!STATUS!\n", device, status));
1364  }
1365 
1366  // cleanup disabled MCN
1367  status = DeviceCleanupDisableMcn(deviceExtension, fileObjectContext);
1368  if (!NT_SUCCESS(status))
1369  {
1370  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1371  "Failed to disable MCN for WDFDEVICE %p, %!STATUS!\n", device, status));
1372  }
1373 
1374  // cleanup exclusive access
1375  if (EXCLUSIVE_MODE(cdData) && EXCLUSIVE_OWNER(cdData, FileObject))
1376  {
1377  status = DeviceUnlockExclusive(deviceExtension, FileObject, FALSE);
1378  if (!NT_SUCCESS(status))
1379  {
1380  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1381  "Failed to release exclusive lock for WDFDEVICE %p, %!STATUS!\n", device, status));
1382  }
1383  }
1384  }
1385 
1386  return;
1387 }
1388 
1390 NTSTATUS
1391 DeviceCleanupProtectedLocks(
1392  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1394  )
1395 /*++
1396 
1397 Routine Description:
1398 
1399  this function removes protected locks for the handle
1400 
1401 Arguments:
1402 
1403  DeviceExtension - device context
1404 
1405  FileObject - WDF file object created for the irp.
1406 
1407 Return Value:
1408 
1409  NTSTATUS
1410 
1411 --*/
1412 {
1414 
1415  PAGED_CODE();
1416 
1417  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1418  "CleanupProtectedLocks called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n",
1419  DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->LockCount));
1420 
1421  // Synchronize with ejection and ejection control requests.
1422  WdfWaitLockAcquire(DeviceExtension->EjectSynchronizationLock, NULL);
1423 
1424  // For each secure lock on this handle decrement the secured lock count
1425  // for the FDO. Keep track of the new value.
1426  if (FileObjectContext->LockCount != 0)
1427  {
1428  DeviceExtension->ProtectedLockCount -= FileObjectContext->LockCount;
1430 
1431  // If the new lock count has been dropped to zero then issue a lock
1432  // command to the device.
1433  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1434  "FDO secured lock count = %d "
1435  "lock count = %d\n",
1436  DeviceExtension->ProtectedLockCount,
1437  DeviceExtension->LockCount));
1438 
1439  if ((DeviceExtension->ProtectedLockCount == 0) && (DeviceExtension->LockCount == 0))
1440  {
1441  SCSI_REQUEST_BLOCK srb = {0};
1442  PCDB cdb = (PCDB) &(srb.Cdb);
1443 
1444  srb.CdbLength = 6;
1445 
1446  cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1447 
1448  // TRUE - prevent media removal.
1449  // FALSE - allow media removal.
1450  cdb->MEDIA_REMOVAL.Prevent = FALSE;
1451 
1452  // Set timeout value.
1453  srb.TimeOutValue = DeviceExtension->TimeOutValue;
1454  status = DeviceSendSrbSynchronously(DeviceExtension->Device,
1455  &srb,
1456  NULL,
1457  0,
1458  FALSE,
1459  NULL);
1460 
1461  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT,
1462  "Allow media removal (unlock) request to drive returned %!STATUS!\n",
1463  status));
1464  }
1465  }
1466 
1467  WdfWaitLockRelease(DeviceExtension->EjectSynchronizationLock);
1468 
1469  return status;
1470 }
1471 
1472 
1474 NTSTATUS
1475 DeviceCleanupDisableMcn(
1476  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1478  )
1479 /*++
1480 
1481 Routine Description:
1482 
1483  cleanup the MCN disable count for the handle
1484 
1485 Arguments:
1486 
1487  DeviceExtension - device context
1488 
1489  FileObject - WDF file object created for the irp.
1490 
1491 Return Value:
1492 
1493  NTSTATUS
1494 
1495 --*/
1496 {
1497  PAGED_CODE();
1498 
1499  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_INIT,
1500  "CleanupDisableMcn called for WDFDEVICE %p, WDFFILEOBJECT %p, locked %d times.\n",
1501  DeviceExtension->Device, FileObjectContext->FileObject, FileObjectContext->McnDisableCount));
1502 
1503  // For each secure lock on this handle decrement the secured lock count
1504  // for the FDO. Keep track of the new value.
1505  while (FileObjectContext->McnDisableCount != 0)
1506  {
1507  DeviceEnableMediaChangeDetection(DeviceExtension, FileObjectContext, TRUE);
1508  }
1509 
1510  return STATUS_SUCCESS;
1511 }
1512 
1513 VOID
1515  _Inout_ PWDF_REQUEST_PARAMETERS requestParameters
1516  )
1517 {
1518  ULONG ioctlCode;
1519  ULONG baseCode;
1520  ULONG functionCode;
1521 
1522  // if this is a class driver ioctl then we need to change the base code
1523  // to IOCTL_STORAGE_BASE so that the switch statement can handle it.
1524  //
1525  // WARNING - currently the scsi class ioctl function codes are between
1526  // 0x200 & 0x300. this routine depends on that fact
1527  ioctlCode = requestParameters->Parameters.DeviceIoControl.IoControlCode;
1528  baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode);
1529  functionCode = (ioctlCode & (~0xffffc003)) >> 2;
1530 
1531  if ((baseCode == IOCTL_SCSI_BASE) ||
1532  (baseCode == IOCTL_DISK_BASE) ||
1533  (baseCode == IOCTL_TAPE_BASE) ||
1534  (baseCode == IOCTL_DVD_BASE) ||
1535  (baseCode == IOCTL_CDROM_BASE))
1536  //IOCTL_STORAGE_BASE does not need to be converted.
1537  {
1538  if((functionCode >= 0x200) && (functionCode <= 0x300))
1539  {
1540  ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_STORAGE_BASE, 0, 0, 0);
1541 
1542  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
1543  "IOCTL code recalibrate, New ioctl code is %lx\n",
1544  ioctlCode));
1545 
1546  // Set the code into request parameters, then "requestParameters" needs to be used for dispatch functions.
1547  requestParameters->Parameters.DeviceIoControl.IoControlCode = ioctlCode;
1548  }
1549  }
1550 }
1551 
1552 VOID
1553 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1555  _In_ WDFDEVICE Device,
1556  _In_ WDFREQUEST Request
1557  )
1558 /*++
1559 Routine Description:
1560 
1561  Responds to EvtIoInCallerContext events from KMDF
1562  It calls different functions to process different type of IOCTLs.
1563 
1564 Arguments:
1565 
1566  Device - handle to a WDF Device object
1567 
1568  Request - handle to the incoming WDF Request object
1569 
1570 Return Value:
1571 
1572  VOID.
1573 
1574 --*/
1575 {
1577  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1578  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
1579  WDF_REQUEST_PARAMETERS requestParameters;
1580 
1581  requestContext->DeviceExtension = deviceExtension;
1582 
1583  // set the received time
1585 
1586  // get the request parameters
1587  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
1588  WdfRequestGetParameters(Request, &requestParameters);
1589 
1590  if (requestParameters.Type == WdfRequestTypeDeviceControl)
1591  {
1593  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
1595 
1596  if (requestParameters.Parameters.DeviceIoControl.IoControlCode != IOCTL_MCN_SYNC_FAKE_IOCTL)
1597  {
1598  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1599  "Receiving IOCTL: %lx\n",
1600  requestParameters.Parameters.DeviceIoControl.IoControlCode));
1601  }
1602  else
1603  {
1604  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_IOCTL,
1605  "Receiving IOCTL: %lx\n",
1606  requestParameters.Parameters.DeviceIoControl.IoControlCode));
1607  }
1608 
1609  // If the device is in exclusive mode, check whether the request is from
1610  // the handle that locked the device.
1611  if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
1612  {
1613  BOOLEAN isBlocked = FALSE;
1614 
1616  UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
1617 
1618  if (isBlocked)
1619  {
1620  if ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_STORAGE_EVENT_NOTIFICATION) &&
1621  (info != NULL) && (info->AsynchronousNotificationSupported != FALSE))
1622  {
1623  // If AN is supported and we receive a signal but we can't send down GESN
1624  // due to exclusive lock, we should save it and fire a GESN when it's unlocked.
1625  // We just need true/false here and don't need count because we will keep sending
1626  // GESN until we deplete all events.
1627  info->ANSignalPendingDueToExclusiveLock = TRUE;
1628  }
1629 
1630  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
1631  "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
1632  requestParameters.Parameters.DeviceIoControl.IoControlCode));
1633  RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
1634 
1635  return;
1636  }
1637  }
1638 
1639  NormalizeIoctl(&requestParameters);
1640 
1641  // 1. All requests that don't need to access device can be processed immediately
1642  if (!processed)
1643  {
1644  processed = RequestDispatchProcessDirectly(Device, Request, requestParameters);
1645  }
1646 
1647  // 2. Requests that should be put in sequential queue.
1648  if (!processed)
1649  {
1651  }
1652 
1653  // 3. Requests that need to be processed sequentially and in caller's context.
1654  if (!processed)
1655  {
1657  }
1658 
1659  // 4. Special requests that needs different process in different cases.
1660  if (!processed)
1661  {
1662  processed = RequestDispatchSpecialIoctls(Device, Request, requestParameters);
1663  }
1664 
1665  // 5. This is default behavior for unknown IOCTLs. To pass it to lower level.
1666  if (!processed)
1667  {
1668  processed = RequestDispatchUnknownRequests(Device, Request, requestParameters);
1669  }
1670 
1671  // All requests should be processed already.
1673  UNREFERENCED_PARAMETER(processed); //defensive coding, avoid PREFAST warning.
1674  }
1675  else if (requestParameters.Type == WdfRequestTypeDeviceControlInternal)
1676  {
1677  RequestProcessInternalDeviceControl(Request, deviceExtension);
1678  }
1679  else
1680  {
1681  // Requests other than IOCTLs will be forwarded to default queue.
1682  status = WdfDeviceEnqueueRequest(Device, Request);
1683  if (!NT_SUCCESS(status))
1684  {
1685  RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
1686  }
1687  }
1688 
1689  return;
1690 }
1691 
1692 
1693 BOOLEAN
1695  _In_ WDFDEVICE Device,
1696  _In_ WDFREQUEST Request,
1698  )
1699 /*++
1700 Routine Description:
1701 
1702  These requests can be processed in a non-serialized manner, most of them don't need to access device.
1703 
1704 Arguments:
1705 
1706  Device - handle to a WDF Device object
1707 
1708  Request - handle to the incoming WDF Request object
1709 
1710  RequestParameters - request parameters
1711 
1712 Return Value:
1713 
1714  BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
1715 
1716 --*/
1717 {
1720  size_t dataLength = 0;
1721 
1722  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1723  ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
1724 
1725  switch (ioctlCode)
1726  {
1727 
1729  {
1731 
1732  processed = TRUE;
1733  break; // complete the irp
1734  }
1735 
1737  {
1738  status = RequestHandleGetMediaTypeEx(deviceExtension, Request, &dataLength);
1739 
1740  processed = TRUE;
1741  break; // complete the irp
1742  }
1743 
1745  {
1747 
1748  processed = TRUE;
1749  break; // complete the irp
1750  }
1751 
1753  {
1755 
1756  processed = TRUE;
1757  break; // complete the irp
1758  }
1759 
1761  {
1763 
1764  processed = TRUE;
1765  break; // complete the irp
1766  }
1767 
1769  {
1771 
1772  processed = TRUE;
1773  break; // complete the irp
1774  }
1775 
1777  {
1779 
1780  processed = TRUE;
1781  break; // complete the irp
1782  }
1783 
1785  {
1787 
1788  processed = TRUE;
1789  break; // complete the irp
1790  }
1791 
1793  {
1794  status = RequestHandleEventNotification(deviceExtension, Request, &RequestParameters, &dataLength);
1795 
1796  processed = TRUE;
1797  break; // complete the irp
1798  }
1799 
1800 #if (NTDDI_VERSION >= NTDDI_WIN8)
1801  case IOCTL_VOLUME_ONLINE:
1802  {
1803  //
1804  // Mount manager and volume manager will
1805  // follow this online with a post online
1806  // but other callers may not. In those
1807  // cases, we process this request right
1808  // away. We approximate that these other
1809  // callers are from user mode
1810  //
1811 
1812  if (WdfRequestGetRequestorMode(Request) == KernelMode)
1813  {
1814  processed = TRUE;
1815  }
1816  break;
1817  }
1818 #endif
1819 
1820  default:
1821  {
1822  processed = FALSE;
1823  break;
1824  }
1825 
1826  } //end of switch (ioctlCode)
1827 
1828  if (processed)
1829  {
1830  UCHAR currentStackLocationFlags = 0;
1831  currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
1832 
1833  if ((status == STATUS_VERIFY_REQUIRED) &&
1834  (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
1835  {
1836  // If the status is verified required and this request
1837  // should bypass verify required then retry the request.
1839  UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
1840 
1842  }
1843  else
1844  {
1845  // Complete the request after processing it.
1846  RequestCompletion(deviceExtension, Request, status, dataLength);
1847  }
1848  }
1849 
1850  return processed;
1851 }
1852 
1853 
1854 BOOLEAN
1856  _In_ WDFDEVICE Device,
1857  _In_ WDFREQUEST Request,
1859  )
1860 /*++
1861 Routine Description:
1862 
1863  These requests can be processed in a non-serialized manner, most of them don't need to access device.
1864 
1865 Arguments:
1866 
1867  Device - handle to a WDF Device object
1868 
1869  Request - handle to the incoming WDF Request object
1870 
1871  RequestParameters - request parameters
1872 
1873 Return Value:
1874 
1875  BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
1876 
1877 --*/
1878 {
1881  size_t dataLength = 0;
1882  BOOLEAN inZeroPowerState = FALSE;
1883 
1884  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
1885  ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
1886  PZERO_POWER_ODD_INFO zpoddInfo = deviceExtension->ZeroPowerODDInfo;
1887 
1888  if ((zpoddInfo != NULL) &&
1889  (zpoddInfo->InZeroPowerState != FALSE))
1890  {
1891  inZeroPowerState = TRUE;
1892  }
1893 
1894  switch (ioctlCode)
1895  {
1896 
1897  case IOCTL_CDROM_RAW_READ:
1898  {
1900 
1901  processed = TRUE;
1902  break;
1903  }
1904 
1907  {
1908  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1909  "RequestDispatchToSequentialQueue: Get drive geometryEx\n"));
1910  if ( RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1912  {
1915  }
1916  else if (inZeroPowerState != FALSE)
1917  {
1919  }
1920  else
1921  {
1923  }
1924 
1925  processed = TRUE;
1926  break;
1927  }
1928 
1931  {
1932  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1933  "RequestDispatchToSequentialQueue: Get drive geometry\n"));
1934  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
1935  sizeof(DISK_GEOMETRY))
1936  {
1938  dataLength = sizeof(DISK_GEOMETRY);
1939  }
1940  else if (inZeroPowerState != FALSE)
1941  {
1943  }
1944  else
1945  {
1947  }
1948 
1949  processed = TRUE;
1950  break;
1951  }
1952 
1954  {
1956 
1957  if (inZeroPowerState != FALSE)
1958  {
1960  }
1961 
1962  processed = TRUE;
1963  break;
1964  }
1965 
1966  case IOCTL_CDROM_READ_TOC:
1967  {
1969 
1970  if (inZeroPowerState != FALSE)
1971  {
1973  }
1974 
1975  processed = TRUE;
1976  break;
1977  }
1978 
1980  {
1982 
1983  processed = TRUE;
1984  break;
1985  }
1986 
1988  {
1989  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
1990  "RequestDispatchToSequentialQueue: Play audio MSF\n"));
1991 
1992  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
1993  sizeof(CDROM_PLAY_AUDIO_MSF))
1994  {
1996  }
1997  else
1998  {
2000  }
2001 
2002  processed = TRUE;
2003  break;
2004  }
2005 
2007  {
2008  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2009  "RequestDispatchToSequentialQueue: Seek audio MSF\n"));
2010 
2011  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2012  sizeof(CDROM_SEEK_AUDIO_MSF))
2013  {
2015  }
2016  else
2017  {
2019  }
2020 
2021  processed = TRUE;
2022  break;
2023  }
2024 
2026  {
2027  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2028  "RequestDispatchToSequentialQueue: Pause audio\n"));
2029 
2031  processed = TRUE;
2032  break;
2033  }
2034 
2036  {
2037  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2038  "RequestDispatchToSequentialQueue: Resume audio\n"));
2039 
2041  processed = TRUE;
2042  break;
2043  }
2044 
2046  {
2048 
2049  processed = TRUE;
2050  break;
2051  }
2052 
2054  {
2055  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2056  "RequestDispatchToSequentialQueue: Get volume control\n"));
2057 
2058  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2059  sizeof(VOLUME_CONTROL))
2060  {
2062  dataLength = sizeof(VOLUME_CONTROL);
2063  }
2064  else
2065  {
2067  }
2068 
2069  processed = TRUE;
2070  break;
2071  }
2072 
2074  {
2075  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2076  "RequestDispatchToSequentialQueue: Set volume control\n"));
2077 
2078  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2079  sizeof(VOLUME_CONTROL))
2080  {
2082  }
2083  else
2084  {
2086  }
2087 
2088  processed = TRUE;
2089  break;
2090  }
2091 
2093  {
2094  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2095  "RequestDispatchToSequentialQueue: Stop audio\n"));
2096 
2098  processed = TRUE;
2099  break;
2100  }
2101 
2104  {
2105  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2106  "RequestDispatchToSequentialQueue: [%p] Check Verify\n", Request));
2107 
2108  // Following check will let the condition "OutputBufferLength == 0" pass.
2109  // Since it's legacy behavior in classpnp, we need to keep it.
2110  if ((RequestParameters.Parameters.DeviceIoControl.OutputBufferLength > 0) &&
2111  (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)))
2112  {
2114  dataLength = sizeof(ULONG);
2115  }
2116  else if (inZeroPowerState != FALSE)
2117  {
2119  }
2120  else
2121  {
2123  }
2124 
2125  processed = TRUE;
2126  break;
2127  }
2128 
2129  case IOCTL_DVD_GET_REGION:
2130  {
2131  // validation will be done when process it.
2133  processed = TRUE;
2134  break;
2135  }
2136 
2138  {
2139  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2140  "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_STRUCTURE\n", Request));
2141 
2143 
2144  processed = TRUE;
2145  break;
2146  }
2147 
2148  case IOCTL_DVD_READ_KEY:
2149  {
2150  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2151  "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_READ_KEY\n", Request));
2152 
2154 
2155  processed = TRUE;
2156  break;
2157  }
2158 
2160  {
2161  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2162  "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_START_SESSION\n", Request));
2163 
2165 
2166  processed = TRUE;
2167  break;
2168  }
2169 
2170  case IOCTL_DVD_SEND_KEY:
2171  case IOCTL_DVD_SEND_KEY2:
2172  {
2173  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2174  "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_SEND_KEY\n", Request));
2175 
2177 
2178  processed = TRUE;
2179  break;
2180  }
2181 
2183  {
2184  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2185  "RequestDispatchToSequentialQueue: [%p] SetReadAhead\n", Request));
2186 
2187  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2188  sizeof(STORAGE_SET_READ_AHEAD))
2189  {
2191  }
2192  else
2193  {
2195  }
2196 
2197  processed = TRUE;
2198  break;
2199  }
2200 
2202  {
2204 
2205  processed = TRUE;
2206  break;
2207  }
2208 
2210  {
2211  ULONG requiredSize = 0;
2212 
2213  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2214  "RequestDispatchToSequentialQueue: Get drive layout\n"));
2215 
2216  requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[1]);
2217 
2218  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2219  requiredSize)
2220  {
2222  dataLength = requiredSize;
2223  }
2224  else
2225  {
2227  }
2228 
2229  processed = TRUE;
2230  break;
2231  }
2232 
2234  {
2235  ULONG requiredSize = 0;
2236 
2237  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2238  "RequestDispatchToSequentialQueue: Get drive layoutEx\n"));
2239 
2240  requiredSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
2241 
2242  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2243  requiredSize)
2244  {
2246  dataLength = requiredSize;
2247  }
2248  else
2249  {
2251  }
2252 
2253  processed = TRUE;
2254  break;
2255  }
2256 
2258  {
2259  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2260  "RequestDispatchToSequentialQueue: Get Partition Info\n"));
2261 
2262  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2263  sizeof(PARTITION_INFORMATION))
2264  {
2267  }
2268  else
2269  {
2271  }
2272 
2273  processed = TRUE;
2274  break;
2275  }
2276 
2278  {
2279  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2280  "RequestDispatchToSequentialQueue: Get Partition InfoEx\n"));
2281 
2282  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2283  sizeof(PARTITION_INFORMATION_EX))
2284  {
2287  }
2288  else
2289  {
2291  }
2292 
2293  processed = TRUE;
2294  break;
2295  }
2296 
2297  case IOCTL_DISK_VERIFY:
2298  {
2299  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2300  "RequestDispatchToSequentialQueue: IOCTL_DISK_VERIFY to device %p through request %p\n",
2301  Device,
2302  Request));
2303 
2304  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2305  sizeof(VERIFY_INFORMATION))
2306  {
2308  }
2309  else
2310  {
2312  }
2313 
2314  processed = TRUE;
2315  break;
2316  }
2317 
2319  {
2320  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2321  "RequestDispatchToSequentialQueue: Disk Get Length InfoEx\n"));
2322 
2323  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength <
2324  sizeof(GET_LENGTH_INFORMATION))
2325  {
2328  }
2329  else if (inZeroPowerState != FALSE)
2330  {
2332  }
2333  else
2334  {
2336  }
2337 
2338  processed = TRUE;
2339  break;
2340  }
2341 
2343  {
2344  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2345  "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_CONFIGURATION\n", Request));
2346 
2348 
2349  processed = TRUE;
2350  break;
2351  }
2352 
2353  case IOCTL_CDROM_SET_SPEED:
2354  {
2355  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2356  "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SET_SPEED\n", Request));
2357 
2359 
2360  processed = TRUE;
2361  break;
2362  }
2363 
2364  case IOCTL_DVD_END_SESSION:
2365  {
2366  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2367  "RequestDispatchToSequentialQueue: [%p] IOCTL_DVD_END_SESSION\n", Request));
2368 
2370 
2371  processed = TRUE;
2372  break;
2373  }
2374 
2376  {
2377  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2378  "RequestDispatchToSequentialQueue: [%p] IOCTL_AACS_END_SESSION\n", Request));
2379 
2381 
2382  processed = TRUE;
2383  break;
2384  }
2385 
2387  {
2388  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2389  "AACS: Querying full MKB with bufferSize of %x bytes\n",
2390  (int)RequestParameters.Parameters.DeviceIoControl.OutputBufferLength
2391  ));
2392 
2394 
2395  processed = TRUE;
2396  break;
2397  }
2398 
2400  {
2401  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2402  "AACS: Requesting AGID\n"
2403  ));
2404 
2406 
2407  processed = TRUE;
2408  break;
2409  }
2410 
2412  {
2413  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2414  "AACS: Sending host certificate to drive\n"
2415  ));
2416 
2418 
2419  processed = TRUE;
2420  break;
2421  }
2422 
2424  {
2425  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2426  "AACS: Querying drive certificate\n"
2427  ));
2428 
2430 
2431  processed = TRUE;
2432  break;
2433  }
2434 
2436  {
2437  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2438  "AACS: Querying drive challenge key\n"
2439  ));
2440 
2442 
2443  processed = TRUE;
2444  break;
2445  }
2446 
2448  {
2449  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2450  "AACS: Sending drive challenge key\n"
2451  ));
2452 
2454 
2455  processed = TRUE;
2456  break;
2457  }
2458 
2460  {
2461  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2462  "AACS: Reading volume ID\n"
2463  ));
2464 
2466 
2467  processed = TRUE;
2468  break;
2469  }
2470 
2472  {
2473  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2474  "AACS: Reading Serial Number\n"
2475  ));
2476 
2478 
2479  processed = TRUE;
2480  break;
2481  }
2482 
2484  {
2485  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2486  "AACS: Reading media ID\n"
2487  ));
2488 
2490 
2491  processed = TRUE;
2492  break;
2493  }
2494 
2497  {
2498  if (ioctlCode == IOCTL_AACS_GENERATE_BINDING_NONCE)
2499  {
2500  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2501  "AACS: Generating new binding nonce\n"
2502  ));
2503  }
2504  else
2505  {
2506  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
2507  "AACS: Reading existing binding nonce\n"
2508  ));
2509  }
2510 
2512 
2513  processed = TRUE;
2514  break;
2515  }
2516 
2518  {
2519  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2520  "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_ENABLE_STREAMING\n", Request));
2521 
2523 
2524  processed = TRUE;
2525  break;
2526  }
2527 
2529  {
2530  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2531  "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_SEND_OPC_INFORMATION\n", Request));
2532 
2534 
2535  processed = TRUE;
2536  break;
2537  }
2538 
2540  {
2541  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
2542  "RequestDispatchToSequentialQueue: [%p] IOCTL_CDROM_GET_PERFORMANCE\n", Request));
2543 
2545 
2546  processed = TRUE;
2547  break;
2548  }
2549 
2552  {
2553  if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2554  sizeof(PREVENT_MEDIA_REMOVAL))
2555  {
2557  }
2558  else
2559  {
2561  }
2562 
2563  processed = TRUE;
2564  break; // complete the irp
2565  }
2566 
2568  {
2569  if(RequestParameters.Parameters.DeviceIoControl.InputBufferLength <
2570  sizeof(PREVENT_MEDIA_REMOVAL))
2571  {
2573  }
2574  else
2575  {
2577  }
2578 
2579  processed = TRUE;
2580  break; // complete the irp
2581  }
2582 
2583  case IOCTL_STORAGE_RESERVE:
2584  case IOCTL_STORAGE_RELEASE:
2585  {
2586  // there is no validate check currently.
2588  processed = TRUE;
2589  break;
2590  }
2591 
2594  {
2596 
2597  processed = TRUE;
2598  break;
2599  }
2600 
2604  {
2606 
2607  processed = TRUE;
2608  break; // complete the irp
2609  }
2610 
2612  {
2613  // process it.
2615 
2617 
2618  processed = TRUE;
2619  break; // complete the irp
2620  }
2621 
2623  {
2624  if (RequestParameters.Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_READ_CAPACITY))
2625  {
2628  }
2629  else if (inZeroPowerState != FALSE)
2630  {
2632  }
2633  else
2634  {
2636  }
2637 
2638  processed = TRUE;
2639  break; // complete the irp
2640  }
2641 
2643  {
2644  // for disk.sys only in original classpnp
2646 
2647  processed = TRUE;
2648  break; // complete the irp
2649  }
2650 
2651 #if (NTDDI_VERSION >= NTDDI_WIN8)
2653  {
2654  // this request doesn't access device at all, so seemingly it can be processed
2655  // directly; however, in case volume online is not received, we will need to
2656  // park these requests in a queue, and the only way a request can be queued is
2657  // if the request came out of another queue.
2659 
2660  processed = TRUE;
2661  break;
2662  }
2663 
2664  case IOCTL_VOLUME_ONLINE:
2666  {
2668 
2669  processed = TRUE;
2670  break;
2671  }
2672 #endif
2673 
2674  default:
2675  {
2676  processed = FALSE;
2677  break;
2678  }
2679  } //end of switch (ioctlCode)
2680 
2681  if (processed)
2682  {
2683  UCHAR currentStackLocationFlags = 0;
2684  currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
2685 
2686  if ((status == STATUS_VERIFY_REQUIRED) &&
2687  (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
2688  {
2689  // If the status is verified required and this request
2690  // should bypass verify required then retry the request.
2692  UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
2693 
2695  }
2696  else
2697  {
2698  if (NT_SUCCESS(status))
2699  {
2700  // Forward the request to serialized queue.
2701  status = WdfDeviceEnqueueRequest(Device, Request);
2702  }
2703 
2704  if (!NT_SUCCESS(status))
2705  {
2706  // Validation failed / forward failed, complete the request.
2707  RequestCompletion(deviceExtension, Request, status, dataLength);
2708  }
2709  }
2710  }
2711 
2712  return processed;
2713 }
2714 
2715 
2716 BOOLEAN
2718  _In_ WDFDEVICE Device,
2719  _In_ WDFREQUEST Request,
2721  )
2722 /*++
2723 Routine Description:
2724 
2725  These requests need to stay in caller's context and be processed in serialized manner.
2726 
2727 Arguments:
2728 
2729  Device - handle to a WDF Device object
2730 
2731  Request - handle to the incoming WDF Request object
2732 
2733  RequestParameters - request parameters
2734 
2735 Return Value:
2736 
2737  BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
2738 
2739 --*/
2740 {
2743  size_t dataLength = 0;
2744 
2745  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2746  ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
2747 
2748  switch (ioctlCode)
2749  {
2750 
2752  {
2753  //1. Validate
2755 
2756  //2. keep the request in serialized manner and stay in user's context.
2757  if (NT_SUCCESS(status))
2758  {
2759  PCDROM_EXCLUSIVE_ACCESS exclusiveAccess = NULL;
2760 
2761  status = WdfRequestRetrieveInputBuffer(Request,
2762  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
2763  &exclusiveAccess,
2764  NULL);
2765 
2766  if (NT_SUCCESS(status))
2767  {
2768  // do not need to check "status" as it passed validation and cannot fail in WdfRequestRetrieveInputBuffer()
2769  switch (exclusiveAccess->RequestType)
2770  {
2771 
2773  {
2774  status = RequestSetContextFields(Request, RequestHandleExclusiveAccessQueryLockState);
2775  break;
2776  }
2777 
2779  {
2780  status = RequestSetContextFields(Request, RequestHandleExclusiveAccessLockDevice);
2781  break;
2782  }
2783 
2785  {
2786  status = RequestSetContextFields(Request, RequestHandleExclusiveAccessUnlockDevice);
2787  break;
2788  }
2789  default:
2790  {
2791  // already valicated in RequestValidateExclusiveAccess()
2792  NT_ASSERT(FALSE);
2793  break;
2794  }
2795  }
2796  }
2797 
2798  if (NT_SUCCESS(status))
2799  {
2800  // now, put the special synchronization information into the context
2802 
2803  // "status" is used for debugging in above statement, reset to success to avoid further work in this function.
2805  }
2806  }
2807 
2808  processed = TRUE;
2809  break; // complete the irp
2810  }
2811 
2812  default:
2813  {
2814  processed = FALSE;
2815  break;
2816  }
2817  } //end of switch (ioctlCode)
2818 
2819  // Following process is only valid if the request is not really processed. (failed in validation)
2820  if (processed && !NT_SUCCESS(status))
2821  {
2822  UCHAR currentStackLocationFlags = 0;
2823  currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
2824 
2825  if ((status == STATUS_VERIFY_REQUIRED) &&
2826  (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
2827  {
2828  //
2829  // If the status is verified required and this request
2830  // should bypass verify required then retry the request.
2831  //
2833  UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
2834 
2836  }
2837  else
2838  {
2839  // Validation failed / forward failed, complete the request.
2840  RequestCompletion(deviceExtension, Request, status, dataLength);
2841  }
2842  }
2843 
2844  return processed;
2845 }
2846 
2847 
2848 BOOLEAN
2850  _In_ WDFDEVICE Device,
2851  _In_ WDFREQUEST Request,
2853  )
2854 /*++
2855 Routine Description:
2856 
2857  These requests need to be processed in different manner according to input parameters
2858 
2859 Arguments:
2860 
2861  Device - handle to a WDF Device object
2862 
2863  Request - handle to the incoming WDF Request object
2864 
2865  RequestParameters - request parameters
2866 
2867 Return Value:
2868 
2869  BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
2870 
2871 --*/
2872 {
2875  size_t dataLength = 0;
2876  BOOLEAN requestCompleted = FALSE;
2877 
2878  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
2879  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
2880  ULONG ioctlCode = RequestParameters.Parameters.DeviceIoControl.IoControlCode;
2881 
2882  switch (ioctlCode)
2883  {
2888  {
2889  // SPTI is considered special case as we need to set the MinorFunction before pass to low level.
2890 
2891 #if defined (_WIN64)
2892  if (WdfRequestIsFrom32BitProcess(Request))
2893  {
2894  if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT))
2895  {
2896  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32))
2897  {
2899  }
2900  }
2901  else
2902  {
2903  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32_EX))
2904  {
2906  }
2907  }
2908  }
2909  else
2910 #endif
2911  {
2912  if ((ioctlCode == IOCTL_SCSI_PASS_THROUGH) || (ioctlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT))
2913  {
2914  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH))
2915  {
2917  }
2918  }
2919  else
2920  {
2921  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH_EX))
2922  {
2924  }
2925  }
2926  }
2927 
2928  if (!NT_SUCCESS(status))
2929  {
2930  // validation failed.
2931  RequestCompletion(deviceExtension, Request, status, dataLength);
2932  }
2933  else
2934  {
2935  // keep the request in serialized manner and stay in user's context.
2936  status = RequestSetContextFields(Request, RequestHandleScsiPassThrough);
2937 
2938  if (NT_SUCCESS(status))
2939  {
2941  }
2942  else
2943  {
2944  RequestCompletion(deviceExtension, Request, status, 0);
2945  }
2946  }
2947 
2948  requestCompleted = TRUE;
2949  processed = TRUE;
2950  break;
2951  }
2952 
2954  {
2955  if (RequestParameters.Parameters.DeviceIoControl.InputBufferLength < sizeof(STORAGE_PROPERTY_QUERY))
2956  {
2958  }
2959  else
2960  {
2961  PSTORAGE_PROPERTY_QUERY inputBuffer = NULL;
2962 
2963  status = WdfRequestRetrieveInputBuffer(Request,
2964  RequestParameters.Parameters.DeviceIoControl.InputBufferLength,
2965  &inputBuffer,
2966  NULL);
2967 
2968  if (NT_SUCCESS(status))
2969  {
2970  if (!EXCLUSIVE_MODE(cdData) || // not locked
2971  EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)) || // request is from lock owner
2972  (inputBuffer->QueryType == PropertyExistsQuery)) // request not access device
2973  {
2974  if (inputBuffer->PropertyId == StorageDeviceUniqueIdProperty)
2975  {
2976  // previously handled in classpnp
2977  // keep the request in serialized manner and stay in user's context.
2979 
2980  if (NT_SUCCESS(status))
2981  {
2983  // remeber that the request has been completed.
2984  requestCompleted = TRUE;
2985  }
2986  }
2987  else if (inputBuffer->PropertyId == StorageDeviceWriteCacheProperty)
2988  {
2989  // previously handled in classpnp
2990  // keep the request in serialized manner and stay in user's context.
2992 
2993  if (NT_SUCCESS(status))
2994  {
2996  // remeber that the request has been completed.
2997  requestCompleted = TRUE;
2998  }
2999  }
3000  else
3001  {
3002  // Pass to port driver for handling
3004 
3005  // remeber that the request has been completed.
3006  requestCompleted = TRUE;
3007  }
3008  }
3009  else
3010  {
3011  // If cached data exists, return cached data. Otherwise, fail the request.
3012  if ((inputBuffer->QueryType == PropertyStandardQuery) &&
3013  ((inputBuffer->PropertyId == StorageDeviceProperty) || (inputBuffer->PropertyId == StorageAdapterProperty)) )
3014  {
3016  }
3017  else
3018  {
3020  }
3021  }
3022  }
3023  }
3024 
3025  processed = TRUE;
3026  break;
3027  }
3028 
3029  // this IOCTL is a fake one, used for MCN process sync-ed with serial queue.
3031  {
3032  PIRP irp = WdfRequestWdmGetIrp(Request);
3033 
3034  if ((deviceExtension->MediaChangeDetectionInfo != NULL) &&
3035  (irp == deviceExtension->MediaChangeDetectionInfo->MediaChangeSyncIrp) &&
3036  (WdfRequestGetRequestorMode(Request) == KernelMode) &&
3040  {
3041  // This is the requset we use to sync Media Change Detection with sequential queue.
3042  status = WdfDeviceEnqueueRequest(Device, Request);
3043 
3044  if (!NT_SUCCESS(status))
3045  {
3046  RequestCompletion(deviceExtension, Request, status, dataLength);
3047  }
3048 
3049  requestCompleted = TRUE;
3050  processed = TRUE;
3051  }
3052  else
3053  {
3054  // process as an unknown request.
3055  processed = FALSE;
3056  }
3057  break;
3058  }
3059 
3060  default:
3061  {
3062  processed = FALSE;
3063  break;
3064  }
3065  } //end of switch (ioctlCode)
3066 
3067  if (processed && !requestCompleted)
3068  {
3069  UCHAR currentStackLocationFlags = 0;
3070  currentStackLocationFlags = RequestGetCurrentStackLocationFlags(Request);
3071 
3072  if ((status == STATUS_VERIFY_REQUIRED) &&
3073  (currentStackLocationFlags & SL_OVERRIDE_VERIFY_VOLUME))
3074  {
3075  // If the status is verified required and this request
3076  // should bypass verify required then retry the request.
3078  UNREFERENCED_PARAMETER(status); // disables prefast warning; defensive coding...
3079 
3081  }
3082  else
3083  {
3084  RequestCompletion(deviceExtension, Request, status, dataLength);
3085  }
3086  }
3087 
3088  return processed;
3089 }
3090 
3091 
3092 BOOLEAN
3094  _In_ WDFDEVICE Device,
3095  _In_ WDFREQUEST Request,
3097  )
3098 /*++
3099 Routine Description:
3100 
3101  All unknown requests will be pass to lower level driver.
3102  If IRQL is PASSIVE_LEVEL, the request will be serialized;
3103  Otherwise, it'll be sent and forget.
3104 
3105 Arguments:
3106 
3107  Device - handle to a WDF Device object
3108 
3109  Request - handle to the incoming WDF Request object
3110 
3111  RequestParameters - request parameters
3112 
3113 Return Value:
3114 
3115  BOOLEAN - TRUE (request processed); FALSE (request is not processed in this function).
3116 
3117 --*/
3118 {
3120  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
3121 
3123 
3124  if ((KeGetCurrentIrql() != PASSIVE_LEVEL) ||
3125  (baseCode == FILE_DEVICE_ACPI))
3126  {
3127  // 1. When IRQL is higher than PASSIVE_LEVEL,
3128  // 2. ataport sends IOCTL_ACPI_ASYNC_EVAL_METHOD before queue starts,
3129  // send request directly to lower driver.
3131  }
3132  else
3133  {
3134  // keep the request in serialized manner and stay in user's context.
3136 
3137  if (NT_SUCCESS(status))
3138  {
3140  }
3141  else
3142  {
3143  RequestCompletion(deviceExtension, Request, status, 0);
3144  }
3145  }
3146 
3147  UNREFERENCED_PARAMETER(status); //defensive coding, avoid PREFAST warning.
3148 
3149  // All unknown IOCTLs are processed in this function.
3150  return TRUE; //processed
3151 }
3152 
3153 VOID
3155  _In_ WDFREQUEST Request,
3156  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
3157  )
3158 /*++
3159 Routine Description:
3160 
3161  all internal IOCTL will be send to lower driver asynchronously.
3162 
3163 Arguments:
3164 
3165  Request - handle to the incoming WDF Request object
3166  DeviceExtension - device extension structure
3167 
3168 Return Value:
3169 
3170  None
3171 
3172 --*/
3173 {
3175  PIRP irp = NULL;
3176  PIO_STACK_LOCATION irpStack = NULL;
3177  PIO_STACK_LOCATION nextStack = NULL;
3178  BOOLEAN requestSent = FALSE;
3179 
3180  irp = WdfRequestWdmGetIrp(Request);
3181  irpStack = IoGetCurrentIrpStackLocation(irp);
3182  nextStack = IoGetNextIrpStackLocation(irp);
3183 
3184  // Set the parameters in the next stack location.
3185  nextStack->Parameters.Scsi.Srb = irpStack->Parameters.Scsi.Srb;
3186  nextStack->MajorFunction = IRP_MJ_SCSI;
3187  nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
3188 
3189  WdfRequestSetCompletionRoutine(Request, RequestDummyCompletionRoutine, NULL);
3190 
3191  status = RequestSend(DeviceExtension,
3192  Request,
3193  DeviceExtension->IoTarget,
3194  0,
3195  &requestSent);
3196 
3197  // send the request straight down (asynchronously)
3198  if (!requestSent)
3199  {
3200  // fail the request
3201  RequestCompletion(DeviceExtension, Request, status, WdfRequestGetInformation(Request));
3202  }
3203 
3204  return;
3205 }
3206 
3207 
3208 
3209 //
3210 // Serial I/O Queue Event callbacks
3211 //
3212 
3213 VOID
3214 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3216  _In_ WDFQUEUE Queue,
3217  _In_ WDFREQUEST Request,
3218  _In_ size_t Length
3219  )
3220 /*++
3221 Routine Description:
3222 
3223  validate and process read/write request.
3224 
3225 Arguments:
3226 
3227  Queue - parallel queue itself
3228 
3229  Request - handle to the incoming WDF Request object
3230 
3231  Length - read / write lenght
3232 
3233 Return Value:
3234 
3235  None
3236 
3237 --*/
3238 {
3240  WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3241  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
3242  WDF_REQUEST_PARAMETERS requestParameters;
3243  PIRP wdmIrp = WdfRequestWdmGetIrp(Request);
3244  PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(wdmIrp);
3245  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3246 
3247  // Get the request parameters
3248  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3249  WdfRequestGetParameters(Request, &requestParameters);
3250 
3251  if (requestParameters.Type == WdfRequestTypeRead)
3252  {
3253  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
3254  "Receiving READ, Length %Ix\n", (ULONG) Length));
3255  }
3256  else
3257  {
3258  TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_GENERAL,
3259  "Receiving WRITE, Length %Ix\n", (ULONG) Length));
3260  }
3261 
3262  // Check if a verify is required before a READ/WRITE
3263  if (TEST_FLAG(deviceExtension->DeviceObject->Flags, DO_VERIFY_VOLUME) &&
3264  (requestParameters.MinorFunction != CDROM_VOLUME_VERIFY_CHECKED) &&
3265  !TEST_FLAG(currentIrpStack->Flags, SL_OVERRIDE_VERIFY_VOLUME))
3266  {
3267  // DO_VERIFY_VOLUME is set for the device object,
3268  // but this request is not itself a verify request.
3269  // So fail this request.
3270  RequestCompletion(deviceExtension, Request, STATUS_VERIFY_REQUIRED, 0);
3271  }
3272  else
3273  {
3274  // Since we've bypassed the verify-required tests we don't need to repeat
3275  // them with this IRP - in particular we don't want to worry about
3276  // hitting them at the partition 0 level if the request has come through
3277  // a non-zero partition.
3278  currentIrpStack->MinorFunction = CDROM_VOLUME_VERIFY_CHECKED;
3279 
3280  // Fail READ/WRITE requests when music is playing
3281  if (deviceExtension->DeviceAdditionalData.PlayActive)
3282  {
3283  RequestCompletion(deviceExtension, Request, STATUS_DEVICE_BUSY, 0);
3284 
3285  return;
3286  }
3287 
3288  // Fail READ/WRITE requests from non-owners if the drive is locked
3289  if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
3290  {
3291  RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
3292 
3293  return;
3294  }
3295 
3296  // Succeed READ/WRITE requests of length 0
3297  if (Length == 0)
3298  {
3299  // Several parts of the code turn 0 into 0xffffffff,
3300  // so don't process a zero-length request any further.
3301  RequestCompletion(deviceExtension, Request, STATUS_SUCCESS, Length);
3302 
3303  return;
3304  }
3305 
3306  // If there is an unexpected write request, we want to rediscover MMC capabilities
3307  if (!deviceExtension->DeviceAdditionalData.Mmc.WriteAllowed &&
3308  (requestParameters.Type == WdfRequestTypeWrite))
3309  {
3310  // Schedule MMC capabilities update now, but perform it later in a work item
3312  }
3313 
3314  // If MMC capabilities update is required, we create a separate work item to avoid blocking
3315  // the current thread; otherwise, we initiate an async read/write in the current thread.
3316  if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3317  {
3319  WdfWorkItemEnqueue(deviceExtension->ReadWriteWorkItem);
3320 
3322  }
3323  else
3324  {
3325  status = RequestValidateReadWrite(deviceExtension, Request, requestParameters);
3326 
3327  if (NT_SUCCESS(status))
3328  {
3329  status = RequestHandleReadWrite(deviceExtension, Request, requestParameters);
3330  }
3331  }
3332 
3333  if (!NT_SUCCESS(status))
3334  {
3335  RequestCompletion(deviceExtension, Request, status, 0);
3336  }
3337  }
3338 
3339  return;
3340 }
3341 
3342 
3343 VOID
3344 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3346  _In_ WDFWORKITEM WorkItem
3347  )
3348 /*++
3349 
3350 Routine Description:
3351 
3352  Work item routine for validating and initiating read and write requests.
3353  The reason why we do that from a work item is because we may need to update MMC
3354  capabilities before validating a read/write request and that is a sync operation.
3355 
3356 Arguments:
3357 
3358  WorkItem - WDF work item
3359 
3360 Return Value:
3361 
3362  none
3363 
3364 --*/
3365 {
3366  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3367  WDFREQUEST readWriteRequest = NULL;
3368  WDF_REQUEST_PARAMETERS readWriteRequestParameters;
3370 
3371  PAGED_CODE ();
3372 
3373  deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION);
3374  readWriteRequest = deviceExtension->ReadWriteWorkItemContext.OriginalRequest;
3375  deviceExtension->ReadWriteWorkItemContext.OriginalRequest = NULL;
3376 
3377  WDF_REQUEST_PARAMETERS_INIT(&readWriteRequestParameters);
3378  WdfRequestGetParameters(readWriteRequest, &readWriteRequestParameters);
3379 
3380  if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3381  {
3382  // Issue command to update the drive capabilities.
3383  // The failure of MMC update is not considered critical, so we'll
3384  // continue to process the request even if MMC update fails.
3385  (VOID) DeviceUpdateMmcCapabilities(deviceExtension->Device);
3386  }
3387 
3388  // Now verify and process the request
3389  if (NT_SUCCESS(status))
3390  {
3391  status = RequestValidateReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters);
3392  }
3393  if (NT_SUCCESS(status))
3394  {
3395  status = RequestHandleReadWrite(deviceExtension, readWriteRequest, readWriteRequestParameters);
3396  }
3397 
3398  // Complete the request immediately on failure
3399  if (!NT_SUCCESS(status))
3400  {
3401  RequestCompletion(deviceExtension, readWriteRequest, status, 0);
3402  }
3403 }
3404 
3405 
3406 VOID
3407 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3409  _In_ WDFQUEUE Queue,
3410  _In_ WDFREQUEST Request,
3411  _In_ size_t OutputBufferLength,
3412  _In_ size_t InputBufferLength,
3414  )
3415 /*++
3416 Routine Description:
3417 
3418  validate and process IOCTL request.
3419 
3420 Arguments:
3421 
3422  Queue - sequential queue
3423 
3424  Request - handle to the incoming WDF Request object
3425 
3426 Return Value:
3427 
3428  None
3429 
3430 --*/
3431 {
3433  WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3434  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(device);
3435  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3436  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3437  WDF_REQUEST_PARAMETERS requestParameters;
3438 
3442 
3443  // get the request parameters
3444  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3445  WdfRequestGetParameters(Request, &requestParameters);
3446 
3447  // If the device is in exclusive mode, check whether the request is from
3448  // the handle that locked the device
3449  if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
3450  {
3451  BOOLEAN isBlocked = FALSE;
3452 
3454  if (NT_SUCCESS(status) && isBlocked)
3455  {
3456  if (requestContext->SyncRequired)
3457  {
3458  // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request.
3459  // this function will wait for the request process finishes.
3460  KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3461  }
3462  else
3463  {
3464  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3465  "DeviceEvtIoInCallerContext: Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
3466  requestParameters.Parameters.DeviceIoControl.IoControlCode));
3467  RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
3468  }
3469 
3470  return;
3471  }
3472  }
3473 
3474  if (!cdData->Mmc.WriteAllowed &&
3475  ((requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_IS_WRITABLE) ||
3476  (requestParameters.Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_VERIFY)))
3477  {
3479  }
3480 
3481  // check if this is a synchronized ioctl
3482  if (requestContext->SyncRequired)
3483  {
3484  // set the following event, so RequestSynchronizeProcessWithSerialQueue() can contintue run to process the real request.
3485  // this function will wait for the request process finishes.
3486  KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3487  }
3488  else
3489  {
3490  deviceExtension->IoctlWorkItemContext.OriginalRequest = Request;
3491 
3492  // all other IOCTL processing is currently processed via a
3493  // work item running at PASSIVE_LEVEL.
3494  WdfWorkItemEnqueue(deviceExtension->IoctlWorkItem);
3495  }
3496 
3497  return;
3498 }
3499 
3500 
3501 VOID
3502 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3504  _In_ WDFWORKITEM WorkItem
3505  )
3506 /*++
3507 
3508 Routine Description:
3509 
3510  Work item routine for processing ioctl requests.
3511  This is needed because event callbacks are called at DISPATCH_LEVEL and ioctl
3512  requests are currently processed synchronously and not asynchronously.
3513 
3514 Arguments:
3515 
3516  WorkItem - WDF work item
3517 
3518 Return Value:
3519 
3520  none
3521 
3522 --*/
3523 {
3524  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3525 
3526  PAGED_CODE ();
3527 
3528  deviceExtension = WdfObjectGetTypedContext(WdfWorkItemGetParentObject(WorkItem), CDROM_DEVICE_EXTENSION);
3529 
3530  if (DeviceIsMmcUpdateRequired(deviceExtension->Device))
3531  {
3532  // Issue command to update the drive capabilities.
3533  // The failure of MMC update is not considered critical,
3534  // so that we'll continue to process I/O even MMC update fails.
3535  DeviceUpdateMmcCapabilities(deviceExtension->Device);
3536  }
3537 
3538  RequestProcessSerializedIoctl(deviceExtension, deviceExtension->IoctlWorkItemContext.OriginalRequest);
3539 }
3540 
3541 
3543 NTSTATUS
3544 RequestProcessSerializedIoctl(
3545  _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3546  _In_ WDFREQUEST Request
3547  )
3548 /*++
3549 Routine Description:
3550 
3551  a dispatch routine for all functions to process IOCTLs.
3552 
3553 Arguments:
3554 
3555  DeviceExtension - device context
3556 
3557  Request - handle to the incoming WDF Request object
3558 
3559 Return Value:
3560 
3561  NTSTATUS
3562 
3563 --*/
3564 {
3566  size_t information = 0;
3567  WDF_REQUEST_PARAMETERS requestParameters;
3568  BOOLEAN completeRequest = TRUE;
3569 
3570  PAGED_CODE ();
3571 
3572  // Get the Request parameters
3573  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
3574  WdfRequestGetParameters(Request, &requestParameters);
3575 
3576  NormalizeIoctl(&requestParameters);
3577 
3578  // process IOCTLs
3579  switch (requestParameters.Parameters.DeviceIoControl.IoControlCode)
3580  {
3581  case IOCTL_CDROM_READ_TOC:
3583  status = RequestHandleReadTOC(DeviceExtension, Request, requestParameters, &information);
3584  break;
3585 
3587  status = RequestHandleReadTocEx(DeviceExtension, Request, requestParameters, &information);
3588  break;
3589 
3591  status = RequestHandleGetConfiguration(DeviceExtension, Request, requestParameters, &information);
3592  break;
3593 
3594  case IOCTL_CDROM_RAW_READ:
3595  status = DeviceHandleRawRead(DeviceExtension, Request, requestParameters, &information);
3596  break;
3597 
3604  status = RequestHandleGetDriveGeometry(DeviceExtension, Request, requestParameters, &information);
3605  break;
3606 
3607  case IOCTL_DISK_VERIFY:
3608  status = RequestHandleDiskVerify(DeviceExtension, Request, requestParameters, &information);
3609  break;
3610 
3612  // IOCTL_STORAGE_CHECK_VERIFY2 was processed including send a Test Unit Read
3613  // with srb flag SRB_CLASS_FLAGS_LOW_PRIORITY to port driver asynchronizelly.
3614  // The original request was completed after TUR finishes.
3615  // As CDROM.SYS serializes IOs need accessing device, it's not a big difference from above behavior to
3616  // just process it in serialized manner. So I put it here and treat it as same as IOCTL_STORAGE_CHECK_VERIFY.
3618  status = RequestHandleCheckVerify(DeviceExtension, Request, requestParameters, &information);
3619  break;
3620 
3625  status = RequestHandleFakePartitionInfo(DeviceExtension, Request, requestParameters, &information);
3626  break;
3627 
3629  //
3630  // Even though this media is writable, the requester of this IOCTL really
3631  // wants to know if thw media behaves like any other disk or not. This is
3632  // so if FeatureDefectManagement and FeatureRandomWritable are current on
3633  // the drive-represented by the FeatureDefectManagement validation schema
3634  //
3635  if (DeviceExtension->DeviceAdditionalData.Mmc.WriteAllowed &&
3636  (DeviceExtension->DeviceAdditionalData.Mmc.ValidationSchema == FeatureDefectManagement))
3637  {
3639  }
3640  else
3641  {
3643  }
3644  information = 0;
3645  break;
3646 
3648  status = DeviceHandlePlayAudioMsf(DeviceExtension, Request, requestParameters, &information);
3649  break;
3650 
3652  status = DeviceHandleReadQChannel(DeviceExtension, Request, requestParameters, &information);
3653  break;
3654 
3656  status = DeviceHandlePauseAudio(DeviceExtension, Request, &information);
3657  break;
3658 
3660  status = DeviceHandleResumeAudio(DeviceExtension, Request, &information);
3661  break;
3662 
3664  status = DeviceHandleSeekAudioMsf(DeviceExtension, Request, requestParameters, &information);
3665  break;
3666 
3668  status = DeviceHandleStopAudio(DeviceExtension, Request, &information);
3669  break;
3670 
3673  status = DeviceHandleGetSetVolume(DeviceExtension, Request, requestParameters, &information);
3674  break;
3675 
3676  case IOCTL_DVD_GET_REGION:
3677  status = RequestHandleGetDvdRegion(DeviceExtension, Request, &information);
3678  break;
3679 
3681  status = DeviceHandleReadDvdStructure(DeviceExtension, Request, requestParameters, &information);
3682  break;
3683 
3684  case IOCTL_DVD_END_SESSION:
3685  status = DeviceHandleDvdEndSession(DeviceExtension, Request, requestParameters, &information);
3686  break;
3687 
3689  case IOCTL_DVD_READ_KEY:
3690  status = DeviceHandleDvdStartSessionReadKey(DeviceExtension, Request, requestParameters, &information);
3691  break;
3692 
3693  case IOCTL_DVD_SEND_KEY:
3694  case IOCTL_DVD_SEND_KEY2:
3695  status = DeviceHandleDvdSendKey(DeviceExtension, Request, requestParameters, &information);
3696  break;
3697 
3699  status = DeviceHandleSetReadAhead(DeviceExtension, Request, requestParameters, &information);
3700  break;
3701 
3702  case IOCTL_CDROM_SET_SPEED:
3703  status = DeviceHandleSetSpeed(DeviceExtension, Request, requestParameters, &information);
3704  break;
3705 
3708  status = DeviceHandleAacsReadMediaKeyBlock(DeviceExtension, Request, requestParameters, &information);
3709  break;
3710 
3712  status = DeviceHandleAacsStartSession(DeviceExtension, Request, requestParameters, &information);
3713  break;
3714 
3716  status = DeviceHandleAacsEndSession(DeviceExtension, Request, requestParameters, &information);
3717  break;
3718 
3720  status = DeviceHandleAacsSendCertificate(DeviceExtension, Request, requestParameters, &information);
3721  break;
3722 
3724  status = DeviceHandleAacsGetCertificate(DeviceExtension, Request, requestParameters, &information);
3725  break;
3726 
3728  status = DeviceHandleAacsGetChallengeKey(DeviceExtension, Request, requestParameters, &information);
3729  break;
3730 
3732  status = DeviceHandleSendChallengeKey(DeviceExtension, Request, requestParameters, &information);
3733  break;
3734 
3736  status = DeviceHandleReadVolumeId(DeviceExtension, Request, requestParameters, &information);
3737  break;
3738 
3740  status = DeviceHandleAacsReadSerialNumber(DeviceExtension, Request, requestParameters, &information);
3741  break;
3742 
3744  status = DeviceHandleAacsReadMediaId(DeviceExtension, Request, requestParameters, &information);
3745  break;
3746 
3748  status = DeviceHandleAacsReadBindingNonce(DeviceExtension, Request, requestParameters, &information);
3749  break;
3750 
3752  status = DeviceHandleAacsGenerateBindingNonce(DeviceExtension, Request, requestParameters, &information);
3753  break;
3754 
3756  status = RequestHandleEnableStreaming(DeviceExtension, Request, &information);
3757  break;
3758 
3760  status = RequestHandleSendOpcInformation(DeviceExtension, Request, &information);
3761  break;
3762 
3764  status = RequestHandleGetPerformance(DeviceExtension, Request, requestParameters, &information);
3765  break;
3766 
3767  // This IOCTL is a fake one, used for MCN process sync-ed with serial queue.
3769  status = RequestHandleMcnSyncFakeIoctl(DeviceExtension, &information);
3770  break;
3771 
3774  {
3775  status = RequestHandleEjectionControl(DeviceExtension, Request, requestParameters, &information);
3776 
3777  break;
3778  }
3779 
3783  {
3784  status = RequestHandleLoadEjectMedia(DeviceExtension, Request, requestParameters, &information);
3785 
3786  break;
3787  }
3788 
3790  {
3791  status = RequestHandleMcnControl(DeviceExtension, Request, &information);
3792 
3793  break;
3794  }
3795 
3796  case IOCTL_STORAGE_RESERVE:
3797  case IOCTL_STORAGE_RELEASE:
3798  {
3799  status = RequestHandleReserveRelease(DeviceExtension, Request, requestParameters, &information);
3800 
3801  break;
3802  }
3803 
3806  {
3807  status = RequestHandlePersistentReserve(DeviceExtension, Request, requestParameters, &information);
3808 
3809  break;
3810  }
3811 
3812 #if (NTDDI_VERSION >= NTDDI_WIN8)
3814  {
3815  status = RequestHandleAreVolumesReady(DeviceExtension, Request, requestParameters, &information);
3816 
3817  completeRequest = FALSE;
3818 
3819  break;
3820  }
3821 
3822  case IOCTL_VOLUME_ONLINE:
3824  {
3825  status = RequestHandleVolumeOnline(DeviceExtension, Request, requestParameters, &information);
3826 
3827  break;
3828  }
3829 #endif
3830 
3831  default:
3832  {
3834  break;
3835  }
3836  } // end of switch(ioctl)
3837 
3838  if (completeRequest)
3839  {
3840  RequestCompletion(DeviceExtension, Request, status, information);
3841  }
3842 
3843  return status;
3844 }
3845 
3846 VOID
3847 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3849  _In_ WDFQUEUE Queue,
3850  _In_ WDFREQUEST Request
3851  )
3852 /*++
3853 Routine Description:
3854 
3855  Perform cancellation when request is still in queue.
3856 
3857  If request is sych-ed in another thread, signal the event to let that thread be able to complete the request.
3858  Otherwise, complete the request.
3859 
3860 Arguments:
3861 
3862  Queue - serial queue
3863  Request - handle to the incoming WDF Request object
3864 
3865 Return Value:
3866 
3867  None
3868 
3869 --*/
3870 {
3871  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3872 
3873  if (requestContext->SyncRequired)
3874  {
3875  KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3876  }
3877  else
3878  {
3879  PCDROM_DEVICE_EXTENSION deviceExtension = NULL;
3880  WDFDEVICE device = WdfIoQueueGetDevice(Queue);
3881 
3882  deviceExtension = DeviceGetExtension(device);
3883 
3884  RequestCompletion(deviceExtension, Request, STATUS_CANCELLED, 0);
3885 
3886  }
3887 
3888  return;
3889 }
3890 
3891 
3892 NTSTATUS
3894  _In_ WDFDEVICE Device,
3895  _In_ WDFREQUEST Request
3896  )
3897 /*++
3898 Routine Description:
3899 
3900  This is the mechanism to sync a request process in original thread with serialize queue.
3901  initialize a EVENT and put the request inot serialize queue;
3902  waiting for serialize queue processes to this request and signal the EVENT;
3903  call the request handler to process this request.
3904 
3905 Arguments:
3906 
3907  DeviceExtension - device context
3908 
3909  Request - handle to the incoming WDF Request object
3910 
3911 Return Value:
3912 
3913  NTSTATUS
3914 
3915 --*/
3916 {
3918  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
3919  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(Request);
3920  PKEVENT bufferToFree = requestContext->SyncEvent;
3921 
3922  if (KeGetCurrentIrql() >= DISPATCH_LEVEL) {
3923  // cannot block at or above DISPATCH_LEVEL
3924  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3925  "RequestSynchronousProcessWithSerialQueue called at DISPATCH_LEVEL or above"));
3926  NT_ASSERT(FALSE);
3927  RequestCompletion(deviceExtension, Request, STATUS_INVALID_LEVEL, 0);
3928  return STATUS_INVALID_LEVEL;
3929  }
3930 
3931  // init the synchronization event
3933 
3934  // do we still need to do something like this?
3935  // SET_FLAG(nextStack->Flags, SL_OVERRIDE_VERIFY_VOLUME);
3936 
3937  // NOTE: this mechanism relies on that KMDF will not complete request by itself.
3938  // Doing that will cause the syncEvent not fired thus this thread will stuck.
3939  // This should not really happen: our EvtCanceledOnQueue callbacks should be
3940  // called even if queues are purged for some reason. The only case when these
3941  // callbacks are not called is when a request is owned by the driver (i.e. has
3942  // already been passed to one of the registered handlers). In this case, it is
3943  // our responsibility to cancel such requests properly.
3944  status = WdfDeviceEnqueueRequest(Device, Request);
3945 
3946  if (!NT_SUCCESS(status))
3947  {
3948  // Failed to forward request! Pretend the sync event already occured, otherwise we'll hit
3949  // an assert in RequestEvtCleanup.
3950  KeSetEvent(requestContext->SyncEvent, IO_CD_ROM_INCREMENT, FALSE);
3951  RequestCompletion(deviceExtension, Request, status, WdfRequestGetInformation(Request));
3952  }
3953  else
3954  {
3955  NTSTATUS waitStatus = STATUS_UNSUCCESSFUL;
3956  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
3957  BOOLEAN fCallSyncCallback = FALSE;
3958  PIRP irp = WdfRequestWdmGetIrp(Request);
3959 
3960  // ok, now wait on the event
3961  while (waitStatus != STATUS_SUCCESS)
3962  {
3963  waitStatus = KeWaitForSingleObject(requestContext->SyncEvent, Executive, KernelMode, TRUE, NULL);
3964  if (waitStatus == STATUS_SUCCESS) // must check equality -- STATUS_ALERTED is success code
3965  {
3966  // do nothing
3967  }
3968  else if (waitStatus != STATUS_ALERTED)
3969  {
3970  // do nothing
3971  TracePrint((TRACE_LEVEL_FATAL, TRACE_FLAG_IOCTL,
3972  "Request %p on device object %p had a non-alert, non-success result from wait (%!HRESULT!)\n",
3973  Request, Device, waitStatus));
3974  NT_ASSERT(FALSE);
3975  }
3977  {
3978  // the thread was alerted and is terminating, so cancel the irp
3979  // this will cause EvtIoCanceledOnQueue to be called, which will signal the event,
3980  // so we will get out of the while loop and eventually complete the request.
3981  if (IoCancelIrp(irp))
3982  {
3983  // cancellation routine was called
3984  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3985  "Sychronize Ioctl: request %p cancelled from device %p\n",
3986  Request, Device));
3987  }
3988  else
3989  {
3990  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3991  "Sychronize Ioctl: request %p could not be cancelled from device %p\n",
3992  Request, Device));
3993  }
3994  }
3995  else
3996  {
3997  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_IOCTL,
3998  "SPURIOUS ALERT waiting for Request %p on device %p (%!STATUS!)\n",
3999  Request, Device, status));
4000  }
4001  } // end of wait loop on the event
4002 
4003  // because we've waited an unknown amount of time, should check
4004  // the cancelled flag to immediately fail the irp as appropriate
4005  if (WdfRequestIsCanceled(Request))
4006  {
4007  // the request was cancelled, thus we should always stop
4008  // processing here if possible.
4010  RequestCompletion(deviceExtension, Request, status, 0);
4011  }
4012  else if (EXCLUSIVE_MODE(cdData) && !EXCLUSIVE_OWNER(cdData, WdfRequestGetFileObject(Request)))
4013  {
4014  WDF_REQUEST_PARAMETERS requestParameters;
4015  BOOLEAN isBlocked = FALSE;
4016 
4017  // get the request parameters
4018  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
4019  WdfRequestGetParameters(Request, &requestParameters);
4020 
4022  if (isBlocked)
4023  {
4024  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
4025  "Access Denied! Device in exclusive mode.Failing Ioctl %lx\n",
4026  requestParameters.Parameters.DeviceIoControl.IoControlCode));
4027  RequestCompletion(deviceExtension, Request, STATUS_ACCESS_DENIED, 0);
4028  }
4029  else
4030  {
4031  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL,
4032  "Ioctl %lx not blocked by cdrom being in exclusive mode\n",
4033  requestParameters.Parameters.DeviceIoControl.IoControlCode));
4034  fCallSyncCallback = TRUE;
4035  }
4036  }
4037  else
4038  {
4039  fCallSyncCallback = TRUE;
4040  }
4041 
4042  if (fCallSyncCallback)
4043  {
4044  // Synchronization completed successfully. Call the requested routine
4045  status = requestContext->SyncCallback(Device, Request);
4046  }
4047  }
4048 
4049  // The next SequentialQueue evt routine will not be triggered until the current request is completed.
4050 
4051  // clean up the request context setting.
4052  FREE_POOL(bufferToFree);
4053 
4054  return status;
4055 }
4056 
4057 NTSTATUS
4059  _In_ WDFREQUEST Request,
4060  _Out_ PBOOLEAN IsBlocked
4061  )
4062 /*++
4063 Routine Description:
4064 
4065  Check if the IOCTL request should be blocked or not according to
4066  the exclusive lock stat.
4067 
4068 Arguments:
4069 
4070  Request - handle to the incoming WDF Request object
4071 
4072 Return Value:
4073 
4074  NTSTATUS
4075 
4076  IsBlocked - TRUE (be blocked); FALSE (not blocked)
4077 
4078 --*/
4079 {
4081  ULONG ioctlCode = 0;
4082  ULONG baseCode = 0;
4083  WDF_REQUEST_PARAMETERS requestParameters;
4084 
4085  // Get the Request parameters
4086  WDF_REQUEST_PARAMETERS_INIT(&requestParameters);
4087  WdfRequestGetParameters(Request, &requestParameters);
4088 
4089  // check and initialize parameter
4090  if (IsBlocked == NULL)
4091  {
4092  //This is an internal function and this parameter must be supplied.
4093  NT_ASSERT(FALSE);
4094 
4095  return STATUS_INVALID_PARAMETER;
4096  }
4097  else
4098  {
4099  *IsBlocked = FALSE;
4100  }
4101 
4102  // check if this is an IOCTL
4103  if ((requestParameters.Type == WdfRequestTypeDeviceControl) ||
4104  (requestParameters.Type == WdfRequestTypeDeviceControlInternal))
4105  {
4106  //
4107  // Allow minimum set of commands that are required for the disk manager
4108  // to show the CD device, while in exclusive mode.
4109  // Note: These commands should not generate any requests to the device,
4110  // and thus must be handled directly in StartIO during exclusive
4111  // access (except for the exclusive owner, of course).
4112  //
4113  ioctlCode = requestParameters.Parameters.DeviceIoControl.IoControlCode;
4114  baseCode = DEVICE_TYPE_FROM_CTL_CODE(ioctlCode);
4115 
4116  if (ioctlCode == IOCTL_SCSI_GET_ADDRESS ||
4117  ioctlCode == IOCTL_STORAGE_GET_HOTPLUG_INFO ||
4118  ioctlCode == IOCTL_STORAGE_GET_DEVICE_NUMBER ||
4119  ioctlCode == IOCTL_STORAGE_GET_MEDIA_TYPES_EX ||
4120  ioctlCode == IOCTL_CDROM_EXCLUSIVE_ACCESS ||
4121  ioctlCode == IOCTL_CDROM_GET_INQUIRY_DATA
4122  )
4123  {
4124  *IsBlocked = FALSE;
4125  }
4126 
4127  //
4128  // Handle IOCTL_STORAGE_QUERY_PROPERTY special because:
4129  // (1) PropertyExistsQuery should not generate device i/o
4130  // (2) Queries for StorageDeviceProperty and StorageAdapterDescriptor
4131  // will return cache'd data
4132  else if (ioctlCode == IOCTL_STORAGE_QUERY_PROPERTY)
4133  {
4135  status = WdfRequestRetrieveInputBuffer(Request,
4136  requestParameters.Parameters.DeviceIoControl.InputBufferLength,
4137  (PVOID*)&query,
4138  NULL);
4139 
4140  if (NT_SUCCESS(status))
4141  {
4142  if (query != NULL)
4143  {
4144  if (query->QueryType == PropertyExistsQuery)
4145  {
4146  *IsBlocked = FALSE;
4147  }
4148  else if ((query->QueryType == PropertyStandardQuery) &&
4149  ((query->PropertyId == StorageDeviceProperty) ||
4150  (query->PropertyId == StorageAdapterProperty)))
4151  {
4152  *IsBlocked = FALSE;
4153  }
4154  }
4155  }
4156  }
4157 
4158  // Return TRUE for unknown IOCTLs with STORAGE bases
4159  else if (baseCode == IOCTL_SCSI_BASE ||
4160  baseCode == IOCTL_DISK_BASE ||
4161  baseCode == IOCTL_CDROM_BASE ||
4162  baseCode == IOCTL_STORAGE_BASE ||
4163  baseCode == IOCTL_DVD_BASE )
4164  {
4165  *IsBlocked = TRUE;
4166  }
4167  }
4168  else
4169  {
4170  // this should only be called with an IOCTL
4171  NT_ASSERT(FALSE);
4172 
4174  }
4175 
4176  return status;
4177 }
4178 
4179 BOOLEAN
4181  _In_ WDFDEVICE Device
4182  )
4183 /*++
4184 Routine Description:
4185 
4186  Check if the device needs to update its MMC information.
4187 
4188 Arguments:
4189 
4190  Device - device to be checked.
4191 
4192 Return Value:
4193 
4194  TRUE (require update); FALSE (not require update)
4195 
4196 --*/
4197 {
4198  PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
4199  PCDROM_DATA cdData = &(deviceExtension->DeviceAdditionalData);
4200 
4201  if ((cdData->Mmc.IsMmc) &&
4202  (cdData->Mmc.UpdateState == CdromMmcUpdateRequired))
4203  {
4204  return TRUE;
4205  }
4206  else
4207  {
4208  // no update required: just proceed
4209  return FALSE;
4210  }
4211 }
4212 
4213 VOID
4214 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4217  )
4218 /*++
4219 Routine Description:
4220 
4221  Request cleanup callback.
4222 
4223 Arguments:
4224 
4225  Request - request to clean up.
4226 
4227 Return Value:
4228 
4229  None
4230 
4231 --*/
4232 {
4233  WDFREQUEST request = (WDFREQUEST)Request;
4234  PCDROM_REQUEST_CONTEXT requestContext = RequestGetContext(request);
4235 
4236  if (requestContext->SyncRequired)
4237  {
4238  // the event should have been signaled, just check that
4239  NT_ASSERT(KeReadStateEvent(requestContext->SyncEvent) != 0);
4240  }
4241 }
4242 
PFN_WDF_IO_QUEUE_IO_READ EvtIoRead
Definition: wdfio.h:401
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
NTSTATUS RequestValidateReadToc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:984
NTSTATUS RequestSynchronizeProcessWithSerialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: cdrom.c:3893
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_STORAGE_MCN_CONTROL
Definition: ntddstor.h:128
WDF_TRI_STATE AutoForwardCleanupClose
Definition: wdfdevice.h:612
#define IOCTL_STORAGE_SET_READ_AHEAD
Definition: cdrw_usr.h:186
PCDROM_DRIVER_EXTENSION DriverExtension
Definition: cdrom.h:490
PFN_WDF_DEVICE_SURPRISE_REMOVAL EvtDeviceSurpriseRemoval
Definition: wdfdevice.h:1175
#define IOCTL_DISK_BASE
Definition: ntdddisk.h:44
NTSTATUS RequestValidateDvdReadKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3286
return STATUS_NOT_SUPPORTED
#define STATUS_NO_MEDIA_IN_DEVICE
Definition: udferr_usr.h:141
#define INVALID_SESSION
Definition: cdromp.h:381
FORCEINLINE UCHAR RequestGetCurrentStackLocationFlags(_In_ WDFREQUEST Request)
Definition: cdrom.h:1554
#define WINPE_REG_KEY_NAME
Definition: cdromp.h:127
UNICODE_STRING WellKnownName
Definition: cdrom.h:357
VOID NTAPI DriverEvtCleanup(_In_ WDFOBJECT Driver)
Definition: cdrom.c:202
NTSTATUS RequestHandleSetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5392
#define IOCTL_CDROM_BASE
Definition: vcdcli.c:21
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
FORCEINLINE VOID WDF_IO_TARGET_OPEN_PARAMS_INIT_EXISTING_DEVICE(_Out_ PWDF_IO_TARGET_OPEN_PARAMS Params, _In_ PDEVICE_OBJECT DeviceObject)
Definition: wdfiotarget.h:287
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
NTSTATUS RequestHandleReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6353
NTSTATUS RequestHandleMountQuerySuggestedLinkName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4088
VOID RequestSetReceivedTime(_In_ WDFREQUEST Request)
Definition: common.c:64
NTSTATUS RequestValidateGetConfiguration(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1364
BOOLEAN RetryFirstCommand
Definition: cdromp.h:273
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
struct config_s config
VOID NTAPI ReadWriteWorkItemRoutine(_In_ WDFWORKITEM WorkItem)
Definition: cdrom.c:3345
FORCEINLINE VOID WDF_WORKITEM_CONFIG_INIT(_Out_ PWDF_WORKITEM_CONFIG Config, _In_ PFN_WDF_WORKITEM EvtWorkItemFunc)
Definition: wdfworkitem.h:85
NTSTATUS DeviceZPODDGetPowerupReason(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason)
Definition: zpodd.c:608
#define IOCTL_STORAGE_SET_HOTPLUG_INFO
Definition: ntddstor.h:157
struct _CDROM_DEVICE_EXTENSION CDROM_DEVICE_EXTENSION
Definition: cdrom.h:216
#define _Inout_
Definition: ms_sal.h:378
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
UCHAR Cdb[16]
Definition: srb.h:271
VOID NTAPI DeviceEvtCleanup(_In_ WDFOBJECT Device)
Definition: cdrom.c:856
BOOLEAN IsInitialized
Definition: cdrom.h:464
#define IRP_MJ_FLUSH_BUFFERS
WDFREQUEST OriginalRequest
Definition: cdrom.h:328
NTSTATUS RequestValidateAacsGetCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1757
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
#define CDROM_VOLUME_VERIFY_CHECKED
Definition: cdromp.h:171
BOOLEAN WriteAllowed
Definition: cdrom.h:250
#define _Out_
Definition: ms_sal.h:345
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
#define IRP_MJ_SHUTDOWN
PCDROM_PRIVATE_FDO_DATA PrivateFdoData
Definition: cdrom.h:605
#define KEY_READ
Definition: nt_native.h:1023
BOOLEAN RequestDispatchSpecialIoctls(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2849
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
WDFWORKITEM ReadWriteWorkItem
Definition: cdrom.h:608
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2221
#define IOCTL_AACS_GET_CERTIFICATE
Definition: ntddcdvd.h:73
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
WDFQUEUE ManualVolumeReadyQueue
Definition: cdrom.h:591
WDFIOTARGET IoTarget
Definition: cdrom.h:476
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN SyncRequired
Definition: cdrom.h:643
#define IOCTL_TAPE_BASE
Definition: ntddtape.h:35
#define IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
Definition: ntddstor.h:172
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:213
#define WRITE_RETRY_DELAY_DVD_1x
Definition: cdrom.h:118
WDF_REQUEST_TYPE Type
Definition: wdfrequest.h:142
#define IOCTL_AACS_START_SESSION
Definition: ntddcdvd.h:64
NTSTATUS RequestValidateDvdStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1225
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
NTSTATUS RequestHandleGetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5337
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
NTSTATUS RequestSend(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDFIOTARGET IoTarget, _In_ ULONG Flags, _Out_opt_ PBOOLEAN RequestSent)
Definition: common.c:3793
#define IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT
Definition: ntddstor.h:196
UCHAR CdbLength
Definition: srb.h:250
#define CDROM_SPECIAL_DISABLE_SPIN_DOWN
Definition: cdrom.h:149
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:443
#define BECOMING_READY_RETRY_COUNT
Definition: cdromp.h:261
BOOLEAN InZeroPowerState
Definition: cdromp.h:272
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG McnDisableCount
Definition: cdromp.h:367
#define IOCTL_AACS_GENERATE_BINDING_NONCE
Definition: ntddcdvd.h:94
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:318
uint16_t * PWCHAR
Definition: typedefs.h:56
CDROM_READ_WRITE_CONTEXT ReadWriteWorkItemContext
Definition: cdrom.h:609
BOOLEAN RequestDispatchProcessDirectly(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1694
PDEVICE_OBJECT LowerPdo
Definition: cdrom.h:496
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
struct _PARTITION_INFORMATION PARTITION_INFORMATION
#define STATUS_ALERTED
Definition: ntstatus.h:80
BOOLEAN SurpriseRemoved
Definition: cdrom.h:470
WDFQUEUE CreateQueue
Definition: cdrom.h:483
ULONG TimeOutValue
Definition: srb.h:254
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
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
NTSTATUS RequestValidateAacsGetChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1826
VOID RequestProcessInternalDeviceControl(_In_ WDFREQUEST Request, _In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: cdrom.c:3154
STORAGE_POWERUP_REASON_TYPE PowerupReason
Definition: ntddstor.h:1102
PSYNC_HANDLER SyncCallback
Definition: cdrom.h:645
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine
Definition: cdrom.h:1608
#define IOCTL_AACS_READ_MEDIA_ID
Definition: ntddcdvd.h:88
BOOLEAN DeviceIsMmcUpdateRequired(_In_ WDFDEVICE Device)
Definition: cdrom.c:4180
PFN_WDF_DEVICE_SELF_MANAGED_IO_INIT EvtDeviceSelfManagedIoInit
Definition: wdfdevice.h:1172
NTSTATUS RequestSetContextFields(_In_ WDFREQUEST Request, _In_ PSYNC_HANDLER Handler)
Definition: common.c:2748
NTSTATUS RequestValidateGetLastSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1029
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSTATUS RequestValidateReadQChannel(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1072
#define WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(_attributes, _contexttype)
Definition: wdfobject.h:170
DEVICE_TYPE DeviceType
Definition: cdrom.h:499
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
Definition: ntddcdrm.h:76
#define IOCTL_CDROM_RAW_READ
Definition: ntddcdrm.h:67
VOID NormalizeIoctl(_Inout_ PWDF_REQUEST_PARAMETERS requestParameters)
Definition: cdrom.c:1514
NTSTATUS NTAPI DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
Definition: cdrom.c:75
#define IOCTL_CDROM_SET_VOLUME
Definition: ntddcdrm.h:55
FxDevice * device
ULONG ScanForSpecialFlags
Definition: cdrom.h:512
NTSTATUS RequestValidateAacsReadMediaKeyBlock(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1584
#define IRP_MJ_SCSI
VOID NTAPI DeviceEvtIoInCallerContext(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: cdrom.c:1554
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
WDF_EXECUTION_LEVEL ExecutionLevel
Definition: wdfobject.h:120
BOOLEAN EnforceStreamingRead
Definition: cdromp.h:368
NTSTATUS RequestValidateReadTocEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:887
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
NTSTATUS RequestValidateEnableStreaming(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3515
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:318
#define IOCTL_STORAGE_FIND_NEW_DEVICES
Definition: ntddstor.h:122
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:93
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
NTSTATUS RequestValidateDvdReadStructure(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1151
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:80
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
NTSTATUS RequestValidateDvdEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3408
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
FORCEINLINE VOID WDF_DRIVER_CONFIG_INIT(_Out_ PWDF_DRIVER_CONFIG Config, _In_opt_ PFN_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd)
Definition: wdfdriver.h:148
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
union _WDF_REQUEST_PARAMETERS::@3634 Parameters
VOID NTAPI DeviceEvtFileClose(_In_ WDFFILEOBJECT FileObject)
Definition: cdrom.c:1327
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
Definition: devices.h:37
#define IOCTL_DISK_VERIFY
Definition: cdrw_usr.h:170
CDROM_IOCTL_CONTEXT IoctlWorkItemContext
Definition: cdrom.h:614
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
WDFREQUEST OriginalRequest
Definition: cdrom.h:335
BOOLEAN RequestDispatchSyncWithSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2717
struct _WDF_REQUEST_PARAMETERS::@3634::@3639 Others
#define IOCTL_CDROM_STOP_AUDIO
Definition: ntddcdrm.h:40
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
struct _GET_LENGTH_INFORMATION GET_LENGTH_INFORMATION
#define IOCTL_STORAGE_RELEASE
Definition: ntddstor.h:119
_In_ PFILE_OBJECT_CONTEXT FileObjectContext
Definition: cdrom.h:1212
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IOCTL_CDROM_SEEK_AUDIO_MSF
Definition: ntddcdrm.h:37
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
union _CDROM_POWER_CONTEXT::@994 PowerChangeState
unsigned char BOOLEAN
NTSTATUS RequestValidateSendOpcInformation(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3576
NTSTATUS RequestValidateExclusiveAccess(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2240
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
Definition: ntddcdvd.h:58
NTSTATUS RequestHandleUnknownIoctl(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
NTSTATUS RequestHandleQueryPropertyDeviceUniqueId(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2799
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:62
union _CDB * PCDB
#define IOCTL_CDROM_PLAY_AUDIO_MSF
Definition: ntddcdrm.h:52
#define _In_
Definition: ms_sal.h:308
NTSTATUS RequestHandleGetDeviceNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5280
#define IOCTL_DVD_END_SESSION
Definition: cdrw_usr.h:162
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_CDROM_ENABLE_STREAMING
Definition: ntddcdrm.h:94
BOOLEAN PlayActive
Definition: cdrom.h:351
WDFDEVICE DeviceObject
Definition: cdromp.h:365
VOID NTAPI IoctlWorkItemRoutine(_In_ WDFWORKITEM WorkItem)
Definition: cdrom.c:3503
#define WDF_NO_CONTEXT
Definition: wdftypes.h:108
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
FORCEINLINE VOID WDF_FILEOBJECT_CONFIG_INIT(_Out_ PWDF_FILEOBJECT_CONFIG FileEventCallbacks, _In_opt_ PFN_WDF_DEVICE_FILE_CREATE EvtDeviceFileCreate, _In_opt_ PFN_WDF_FILE_CLOSE EvtFileClose, _In_opt_ PFN_WDF_FILE_CLEANUP EvtFileCleanup)
Definition: wdfdevice.h:625
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: cdrom.h:539
#define IOCTL_AACS_GET_CHALLENGE_KEY
Definition: ntddcdvd.h:76
VOID NTAPI DeviceEvtSelfManagedIoCleanup(_In_ WDFDEVICE Device)
Definition: cdrom.c:902
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
VOID NTAPI DeviceEvtSurpriseRemoval(_In_ WDFDEVICE Device)
Definition: cdrom.c:1223
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
_IRQL_requires_max_(PASSIVE_LEVEL)
Definition: cdrom.c:1389
LARGE_INTEGER StartingOffset
Definition: cdrom.h:533
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX
Definition: cdrw_usr.h:190
struct _WDF_REQUEST_PARAMETERS::@3634::@3638 DeviceIoControl
#define WPP_CLEANUP(a)
Definition: kdebugprint.h:57
struct @1624::@1625 driver
NTSTATUS RequestValidatePersistentReserve(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:6715
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: cdrom.h:542
NTSTATUS RequestValidateAacsSendCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1697
#define IOCTL_DVD_BASE
Definition: ntddcdvd.h:32
NTSTATUS RequestValidateReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6117
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
#define WPP_INIT_TRACING(a, b)
Definition: kdebugprint.h:56
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define IOCTL_VOLUME_POST_ONLINE
Definition: volume.c:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
NTSTATUS RequestValidateSetSpeed(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1501
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:73
PZERO_POWER_ODD_INFO ZeroPowerODDInfo
Definition: cdrom.h:566
static void Exit(void)
Definition: sock.c:1331
PFN_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP EvtDeviceSelfManagedIoCleanup
Definition: wdfdevice.h:1170
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
#define DECLARE_CONST_UNICODE_STRING(_variablename, _string)
Definition: wdfcore.h:161
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit
Definition: cdrom.h:874
BOOLEAN IsVolumeOnlinePending
Definition: cdrom.h:590
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
ULONG dataLength
Definition: scsi.h:3751
#define IOCTL_DVD_SEND_KEY
Definition: cdrw_usr.h:161
#define SCSI_CDROM_TIMEOUT
Definition: cdrom.h:680
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
#define IOCTL_STORAGE_LOAD_MEDIA2
Definition: ntddk_ex.h:210
#define EXCLUSIVE_MODE(_CdData)
Definition: cdrom.h:788
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
NTSTATUS RequestValidateGetPerformance(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3634
ULONG CachedInquiryDataByteCount
Definition: cdrom.h:392
BOOLEAN PowerDownInProgress
Definition: cdrom.h:587
#define IOCTL_DISK_ARE_VOLUMES_READY
Definition: ntdddisk.h:46
BOOLEAN RequestDispatchToSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1855
#define CDROM_TAG_STRINGS
Definition: cdrom.h:743
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOLEAN RequestDispatchUnknownRequests(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:3093
unsigned char UCHAR
Definition: xmlstorage.h:181
#define EXCLUSIVE_OWNER(_CdData, _FileObject)
Definition: cdrom.h:789
_Null_terminated_ wchar_t * NTSTRSAFE_PWSTR
Definition: ntstrsafe.h:58
char * PBOOLEAN
Definition: retypes.h:11
#define IRP_MJ_POWER
FORCEINLINE VOID WDF_PNPPOWER_EVENT_CALLBACKS_INIT(_Out_ PWDF_PNPPOWER_EVENT_CALLBACKS Callbacks)
Definition: wdfdevice.h:1214
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
static const WCHAR L[]
Definition: oid.c:1250
PFN_WDF_DEVICE_D0_ENTRY EvtDeviceD0Entry
Definition: wdfdevice.h:1164
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define VOID
Definition: acefi.h:82
#define IOCTL_AACS_READ_SERIAL_NUMBER
Definition: ntddcdvd.h:85
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:318
ULONG LowPart
Definition: typedefs.h:106
NTSTATUS RequestValidateAacsReadVolumeId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1955
#define IRP_MN_SET_POWER
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessSetPower
Definition: cdrom.h:910
#define IOCTL_CDROM_EXCLUSIVE_ACCESS
Definition: ntddcdrm.h:85
NTSTATUS RequestIsIoctlBlockedByExclusiveAccess(_In_ WDFREQUEST Request, _Out_ PBOOLEAN IsBlocked)
Definition: cdrom.c:4058
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
PDEVICE_POWER_DESCRIPTOR PowerDescriptor
Definition: cdrom.h:545
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
PCDROM_DEVICE_EXTENSION DeviceExtension
Definition: cdrom.h:631
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IOCTL_STORAGE_EVENT_NOTIFICATION
Definition: ntddstor.h:226
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessShutdownFlush
Definition: cdrom.h:908
NTSTATUS RequestValidateAacsSendChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1895
VOID NTAPI RequestEvtCleanup(_In_ WDFOBJECT Request)
Definition: cdrom.c:4215
#define IOCTL_CDROM_PAUSE_AUDIO
Definition: ntddcdrm.h:43
VOID NTAPI SequentialQueueEvtIoReadWrite(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length)
Definition: cdrom.c:3215
#define IOCTL_DVD_GET_REGION
Definition: cdrw_usr.h:164
#define IOCTL_CDROM_GET_INQUIRY_DATA
Definition: ntddcdrm.h:91
_In_ WDF_POWER_DEVICE_STATE TargetState
Definition: wdfdevice.h:859
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define IOCTL_AACS_END_SESSION
Definition: ntddcdvd.h:67
WDFDEVICE Device
Definition: cdrom.h:473
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
EXCLUSIVE_ACCESS_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:419
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define IOCTL_CDROM_RESUME_AUDIO
Definition: ntddcdrm.h:46
WDFWAITLOCK ShutdownFlushWaitLock
Definition: cdrom.h:595
WDFWAITLOCK EjectSynchronizationLock
Definition: cdrom.h:559
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
NTSTATUS RequestValidateAacsBindingNonce(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2162
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
struct _DISK_GEOMETRY DISK_GEOMETRY
NTSTATUS RequestValidateAacsReadMediaId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2093
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
#define IOCTL_AACS_SEND_CERTIFICATE
Definition: ntddcdvd.h:70
LARGE_INTEGER PartitionLength
Definition: cdrom.h:530
#define IO_CD_ROM_INCREMENT
Definition: iotypes.h:599
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:2342
PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback
Definition: wdfobject.h:109
PFN_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl
Definition: wdfio.h:405
WDFQUEUE SerialIOQueue
Definition: cdrom.h:479
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
DISK_GEOMETRY DiskGeometry
Definition: cdrom.h:524
PFN_WDF_IO_QUEUE_IO_DEFAULT EvtIoDefault
Definition: wdfio.h:399
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK
Definition: ntddcdvd.h:61
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
WDF_TRI_STATE PowerManaged
Definition: wdfio.h:393
PFN_WDF_IO_QUEUE_IO_WRITE EvtIoWrite
Definition: wdfio.h:403
NTSTATUS RequestHandleMountQueryUniqueId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3939
#define IOCTL_SCSI_BASE
Definition: scsi_port.h:37
NTSTATUS RequestValidateRawRead(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:650
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:99
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
CDROM_POWER_DOWN_STATE PowerDown
Definition: cdrom.h:438
PDRIVER_OBJECT DriverObject
Definition: cdrom.h:232
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
VOID NTAPI SequentialQueueEvtCanceledOnQueue(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request)
Definition: cdrom.c:3848
NTSTATUS RequestValidateAacsReadSerialNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2024
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
WDFOBJECT ParentObject
Definition: wdfobject.h:130
#define IOCTL_STORAGE_LOAD_MEDIA
Definition: ntddstor.h:110
PSENSE_DATA SenseData
Definition: cdrom.h:548
#define WDF_NO_EVENT_CALLBACK
Definition: wdftypes.h:106
#define WdfObjectGetTypedContext(handle, type)
Definition: wdfobject.h:404
#define NULL
Definition: types.h:112
#define DEVICE_TYPE_FROM_CTL_CODE(c)
Definition: winioctl.h:205
#define IOCTL_MCN_SYNC_FAKE_IOCTL
Definition: cdrom.h:181
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
#define WDF_NO_OBJECT_ATTRIBUTES
Definition: wdftypes.h:105
#define IOCTL_DVD_SEND_KEY2
Definition: cdrw_usr.h:165
FORCEINLINE VOID WDF_REQUEST_PARAMETERS_INIT(_Out_ PWDF_REQUEST_PARAMETERS Parameters)
Definition: wdfrequest.h:211
Definition: tftpd.h:85
VOID NTAPI SequentialQueueEvtIoDeviceControl(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode)
Definition: cdrom.c:3408
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
ULONG BecomingReadyRetryCount
Definition: cdromp.h:277
PFN_WDF_DEVICE_D0_EXIT EvtDeviceD0Exit
Definition: wdfdevice.h:1166
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
#define IOCTL_CDROM_GET_PERFORMANCE
Definition: ntddcdrm.h:100
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
NTSTATUS NTAPI DeviceEvtD0Entry(_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE PreviousState)
Definition: cdrom.c:993
BOOLEAN BootEnvironmentIsWinPE(VOID)
Definition: cdrom.c:158
LONGLONG ReadWriteRetryDelay100nsUnits
Definition: cdrom.h:384
#define IOCTL_AACS_READ_BINDING_NONCE
Definition: ntddcdvd.h:91
#define IOCTL_AACS_READ_VOLUME_ID
Definition: ntddcdvd.h:82
#define IOCTL_CDROM_SEND_OPC_INFORMATION
Definition: ntddcdrm.h:97
NTSTATUS RequestHandleMountQueryDeviceName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4015
CDROM_POWER_OPTIONS Options
Definition: cdrom.h:442
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
WDF_FILEOBJECT_CLASS FileObjectClass
Definition: wdfdevice.h:619
static int processed(const type_t *type)
Definition: typegen.c:2254
#define FILE_DEVICE_ACPI
Definition: winioctl.h:156
static PDB_INFORMATION information
Definition: db.cpp:178
UCHAR LoadingMechanism
Definition: cdromp.h:266
unsigned int ULONG
Definition: retypes.h:1
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:137
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:426
NTSTATUS RequestValidateDvdSendKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1274
PDEVICE_OBJECT DeviceObject
Definition: cdrom.h:493
WDF_SYNCHRONIZATION_SCOPE SynchronizationScope
Definition: wdfobject.h:125
_In_ PWDFDEVICE_INIT DeviceInit
Definition: wdfcontrol.h:113
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
BOOLEAN EnforceStreamingWrite
Definition: cdromp.h:369
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: cdrom.h:563
enum _WDF_POWER_DEVICE_STATE WDF_POWER_DEVICE_STATE
#define IOCTL_AACS_SEND_CHALLENGE_KEY
Definition: ntddcdvd.h:79
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI CreateQueueEvtIoDefault(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request)
Definition: cdrom.c:1266
#define IRP_MN_SCSI_CLASS
#define IOCTL_DVD_START_SESSION
Definition: cdrw_usr.h:159
_Must_inspect_result_ _In_ PWDF_WORKITEM_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWORKITEM * WorkItem
Definition: wdfworkitem.h:110
NTSTATUS RequestHandleGetInquiryData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:270
NTSTATUS RequestHandleGetMediaTypeEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _Out_ size_t *DataLength)
Definition: ioctl.c:336
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
FORCEINLINE VOID WDF_REMOVE_LOCK_OPTIONS_INIT(_Out_ PWDF_REMOVE_LOCK_OPTIONS RemoveLockOptions, _In_ ULONG Flags)
Definition: wdfdevice.h:1661
BOOLEAN NTAPI PsIsThreadTerminating(IN PETHREAD Thread)
Definition: thread.c:868
WDFFILEOBJECT FileObject
Definition: cdromp.h:364
PFN_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue
Definition: wdfio.h:413
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
_Must_inspect_result_ _In_ WDFDRIVER Driver
Definition: wdfcontrol.h:83
signed int * PLONG
Definition: retypes.h:5
static SERVICE_STATUS status
Definition: service.c:31
VOID DeviceSendIoctlAsynchronously(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: common.c:1030
#define IOCTL_STORAGE_BASE
Definition: ntddstor.h:96
#define APC_LEVEL
Definition: env_spec_w32.h:695
VOID NTAPI KeFlushQueuedDpcs(VOID)
Definition: dpc.c:919
NTSTATUS RequestValidateAacsStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1651
NTSTATUS RequestHandleQueryPropertyWriteCache(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2974
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
FxIrp * irp
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
NTSTATUS RequestValidateAacsEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3462
struct _VOLUME_CONTROL VOLUME_CONTROL
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDF_POWER_DEVICE_STATE PreviousState
Definition: wdfdevice.h:829
NTSTATUS NTAPI DeviceEvtD0Exit(_In_ WDFDEVICE Device, _In_ WDF_POWER_DEVICE_STATE TargetState)
Definition: cdrom.c:1075
NTSTATUS NTAPI DriverEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit)
Definition: cdrom.c:238
CDROM_POWER_CONTEXT PowerContext
Definition: cdrom.h:586
#define CDROM_FLAG_WINPE_MODE
Definition: cdrom.h:237
NTSTATUS RequestHandleQueryPropertyRetrieveCachedData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2628
_Must_inspect_result_ FORCEINLINE NTSTATUS WdfWaitLockAcquire(_In_ _Requires_lock_not_held_(_Curr_) WDFWAITLOCK Lock, _In_opt_ PLONGLONG Timeout)
Definition: wdfsync.h:173
#define PAGED_CODE()
WDFWORKITEM IoctlWorkItem
Definition: cdrom.h:613
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
UNICODE_STRING DeviceName
Definition: cdrom.h:502
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define IOCTL_DVD_READ_STRUCTURE
Definition: cdrw_usr.h:157
Definition: ps.c:97