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