3 Copyright (C) Microsoft Corporation, 1999 - 1999
11 The CDROM class driver tranlates IRPs to SRBs with embedded CDBs
12 and sends them to its devices through the port driver.
20 SCSI Tape, CDRom and Disk class drivers share common routines
21 that can be found in the CLASS directory (..\ntos\dd\class).
41 PUCHAR READ_DVD_STRUCTURE_FORMAT_STRINGS
[DvdMaxDescriptor
+1] = {
51 #define DEFAULT_CDROM_SECTORS_PER_TRACK 32
52 #define DEFAULT_TRACKS_PER_CYLINDER 64
56 CdRomDeviceControlDispatch(
57 IN PDEVICE_OBJECT DeviceObject
,
64 This is the NT device control handler for CDROMs.
68 DeviceObject - for this CDROM
70 Irp - IO Request packet
78 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
79 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
81 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
82 PIO_STACK_LOCATION nextStack
;
83 PCDROM_DATA cdData
= (PCDROM_DATA
)(commonExtension
->DriverData
);
85 BOOLEAN use6Byte
= TEST_FLAG(cdData
->XAFlags
, XA_USE_6_BYTE
);
86 SCSI_REQUEST_BLOCK srb
;
87 PCDB cdb
= (PCDB
)srb
.Cdb
;
89 ULONG bytesTransferred
= 0;
101 // Zero the SRB on stack.
104 RtlZeroMemory(&srb
, sizeof(SCSI_REQUEST_BLOCK
));
106 Irp
->IoStatus
.Information
= 0;
109 // if this is a class driver ioctl then we need to change the base code
110 // to IOCTL_CDROM_BASE so that the switch statement can handle it.
112 // WARNING - currently the scsi class ioctl function codes are between
113 // 0x200 & 0x300. this routine depends on that fact
116 ioctlCode
= irpStack
->Parameters
.DeviceIoControl
.IoControlCode
;
117 baseCode
= ioctlCode
>> 16;
118 functionCode
= (ioctlCode
& (~0xffffc003)) >> 2;
120 TraceLog((CdromDebugTrace
,
121 "CdRomDeviceControl: Ioctl Code = %lx, Base Code = %lx,"
122 " Function Code = %lx\n",
128 if((functionCode
>= 0x200) && (functionCode
<= 0x300)) {
130 ioctlCode
= (ioctlCode
& 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE
, 0, 0, 0);
132 TraceLog((CdromDebugTrace
,
133 "CdRomDeviceControl: Class Code - new ioctl code is %lx\n",
136 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
= ioctlCode
;
142 case IOCTL_STORAGE_GET_MEDIA_TYPES_EX
: {
144 PGET_MEDIA_TYPES mediaTypes
= Irp
->AssociatedIrp
.SystemBuffer
;
145 PDEVICE_MEDIA_INFO mediaInfo
= &mediaTypes
->MediaInfo
[0];
148 sizeNeeded
= sizeof(GET_MEDIA_TYPES
);
151 // IsMmc is static...
154 if (cdData
->Mmc
.IsMmc
) {
155 sizeNeeded
+= sizeof(DEVICE_MEDIA_INFO
) * 1; // return two media types
159 // Ensure that buffer is large enough.
162 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
169 Irp
->IoStatus
.Information
= sizeNeeded
;
170 status
= STATUS_BUFFER_TOO_SMALL
;
174 RtlZeroMemory(Irp
->AssociatedIrp
.SystemBuffer
, sizeNeeded
);
177 // ISSUE-2000/5/11-henrygab - need to update GET_MEDIA_TYPES_EX
180 mediaTypes
->DeviceType
= CdRomGetDeviceType(DeviceObject
);
182 mediaTypes
->MediaInfoCount
= 1;
183 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaType
= CD_ROM
;
184 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.NumberMediaSides
= 1;
185 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaCharacteristics
= MEDIA_READ_ONLY
;
186 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.Cylinders
.QuadPart
= fdoExtension
->DiskGeometry
.Cylinders
.QuadPart
;
187 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.TracksPerCylinder
= fdoExtension
->DiskGeometry
.TracksPerCylinder
;
188 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.SectorsPerTrack
= fdoExtension
->DiskGeometry
.SectorsPerTrack
;
189 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.BytesPerSector
= fdoExtension
->DiskGeometry
.BytesPerSector
;
191 if (cdData
->Mmc
.IsMmc
) {
194 // also report a removable disk
196 mediaTypes
->MediaInfoCount
+= 1;
199 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaType
= RemovableMedia
;
200 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.NumberMediaSides
= 1;
201 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaCharacteristics
= MEDIA_READ_WRITE
;
202 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.Cylinders
.QuadPart
= fdoExtension
->DiskGeometry
.Cylinders
.QuadPart
;
203 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.TracksPerCylinder
= fdoExtension
->DiskGeometry
.TracksPerCylinder
;
204 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.SectorsPerTrack
= fdoExtension
->DiskGeometry
.SectorsPerTrack
;
205 mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.BytesPerSector
= fdoExtension
->DiskGeometry
.BytesPerSector
;
211 // Status will either be success, if media is present, or no media.
212 // It would be optimal to base from density code and medium type, but not all devices
213 // have values for these fields.
217 // Send a TUR to determine if media is present.
222 cdb
->CDB6GENERIC
.OperationCode
= SCSIOP_TEST_UNIT_READY
;
225 // Set timeout value.
228 srb
.TimeOutValue
= fdoExtension
->TimeOutValue
;
230 status
= ClassSendSrbSynchronous(DeviceObject
,
237 TraceLog((CdromDebugWarning
,
238 "CdRomDeviceControl: GET_MEDIA_TYPES status of TUR - %lx\n",
241 if (NT_SUCCESS(status
)) {
244 // set the disk's media as current if we can write to it.
247 if (cdData
->Mmc
.IsMmc
&& cdData
->Mmc
.WriteAllowed
) {
250 SET_FLAG(mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaCharacteristics
,
251 MEDIA_CURRENTLY_MOUNTED
);
257 SET_FLAG(mediaInfo
->DeviceSpecific
.RemovableDiskInfo
.MediaCharacteristics
,
258 MEDIA_CURRENTLY_MOUNTED
);
264 Irp
->IoStatus
.Information
= sizeNeeded
;
265 status
= STATUS_SUCCESS
;
270 case IOCTL_CDROM_RAW_READ
: {
272 LARGE_INTEGER startingOffset
;
273 ULONGLONG transferBytes
;
276 //ULONG startingSector;
277 PRAW_READ_INFO rawReadInfo
= (PRAW_READ_INFO
)irpStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
280 // Ensure that XA reads are supported.
283 if (TEST_FLAG(cdData
->XAFlags
, XA_NOT_SUPPORTED
)) {
284 TraceLog((CdromDebugWarning
,
285 "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n",
287 status
= STATUS_INVALID_DEVICE_REQUEST
;
292 // Check that ending sector is on disc and buffers are there and of
296 if (rawReadInfo
== NULL
) {
299 // Called from user space. Save the userbuffer in the
300 // Type3InputBuffer so we can reduce the number of code paths.
303 irpStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
=
304 Irp
->AssociatedIrp
.SystemBuffer
;
307 // Called from user space. Validate the buffers.
310 rawReadInfo
= (PRAW_READ_INFO
)irpStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
312 if (rawReadInfo
== NULL
) {
314 TraceLog((CdromDebugWarning
,
315 "CdRomDeviceControl: Invalid I/O parameters for "
316 "XA Read (No extent info\n"));
317 status
= STATUS_INVALID_PARAMETER
;
322 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
!=
323 sizeof(RAW_READ_INFO
)) {
325 TraceLog((CdromDebugWarning
,
326 "CdRomDeviceControl: Invalid I/O parameters for "
327 "XA Read (Invalid info buffer\n"));
328 status
= STATUS_INVALID_PARAMETER
;
335 // if they don't request any data, just fail the request
338 if (rawReadInfo
->SectorCount
== 0) {
340 status
= STATUS_INVALID_PARAMETER
;
345 startingOffset
.QuadPart
= rawReadInfo
->DiskOffset
.QuadPart
;
346 /* startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >>
347 fdoExtension->SectorShift); */
348 transferBytes
= (ULONGLONG
)rawReadInfo
->SectorCount
* RAW_SECTOR_SIZE
;
350 endOffset
= (ULONGLONG
)rawReadInfo
->SectorCount
* COOKED_SECTOR_SIZE
;
351 endOffset
+= startingOffset
.QuadPart
;
354 // check for overflows....
357 if (transferBytes
< (ULONGLONG
)(rawReadInfo
->SectorCount
)) {
358 TraceLog((CdromDebugWarning
,
359 "CdRomDeviceControl: Invalid I/O parameters for XA "
360 "Read (TransferBytes Overflow)\n"));
361 status
= STATUS_INVALID_PARAMETER
;
364 if (endOffset
< (ULONGLONG
)startingOffset
.QuadPart
) {
365 TraceLog((CdromDebugWarning
,
366 "CdRomDeviceControl: Invalid I/O parameters for XA "
367 "Read (EndingOffset Overflow)\n"));
368 status
= STATUS_INVALID_PARAMETER
;
371 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
373 TraceLog((CdromDebugWarning
,
374 "CdRomDeviceControl: Invalid I/O parameters for XA "
375 "Read (Bad buffer size)\n"));
376 status
= STATUS_INVALID_PARAMETER
;
379 if (endOffset
> (ULONGLONG
)commonExtension
->PartitionLength
.QuadPart
) {
380 TraceLog((CdromDebugWarning
,
381 "CdRomDeviceControl: Invalid I/O parameters for XA "
382 "Read (Request Out of Bounds)\n"));
383 status
= STATUS_INVALID_PARAMETER
;
388 // cannot validate the MdlAddress, since it is not included in any
389 // other location per the DDK and file system calls.
393 // validate the mdl describes at least the number of bytes
394 // requested from us.
397 mdlBytes
= (ULONGLONG
)MmGetMdlByteCount(Irp
->MdlAddress
);
398 if (mdlBytes
< transferBytes
) {
399 TraceLog((CdromDebugWarning
,
400 "CdRomDeviceControl: Invalid MDL %s, Irp %p\n",
402 status
= STATUS_INVALID_PARAMETER
;
407 // HACKHACK - REF #0001
408 // The retry count will be in this irp's IRP_MN function,
409 // as the new irp was freed, and we therefore cannot use
410 // this irp's next stack location for this function.
411 // This may be a good location to store this info for
412 // when we remove RAW_READ (mode switching), as we will
413 // no longer have the nextIrpStackLocation to play with
416 // once XA_READ is removed, then this hack can also be
419 irpStack
->MinorFunction
= MAXIMUM_RETRIES
; // HACKHACK - REF #0001
421 IoMarkIrpPending(Irp
);
422 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
424 return STATUS_PENDING
;
427 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
:
428 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
: {
429 TraceLog((CdromDebugTrace
,
430 "CdRomDeviceControl: Get drive geometryEx\n"));
431 if ( irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
432 FIELD_OFFSET(DISK_GEOMETRY_EX
, Data
)) {
433 status
= STATUS_BUFFER_TOO_SMALL
;
434 Irp
->IoStatus
.Information
= FIELD_OFFSET(DISK_GEOMETRY_EX
, Data
);
437 IoMarkIrpPending(Irp
);
438 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
439 return STATUS_PENDING
;
442 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
443 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
: {
445 TraceLog((CdromDebugTrace
,
446 "CdRomDeviceControl: Get drive geometry\n"));
448 if ( irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
449 sizeof( DISK_GEOMETRY
) ) {
451 status
= STATUS_BUFFER_TOO_SMALL
;
452 Irp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
456 IoMarkIrpPending(Irp
);
457 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
459 return STATUS_PENDING
;
462 case IOCTL_CDROM_READ_TOC_EX
: {
464 PCDROM_READ_TOC_EX inputBuffer
;
466 if (CdRomIsPlayActive(DeviceObject
)) {
467 status
= STATUS_DEVICE_BUSY
;
471 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
472 sizeof(CDROM_READ_TOC_EX
)) {
473 status
= STATUS_INFO_LENGTH_MISMATCH
;
477 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
478 MINIMUM_CDROM_READ_TOC_EX_SIZE
) {
479 status
= STATUS_BUFFER_TOO_SMALL
;
480 Irp
->IoStatus
.Information
= MINIMUM_CDROM_READ_TOC_EX_SIZE
;
484 if (irpStack
->Parameters
.Read
.Length
> ((USHORT
)-1)) {
485 status
= STATUS_INVALID_PARAMETER
;
489 inputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
491 if ((inputBuffer
->Reserved1
!= 0) ||
492 (inputBuffer
->Reserved2
!= 0) ||
493 (inputBuffer
->Reserved3
!= 0)) {
494 status
= STATUS_INVALID_PARAMETER
;
499 // NOTE: when adding new formats, ensure that first two bytes
500 // specify the amount of additional data available.
503 if ((inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_TOC
) ||
504 (inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_FULL_TOC
) ||
505 (inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_CDTEXT
)) {
507 // SessionTrack field is used
510 if ((inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_SESSION
) ||
511 (inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_PMA
) ||
512 (inputBuffer
->Format
== CDROM_READ_TOC_EX_FORMAT_ATIP
)) {
514 // SessionTrack field is reserved
516 if (inputBuffer
->SessionTrack
!= 0) {
517 status
= STATUS_INVALID_PARAMETER
;
522 status
= STATUS_INVALID_PARAMETER
;
526 IoMarkIrpPending(Irp
);
527 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
528 return STATUS_PENDING
;
531 case IOCTL_CDROM_GET_LAST_SESSION
: {
534 // If the cd is playing music then reject this request.
537 if (CdRomIsPlayActive(DeviceObject
)) {
538 status
= STATUS_DEVICE_BUSY
;
543 // Make sure the caller is requesting enough data to make this worth
547 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
548 sizeof(CDROM_TOC_SESSION_DATA
)) {
551 // they didn't request the entire TOC -- use _EX version
552 // for partial transfers and such.
555 status
= STATUS_BUFFER_TOO_SMALL
;
556 Irp
->IoStatus
.Information
= sizeof(CDROM_TOC_SESSION_DATA
);
560 IoMarkIrpPending(Irp
);
561 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
563 return STATUS_PENDING
;
566 case IOCTL_CDROM_READ_TOC
: {
569 // If the cd is playing music then reject this request.
572 if (CdRomIsPlayActive(DeviceObject
)) {
573 status
= STATUS_DEVICE_BUSY
;
578 // Make sure the caller is requesting enough data to make this worth
582 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
586 // they didn't request the entire TOC -- use _EX version
587 // for partial transfers and such.
590 status
= STATUS_BUFFER_TOO_SMALL
;
591 Irp
->IoStatus
.Information
= sizeof(CDROM_TOC
);
595 IoMarkIrpPending(Irp
);
596 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
598 return STATUS_PENDING
;
601 case IOCTL_CDROM_PLAY_AUDIO_MSF
: {
607 TraceLog((CdromDebugTrace
,
608 "CdRomDeviceControl: Play audio MSF\n"));
610 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
611 sizeof(CDROM_PLAY_AUDIO_MSF
)) {
614 // Indicate unsuccessful status.
617 status
= STATUS_INFO_LENGTH_MISMATCH
;
621 IoMarkIrpPending(Irp
);
622 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
624 return STATUS_PENDING
;
627 case IOCTL_CDROM_SEEK_AUDIO_MSF
: {
634 TraceLog((CdromDebugTrace
,
635 "CdRomDeviceControl: Seek audio MSF\n"));
637 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
638 sizeof(CDROM_SEEK_AUDIO_MSF
)) {
641 // Indicate unsuccessful status.
644 status
= STATUS_INFO_LENGTH_MISMATCH
;
648 IoMarkIrpPending(Irp
);
649 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
650 return STATUS_PENDING
;
654 case IOCTL_CDROM_PAUSE_AUDIO
: {
660 TraceLog((CdromDebugTrace
,
661 "CdRomDeviceControl: Pause audio\n"));
663 IoMarkIrpPending(Irp
);
664 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
666 return STATUS_PENDING
;
671 case IOCTL_CDROM_RESUME_AUDIO
: {
677 TraceLog((CdromDebugTrace
,
678 "CdRomDeviceControl: Resume audio\n"));
680 IoMarkIrpPending(Irp
);
681 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
683 return STATUS_PENDING
;
686 case IOCTL_CDROM_READ_Q_CHANNEL
: {
688 PCDROM_SUB_Q_DATA_FORMAT inputBuffer
=
689 Irp
->AssociatedIrp
.SystemBuffer
;
691 if(irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
692 sizeof(CDROM_SUB_Q_DATA_FORMAT
)) {
694 status
= STATUS_INFO_LENGTH_MISMATCH
;
699 // check for all valid types of request
702 if (inputBuffer
->Format
!= IOCTL_CDROM_CURRENT_POSITION
&&
703 inputBuffer
->Format
!= IOCTL_CDROM_MEDIA_CATALOG
&&
704 inputBuffer
->Format
!= IOCTL_CDROM_TRACK_ISRC
) {
705 status
= STATUS_INVALID_PARAMETER
;
706 Irp
->IoStatus
.Information
= 0;
710 IoMarkIrpPending(Irp
);
711 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
713 return STATUS_PENDING
;
716 case IOCTL_CDROM_GET_CONTROL
: {
718 TraceLog((CdromDebugTrace
,
719 "CdRomDeviceControl: Get audio control\n"));
722 // Verify user buffer is large enough for the data.
725 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
726 sizeof(CDROM_AUDIO_CONTROL
)) {
729 // Indicate unsuccessful status and no data transferred.
732 status
= STATUS_BUFFER_TOO_SMALL
;
733 Irp
->IoStatus
.Information
= sizeof(CDROM_AUDIO_CONTROL
);
738 IoMarkIrpPending(Irp
);
739 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
741 return STATUS_PENDING
;
744 case IOCTL_CDROM_GET_VOLUME
: {
746 TraceLog((CdromDebugTrace
,
747 "CdRomDeviceControl: Get volume control\n"));
750 // Verify user buffer is large enough for data.
753 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
754 sizeof(VOLUME_CONTROL
)) {
757 // Indicate unsuccessful status and no data transferred.
760 status
= STATUS_BUFFER_TOO_SMALL
;
761 Irp
->IoStatus
.Information
= sizeof(VOLUME_CONTROL
);
766 IoMarkIrpPending(Irp
);
767 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
769 return STATUS_PENDING
;
772 case IOCTL_CDROM_SET_VOLUME
: {
774 TraceLog((CdromDebugTrace
,
775 "CdRomDeviceControl: Set volume control\n"));
777 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
778 sizeof(VOLUME_CONTROL
)) {
781 // Indicate unsuccessful status.
784 status
= STATUS_INFO_LENGTH_MISMATCH
;
789 IoMarkIrpPending(Irp
);
790 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
792 return STATUS_PENDING
;
795 case IOCTL_CDROM_STOP_AUDIO
: {
801 TraceLog((CdromDebugTrace
,
802 "CdRomDeviceControl: Stop audio\n"));
804 IoMarkIrpPending(Irp
);
805 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
807 return STATUS_PENDING
;
810 case IOCTL_STORAGE_CHECK_VERIFY
:
811 case IOCTL_DISK_CHECK_VERIFY
:
812 case IOCTL_CDROM_CHECK_VERIFY
: {
814 TraceLog((CdromDebugTrace
,
815 "CdRomDeviceControl: [%p] Check Verify\n", Irp
));
817 if((irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
) &&
818 (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))) {
820 TraceLog((CdromDebugWarning
,
821 "CdRomDeviceControl: Check Verify: media count "
822 "buffer too small\n"));
824 status
= STATUS_BUFFER_TOO_SMALL
;
825 Irp
->IoStatus
.Information
= sizeof(ULONG
);
829 IoMarkIrpPending(Irp
);
830 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
832 return STATUS_PENDING
;
835 case IOCTL_DVD_READ_STRUCTURE
: {
837 TraceLog((CdromDebugTrace
,
838 "DvdDeviceControl: [%p] IOCTL_DVD_READ_STRUCTURE\n", Irp
));
840 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
841 TraceLog((CdromDebugWarning
,
842 "DvdDeviceControl: License Failure\n"));
843 status
= STATUS_COPY_PROTECTION_FAILURE
;
847 if (cdData
->DvdRpc0Device
&& cdData
->Rpc0RetryRegistryCallback
) {
849 // if currently in-progress, this will just return.
850 // prevents looping by doing that interlockedExchange()
852 TraceLog((CdromDebugWarning
,
853 "DvdDeviceControl: PickRegion() from "
854 "READ_STRUCTURE\n"));
855 CdRomPickDvdRegion(DeviceObject
);
859 if(irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
860 sizeof(DVD_READ_STRUCTURE
)) {
862 TraceLog((CdromDebugWarning
,
863 "DvdDeviceControl - READ_STRUCTURE: input buffer "
864 "length too small (was %d should be %d)\n",
865 irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
,
866 sizeof(DVD_READ_STRUCTURE
)));
867 status
= STATUS_INVALID_PARAMETER
;
871 if(irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
872 sizeof(READ_DVD_STRUCTURES_HEADER
)) {
874 TraceLog((CdromDebugWarning
,
875 "DvdDeviceControl - READ_STRUCTURE: output buffer "
876 "cannot hold header information\n"));
877 status
= STATUS_BUFFER_TOO_SMALL
;
878 Irp
->IoStatus
.Information
= sizeof(READ_DVD_STRUCTURES_HEADER
);
882 if(irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>
886 // key length must fit in two bytes
888 TraceLog((CdromDebugWarning
,
889 "DvdDeviceControl - READ_STRUCTURE: output buffer "
891 status
= STATUS_INVALID_PARAMETER
;
895 IoMarkIrpPending(Irp
);
896 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
898 return STATUS_PENDING
;
901 case IOCTL_DVD_START_SESSION
: {
903 TraceLog((CdromDebugTrace
,
904 "DvdDeviceControl: [%p] IOCTL_DVD_START_SESSION\n", Irp
));
906 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
907 TraceLog((CdromDebugWarning
,
908 "DvdDeviceControl: License Failure\n"));
909 status
= STATUS_COPY_PROTECTION_FAILURE
;
913 if(irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
914 sizeof(DVD_SESSION_ID
)) {
916 TraceLog((CdromDebugWarning
,
917 "DvdDeviceControl: DVD_START_SESSION - output "
918 "buffer too small\n"));
919 status
= STATUS_BUFFER_TOO_SMALL
;
920 Irp
->IoStatus
.Information
= sizeof(DVD_SESSION_ID
);
924 IoMarkIrpPending(Irp
);
925 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
927 return STATUS_PENDING
;
930 case IOCTL_DVD_SEND_KEY
:
931 case IOCTL_DVD_SEND_KEY2
: {
933 PDVD_COPY_PROTECT_KEY key
= Irp
->AssociatedIrp
.SystemBuffer
;
936 TraceLog((CdromDebugTrace
,
937 "DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY\n", Irp
));
939 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
940 TraceLog((CdromDebugWarning
,
941 "DvdDeviceControl: License Failure\n"));
942 status
= STATUS_COPY_PROTECTION_FAILURE
;
946 if((irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
947 sizeof(DVD_COPY_PROTECT_KEY
)) ||
948 (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
!=
952 // Key is too small to have a header or the key length doesn't
953 // match the input buffer length. Key must be invalid
956 TraceLog((CdromDebugWarning
,
957 "DvdDeviceControl: [%p] IOCTL_DVD_SEND_KEY - "
958 "key is too small or does not match KeyLength\n",
960 status
= STATUS_INVALID_PARAMETER
;
965 // allow only certain key type (non-destructive) to go through
966 // IOCTL_DVD_SEND_KEY (which only requires READ access to the device
968 if (ioctlCode
== IOCTL_DVD_SEND_KEY
) {
970 if ((key
->KeyType
!= DvdChallengeKey
) &&
971 (key
->KeyType
!= DvdBusKey2
) &&
972 (key
->KeyType
!= DvdInvalidateAGID
)) {
974 status
= STATUS_INVALID_PARAMETER
;
979 if (cdData
->DvdRpc0Device
) {
981 if (key
->KeyType
== DvdSetRpcKey
) {
983 PDVD_SET_RPC_KEY rpcKey
= (PDVD_SET_RPC_KEY
) key
->KeyData
;
985 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
986 DVD_SET_RPC_KEY_LENGTH
) {
988 status
= STATUS_INVALID_PARAMETER
;
993 // we have a request to set region code
994 // on a RPC0 device which doesn't support
997 // we have to fake it.
1000 KeWaitForMutexObject(
1001 &cdData
->Rpc0RegionMutex
,
1008 if (cdData
->DvdRpc0Device
&& cdData
->Rpc0RetryRegistryCallback
) {
1010 // if currently in-progress, this will just return.
1011 // prevents looping by doing that interlockedExchange()
1013 TraceLog((CdromDebugWarning
,
1014 "DvdDeviceControl: PickRegion() from "
1016 CdRomPickDvdRegion(DeviceObject
);
1019 if (cdData
->Rpc0SystemRegion
== rpcKey
->PreferredDriveRegionCode
) {
1022 // nothing to change
1024 TraceLog((CdromDebugWarning
,
1025 "DvdDeviceControl (%p) => not changing "
1026 "regions -- requesting current region\n",
1028 status
= STATUS_SUCCESS
;
1030 } else if (cdData
->Rpc0SystemRegionResetCount
== 0) {
1033 // not allowed to change it again
1036 TraceLog((CdromDebugWarning
,
1037 "DvdDeviceControl (%p) => no more region "
1038 "changes are allowed for this device\n",
1040 status
= STATUS_CSS_RESETS_EXHAUSTED
;
1047 PDVD_READ_STRUCTURE dvdReadStructure
;
1048 PDVD_COPYRIGHT_DESCRIPTOR dvdCopyRight
;
1049 IO_STATUS_BLOCK ioStatus
;
1050 UCHAR mediaRegionData
;
1052 mask
= ~rpcKey
->PreferredDriveRegionCode
;
1054 if (CountOfSetBitsUChar(mask
) != 1) {
1056 status
= STATUS_INVALID_DEVICE_REQUEST
;
1061 // this test will always be TRUE except during initial
1062 // automatic selection of the first region.
1065 if (cdData
->Rpc0SystemRegion
!= 0xff) {
1068 // make sure we have a media in the drive with the same
1069 // region code if the drive is already has a region set
1072 TraceLog((CdromDebugTrace
,
1073 "DvdDeviceControl (%p) => Checking "
1077 bufferLen
= max(sizeof(DVD_DESCRIPTOR_HEADER
) +
1078 sizeof(DVD_COPYRIGHT_DESCRIPTOR
),
1079 sizeof(DVD_READ_STRUCTURE
)
1082 dvdReadStructure
= (PDVD_READ_STRUCTURE
)
1083 ExAllocatePoolWithTag(PagedPool
,
1085 DVD_TAG_RPC2_CHECK
);
1087 if (dvdReadStructure
== NULL
) {
1088 status
= STATUS_INSUFFICIENT_RESOURCES
;
1089 KeReleaseMutex(&cdData
->Rpc0RegionMutex
,FALSE
);
1093 dvdCopyRight
= (PDVD_COPYRIGHT_DESCRIPTOR
)
1094 ((PDVD_DESCRIPTOR_HEADER
) dvdReadStructure
)->Data
;
1097 // check to see if we have a DVD device
1100 RtlZeroMemory (dvdReadStructure
, bufferLen
);
1101 dvdReadStructure
->Format
= DvdCopyrightDescriptor
;
1104 // Build a request for READ_KEY
1106 ClassSendDeviceIoControlSynchronous(
1107 IOCTL_DVD_READ_STRUCTURE
,
1110 sizeof(DVD_READ_STRUCTURE
),
1111 sizeof(DVD_DESCRIPTOR_HEADER
) +
1112 sizeof(DVD_COPYRIGHT_DESCRIPTOR
),
1117 // this is just to prevent bugs from creeping in
1118 // if status is not set later in development
1121 status
= ioStatus
.Status
;
1127 if (!NT_SUCCESS(status
)) {
1128 KeReleaseMutex(&cdData
->Rpc0RegionMutex
,FALSE
);
1129 ExFreePool(dvdReadStructure
);
1130 status
= STATUS_INVALID_DEVICE_REQUEST
;
1135 // save the mediaRegionData before freeing the
1140 dvdCopyRight
->RegionManagementInformation
;
1141 ExFreePool(dvdReadStructure
);
1143 TraceLog((CdromDebugWarning
,
1144 "DvdDeviceControl (%p) => new mask is %x"
1145 " MediaRegionData is %x\n", DeviceObject
,
1146 rpcKey
->PreferredDriveRegionCode
,
1150 // the media region must match the requested region
1151 // for RPC0 drives for initial region selection
1154 if (((UCHAR
)~(mediaRegionData
| rpcKey
->PreferredDriveRegionCode
)) == 0) {
1155 KeReleaseMutex(&cdData
->Rpc0RegionMutex
,FALSE
);
1156 status
= STATUS_CSS_REGION_MISMATCH
;
1163 // now try to set the region
1166 TraceLog((CdromDebugTrace
,
1167 "DvdDeviceControl (%p) => Soft-Setting "
1168 "region of RPC1 device to %x\n",
1170 rpcKey
->PreferredDriveRegionCode
1173 status
= CdRomSetRpc0Settings(DeviceObject
,
1174 rpcKey
->PreferredDriveRegionCode
);
1176 if (!NT_SUCCESS(status
)) {
1177 TraceLog((CdromDebugWarning
,
1178 "DvdDeviceControl (%p) => Could not "
1179 "set region code (%x)\n",
1180 DeviceObject
, status
1184 TraceLog((CdromDebugTrace
,
1185 "DvdDeviceControl (%p) => New region set "
1186 " for RPC1 drive\n", DeviceObject
));
1189 // if it worked, our extension is already updated.
1190 // release the mutex
1193 DebugPrint ((4, "DvdDeviceControl (%p) => DVD current "
1194 "region bitmap 0x%x\n", DeviceObject
,
1195 cdData
->Rpc0SystemRegion
));
1196 DebugPrint ((4, "DvdDeviceControl (%p) => DVD region "
1197 " reset Count 0x%x\n", DeviceObject
,
1198 cdData
->Rpc0SystemRegionResetCount
));
1203 KeReleaseMutex(&cdData
->Rpc0RegionMutex
,FALSE
);
1205 } // end of key->KeyType == DvdSetRpcKey
1206 } // end of Rpc0Device hacks
1208 IoMarkIrpPending(Irp
);
1209 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1210 return STATUS_PENDING
;
1214 case IOCTL_DVD_READ_KEY
: {
1216 PDVD_COPY_PROTECT_KEY keyParameters
= Irp
->AssociatedIrp
.SystemBuffer
;
1219 TraceLog((CdromDebugTrace
,
1220 "DvdDeviceControl: [%p] IOCTL_DVD_READ_KEY\n", Irp
));
1222 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
1223 TraceLog((CdromDebugWarning
,
1224 "DvdDeviceControl: License Failure\n"));
1225 status
= STATUS_COPY_PROTECTION_FAILURE
;
1229 if (cdData
->DvdRpc0Device
&& cdData
->Rpc0RetryRegistryCallback
) {
1230 TraceLog((CdromDebugWarning
,
1231 "DvdDeviceControl: PickRegion() from READ_KEY\n"));
1232 CdRomPickDvdRegion(DeviceObject
);
1236 if(irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1237 sizeof(DVD_COPY_PROTECT_KEY
)) {
1239 TraceLog((CdromDebugWarning
,
1240 "DvdDeviceControl: EstablishDriveKey - challenge "
1241 "key buffer too small\n"));
1243 status
= STATUS_INVALID_PARAMETER
;
1249 switch(keyParameters
->KeyType
) {
1251 case DvdChallengeKey
:
1252 keyLength
= DVD_CHALLENGE_KEY_LENGTH
;
1258 keyLength
= DVD_BUS_KEY_LENGTH
;
1262 keyLength
= DVD_TITLE_KEY_LENGTH
;
1266 keyLength
= DVD_ASF_LENGTH
;
1270 keyLength
= DVD_DISK_KEY_LENGTH
;
1274 keyLength
= DVD_RPC_KEY_LENGTH
;
1278 keyLength
= sizeof(DVD_COPY_PROTECT_KEY
);
1282 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1285 TraceLog((CdromDebugWarning
,
1286 "DvdDeviceControl: EstablishDriveKey - output "
1287 "buffer too small\n"));
1288 status
= STATUS_BUFFER_TOO_SMALL
;
1289 Irp
->IoStatus
.Information
= keyLength
;
1293 if (keyParameters
->KeyType
== DvdGetRpcKey
) {
1295 CdRomPickDvdRegion(DeviceObject
);
1298 if ((keyParameters
->KeyType
== DvdGetRpcKey
) &&
1299 (cdData
->DvdRpc0Device
)) {
1301 PDVD_RPC_KEY rpcKey
;
1302 rpcKey
= (PDVD_RPC_KEY
)keyParameters
->KeyData
;
1303 RtlZeroMemory (rpcKey
, sizeof (*rpcKey
));
1305 KeWaitForMutexObject(
1306 &cdData
->Rpc0RegionMutex
,
1316 rpcKey
->UserResetsAvailable
= cdData
->Rpc0SystemRegionResetCount
;
1317 rpcKey
->ManufacturerResetsAvailable
= 0;
1318 if (cdData
->Rpc0SystemRegion
== 0xff) {
1319 rpcKey
->TypeCode
= 0;
1321 rpcKey
->TypeCode
= 1;
1323 rpcKey
->RegionMask
= (UCHAR
) cdData
->Rpc0SystemRegion
;
1324 rpcKey
->RpcScheme
= 1;
1327 &cdData
->Rpc0RegionMutex
,
1331 Irp
->IoStatus
.Information
= DVD_RPC_KEY_LENGTH
;
1332 status
= STATUS_SUCCESS
;
1335 } else if (keyParameters
->KeyType
== DvdDiskKey
) {
1337 PDVD_COPY_PROTECT_KEY keyHeader
;
1338 PDVD_READ_STRUCTURE readStructureRequest
;
1341 // Special case - build a request to get the dvd structure
1342 // so we can get the disk key.
1346 // save the key header so we can restore the interesting
1350 keyHeader
= ExAllocatePoolWithTag(NonPagedPool
,
1351 sizeof(DVD_COPY_PROTECT_KEY
),
1354 if(keyHeader
== NULL
) {
1357 // Can't save the context so return an error
1360 TraceLog((CdromDebugWarning
,
1361 "DvdDeviceControl - READ_KEY: unable to "
1362 "allocate context\n"));
1363 status
= STATUS_INSUFFICIENT_RESOURCES
;
1367 RtlCopyMemory(keyHeader
,
1368 Irp
->AssociatedIrp
.SystemBuffer
,
1369 sizeof(DVD_COPY_PROTECT_KEY
));
1371 IoCopyCurrentIrpStackLocationToNext(Irp
);
1373 nextStack
= IoGetNextIrpStackLocation(Irp
);
1375 nextStack
->Parameters
.DeviceIoControl
.IoControlCode
=
1376 IOCTL_DVD_READ_STRUCTURE
;
1378 readStructureRequest
= Irp
->AssociatedIrp
.SystemBuffer
;
1379 readStructureRequest
->Format
= DvdDiskKeyDescriptor
;
1380 readStructureRequest
->BlockByteOffset
.QuadPart
= 0;
1381 readStructureRequest
->LayerNumber
= 0;
1382 readStructureRequest
->SessionId
= keyHeader
->SessionId
;
1384 nextStack
->Parameters
.DeviceIoControl
.InputBufferLength
=
1385 sizeof(DVD_READ_STRUCTURE
);
1387 nextStack
->Parameters
.DeviceIoControl
.OutputBufferLength
=
1388 sizeof(READ_DVD_STRUCTURES_HEADER
) + sizeof(DVD_DISK_KEY_DESCRIPTOR
);
1390 IoSetCompletionRoutine(Irp
,
1391 CdRomDvdReadDiskKeyCompletion
,
1398 UCHAR uniqueAddress
;
1399 ClassAcquireRemoveLock(DeviceObject
, (PIRP
)&uniqueAddress
);
1400 ClassReleaseRemoveLock(DeviceObject
, Irp
);
1402 IoMarkIrpPending(Irp
);
1403 IoCallDriver(commonExtension
->DeviceObject
, Irp
);
1404 status
= STATUS_PENDING
;
1406 ClassReleaseRemoveLock(DeviceObject
, (PIRP
)&uniqueAddress
);
1409 return STATUS_PENDING
;
1413 IoMarkIrpPending(Irp
);
1414 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1417 return STATUS_PENDING
;
1420 case IOCTL_DVD_END_SESSION
: {
1422 PDVD_SESSION_ID sessionId
= Irp
->AssociatedIrp
.SystemBuffer
;
1424 TraceLog((CdromDebugTrace
,
1425 "DvdDeviceControl: [%p] END_SESSION\n", Irp
));
1427 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
1428 TraceLog((CdromDebugWarning
,
1429 "DvdDeviceControl: License Failure\n"));
1430 status
= STATUS_COPY_PROTECTION_FAILURE
;
1434 if(irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1435 sizeof(DVD_SESSION_ID
)) {
1437 TraceLog((CdromDebugWarning
,
1438 "DvdDeviceControl: EndSession - input buffer too "
1440 status
= STATUS_INVALID_PARAMETER
;
1444 IoMarkIrpPending(Irp
);
1446 if(*sessionId
== DVD_END_ALL_SESSIONS
) {
1448 status
= CdRomDvdEndAllSessionsCompletion(DeviceObject
, Irp
, NULL
);
1450 if(status
== STATUS_SUCCESS
) {
1453 // Just complete the request - it was never issued to the
1461 return STATUS_PENDING
;
1466 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1468 return STATUS_PENDING
;
1471 case IOCTL_DVD_GET_REGION
: {
1473 PDVD_COPY_PROTECT_KEY copyProtectKey
;
1475 IO_STATUS_BLOCK ioStatus
;
1476 PDVD_DESCRIPTOR_HEADER dvdHeader
;
1477 PDVD_COPYRIGHT_DESCRIPTOR copyRightDescriptor
;
1478 PDVD_REGION dvdRegion
;
1479 PDVD_READ_STRUCTURE readStructure
;
1480 PDVD_RPC_KEY rpcKey
;
1482 TraceLog((CdromDebugTrace
,
1483 "DvdDeviceControl: [%p] IOCTL_DVD_GET_REGION\n", Irp
));
1485 if (cdData
->DvdRpc0Device
&& cdData
->DvdRpc0LicenseFailure
) {
1486 TraceLog((CdromDebugWarning
,
1487 "DvdDeviceControl: License Failure\n"));
1488 status
= STATUS_COPY_PROTECTION_FAILURE
;
1492 if(irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1493 sizeof(DVD_REGION
)) {
1495 TraceLog((CdromDebugWarning
,
1496 "DvdDeviceControl: output buffer DVD_REGION too small\n"));
1497 status
= STATUS_INVALID_PARAMETER
;
1502 // figure out how much data buffer we need
1505 keyLength
= max(sizeof(DVD_DESCRIPTOR_HEADER
) +
1506 sizeof(DVD_COPYRIGHT_DESCRIPTOR
),
1507 sizeof(DVD_READ_STRUCTURE
)
1509 keyLength
= max(keyLength
,
1514 // round the size to nearest ULONGLONG -- why?
1517 keyLength
+= sizeof(ULONGLONG
) - (keyLength
& (sizeof(ULONGLONG
) - 1));
1519 readStructure
= ExAllocatePoolWithTag(NonPagedPool
,
1522 if (readStructure
== NULL
) {
1523 status
= STATUS_INSUFFICIENT_RESOURCES
;
1527 RtlZeroMemory (readStructure
, keyLength
);
1528 readStructure
->Format
= DvdCopyrightDescriptor
;
1531 // Build a request for READ_STRUCTURE
1534 ClassSendDeviceIoControlSynchronous(
1535 IOCTL_DVD_READ_STRUCTURE
,
1539 sizeof(DVD_DESCRIPTOR_HEADER
) +
1540 sizeof(DVD_COPYRIGHT_DESCRIPTOR
),
1544 status
= ioStatus
.Status
;
1546 if (!NT_SUCCESS(status
)) {
1547 TraceLog((CdromDebugWarning
,
1548 "CdRomDvdGetRegion => read structure failed %x\n",
1550 ExFreePool(readStructure
);
1555 // we got the copyright descriptor, so now get the region if possible
1558 dvdHeader
= (PDVD_DESCRIPTOR_HEADER
) readStructure
;
1559 copyRightDescriptor
= (PDVD_COPYRIGHT_DESCRIPTOR
) dvdHeader
->Data
;
1562 // the original irp's systembuffer has a copy of the info that
1563 // should be passed down in the request
1566 dvdRegion
= Irp
->AssociatedIrp
.SystemBuffer
;
1568 dvdRegion
->CopySystem
= copyRightDescriptor
->CopyrightProtectionType
;
1569 dvdRegion
->RegionData
= copyRightDescriptor
->RegionManagementInformation
;
1572 // now reuse the buffer to request the copy protection info
1575 copyProtectKey
= (PDVD_COPY_PROTECT_KEY
) readStructure
;
1576 RtlZeroMemory (copyProtectKey
, DVD_RPC_KEY_LENGTH
);
1577 copyProtectKey
->KeyLength
= DVD_RPC_KEY_LENGTH
;
1578 copyProtectKey
->KeyType
= DvdGetRpcKey
;
1581 // send a request for READ_KEY
1584 ClassSendDeviceIoControlSynchronous(
1592 status
= ioStatus
.Status
;
1594 if (!NT_SUCCESS(status
)) {
1595 TraceLog((CdromDebugWarning
,
1596 "CdRomDvdGetRegion => read key failed %x\n",
1598 ExFreePool(readStructure
);
1603 // the request succeeded. if a supported scheme is returned,
1604 // then return the information to the caller
1607 rpcKey
= (PDVD_RPC_KEY
) copyProtectKey
->KeyData
;
1609 if (rpcKey
->RpcScheme
== 1) {
1611 if (rpcKey
->TypeCode
) {
1613 dvdRegion
->SystemRegion
= ~rpcKey
->RegionMask
;
1614 dvdRegion
->ResetCount
= rpcKey
->UserResetsAvailable
;
1619 // the drive has not been set for any region
1622 dvdRegion
->SystemRegion
= 0;
1623 dvdRegion
->ResetCount
= rpcKey
->UserResetsAvailable
;
1625 Irp
->IoStatus
.Information
= sizeof(DVD_REGION
);
1629 TraceLog((CdromDebugWarning
,
1630 "CdRomDvdGetRegion => rpcKey->RpcScheme != 1\n"));
1631 status
= STATUS_INVALID_DEVICE_REQUEST
;
1634 ExFreePool(readStructure
);
1639 case IOCTL_STORAGE_SET_READ_AHEAD
: {
1641 if(irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1642 sizeof(STORAGE_SET_READ_AHEAD
)) {
1644 TraceLog((CdromDebugWarning
,
1645 "DvdDeviceControl: SetReadAhead buffer too small\n"));
1646 status
= STATUS_INVALID_PARAMETER
;
1650 IoMarkIrpPending(Irp
);
1651 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1653 return STATUS_PENDING
;
1656 case IOCTL_DISK_IS_WRITABLE
: {
1658 IoMarkIrpPending(Irp
);
1659 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1661 return STATUS_PENDING
;
1665 case IOCTL_DISK_GET_DRIVE_LAYOUT
: {
1670 // we always fake zero or one partitions, and one partition
1671 // structure is included in DRIVE_LAYOUT_INFORMATION
1674 size
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION
, PartitionEntry
[1]);
1677 TraceLog((CdromDebugTrace
,
1678 "CdRomDeviceControl: Get drive layout\n"));
1679 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< size
) {
1680 status
= STATUS_BUFFER_TOO_SMALL
;
1681 Irp
->IoStatus
.Information
= size
;
1685 IoMarkIrpPending(Irp
);
1686 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1687 return STATUS_PENDING
;
1691 case IOCTL_DISK_GET_DRIVE_LAYOUT_EX
: {
1696 // we always fake zero or one partitions, and one partition
1697 // structure is included in DRIVE_LAYOUT_INFORMATION_EX
1700 size
= FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX
, PartitionEntry
[1]);
1702 TraceLog((CdromDebugTrace
,
1703 "CdRomDeviceControl: Get drive layout ex\n"));
1704 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< size
) {
1705 status
= STATUS_BUFFER_TOO_SMALL
;
1706 Irp
->IoStatus
.Information
= size
;
1710 IoMarkIrpPending(Irp
);
1711 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1712 return STATUS_PENDING
;
1717 case IOCTL_DISK_GET_PARTITION_INFO
: {
1720 // Check that the buffer is large enough.
1723 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1724 sizeof(PARTITION_INFORMATION
)) {
1726 status
= STATUS_BUFFER_TOO_SMALL
;
1727 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
1731 IoMarkIrpPending(Irp
);
1732 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1733 return STATUS_PENDING
;
1736 case IOCTL_DISK_GET_PARTITION_INFO_EX
: {
1738 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1739 sizeof(PARTITION_INFORMATION_EX
)) {
1741 status
= STATUS_BUFFER_TOO_SMALL
;
1742 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION_EX
);
1746 IoMarkIrpPending(Irp
);
1747 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1748 return STATUS_PENDING
;
1751 case IOCTL_DISK_VERIFY
: {
1753 TraceLog((CdromDebugTrace
,
1754 "IOCTL_DISK_VERIFY to device %p through irp %p\n",
1755 DeviceObject
, Irp
));
1758 // Validate buffer length.
1761 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
<
1762 sizeof(VERIFY_INFORMATION
)) {
1764 status
= STATUS_INFO_LENGTH_MISMATCH
;
1767 IoMarkIrpPending(Irp
);
1768 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1769 return STATUS_PENDING
;
1772 case IOCTL_DISK_GET_LENGTH_INFO
: {
1774 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1775 sizeof(GET_LENGTH_INFORMATION
)) {
1776 status
= STATUS_BUFFER_TOO_SMALL
;
1777 Irp
->IoStatus
.Information
= sizeof(GET_LENGTH_INFORMATION
);
1780 IoMarkIrpPending(Irp
);
1781 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1782 return STATUS_PENDING
;
1785 case IOCTL_CDROM_GET_CONFIGURATION
: {
1787 PGET_CONFIGURATION_IOCTL_INPUT inputBuffer
;
1789 TraceLog((CdromDebugTrace
,
1790 "IOCTL_CDROM_GET_CONFIGURATION to via irp %p\n", Irp
));
1793 // Validate buffer length.
1796 if (irpStack
->Parameters
.DeviceIoControl
.InputBufferLength
!=
1797 sizeof(GET_CONFIGURATION_IOCTL_INPUT
)) {
1798 status
= STATUS_INFO_LENGTH_MISMATCH
;
1801 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
1802 sizeof(GET_CONFIGURATION_HEADER
)) {
1803 status
= STATUS_BUFFER_TOO_SMALL
;
1804 Irp
->IoStatus
.Information
= sizeof(GET_CONFIGURATION_HEADER
);
1807 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
> 0xffff) {
1808 // output buffer is too large
1809 status
= STATUS_INVALID_BUFFER_SIZE
;
1814 // also verify the arguments are reasonable.
1817 inputBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
1818 if (inputBuffer
->Feature
> 0xffff) {
1819 status
= STATUS_INVALID_PARAMETER
;
1822 if ((inputBuffer
->RequestType
!= SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE
) &&
1823 (inputBuffer
->RequestType
!= SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT
) &&
1824 (inputBuffer
->RequestType
!= SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL
)) {
1825 status
= STATUS_INVALID_PARAMETER
;
1828 if (inputBuffer
->Reserved
[0] || inputBuffer
->Reserved
[1]) {
1829 status
= STATUS_INVALID_PARAMETER
;
1833 IoMarkIrpPending(Irp
);
1834 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1835 return STATUS_PENDING
;
1841 BOOLEAN synchronize
= (KeGetCurrentIrql() == PASSIVE_LEVEL
);
1842 PKEVENT deviceControlEvent
;
1845 // If the ioctl has come in at passive level then we will synchronize
1846 // with our start-io routine when sending the ioctl. If the ioctl
1847 // has come in at a higher interrupt level and it was not handled
1848 // above then it's unlikely to be a request for the class DLL - however
1849 // we'll still use it's common code to forward the request through.
1854 deviceControlEvent
= ExAllocatePoolWithTag(NonPagedPool
,
1856 CDROM_TAG_DC_EVENT
);
1858 if (deviceControlEvent
== NULL
) {
1861 // must complete this irp unsuccessful here
1863 status
= STATUS_INSUFFICIENT_RESOURCES
;
1868 //PIO_STACK_LOCATION currentStack;
1870 KeInitializeEvent(deviceControlEvent
, NotificationEvent
, FALSE
);
1872 //currentStack = IoGetCurrentIrpStackLocation(Irp);
1873 nextStack
= IoGetNextIrpStackLocation(Irp
);
1876 // Copy the stack down a notch
1879 IoCopyCurrentIrpStackLocationToNext(Irp
);
1881 IoSetCompletionRoutine(
1883 CdRomClassIoctlCompletion
,
1890 IoSetNextIrpStackLocation(Irp
);
1892 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1893 Irp
->IoStatus
.Information
= 0;
1896 // Override volume verifies on this stack location so that we
1897 // will be forced through the synchronization. Once this
1898 // location goes away we get the old value back
1901 SET_FLAG(nextStack
->Flags
, SL_OVERRIDE_VERIFY_VOLUME
);
1903 IoStartPacket(DeviceObject
, Irp
, NULL
, NULL
);
1906 // Wait for CdRomClassIoctlCompletion to set the event. This
1907 // ensures serialization remains intact for these unhandled device
1911 KeWaitForSingleObject(
1918 ExFreePool(deviceControlEvent
);
1920 TraceLog((CdromDebugTrace
,
1921 "CdRomDeviceControl: irp %p synchronized\n", Irp
));
1923 status
= Irp
->IoStatus
.Status
;
1927 status
= STATUS_SUCCESS
;
1931 // If an error occured then propagate that back up - we are no longer
1932 // guaranteed synchronization and the upper layers will have to
1935 // If no error occured, call down to the class driver directly
1936 // then start up the next request.
1939 if (NT_SUCCESS(status
)) {
1941 UCHAR uniqueAddress
;
1944 // The class device control routine will release the remove
1945 // lock for this Irp. We need to make sure we have one
1946 // available so that it's safe to call IoStartNextPacket
1951 ClassAcquireRemoveLock(DeviceObject
, (PIRP
)&uniqueAddress
);
1955 status
= ClassDeviceControl(DeviceObject
, Irp
);
1958 KeRaiseIrql(DISPATCH_LEVEL
, &irql
);
1959 IoStartNextPacket(DeviceObject
, FALSE
);
1961 ClassReleaseRemoveLock(DeviceObject
, (PIRP
)&uniqueAddress
);
1968 // an error occurred (either STATUS_INSUFFICIENT_RESOURCES from
1969 // attempting to synchronize or StartIo() error'd this one
1970 // out), so we need to finish the irp, which is
1971 // done at the end of this routine.
1975 } // end default case
1979 if (status
== STATUS_VERIFY_REQUIRED
) {
1982 // If the status is verified required and this request
1983 // should bypass verify required then retry the request.
1986 if (irpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
) {
1988 status
= STATUS_IO_DEVICE_ERROR
;
1994 if (IoIsErrorUserInduced(status
)) {
1996 if (Irp
->Tail
.Overlay
.Thread
) {
1997 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
2003 // Update IRP with completion status.
2006 Irp
->IoStatus
.Status
= status
;
2009 // Complete the request.
2012 ClassReleaseRemoveLock(DeviceObject
, Irp
);
2013 ClassCompleteRequest(DeviceObject
, Irp
, IO_DISK_INCREMENT
);
2014 TraceLog((CdromDebugTrace
,
2015 "CdRomDeviceControl: Status is %lx\n", status
));
2018 } // end CdRomDeviceControl()
2022 CdRomClassIoctlCompletion(
2023 IN PDEVICE_OBJECT DeviceObject
,
2029 Routine Description:
2031 This routine signals the event used by CdRomDeviceControl to synchronize
2032 class driver (and lower level driver) ioctls with cdrom's startio routine.
2033 The irp completion is short-circuited so that CdRomDeviceControlDispatch
2034 can reissue it once it wakes up.
2038 DeviceObject - the device object
2039 Irp - the request we are synchronizing
2040 Context - a PKEVENT that we need to signal
2048 PKEVENT syncEvent
= (PKEVENT
) Context
;
2050 TraceLog((CdromDebugTrace
,
2051 "CdRomClassIoctlCompletion: setting event for irp %p\n", Irp
));
2054 // We released the lock when we completed this request. Reacquire it.
2057 ClassAcquireRemoveLock(DeviceObject
, Irp
);
2059 KeSetEvent(syncEvent
, IO_DISK_INCREMENT
, FALSE
);
2061 return STATUS_MORE_PROCESSING_REQUIRED
;
2066 CdRomDeviceControlCompletion(
2067 IN PDEVICE_OBJECT DeviceObject
,
2072 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
2073 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
2075 PCDROM_DATA cdData
= (PCDROM_DATA
)(commonExtension
->DriverData
);
2076 BOOLEAN use6Byte
= TEST_FLAG(cdData
->XAFlags
, XA_USE_6_BYTE
);
2078 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
2079 PIO_STACK_LOCATION realIrpStack
;
2080 PIO_STACK_LOCATION realIrpNextStack
;
2082 PSCSI_REQUEST_BLOCK srb
= Context
;
2084 PIRP realIrp
= NULL
;
2091 // Extract the 'real' irp from the irpstack.
2094 realIrp
= (PIRP
) irpStack
->Parameters
.Others
.Argument2
;
2095 realIrpStack
= IoGetCurrentIrpStackLocation(realIrp
);
2096 realIrpNextStack
= IoGetNextIrpStackLocation(realIrp
);
2099 // check that we've really got the correct irp
2102 ASSERT(realIrpNextStack
->Parameters
.Others
.Argument3
== Irp
);
2105 // Check SRB status for success of completing request.
2108 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
2110 ULONG retryInterval
;
2112 TraceLog((CdromDebugTrace
,
2113 "CdRomDeviceControlCompletion: Irp %p, Srb %p Real Irp %p Status %lx\n",
2120 // Release the queue if it is frozen.
2123 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
2124 TraceLog((CdromDebugTrace
,
2125 "CdRomDeviceControlCompletion: Releasing Queue\n"));
2126 ClassReleaseQueue(DeviceObject
);
2130 retry
= ClassInterpretSenseInfo(DeviceObject
,
2132 irpStack
->MajorFunction
,
2133 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2134 MAXIMUM_RETRIES
- ((ULONG
)(ULONG_PTR
)realIrpNextStack
->Parameters
.Others
.Argument1
),
2138 TraceLog((CdromDebugTrace
,
2139 "CdRomDeviceControlCompletion: IRP will %sbe retried\n",
2140 (retry
? "" : "not ")));
2143 // Some of the Device Controls need special cases on non-Success status's.
2146 if (realIrpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
) {
2147 if ((realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_GET_LAST_SESSION
) ||
2148 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_READ_TOC
) ||
2149 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_READ_TOC_EX
) ||
2150 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_GET_CONTROL
) ||
2151 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_GET_VOLUME
)) {
2153 if (status
== STATUS_DATA_OVERRUN
) {
2154 status
= STATUS_SUCCESS
;
2159 if (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_READ_Q_CHANNEL
) {
2160 PLAY_ACTIVE(fdoExtension
) = FALSE
;
2165 // If the status is verified required and the this request
2166 // should bypass verify required then retry the request.
2169 if (realIrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
2170 status
== STATUS_VERIFY_REQUIRED
) {
2172 // note: status gets overwritten here
2173 status
= STATUS_IO_DEVICE_ERROR
;
2176 if (((realIrpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
) ||
2177 (realIrpStack
->MajorFunction
== IRP_MJ_INTERNAL_DEVICE_CONTROL
)
2179 ((realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
2180 IOCTL_CDROM_CHECK_VERIFY
) ||
2181 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
2182 IOCTL_STORAGE_CHECK_VERIFY
) ||
2183 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
2184 IOCTL_STORAGE_CHECK_VERIFY2
) ||
2185 (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
2186 IOCTL_DISK_CHECK_VERIFY
)
2191 // Update the geometry information, as the media could have
2192 // changed. The completion routine for this will complete
2193 // the real irp and start the next packet.
2197 if (srb
->SenseInfoBuffer
) {
2198 ExFreePool(srb
->SenseInfoBuffer
);
2200 if (srb
->DataBuffer
) {
2201 ExFreePool(srb
->DataBuffer
);
2207 if (Irp
->MdlAddress
) {
2208 IoFreeMdl(Irp
->MdlAddress
);
2209 Irp
->MdlAddress
= NULL
;
2215 status
= CdRomUpdateCapacity(fdoExtension
, realIrp
, NULL
);
2216 TraceLog((CdromDebugTrace
,
2217 "CdRomDeviceControlCompletion: [%p] "
2218 "CdRomUpdateCapacity completed with status %lx\n",
2222 // needed to update the capacity.
2223 // the irp's already handed off to CdRomUpdateCapacity().
2224 // we've already free'd the current irp.
2225 // nothing left to do in this code path.
2228 return STATUS_MORE_PROCESSING_REQUIRED
;
2230 } // end of ioctls to update capacity
2235 // get current retry count
2237 retryCount
= PtrToUlong(realIrpNextStack
->Parameters
.Others
.Argument1
);
2239 if (retry
&& retryCount
) {
2242 // update retry count
2244 realIrpNextStack
->Parameters
.Others
.Argument1
= UlongToPtr(retryCount
-1);
2246 if (((ULONG
)(ULONG_PTR
)realIrpNextStack
->Parameters
.Others
.Argument1
)) {
2252 TraceLog((CdromDebugWarning
,
2253 "Retry request %p - Calling StartIo\n", Irp
));
2256 ExFreePool(srb
->SenseInfoBuffer
);
2257 if (srb
->DataBuffer
) {
2258 ExFreePool(srb
->DataBuffer
);
2261 if (Irp
->MdlAddress
) {
2262 IoFreeMdl(Irp
->MdlAddress
);
2265 realIrpNextStack
->Parameters
.Others
.Argument3
= (PVOID
)-1;
2268 CdRomRetryRequest(fdoExtension
, realIrp
, retryInterval
, FALSE
);
2269 return STATUS_MORE_PROCESSING_REQUIRED
;
2273 // Exhausted retries. Fall through and complete the request with
2274 // the appropriate status.
2281 // Set status for successful request.
2284 status
= STATUS_SUCCESS
;
2289 if (NT_SUCCESS(status
)) {
2294 switch (realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
) {
2296 case IOCTL_CDROM_GET_CONFIGURATION
: {
2297 RtlMoveMemory(realIrp
->AssociatedIrp
.SystemBuffer
,
2299 srb
->DataTransferLength
);
2300 realIrp
->IoStatus
.Information
= srb
->DataTransferLength
;
2304 case IOCTL_DISK_GET_LENGTH_INFO
: {
2306 PGET_LENGTH_INFORMATION lengthInfo
;
2308 CdRomInterpretReadCapacity(DeviceObject
,
2309 (PREAD_CAPACITY_DATA
)srb
->DataBuffer
);
2311 lengthInfo
= (PGET_LENGTH_INFORMATION
)realIrp
->AssociatedIrp
.SystemBuffer
;
2312 lengthInfo
->Length
= commonExtension
->PartitionLength
;
2313 realIrp
->IoStatus
.Information
= sizeof(GET_LENGTH_INFORMATION
);
2314 status
= STATUS_SUCCESS
;
2318 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
:
2319 case IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX
: {
2321 PDISK_GEOMETRY_EX geometryEx
;
2323 CdRomInterpretReadCapacity(DeviceObject
,
2324 (PREAD_CAPACITY_DATA
)srb
->DataBuffer
);
2326 geometryEx
= (PDISK_GEOMETRY_EX
)(realIrp
->AssociatedIrp
.SystemBuffer
);
2327 geometryEx
->DiskSize
= commonExtension
->PartitionLength
;
2328 geometryEx
->Geometry
= fdoExtension
->DiskGeometry
;
2329 realIrp
->IoStatus
.Information
=
2330 FIELD_OFFSET(DISK_GEOMETRY_EX
, Data
);
2334 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
2335 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
: {
2337 PDISK_GEOMETRY geometry
;
2339 CdRomInterpretReadCapacity(DeviceObject
,
2340 (PREAD_CAPACITY_DATA
)srb
->DataBuffer
);
2342 geometry
= (PDISK_GEOMETRY
)(realIrp
->AssociatedIrp
.SystemBuffer
);
2343 *geometry
= fdoExtension
->DiskGeometry
;
2344 realIrp
->IoStatus
.Information
= sizeof(DISK_GEOMETRY
);
2348 case IOCTL_DISK_VERIFY
: {
2350 // nothing to do but return the status...
2355 case IOCTL_DISK_CHECK_VERIFY
:
2356 case IOCTL_STORAGE_CHECK_VERIFY
:
2357 case IOCTL_CDROM_CHECK_VERIFY
: {
2359 if((realIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
== IOCTL_CDROM_CHECK_VERIFY
) &&
2360 (realIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)) {
2362 *((PULONG
)realIrp
->AssociatedIrp
.SystemBuffer
) =
2363 commonExtension
->PartitionZeroExtension
->MediaChangeCount
;
2365 realIrp
->IoStatus
.Information
= sizeof(ULONG
);
2367 realIrp
->IoStatus
.Information
= 0;
2370 TraceLog((CdromDebugTrace
,
2371 "CdRomDeviceControlCompletion: [%p] completing "
2372 "CHECK_VERIFY buddy irp %p\n", realIrp
, Irp
));
2376 case IOCTL_CDROM_READ_TOC_EX
: {
2378 if (srb
->DataTransferLength
< MINIMUM_CDROM_READ_TOC_EX_SIZE
) {
2379 status
= STATUS_INVALID_DEVICE_REQUEST
;
2384 // Copy the returned info into the user buffer.
2387 RtlMoveMemory(realIrp
->AssociatedIrp
.SystemBuffer
,
2389 srb
->DataTransferLength
);
2392 // update information field.
2395 realIrp
->IoStatus
.Information
= srb
->DataTransferLength
;
2400 case IOCTL_CDROM_GET_LAST_SESSION
:
2401 case IOCTL_CDROM_READ_TOC
: {
2404 // Copy the returned info into the user buffer.
2407 RtlMoveMemory(realIrp
->AssociatedIrp
.SystemBuffer
,
2409 srb
->DataTransferLength
);
2412 // update information field.
2415 realIrp
->IoStatus
.Information
= srb
->DataTransferLength
;
2419 case IOCTL_DVD_READ_STRUCTURE
: {
2421 DVD_STRUCTURE_FORMAT format
= ((PDVD_READ_STRUCTURE
) realIrp
->AssociatedIrp
.SystemBuffer
)->Format
;
2423 PDVD_DESCRIPTOR_HEADER header
= realIrp
->AssociatedIrp
.SystemBuffer
;
2425 //FOUR_BYTE fourByte;
2426 //PTWO_BYTE twoByte;
2429 TraceLog((CdromDebugTrace
,
2430 "DvdDeviceControlCompletion - IOCTL_DVD_READ_STRUCTURE: completing irp %p (buddy %p)\n",
2434 TraceLog((CdromDebugTrace
,
2435 "DvdDCCompletion - READ_STRUCTURE: descriptor format of %d\n", format
));
2437 RtlMoveMemory(header
,
2439 srb
->DataTransferLength
);
2442 // Cook the data. There are a number of fields that really
2443 // should be byte-swapped for the caller.
2446 TraceLog((CdromDebugInfo
,
2447 "DvdDCCompletion - READ_STRUCTURE:\n"
2449 "\tDvdDCCompletion - READ_STRUCTURE: data at %p\n"
2450 "\tDataBuffer was at %p\n"
2451 "\tDataTransferLength was %lx\n",
2455 srb
->DataTransferLength
));
2458 // First the fields in the header
2461 TraceLog((CdromDebugInfo
, "READ_STRUCTURE: header->Length %lx -> ",
2463 REVERSE_SHORT(&header
->Length
);
2464 TraceLog((CdromDebugInfo
, "%lx\n", header
->Length
));
2467 // Now the fields in the descriptor
2470 if(format
== DvdPhysicalDescriptor
) {
2472 PDVD_LAYER_DESCRIPTOR layer
= (PDVD_LAYER_DESCRIPTOR
) &(header
->Data
[0]);
2474 TraceLog((CdromDebugInfo
, "READ_STRUCTURE: StartingDataSector %lx -> ",
2475 layer
->StartingDataSector
));
2476 REVERSE_LONG(&(layer
->StartingDataSector
));
2477 TraceLog((CdromDebugInfo
, "%lx\n", layer
->StartingDataSector
));
2479 TraceLog((CdromDebugInfo
, "READ_STRUCTURE: EndDataSector %lx -> ",
2480 layer
->EndDataSector
));
2481 REVERSE_LONG(&(layer
->EndDataSector
));
2482 TraceLog((CdromDebugInfo
, "%lx\n", layer
->EndDataSector
));
2484 TraceLog((CdromDebugInfo
, "READ_STRUCTURE: EndLayerZeroSector %lx -> ",
2485 layer
->EndLayerZeroSector
));
2486 REVERSE_LONG(&(layer
->EndLayerZeroSector
));
2487 TraceLog((CdromDebugInfo
, "%lx\n", layer
->EndLayerZeroSector
));
2490 TraceLog((CdromDebugTrace
, "Status is %lx\n", Irp
->IoStatus
.Status
));
2491 TraceLog((CdromDebugTrace
, "DvdDeviceControlCompletion - "
2492 "IOCTL_DVD_READ_STRUCTURE: data transfer length of %d\n",
2493 srb
->DataTransferLength
));
2495 realIrp
->IoStatus
.Information
= srb
->DataTransferLength
;
2499 case IOCTL_DVD_READ_KEY
: {
2501 PDVD_COPY_PROTECT_KEY copyProtectKey
= realIrp
->AssociatedIrp
.SystemBuffer
;
2503 PCDVD_KEY_HEADER keyHeader
= srb
->DataBuffer
;
2506 ULONG transferLength
=
2507 srb
->DataTransferLength
-
2508 FIELD_OFFSET(CDVD_KEY_HEADER
, Data
);
2511 // Adjust the data length to ignore the two reserved bytes in the
2515 dataLength
= (keyHeader
->DataLength
[0] << 8) +
2516 keyHeader
->DataLength
[1];
2520 // take the minimum of the transferred length and the
2521 // length as specified in the header.
2524 if(dataLength
< transferLength
) {
2525 transferLength
= dataLength
;
2528 TraceLog((CdromDebugTrace
,
2529 "DvdDeviceControlCompletion: [%p] - READ_KEY with "
2530 "transfer length of (%d or %d) bytes\n",
2533 srb
->DataTransferLength
- 2));
2536 // Copy the key data into the return buffer
2538 if(copyProtectKey
->KeyType
== DvdTitleKey
) {
2540 RtlMoveMemory(copyProtectKey
->KeyData
,
2541 keyHeader
->Data
+ 1,
2542 transferLength
- 1);
2543 copyProtectKey
->KeyData
[transferLength
- 1] = 0;
2546 // If this is a title key then we need to copy the CGMS flags
2549 copyProtectKey
->KeyFlags
= *(keyHeader
->Data
);
2553 RtlMoveMemory(copyProtectKey
->KeyData
,
2558 copyProtectKey
->KeyLength
= sizeof(DVD_COPY_PROTECT_KEY
);
2559 copyProtectKey
->KeyLength
+= transferLength
;
2561 realIrp
->IoStatus
.Information
= copyProtectKey
->KeyLength
;
2565 case IOCTL_DVD_START_SESSION
: {
2567 PDVD_SESSION_ID sessionId
= realIrp
->AssociatedIrp
.SystemBuffer
;
2569 PCDVD_KEY_HEADER keyHeader
= srb
->DataBuffer
;
2570 PCDVD_REPORT_AGID_DATA keyData
= (PCDVD_REPORT_AGID_DATA
) keyHeader
->Data
;
2572 *sessionId
= keyData
->AGID
;
2574 realIrp
->IoStatus
.Information
= sizeof(DVD_SESSION_ID
);
2579 case IOCTL_DVD_END_SESSION
:
2580 case IOCTL_DVD_SEND_KEY
:
2581 case IOCTL_DVD_SEND_KEY2
:
2584 // nothing to return
2586 realIrp
->IoStatus
.Information
= 0;
2589 case IOCTL_CDROM_PLAY_AUDIO_MSF
:
2591 PLAY_ACTIVE(fdoExtension
) = TRUE
;
2595 case IOCTL_CDROM_READ_Q_CHANNEL
: {
2597 PSUB_Q_CHANNEL_DATA userChannelData
= realIrp
->AssociatedIrp
.SystemBuffer
;
2598 PCDROM_SUB_Q_DATA_FORMAT inputBuffer
= realIrp
->AssociatedIrp
.SystemBuffer
;
2599 PSUB_Q_CHANNEL_DATA subQPtr
= srb
->DataBuffer
;
2602 switch( inputBuffer
->Format
) {
2604 case IOCTL_CDROM_CURRENT_POSITION
:
2605 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr
->CurrentPosition
.Header
.AudioStatus
));
2606 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr
->CurrentPosition
.ADR
));
2607 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr
->CurrentPosition
.Control
));
2608 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr
->CurrentPosition
.TrackNumber
));
2609 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr
->CurrentPosition
.IndexNumber
));
2610 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG
)subQPtr
->CurrentPosition
.AbsoluteAddress
) ));
2611 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG
)subQPtr
->CurrentPosition
.TrackRelativeAddress
) ));
2614 case IOCTL_CDROM_MEDIA_CATALOG
:
2615 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr
->MediaCatalog
.Header
.AudioStatus
));
2616 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr
->MediaCatalog
.Mcval
));
2619 case IOCTL_CDROM_TRACK_ISRC
:
2620 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr
->TrackIsrc
.Header
.AudioStatus
));
2621 TraceLog((CdromDebugTrace
,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr
->TrackIsrc
.Tcval
));
2628 // Update the play active status.
2631 if (subQPtr
->CurrentPosition
.Header
.AudioStatus
== AUDIO_STATUS_IN_PROGRESS
) {
2633 PLAY_ACTIVE(fdoExtension
) = TRUE
;
2637 PLAY_ACTIVE(fdoExtension
) = FALSE
;
2642 // Check if output buffer is large enough to contain
2646 if (realIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
<
2647 srb
->DataTransferLength
) {
2649 srb
->DataTransferLength
=
2650 realIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
2654 // Copy our buffer into users.
2657 RtlMoveMemory(userChannelData
,
2659 srb
->DataTransferLength
);
2661 realIrp
->IoStatus
.Information
= srb
->DataTransferLength
;
2665 case IOCTL_CDROM_PAUSE_AUDIO
:
2667 PLAY_ACTIVE(fdoExtension
) = FALSE
;
2668 realIrp
->IoStatus
.Information
= 0;
2671 case IOCTL_CDROM_RESUME_AUDIO
:
2673 realIrp
->IoStatus
.Information
= 0;
2676 case IOCTL_CDROM_SEEK_AUDIO_MSF
:
2678 realIrp
->IoStatus
.Information
= 0;
2681 case IOCTL_CDROM_STOP_AUDIO
:
2683 PLAY_ACTIVE(fdoExtension
) = FALSE
;
2684 realIrp
->IoStatus
.Information
= 0;
2687 case IOCTL_CDROM_GET_CONTROL
: {
2689 PCDROM_AUDIO_CONTROL audioControl
= srb
->DataBuffer
;
2690 PAUDIO_OUTPUT audioOutput
;
2691 ULONG bytesTransferred
;
2693 audioOutput
= ClassFindModePage((PCHAR
)audioControl
,
2694 srb
->DataTransferLength
,
2695 CDROM_AUDIO_CONTROL_PAGE
,
2698 // Verify the page is as big as expected.
2701 bytesTransferred
= (ULONG
)((PCHAR
) audioOutput
- (PCHAR
) audioControl
) +
2702 sizeof(AUDIO_OUTPUT
);
2704 if (audioOutput
!= NULL
&&
2705 srb
->DataTransferLength
>= bytesTransferred
) {
2707 audioControl
->LbaFormat
= audioOutput
->LbaFormat
;
2709 audioControl
->LogicalBlocksPerSecond
=
2710 (audioOutput
->LogicalBlocksPerSecond
[0] << (UCHAR
)8) |
2711 audioOutput
->LogicalBlocksPerSecond
[1];
2713 realIrp
->IoStatus
.Information
= sizeof(CDROM_AUDIO_CONTROL
);
2716 realIrp
->IoStatus
.Information
= 0;
2717 status
= STATUS_INVALID_DEVICE_REQUEST
;
2722 case IOCTL_CDROM_GET_VOLUME
: {
2724 PAUDIO_OUTPUT audioOutput
;
2725 PVOLUME_CONTROL volumeControl
= srb
->DataBuffer
;
2727 ULONG bytesTransferred
;
2729 audioOutput
= ClassFindModePage((PCHAR
)volumeControl
,
2730 srb
->DataTransferLength
,
2731 CDROM_AUDIO_CONTROL_PAGE
,
2735 // Verify the page is as big as expected.
2738 bytesTransferred
= (ULONG
)((PCHAR
) audioOutput
- (PCHAR
) volumeControl
) +
2739 sizeof(AUDIO_OUTPUT
);
2741 if (audioOutput
!= NULL
&&
2742 srb
->DataTransferLength
>= bytesTransferred
) {
2744 for (i
=0; i
<4; i
++) {
2745 volumeControl
->PortVolume
[i
] =
2746 audioOutput
->PortOutput
[i
].Volume
;
2750 // Set bytes transferred in IRP.
2753 realIrp
->IoStatus
.Information
= sizeof(VOLUME_CONTROL
);
2756 realIrp
->IoStatus
.Information
= 0;
2757 status
= STATUS_INVALID_DEVICE_REQUEST
;
2763 case IOCTL_CDROM_SET_VOLUME
:
2765 realIrp
->IoStatus
.Information
= 0;
2771 realIrp
->IoStatus
.Information
= 0;
2772 status
= STATUS_INVALID_DEVICE_REQUEST
;
2778 // Deallocate srb and sense buffer.
2782 if (srb
->DataBuffer
) {
2783 ExFreePool(srb
->DataBuffer
);
2785 if (srb
->SenseInfoBuffer
) {
2786 ExFreePool(srb
->SenseInfoBuffer
);
2791 if (realIrp
->PendingReturned
) {
2792 IoMarkIrpPending(realIrp
);
2795 if (Irp
->MdlAddress
) {
2796 IoFreeMdl(Irp
->MdlAddress
);
2802 // Set status in completing IRP.
2805 realIrp
->IoStatus
.Status
= status
;
2808 // Set the hard error if necessary.
2811 if (!NT_SUCCESS(status
) && IoIsErrorUserInduced(status
)) {
2814 // Store DeviceObject for filesystem, and clear
2815 // in IoStatus.Information field.
2818 TraceLog((CdromDebugWarning
,
2819 "CdRomDeviceCompletion - Setting Hard Error on realIrp %p\n",
2821 if (realIrp
->Tail
.Overlay
.Thread
) {
2822 IoSetHardErrorOrVerifyDevice(realIrp
, DeviceObject
);
2825 realIrp
->IoStatus
.Information
= 0;
2829 // note: must complete the realIrp, as the completed irp (above)
2830 // was self-allocated.
2833 CdRomCompleteIrpAndStartNextPacketSafely(DeviceObject
, realIrp
);
2834 return STATUS_MORE_PROCESSING_REQUIRED
;
2839 CdRomSetVolumeIntermediateCompletion(
2840 IN PDEVICE_OBJECT DeviceObject
,
2845 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension
= DeviceObject
->DeviceExtension
;
2846 PCOMMON_DEVICE_EXTENSION commonExtension
= DeviceObject
->DeviceExtension
;
2848 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
2849 PCDROM_DATA cdData
= (PCDROM_DATA
)(commonExtension
->DriverData
);
2850 BOOLEAN use6Byte
= TEST_FLAG(cdData
->XAFlags
, XA_USE_6_BYTE
);
2851 PIO_STACK_LOCATION realIrpStack
;
2852 PIO_STACK_LOCATION realIrpNextStack
;
2853 PSCSI_REQUEST_BLOCK srb
= Context
;
2854 PIRP realIrp
= NULL
;
2860 // Extract the 'real' irp from the irpstack.
2863 realIrp
= (PIRP
) irpStack
->Parameters
.Others
.Argument2
;
2864 realIrpStack
= IoGetCurrentIrpStackLocation(realIrp
);
2865 realIrpNextStack
= IoGetNextIrpStackLocation(realIrp
);
2868 // Check SRB status for success of completing request.
2871 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
2873 ULONG retryInterval
;
2875 TraceLog((CdromDebugTrace
,
2876 "CdRomSetVolumeIntermediateCompletion: Irp %p, Srb %p, Real Irp %p\n",
2882 // Release the queue if it is frozen.
2885 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
2886 ClassReleaseQueue(DeviceObject
);
2890 retry
= ClassInterpretSenseInfo(DeviceObject
,
2892 irpStack
->MajorFunction
,
2893 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
,
2894 MAXIMUM_RETRIES
- ((ULONG
)(ULONG_PTR
)realIrpNextStack
->Parameters
.Others
.Argument1
),
2898 if (status
== STATUS_DATA_OVERRUN
) {
2899 status
= STATUS_SUCCESS
;
2904 // If the status is verified required and the this request
2905 // should bypass verify required then retry the request.
2908 if (realIrpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
2909 status
== STATUS_VERIFY_REQUIRED
) {
2911 status
= STATUS_IO_DEVICE_ERROR
;
2916 // get current retry count
2918 retryCount
= PtrToUlong(realIrpNextStack
->Parameters
.Others
.Argument1
);
2920 if (retry
&& retryCount
) {
2923 // update retry count
2925 realIrpNextStack
->Parameters
.Others
.Argument1
= UlongToPtr(retryCount
-1);
2928 if (((ULONG
)(ULONG_PTR
)realIrpNextStack
->Parameters
.Others
.Argument1
)) {
2934 TraceLog((CdromDebugWarning
,
2935 "Retry request %p - Calling StartIo\n", Irp
));
2938 ExFreePool(srb
->SenseInfoBuffer
);
2939 ExFreePool(srb
->DataBuffer
);
2941 if (Irp
->MdlAddress
) {
2942 IoFreeMdl(Irp
->MdlAddress
);
2947 CdRomRetryRequest(deviceExtension
,
2952 return STATUS_MORE_PROCESSING_REQUIRED
;
2957 // Exhausted retries. Fall through and complete the request with the appropriate status.
2964 // Set status for successful request.
2967 status
= STATUS_SUCCESS
;
2971 if (NT_SUCCESS(status
)) {
2973 PAUDIO_OUTPUT audioInput
= NULL
;
2974 PAUDIO_OUTPUT audioOutput
;
2975 PVOLUME_CONTROL volumeControl
= realIrp
->AssociatedIrp
.SystemBuffer
;
2976 ULONG i
,bytesTransferred
,headerLength
;
2980 audioInput
= ClassFindModePage((PCHAR
)srb
->DataBuffer
,
2981 srb
->DataTransferLength
,
2982 CDROM_AUDIO_CONTROL_PAGE
,
2986 // Check to make sure the mode sense data is valid before we go on
2989 if(audioInput
== NULL
) {
2991 TraceLog((CdromDebugWarning
,
2992 "Mode Sense Page %d not found\n",
2993 CDROM_AUDIO_CONTROL_PAGE
));
2995 realIrp
->IoStatus
.Information
= 0;
2996 realIrp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
3001 headerLength
= sizeof(MODE_PARAMETER_HEADER
);
3003 headerLength
= sizeof(MODE_PARAMETER_HEADER10
);
3006 bytesTransferred
= sizeof(AUDIO_OUTPUT
) + headerLength
;
3009 // Allocate a new buffer for the mode select.
3012 dataBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
,
3014 CDROM_TAG_VOLUME_INT
);
3017 realIrp
->IoStatus
.Information
= 0;
3018 realIrp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
3022 RtlZeroMemory(dataBuffer
, bytesTransferred
);
3025 // Rebuild the data buffer to include the user requested values.
3028 audioOutput
= (PAUDIO_OUTPUT
) ((PCHAR
) dataBuffer
+ headerLength
);
3030 for (i
=0; i
<4; i
++) {
3031 audioOutput
->PortOutput
[i
].Volume
=
3032 volumeControl
->PortVolume
[i
];
3033 audioOutput
->PortOutput
[i
].ChannelSelection
=
3034 audioInput
->PortOutput
[i
].ChannelSelection
;
3037 audioOutput
->CodePage
= CDROM_AUDIO_CONTROL_PAGE
;
3038 audioOutput
->ParameterLength
= sizeof(AUDIO_OUTPUT
) - 2;
3039 audioOutput
->Immediate
= MODE_SELECT_IMMEDIATE
;
3042 // Free the old data buffer, mdl.
3045 IoFreeMdl(Irp
->MdlAddress
);
3046 Irp
->MdlAddress
= NULL
;
3047 ExFreePool(srb
->DataBuffer
);
3050 // set the data buffer to new allocation, so it can be
3051 // freed in the exit path
3054 srb
->DataBuffer
= dataBuffer
;
3060 cdb
= (PCDB
)srb
->Cdb
;
3061 RtlZeroMemory(cdb
, CDB12GENERIC_LENGTH
);
3063 srb
->SrbStatus
= srb
->ScsiStatus
= 0;
3064 srb
->SrbFlags
= deviceExtension
->SrbFlags
;
3065 SET_FLAG(srb
->SrbFlags
, SRB_FLAGS_DISABLE_SYNCH_TRANSFER
);
3066 SET_FLAG(srb
->SrbFlags
, SRB_FLAGS_DATA_OUT
);
3067 srb
->DataTransferLength
= bytesTransferred
;
3071 cdb
->MODE_SELECT
.OperationCode
= SCSIOP_MODE_SELECT
;
3072 cdb
->MODE_SELECT
.ParameterListLength
= (UCHAR
) bytesTransferred
;
3073 cdb
->MODE_SELECT
.PFBit
= 1;
3077 cdb
->MODE_SELECT10
.OperationCode
= SCSIOP_MODE_SELECT10
;
3078 cdb
->MODE_SELECT10
.ParameterListLength
[0] = (UCHAR
) (bytesTransferred
>> 8);
3079 cdb
->MODE_SELECT10
.ParameterListLength
[1] = (UCHAR
) (bytesTransferred
& 0xFF);
3080 cdb
->MODE_SELECT10
.PFBit
= 1;
3081 srb
->CdbLength
= 10;
3088 Irp
->MdlAddress
= IoAllocateMdl(dataBuffer
,
3094 if (!Irp
->MdlAddress
) {
3095 realIrp
->IoStatus
.Information
= 0;
3096 realIrp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
3100 MmBuildMdlForNonPagedPool(Irp
->MdlAddress
);
3102 irpStack
= IoGetNextIrpStackLocation(Irp
);
3103 irpStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
3104 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
= IOCTL_SCSI_EXECUTE_IN
;
3105 irpStack
->Parameters
.Scsi
.Srb
= srb
;
3108 // reset the irp completion.
3111 IoSetCompletionRoutine(Irp
,
3112 CdRomDeviceControlCompletion
,
3118 // Call the port driver.
3121 IoCallDriver(commonExtension
->LowerDeviceObject
, Irp
);
3123 return STATUS_MORE_PROCESSING_REQUIRED
;
3129 // Deallocate srb and sense buffer.
3133 if (srb
->DataBuffer
) {
3134 ExFreePool(srb
->DataBuffer
);
3136 if (srb
->SenseInfoBuffer
) {
3137 ExFreePool(srb
->SenseInfoBuffer
);
3142 if (Irp
->PendingReturned
) {
3143 IoMarkIrpPending(Irp
);
3146 if (realIrp
->PendingReturned
) {
3147 IoMarkIrpPending(realIrp
);
3150 if (Irp
->MdlAddress
) {
3151 IoFreeMdl(Irp
->MdlAddress
);
3157 // Set status in completing IRP.
3160 realIrp
->IoStatus
.Status
= status
;
3163 // Set the hard error if necessary.
3166 if (!NT_SUCCESS(status
) && IoIsErrorUserInduced(status
)) {
3169 // Store DeviceObject for filesystem, and clear
3170 // in IoStatus.Information field.
3173 if (realIrp
->Tail
.Overlay
.Thread
) {
3174 IoSetHardErrorOrVerifyDevice(realIrp
, DeviceObject
);
3176 realIrp
->IoStatus
.Information
= 0;
3179 CdRomCompleteIrpAndStartNextPacketSafely(DeviceObject
, realIrp
);
3180 return STATUS_MORE_PROCESSING_REQUIRED
;
3185 CdRomDvdEndAllSessionsCompletion(
3186 IN PDEVICE_OBJECT DeviceObject
,
3193 Routine Description:
3195 This routine will setup the next stack location to issue an end session
3196 to the device. It will increment the session id in the system buffer
3197 and issue an END_SESSION for that AGID if the AGID is valid.
3199 When the new AGID is > 3 this routine will complete the request.
3203 DeviceObject - the device object for this drive
3211 STATUS_MORE_PROCESSING_REQUIRED if there is another AGID to clear
3217 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= DeviceObject
->DeviceExtension
;
3219 PIO_STACK_LOCATION nextIrpStack
= IoGetNextIrpStackLocation(Irp
);
3221 PDVD_SESSION_ID sessionId
= Irp
->AssociatedIrp
.SystemBuffer
;
3225 if(++(*sessionId
) > MAX_COPY_PROTECT_AGID
) {
3228 // We're done here - just return success and let the io system
3229 // continue to complete it.
3232 return STATUS_SUCCESS
;
3236 IoCopyCurrentIrpStackLocationToNext(Irp
);
3238 IoSetCompletionRoutine(Irp
,
3239 CdRomDvdEndAllSessionsCompletion
,
3245 IoMarkIrpPending(Irp
);
3247 IoCallDriver(fdoExtension
->CommonExtension
.DeviceObject
, Irp
);
3250 // At this point we have to assume the irp may have already been
3251 // completed. Ignore the returned status and return.
3254 return STATUS_MORE_PROCESSING_REQUIRED
;
3259 CdRomDvdReadDiskKeyCompletion(
3260 IN PDEVICE_OBJECT DeviceObject
,
3267 Routine Description:
3269 This routine handles the completion of a request to obtain the disk
3270 key from the dvd media. It will transform the raw 2K of key data into
3271 a DVD_COPY_PROTECT_KEY structure and copy back the saved key parameters
3272 from the context pointer before returning.
3280 Context - a DVD_COPY_PROTECT_KEY pointer which contains the key
3281 parameters handed down by the caller.
3290 PDVD_COPY_PROTECT_KEY savedKey
= Context
;
3292 PREAD_DVD_STRUCTURES_HEADER rawKey
= Irp
->AssociatedIrp
.SystemBuffer
;
3293 PDVD_COPY_PROTECT_KEY outputKey
= Irp
->AssociatedIrp
.SystemBuffer
;
3295 if (NT_SUCCESS(Irp
->IoStatus
.Status
)) {
3298 // Shift the data down to its new position.
3301 RtlMoveMemory(outputKey
->KeyData
,
3303 sizeof(DVD_DISK_KEY_DESCRIPTOR
));
3305 RtlCopyMemory(outputKey
,
3307 sizeof(DVD_COPY_PROTECT_KEY
));
3309 outputKey
->KeyLength
= DVD_DISK_KEY_LENGTH
;
3311 Irp
->IoStatus
.Information
= DVD_DISK_KEY_LENGTH
;
3315 TraceLog((CdromDebugWarning
,
3316 "DiskKey Failed with status %x, %p (%x) bytes\n",
3317 Irp
->IoStatus
.Status
,
3318 (PVOID
)Irp
->IoStatus
.Information
,
3319 ((rawKey
->Length
[0] << 16) | rawKey
->Length
[1])
3325 // release the context block
3328 ExFreePool(Context
);
3330 return STATUS_SUCCESS
;
3336 IN PDEVICE_OBJECT DeviceObject
,
3343 Routine Description:
3345 This routine executes when the port driver has completed a request.
3346 It looks at the SRB status in the completing SRB and if not success
3347 it checks for valid request sense buffer information. If valid, the
3348 info is used to update status with more precise message of type of
3349 error. This routine deallocates the SRB.
3353 DeviceObject - Supplies the device object which represents the logical
3356 Irp - Supplies the Irp which has completed.
3358 Context - Supplies a pointer to the SRB.
3367 PIO_STACK_LOCATION irpStack
= IoGetCurrentIrpStackLocation(Irp
);
3368 PSCSI_REQUEST_BLOCK srb
= Context
;
3369 PFUNCTIONAL_DEVICE_EXTENSION deviceExtension
= DeviceObject
->DeviceExtension
;
3374 // Check SRB status for success of completing request.
3377 if (SRB_STATUS(srb
->SrbStatus
) != SRB_STATUS_SUCCESS
) {
3379 ULONG retryInterval
;
3381 TraceLog((CdromDebugTrace
, "CdromXAComplete: IRP %p SRB %p Status %x\n",
3382 Irp
, srb
, srb
->SrbStatus
));
3385 // Release the queue if it is frozen.
3388 if (srb
->SrbStatus
& SRB_STATUS_QUEUE_FROZEN
) {
3389 ClassReleaseQueue(DeviceObject
);
3392 retry
= ClassInterpretSenseInfo(
3395 irpStack
->MajorFunction
,
3396 irpStack
->MajorFunction
== IRP_MJ_DEVICE_CONTROL
? irpStack
->Parameters
.DeviceIoControl
.IoControlCode
: 0,
3397 MAXIMUM_RETRIES
- irpStack
->MinorFunction
, // HACKHACK - REF #0001
3402 // If the status is verified required and the this request
3403 // should bypass verify required then retry the request.
3406 if (irpStack
->Flags
& SL_OVERRIDE_VERIFY_VOLUME
&&
3407 status
== STATUS_VERIFY_REQUIRED
) {
3409 status
= STATUS_IO_DEVICE_ERROR
;
3415 if (irpStack
->MinorFunction
!= 0) { // HACKHACK - REF #0001
3417 irpStack
->MinorFunction
--; // HACKHACK - REF #0001
3423 TraceLog((CdromDebugWarning
,
3424 "CdRomXACompletion: Retry request %p (%x) - "
3425 "Calling StartIo\n", Irp
, irpStack
->MinorFunction
));
3428 ExFreePool(srb
->SenseInfoBuffer
);
3432 // Call StartIo directly since IoStartNextPacket hasn't been called,
3433 // the serialisation is still intact.
3436 CdRomRetryRequest(deviceExtension
,
3441 return STATUS_MORE_PROCESSING_REQUIRED
;
3446 // Exhausted retries, fall through and complete the request
3447 // with the appropriate status
3450 TraceLog((CdromDebugWarning
,
3451 "CdRomXACompletion: Retries exhausted for irp %p\n",
3459 // Set status for successful request.
3462 status
= STATUS_SUCCESS
;
3464 } // end if (SRB_STATUS(srb->SrbStatus) ...
3467 // Return SRB to nonpaged pool.
3470 ExFreePool(srb
->SenseInfoBuffer
);
3474 // Set status in completing IRP.
3477 Irp
->IoStatus
.Status
= status
;
3480 // Set the hard error if necessary.
3483 if (!NT_SUCCESS(status
) &&
3484 IoIsErrorUserInduced(status
) &&
3485 Irp
->Tail
.Overlay
.Thread
!= NULL
) {
3488 // Store DeviceObject for filesystem, and clear
3489 // in IoStatus.Information field.
3492 IoSetHardErrorOrVerifyDevice(Irp
, DeviceObject
);
3493 Irp
->IoStatus
.Information
= 0;
3497 // If pending has be returned for this irp then mark the current stack as
3501 if (Irp
->PendingReturned
) {
3502 IoMarkIrpPending(Irp
);
3506 KIRQL oldIrql
= KeRaiseIrqlToDpcLevel();
3507 IoStartNextPacket(DeviceObject
, FALSE
);
3508 KeLowerIrql(oldIrql
);
3510 ClassReleaseRemoveLock(DeviceObject
, Irp
);
3517 CdRomDeviceControlDvdReadStructure(
3518 IN PDEVICE_OBJECT Fdo
,
3519 IN PIRP OriginalIrp
,
3521 IN PSCSI_REQUEST_BLOCK Srb
3524 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(OriginalIrp
);
3525 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
3526 PCDB cdb
= (PCDB
)Srb
->Cdb
;
3529 PDVD_READ_STRUCTURE request
;
3532 PFOUR_BYTE fourByte
;
3535 (USHORT
)currentIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
3537 request
= OriginalIrp
->AssociatedIrp
.SystemBuffer
;
3539 (ULONG
)(request
->BlockByteOffset
.QuadPart
>> fdoExtension
->SectorShift
);
3540 fourByte
= (PFOUR_BYTE
) &blockNumber
;
3542 Srb
->CdbLength
= 12;
3543 Srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3544 Srb
->SrbFlags
= fdoExtension
->SrbFlags
;
3545 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_IN
);
3547 cdb
->READ_DVD_STRUCTURE
.OperationCode
= SCSIOP_READ_DVD_STRUCTURE
;
3548 cdb
->READ_DVD_STRUCTURE
.RMDBlockNumber
[0] = fourByte
->Byte3
;
3549 cdb
->READ_DVD_STRUCTURE
.RMDBlockNumber
[1] = fourByte
->Byte2
;
3550 cdb
->READ_DVD_STRUCTURE
.RMDBlockNumber
[2] = fourByte
->Byte1
;
3551 cdb
->READ_DVD_STRUCTURE
.RMDBlockNumber
[3] = fourByte
->Byte0
;
3552 cdb
->READ_DVD_STRUCTURE
.LayerNumber
= request
->LayerNumber
;
3553 cdb
->READ_DVD_STRUCTURE
.Format
= (UCHAR
)request
->Format
;
3557 if ((UCHAR
)request
->Format
> DvdMaxDescriptor
) {
3558 TraceLog((CdromDebugWarning
,
3559 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n",
3560 (UCHAR
)request
->Format
,
3561 READ_DVD_STRUCTURE_FORMAT_STRINGS
[DvdMaxDescriptor
],
3565 TraceLog((CdromDebugWarning
,
3566 "READ_DVD_STRUCTURE format %x = %s (%x bytes)\n",
3567 (UCHAR
)request
->Format
,
3568 READ_DVD_STRUCTURE_FORMAT_STRINGS
[(UCHAR
)request
->Format
],
3575 if (request
->Format
== DvdDiskKeyDescriptor
) {
3577 cdb
->READ_DVD_STRUCTURE
.AGID
= (UCHAR
) request
->SessionId
;
3581 cdb
->READ_DVD_STRUCTURE
.AllocationLength
[0] = (UCHAR
)(dataLength
>> 8);
3582 cdb
->READ_DVD_STRUCTURE
.AllocationLength
[1] = (UCHAR
)(dataLength
& 0xff);
3583 Srb
->DataTransferLength
= dataLength
;
3587 dataBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
,
3589 DVD_TAG_READ_STRUCTURE
);
3592 ExFreePool(Srb
->SenseInfoBuffer
);
3595 OriginalIrp
->IoStatus
.Information
= 0;
3596 OriginalIrp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
3598 BAIL_OUT(OriginalIrp
);
3599 CdRomCompleteIrpAndStartNextPacketSafely(Fdo
, OriginalIrp
);
3602 RtlZeroMemory(dataBuffer
, dataLength
);
3604 NewIrp
->MdlAddress
= IoAllocateMdl(dataBuffer
,
3605 currentIrpStack
->Parameters
.Read
.Length
,
3610 if (NewIrp
->MdlAddress
== NULL
) {
3611 ExFreePool(dataBuffer
);
3612 ExFreePool(Srb
->SenseInfoBuffer
);
3615 OriginalIrp
->IoStatus
.Information
= 0;
3616 OriginalIrp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
3618 BAIL_OUT(OriginalIrp
);
3619 CdRomCompleteIrpAndStartNextPacketSafely(Fdo
, OriginalIrp
);
3627 MmBuildMdlForNonPagedPool(NewIrp
->MdlAddress
);
3629 Srb
->DataBuffer
= dataBuffer
;
3631 IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, NewIrp
);
3638 CdRomDeviceControlDvdEndSession(
3639 IN PDEVICE_OBJECT Fdo
,
3640 IN PIRP OriginalIrp
,
3642 IN PSCSI_REQUEST_BLOCK Srb
3645 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(OriginalIrp
);
3646 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
3647 PCDB cdb
= (PCDB
)Srb
->Cdb
;
3649 PDVD_SESSION_ID sessionId
= OriginalIrp
->AssociatedIrp
.SystemBuffer
;
3651 Srb
->CdbLength
= 12;
3652 Srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3653 Srb
->SrbFlags
= fdoExtension
->SrbFlags
;
3654 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_NO_DATA_TRANSFER
);
3656 cdb
->SEND_KEY
.OperationCode
= SCSIOP_SEND_KEY
;
3657 cdb
->SEND_KEY
.AGID
= (UCHAR
) (*sessionId
);
3658 cdb
->SEND_KEY
.KeyFormat
= DVD_INVALIDATE_AGID
;
3660 IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, NewIrp
);
3667 CdRomDeviceControlDvdStartSessionReadKey(
3668 IN PDEVICE_OBJECT Fdo
,
3669 IN PIRP OriginalIrp
,
3671 IN PSCSI_REQUEST_BLOCK Srb
3674 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(OriginalIrp
);
3675 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
3676 PCDB cdb
= (PCDB
)Srb
->Cdb
;
3679 PDVD_COPY_PROTECT_KEY keyParameters
;
3680 PCDVD_KEY_HEADER keyBuffer
= NULL
;
3684 ULONG allocationLength
;
3685 PFOUR_BYTE fourByte
;
3688 // Both of these use REPORT_KEY commands.
3689 // Determine the size of the input buffer
3692 if(currentIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
3693 IOCTL_DVD_READ_KEY
) {
3695 keyParameters
= OriginalIrp
->AssociatedIrp
.SystemBuffer
;
3697 keyLength
= sizeof(CDVD_KEY_HEADER
) +
3698 (currentIrpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
-
3699 sizeof(DVD_COPY_PROTECT_KEY
));
3702 keyParameters
= NULL
;
3703 keyLength
= sizeof(CDVD_KEY_HEADER
) +
3704 sizeof(CDVD_REPORT_AGID_DATA
);
3709 keyBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
,
3713 if(keyBuffer
== NULL
) {
3715 TraceLog((CdromDebugWarning
,
3716 "IOCTL_DVD_READ_KEY - couldn't allocate "
3717 "%d byte buffer for key\n",
3719 status
= STATUS_INSUFFICIENT_RESOURCES
;
3724 NewIrp
->MdlAddress
= IoAllocateMdl(keyBuffer
,
3730 if(NewIrp
->MdlAddress
== NULL
) {
3732 TraceLog((CdromDebugWarning
,
3733 "IOCTL_DVD_READ_KEY - couldn't create mdl\n"));
3734 status
= STATUS_INSUFFICIENT_RESOURCES
;
3738 MmBuildMdlForNonPagedPool(NewIrp
->MdlAddress
);
3740 Srb
->DataBuffer
= keyBuffer
;
3741 Srb
->CdbLength
= 12;
3743 cdb
->REPORT_KEY
.OperationCode
= SCSIOP_REPORT_KEY
;
3745 allocationLength
= keyLength
;
3746 fourByte
= (PFOUR_BYTE
) &allocationLength
;
3747 cdb
->REPORT_KEY
.AllocationLength
[0] = fourByte
->Byte1
;
3748 cdb
->REPORT_KEY
.AllocationLength
[1] = fourByte
->Byte0
;
3750 Srb
->DataTransferLength
= keyLength
;
3753 // set the specific parameters....
3756 if(currentIrpStack
->Parameters
.DeviceIoControl
.IoControlCode
==
3757 IOCTL_DVD_READ_KEY
) {
3759 if(keyParameters
->KeyType
== DvdTitleKey
) {
3761 ULONG logicalBlockAddress
;
3763 logicalBlockAddress
= (ULONG
)
3764 (keyParameters
->Parameters
.TitleOffset
.QuadPart
>>
3765 fdoExtension
->SectorShift
);
3767 fourByte
= (PFOUR_BYTE
) &(logicalBlockAddress
);
3769 cdb
->REPORT_KEY
.LogicalBlockAddress
[0] = fourByte
->Byte3
;
3770 cdb
->REPORT_KEY
.LogicalBlockAddress
[1] = fourByte
->Byte2
;
3771 cdb
->REPORT_KEY
.LogicalBlockAddress
[2] = fourByte
->Byte1
;
3772 cdb
->REPORT_KEY
.LogicalBlockAddress
[3] = fourByte
->Byte0
;
3775 cdb
->REPORT_KEY
.KeyFormat
= (UCHAR
)keyParameters
->KeyType
;
3776 cdb
->REPORT_KEY
.AGID
= (UCHAR
) keyParameters
->SessionId
;
3777 TraceLog((CdromDebugWarning
,
3778 "CdRomDvdReadKey => sending irp %p for irp %p (%s)\n",
3779 NewIrp
, OriginalIrp
, "READ_KEY"));
3783 cdb
->REPORT_KEY
.KeyFormat
= DVD_REPORT_AGID
;
3784 cdb
->REPORT_KEY
.AGID
= 0;
3785 TraceLog((CdromDebugWarning
,
3786 "CdRomDvdReadKey => sending irp %p for irp %p (%s)\n",
3787 NewIrp
, OriginalIrp
, "START_SESSION"));
3790 Srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3791 Srb
->SrbFlags
= fdoExtension
->SrbFlags
;
3792 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_IN
);
3794 IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, NewIrp
);
3796 status
= STATUS_SUCCESS
;
3800 if (!NT_SUCCESS(status
)) {
3803 // An error occured during setup - free resources and
3804 // complete this request.
3806 if (NewIrp
->MdlAddress
!= NULL
) {
3807 IoFreeMdl(NewIrp
->MdlAddress
);
3810 if (keyBuffer
!= NULL
) {
3811 ExFreePool(keyBuffer
);
3813 ExFreePool(Srb
->SenseInfoBuffer
);
3817 OriginalIrp
->IoStatus
.Information
= 0;
3818 OriginalIrp
->IoStatus
.Status
= status
;
3820 BAIL_OUT(OriginalIrp
);
3821 CdRomCompleteIrpAndStartNextPacketSafely(Fdo
, OriginalIrp
);
3823 } // end !NT_SUCCESS
3830 CdRomDeviceControlDvdSendKey(
3831 IN PDEVICE_OBJECT Fdo
,
3832 IN PIRP OriginalIrp
,
3834 IN PSCSI_REQUEST_BLOCK Srb
3837 PIO_STACK_LOCATION currentIrpStack
= IoGetCurrentIrpStackLocation(OriginalIrp
);
3838 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
3839 PCDB cdb
= (PCDB
)Srb
->Cdb
;
3841 PDVD_COPY_PROTECT_KEY key
;
3842 PCDVD_KEY_HEADER keyBuffer
= NULL
;
3846 PFOUR_BYTE fourByte
;
3848 key
= OriginalIrp
->AssociatedIrp
.SystemBuffer
;
3849 keyLength
= (key
->KeyLength
- sizeof(DVD_COPY_PROTECT_KEY
)) +
3850 sizeof(CDVD_KEY_HEADER
);
3854 keyBuffer
= ExAllocatePoolWithTag(NonPagedPoolCacheAligned
,
3858 if(keyBuffer
== NULL
) {
3860 TraceLog((CdromDebugWarning
,
3861 "IOCTL_DVD_SEND_KEY - couldn't allocate "
3862 "%d byte buffer for key\n",
3864 status
= STATUS_INSUFFICIENT_RESOURCES
;
3868 RtlZeroMemory(keyBuffer
, keyLength
);
3871 // keylength is decremented here by two because the
3872 // datalength does not include the header, which is two
3873 // bytes. keylength is immediately incremented later
3874 // by the same amount.
3878 fourByte
= (PFOUR_BYTE
) &keyLength
;
3879 keyBuffer
->DataLength
[0] = fourByte
->Byte1
;
3880 keyBuffer
->DataLength
[1] = fourByte
->Byte0
;
3884 // copy the user's buffer to our own allocated buffer
3887 RtlMoveMemory(keyBuffer
->Data
,
3889 key
->KeyLength
- sizeof(DVD_COPY_PROTECT_KEY
));
3892 NewIrp
->MdlAddress
= IoAllocateMdl(keyBuffer
,
3898 if(NewIrp
->MdlAddress
== NULL
) {
3899 TraceLog((CdromDebugWarning
,
3900 "IOCTL_DVD_SEND_KEY - couldn't create mdl\n"));
3901 status
= STATUS_INSUFFICIENT_RESOURCES
;
3906 MmBuildMdlForNonPagedPool(NewIrp
->MdlAddress
);
3908 Srb
->CdbLength
= 12;
3909 Srb
->DataBuffer
= keyBuffer
;
3910 Srb
->DataTransferLength
= keyLength
;
3912 Srb
->TimeOutValue
= fdoExtension
->TimeOutValue
;
3913 Srb
->SrbFlags
= fdoExtension
->SrbFlags
;
3914 SET_FLAG(Srb
->SrbFlags
, SRB_FLAGS_DATA_OUT
);
3916 cdb
->REPORT_KEY
.OperationCode
= SCSIOP_SEND_KEY
;
3918 fourByte
= (PFOUR_BYTE
) &keyLength
;
3920 cdb
->SEND_KEY
.ParameterListLength
[0] = fourByte
->Byte1
;
3921 cdb
->SEND_KEY
.ParameterListLength
[1] = fourByte
->Byte0
;
3922 cdb
->SEND_KEY
.KeyFormat
= (UCHAR
)key
->KeyType
;
3923 cdb
->SEND_KEY
.AGID
= (UCHAR
) key
->SessionId
;
3925 if (key
->KeyType
== DvdSetRpcKey
) {
3926 TraceLog((CdromDebugWarning
,
3927 "IOCTL_DVD_SEND_KEY - Setting RPC2 drive region\n"));
3929 TraceLog((CdromDebugWarning
,
3930 "IOCTL_DVD_SEND_KEY - key type %x\n", key
->KeyType
));
3933 IoCallDriver(fdoExtension
->CommonExtension
.LowerDeviceObject
, NewIrp
);
3935 status
= STATUS_SUCCESS
;
3939 if (!NT_SUCCESS(status
)) {
3942 // An error occured during setup - free resources and
3943 // complete this request.
3946 if (NewIrp
->MdlAddress
!= NULL
) {
3947 IoFreeMdl(NewIrp
->MdlAddress
);
3950 if (keyBuffer
!= NULL
) {
3951 ExFreePool(keyBuffer
);
3954 ExFreePool(Srb
->SenseInfoBuffer
);
3958 OriginalIrp
->IoStatus
.Information
= 0;
3959 OriginalIrp
->IoStatus
.Status
= status
;
3961 BAIL_OUT(OriginalIrp
);
3962 CdRomCompleteIrpAndStartNextPacketSafely(Fdo
, OriginalIrp
);
3972 CdRomInterpretReadCapacity(
3973 IN PDEVICE_OBJECT Fdo
,
3974 IN PREAD_CAPACITY_DATA ReadCapacityBuffer
3977 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
3978 PCOMMON_DEVICE_EXTENSION commonExtension
= Fdo
->DeviceExtension
;
3984 ASSERT(ReadCapacityBuffer
);
3985 ASSERT(commonExtension
->IsFdo
);
3987 TraceLog((CdromDebugError
,
3988 "CdRomInterpretReadCapacity: Entering\n"));
3991 // Swizzle bytes from Read Capacity and translate into
3992 // the necessary geometry information in the device extension.
3995 tmp
= ReadCapacityBuffer
->BytesPerBlock
;
3996 ((PFOUR_BYTE
)&bps
)->Byte0
= ((PFOUR_BYTE
)&tmp
)->Byte3
;
3997 ((PFOUR_BYTE
)&bps
)->Byte1
= ((PFOUR_BYTE
)&tmp
)->Byte2
;
3998 ((PFOUR_BYTE
)&bps
)->Byte2
= ((PFOUR_BYTE
)&tmp
)->Byte1
;
3999 ((PFOUR_BYTE
)&bps
)->Byte3
= ((PFOUR_BYTE
)&tmp
)->Byte0
;
4002 // Insure that bps is a power of 2.
4003 // This corrects a problem with the HP 4020i CDR where it
4004 // returns an incorrect number for bytes per sector.
4010 lastBit
= (ULONG
) -1;
4018 fdoExtension
->DiskGeometry
.BytesPerSector
= bps
;
4020 TraceLog((CdromDebugTrace
, "CdRomInterpretReadCapacity: Calculated bps %#x\n",
4021 fdoExtension
->DiskGeometry
.BytesPerSector
));
4024 // Copy last sector in reverse byte order.
4027 tmp
= ReadCapacityBuffer
->LogicalBlockAddress
;
4028 ((PFOUR_BYTE
)&lastSector
)->Byte0
= ((PFOUR_BYTE
)&tmp
)->Byte3
;
4029 ((PFOUR_BYTE
)&lastSector
)->Byte1
= ((PFOUR_BYTE
)&tmp
)->Byte2
;
4030 ((PFOUR_BYTE
)&lastSector
)->Byte2
= ((PFOUR_BYTE
)&tmp
)->Byte1
;
4031 ((PFOUR_BYTE
)&lastSector
)->Byte3
= ((PFOUR_BYTE
)&tmp
)->Byte0
;
4034 // Calculate sector to byte shift.
4037 WHICH_BIT(bps
, fdoExtension
->SectorShift
);
4039 TraceLog((CdromDebugTrace
,"CdRomInterpretReadCapacity: Sector size is %d\n",
4040 fdoExtension
->DiskGeometry
.BytesPerSector
));
4042 TraceLog((CdromDebugTrace
,"CdRomInterpretReadCapacity: Number of Sectors is %d\n",
4046 // Calculate media capacity in bytes.
4049 commonExtension
->PartitionLength
.QuadPart
= (LONGLONG
)(lastSector
+ 1);
4052 // we've defaulted to 32/64 forever. don't want to change this now...
4055 fdoExtension
->DiskGeometry
.TracksPerCylinder
= 0x40;
4056 fdoExtension
->DiskGeometry
.SectorsPerTrack
= 0x20;
4059 // Calculate number of cylinders.
4062 fdoExtension
->DiskGeometry
.Cylinders
.QuadPart
= (LONGLONG
)((lastSector
+ 1) / (32 * 64));
4064 commonExtension
->PartitionLength
.QuadPart
=
4065 (commonExtension
->PartitionLength
.QuadPart
<< fdoExtension
->SectorShift
);
4068 ASSERT(TEST_FLAG(Fdo
->Characteristics
, FILE_REMOVABLE_MEDIA
));
4071 // This device supports removable media.
4074 fdoExtension
->DiskGeometry
.MediaType
= RemovableMedia
;