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
ValidChar(UCHAR Ch)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
PORT_ALLOCATED_SENSE(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ PSCSI_REQUEST_BLOCK Srb)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
FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PCDROM_DEVICE_EXTENSION DeviceExtension,_In_ PSCSI_REQUEST_BLOCK Srb)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 //
CountOfSetBitsUChar(UCHAR _X)1500 FORCEINLINE ULONG CountOfSetBitsUChar(UCHAR _X)
1501 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong(ULONG _X)1502 FORCEINLINE ULONG CountOfSetBitsULong(ULONG _X)
1503 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong32(ULONG32 _X)1504 FORCEINLINE ULONG CountOfSetBitsULong32(ULONG32 _X)
1505 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsULong64(ULONG64 _X)1506 FORCEINLINE ULONG CountOfSetBitsULong64(ULONG64 _X)
1507 { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
CountOfSetBitsUlongPtr(ULONG_PTR _X)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
IsVolumeMounted(_In_ PDEVICE_OBJECT DeviceObject)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
RequestGetCurrentStackLocationFlags(_In_ WDFREQUEST Request)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
TimeOutValueGetCapValue(_In_ ULONG TimeOutValue,_In_ ULONG Times)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