xref: /reactos/drivers/storage/class/cdrom/cdrom.h (revision ea6e7740)
1 /*++
2 
3 Copyright (C) Microsoft Corporation. All rights reserved.
4 
5 Module Name:
6 
7     cdrom.h
8 
9 Abstract:
10 
11     Main header file for cdrom.sys.
12     This contains structure and function declarations as well as constant values.
13 
14 Author:
15 
16 Environment:
17 
18     kernel mode only
19 
20 Notes:
21 
22 
23 Revision History:
24 
25 --*/
26 
27 #ifndef __CDROM_H__
28 #define __CDROM_H__
29 
30 #pragma warning(push)
31 #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
32 #pragma warning(disable:4214) // nonstandard extension used : bit field types other than int
33 #pragma warning(disable:4152) // nonstandard extension, function/data pointer conversion in expression
34 
35 #include "wdf.h"
36 #include "ntddmmc.h"
37 #include "ntddcdvd.h"
38 #include "ntddcdrm.h"
39 #include "ntdddisk.h"
40 #include "ntddtape.h"
41 #include "ntddscsi.h"
42 #include "ntddvol.h"
43 #include "specstrings.h"
44 #include "cdromp.h"
45 
46 // Set component ID for DbgPrintEx calls
47 #ifndef DEBUG_COMP_ID
48     #define DEBUG_COMP_ID   DPFLTR_CDROM_ID
49 #endif
50 
51 // Include initguid.h so GUID_CONSOLE_DISPLAY_STATE is declared
52 #include <initguid.h>
53 
54 // Include header file and setup GUID for tracing
55 #include <storswtr.h>
56 #define WPP_GUID_CDROM      (A4196372, C3C4, 42d5, 87BF, 7EDB2E9BCC27)
57 #ifndef WPP_CONTROL_GUIDS
58     #define WPP_CONTROL_GUIDS   WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_CDROM)
59 #endif
60 
61 #ifdef __REACTOS__
62 #include <pseh/pseh2.h>
63 #endif
64 
65 #ifdef __REACTOS__
66 #undef MdlMappingNoExecute
67 #define MdlMappingNoExecute 0
68 #define NonPagedPoolNx NonPagedPool
69 #define NonPagedPoolNxCacheAligned NonPagedPoolCacheAligned
70 #undef POOL_NX_ALLOCATION
71 #define POOL_NX_ALLOCATION 0
72 #endif
73 
74 // This prototype is needed because, although NTIFS.H is now shipping with
75 // the WDK, can't include both it and the other headers we already use.
76 _IRQL_requires_max_(DISPATCH_LEVEL)
77 NTKERNELAPI
78 BOOLEAN
79 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
80 PsIsThreadTerminating(
81     _In_ PETHREAD Thread
82     );
83 
84 //
85 //
86 extern CDROM_SCAN_FOR_SPECIAL_INFO CdromHackItems[];
87 
88 #define CDROM_HACK_DEC_RRD                 (0x00000001)
89 #define CDROM_HACK_FUJITSU_FMCD_10x        (0x00000002)
90 //#define CDROM_HACK_HITACHI_1750            (0x00000004) -- obsolete
91 #define CDROM_HACK_HITACHI_GD_2000         (0x00000008)
92 #define CDROM_HACK_TOSHIBA_SD_W1101        (0x00000010)
93 //#define CDROM_HACK_TOSHIBA_XM_3xx          (0x00000020) -- obsolete
94 //#define CDROM_HACK_NEC_CDDA                (0x00000040) -- obsolete
95 //#define CDROM_HACK_PLEXTOR_CDDA            (0x00000080) -- obsolete
96 #define CDROM_HACK_BAD_GET_CONFIG_SUPPORT  (0x00000100)
97 //#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200) -- obsolete
98 //#define CDROM_HACK_READ_CD_SUPPORTED       (0x00000400) -- obsolete
99 #define CDROM_HACK_BAD_TYPE_ONE_GET_CONFIG (0x00000800)
100 #define CDROM_HACK_BAD_VENDOR_PROFILES     (0x00001000)
101 #define CDROM_HACK_MSFT_VIRTUAL_ODD        (0x00002000)
102 #define CDROM_HACK_LOCKED_PAGES            (0x80000000) // not a valid flag to save
103 
104 #define CDROM_HACK_VALID_FLAGS             (0x00003fff)
105 #define CDROM_HACK_INVALID_FLAGS           (~CDROM_HACK_VALID_FLAGS)
106 
107 
108 // A 64k buffer to be written takes the following amount of time:
109 //   1x    CD ==     75 sectors/sec == 0.4266667 seconds == 4266667 100ns units
110 //   4x    CD ==    300 sectors/sec == 0.1066667 seconds == 1066667 100ns units
111 //  10x    CD ==    300 sectors/sec == 0.0426667 seconds ==  426667 100ns units
112 //   1x   DVD ==    676 sectors/sec == 0.0473373 seconds ==  473373 100ns units
113 //  16x   DVD == 10,816 sectors/sec == 0.0029586 seconds ==   29586 100ns units
114 //   1x HDDVD ==  2,230 sectors/sec == 0.0143498 seconds ==  143498 100ns units
115 #define WRITE_RETRY_DELAY_CD_1x    ((LONGLONG)4266667)
116 #define WRITE_RETRY_DELAY_CD_4x    ((LONGLONG)1066667)
117 #define WRITE_RETRY_DELAY_CD_10x   ((LONGLONG) 426667)
118 #define WRITE_RETRY_DELAY_DVD_1x   ((LONGLONG) 473373)
119 #define WRITE_RETRY_DELAY_DVD_4x   ((LONGLONG) 118343)
120 #define WRITE_RETRY_DELAY_DVD_16x  ((LONGLONG)  29586)
121 #define WRITE_RETRY_DELAY_HDDVD_1x ((LONGLONG) 143498)
122 
123 //
124 #define MAXIMUM_RETRIES 4
125 
126 #define CDROM_GET_CONFIGURATION_TIMEOUT     (0x4)
127 #define CDROM_READ_DISC_INFORMATION_TIMEOUT (0x4)
128 #define CDROM_TEST_UNIT_READY_TIMEOUT       (0x14)
129 #define CDROM_GET_PERFORMANCE_TIMEOUT       (0x14)
130 #define CDROM_READ_CAPACITY_TIMEOUT         (0x14)
131 
132 #define START_UNIT_TIMEOUT  (60 * 4)
133 
134 // Used to detect the loss of the autorun irp.
135 #define MEDIA_CHANGE_TIMEOUT_TIME  300
136 
137 // Indicates whether is is safe to send StartUnit commands
138 // to this device. It will only be off for some removeable devices.
139 #define DEV_SAFE_START_UNIT 0x00000004
140 
141 // Indicates that the device is connected to a backup power supply
142 // and hence write-through and synch cache requests may be ignored
143 #define DEV_POWER_PROTECTED 0x00000010
144 
145 // The following CDROM_SPECIAL_ flags are set in ScanForSpecialFlags
146 // in the Device Extension
147 
148 // Never Spin Up/Down the drive (may not handle properly)
149 #define CDROM_SPECIAL_DISABLE_SPIN_DOWN                 0x00000001
150 //#define CDROM_SPECIAL_DISABLE_SPIN_UP                   0x00000002
151 
152 // Don't bother to lock the queue when powering down
153 // (used mostly to send a quick stop to a cdrom to abort audio playback)
154 //#define CDROM_SPECIAL_NO_QUEUE_LOCK                     0x00000008
155 
156 // Disable write cache due to known bugs
157 #define CDROM_SPECIAL_DISABLE_WRITE_CACHE               0x00000010
158 
159 // Used to indicate that this request shouldn't invoke any power type operations
160 // like spinning up the drive.
161 
162 #define SRB_CLASS_FLAGS_LOW_PRIORITY      0x10000000
163 
164 // Used to indicate that an SRB is the result of a paging operation.
165 #define SRB_CLASS_FLAGS_PAGING            0x40000000
166 
167 typedef struct _ERROR_RECOVERY_DATA {
168     MODE_PARAMETER_HEADER   Header;
169     MODE_PARAMETER_BLOCK    BlockDescriptor;
170     MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
171 } ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA;
172 
173 // A compile-time check of the 30,000 limit not overflowing ULONG size...
174 // Note that it is not expected that a release (FRE) driver will normally
175 // have such a large history, instead using the compression function.
176 #define CDROM_INTERPRET_SENSE_INFO2_MAXIMUM_HISTORY_COUNT   30000
177 C_ASSERT( (MAXULONG - sizeof(SRB_HISTORY)) / 30000 >= sizeof(SRB_HISTORY_ITEM) );
178 
179 // Intended to reuse a defined IOCTL code that not seen in Optical stack and does not require input parameter.
180 // This fake IOCTL is used used for MCN process sync-ed with serial queue.
181 #define IOCTL_MCN_SYNC_FAKE_IOCTL    IOCTL_DISK_UPDATE_DRIVE_SIZE
182 
183 /*++////////////////////////////////////////////////////////////////////////////
184 
185 PCDROM_ERROR_HANDLER()
186 
187 Routine Description:
188 
189     This routine is a callback into the driver to handle errors.  The queue
190     shall not be unfrozen when this error handler is called, even though the
191     SRB flags may mark the queue as having been frozen due to this SRB.
192 
193 Irql:
194 
195     This routine will be called at KIRQL <= DISPATCH_LEVEL
196 
197 Arguments:
198 
199     DeviceObject is the device object the error occurred on.
200 
201     Srb is the Srb that was being processed when the error occurred.
202 
203     Status may be overwritten by the routine if it decides that the error
204         was benign, or otherwise wishes to change the returned status code
205         for this command
206 
207     Retry may be overwritten to specify that this command should or should
208         not be retried (if the callee supports retrying commands)
209 
210 Return Value:
211 
212     status
213 
214 --*/
215 struct _CDROM_DEVICE_EXTENSION;     // *PCDROM_DEVICE_EXTENSION;
216 typedef struct _CDROM_DEVICE_EXTENSION
217                 CDROM_DEVICE_EXTENSION,
218                 *PCDROM_DEVICE_EXTENSION;
219 
220 typedef
221 VOID
222 (*PCDROM_ERROR_HANDLER) (
223     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
224     _In_ PSCSI_REQUEST_BLOCK      Srb,
225     _Inout_ PNTSTATUS             Status,
226     _Inout_ PBOOLEAN              Retry
227     );
228 
229 // CdRom driver extension
230 typedef struct _CDROM_DRIVER_EXTENSION {
231     ULONG               Version;
232     PDRIVER_OBJECT      DriverObject;
233     ULONG               Flags;
234 
235 } CDROM_DRIVER_EXTENSION, *PCDROM_DRIVER_EXTENSION;
236 
237 #define CDROM_FLAG_WINPE_MODE   0x00000001
238 
239 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_DRIVER_EXTENSION, DriverGetExtension)
240 
241 #define CdromMmcUpdateComplete  0
242 #define CdromMmcUpdateRequired  1
243 #define CdromMmcUpdateStarted   2
244 
245 typedef struct _CDROM_MMC_EXTENSION {
246 
247     BOOLEAN         IsMmc;          // mmc device
248     BOOLEAN         IsAACS;         // aacs compatible device
249     BOOLEAN         IsWriter;       // the drive is a writer or not
250     BOOLEAN         WriteAllowed;   // currently allow write request or not
251 
252     BOOLEAN         IsCssDvd;       // A CSS protected DVD or CPPM-protected DVDAudio media in Drive.
253     BOOLEAN         StreamingReadSupported;   // the drive supports streaming for reads
254     BOOLEAN         StreamingWriteSupported;  // the drive supports streaming for writes
255 
256     LONG            UpdateState;
257 
258     // The feature number defines the level and form of
259     // validation that needs to be performed on Io requests
260     FEATURE_NUMBER  ValidationSchema;
261     ULONG           Blocking;
262 
263     SCSI_REQUEST_BLOCK          CapabilitiesSrb;
264     PIRP                        CapabilitiesIrp;
265     WDFREQUEST                  CapabilitiesRequest;
266     SENSE_DATA                  CapabilitiesSenseData;
267     _Field_size_bytes_(CapabilitiesBufferSize)
268     PGET_CONFIGURATION_HEADER   CapabilitiesBuffer;
269     ULONG                       CapabilitiesBufferSize;
270     PMDL                        CapabilitiesMdl;
271 
272     BOOLEAN                     ReadCdC2Pointers;
273     BOOLEAN                     ReadCdSubCode;
274 
275 } CDROM_MMC_EXTENSION, *PCDROM_MMC_EXTENSION;
276 
277 typedef struct _CDROM_SCRATCH_READ_WRITE_CONTEXT {
278 
279     // Information about the data that we need to read/write
280     ULONG           PacketsCount;
281     ULONG           TransferedBytes;
282     ULONG           EntireXferLen;
283     ULONG           MaxLength;
284     PUCHAR          DataBuffer;
285     LARGE_INTEGER   StartingOffset;
286     BOOLEAN         IsRead;
287 
288     // A pointer to the SRB history item to be filled upon completion
289     PSRB_HISTORY_ITEM   SrbHistoryItem;
290 
291 } CDROM_SCRATCH_READ_WRITE_CONTEXT, *PCDROM_SCRATCH_READ_WRITE_CONTEXT;
292 
293 // Many commands get double-buffered.  Since the max
294 // transfer size is typically 64k, most of these requests
295 // can be handled with a single pre-allocated buffer.
296 typedef struct _CDROM_SCRATCH_CONTEXT {
297 
298     _Field_range_(4*1024, 64*1024)       ULONG   ScratchBufferSize; // 0x1000..0x10000 (4k..64k)
299     _Field_size_bytes_(ScratchBufferSize)    PVOID   ScratchBuffer;     // used to get data for clients
300 
301     PMDL                         ScratchBufferMdl;  // used to get data for clients
302 
303     WDFREQUEST                   ScratchRequest;
304     PSCSI_REQUEST_BLOCK          ScratchSrb;
305     PSENSE_DATA                  ScratchSense;
306     PSRB_HISTORY                 ScratchHistory;
307 
308     // This MDL is used to performed the request whose required transfer size is bigger than adaptor's max.
309     PMDL                         PartialMdl;
310     BOOLEAN                      PartialMdlIsBuilt;
311 
312     // For debugging, set/clear this field when using the scratch buffer/request
313     PVOID                        ScratchInUse;
314     PCSTR                        ScratchInUseFileName;
315     ULONG                        ScratchInUseLineNumber;
316 
317     // Stuff for asynchronous retrying of the transfer.
318     ULONG                        NumRetries;
319 
320     // Read Write context
321     CDROM_SCRATCH_READ_WRITE_CONTEXT ScratchReadWriteContext;
322 
323 } CDROM_SCRATCH_CONTEXT, *PCDROM_SCRATCH_CONTEXT;
324 
325 // Context structure for the IOCTL work item
326 typedef struct _CDROM_IOCTL_CONTEXT {
327 
328     WDFREQUEST OriginalRequest;
329 
330 } CDROM_IOCTL_CONTEXT, *PCDROM_IOCTL_CONTEXT;
331 
332 // Context structure for the read/write work item
333 typedef struct _CDROM_READ_WRITE_CONTEXT {
334 
335     WDFREQUEST OriginalRequest;
336 
337 } CDROM_READ_WRITE_CONTEXT, *PCDROM_READ_WRITE_CONTEXT;
338 
339 typedef struct _CDROM_DATA {
340 
341     CDROM_MMC_EXTENSION     Mmc;
342 
343     // hack flags for ScanForSpecial routines
344     ULONG_PTR               HackFlags;
345 
346     // the error handling routines need to be per-device, not per-driver....
347     PCDROM_ERROR_HANDLER    ErrorHandler;
348 
349     // Indicates whether an audio play operation is currently being performed.
350     // Only thing this does is prevent reads and toc requests while playing audio.
351     BOOLEAN                 PlayActive;
352 
353     // indicate we need to pick a default dvd region for the user if we can
354     ULONG                   PickDvdRegion;
355 
356     // The well known name link for this device.
357     UNICODE_STRING          WellKnownName;
358 
359     // We need to distinguish between the two...
360     ULONG                   MaxPageAlignedTransferBytes;
361     ULONG                   MaxUnalignedTransferBytes;
362 
363     // Indicates that this is a DEC RRD cdrom.
364     // This drive requires software to fix responses from the faulty firmware
365     BOOLEAN                 IsDecRrd;
366 
367     // Storage for the error recovery page. This is used as the method
368     // to switch block sizes for some drive-specific error recovery routines.
369     // ERROR_RECOVERY_DATA     recoveryData;    //obsolete along with error process for TOSHIBA_XM_3xx
370 
371     // Indicates that the device is in exclusive mode and only
372     // the requests from the exclusive owner will be processed.
373     WDFFILEOBJECT           ExclusiveOwner;
374 
375     // Caller name of the owner, if the device is in exclusive mode.
376     UCHAR                   CallerName[CDROM_EXCLUSIVE_CALLER_LENGTH];
377 
378     // Indicates that the device speed should be set to
379     // default value on the next media change.
380     BOOLEAN                 RestoreDefaults;
381 
382     // How long to wait between retries if a READ/WRITE irp
383     // gets a LWIP (2/4/7, 2/4/8)?
384     LONGLONG                ReadWriteRetryDelay100nsUnits;
385 
386     // Cached Device Type information. Maybe FILE_DEVICE_CD_ROM or FILE_DEVICE_DVD
387     // CommonExtension.DevInfo->DeviceType maybe FILE_DEVICE_CD_ROM when this field is FILE_DEVICE_DVD
388     DEVICE_TYPE             DriveDeviceType;
389 
390     _Field_size_bytes_(CachedInquiryDataByteCount)
391         PINQUIRYDATA        CachedInquiryData;
392     ULONG                   CachedInquiryDataByteCount;
393 
394 } CDROM_DATA, *PCDROM_DATA;
395 
396 
397 typedef struct _CDROM_POWER_OPTIONS {
398     ULONG   PowerDown              :  1;
399     ULONG   LockQueue              :  1;
400     ULONG   HandleSpinDown         :  1;
401     ULONG   HandleSpinUp           :  1;
402     ULONG   Reserved               : 27;
403 } CDROM_POWER_OPTIONS, *PCDROM_POWER_OPTIONS;
404 
405 // this is a private enum, but must be kept here
406 // to properly compile size of CDROM_DEVICE_EXTENSION
407 typedef enum {
408     PowerDownDeviceInitial,
409     PowerDownDeviceLocked,
410     PowerDownDeviceQuiesced,
411     PowerDownDeviceFlushed,
412     PowerDownDeviceStopped,
413     PowerDownDeviceOff,
414     PowerDownDeviceUnlocked
415 } CDROM_POWER_DOWN_STATE;
416 
417 // this is a private enum, but must be kept here
418 // to properly compile size of CDROM_DEVICE_EXTENSION
419 typedef enum {
420     PowerUpDeviceInitial,
421     PowerUpDeviceLocked,
422     PowerUpDeviceOn,
423     PowerUpDeviceStarted,
424     PowerUpDeviceUnlocked
425 } CDROM_POWER_UP_STATE;
426 
427 // this is a private structure, but must be kept here
428 // to properly compile size of CDROM_DEVICE_EXTENSION
429 typedef struct _CDROM_POWER_CONTEXT {
430 
431     BOOLEAN                 InUse;
432 
433     LARGE_INTEGER           StartTime;
434     LARGE_INTEGER           Step1CompleteTime;  // for SYNC CACHE in power down case
435     LARGE_INTEGER           CompleteTime;
436 
437     union {
438         CDROM_POWER_DOWN_STATE  PowerDown;
439         CDROM_POWER_UP_STATE    PowerUp;    // currently not used.
440     } PowerChangeState;
441 
442     CDROM_POWER_OPTIONS     Options;
443 
444     WDFREQUEST              PowerRequest;
445 
446     SCSI_REQUEST_BLOCK      Srb;
447     SENSE_DATA              SenseData;
448 
449     ULONG                   RetryCount;
450     LONGLONG                RetryIntervalIn100ns;
451 
452 } CDROM_POWER_CONTEXT, *PCDROM_POWER_CONTEXT;
453 
454 // device extension structure
455 typedef struct _CDROM_DEVICE_EXTENSION {
456 
457     // Version control field
458     ULONG           Version;
459 
460     // structure size
461     ULONG           Size;
462 
463     // the structure is fully ready to use
464     BOOLEAN         IsInitialized;
465 
466     // the device is active
467     BOOLEAN         IsActive;
468 
469     // the device is surprise removed.
470     BOOLEAN         SurpriseRemoved;
471 
472     // Back pointer to device object
473     WDFDEVICE       Device;
474 
475     // Save IoTarget here, do not retrieve anytime.
476     WDFIOTARGET     IoTarget;
477 
478     // Additional WDF queue for serial I/O processing
479     WDFQUEUE        SerialIOQueue;
480 
481     // A separate queue for all the create file requests in sync with device
482     // removal
483     WDFQUEUE        CreateQueue;
484 
485     //Main timer of driver, will do Mcn work. (once per second)
486     WDFTIMER        MainTimer;
487 
488     // Pointer to the initialization data for this driver.  This is more
489     // efficient than constantly getting the driver extension.
490     PCDROM_DRIVER_EXTENSION DriverExtension;
491 
492     // WDM device information
493     PDEVICE_OBJECT  DeviceObject;
494 
495     // Pointer to the physical device object we attached to
496     PDEVICE_OBJECT  LowerPdo;
497 
498     // FILE_DEVICE_CD_ROM -- 2
499     DEVICE_TYPE     DeviceType;
500 
501     // The name of the object
502     UNICODE_STRING  DeviceName;
503 
504     // System device number
505     ULONG           DeviceNumber;
506 
507     // Values for the flags are below.
508     USHORT          DeviceFlags;
509 
510     // Flags for special behaviour required by different hardware,
511     // such as never spinning down or disabling advanced features such as write cache
512     ULONG           ScanForSpecialFlags;
513 
514     // Add default Srb Flags.
515     ULONG           SrbFlags;
516 
517     // Request timeout in seconds;
518     ULONG           TimeOutValue;
519 
520     //The SCSI address of the device.
521     SCSI_ADDRESS    ScsiAddress;
522 
523     // Buffer for drive parameters returned in IO device control.
524     DISK_GEOMETRY   DiskGeometry;
525 
526     // Log2 of sector size
527     UCHAR           SectorShift;
528 
529     // Length of partition in bytes
530     LARGE_INTEGER   PartitionLength;
531 
532     // Number of bytes before start of partition
533     LARGE_INTEGER   StartingOffset;
534 
535     // Interface name string returned by IoRegisterDeviceInterface.
536     UNICODE_STRING  MountedDeviceInterfaceName;
537 
538     // Device capabilities
539     PSTORAGE_DEVICE_DESCRIPTOR  DeviceDescriptor;
540 
541     // SCSI port driver capabilities
542     PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor;
543 
544     // Device power properties
545     PDEVICE_POWER_DESCRIPTOR PowerDescriptor;
546 
547     // Request Sense Buffer
548     PSENSE_DATA     SenseData;
549 
550     // Total number of SCSI protocol errors on the device.
551     ULONG           ErrorCount;
552 
553     // Lock count for removable media.
554     LONG            LockCount;
555     LONG            ProtectedLockCount;
556     LONG            InternalLockCount;
557 
558     KEVENT          EjectSynchronizationEvent;
559     WDFWAITLOCK     EjectSynchronizationLock;
560 
561     // Indicates that the necessary data structures for media change
562     // detection have been initialized.
563     PMEDIA_CHANGE_DETECTION_INFO MediaChangeDetectionInfo;
564 
565     // Contains necessary data structures for ZPODD support.
566     PZERO_POWER_ODD_INFO         ZeroPowerODDInfo;
567 
568     // File system context. Used for kernel-mode requests to disable autorun.
569     FILE_OBJECT_CONTEXT   KernelModeMcnContext;
570 
571     // Count of media changes.  This field is only valid for the root partition
572     // (ie. if PhysicalDevice == NULL).
573     ULONG               MediaChangeCount;
574 
575     // Storage for a release queue request.
576     WDFSPINLOCK         ReleaseQueueSpinLock;
577     WDFREQUEST          ReleaseQueueRequest;
578     SCSI_REQUEST_BLOCK  ReleaseQueueSrb;
579     WDFMEMORY           ReleaseQueueInputMemory;    //This is a wrapper of ReleaseQueueSrb
580     BOOLEAN             ReleaseQueueNeeded;
581     BOOLEAN             ReleaseQueueInProgress;
582 
583     // Context structure for power operations.  Since we can only have
584     // one D irp at any time in the stack we don't need to worry about
585     // allocating multiple of these structures.
586     CDROM_POWER_CONTEXT     PowerContext;
587     BOOLEAN                 PowerDownInProgress;
588 
589 #if (NTDDI_VERSION >= NTDDI_WIN8)
590     BOOLEAN                 IsVolumeOnlinePending;
591     WDFQUEUE                ManualVolumeReadyQueue;
592 #endif
593 
594     // Lock for Shutdown/Flush operations that need to stop/start the queue
595     WDFWAITLOCK             ShutdownFlushWaitLock;
596 
597     // device specific data area
598     CDROM_DATA              DeviceAdditionalData;
599 
600     // scratch buffer related fields.
601     CDROM_SCRATCH_CONTEXT   ScratchContext;
602 
603     // Hold new private data that only classpnp should modify
604     // in this structure.
605     PCDROM_PRIVATE_FDO_DATA PrivateFdoData;
606 
607     // Work item for async reads and writes and its context
608     WDFWORKITEM                 ReadWriteWorkItem;
609     CDROM_READ_WRITE_CONTEXT    ReadWriteWorkItemContext;
610 
611     // Auxiliary WDF object for processing ioctl requests that need to go down
612     // to the port driver.
613     WDFWORKITEM             IoctlWorkItem;
614     CDROM_IOCTL_CONTEXT     IoctlWorkItemContext;
615 
616 } CDROM_DEVICE_EXTENSION, *PCDROM_DEVICE_EXTENSION;
617 
618 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_DEVICE_EXTENSION, DeviceGetExtension)
619 
620 // a type definition for functions to be called after synchronization
621 typedef
622 NTSTATUS
623 SYNC_HANDLER (
624     _In_ WDFDEVICE  Device,
625     _In_ WDFREQUEST Request
626     );
627 
628 typedef SYNC_HANDLER *PSYNC_HANDLER ;
629 
630 typedef struct _CDROM_REQUEST_CONTEXT {
631     PCDROM_DEVICE_EXTENSION     DeviceExtension;
632 
633     WDFREQUEST      OriginalRequest;
634 
635     LARGE_INTEGER   TimeReceived;
636     LARGE_INTEGER   TimeSentDownFirstTime;
637     LARGE_INTEGER   TimeSentDownLasttTime;
638 
639 
640     ULONG           RetriedCount;
641 
642     // Used to send down an incoming IOCTL in the original context
643     BOOLEAN         SyncRequired;
644     PKEVENT         SyncEvent;
645     PSYNC_HANDLER   SyncCallback;
646 
647     //
648     // Used for READ/WRITE requests.
649     // The reason why kernel primitives are used for the spinlock and
650     // the timer instead of WDF object is there is a race condition
651     // between the cancel callback and the timer routine.
652     // Because of this, the timer and the spin lock need to be associated
653     // per request rather than using shared memory in the device extension
654     // and it is possible for the WDF object initialization to fail whereas
655     // the kernel primitives initialize provided memory.  Initializing the
656     // kernel primitives will never fail.  Since READ/WRITE is a critical
657     // code path, it is not desired for READs or WRITEs to fail due to
658     // an allocation failure that can be avoided and because it is not
659     // uncommon to see a failure during a READ or WRITE that may not
660     // occur upon a retry.
661     //
662     KSPIN_LOCK      ReadWriteCancelSpinLock;
663     KTIMER          ReadWriteTimer;
664     KDPC            ReadWriteDpc;
665     BOOLEAN         ReadWriteIsCompleted;
666     BOOLEAN         ReadWriteRetryInitialized;
667 
668 } CDROM_REQUEST_CONTEXT, *PCDROM_REQUEST_CONTEXT;
669 
670 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDROM_REQUEST_CONTEXT, RequestGetContext)
671 
672 // Define context structure for asynchronous completions.
673 typedef struct _COMPLETION_CONTEXT {
674     WDFDEVICE           Device;
675     SCSI_REQUEST_BLOCK  Srb;
676 } COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT;
677 
678 
679 //
680 #define SCSI_CDROM_TIMEOUT          10
681 #define SCSI_CHANGER_BONUS_TIMEOUT  10
682 
683 //
684 // This value is used as the upper limit for all commands CDROM sends down
685 // to device, unless the default timeout value is overriden by registry value
686 // "TimeOutValue" and it is larger than this value.
687 //
688 #define SCSI_CDROM_OPC_TIMEOUT      260
689 
690 #define HITACHI_MODE_DATA_SIZE      12
691 #define MODE_DATA_SIZE              64
692 
693 #define RAW_SECTOR_SIZE           2352
694 #define COOKED_SECTOR_SIZE        2048
695 
696 #define CDROM_SRB_LIST_SIZE          4
697 
698 #define PLAY_ACTIVE(x) (x->DeviceAdditionalData.PlayActive)
699 
700 #define MSF_TO_LBA(Minutes,Seconds,Frames) \
701                 (ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
702 
703 // Sector types for READ_CD
704 
705 #define ANY_SECTOR                0
706 #define CD_DA_SECTOR              1
707 #define YELLOW_MODE1_SECTOR       2
708 #define YELLOW_MODE2_SECTOR       3
709 #define FORM2_MODE1_SECTOR        4
710 #define FORM2_MODE2_SECTOR        5
711 
712 #define MAX_COPY_PROTECT_AGID     4
713 
714 #ifdef ExAllocatePool
715     #undef ExAllocatePool
716     #define ExAllocatePool #assert(FALSE)
717 #endif
718 
719 // memory allocation tags
720 // Sc?? - Mass storage driver tags
721 // ScC<number> - Class driver misc allocations
722 // ScC? - CdRom
723 
724 #define CDROM_TAG_AUTORUN_DISABLE        'ACcS' // "ScCA" - Autorun disable functionality
725 #define CDROM_TAG_MEDIA_CHANGE_DETECTION 'aCcS' // "ScCa" - Media change detection
726 
727 #define CDROM_TAG_SCRATCH               'BCcS'  // "ScSB" - Scratch buffer (usually 64k)
728 #define CDROM_TAG_GET_CONFIG            'CCcS'  // "ScCC" - Ioctl GET_CONFIGURATION
729 #define CDROM_TAG_COMPLETION_CONTEXT    'cCcS'  // "ScCc" - Context of completion routine
730 #define CDROM_TAG_DESCRIPTOR            'DCcS'  // "ScCD" - Adaptor & Device descriptor buffer
731 #define CDROM_TAG_DISC_INFO             'dCcS'  // "ScCd" - Disc information
732 #define CDROM_TAG_SYNC_EVENT            'eCcS'  // "ScCe" - Request sync event
733 #define CDROM_TAG_FEATURE               'FCcS'  // "ScCF" - Feature descriptor
734 #define CDROM_TAG_GESN                  'GCcS'  // "ScCG" - GESN buffer
735 #define CDROM_TAG_SENSE_INFO            'ICcS'  // "ScCI" - Sense info buffers
736 #define CDROM_TAG_INQUIRY               'iCcS'  // "ScCi" - Cached inquiry buffer
737 #define CDROM_TAG_MODE_DATA             'MCcS'  // "ScCM" - Mode data buffer
738 #define CDROM_TAG_STREAM                'OCCS'  // "SCCO" - Set stream buffer
739 #define CDROM_TAG_NOTIFICATION          'oCcS'  // "ScCo" - Device Notification buffer
740 #define CDROM_TAG_PLAY_ACTIVE           'pCcS'  // "ScCp" - Play active checks
741 #define CDROM_TAG_REGISTRY              'rCcS'  // "ScCr" - Registry string
742 #define CDROM_TAG_SRB                   'SCcS'  // "ScCS" - Srb allocation
743 #define CDROM_TAG_STRINGS               'sCcS'  // "ScCs" - Assorted string data
744 #define CDROM_TAG_UPDATE_CAP            'UCcS'  // "ScCU" - Update capacity path
745 #define CDROM_TAG_ZERO_POWER_ODD        'ZCcS'  // "ScCZ" - Zero Power ODD
746 
747 #define DVD_TAG_READ_KEY                'uCcS'  // "ScCu" - Read buffer for dvd key
748 #define DVD_TAG_RPC2_CHECK              'VCcS'  // "ScCV" - Read buffer for dvd/rpc2 check
749 #define DVD_TAG_DVD_REGION              'vCcS'  // "ScCv" - Read buffer for rpc2 check
750 #define DVD_TAG_SECURITY                'XCcS'  // "ScCX" - Security descriptor
751 
752 
753 // registry keys and data entry names.
754 #define CDROM_SUBKEY_NAME                       (L"CdRom")  // store new settings here
755 #define CDROM_READ_CD_NAME                      (L"ReadCD") // READ_CD support previously detected
756 #define CDROM_NON_MMC_DRIVE_NAME                (L"NonMmc") // MMC commands hang
757 #define CDROM_TYPE_ONE_GET_CONFIG_NAME          (L"NoTypeOneGetConfig") // Type One Get Config commands not supported
758 #define CDROM_NON_MMC_VENDOR_SPECIFIC_PROFILE   (L"NonMmcVendorSpecificProfile") // GET_CONFIG returns vendor specific header
759                                                                                  // profiles that are not per spec (length divisible by 4)
760 #define DVD_DEFAULT_REGION          (L"DefaultDvdRegion")   // this is init. by the dvd class installer
761 #define DVD_MAX_REGION              8
762 
763 // AACS defines
764 #define AACS_MKB_PACK_SIZE  0x8000 // does not include header
765 
766 //enumeration of device interfaces need to be registered.
767 typedef enum {
768     CdRomDeviceInterface = 0,     // CdRomClassGuid
769     MountedDeviceInterface        // MOUNTDEV_MOUNTED_DEVICE_GUID
770 } CDROM_DEVICE_INTERFACES, *PCDROM_DEVICE_INTERFACES;
771 
772 
773 typedef
774 VOID
775 (*PCDROM_SCAN_FOR_SPECIAL_HANDLER) (
776     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
777     _In_ ULONG_PTR                Data
778     );
779 
780 // Rountines Definition
781 
782 #define FREE_POOL(_PoolPtr)     \
783     if (_PoolPtr != NULL) {     \
784         ExFreePool(_PoolPtr);   \
785         _PoolPtr = NULL;        \
786     }
787 
788 #define EXCLUSIVE_MODE(_CdData)                 (_CdData->ExclusiveOwner != NULL)
789 #define EXCLUSIVE_OWNER(_CdData, _FileObject)   (_CdData->ExclusiveOwner == _FileObject)
790 
791 #define IS_SCSIOP_READ(opCode)         \
792       ((opCode == SCSIOP_READ6)   ||   \
793        (opCode == SCSIOP_READ)    ||   \
794        (opCode == SCSIOP_READ12)  ||   \
795        (opCode == SCSIOP_READ16))
796 
797 #define IS_SCSIOP_WRITE(opCode)         \
798       ((opCode == SCSIOP_WRITE6)   ||   \
799        (opCode == SCSIOP_WRITE)    ||   \
800        (opCode == SCSIOP_WRITE12)  ||   \
801        (opCode == SCSIOP_WRITE16))
802 
803 #define IS_SCSIOP_READWRITE(opCode)  (IS_SCSIOP_READ(opCode) || IS_SCSIOP_WRITE(opCode))
804 
805 // Bit Flag Macros
806 #define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
807 #define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
808 #define TEST_FLAG(Flags, Bit)   (((Flags) & (Bit)) != 0)
809 
810 FORCEINLINE // __REACTOS__
811 BOOLEAN
812 ValidChar(UCHAR Ch)
813 {
814     if (((Ch >= '0') && (Ch <= '9')) ||
815         (((Ch|0x20) >= 'a') && ((Ch|0x20) <= 'z')) ||
816         (strchr(" .,:;_-", Ch) != NULL))
817     {
818         return TRUE;
819     }
820     return FALSE;
821 }
822 
823 // could be #define, but this allows typechecking
824 FORCEINLINE // __REACTOS__
825 BOOLEAN
826 PORT_ALLOCATED_SENSE(
827     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
828     _In_ PSCSI_REQUEST_BLOCK      Srb
829     )
830 {
831     UNREFERENCED_PARAMETER(DeviceExtension);
832     return (BOOLEAN)((TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE) &&
833              TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER))
834             );
835 }
836 
837 FORCEINLINE // __REACTOS__
838 VOID
839 FREE_PORT_ALLOCATED_SENSE_BUFFER(
840     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
841     _In_ PSCSI_REQUEST_BLOCK      Srb
842     )
843 {
844 #ifndef DEBUG
845     UNREFERENCED_PARAMETER(DeviceExtension);
846 #endif
847     NT_ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE));
848     NT_ASSERT(TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
849     NT_ASSERT(Srb->SenseInfoBuffer != DeviceExtension->SenseData);
850 
851     ExFreePool(Srb->SenseInfoBuffer);
852     Srb->SenseInfoBuffer = NULL;
853     Srb->SenseInfoBufferLength = 0;
854     CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER);
855     return;
856 }
857 
858 // Standard driver entry function
859 DRIVER_INITIALIZE DriverEntry;
860 
861 // Driver Event callbacks
862 EVT_WDF_DRIVER_DEVICE_ADD DriverEvtDeviceAdd;
863 
864 EVT_WDF_OBJECT_CONTEXT_CLEANUP DriverEvtCleanup;
865 
866 // Device Event callbacks
867 
868 EVT_WDF_OBJECT_CONTEXT_CLEANUP DeviceEvtCleanup;
869 
870 EVT_WDF_FILE_CLOSE DeviceEvtFileClose;
871 
872 EVT_WDF_IO_IN_CALLER_CONTEXT DeviceEvtIoInCallerContext;
873 
874 EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT DeviceEvtSelfManagedIoInit;
875 
876 EVT_WDF_DEVICE_SELF_MANAGED_IO_CLEANUP DeviceEvtSelfManagedIoCleanup;
877 
878 EVT_WDF_DEVICE_D0_ENTRY DeviceEvtD0Entry;
879 
880 EVT_WDF_DEVICE_D0_EXIT DeviceEvtD0Exit;
881 
882 EVT_WDF_DEVICE_SURPRISE_REMOVAL DeviceEvtSurpriseRemoval;
883 
884 // Create Queue Event callbacks
885 
886 EVT_WDF_IO_QUEUE_IO_DEFAULT CreateQueueEvtIoDefault;
887 
888 // Sequential Queue Event callbacks
889 
890 // We do not use KMDF annotation for the following function, because it handles
891 // both read and write requests and there is no single annotation for that.
892 VOID
893 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
894 SequentialQueueEvtIoReadWrite(
895     _In_ WDFQUEUE     Queue,
896     _In_ WDFREQUEST   Request,
897     _In_ size_t       Length
898     );
899 
900 EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SequentialQueueEvtIoDeviceControl;
901 
902 EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SequentialQueueEvtCanceledOnQueue;
903 
904 // Miscellaneous request callbacks
905 
906 EVT_WDF_OBJECT_CONTEXT_CLEANUP RequestEvtCleanup;
907 
908 EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessShutdownFlush;
909 
910 EVT_WDFDEVICE_WDM_IRP_PREPROCESS RequestProcessSetPower;
911 
912 
913 // helper functions
914 
915 _IRQL_requires_max_(PASSIVE_LEVEL)
916 NTSTATUS
917 DeviceClaimRelease(
918     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
919     _In_ BOOLEAN      Release
920     );
921 
922 _IRQL_requires_max_(APC_LEVEL)
923 VOID
924 DeviceReleaseMcnResources(
925     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
926     );
927 
928 _IRQL_requires_max_(PASSIVE_LEVEL)
929 NTSTATUS
930 DeviceRetrieveDescriptor(
931     _In_ WDFDEVICE                              Device,
932     _In_ PSTORAGE_PROPERTY_ID                   PropertyId,
933     _Outptr_ PSTORAGE_DESCRIPTOR_HEADER*        Descriptor
934     );
935 
936 _IRQL_requires_max_(PASSIVE_LEVEL)
937 VOID
938 DeviceRetrieveHackFlagsFromRegistry(
939     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
940     );
941 
942 _IRQL_requires_max_(APC_LEVEL)
943 VOID
944 DeviceHackFlagsScan(
945     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
946     _In_ ULONG_PTR                Data
947     );
948 
949 _IRQL_requires_max_(APC_LEVEL)
950 BOOLEAN
951 StringsAreMatched(
952     _In_opt_z_ PCHAR StringToMatch,
953     _In_z_     PCHAR TargetString
954     );
955 
956 _IRQL_requires_max_(PASSIVE_LEVEL)
957 VOID
958 DeviceGetParameter(
959     _In_ PCDROM_DEVICE_EXTENSION    DeviceExtension,
960     _In_opt_ PWSTR                  SubkeyName,
961     _In_ PWSTR                      ParameterName,
962     _Inout_ PULONG                  ParameterValue  // also default value
963     );
964 
965 _IRQL_requires_max_(PASSIVE_LEVEL)
966 NTSTATUS
967 DeviceSetParameter(
968     _In_ PCDROM_DEVICE_EXTENSION    DeviceExtension,
969     _In_opt_z_ PWSTR                SubkeyName,
970     _In_ PWSTR                      ParameterName,
971     _In_ ULONG                      ParameterValue
972     );
973 
974 _IRQL_requires_max_(PASSIVE_LEVEL)
975 ULONG
976 DeviceGetTimeOutValueFromRegistry();
977 
978 _IRQL_requires_max_(APC_LEVEL)
979 VOID
980 ScanForSpecialHandler(
981     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
982     _In_ ULONG_PTR               HackFlags
983     );
984 
985 _IRQL_requires_max_(PASSIVE_LEVEL)
986 NTSTATUS
987 DeviceSendSrbSynchronously(
988     _In_ WDFDEVICE           Device,
989     _In_ PSCSI_REQUEST_BLOCK Srb,
990     _In_opt_ PVOID           BufferAddress,
991     _In_ ULONG               BufferLength,
992     _In_ BOOLEAN             WriteToDevice,
993     _In_opt_ WDFREQUEST      OriginalRequest
994     );
995 
996 BOOLEAN
997 RequestSenseInfoInterpret(
998     _In_      PCDROM_DEVICE_EXTENSION   DeviceExtension,
999     _In_      WDFREQUEST                Request, // get IRP MJ code, IoControlCode from it (or attached original request)
1000     _In_      PSCSI_REQUEST_BLOCK       Srb,
1001     _In_      ULONG                     RetriedCount,
1002     _Out_     NTSTATUS*                 Status,
1003     _Out_opt_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
1004               LONGLONG*                 RetryIntervalIn100ns
1005     );
1006 
1007 VOID
1008 RequestSetReceivedTime(
1009     _In_ WDFREQUEST Request
1010     );
1011 
1012 VOID
1013 RequestSetSentTime(
1014     _In_ WDFREQUEST Request
1015     );
1016 
1017 VOID
1018 RequestClearSendTime(
1019     _In_ WDFREQUEST Request
1020     );
1021 
1022 BOOLEAN
1023 RequestSenseInfoInterpretForScratchBuffer(
1024     _In_    PCDROM_DEVICE_EXTENSION DeviceExtension,
1025     _In_    ULONG                   RetriedCount,
1026     _Out_   NTSTATUS*               Status,
1027     _Out_ _Deref_out_range_(0, MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
1028             LONGLONG*               RetryIntervalIn100ns
1029     );
1030 
1031 
1032 VOID
1033 DeviceSendNotification(
1034     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1035     _In_ const GUID*              Guid,
1036     _In_ ULONG                    ExtraDataSize,
1037     _In_opt_ PVOID                ExtraData
1038     );
1039 
1040 VOID
1041 DeviceSendStartUnit(
1042     _In_ WDFDEVICE Device
1043     );
1044 
1045 EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceAsynchronousCompletion;
1046 
1047 VOID
1048 DeviceReleaseQueue(
1049     _In_ WDFDEVICE    Device
1050     );
1051 
1052 EVT_WDF_REQUEST_COMPLETION_ROUTINE DeviceReleaseQueueCompletion;
1053 
1054 VOID
1055 DevicePerfIncrementErrorCount(
1056     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1057     );
1058 
1059 _IRQL_requires_max_(PASSIVE_LEVEL)
1060 NTSTATUS
1061 DeviceCacheDeviceInquiryData(
1062     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1063     );
1064 
1065 _IRQL_requires_max_(APC_LEVEL)
1066 NTSTATUS
1067 DeviceCacheGetConfigurationData(
1068     _In_  WDFDEVICE     Device
1069     );
1070 
1071 _IRQL_requires_max_(APC_LEVEL)
1072 PVOID
1073 DeviceFindFeaturePage(
1074     _In_reads_bytes_(Length) PGET_CONFIGURATION_HEADER   FeatureBuffer,
1075     _In_ ULONG const                                Length,
1076     _In_ FEATURE_NUMBER const                       Feature
1077     );
1078 
1079 _IRQL_requires_max_(APC_LEVEL)
1080 VOID
1081 DevicePrintAllFeaturePages(
1082     _In_reads_bytes_(Usable) PGET_CONFIGURATION_HEADER   Buffer,
1083     _In_ ULONG const                                Usable
1084     );
1085 
1086 _IRQL_requires_max_(APC_LEVEL)
1087 NTSTATUS
1088 DeviceSetRawReadInfo(
1089     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1090     );
1091 
1092 _IRQL_requires_max_(PASSIVE_LEVEL)
1093 NTSTATUS
1094 MediaReadCapacity(
1095     _In_ WDFDEVICE Device
1096     );
1097 
1098 _IRQL_requires_max_(APC_LEVEL)
1099 VOID
1100 MediaReadCapacityDataInterpret(
1101     _In_ WDFDEVICE            Device,
1102     _In_ PREAD_CAPACITY_DATA  ReadCapacityBuffer
1103     );
1104 
1105 _IRQL_requires_max_(APC_LEVEL)
1106 NTSTATUS
1107 DeviceInitReleaseQueueContext(
1108     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1109     );
1110 
1111 _IRQL_requires_max_(APC_LEVEL)
1112 NTSTATUS
1113 DeviceInitPowerContext(
1114     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1115     );
1116 
1117 _IRQL_requires_max_(APC_LEVEL)
1118 NTSTATUS
1119 DeviceCreateWellKnownName(
1120     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1121     );
1122 
1123 _IRQL_requires_max_(APC_LEVEL)
1124 NTSTATUS
1125 DeviceInitializeDvd(
1126     _In_ WDFDEVICE Device
1127     );
1128 
1129 _IRQL_requires_max_(APC_LEVEL)
1130 VOID
1131 DevicePickDvdRegion(
1132     _In_ WDFDEVICE Device
1133     );
1134 
1135 _IRQL_requires_max_(PASSIVE_LEVEL)
1136 NTSTATUS
1137 DeviceRegisterInterface(
1138     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1139     _In_ CDROM_DEVICE_INTERFACES InterfaceType
1140     );
1141 
1142 _IRQL_requires_max_(DISPATCH_LEVEL)
1143 NTSTATUS
1144 DeviceSendPowerDownProcessRequest(
1145     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1146     _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine,
1147     _In_opt_ WDFCONTEXT Context
1148     );
1149 
1150 _IRQL_requires_max_(APC_LEVEL)
1151 VOID
1152 DeviceScanForSpecial(
1153     _In_ PCDROM_DEVICE_EXTENSION          DeviceExtension,
1154     _In_ CDROM_SCAN_FOR_SPECIAL_INFO      DeviceList[],
1155     _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER  Function
1156     );
1157 
1158 _IRQL_requires_max_(PASSIVE_LEVEL)
1159 NTSTATUS
1160 DeviceInitializeHotplugInfo(
1161     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1162     );
1163 
1164 NTSTATUS
1165 DeviceErrorHandlerForMmc(
1166     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1167     _In_ PSCSI_REQUEST_BLOCK      Srb,
1168     _Inout_ PNTSTATUS             Status,
1169     _Inout_ PBOOLEAN              Retry
1170     );
1171 
1172 NTSTATUS
1173 DeviceErrorHandlerForHitachiGD2000(
1174     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1175     _In_ PSCSI_REQUEST_BLOCK      Srb,
1176     _Inout_ PNTSTATUS             Status,
1177     _Inout_ PBOOLEAN              Retry
1178     );
1179 
1180 EVT_WDF_WORKITEM DeviceRestoreDefaultSpeed;
1181 
1182 _IRQL_requires_max_(PASSIVE_LEVEL)
1183 NTSTATUS
1184 DeviceInitializeMediaChangeDetection(
1185     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension
1186     );
1187 
1188 VOID
1189 DeviceSetMediaChangeStateEx(
1190     _In_        PCDROM_DEVICE_EXTENSION       DeviceExtension,
1191     _In_        MEDIA_CHANGE_DETECTION_STATE  NewState,
1192     _Inout_opt_ PMEDIA_CHANGE_DETECTION_STATE OldState
1193     );
1194 
1195 _IRQL_requires_max_(APC_LEVEL)
1196 VOID
1197 DeviceSendDelayedMediaChangeNotifications(
1198     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1199     );
1200 
1201 NTSTATUS
1202 RequestSynchronizeProcessWithSerialQueue(
1203     _In_ WDFDEVICE Device,
1204     _In_ WDFREQUEST Request
1205     );
1206 
1207 _IRQL_requires_max_(PASSIVE_LEVEL)
1208 NTSTATUS
1209 DeviceCleanupProtectedLocks(
1210     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1211     _In_ PFILE_OBJECT_CONTEXT     FileObjectContext
1212     );
1213 
1214 _IRQL_requires_max_(APC_LEVEL)
1215 NTSTATUS
1216 DeviceCleanupDisableMcn(
1217     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1218     _In_ PFILE_OBJECT_CONTEXT     FileObjectContext
1219     );
1220 
1221 _IRQL_requires_max_(APC_LEVEL)
1222 NTSTATUS
1223 DeviceUnlockExclusive(
1224     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1225     _In_ WDFFILEOBJECT            FileObject,
1226     _In_ BOOLEAN                  IgnorePreviousMediaChanges
1227     );
1228 
1229 _IRQL_requires_max_(PASSIVE_LEVEL)
1230 NTSTATUS
1231 RequestProcessSerializedIoctl(
1232     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1233     _In_ WDFREQUEST               Request
1234     );
1235 
1236 NTSTATUS
1237 RequestIsIoctlBlockedByExclusiveAccess(
1238     _In_  WDFREQUEST  Request,
1239     _Out_ PBOOLEAN    IsBlocked
1240     );
1241 
1242 _IRQL_requires_max_(APC_LEVEL)
1243 NTSTATUS
1244 DeviceSendRequestSynchronously(
1245     _In_ WDFDEVICE    Device,
1246     _In_ WDFREQUEST   Request,
1247     _In_ BOOLEAN      RequestFormated
1248     );
1249 
1250 VOID
1251 DeviceSendIoctlAsynchronously(
1252     _In_ PCDROM_DEVICE_EXTENSION    DeviceExtension,
1253     _In_ ULONG                      IoControlCode,
1254     _In_ PDEVICE_OBJECT             TargetDeviceObject
1255     );
1256 
1257 IO_COMPLETION_ROUTINE RequestAsynchronousIrpCompletion;
1258 
1259 //  MMC Update functions
1260 
1261 BOOLEAN
1262 DeviceIsMmcUpdateRequired(
1263     _In_ WDFDEVICE    Device
1264     );
1265 
1266 // Helper functions
1267 
1268 _IRQL_requires_max_(APC_LEVEL)
1269 VOID
1270 DeviceEnableMediaChangeDetection(
1271     _In_    PCDROM_DEVICE_EXTENSION DeviceExtension,
1272     _Inout_ PFILE_OBJECT_CONTEXT    FileObjectContext,
1273     _In_    BOOLEAN                 IgnorePreviousMediaChanges
1274     );
1275 
1276 _IRQL_requires_max_(APC_LEVEL)
1277 VOID
1278 DeviceDisableMediaChangeDetection(
1279     _In_    PCDROM_DEVICE_EXTENSION DeviceExtension,
1280     _Inout_ PFILE_OBJECT_CONTEXT    FileObjectContext
1281     );
1282 
1283 NTSTATUS
1284 RequestSetContextFields(
1285     _In_ WDFREQUEST    Request,
1286     _In_ PSYNC_HANDLER Handler
1287     );
1288 
1289 _IRQL_requires_max_(APC_LEVEL)
1290 BOOLEAN
1291 DeviceIsPlayActive(
1292     _In_ WDFDEVICE Device
1293     );
1294 
1295 NTSTATUS
1296 RequestDuidGetDeviceIdProperty(
1297     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1298     _In_ WDFREQUEST              Request,
1299     _In_ WDF_REQUEST_PARAMETERS  RequestParameters,
1300     _Out_ size_t *               DataLength
1301     );
1302 
1303 NTSTATUS
1304 RequestDuidGetDeviceProperty(
1305     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1306     _In_ WDFREQUEST              Request,
1307     _In_ WDF_REQUEST_PARAMETERS  RequestParameters,
1308     _Out_ size_t *               DataLength
1309     );
1310 
1311 _IRQL_requires_max_(APC_LEVEL)
1312 ULONG
1313 DeviceRetrieveModeSenseUsingScratch(
1314     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1315     _In_reads_bytes_(Length) PCHAR     ModeSenseBuffer,
1316     _In_ ULONG                    Length,
1317     _In_ UCHAR                    PageCode,
1318     _In_ UCHAR                    PageControl
1319     );
1320 
1321 _IRQL_requires_max_(APC_LEVEL)
1322 PVOID
1323 ModeSenseFindSpecificPage(
1324     _In_reads_bytes_(Length) PCHAR   ModeSenseBuffer,
1325     _In_ size_t                 Length,
1326     _In_ UCHAR                  PageMode,
1327     _In_ BOOLEAN                Use6Byte
1328     );
1329 
1330 _IRQL_requires_max_(PASSIVE_LEVEL)
1331 NTSTATUS
1332 PerformEjectionControl(
1333     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1334     _In_ WDFREQUEST               Request,
1335     _In_ MEDIA_LOCK_TYPE          LockType,
1336     _In_ BOOLEAN                  Lock
1337     );
1338 
1339 _IRQL_requires_max_(PASSIVE_LEVEL)
1340 VOID
1341 DeviceDisableMainTimer(
1342     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1343     );
1344 
1345 _IRQL_requires_max_(APC_LEVEL)
1346 NTSTATUS
1347 DeviceEnableMainTimer(
1348     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1349     );
1350 
1351 EVT_WDF_TIMER DeviceMainTimerTickHandler;
1352 
1353 VOID
1354 RequestSetupMcnSyncIrp(
1355     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1356     );
1357 
1358 _IRQL_requires_max_(APC_LEVEL)
1359 NTSTATUS
1360 RequestSetupMcnRequest(
1361     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension,
1362     _In_ BOOLEAN                  UseGesn
1363     );
1364 
1365 _IRQL_requires_max_(APC_LEVEL)
1366 BOOLEAN
1367 RequestSendMcnRequest(
1368     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension
1369     );
1370 
1371 _IRQL_requires_max_(APC_LEVEL)
1372 BOOLEAN
1373 RequestPostWorkMcnRequest(
1374     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension
1375     );
1376 
1377 _IRQL_requires_max_(DISPATCH_LEVEL)
1378 NTSTATUS
1379 PowerContextReuseRequest(
1380     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1381     );
1382 
1383 _IRQL_requires_max_(DISPATCH_LEVEL)
1384 NTSTATUS
1385 PowerContextBeginUse(
1386     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1387     );
1388 
1389 _IRQL_requires_max_(DISPATCH_LEVEL)
1390 NTSTATUS
1391 PowerContextEndUse(
1392     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1393     );
1394 
1395 POWER_SETTING_CALLBACK DevicePowerSettingCallback;
1396 
1397 //  Zero Power ODD functions
1398 
1399 _IRQL_requires_max_(PASSIVE_LEVEL)
1400 NTSTATUS
1401 DeviceInitializeZPODD(
1402     _In_ PCDROM_DEVICE_EXTENSION  DeviceExtension
1403     );
1404 
1405 _IRQL_requires_max_(APC_LEVEL)
1406 VOID
1407 DeviceReleaseZPODDResources(
1408     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1409     );
1410 
1411 NTSTATUS
1412 DeviceZPODDGetPowerupReason(
1413     _In_    PCDROM_DEVICE_EXTENSION         DeviceExtension,
1414     _Out_   PSTORAGE_IDLE_POWERUP_REASON    PowerupReason
1415     );
1416 
1417 _IRQL_requires_max_(PASSIVE_LEVEL)
1418 BOOLEAN
1419 DeviceZPODDIsInHomePosition(
1420     _In_    PCDROM_DEVICE_EXTENSION DeviceExtension
1421     );
1422 
1423 _IRQL_requires_max_(PASSIVE_LEVEL)
1424 VOID
1425 DeviceMarkActive(
1426     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1427     _In_ BOOLEAN                 IsActive,
1428     _In_ BOOLEAN                 SetIdleTimeout
1429     );
1430 
1431 // common routines for specific IOCTL process
1432 
1433 _IRQL_requires_max_(APC_LEVEL)
1434 NTSTATUS
1435 DvdStartSessionReadKey(
1436     _In_  PCDROM_DEVICE_EXTENSION  DeviceExtension,
1437     _In_  ULONG                    IoControlCode,
1438     _In_opt_  WDFREQUEST           OriginalRequest,
1439     _In_opt_  PVOID                InputBuffer,
1440     _In_  size_t                   InputBufferLength,
1441     _In_  PVOID                    OutputBuffer,
1442     _In_  size_t                   OutputBufferLength,
1443     _Out_ size_t *                 DataLength
1444     );
1445 
1446 _IRQL_requires_max_(APC_LEVEL)
1447 NTSTATUS
1448 ReadDvdStructure(
1449     _In_  PCDROM_DEVICE_EXTENSION  DeviceExtension,
1450     _In_opt_  WDFREQUEST           OriginalRequest,
1451     _In_  PVOID                    InputBuffer,
1452     _In_  size_t                   InputBufferLength,
1453     _In_  PVOID                    OutputBuffer,
1454     _In_  size_t                   OutputBufferLength,
1455     _Out_ size_t *                 DataLength
1456     );
1457 
1458 _IRQL_requires_max_(APC_LEVEL)
1459 NTSTATUS
1460 ReadQChannel(
1461     _In_  PCDROM_DEVICE_EXTENSION  DeviceExtension,
1462     _In_opt_  WDFREQUEST           OriginalRequest,
1463     _In_  PVOID                    InputBuffer,
1464     _In_  size_t                   InputBufferLength,
1465     _In_  PVOID                    OutputBuffer,
1466     _In_  size_t                   OutputBufferLength,
1467     _Out_ size_t *                 DataLength
1468     );
1469 
1470 _IRQL_requires_max_(APC_LEVEL)
1471 NTSTATUS
1472 DvdSendKey(
1473     _In_  PCDROM_DEVICE_EXTENSION  DeviceExtension,
1474     _In_opt_  WDFREQUEST           OriginalRequest,
1475     _In_  PVOID                    InputBuffer,
1476     _In_  size_t                   InputBufferLength,
1477     _Out_ size_t *                 DataLength
1478     );
1479 
1480 
1481 #ifndef SIZEOF_ARRAY
1482     #define SIZEOF_ARRAY(ar)        (sizeof(ar)/sizeof((ar)[0]))
1483 #endif // !defined(SIZEOF_ARRAY)
1484 
1485 
1486 // 100us to seconds
1487 #define UNIT_100NS_PER_SECOND (10*1000*1000)
1488 #define SECONDS_TO_100NS_UNITS(x) (((LONGLONG)x) * UNIT_100NS_PER_SECOND)
1489 
1490 //
1491 // Bit Flag Macros
1492 //
1493 #define SET_FLAG(Flags, Bit)    ((Flags) |= (Bit))
1494 #define CLEAR_FLAG(Flags, Bit)  ((Flags) &= ~(Bit))
1495 #define TEST_FLAG(Flags, Bit)   (((Flags) & (Bit)) != 0)
1496 
1497 //
1498 // neat little hacks to count number of bits set efficiently
1499 //
1500 FORCEINLINE ULONG CountOfSetBitsUChar(UCHAR _X)
1501                     { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
1502 FORCEINLINE ULONG CountOfSetBitsULong(ULONG _X)
1503                     { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
1504 FORCEINLINE ULONG CountOfSetBitsULong32(ULONG32 _X)
1505                     { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
1506 FORCEINLINE ULONG CountOfSetBitsULong64(ULONG64 _X)
1507                     { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
1508 FORCEINLINE ULONG CountOfSetBitsUlongPtr(ULONG_PTR _X)
1509                     { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
1510 
1511 
1512 FORCEINLINE // __REACTOS__
1513 BOOLEAN
1514 IsVolumeMounted(
1515     _In_ PDEVICE_OBJECT DeviceObject
1516     )
1517 {
1518 #pragma prefast(push)
1519 #pragma prefast(disable: 28175, "there is no other way to check if there is volume mounted")
1520     return (DeviceObject->Vpb != NULL) &&
1521            ((DeviceObject->Vpb->Flags & VPB_MOUNTED) != 0);
1522 #pragma prefast(pop)
1523 }
1524 
1525 
1526 FORCEINLINE _Ret_range_(0,MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS)
1527 LONGLONG
1528 ConvertSectorsPerSecondTo100nsUnitsFor64kWrite(
1529     _In_range_(1,0xFFFFFFFF) ULONG SectorsPerSecond // zero would cause divide-by-zero
1530     )
1531 {
1532     //     64k write
1533     // ---------------- == time per 64k write
1534     //  sectors/second
1535     //
1536     //  (32 / N) == seconds
1537     //  (32 / N) * (1,000,000,000) == nanoseconds
1538     //  (32 / N) * (1,000,000,000) / 100 == 100ns increments
1539     //  (32 * 10,000,000) / N == 100ns increments
1540     //
1541     //  320,000,000 / N == 100ns increments
1542     //  And this is safe to run in kernel-mode (no floats)
1543     //
1544 
1545     // this assert ensures that we _never_ can return a value
1546     // larger than the maximum allowed.
1547     C_ASSERT(320000000 < MAXIMUM_RETRY_FOR_SINGLE_IO_IN_100NS_UNITS);
1548 
1549     return 320000000 / SectorsPerSecond;
1550 }
1551 
1552 FORCEINLINE // __REACTOS__
1553 UCHAR
1554 RequestGetCurrentStackLocationFlags(
1555     _In_ WDFREQUEST Request
1556     )
1557 {
1558     PIRP                irp = NULL;
1559     PIO_STACK_LOCATION  currentStack = NULL;
1560 
1561     irp = WdfRequestWdmGetIrp(Request);
1562     currentStack = IoGetCurrentIrpStackLocation(irp);
1563 
1564     return currentStack->Flags;
1565 }
1566 
1567 FORCEINLINE // __REACTOS__
1568 ULONG
1569 TimeOutValueGetCapValue(
1570     _In_ ULONG  TimeOutValue,
1571     _In_ ULONG  Times
1572     )
1573 {
1574     ULONG   value = 0;
1575 
1576     if (TimeOutValue > SCSI_CDROM_OPC_TIMEOUT)
1577     {
1578         // if time out value is specified by user in registry, and is
1579         // bigger than OPC time out, it should be big enough
1580         value = TimeOutValue;
1581     }
1582     else
1583     {
1584         // otherwise, OPC time out value should be the upper limit
1585         value = min(TimeOutValue * Times, SCSI_CDROM_OPC_TIMEOUT);
1586     }
1587 
1588     return value;
1589 }
1590 
1591 VOID
1592 RequestCompletion(
1593     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension,
1594     _In_ WDFREQUEST              Request,
1595     _In_ NTSTATUS                Status,
1596     _In_ ULONG_PTR               Information
1597     );
1598 
1599 NTSTATUS
1600 RequestSend(
1601     _In_        PCDROM_DEVICE_EXTENSION DeviceExtension,
1602     _In_        WDFREQUEST              Request,
1603     _In_        WDFIOTARGET             IoTarget,
1604     _In_        ULONG                   Flags,
1605     _Out_opt_   PBOOLEAN                RequestSent
1606     );
1607 
1608 EVT_WDF_REQUEST_COMPLETION_ROUTINE RequestDummyCompletionRoutine;
1609 
1610 VOID
1611 RequestProcessInternalDeviceControl(
1612     _In_ WDFREQUEST              Request,
1613     _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
1614     );
1615 
1616 EVT_WDF_WORKITEM IoctlWorkItemRoutine;
1617 
1618 EVT_WDF_WORKITEM ReadWriteWorkItemRoutine;
1619 
1620 #pragma warning(pop) // un-sets any local warning changes
1621 
1622 #endif // __CDROMP_H__
1623 
1624 
1625