ReactOS 0.4.16-dev-258-g81860b4
cdrom.c
Go to the documentation of this file.
1/*--
2
3Copyright (C) Microsoft Corporation. All rights reserved.
4
5Module Name:
6
7 cdrom.c
8
9Abstract:
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
14Environment:
15
16 kernel mode only
17
18Notes:
19
20
21Revision 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
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
74NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
78 )
79/*++
80
81Routine Description:
82
83 Installable driver initialization entry point.
84 This entry point is called directly by the I/O system.
85
86Arguments:
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
93Return 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,
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
147
148 SET_FLAG(driverExtension->Flags, CDROM_FLAG_WINPE_MODE);
149 }
150
151 }
152
153 return status;
154}
155
156
159 VOID
160 )
161/*++
162
163Routine Description:
164
165 This routine determines if the boot enviroment is WinPE
166
167Arguments:
168
169 None
170
171Return 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
200VOID
201NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
204 )
205/*++
206Routine Description:
207
208 Free all the resources allocated in DriverEntry.
209
210Arguments:
211
212 Driver - handle to a WDF Driver object.
213
214Return 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
237NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
239 _In_ WDFDRIVER Driver,
241 )
242/*++
243
244Routine Description:
245
246 EvtDeviceAdd is called by the framework in response to AddDevice
247 call from the PnP manager.
248
249
250Arguments:
251
252 Driver - Handle to a framework driver object created in DriverEntry
253
254 DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
255
256Return 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,
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.
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 {
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
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
831Exit:
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
854VOID
855NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
858 )
859/*++
860Routine Description:
861
862 Free all the resources allocated in DriverEvtDeviceAdd.
863
864Arguments:
865
866 Device - handle to a WDF Device object.
867
868Return 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
900VOID
901NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
903 _In_ WDFDEVICE Device
904 )
905/*++
906
907Routine Description:
908
909 this function is called when the device is removed.
910 release the ownership of the device, release allocated resources.
911
912Arguments:
913
914 Device - Handle to device object
915
916Return 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.
954 KeFlushQueuedDpcs();
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
992NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
994 _In_ WDFDEVICE Device,
996 )
997/*++
998
999Routine 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
1004Arguments:
1005
1006 Device - Handle to device object
1007 PreviousState - Power state the device was in.
1008
1009Return 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) &&
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
1074NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1076 _In_ WDFDEVICE Device,
1078 )
1079/*++
1080
1081Routine 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
1087Arguments:
1088
1089 Device - Handle to device object
1090 TargetState - Power state the device is entering.
1091
1092Return 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
1221VOID
1222NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1224 _In_ WDFDEVICE Device
1225 )
1226/*++
1227
1228Routine 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
1233Arguments:
1234
1235 Device - Handle to device object
1236
1237Return 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
1264VOID
1265NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1267 _In_ WDFQUEUE Queue,
1268 _In_ WDFREQUEST Request
1269 )
1270/*++
1271
1272Routine 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
1277Arguments:
1278
1279 Queue - Handle to device queue
1280
1281 Request - the creation request
1282
1283Return 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
1325VOID
1326NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1328 _In_ WDFFILEOBJECT FileObject
1329 )
1330/*++
1331
1332Routine Description:
1333
1334 this function is called when CLOSE irp comes.
1335 clean up MCN / Lock if necessary
1336
1337Arguments:
1338
1339 FileObject - WDF file object created for the irp.
1340
1341Return 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
1391DeviceCleanupProtectedLocks(
1392 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1394 )
1395/*++
1396
1397Routine Description:
1398
1399 this function removes protected locks for the handle
1400
1401Arguments:
1402
1403 DeviceExtension - device context
1404
1405 FileObject - WDF file object created for the irp.
1406
1407Return 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
1475DeviceCleanupDisableMcn(
1476 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1478 )
1479/*++
1480
1481Routine Description:
1482
1483 cleanup the MCN disable count for the handle
1484
1485Arguments:
1486
1487 DeviceExtension - device context
1488
1489 FileObject - WDF file object created for the irp.
1490
1491Return 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.
1506 {
1507 DeviceEnableMediaChangeDetection(DeviceExtension, FileObjectContext, TRUE);
1508 }
1509
1510 return STATUS_SUCCESS;
1511}
1512
1513VOID
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
1552VOID
1553NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1555 _In_ WDFDEVICE Device,
1556 _In_ WDFREQUEST Request
1557 )
1558/*++
1559Routine Description:
1560
1561 Responds to EvtIoInCallerContext events from KMDF
1562 It calls different functions to process different type of IOCTLs.
1563
1564Arguments:
1565
1566 Device - handle to a WDF Device object
1567
1568 Request - handle to the incoming WDF Request object
1569
1570Return 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 {
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 {
1663 }
1664
1665 // 5. This is default behavior for unknown IOCTLs. To pass it to lower level.
1666 if (!processed)
1667 {
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 {
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
1693BOOLEAN
1695 _In_ WDFDEVICE Device,
1696 _In_ WDFREQUEST Request,
1698 )
1699/*++
1700Routine Description:
1701
1702 These requests can be processed in a non-serialized manner, most of them don't need to access device.
1703
1704Arguments:
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
1712Return 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 {
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)
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
1854BOOLEAN
1856 _In_ WDFDEVICE Device,
1857 _In_ WDFREQUEST Request,
1859 )
1860/*++
1861Routine Description:
1862
1863 These requests can be processed in a non-serialized manner, most of them don't need to access device.
1864
1865Arguments:
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
1873Return 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
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
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
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:
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 <
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
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
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
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
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
2716BOOLEAN
2718 _In_ WDFDEVICE Device,
2719 _In_ WDFREQUEST Request,
2721 )
2722/*++
2723Routine Description:
2724
2725 These requests need to stay in caller's context and be processed in serialized manner.
2726
2727Arguments:
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
2735Return 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,
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()
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
2848BOOLEAN
2850 _In_ WDFDEVICE Device,
2851 _In_ WDFREQUEST Request,
2853 )
2854/*++
2855Routine Description:
2856
2857 These requests need to be processed in different manner according to input parameters
2858
2859Arguments:
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
2867Return 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 {
2956 {
2958 }
2959 else
2960 {
2961 PSTORAGE_PROPERTY_QUERY inputBuffer = NULL;
2962
2963 status = WdfRequestRetrieveInputBuffer(Request,
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
3092BOOLEAN
3094 _In_ WDFDEVICE Device,
3095 _In_ WDFREQUEST Request,
3097 )
3098/*++
3099Routine 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
3105Arguments:
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
3113Return 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
3153VOID
3155 _In_ WDFREQUEST Request,
3156 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
3157 )
3158/*++
3159Routine Description:
3160
3161 all internal IOCTL will be send to lower driver asynchronously.
3162
3163Arguments:
3164
3165 Request - handle to the incoming WDF Request object
3166 DeviceExtension - device extension structure
3167
3168Return 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);
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
3213VOID
3214NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3216 _In_ WDFQUEUE Queue,
3217 _In_ WDFREQUEST Request,
3218 _In_ size_t Length
3219 )
3220/*++
3221Routine Description:
3222
3223 validate and process read/write request.
3224
3225Arguments:
3226
3227 Queue - parallel queue itself
3228
3229 Request - handle to the incoming WDF Request object
3230
3231 Length - read / write lenght
3232
3233Return 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
3343VOID
3344NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3346 _In_ WDFWORKITEM WorkItem
3347 )
3348/*++
3349
3350Routine 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
3356Arguments:
3357
3358 WorkItem - WDF work item
3359
3360Return 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;
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
3406VOID
3407NTAPI /* 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/*++
3416Routine Description:
3417
3418 validate and process IOCTL request.
3419
3420Arguments:
3421
3422 Queue - sequential queue
3423
3424 Request - handle to the incoming WDF Request object
3425
3426Return 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
3501VOID
3502NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3504 _In_ WDFWORKITEM WorkItem
3505 )
3506/*++
3507
3508Routine 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
3514Arguments:
3515
3516 WorkItem - WDF work item
3517
3518Return 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
3544RequestProcessSerializedIoctl(
3545 _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
3546 _In_ WDFREQUEST Request
3547 )
3548/*++
3549Routine Description:
3550
3551 a dispatch routine for all functions to process IOCTLs.
3552
3553Arguments:
3554
3555 DeviceExtension - device context
3556
3557 Request - handle to the incoming WDF Request object
3558
3559Return 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 {
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
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
3677 status = RequestHandleGetDvdRegion(DeviceExtension, Request, &information);
3678 break;
3679
3681 status = DeviceHandleReadDvdStructure(DeviceExtension, Request, requestParameters, &information);
3682 break;
3683
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:
3695 status = DeviceHandleDvdSendKey(DeviceExtension, Request, requestParameters, &information);
3696 break;
3697
3699 status = DeviceHandleSetReadAhead(DeviceExtension, Request, requestParameters, &information);
3700 break;
3701
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
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
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
3846VOID
3847NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3849 _In_ WDFQUEUE Queue,
3850 _In_ WDFREQUEST Request
3851 )
3852/*++
3853Routine 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
3860Arguments:
3861
3862 Queue - serial queue
3863 Request - handle to the incoming WDF Request object
3864
3865Return 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
3894 _In_ WDFDEVICE Device,
3895 _In_ WDFREQUEST Request
3896 )
3897/*++
3898Routine 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
3905Arguments:
3906
3907 DeviceExtension - device context
3908
3909 Request - handle to the incoming WDF Request object
3910
3911Return 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
3923 // cannot block at or above DISPATCH_LEVEL
3924 TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_IOCTL,
3925 "RequestSynchronousProcessWithSerialQueue called at DISPATCH_LEVEL or above"));
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));
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
4059 _In_ WDFREQUEST Request,
4060 _Out_ PBOOLEAN IsBlocked
4061 )
4062/*++
4063Routine Description:
4064
4065 Check if the IOCTL request should be blocked or not according to
4066 the exclusive lock stat.
4067
4068Arguments:
4069
4070 Request - handle to the incoming WDF Request object
4071
4072Return 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.
4094
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
4172
4174 }
4175
4176 return status;
4177}
4178
4179BOOLEAN
4181 _In_ WDFDEVICE Device
4182 )
4183/*++
4184Routine Description:
4185
4186 Check if the device needs to update its MMC information.
4187
4188Arguments:
4189
4190 Device - device to be checked.
4191
4192Return 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) &&
4203 {
4204 return TRUE;
4205 }
4206 else
4207 {
4208 // no update required: just proceed
4209 return FALSE;
4210 }
4211}
4212
4213VOID
4214NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
4217 )
4218/*++
4219Routine Description:
4220
4221 Request cleanup callback.
4222
4223Arguments:
4224
4225 Request - request to clean up.
4226
4227Return 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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define VOID
Definition: acefi.h:82
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
VOID RequestSetupMcnSyncIrp(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: autorun.c:2749
BOOLEAN RequestDispatchToSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1855
NTSTATUS RequestSynchronizeProcessWithSerialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: cdrom.c:3893
BOOLEAN RequestDispatchUnknownRequests(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:3093
NTSTATUS RequestIsIoctlBlockedByExclusiveAccess(_In_ WDFREQUEST Request, _Out_ PBOOLEAN IsBlocked)
Definition: cdrom.c:4058
BOOLEAN DeviceIsMmcUpdateRequired(_In_ WDFDEVICE Device)
Definition: cdrom.c:4180
VOID RequestProcessInternalDeviceControl(_In_ WDFREQUEST Request, _In_ PCDROM_DEVICE_EXTENSION DeviceExtension)
Definition: cdrom.c:3154
VOID NormalizeIoctl(_Inout_ PWDF_REQUEST_PARAMETERS requestParameters)
Definition: cdrom.c:1514
BOOLEAN RequestDispatchSyncWithSequentialQueue(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2717
VOID NTAPI SequentialQueueEvtIoReadWrite(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length)
Definition: cdrom.c:3215
BOOLEAN RequestDispatchProcessDirectly(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:1694
BOOLEAN RequestDispatchSpecialIoctls(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: cdrom.c:2849
BOOLEAN BootEnvironmentIsWinPE(VOID)
Definition: cdrom.c:158
EVT_WDF_IO_QUEUE_IO_DEFAULT CreateQueueEvtIoDefault
Definition: cdrom.h:886
#define IOCTL_MCN_SYNC_FAKE_IOCTL
Definition: cdrom.h:181
#define WRITE_RETRY_DELAY_DVD_1x
Definition: cdrom.h:118
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define CdromMmcUpdateRequired
Definition: cdrom.h:242
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessSetPower
Definition: cdrom.h:910
EVT_WDF_WORKITEM IoctlWorkItemRoutine
Definition: cdrom.h:1616
EVT_WDF_WORKITEM ReadWriteWorkItemRoutine
Definition: cdrom.h:1618
EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP DeviceEvtSelfManagedIoCleanup
Definition: cdrom.h:876
EVT_WDF_FILE_CLOSE DeviceEvtFileClose
Definition: cdrom.h:870
_In_ PFILE_OBJECT_CONTEXT FileObjectContext
Definition: cdrom.h:1212
NTSTATUS RequestSetContextFields(_In_ WDFREQUEST Request, _In_ PSYNC_HANDLER Handler)
Definition: common.c:2748
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SequentialQueueEvtIoDeviceControl
Definition: cdrom.h:900
EVT_WDF_OBJECT_CONTEXT_CLEANUP DeviceEvtCleanup
Definition: cdrom.h:868
EVT_WDF_DEVICE_D0_ENTRY DeviceEvtD0Entry
Definition: cdrom.h:878
NTSTATUS RequestSend(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDFIOTARGET IoTarget, _In_ ULONG Flags, _Out_opt_ PBOOLEAN RequestSent)
Definition: common.c:3793
EVT_WDF_OBJECT_CONTEXT_CLEANUP RequestEvtCleanup
Definition: cdrom.h:906
FORCEINLINE UCHAR RequestGetCurrentStackLocationFlags(_In_ WDFREQUEST Request)
Definition: cdrom.h:1554
EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit
Definition: cdrom.h:874
#define EXCLUSIVE_OWNER(_CdData, _FileObject)
Definition: cdrom.h:789
EVT_WDF_DRIVER_DEVICE_ADD DriverEvtDeviceAdd
Definition: cdrom.h:862
EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine
Definition: cdrom.h:1608
#define SCSI_CDROM_TIMEOUT
Definition: cdrom.h:680
VOID RequestCompletion(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ NTSTATUS Status, _In_ ULONG_PTR Information)
Definition: common.c:3439
EVT_WDF_IO_IN_CALLER_CONTEXT DeviceEvtIoInCallerContext
Definition: cdrom.h:872
EVT_WDF_DEVICE_SURPRISE_REMOVAL DeviceEvtSurpriseRemoval
Definition: cdrom.h:882
NTSTATUS DeviceZPODDGetPowerupReason(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _Out_ PSTORAGE_IDLE_POWERUP_REASON PowerupReason)
Definition: zpodd.c:608
EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SequentialQueueEvtCanceledOnQueue
Definition: cdrom.h:902
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define EXCLUSIVE_MODE(_CdData)
Definition: cdrom.h:788
EVT_WDF_OBJECT_CONTEXT_CLEANUP DriverEvtCleanup
Definition: cdrom.h:864
VOID RequestSetReceivedTime(_In_ WDFREQUEST Request)
Definition: common.c:64
#define CDROM_SPECIAL_DISABLE_SPIN_DOWN
Definition: cdrom.h:149
struct _CDROM_DEVICE_EXTENSION CDROM_DEVICE_EXTENSION
Definition: cdrom.h:216
#define SET_FLAG(Flags, Bit)
Definition: cdrom.h:1493
#define CDROM_TAG_STRINGS
Definition: cdrom.h:743
VOID DeviceSendIoctlAsynchronously(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: common.c:1030
#define CDROM_FLAG_WINPE_MODE
Definition: cdrom.h:237
EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessShutdownFlush
Definition: cdrom.h:908
@ CdRomDeviceInterface
Definition: cdrom.h:768
@ MountedDeviceInterface
Definition: cdrom.h:769
EVT_WDF_DEVICE_D0_EXIT DeviceEvtD0Exit
Definition: cdrom.h:880
#define INVALID_SESSION
Definition: cdromp.h:381
#define WINPE_REG_KEY_NAME
Definition: cdromp.h:127
#define CDROM_VOLUME_VERIFY_CHECKED
Definition: cdromp.h:171
#define BECOMING_READY_RETRY_COUNT
Definition: cdromp.h:261
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
union _CDB * PCDB
#define IOCTL_DVD_SEND_KEY
Definition: cdrw_usr.h:161
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_DVD_END_SESSION
Definition: cdrw_usr.h:162
#define IOCTL_STORAGE_SET_READ_AHEAD
Definition: cdrw_usr.h:186
#define IOCTL_DVD_SEND_KEY2
Definition: cdrw_usr.h:165
#define IOCTL_DVD_GET_REGION
Definition: cdrw_usr.h:164
#define IOCTL_DISK_VERIFY
Definition: cdrw_usr.h:170
#define IOCTL_DVD_READ_KEY
Definition: cdrw_usr.h:160
#define IOCTL_DVD_START_SESSION
Definition: cdrw_usr.h:159
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
#define IOCTL_DVD_READ_STRUCTURE
Definition: cdrw_usr.h:157
#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX
Definition: cdrw_usr.h:190
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
static PDB_INFORMATION information
Definition: db.cpp:178
struct config_s config
ULONG DEVPROPTYPE
Definition: devpropdef.h:24
#define DEVPROP_TYPE_EMPTY
Definition: devpropdef.h:29
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define IOCTL_VOLUME_POST_ONLINE
Definition: volume.c:26
#define WPP_INIT_TRACING(a, b)
Definition: kdebugprint.h:56
#define WPP_CLEANUP(a)
Definition: kdebugprint.h:57
NTSTATUS RequestHandleGetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5337
NTSTATUS RequestValidateReadToc(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:984
NTSTATUS RequestHandleGetMediaTypeEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _Out_ size_t *DataLength)
Definition: ioctl.c:336
NTSTATUS RequestHandleMountQuerySuggestedLinkName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4088
NTSTATUS RequestHandleQueryPropertyWriteCache(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2974
NTSTATUS RequestValidateAacsGetChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1826
NTSTATUS RequestHandleGetInquiryData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:270
NTSTATUS RequestValidateSetSpeed(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1501
NTSTATUS RequestHandleSetHotPlugInfo(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5392
NTSTATUS RequestValidateRawRead(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:650
NTSTATUS RequestValidateSendOpcInformation(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3576
NTSTATUS RequestHandleGetDeviceNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:5280
NTSTATUS RequestValidateAacsReadMediaKeyBlock(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1584
NTSTATUS RequestValidateAacsReadVolumeId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1955
NTSTATUS RequestValidateGetPerformance(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3634
NTSTATUS RequestValidateReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6117
NTSTATUS RequestHandleMountQueryUniqueId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3939
NTSTATUS RequestHandleQueryPropertyDeviceUniqueId(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
Definition: ioctl.c:2799
NTSTATUS RequestValidateAacsStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1651
NTSTATUS RequestValidateDvdStartSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1225
NTSTATUS RequestValidateAacsReadMediaId(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2093
NTSTATUS RequestValidateGetLastSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1029
NTSTATUS RequestValidateReadQChannel(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1072
NTSTATUS RequestHandleMountQueryDeviceName(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:4015
NTSTATUS RequestValidateGetConfiguration(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1364
NTSTATUS RequestValidateReadTocEx(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:887
NTSTATUS RequestValidateAacsSendCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1697
NTSTATUS RequestValidateAacsSendChallengeKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1895
NTSTATUS RequestValidateDvdEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3408
NTSTATUS RequestValidateDvdReadStructure(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1151
NTSTATUS RequestValidatePersistentReserve(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:6715
NTSTATUS RequestValidateAacsEndSession(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3462
NTSTATUS RequestValidateAacsGetCertificate(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1757
NTSTATUS RequestValidateDvdSendKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:1274
NTSTATUS RequestHandleQueryPropertyRetrieveCachedData(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2628
NTSTATUS RequestHandleReadWrite(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters)
Definition: ioctl.c:6353
NTSTATUS RequestValidateExclusiveAccess(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2240
NTSTATUS RequestValidateDvdReadKey(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3286
NTSTATUS RequestValidateAacsReadSerialNumber(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2024
NTSTATUS RequestValidateAacsBindingNonce(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension, _In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:2162
NTSTATUS RequestValidateEnableStreaming(_In_ WDFREQUEST Request, _In_ WDF_REQUEST_PARAMETERS RequestParameters, _Out_ size_t *DataLength)
Definition: ioctl.c:3515
_In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_PARAMETERS RequestParameters
Definition: ioctl.h:138
NTSTATUS RequestHandleUnknownIoctl(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request)
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG NTAPI KeReadStateEvent(IN PKEVENT Event)
Definition: eventobj.c:120
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
#define IOCTL_STORAGE_CHECK_VERIFY2
Definition: ntddk_ex.h:212
#define IOCTL_STORAGE_LOAD_MEDIA2
Definition: ntddk_ex.h:210
FxIrp * irp
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:91
struct _GET_LENGTH_INFORMATION GET_LENGTH_INFORMATION
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:97
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:78
#define IOCTL_STORAGE_GET_HOTPLUG_INFO
Definition: imports.h:238
struct @1677::@1678 driver
#define KernelMode
Definition: asm.h:34
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define IOCTL_CDROM_ENABLE_STREAMING
Definition: ntddcdrm.h:94
struct _VOLUME_CONTROL VOLUME_CONTROL
#define IOCTL_CDROM_GET_LAST_SESSION
Definition: ntddcdrm.h:64
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
Definition: ntddcdrm.h:76
#define IOCTL_CDROM_SEEK_AUDIO_MSF
Definition: ntddcdrm.h:37
#define IOCTL_CDROM_READ_TOC_EX
Definition: ntddcdrm.h:79
@ ExclusiveAccessQueryState
Definition: ntddcdrm.h:412
@ ExclusiveAccessLockDevice
Definition: ntddcdrm.h:413
@ ExclusiveAccessUnlockDevice
Definition: ntddcdrm.h:414
#define IOCTL_CDROM_GET_VOLUME
Definition: ntddcdrm.h:49
#define IOCTL_CDROM_PAUSE_AUDIO
Definition: ntddcdrm.h:43
#define IOCTL_CDROM_SET_VOLUME
Definition: ntddcdrm.h:55
#define IOCTL_CDROM_STOP_AUDIO
Definition: ntddcdrm.h:40
#define IOCTL_CDROM_READ_Q_CHANNEL
Definition: ntddcdrm.h:58
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY
Definition: ntddcdrm.h:73
#define IOCTL_CDROM_SET_SPEED
Definition: ntddcdrm.h:88
#define IOCTL_CDROM_GET_INQUIRY_DATA
Definition: ntddcdrm.h:91
#define IOCTL_CDROM_GET_CONFIGURATION
Definition: ntddcdrm.h:82
#define IOCTL_CDROM_PLAY_AUDIO_MSF
Definition: ntddcdrm.h:52
#define IOCTL_CDROM_EXCLUSIVE_ACCESS
Definition: ntddcdrm.h:85
#define IOCTL_CDROM_RESUME_AUDIO
Definition: ntddcdrm.h:46
#define IOCTL_CDROM_SEND_OPC_INFORMATION
Definition: ntddcdrm.h:97
#define IOCTL_CDROM_READ_TOC
Definition: ntddcdrm.h:34
#define IOCTL_CDROM_RAW_READ
Definition: ntddcdrm.h:67
#define IOCTL_CDROM_GET_PERFORMANCE
Definition: ntddcdrm.h:100
struct _DISK_GEOMETRY DISK_GEOMETRY
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
#define IOCTL_DISK_ARE_VOLUMES_READY
Definition: ntdddisk.h:46
struct _PARTITION_INFORMATION PARTITION_INFORMATION
@ RemovableMedia
Definition: ntdddisk.h:382
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
#define IOCTL_DISK_BASE
Definition: ntdddisk.h:44
@ FeatureDefectManagement
Definition: ntddmmc.h:88
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
#define IOCTL_STORAGE_RELEASE
Definition: ntddstor.h:119
STORAGE_READ_CAPACITY
Definition: ntddstor.h:861
#define IOCTL_STORAGE_EVENT_NOTIFICATION
Definition: ntddstor.h:226
#define IOCTL_STORAGE_SET_HOTPLUG_INFO
Definition: ntddstor.h:157
#define IOCTL_STORAGE_GET_DEVICE_NUMBER
Definition: ntddstor.h:143
#define IOCTL_STORAGE_CHECK_VERIFY
Definition: ntddstor.h:98
#define IOCTL_STORAGE_READ_CAPACITY
Definition: ntddstor.h:175
@ StoragePowerupDeviceAttention
Definition: ntddstor.h:1095
#define IOCTL_STORAGE_PERSISTENT_RESERVE_IN
Definition: ntddstor.h:169
#define IOCTL_STORAGE_PERSISTENT_RESERVE_OUT
Definition: ntddstor.h:172
#define IOCTL_STORAGE_LOAD_MEDIA
Definition: ntddstor.h:110
#define IOCTL_STORAGE_RESERVE
Definition: ntddstor.h:116
@ StorageDeviceUniqueIdProperty
Definition: ntddstor.h:515
@ StorageDeviceWriteCacheProperty
Definition: ntddstor.h:516
@ StorageAdapterProperty
Definition: ntddstor.h:513
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ PropertyExistsQuery
Definition: ntddstor.h:506
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define IOCTL_STORAGE_FIND_NEW_DEVICES
Definition: ntddstor.h:122
#define IOCTL_STORAGE_BASE
Definition: ntddstor.h:96
#define IOCTL_STORAGE_MCN_CONTROL
Definition: ntddstor.h:128
#define IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT
Definition: ntddstor.h:196
#define IOCTL_STORAGE_EJECT_MEDIA
Definition: ntddstor.h:107
#define IOCTL_STORAGE_EJECTION_CONTROL
Definition: ntddstor.h:125
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
#define IOCTL_TAPE_BASE
Definition: ntddtape.h:35
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:63
@ NotificationEvent
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
BOOLEAN NTAPI PsIsThreadTerminating(IN PETHREAD Thread)
Definition: thread.c:868
#define STATUS_INTERNAL_ERROR
Definition: ntstatus.h:465
#define STATUS_ALERTED
Definition: ntstatus.h:80
#define STATUS_INVALID_LEVEL
Definition: ntstatus.h:564
_Null_terminated_ wchar_t * NTSTRSAFE_PWSTR
Definition: ntstrsafe.h:58
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
#define L(x)
Definition: ntvdm.h:50
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK
Definition: ntddcdvd.h:61
#define IOCTL_AACS_READ_MEDIA_KEY_BLOCK_SIZE
Definition: ntddcdvd.h:58
#define IOCTL_AACS_START_SESSION
Definition: ntddcdvd.h:64
#define IOCTL_AACS_READ_BINDING_NONCE
Definition: ntddcdvd.h:91
#define IOCTL_AACS_SEND_CHALLENGE_KEY
Definition: ntddcdvd.h:79
#define IOCTL_AACS_READ_VOLUME_ID
Definition: ntddcdvd.h:82
#define IOCTL_AACS_END_SESSION
Definition: ntddcdvd.h:67
#define IOCTL_AACS_GET_CHALLENGE_KEY
Definition: ntddcdvd.h:76
#define IOCTL_AACS_SEND_CERTIFICATE
Definition: ntddcdvd.h:70
#define IOCTL_AACS_GENERATE_BINDING_NONCE
Definition: ntddcdvd.h:94
#define IOCTL_AACS_GET_CERTIFICATE
Definition: ntddcdvd.h:73
#define IOCTL_DVD_BASE
Definition: ntddcdvd.h:32
#define IOCTL_AACS_READ_SERIAL_NUMBER
Definition: ntddcdvd.h:85
#define IOCTL_AACS_READ_MEDIA_ID
Definition: ntddcdvd.h:88
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:47
#define DEVICE_TYPE_FROM_CTL_CODE(c)
Definition: winioctl.h:144
#define FILE_DEVICE_ACPI
Definition: winioctl.h:95
#define IOCTL_SCSI_PASS_THROUGH
Definition: scsi_port.h:47
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define IOCTL_SCSI_PASS_THROUGH_DIRECT
Definition: scsi_port.h:51
#define IOCTL_SCSI_BASE
Definition: scsi_port.h:37
#define LOADING_MECHANISM_TRAY
Definition: scsi.h:972
ULONG dataLength
Definition: scsi.h:3751
#define IOCTL_SCSI_PASS_THROUGH_DIRECT_EX
Definition: ntddscsi.h:38
#define IOCTL_SCSI_PASS_THROUGH_EX
Definition: ntddscsi.h:37
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
static void Exit(void)
Definition: sock.c:1330
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_FATAL
Definition: storswtr.h:26
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
UNICODE_STRING WellKnownName
Definition: cdrom.h:357
CDROM_MMC_EXTENSION Mmc
Definition: cdrom.h:341
BOOLEAN PlayActive
Definition: cdrom.h:351
LONGLONG ReadWriteRetryDelay100nsUnits
Definition: cdrom.h:384
ULONG CachedInquiryDataByteCount
Definition: cdrom.h:392
WDFIOTARGET IoTarget
Definition: cdrom.h:476
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: cdrom.h:542
ULONG ScanForSpecialFlags
Definition: cdrom.h:512
PDEVICE_OBJECT DeviceObject
Definition: cdrom.h:493
WDFWAITLOCK EjectSynchronizationLock
Definition: cdrom.h:559
PZERO_POWER_ODD_INFO ZeroPowerODDInfo
Definition: cdrom.h:566
WDFWORKITEM IoctlWorkItem
Definition: cdrom.h:613
CDROM_READ_WRITE_CONTEXT ReadWriteWorkItemContext
Definition: cdrom.h:609
WDFQUEUE ManualVolumeReadyQueue
Definition: cdrom.h:591
PCDROM_PRIVATE_FDO_DATA PrivateFdoData
Definition: cdrom.h:605
WDFWORKITEM ReadWriteWorkItem
Definition: cdrom.h:608
LARGE_INTEGER StartingOffset
Definition: cdrom.h:533
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: cdrom.h:539
UNICODE_STRING DeviceName
Definition: cdrom.h:502
DEVICE_TYPE DeviceType
Definition: cdrom.h:499
CDROM_POWER_CONTEXT PowerContext
Definition: cdrom.h:586
CDROM_IOCTL_CONTEXT IoctlWorkItemContext
Definition: cdrom.h:614
WDFQUEUE CreateQueue
Definition: cdrom.h:483
WDFQUEUE SerialIOQueue
Definition: cdrom.h:479
LARGE_INTEGER PartitionLength
Definition: cdrom.h:530
DISK_GEOMETRY DiskGeometry
Definition: cdrom.h:524
WDFWAITLOCK ShutdownFlushWaitLock
Definition: cdrom.h:595
PDEVICE_OBJECT LowerPdo
Definition: cdrom.h:496
BOOLEAN PowerDownInProgress
Definition: cdrom.h:587
BOOLEAN IsVolumeOnlinePending
Definition: cdrom.h:590
BOOLEAN SurpriseRemoved
Definition: cdrom.h:470
BOOLEAN IsInitialized
Definition: cdrom.h:464
PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo
Definition: cdrom.h:563
WDFDEVICE Device
Definition: cdrom.h:473
PSENSE_DATA SenseData
Definition: cdrom.h:548
PCDROM_DRIVER_EXTENSION DriverExtension
Definition: cdrom.h:490
CDROM_DATA DeviceAdditionalData
Definition: cdrom.h:598
PDEVICE_POWER_DESCRIPTOR PowerDescriptor
Definition: cdrom.h:545
PDRIVER_OBJECT DriverObject
Definition: cdrom.h:232
EXCLUSIVE_ACCESS_REQUEST_TYPE RequestType
Definition: ntddcdrm.h:419
WDFREQUEST OriginalRequest
Definition: cdrom.h:328
BOOLEAN WriteAllowed
Definition: cdrom.h:250
CDROM_POWER_OPTIONS Options
Definition: cdrom.h:442
union _CDROM_POWER_CONTEXT::@1058 PowerChangeState
CDROM_POWER_DOWN_STATE PowerDown
Definition: cdrom.h:438
WDFREQUEST OriginalRequest
Definition: cdrom.h:335
PCDROM_DEVICE_EXTENSION DeviceExtension
Definition: cdrom.h:631
BOOLEAN SyncRequired
Definition: cdrom.h:643
PSYNC_HANDLER SyncCallback
Definition: cdrom.h:645
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
BOOLEAN EnforceStreamingRead
Definition: cdromp.h:368
BOOLEAN EnforceStreamingWrite
Definition: cdromp.h:369
WDFDEVICE DeviceObject
Definition: cdromp.h:365
ULONG McnDisableCount
Definition: cdromp.h:367
WDFFILEOBJECT FileObject
Definition: cdromp.h:364
union _IO_STACK_LOCATION::@1579 Parameters
struct _IO_STACK_LOCATION::@3978::@4000 Scsi
ULONG TimeOutValue
Definition: srb.h:262
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
STORAGE_POWERUP_REASON_TYPE PowerupReason
Definition: ntddstor.h:1102
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
WDF_TRI_STATE AutoForwardCleanupClose
Definition: wdfdevice.h:612
WDF_FILEOBJECT_CLASS FileObjectClass
Definition: wdfdevice.h:619
PFN_WDF_IO_QUEUE_IO_DEFAULT EvtIoDefault
Definition: wdfio.h:399
PFN_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl
Definition: wdfio.h:405
WDF_TRI_STATE PowerManaged
Definition: wdfio.h:393
PFN_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE EvtIoCanceledOnQueue
Definition: wdfio.h:413
PFN_WDF_IO_QUEUE_IO_READ EvtIoRead
Definition: wdfio.h:401
PFN_WDF_IO_QUEUE_IO_WRITE EvtIoWrite
Definition: wdfio.h:403
WDFOBJECT ParentObject
Definition: wdfobject.h:130
PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback
Definition: wdfobject.h:109
WDF_EXECUTION_LEVEL ExecutionLevel
Definition: wdfobject.h:120