ReactOS  0.4.13-dev-73-gcfe54aa
cdrom.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Storage Stack
3  * LICENSE: DDK - see license.txt in the root dir
4  * FILE: drivers/storage/cdrom/cdrom.c
5  * PURPOSE: CDROM driver
6  * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
7  */
8 
9 #include "precomp.h"
10 
11 #include <ntddk.h>
12 #include <scsi.h>
13 #include <ntdddisk.h>
14 #include <ntddcdrm.h>
15 #include <include/class2.h>
16 #include <stdio.h>
17 
18 //#define NDEBUG
19 #include <debug.h>
20 
21 #define CDB12GENERIC_LENGTH 12
22 
23 typedef struct _XA_CONTEXT {
24 
25  //
26  // Pointer to the device object.
27  //
28 
30 
31  //
32  // Pointer to the original request when
33  // a mode select must be sent.
34  //
35 
37 
38  //
39  // Pointer to the mode select srb.
40  //
41 
44 
45 typedef struct _ERROR_RECOVERY_DATA {
50 
51 typedef struct _ERROR_RECOVERY_DATA10 {
56 
57 //
58 // CdRom specific addition to device extension.
59 //
60 
61 typedef struct _CDROM_DATA {
62 
63  //
64  // Indicates whether an audio play operation
65  // is currently being performed.
66  //
67 
69 
70  //
71  // Indicates whether the blocksize used for user data
72  // is 2048 or 2352.
73  //
74 
76 
77  //
78  // Indicates whether 6 or 10 byte mode sense/select
79  // should be used.
80  //
81 
83 
84  //
85  // Storage for the error recovery page. This is used
86  // as an easy method to switch block sizes.
87  //
88 
89  union {
92  };
93 
94 
95  //
96  // Pointer to the original irp for the raw read.
97  //
98 
100 
101  //
102  // Used to protect accesses to the RawAccess flag.
103  //
104 
106 
107  //
108  // Even if media change support is requested, there are some devices
109  // that are not supported. This flag will indicate that such a device
110  // is present when it is FALSE.
111  //
112 
114 
115  //
116  // The media change event is being supported. The media change timer
117  // should be running whenever this is true.
118  //
119 
121 
122  //
123  // The timer value to support media change events. This is a countdown
124  // value used to determine when to poll the device for a media change.
125  // The max value for the timer is 255 seconds.
126  //
127 
129 
130 #if DBG
131  //
132  // Second timer to keep track of how long the media change IRP has been
133  // in use. If this value exceeds the timeout (#defined) then we should
134  // print out a message to the user and set the MediaChangeIrpLost flag
135  //
136 
137  SHORT MediaChangeIrpTimeInUse;
138 
139  //
140  // Set by CdRomTickHandler when we determine that the media change irp has
141  // been lost
142  //
143 
144  BOOLEAN MediaChangeIrpLost;
145 #endif
146 
147  UCHAR PadReserve; // use this for new flags.
148 
149  //
150  // An IRP is allocated and kept for the duration that media change
151  // detection is in effect. If this is NULL and MediaChange is TRUE,
152  // the detection is in progress. This should always be NULL when
153  // MediaChange is FALSE.
154  //
155 
157 
158  //
159  // The timer work list is a collection of IRPS that are prepared for
160  // submission, but need to allow some time to pass before they are
161  // run.
162  //
163 
166 
168 
169 #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(CDROM_DATA)
170 #define SCSI_CDROM_TIMEOUT 10
171 #define SCSI_CHANGER_BONUS_TIMEOUT 10
172 #define HITACHI_MODE_DATA_SIZE 12
173 #define MODE_DATA_SIZE 64
174 #define RAW_SECTOR_SIZE 2352
175 #define COOKED_SECTOR_SIZE 2048
176 #define MEDIA_CHANGE_DEFAULT_TIME 4
177 #define CDROM_SRB_LIST_SIZE 4
178 
179 
180 #if DBG
181 
182 //
183 // Used to detect the loss of the autorun irp. The driver prints out a message
184 // (debug level 0) if this timeout ever occurs
185 //
186 #define MEDIA_CHANGE_TIMEOUT_TIME 300
187 
188 #endif
189 
190 #define PLAY_ACTIVE(DeviceExtension) (((PCDROM_DATA)(DeviceExtension + 1))->PlayActive)
191 
192 #define MSF_TO_LBA(Minutes,Seconds,Frames) \
193  (ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
194 
195 #define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
196 { \
197  (Minutes) = (UCHAR)(Lba / (60 * 75)); \
198  (Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \
199  (Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \
200 }
201 
202 #define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
203 
204 //
205 // Define flags for XA, CDDA, and Mode Select/Sense
206 //
207 
208 #define XA_USE_6_BYTE 0x01
209 #define XA_USE_10_BYTE 0x02
210 #define XA_USE_READ_CD 0x04
211 #define XA_NOT_SUPPORTED 0x08
212 
213 #define PLEXTOR_CDDA 0x10
214 #define NEC_CDDA 0x20
215 
216 //
217 // Sector types for READ_CD
218 //
219 
220 #define ANY_SECTOR 0
221 #define CD_DA_SECTOR 1
222 #define YELLOW_MODE1_SECTOR 2
223 #define YELLOW_MODE2_SECTOR 3
224 #define FORM2_MODE1_SECTOR 4
225 #define FORM2_MODE2_SECTOR 5
226 
227 
228 #ifdef POOL_TAGGING
229 #ifdef ExAllocatePool
230 #undef ExAllocatePool
231 #endif
232 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'CscS')
233 #endif
234 
235 NTSTATUS
236 NTAPI
240  );
241 
242 BOOLEAN
243 NTAPI
248  IN PDEVICE_OBJECT PortDeviceObject,
250  );
251 
252 NTSTATUS
253 NTAPI
256  IN PIRP Irp
257  );
258 
259 NTSTATUS
260 NTAPI
263  IN PIRP Irp
264  );
265 
266 NTSTATUS
267 NTAPI
272  );
273 
274 NTSTATUS
275 NTAPI
278  IN PIRP Irp
279  );
280 
281 IO_COMPLETION_ROUTINE CdRomDeviceControlCompletion;
282 NTSTATUS
283 NTAPI
286  IN PIRP Irp,
288  );
289 
291 NTSTATUS
292 NTAPI
295  IN PIRP Irp,
297  );
298 
299 IO_COMPLETION_ROUTINE CdRomSwitchModeCompletion;
300 NTSTATUS
301 NTAPI
304  IN PIRP Irp,
306  );
307 
308 IO_COMPLETION_ROUTINE CdRomXACompletion;
309 NTSTATUS
310 NTAPI
313  IN PIRP Irp,
315  );
316 
317 IO_COMPLETION_ROUTINE CdRomClassIoctlCompletion;
318 NTSTATUS
319 NTAPI
322  IN PIRP Irp,
324  );
325 
326 VOID
327 NTAPI
330  IN PIRP Irp
331  );
332 
333 VOID
334 NTAPI
338  );
339 
340 BOOLEAN
341 NTAPI
345  );
346 
347 NTSTATUS
348 NTAPI
350  IN PDEVICE_EXTENSION DeviceExtension,
351  IN PIRP IrpToComplete,
352  IN OPTIONAL PKEVENT IoctlEvent
353  );
354 
355 NTSTATUS
356 NTAPI
359  IN PDEVICE_OBJECT PortDeviceObject,
362  PIO_SCSI_CAPABILITIES PortCapabilities,
363  IN PSCSI_INQUIRY_DATA LunInfo,
366  );
367 
368 VOID
369 NTAPI
372  PINQUIRYDATA InquiryData,
373  PIO_SCSI_CAPABILITIES PortCapabilities
374  );
375 
376 BOOLEAN
377 NTAPI
380  );
381 
382 VOID
383 NTAPI
387  NTSTATUS *Status,
388  BOOLEAN *Retry
389  );
390 
391 IO_COMPLETION_ROUTINE ToshibaProcessErrorCompletion;
392 VOID
393 NTAPI
397  NTSTATUS *Status,
398  BOOLEAN *Retry
399  );
400 
401 BOOLEAN
402 NTAPI
405  OUT PULONG DiscsPresent
406  );
407 
408 BOOLEAN
409 NTAPI
412  IN UCHAR PathId,
414  );
415 
416 BOOLEAN
417 NTAPI
420  IN PDEVICE_OBJECT PortDeviceObject
421  );
422 
423 VOID
424 NTAPI
426  IN PDEVICE_EXTENSION DeviceExtension,
428  );
429 
430 #ifdef _PPC_
431 NTSTATUS
434  IN UNICODE_STRING ScsiUnicodeString[],
435  OUT PUCHAR IntermediateController
436  );
437 #endif
438 
439 #ifdef ALLOC_PRAGMA
440 #pragma alloc_text(PAGE, DriverEntry)
441 #pragma alloc_text(PAGE, ScsiCdRomFindDevices)
442 #pragma alloc_text(PAGE, CreateCdRomDeviceObject)
443 #pragma alloc_text(PAGE, ScanForSpecial)
444 //#pragma alloc_text(PAGE, CdRomDeviceControl)
445 #pragma alloc_text(PAGE, HitachProcessError)
446 #pragma alloc_text(PAGE, CdRomIsPlayActive)
447 #pragma alloc_text(PAGE, ScsiCdRomReadVerification)
448 #pragma alloc_text(INIT, CdRomCheckRegistryForMediaChangeValue)
449 #pragma alloc_text(INIT, IsThisAnAtapiChanger)
450 #pragma alloc_text(INIT, IsThisASanyo)
451 #pragma alloc_text(INIT, IsThisAMultiLunDevice)
452 #pragma alloc_text(INIT, CdRomCreateNamedEvent)
453 #ifdef _PPC_
454 #pragma alloc_text(PAGE, FindScsiAdapter)
455 #endif
456 #endif
457 
459 
460 NTSTATUS
461 NTAPI
465  )
466 
467 /*++
468 
469 Routine Description:
470 
471  This routine initializes the cdrom class driver.
472 
473 Arguments:
474 
475  DriverObject - Pointer to driver object created by system.
476 
477  RegistryPath - Pointer to the name of the services node for this driver.
478 
479 Return Value:
480 
481  The function value is the final status from the initialization operation.
482 
483 --*/
484 
485 {
487 
488  if(NoLoad) {
489  return STATUS_NO_SUCH_DEVICE;
490  }
491 
492  //
493  // Zero InitData
494  //
495 
497 
498  //
499  // Set sizes
500  //
501 
502  InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
503  InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
504 
507 
508  //
509  // Set entry points
510  //
511 
512  InitializationData.ClassReadWriteVerification = ScsiCdRomReadVerification;
513  InitializationData.ClassDeviceControl = CdRomDeviceControl;
514  InitializationData.ClassFindDevices = ScsiCdRomFindDevices;
515  InitializationData.ClassShutdownFlush = NULL;
516  InitializationData.ClassCreateClose = NULL;
517  InitializationData.ClassStartIo = ScsiCdRomStartIo;
518 
519  //
520  // Call the class init routine
521  //
522 
524 
525 } // end DriverEntry()
526 
527 BOOLEAN
528 NTAPI
533  IN PDEVICE_OBJECT PortDeviceObject,
535  )
536 
537 /*++
538 
539 Routine Description:
540 
541  Connect to SCSI port driver. Get adapter capabilities and
542  SCSI bus configuration information. Search inquiry data
543  for CDROM devices to process.
544 
545 Arguments:
546 
547  DriverObject - CDROM class driver object.
548  PortDeviceObject - SCSI port driver device object.
549  PortNumber - The system ordinal for this scsi adapter.
550 
551 Return Value:
552 
553  TRUE if CDROM device present on this SCSI adapter.
554 
555 --*/
556 
557 {
558  PIO_SCSI_CAPABILITIES portCapabilities;
559  PULONG cdRomCount;
560  PCHAR buffer;
561  PSCSI_INQUIRY_DATA lunInfo;
562  PSCSI_ADAPTER_BUS_INFO adapterInfo;
563  PINQUIRYDATA inquiryData;
564  ULONG scsiBus;
566  BOOLEAN foundDevice = FALSE;
567 
568  //
569  // Call port driver to get adapter capabilities.
570  //
571 
572  status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
573 
574  if (!NT_SUCCESS(status)) {
575  DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
576  return foundDevice;
577  }
578 
579  //
580  // Call port driver to get inquiry information to find cdroms.
581  //
582 
584 
585  if (!NT_SUCCESS(status)) {
586  DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
587  return foundDevice;
588  }
589 
590  //
591  // Get the address of the count of the number of cdroms already initialized.
592  //
593 
594  cdRomCount = &IoGetConfigurationInformation()->CdRomCount;
595  adapterInfo = (PVOID) buffer;
596 
597  //
598  // For each SCSI bus this adapter supports ...
599  //
600 
601  for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++) {
602 
603  //
604  // Get the SCSI bus scan data for this bus.
605  //
606 
607  lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
608 
609  //
610  // Search list for unclaimed disk devices.
611  //
612 
613  while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
614 
615  inquiryData = (PVOID)lunInfo->InquiryData;
616 
617  if ((inquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) &&
618  (inquiryData->DeviceTypeQualifier == 0) &&
619  (!lunInfo->DeviceClaimed)) {
620 
621  DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n",
622  inquiryData->VendorId));
623 
624  //
625  // Create device objects for cdrom
626  //
627 
629  PortDeviceObject,
630  PortNumber,
631  cdRomCount,
632  portCapabilities,
633  lunInfo,
635  RegistryPath);
636 
637  if (NT_SUCCESS(status)) {
638 
639  //
640  // Increment system cdrom device count.
641  //
642 
643  (*cdRomCount)++;
644 
645  //
646  // Indicate that a cdrom device was found.
647  //
648 
649  foundDevice = TRUE;
650  }
651  }
652 
653  //
654  // Get next LunInfo.
655  //
656 
657  if (lunInfo->NextInquiryDataOffset == 0) {
658  break;
659  }
660 
661  lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
662  }
663  }
664 
666 
667 
668  return foundDevice;
669 
670 } // end FindScsiCdRoms()
671 
672 VOID
673 NTAPI
675  IN PDEVICE_EXTENSION DeviceExtension,
677  )
678 
679 /*++
680 
681 Routine Description:
682 
683  Create the named synchronization event for notification of media change
684  events to the system. The event is reset before this function returns.
685 
686 Arguments:
687 
688  DeviceExtension - the device extension pointer for storage of the event pointer.
689 
690 Return Value:
691 
692  None.
693 
694 --*/
695 
696 {
697  UNICODE_STRING unicodeString;
698  OBJECT_ATTRIBUTES objectAttributes;
699  CCHAR eventNameBuffer[MAXIMUM_FILENAME_LENGTH];
700  STRING eventNameString;
701  HANDLE handle;
703 
704 
705  sprintf(eventNameBuffer,"\\Device\\MediaChangeEvent%ld",
706  DeviceNumber);
707 
708  RtlInitString(&eventNameString,
709  eventNameBuffer);
710 
711  status = RtlAnsiStringToUnicodeString(&unicodeString,
712  &eventNameString,
713  TRUE);
714 
715  if (!NT_SUCCESS(status)) {
716  return;
717  }
718 
719  InitializeObjectAttributes(&objectAttributes,
720  &unicodeString,
722  NULL,
723  NULL);
724 
725  DeviceExtension->MediaChangeEvent = IoCreateSynchronizationEvent(&unicodeString,
726  &handle);
727  DeviceExtension->MediaChangeEventHandle = handle;
728 
729  KeClearEvent(DeviceExtension->MediaChangeEvent);
730 
731  RtlFreeUnicodeString(&unicodeString);
732 }
733 
734 NTSTATUS
735 NTAPI
738  IN PDEVICE_OBJECT PortDeviceObject,
741  IN PIO_SCSI_CAPABILITIES PortCapabilities,
742  IN PSCSI_INQUIRY_DATA LunInfo,
745  )
746 
747 /*++
748 
749 Routine Description:
750 
751  This routine creates an object for the device and then calls the
752  SCSI port driver for media capacity and sector size.
753 
754 Arguments:
755 
756  DriverObject - Pointer to driver object created by system.
757  PortDeviceObject - to connect to SCSI port driver.
758  DeviceCount - Number of previously installed CDROMs.
759  PortCapabilities - Pointer to structure returned by SCSI port
760  driver describing adapter capabilities (and limitations).
761  LunInfo - Pointer to configuration information for this device.
762 
763 Return Value:
764 
765  NTSTATUS
766 
767 --*/
768 {
769  CHAR ntNameBuffer[64];
771  BOOLEAN changerDevice;
772  SCSI_REQUEST_BLOCK srb;
773  ULONG length;
774  PCDROM_DATA cddata;
775  PCDB cdb;
776  PVOID senseData = NULL;
777  PDEVICE_OBJECT deviceObject = NULL;
778  PDEVICE_EXTENSION deviceExtension = NULL;
779  PUCHAR buffer;
780  ULONG bps;
781  ULONG lastBit;
782  ULONG timeOut;
783  BOOLEAN srbListInitialized = FALSE;
784 
785  //
786  // Claim the device. Note that any errors after this
787  // will goto the generic handler, where the device will
788  // be released.
789  //
790 
791  status = ScsiClassClaimDevice(PortDeviceObject,
792  LunInfo,
793  FALSE,
794  &PortDeviceObject);
795 
796  if (!NT_SUCCESS(status)) {
797  return(status);
798  }
799 
800  //
801  // Create device object for this device.
802  //
803 
804  sprintf(ntNameBuffer,
805  "\\Device\\CdRom%lu",
806  *DeviceCount);
807 
809  ntNameBuffer,
810  NULL,
811  &deviceObject,
813 
814  if (!NT_SUCCESS(status)) {
815  DebugPrint((1,"CreateCdRomDeviceObjects: Can not create device %s\n",
816  ntNameBuffer));
817 
818  goto CreateCdRomDeviceObjectExit;
819  }
820 
821  //
822  // Indicate that IRPs should include MDLs.
823  //
824 
825  deviceObject->Flags |= DO_DIRECT_IO;
826 
827  //
828  // Set up required stack size in device object.
829  //
830 
831  deviceObject->StackSize = PortDeviceObject->StackSize + 2;
832 
833  deviceExtension = deviceObject->DeviceExtension;
834 
835  //
836  // Allocate spinlock for split request completion.
837  //
838 
839  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
840 
841  //
842  // This is the physical device.
843  //
844 
845  deviceExtension->PhysicalDevice = deviceObject;
846 
847  //
848  // Initialize lock count to zero. The lock count is used to
849  // disable the ejection mechanism when media is mounted.
850  //
851 
852  deviceExtension->LockCount = 0;
853 
854  //
855  // Save system cdrom number
856  //
857 
858  deviceExtension->DeviceNumber = *DeviceCount;
859 
860  //
861  // Copy port device object to device extension.
862  //
863 
864  deviceExtension->PortDeviceObject = PortDeviceObject;
865 
866  //
867  // Set the alignment requirements for the device based on the
868  // host adapter requirements
869  //
870 
871  if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
872  deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
873  }
874 
875  //
876  // Save address of port driver capabilities.
877  //
878 
879  deviceExtension->PortCapabilities = PortCapabilities;
880 
881  //
882  // Clear SRB flags.
883  //
884 
885  deviceExtension->SrbFlags = 0;
886  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
887 
888  //
889  // Allocate request sense buffer.
890  //
891 
893 
894  if (senseData == NULL) {
895 
896  //
897  // The buffer cannot be allocated.
898  //
899 
901  goto CreateCdRomDeviceObjectExit;
902  }
903 
904  //
905  // Set the sense data pointer in the device extension.
906  //
907 
908  deviceExtension->SenseData = senseData;
909 
910  //
911  // CDROMs are not partitionable so starting offset is 0.
912  //
913 
914  deviceExtension->StartingOffset.LowPart = 0;
915  deviceExtension->StartingOffset.HighPart = 0;
916 
917  //
918  // Path/TargetId/LUN describes a device location on the SCSI bus.
919  // This information comes from the LunInfo buffer.
920  //
921 
922  deviceExtension->PortNumber = (UCHAR)PortNumber;
923  deviceExtension->PathId = LunInfo->PathId;
924  deviceExtension->TargetId = LunInfo->TargetId;
925  deviceExtension->Lun = LunInfo->Lun;
926 
927  //
928  // Set timeout value in seconds.
929  //
930 
932  if (timeOut) {
933  deviceExtension->TimeOutValue = timeOut;
934  } else {
935  deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
936  }
937 
938  //
939  // Build the lookaside list for srb's for the physical disk. Should only
940  // need a couple.
941  //
942 
943  ScsiClassInitializeSrbLookasideList(deviceExtension,
945 
946  srbListInitialized = TRUE;
947 
948  //
949  // Back pointer to device object.
950  //
951 
952  deviceExtension->DeviceObject = deviceObject;
953 
954  //
955  // Allocate buffer for drive geometry.
956  //
957 
958  deviceExtension->DiskGeometry =
960 
961  if (deviceExtension->DiskGeometry == NULL) {
962 
964  goto CreateCdRomDeviceObjectExit;
965  }
966 
967  //
968  // Set up media change support defaults.
969  //
970 
971  cddata = (PCDROM_DATA)(deviceExtension + 1);
972 
976 
978  cddata->MediaChangeSupported = FALSE;
979  cddata->MediaChange = FALSE;
980 
981  //
982  // Assume that there is initially no media in the device
983  // only notify upper layers if there is something there
984  //
985 
986  deviceExtension->MediaChangeNoMedia = TRUE;
987  cddata->MediaChangeIrp = NULL;
988 #if DBG
989  cddata->MediaChangeIrpTimeInUse = 0;
990  cddata->MediaChangeIrpLost = FALSE;
991 #endif
992 
993  //
994  // Scan for Scsi controllers that require special processing.
995  //
996 
997  ScanForSpecial(deviceObject,
998  (PINQUIRYDATA) LunInfo->InquiryData,
999  PortCapabilities);
1000 
1001  //
1002  // Do READ CAPACITY. This SCSI command
1003  // returns the last sector address on the device
1004  // and the bytes per sector.
1005  // These are used to calculate the drive capacity
1006  // in bytes.
1007  //
1008 
1009  status = ScsiClassReadDriveCapacity(deviceObject);
1010  bps = deviceExtension->DiskGeometry->Geometry.BytesPerSector;
1011 
1012  if (!NT_SUCCESS(status) || !bps) {
1013 
1014  DebugPrint((1,
1015  "CreateCdRomDeviceObjects: Can't read capacity for device %s\n",
1016  ntNameBuffer));
1017 
1018  //
1019  // Set disk geometry to default values (per ISO 9660).
1020  //
1021 
1022  bps = 2048;
1023  deviceExtension->SectorShift = 11;
1024  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);
1025  } else {
1026 
1027  //
1028  // Insure that bytes per sector is a power of 2
1029  // This corrects a problem with the HP 4020i CDR where it
1030  // returns an incorrect number for bytes per sector.
1031  //
1032 
1033  lastBit = (ULONG) -1;
1034  while (bps) {
1035  lastBit++;
1036  bps = bps >> 1;
1037  }
1038 
1039  bps = 1 << lastBit;
1040  }
1041  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
1042  DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps));
1043 
1044  //
1045  // Check to see if this is some sort of changer device
1046  //
1047 
1048  changerDevice = FALSE;
1049 
1050  //
1051  // Search for devices that have special requirements for media
1052  // change support.
1053  //
1054 
1055  if (deviceExtension->Lun > 0) {
1056  changerDevice = TRUE;
1057  }
1058 
1059  if (!changerDevice) {
1060  changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId,
1061  deviceExtension->TargetId);
1062  }
1063 
1064  if (!changerDevice) {
1065  ULONG tmp;
1066  changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp);
1067  }
1068 
1069  if (!changerDevice) {
1070  changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject);
1071  }
1072 
1073  //
1074  // If it is a changer device, increment the timeout to take platter-swapping
1075  // time into account
1076  //
1077 
1078  if(changerDevice) {
1079  deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT;
1080  }
1081 
1082  //
1083  // Create the media change named event. If this succeeds then continue
1084  // initializing the media change support data items.
1085  //
1086 
1087  CdRomCreateNamedEvent(deviceExtension,*DeviceCount);
1088  if (deviceExtension->MediaChangeEvent) {
1089 
1090  //
1091  // If this is not a changer, get an IRP for the timer request
1092  // and initialize the timer.
1093  //
1094 
1095  if (!changerDevice) {
1096 
1097  //
1098  // Not a changer device - continue with media change initialization.
1099  // Determine if the user actually wants media change events.
1100  //
1101 
1103  PIO_STACK_LOCATION irpStack;
1104  PSCSI_REQUEST_BLOCK srb;
1105  PIRP irp;
1106 
1107  //
1108  // User wants it - preallocate IRP and SRB.
1109  //
1110 
1111  irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1),
1112  FALSE);
1113  if (irp) {
1114  PVOID buffer;
1115 
1118 
1119  if (srb && buffer) {
1120  PCDB cdb;
1121 
1122  //
1123  // All resources have been allocated set up the IRP.
1124  //
1125 
1127  irpStack = IoGetCurrentIrpStackLocation(irp);
1128  irpStack->DeviceObject = deviceObject;
1129  irpStack = IoGetNextIrpStackLocation(irp);
1130  cddata->MediaChangeIrp = irp;
1131  irpStack->Parameters.Scsi.Srb = srb;
1132 
1133  //
1134  // Initialize the SRB
1135  //
1136 
1137  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1138 
1139  srb->CdbLength = 6;
1140  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
1141  srb->QueueTag = SP_UNTAGGED;
1144  srb->PathId = deviceExtension->PathId;
1145  srb->TargetId = deviceExtension->TargetId;
1146  srb->Lun = deviceExtension->Lun;
1148 
1149  //
1150  // Initialize and set up the sense information buffer
1151  //
1152 
1154  srb->SenseInfoBuffer = buffer;
1156 
1157  //
1158  // Initialize the CDB
1159  //
1160 
1161  cdb = (PCDB)&srb->Cdb[0];
1162  cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
1163  cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun;
1164 
1165  //
1166  // It is ok to support media change events on this device.
1167  //
1168 
1169  cddata->MediaChangeSupported = TRUE;
1170  cddata->MediaChange = TRUE;
1171 
1172  } else {
1173 
1174  if (srb) {
1175  ExFreePool(srb);
1176  }
1177  if (buffer) {
1178  ExFreePool(buffer);
1179  }
1180  IoFreeIrp(irp);
1181  }
1182  }
1183  } else {
1184  deviceExtension->MediaChangeEvent = NULL;
1185  }
1186  } else {
1187  deviceExtension->MediaChangeEvent = NULL;
1188  }
1189  }
1190 
1191  //
1192  // Assume use of 6-byte mode sense/select for now.
1193  //
1194 
1195  cddata->XAFlags |= XA_USE_6_BYTE;
1196 
1197  //
1198  // Build and issue mode sense with Read error recovery page. This will be used to change
1199  // block size in case of any raw reads (Mode 2, Form 2).
1200  //
1201 
1203 
1204  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1205 
1206  srb.CdbLength = 6;
1207  cdb = (PCDB)srb.Cdb;
1208 
1209  //
1210  // Set timeout value from device extension.
1211  //
1212 
1213  srb.TimeOutValue = deviceExtension->TimeOutValue;
1214 
1215  //
1216  // Build the MODE SENSE CDB. The data returned will be kept in the device extension
1217  // and used to set block size.
1218  //
1219 
1220  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1221  cdb->MODE_SENSE.PageCode = 0x1;
1222  cdb->MODE_SENSE.AllocationLength = (UCHAR)length;
1223 
1225  if (!buffer) {
1227  goto CreateCdRomDeviceObjectExit;
1228  }
1229 
1230  status = ScsiClassSendSrbSynchronous(deviceObject,
1231  &srb,
1232  buffer,
1233  length,
1234  FALSE);
1235  if (!NT_SUCCESS(status)) {
1236 
1237  //
1238  // May be Atapi, try 10-byte.
1239  //
1240 
1242 
1243  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
1244 
1245  //
1246  // Build the MODE SENSE CDB.
1247  //
1248 
1249  srb.CdbLength = 10;
1250  cdb = (PCDB)srb.Cdb;
1251 
1252  //
1253  // Set timeout value from device extension.
1254  //
1255 
1256  srb.TimeOutValue = deviceExtension->TimeOutValue;
1257 
1258  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
1259  cdb->MODE_SENSE10.PageCode = 0x1;
1260 
1261  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8);
1262  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF);
1263 
1264  status = ScsiClassSendSrbSynchronous(deviceObject,
1265  &srb,
1266  buffer,
1267  length,
1268  FALSE);
1269  if (status == STATUS_DATA_OVERRUN) {
1270 
1271  //
1272  // Build and issue the ReadCd command to ensure that this device supports it.
1273  //
1274 
1275  RtlZeroMemory(cdb, 12);
1276 
1277  cdb->READ_CD.OperationCode = SCSIOP_READ_CD;
1278 
1279  status = ScsiClassSendSrbSynchronous(deviceObject,
1280  &srb,
1281  NULL,
1282  0,
1283  FALSE);
1284 
1285  //
1286  // If the command wasn't rejected then support the READ_CD.
1287  //
1288 
1290 
1291  //
1292  // Using Read CD precludes issuing a mode select to
1293  // set the user data size. So, no buffer copy is
1294  // necessary.
1295  //
1296 
1297  cddata->XAFlags &= ~XA_USE_6_BYTE;
1298  cddata->XAFlags |= XA_USE_READ_CD | XA_USE_10_BYTE;
1299  } else {
1300 
1301  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10));
1302  cddata->u1.Header.ModeDataLength = 0;
1303 
1304  cddata->XAFlags &= ~XA_USE_6_BYTE;
1305  cddata->XAFlags |= XA_USE_10_BYTE;
1306  }
1307 
1308  } else if (NT_SUCCESS(status)) {
1309 
1310  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA10));
1311  cddata->u1.Header.ModeDataLength = 0;
1312 
1313  cddata->XAFlags &= ~XA_USE_6_BYTE;
1314  cddata->XAFlags |= XA_USE_10_BYTE;
1315 
1316  } else {
1317  cddata->XAFlags |= XA_NOT_SUPPORTED;
1318  }
1319  } else {
1320  RtlCopyMemory(&cddata->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA));
1321  cddata->u1.Header.ModeDataLength = 0;
1322  }
1323 
1324  ExFreePool(buffer);
1325 
1326  //
1327  // Start the timer now regardless of if Autorun is enabled.
1328  // The timer must run forever since IoStopTimer faults.
1329  //
1330 
1331  IoInitializeTimer(deviceObject, CdRomTickHandler, NULL);
1332  IoStartTimer(deviceObject);
1333 
1334  return(STATUS_SUCCESS);
1335 
1336 CreateCdRomDeviceObjectExit:
1337 
1338  //
1339  // Release the device since an error occured.
1340  //
1341 
1342  ScsiClassClaimDevice(PortDeviceObject,
1343  LunInfo,
1344  TRUE,
1345  NULL);
1346 
1347  if (senseData != NULL) {
1348  ExFreePool(senseData);
1349  }
1350 
1351  if (deviceExtension->DiskGeometry != NULL) {
1352  ExFreePool(deviceExtension->DiskGeometry);
1353  }
1354 
1355  if (deviceObject != NULL) {
1356  if (srbListInitialized) {
1357  ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
1358  }
1359  IoDeleteDevice(deviceObject);
1360  }
1361 
1362 
1363  return status;
1364 
1365 } // end CreateCdRomDeviceObject()
1366 
1367 VOID
1368 NTAPI
1371  IN PIRP Irp
1372  )
1373 {
1374 
1375  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1378  PIO_STACK_LOCATION irpStack;
1379  PIRP irp2 = NULL;
1380  ULONG transferPages;
1381  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1382  ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
1383  PCDROM_DATA cdData;
1384  PSCSI_REQUEST_BLOCK srb = NULL;
1385  PCDB cdb;
1386  PUCHAR senseBuffer = NULL;
1387  PVOID dataBuffer;
1388  NTSTATUS status;
1389  BOOLEAN use6Byte;
1390 
1391  //
1392  // Mark IRP with status pending.
1393  //
1394 
1396 
1397  //
1398  // If the flag is set in the device object, force a verify.
1399  //
1400 
1402  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Volume needs verified\n", Irp));
1403  if (!(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
1404 
1405  if (Irp->Tail.Overlay.Thread) {
1407  }
1408 
1409  Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
1410 
1411  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Calling UpdateCapacity - "
1412  "ioctl event = %lx\n",
1413  Irp,
1414  nextIrpStack->Parameters.Others.Argument1
1415  ));
1416 
1417  //
1418  // our device control dispatch routine stores an event in the next
1419  // stack location to signal when startio has completed. We need to
1420  // pass this in so that the update capacity completion routine can
1421  // set it rather than completing the Irp.
1422  //
1423 
1424  status = CdRomUpdateCapacity(deviceExtension,
1425  Irp,
1426  nextIrpStack->Parameters.Others.Argument1
1427  );
1428 
1429  DebugPrint((2, "ScsiCdRomStartIo: [%lx] UpdateCapacity returned %lx\n", Irp, status));
1431  return;
1432  }
1433  }
1434 
1435  cdData = (PCDROM_DATA)(deviceExtension + 1);
1436  use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
1437 
1438  if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
1439 
1440  //
1441  // Add partition byte offset to make starting byte relative to
1442  // beginning of disk. In addition, add in skew for DM Driver, if any.
1443  //
1444 
1445  currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart);
1446 
1447  //
1448  // Calculate number of pages in this transfer.
1449  //
1450 
1451  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1452  currentIrpStack->Parameters.Read.Length);
1453 
1454  //
1455  // Check if request length is greater than the maximum number of
1456  // bytes that the hardware can transfer.
1457  //
1458 
1459  if (cdData->RawAccess) {
1460 
1461  ASSERT(!(cdData->XAFlags & XA_USE_READ_CD));
1462 
1463  //
1464  // Fire off a mode select to switch back to cooked sectors.
1465  //
1466 
1467  irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
1468  FALSE);
1469 
1470  if (!irp2) {
1471  Irp->IoStatus.Information = 0;
1472  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1475  return;
1476  }
1477 
1479  if (!srb) {
1480  Irp->IoStatus.Information = 0;
1481  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1483  IoFreeIrp(irp2);
1485  return;
1486  }
1487 
1488  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1489 
1490  cdb = (PCDB)srb->Cdb;
1491 
1492  //
1493  // Allocate sense buffer.
1494  //
1495 
1497 
1498  if (!senseBuffer) {
1499  Irp->IoStatus.Information = 0;
1500  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1502  ExFreePool(srb);
1503  IoFreeIrp(irp2);
1505  return;
1506  }
1507 
1508  //
1509  // Set up the irp.
1510  //
1511 
1513  irp2->IoStatus.Status = STATUS_SUCCESS;
1514  irp2->IoStatus.Information = 0;
1515  irp2->Flags = 0;
1516  irp2->UserBuffer = NULL;
1517 
1518  //
1519  // Save the device object and irp in a private stack location.
1520  //
1521 
1522  irpStack = IoGetCurrentIrpStackLocation(irp2);
1523  irpStack->DeviceObject = deviceExtension->DeviceObject;
1524  irpStack->Parameters.Others.Argument2 = (PVOID) Irp;
1525 
1526  //
1527  // The retry count will be in the real Irp, as the retry logic will
1528  // recreate our private irp.
1529  //
1530 
1531  if (!(nextIrpStack->Parameters.Others.Argument1)) {
1532 
1533  //
1534  // Only jam this in if it doesn't exist. The completion routines can
1535  // call StartIo directly in the case of retries and resetting it will
1536  // cause infinite loops.
1537  //
1538 
1539  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
1540  }
1541 
1542  //
1543  // Construct the IRP stack for the lower level driver.
1544  //
1545 
1546  irpStack = IoGetNextIrpStackLocation(irp2);
1548  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1549  irpStack->Parameters.Scsi.Srb = srb;
1550 
1552  srb->PathId = deviceExtension->PathId;
1553  srb->TargetId = deviceExtension->TargetId;
1554  srb->Lun = deviceExtension->Lun;
1556  srb->Cdb[1] |= deviceExtension->Lun << 5;
1557  srb->SrbStatus = srb->ScsiStatus = 0;
1558  srb->NextSrb = 0;
1559  srb->OriginalRequest = irp2;
1561  srb->SenseInfoBuffer = senseBuffer;
1562 
1563  transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
1564  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
1565  if (!dataBuffer) {
1566  Irp->IoStatus.Information = 0;
1567  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1569  ExFreePool(senseBuffer);
1570  ExFreePool(srb);
1571  IoFreeIrp(irp2);
1573  return;
1574 
1575  }
1576 
1577  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
1578  transferByteCount,
1579  FALSE,
1580  FALSE,
1581  (PIRP) NULL);
1582 
1583  if (!irp2->MdlAddress) {
1584  Irp->IoStatus.Information = 0;
1585  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1587  ExFreePool(senseBuffer);
1588  ExFreePool(srb);
1589  ExFreePool(dataBuffer);
1590  IoFreeIrp(irp2);
1592  return;
1593  }
1594 
1595  //
1596  // Prepare the MDL
1597  //
1598 
1599  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
1600 
1601  srb->DataBuffer = dataBuffer;
1602 
1603  //
1604  // Set the new block size in the descriptor.
1605  //
1606 
1607  cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(COOKED_SECTOR_SIZE >> 16) & 0xFF;
1608  cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(COOKED_SECTOR_SIZE >> 8) & 0xFF;
1609  cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(COOKED_SECTOR_SIZE & 0xFF);
1610 
1611  //
1612  // Move error page into dataBuffer.
1613  //
1614 
1615  RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);
1616 
1617  //
1618  // Build and send a mode select to switch into raw mode.
1619  //
1620 
1621  srb->SrbFlags = deviceExtension->SrbFlags;
1623  srb->DataTransferLength = transferByteCount;
1624  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
1625 
1626  if (use6Byte) {
1627  srb->CdbLength = 6;
1628  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1629  cdb->MODE_SELECT.PFBit = 1;
1630  cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
1631  } else {
1632 
1633  srb->CdbLength = 10;
1634  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
1635  cdb->MODE_SELECT10.PFBit = 1;
1636  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
1637  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
1638  }
1639 
1640  //
1641  // Update completion routine.
1642  //
1643 
1646  srb,
1647  TRUE,
1648  TRUE,
1649  TRUE);
1650 
1651  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
1652  return;
1653  }
1654 
1655  if ((currentIrpStack->Parameters.Read.Length > maximumTransferLength) ||
1656  (transferPages >
1657  deviceExtension->PortCapabilities->MaximumPhysicalPages)) {
1658 
1659  //
1660  // Request needs to be split. Completion of each portion of the
1661  // request will fire off the next portion. The final request will
1662  // signal Io to send a new request.
1663  //
1664 
1665  transferPages =
1666  deviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
1667 
1668  if(maximumTransferLength > transferPages << PAGE_SHIFT) {
1669  maximumTransferLength = transferPages << PAGE_SHIFT;
1670  }
1671 
1672  //
1673  // Check that the maximum transfer size is not zero
1674  //
1675 
1676  if(maximumTransferLength == 0) {
1677  maximumTransferLength = PAGE_SIZE;
1678  }
1679 
1680  ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength);
1681  return;
1682 
1683  } else {
1684 
1685  //
1686  // Build SRB and CDB for this IRP.
1687  //
1688 
1690 
1691  }
1692 
1693 
1694  } else if (currentIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
1695 
1696  //
1697  // Allocate an irp, srb and associated structures.
1698  //
1699 
1700  irp2 = IoAllocateIrp((CCHAR)(deviceExtension->DeviceObject->StackSize+1),
1701  FALSE);
1702 
1703  if (!irp2) {
1704  Irp->IoStatus.Information = 0;
1705  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1708  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1709  return;
1710  }
1711 
1713  if (!srb) {
1714  Irp->IoStatus.Information = 0;
1715  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1717  IoFreeIrp(irp2);
1719  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1720  return;
1721  }
1722 
1723  RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
1724 
1725  cdb = (PCDB)srb->Cdb;
1726 
1727  //
1728  // Allocate sense buffer.
1729  //
1730 
1732 
1733  if (!senseBuffer) {
1734  Irp->IoStatus.Information = 0;
1735  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1737  ExFreePool(srb);
1738  IoFreeIrp(irp2);
1740  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
1741  return;
1742  }
1743 
1744  //
1745  // Set up the irp.
1746  //
1747 
1749  irp2->IoStatus.Status = STATUS_SUCCESS;
1750  irp2->IoStatus.Information = 0;
1751  irp2->Flags = 0;
1752  irp2->UserBuffer = NULL;
1753 
1754  //
1755  // Save the device object and irp in a private stack location.
1756  //
1757 
1758  irpStack = IoGetCurrentIrpStackLocation(irp2);
1759  irpStack->DeviceObject = deviceExtension->DeviceObject;
1760  irpStack->Parameters.Others.Argument2 = (PVOID) Irp;
1761 
1762  //
1763  // The retry count will be in the real Irp, as the retry logic will
1764  // recreate our private irp.
1765  //
1766 
1767  if (!(nextIrpStack->Parameters.Others.Argument1)) {
1768 
1769  //
1770  // Only jam this in if it doesn't exist. The completion routines can
1771  // call StartIo directly in the case of retries and resetting it will
1772  // cause infinite loops.
1773  //
1774 
1775  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
1776  }
1777 
1778  //
1779  // Construct the IRP stack for the lower level driver.
1780  //
1781 
1782  irpStack = IoGetNextIrpStackLocation(irp2);
1784  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
1785  irpStack->Parameters.Scsi.Srb = srb;
1786 
1789  srb,
1790  TRUE,
1791  TRUE,
1792  TRUE);
1793  //
1794  // Setup those fields that are generic to all requests.
1795  //
1796 
1798  srb->PathId = deviceExtension->PathId;
1799  srb->TargetId = deviceExtension->TargetId;
1800  srb->Lun = deviceExtension->Lun;
1802  srb->Cdb[1] |= deviceExtension->Lun << 5;
1803  srb->SrbStatus = srb->ScsiStatus = 0;
1804  srb->NextSrb = 0;
1805  srb->OriginalRequest = irp2;
1807  srb->SenseInfoBuffer = senseBuffer;
1808 
1809  switch (currentIrpStack->Parameters.DeviceIoControl.IoControlCode) {
1810 
1811  case IOCTL_CDROM_RAW_READ: {
1812 
1813  //
1814  // Determine whether the drive is currently in raw or cooked mode,
1815  // and which command to use to read the data.
1816  //
1817 
1818  if (!(cdData->XAFlags & XA_USE_READ_CD)) {
1819 
1820  PRAW_READ_INFO rawReadInfo =
1821  (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
1822  ULONG maximumTransferLength;
1823  ULONG transferPages;
1824 
1825  if (cdData->RawAccess) {
1826 
1827  ULONG startingSector;
1828 
1829  //
1830  // Free the recently allocated irp, as we don't need it.
1831  //
1832 
1833  IoFreeIrp(irp2);
1834 
1835  cdb = (PCDB)srb->Cdb;
1836  RtlZeroMemory(cdb, 12);
1837 
1838  //
1839  // Calculate starting offset.
1840  //
1841 
1842  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
1843  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
1844  maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
1845  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
1846  transferByteCount);
1847 
1848  //
1849  // Determine if request is within limits imposed by miniport.
1850  //
1851 
1852  if (transferByteCount > maximumTransferLength ||
1853  transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
1854 
1855  //
1856  // The claim is that this won't happen, and is backed up by
1857  // ActiveMovie usage, which does unbuffered XA reads of 0x18000, yet
1858  // we get only 4 sector requests.
1859  //
1860 
1861 
1862  Irp->IoStatus.Information = 0;
1863  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1865  ExFreePool(senseBuffer);
1866  ExFreePool(srb);
1868  return;
1869 
1870  }
1871 
1872  srb->OriginalRequest = Irp;
1873  srb->SrbFlags = deviceExtension->SrbFlags;
1875  srb->DataTransferLength = transferByteCount;
1876  srb->TimeOutValue = deviceExtension->TimeOutValue;
1877  srb->CdbLength = 10;
1878  srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1879 
1880  if (rawReadInfo->TrackMode == CDDA) {
1881  if (cdData->XAFlags & PLEXTOR_CDDA) {
1882 
1883  srb->CdbLength = 12;
1884 
1885  cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
1886  cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
1887  cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
1888  cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
1889  cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
1890 
1891  cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
1892  cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
1893  cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
1894  cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;
1895 
1896  cdb->PLXTR_READ_CDDA.SubCode = 0;
1897  cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;
1898 
1899  } else if (cdData->XAFlags & NEC_CDDA) {
1900 
1901  cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
1902  cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
1903  cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
1904  cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
1905 
1906  cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
1907  cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);
1908 
1909  cdb->NEC_READ_CDDA.OperationCode = 0xD4;
1910  }
1911  } else {
1912 
1913  cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
1914 
1915  cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8);
1916  cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
1917 
1918  cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
1919  cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
1920  cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
1921  cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
1922 
1923  cdb->CDB10.OperationCode = SCSIOP_READ;
1924  }
1925 
1926  srb->SrbStatus = srb->ScsiStatus = 0;
1927 
1928  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
1929  nextIrpStack->Parameters.Scsi.Srb = srb;
1930 
1931  if (!(nextIrpStack->Parameters.Others.Argument1)) {
1932 
1933  //
1934  // Only jam this in if it doesn't exist. The completion routines can
1935  // call StartIo directly in the case of retries and resetting it will
1936  // cause infinite loops.
1937  //
1938 
1939  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
1940  }
1941 
1942  //
1943  // Set up IoCompletion routine address.
1944  //
1945 
1948  srb,
1949  TRUE,
1950  TRUE,
1951  TRUE);
1952 
1953  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
1954  return;
1955 
1956  } else {
1957 
1958  transferByteCount = (use6Byte) ? sizeof(ERROR_RECOVERY_DATA) : sizeof(ERROR_RECOVERY_DATA10);
1959  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount );
1960  if (!dataBuffer) {
1961  Irp->IoStatus.Information = 0;
1962  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1964  ExFreePool(senseBuffer);
1965  ExFreePool(srb);
1966  IoFreeIrp(irp2);
1968  return;
1969 
1970  }
1971 
1972  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
1973  transferByteCount,
1974  FALSE,
1975  FALSE,
1976  (PIRP) NULL);
1977 
1978  if (!irp2->MdlAddress) {
1979  Irp->IoStatus.Information = 0;
1980  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1982  ExFreePool(senseBuffer);
1983  ExFreePool(srb);
1984  ExFreePool(dataBuffer);
1985  IoFreeIrp(irp2);
1987  return;
1988  }
1989 
1990  //
1991  // Prepare the MDL
1992  //
1993 
1994  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
1995 
1996  srb->DataBuffer = dataBuffer;
1997 
1998  //
1999  // Set the new block size in the descriptor.
2000  //
2001 
2002  cdData->u1.BlockDescriptor.BlockLength[0] = (UCHAR)(RAW_SECTOR_SIZE >> 16) & 0xFF;
2003  cdData->u1.BlockDescriptor.BlockLength[1] = (UCHAR)(RAW_SECTOR_SIZE >> 8) & 0xFF;
2004  cdData->u1.BlockDescriptor.BlockLength[2] = (UCHAR)(RAW_SECTOR_SIZE & 0xFF);
2005 
2006 
2007  //
2008  // TODO: Set density code, based on operation
2009  //
2010 
2011  cdData->u1.BlockDescriptor.DensityCode = 0;
2012 
2013 
2014  //
2015  // Move error page into dataBuffer.
2016  //
2017 
2018  RtlCopyMemory(srb->DataBuffer, &cdData->u1.Header, transferByteCount);
2019 
2020 
2021  //
2022  // Build and send a mode select to switch into raw mode.
2023  //
2024 
2025  srb->SrbFlags = deviceExtension->SrbFlags;
2027  srb->DataTransferLength = transferByteCount;
2028  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
2029 
2030  if (use6Byte) {
2031  srb->CdbLength = 6;
2032  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
2033  cdb->MODE_SELECT.PFBit = 1;
2034  cdb->MODE_SELECT.ParameterListLength = (UCHAR)transferByteCount;
2035  } else {
2036 
2037  srb->CdbLength = 10;
2038  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
2039  cdb->MODE_SELECT10.PFBit = 1;
2040  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR)(transferByteCount >> 8);
2041  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR)(transferByteCount & 0xFF);
2042  }
2043 
2044  //
2045  // Update completion routine.
2046  //
2047 
2050  srb,
2051  TRUE,
2052  TRUE,
2053  TRUE);
2054 
2055  }
2056 
2057  } else {
2058 
2059  PRAW_READ_INFO rawReadInfo =
2060  (PRAW_READ_INFO)currentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
2061  ULONG startingSector;
2062 
2063  //
2064  // Free the recently allocated irp, as we don't need it.
2065  //
2066 
2067  IoFreeIrp(irp2);
2068 
2069  cdb = (PCDB)srb->Cdb;
2070  RtlZeroMemory(cdb, 12);
2071 
2072 
2073  //
2074  // Calculate starting offset.
2075  //
2076 
2077  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
2078  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
2079 
2080 
2081  srb->OriginalRequest = Irp;
2082  srb->SrbFlags = deviceExtension->SrbFlags;
2084  srb->DataTransferLength = transferByteCount;
2085  srb->TimeOutValue = deviceExtension->TimeOutValue;
2086  srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
2087  srb->CdbLength = 12;
2088  srb->SrbStatus = srb->ScsiStatus = 0;
2089 
2090  //
2091  // Fill in CDB fields.
2092  //
2093 
2094  cdb = (PCDB)srb->Cdb;
2095 
2096 
2097  cdb->READ_CD.TransferBlocks[2] = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
2098  cdb->READ_CD.TransferBlocks[1] = (UCHAR) (rawReadInfo->SectorCount >> 8 );
2099  cdb->READ_CD.TransferBlocks[0] = (UCHAR) (rawReadInfo->SectorCount >> 16);
2100 
2101 
2102  cdb->READ_CD.StartingLBA[3] = (UCHAR) (startingSector & 0xFF);
2103  cdb->READ_CD.StartingLBA[2] = (UCHAR) ((startingSector >> 8));
2104  cdb->READ_CD.StartingLBA[1] = (UCHAR) ((startingSector >> 16));
2105  cdb->READ_CD.StartingLBA[0] = (UCHAR) ((startingSector >> 24));
2106 
2107  //
2108  // Setup cdb depending upon the sector type we want.
2109  //
2110 
2111  switch (rawReadInfo->TrackMode) {
2112  case CDDA:
2113 
2114  cdb->READ_CD.ExpectedSectorType = CD_DA_SECTOR;
2115  cdb->READ_CD.IncludeUserData = 1;
2116  cdb->READ_CD.HeaderCode = 3;
2117  cdb->READ_CD.IncludeSyncData = 1;
2118  break;
2119 
2120  case YellowMode2:
2121 
2122  cdb->READ_CD.ExpectedSectorType = YELLOW_MODE2_SECTOR;
2123  cdb->READ_CD.IncludeUserData = 1;
2124  cdb->READ_CD.HeaderCode = 1;
2125  cdb->READ_CD.IncludeSyncData = 1;
2126  break;
2127 
2128  case XAForm2:
2129 
2130  cdb->READ_CD.ExpectedSectorType = FORM2_MODE2_SECTOR;
2131  cdb->READ_CD.IncludeUserData = 1;
2132  cdb->READ_CD.HeaderCode = 3;
2133  cdb->READ_CD.IncludeSyncData = 1;
2134  break;
2135 
2136  default:
2137  Irp->IoStatus.Information = 0;
2138  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2140  ExFreePool(senseBuffer);
2141  ExFreePool(srb);
2143  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2144  return;
2145  }
2146 
2147  cdb->READ_CD.OperationCode = SCSIOP_READ_CD;
2148 
2149  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2150  nextIrpStack->Parameters.Scsi.Srb = srb;
2151 
2152  if (!(nextIrpStack->Parameters.Others.Argument1)) {
2153 
2154  //
2155  // Only jam this in if it doesn't exist. The completion routines can
2156  // call StartIo directly in the case of retries and resetting it will
2157  // cause infinite loops.
2158  //
2159 
2160  nextIrpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
2161  }
2162 
2163  //
2164  // Set up IoCompletion routine address.
2165  //
2166 
2169  srb,
2170  TRUE,
2171  TRUE,
2172  TRUE);
2173 
2174  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2175  return;
2176 
2177  }
2178 
2179  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2180  return;
2181  }
2182 
2188 
2189  //
2190  // Issue ReadCapacity to update device extension
2191  // with information for current media.
2192  //
2193 
2194  DebugPrint((3,
2195  "CdRomStartIo: Get drive capacity\n"));
2196 
2197  //
2198  // setup remaining srb and cdb parameters.
2199  //
2200 
2201  srb->SrbFlags = deviceExtension->SrbFlags;
2203  srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
2204  srb->CdbLength = 10;
2205  srb->TimeOutValue = deviceExtension->TimeOutValue;
2206 
2208  if (!dataBuffer) {
2209  Irp->IoStatus.Information = 0;
2210  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2212  ExFreePool(senseBuffer);
2213  ExFreePool(srb);
2214  IoFreeIrp(irp2);
2216  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2217  return;
2218 
2219  }
2220 
2221  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2222  sizeof(READ_CAPACITY_DATA),
2223  FALSE,
2224  FALSE,
2225  (PIRP) NULL);
2226 
2227  if (!irp2->MdlAddress) {
2228  Irp->IoStatus.Information = 0;
2229  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2231  ExFreePool(senseBuffer);
2232  ExFreePool(srb);
2233  ExFreePool(dataBuffer);
2234  IoFreeIrp(irp2);
2236  DebugPrint((2, "ScsiCdRomStartIo: [%lx] bailing with status %lx at line %s\n", Irp, Irp->IoStatus.Status, __LINE__));
2237  return;
2238  }
2239 
2240  //
2241  // Prepare the MDL
2242  //
2243 
2244  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2245 
2246  srb->DataBuffer = dataBuffer;
2247  cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
2248 
2249  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2250  return;
2251  }
2252 
2253  case IOCTL_CDROM_CHECK_VERIFY: {
2254 
2255  //
2256  // Since a test unit ready is about to be performed, reset the timer
2257  // value to decrease the opportunities for it to race with this code.
2258  //
2259 
2261 
2262  //
2263  // Set up the SRB/CDB
2264  //
2265 
2266  srb->CdbLength = 6;
2267  cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
2268  srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
2269  srb->SrbFlags = deviceExtension->SrbFlags;
2271 
2272  DebugPrint((2, "ScsiCdRomStartIo: [%lx] Sending CHECK_VERIFY irp %lx\n", Irp, irp2));
2273  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2274  return;
2275  }
2276 
2278 
2279  //
2280  // Set format to return first and last session numbers.
2281  //
2282 
2283  cdb->READ_TOC.Format = GET_LAST_SESSION;
2284 
2285  //
2286  // Fall through to READ TOC code.
2287  //
2288 
2289  case IOCTL_CDROM_READ_TOC: {
2290 
2291 
2292  if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) {
2293 
2294  //
2295  // Use MSF addressing if not request for session information.
2296  //
2297 
2298  cdb->READ_TOC.Msf = CDB_USE_MSF;
2299  }
2300 
2301  //
2302  // Set size of TOC structure.
2303  //
2304 
2305  transferByteCount =
2306  currentIrpStack->Parameters.Read.Length >
2307  sizeof(CDROM_TOC) ? sizeof(CDROM_TOC):
2308  currentIrpStack->Parameters.Read.Length;
2309 
2310  cdb->READ_TOC.AllocationLength[0] = (UCHAR) (transferByteCount >> 8);
2311  cdb->READ_TOC.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF);
2312 
2313  cdb->READ_TOC.Control = 0;
2314 
2315  //
2316  // Start at beginning of disc.
2317  //
2318 
2319  cdb->READ_TOC.StartingTrack = 0;
2320 
2321  //
2322  // setup remaining srb and cdb parameters.
2323  //
2324 
2325  srb->SrbFlags = deviceExtension->SrbFlags;
2327  srb->DataTransferLength = transferByteCount;
2328  srb->CdbLength = 10;
2329  srb->TimeOutValue = deviceExtension->TimeOutValue;
2330 
2331  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, transferByteCount);
2332  if (!dataBuffer) {
2333  Irp->IoStatus.Information = 0;
2334  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2336  ExFreePool(senseBuffer);
2337  ExFreePool(srb);
2338  IoFreeIrp(irp2);
2340  return;
2341 
2342  }
2343 
2344  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2345  transferByteCount,
2346  FALSE,
2347  FALSE,
2348  (PIRP) NULL);
2349 
2350  if (!irp2->MdlAddress) {
2351  Irp->IoStatus.Information = 0;
2352  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2354  ExFreePool(senseBuffer);
2355  ExFreePool(srb);
2356  ExFreePool(dataBuffer);
2357  IoFreeIrp(irp2);
2359  return;
2360  }
2361 
2362  //
2363  // Prepare the MDL
2364  //
2365 
2366  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2367 
2368  srb->DataBuffer = dataBuffer;
2369  cdb->READ_TOC.OperationCode = SCSIOP_READ_TOC;
2370 
2371  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2372  return;
2373 
2374  }
2375 
2377 
2378  PCDROM_PLAY_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
2379 
2380  //
2381  // Set up the SRB/CDB
2382  //
2383 
2384  srb->CdbLength = 10;
2385  cdb->PLAY_AUDIO_MSF.OperationCode = SCSIOP_PLAY_AUDIO_MSF;
2386 
2387  cdb->PLAY_AUDIO_MSF.StartingM = inputBuffer->StartingM;
2388  cdb->PLAY_AUDIO_MSF.StartingS = inputBuffer->StartingS;
2389  cdb->PLAY_AUDIO_MSF.StartingF = inputBuffer->StartingF;
2390 
2391  cdb->PLAY_AUDIO_MSF.EndingM = inputBuffer->EndingM;
2392  cdb->PLAY_AUDIO_MSF.EndingS = inputBuffer->EndingS;
2393  cdb->PLAY_AUDIO_MSF.EndingF = inputBuffer->EndingF;
2394 
2395  srb->TimeOutValue = deviceExtension->TimeOutValue;
2396  srb->SrbFlags = deviceExtension->SrbFlags;
2398 
2399  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2400  return;
2401 
2402  }
2403 
2405 
2406  PCDROM_SUB_Q_DATA_FORMAT inputBuffer =
2407  Irp->AssociatedIrp.SystemBuffer;
2408 
2409  //
2410  // Allocate buffer for subq channel information.
2411  //
2412 
2414  sizeof(SUB_Q_CHANNEL_DATA));
2415 
2416  if (!dataBuffer) {
2417  Irp->IoStatus.Information = 0;
2418  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2420  ExFreePool(senseBuffer);
2421  ExFreePool(srb);
2422  IoFreeIrp(irp2);
2424  return;
2425 
2426  }
2427 
2428  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2429  transferByteCount,
2430  FALSE,
2431  FALSE,
2432  (PIRP) NULL);
2433 
2434  if (!irp2->MdlAddress) {
2435  Irp->IoStatus.Information = 0;
2436  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2438  ExFreePool(senseBuffer);
2439  ExFreePool(srb);
2440  ExFreePool(dataBuffer);
2441  IoFreeIrp(irp2);
2443  return;
2444  }
2445 
2446  //
2447  // Prepare the MDL
2448  //
2449 
2450  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2451 
2452  srb->DataBuffer = dataBuffer;
2453 
2454  //
2455  // Always logical unit 0, but only use MSF addressing
2456  // for IOCTL_CDROM_CURRENT_POSITION
2457  //
2458 
2459  if (inputBuffer->Format==IOCTL_CDROM_CURRENT_POSITION)
2460  cdb->SUBCHANNEL.Msf = CDB_USE_MSF;
2461 
2462  //
2463  // Return subchannel data
2464  //
2465 
2466  cdb->SUBCHANNEL.SubQ = CDB_SUBCHANNEL_BLOCK;
2467 
2468  //
2469  // Specify format of information to return
2470  //
2471 
2472  cdb->SUBCHANNEL.Format = inputBuffer->Format;
2473 
2474  //
2475  // Specify which track to access (only used by Track ISRC reads)
2476  //
2477 
2478  if (inputBuffer->Format==IOCTL_CDROM_TRACK_ISRC) {
2479  cdb->SUBCHANNEL.TrackNumber = inputBuffer->Track;
2480  }
2481 
2482  //
2483  // Set size of channel data -- however, this is dependent on
2484  // what information we are requesting (which Format)
2485  //
2486 
2487  switch( inputBuffer->Format ) {
2488 
2490  transferByteCount = sizeof(SUB_Q_CURRENT_POSITION);
2491  break;
2492 
2494  transferByteCount = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
2495  break;
2496 
2498  transferByteCount = sizeof(SUB_Q_TRACK_ISRC);
2499  break;
2500  }
2501 
2502  cdb->SUBCHANNEL.AllocationLength[0] = (UCHAR) (transferByteCount >> 8);
2503  cdb->SUBCHANNEL.AllocationLength[1] = (UCHAR) (transferByteCount & 0xFF);
2504  cdb->SUBCHANNEL.OperationCode = SCSIOP_READ_SUB_CHANNEL;
2505  srb->SrbFlags = deviceExtension->SrbFlags;
2507  srb->DataTransferLength = transferByteCount;
2508  srb->CdbLength = 10;
2509  srb->TimeOutValue = deviceExtension->TimeOutValue;
2510 
2511  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2512  return;
2513 
2514  }
2515 
2516  case IOCTL_CDROM_PAUSE_AUDIO: {
2517 
2518  cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
2519  cdb->PAUSE_RESUME.Action = CDB_AUDIO_PAUSE;
2520 
2521  srb->CdbLength = 10;
2522  srb->TimeOutValue = deviceExtension->TimeOutValue;
2523  srb->SrbFlags = deviceExtension->SrbFlags;
2525 
2526  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2527  return;
2528  }
2529 
2530  case IOCTL_CDROM_RESUME_AUDIO: {
2531 
2532  cdb->PAUSE_RESUME.OperationCode = SCSIOP_PAUSE_RESUME;
2533  cdb->PAUSE_RESUME.Action = CDB_AUDIO_RESUME;
2534 
2535  srb->CdbLength = 10;
2536  srb->TimeOutValue = deviceExtension->TimeOutValue;
2537  srb->SrbFlags = deviceExtension->SrbFlags;
2539 
2540  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2541  return;
2542  }
2543 
2545 
2546  PCDROM_SEEK_AUDIO_MSF inputBuffer = Irp->AssociatedIrp.SystemBuffer;
2547  ULONG logicalBlockAddress;
2548 
2549  logicalBlockAddress = MSF_TO_LBA(inputBuffer->M, inputBuffer->S, inputBuffer->F);
2550 
2551  cdb->SEEK.OperationCode = SCSIOP_SEEK;
2552  cdb->SEEK.LogicalBlockAddress[0] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
2553  cdb->SEEK.LogicalBlockAddress[1] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
2554  cdb->SEEK.LogicalBlockAddress[2] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
2555  cdb->SEEK.LogicalBlockAddress[3] = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
2556 
2557  srb->CdbLength = 10;
2558  srb->TimeOutValue = deviceExtension->TimeOutValue;
2559  srb->SrbFlags = deviceExtension->SrbFlags;
2561 
2562  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2563  return;
2564 
2565  }
2566 
2567  case IOCTL_CDROM_STOP_AUDIO: {
2568 
2569  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
2570  cdb->START_STOP.Immediate = 1;
2571  cdb->START_STOP.Start = 0;
2572  cdb->START_STOP.LoadEject = 0;
2573 
2574  srb->CdbLength = 6;
2575  srb->TimeOutValue = deviceExtension->TimeOutValue;
2576 
2577  srb->SrbFlags = deviceExtension->SrbFlags;
2579 
2580  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2581  return;
2582  }
2583 
2584  case IOCTL_CDROM_GET_CONTROL: {
2585  //
2586  // Allocate buffer for volume control information.
2587  //
2588 
2590  MODE_DATA_SIZE);
2591 
2592  if (!dataBuffer) {
2593  Irp->IoStatus.Information = 0;
2594  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2596  ExFreePool(senseBuffer);
2597  ExFreePool(srb);
2598  IoFreeIrp(irp2);
2600  return;
2601 
2602  }
2603 
2604  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2606  FALSE,
2607  FALSE,
2608  (PIRP) NULL);
2609 
2610  if (!irp2->MdlAddress) {
2611  Irp->IoStatus.Information = 0;
2612  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2614  ExFreePool(senseBuffer);
2615  ExFreePool(srb);
2616  ExFreePool(dataBuffer);
2617  IoFreeIrp(irp2);
2619  return;
2620  }
2621 
2622  //
2623  // Prepare the MDL
2624  //
2625 
2626  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2627  srb->DataBuffer = dataBuffer;
2628 
2629  RtlZeroMemory(dataBuffer, MODE_DATA_SIZE);
2630 
2631  //
2632  // Setup for either 6 or 10 byte CDBs.
2633  //
2634 
2635  if (use6Byte) {
2636 
2637  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2638  cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2639  cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2640 
2641  //
2642  // Disable block descriptors.
2643  //
2644 
2645  cdb->MODE_SENSE.Dbd = TRUE;
2646 
2647  srb->CdbLength = 6;
2648  } else {
2649 
2650  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
2651  cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2652  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8);
2653  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF);
2654 
2655  //
2656  // Disable block descriptors.
2657  //
2658 
2659  cdb->MODE_SENSE10.Dbd = TRUE;
2660 
2661  srb->CdbLength = 10;
2662  }
2663 
2664  srb->TimeOutValue = deviceExtension->TimeOutValue;
2666  srb->SrbFlags = deviceExtension->SrbFlags;
2668 
2669  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2670  return;
2671 
2672  }
2673 
2675  case IOCTL_CDROM_SET_VOLUME: {
2676 
2678  MODE_DATA_SIZE);
2679 
2680  if (!dataBuffer) {
2681  Irp->IoStatus.Information = 0;
2682  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2684  ExFreePool(senseBuffer);
2685  ExFreePool(srb);
2686  IoFreeIrp(irp2);
2688  return;
2689  }
2690 
2691  irp2->MdlAddress = IoAllocateMdl(dataBuffer,
2693  FALSE,
2694  FALSE,
2695  (PIRP) NULL);
2696 
2697  if (!irp2->MdlAddress) {
2698  Irp->IoStatus.Information = 0;
2699  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2701  ExFreePool(senseBuffer);
2702  ExFreePool(srb);
2703  ExFreePool(dataBuffer);
2704  IoFreeIrp(irp2);
2706  return;
2707  }
2708 
2709  //
2710  // Prepare the MDL
2711  //
2712 
2713  MmBuildMdlForNonPagedPool(irp2->MdlAddress);
2714  srb->DataBuffer = dataBuffer;
2715 
2716  RtlZeroMemory(dataBuffer, MODE_DATA_SIZE);
2717 
2718 
2719  if (use6Byte) {
2720  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
2721  cdb->MODE_SENSE.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2722  cdb->MODE_SENSE.AllocationLength = MODE_DATA_SIZE;
2723 
2724  srb->CdbLength = 6;
2725 
2726  } else {
2727 
2728  cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
2729  cdb->MODE_SENSE10.PageCode = CDROM_AUDIO_CONTROL_PAGE;
2730  cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(MODE_DATA_SIZE >> 8);
2731  cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(MODE_DATA_SIZE & 0xFF);
2732 
2733  srb->CdbLength = 10;
2734  }
2735 
2736  srb->TimeOutValue = deviceExtension->TimeOutValue;
2738  srb->SrbFlags = deviceExtension->SrbFlags;
2740 
2741  if (currentIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_SET_VOLUME) {
2742 
2743  //
2744  // Setup a different completion routine as the mode sense data is needed in order
2745  // to send the mode select.
2746  //
2747 
2750  srb,
2751  TRUE,
2752  TRUE,
2753  TRUE);
2754 
2755  }
2756 
2757  IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2758  return;
2759 
2760  }
2761 
2762  default:
2763 
2764  //
2765  // Just complete the request - CdRomClassIoctlCompletion will take
2766  // care of it for us
2767  //
2768 
2770  ExFreePool(senseBuffer);
2771  ExFreePool(srb);
2772  IoFreeIrp(irp2);
2773  return;
2774 
2775  } // end switch()
2776  }
2777 
2778  //
2779  // If a read or an unhandled IRP_MJ_XX, end up here. The unhandled IRP_MJ's
2780  // are expected and composed of AutoRun Irps, at present.
2781  //
2782 
2783  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2784  return;
2785 }
2786 
2787 
2788 NTSTATUS
2789 NTAPI
2792  IN PIRP Irp
2793  )
2794 
2795 /*++
2796 
2797 Routine Description:
2798 
2799  This is the entry called by the I/O system for read requests.
2800  It builds the SRB and sends it to the port driver.
2801 
2802 Arguments:
2803 
2804  DeviceObject - the system object for the device.
2805  Irp - IRP involved.
2806 
2807 Return Value:
2808 
2809  NT Status
2810 
2811 --*/
2812 
2813 {
2814  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2816  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
2817  LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
2818 
2819  //
2820  // If the cd is playing music then reject this request.
2821  //
2822 
2823  if (PLAY_ACTIVE(deviceExtension)) {
2824  Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
2825  return STATUS_DEVICE_BUSY;
2826  }
2827 
2828  //
2829  // Verify parameters of this request.
2830  // Check that ending sector is on disc and
2831  // that number of bytes to transfer is a multiple of
2832  // the sector size.
2833  //
2834 
2835  startingOffset.QuadPart = currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
2836  transferByteCount;
2837 
2838  if (!deviceExtension->DiskGeometry->Geometry.BytesPerSector) {
2839  deviceExtension->DiskGeometry->Geometry.BytesPerSector = 2048;
2840  }
2841 
2842  if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) ||
2843  (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) {
2844 
2845  DebugPrint((1,"ScsiCdRomRead: Invalid I/O parameters\n"));
2846  DebugPrint((1, "\toffset %x:%x, Length %x:%x\n",
2847  startingOffset.u.HighPart,
2848  startingOffset.u.LowPart,
2849  deviceExtension->PartitionLength.u.HighPart,
2850  deviceExtension->PartitionLength.u.LowPart));
2851  DebugPrint((1, "\tbps %x\n", deviceExtension->DiskGeometry->Geometry.BytesPerSector));
2852 
2853  //
2854  // Fail request with status of invalid parameters.
2855  //
2856 
2857  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
2858 
2859  return STATUS_INVALID_PARAMETER;
2860  }
2861 
2862 
2863  return STATUS_SUCCESS;
2864 
2865 } // end ScsiCdRomReadVerification()
2866 
2867 
2868 NTSTATUS
2869 NTAPI
2872  IN PIRP Irp,
2873  IN PVOID Context
2874  )
2875 {
2876  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2877  PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
2879  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
2880  BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
2881  PIO_STACK_LOCATION realIrpStack;
2882  PIO_STACK_LOCATION realIrpNextStack;
2884  PIRP realIrp = NULL;
2885  NTSTATUS status;
2886  BOOLEAN retry;
2887 
2888  //
2889  // Extract the 'real' irp from the irpstack.
2890  //
2891 
2892  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
2893  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
2894  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
2895 
2896  //
2897  // Check SRB status for success of completing request.
2898  //
2899 
2900  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
2901 
2902  DebugPrint((2,
2903  "CdRomDeviceControlCompletion: Irp %lx, Srb %lx Real Irp %lx Status %lx\n",
2904  Irp,
2905  srb,
2906  realIrp,
2907  srb->SrbStatus));
2908 
2909  //
2910  // Release the queue if it is frozen.
2911  //
2912 
2913  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
2914  DebugPrint((2, "CdRomDeviceControlCompletion: Releasing Queue\n"));
2916  }
2917 
2918 
2920  srb,
2921  irpStack->MajorFunction,
2922  irpStack->Parameters.DeviceIoControl.IoControlCode,
2923  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
2924  &status);
2925 
2926  DebugPrint((2, "CdRomDeviceControlCompletion: IRP will %sbe retried\n",
2927  (retry ? "" : "not ")));
2928 
2929  //
2930  // Some of the Device Controls need special cases on non-Success status's.
2931  //
2932 
2933  if (realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
2934  if ((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_LAST_SESSION) ||
2935  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_TOC) ||
2936  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_CONTROL) ||
2937  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_GET_VOLUME)) {
2938 
2939  if (status == STATUS_DATA_OVERRUN) {
2941  retry = FALSE;
2942  }
2943  }
2944 
2945  if (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_READ_Q_CHANNEL) {
2946  PLAY_ACTIVE(deviceExtension) = FALSE;
2947  }
2948  }
2949 
2950  //
2951  // If the status is verified required and the this request
2952  // should bypass verify required then retry the request.
2953  //
2954 
2955  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
2957 
2958  if (((realIrpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) ||
2959  (realIrpStack->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL)) &&
2960  (realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY)) {
2961 
2963  if (srb->DataBuffer) {
2964  ExFreePool(srb->DataBuffer);
2965  }
2966  ExFreePool(srb);
2967  if (Irp->MdlAddress) {
2968  IoFreeMdl(Irp->MdlAddress);
2969  }
2970 
2971  IoFreeIrp(Irp);
2972 
2973  //
2974  // Update the geometry information, as the media could have changed.
2975  // The completion routine for this will complete the real irp and start
2976  // the next packet.
2977  //
2978 
2979  status = CdRomUpdateCapacity(deviceExtension,realIrp, NULL);
2980  DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] CdRomUpdateCapacity completed with status %lx\n", realIrp, status));
2982 
2984 
2985  } else {
2986 
2988  retry = TRUE;
2989  }
2990 
2991  }
2992 
2993  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
2994 
2995 
2996  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
2997 
2998  //
2999  // Retry request.
3000  //
3001 
3002  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
3003 
3004 
3006  if (srb->DataBuffer) {
3007  ExFreePool(srb->DataBuffer);
3008  }
3009  ExFreePool(srb);
3010  if (Irp->MdlAddress) {
3011  IoFreeMdl(Irp->MdlAddress);
3012  }
3013 
3014  IoFreeIrp(Irp);
3015 
3016  //
3017  // Call StartIo directly since IoStartNextPacket hasn't been called,
3018  // the serialisation is still intact.
3019  //
3020 
3021  ScsiCdRomStartIo(DeviceObject, realIrp);
3023 
3024  }
3025 
3026  //
3027  // Exhausted retries. Fall through and complete the request with the appropriate status.
3028  //
3029 
3030  }
3031  } else {
3032 
3033  //
3034  // Set status for successful request.
3035  //
3036 
3038  }
3039 
3040  if (NT_SUCCESS(status)) {
3041 
3042  switch (realIrpStack->Parameters.DeviceIoControl.IoControlCode) {
3043 
3045 
3046  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3047  ULONG lastSector;
3048  ULONG bps;
3049  ULONG lastBit;
3050  ULONG tmp;
3051 
3052  //
3053  // Swizzle bytes from Read Capacity and translate into
3054  // the necessary geometry information in the device extension.
3055  //
3056 
3057  tmp = readCapacityBuffer->BytesPerBlock;
3058  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3059  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3060  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3061  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3062 
3063  //
3064  // Insure that bps is a power of 2.
3065  // This corrects a problem with the HP 4020i CDR where it
3066  // returns an incorrect number for bytes per sector.
3067  //
3068 
3069  if (!bps) {
3070  bps = 2048;
3071  } else {
3072  lastBit = (ULONG) -1;
3073  while (bps) {
3074  lastBit++;
3075  bps = bps >> 1;
3076  }
3077 
3078  bps = 1 << lastBit;
3079  }
3080  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3081 
3082  DebugPrint((2,
3083  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3084  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3085 
3086  //
3087  // Copy last sector in reverse byte order.
3088  //
3089 
3090  tmp = readCapacityBuffer->LogicalBlockAddress;
3091  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3092  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3093  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3094  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3095 
3096  //
3097  // Calculate sector to byte shift.
3098  //
3099 
3100  WHICH_BIT(bps, deviceExtension->SectorShift);
3101 
3102  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3103  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3104 
3105  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3106  lastSector + 1));
3107 
3108  //
3109  // Calculate media capacity in bytes.
3110  //
3111 
3112  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3113 
3114  //
3115  // Calculate number of cylinders.
3116  //
3117 
3118  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3119 
3120  deviceExtension->PartitionLength.QuadPart =
3121  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3122 
3123  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3124 
3125  //
3126  // This device supports removable media.
3127  //
3128 
3129  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3130 
3131  } else {
3132 
3133  //
3134  // Assume media type is fixed disk.
3135  //
3136 
3137  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3138  }
3139 
3140  //
3141  // Assume sectors per track are 32;
3142  //
3143 
3144  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3145 
3146  //
3147  // Assume tracks per cylinder (number of heads) is 64.
3148  //
3149 
3150  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3151 
3152  //
3153  // Copy the device extension's geometry info into the user buffer.
3154  //
3155 
3156  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3157  &deviceExtension->PartitionLength,
3158  sizeof(GET_LENGTH_INFORMATION));
3159 
3160  //
3161  // update information field.
3162  //
3163 
3164  realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY);
3165  break;
3166  }
3167 
3170 
3171  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3172  ULONG lastSector;
3173  ULONG bps;
3174  ULONG lastBit;
3175  ULONG tmp;
3176  PDISK_GEOMETRY_EX geometryEx;
3177 
3178  //
3179  // Swizzle bytes from Read Capacity and translate into
3180  // the necessary geometry information in the device extension.
3181  //
3182 
3183  tmp = readCapacityBuffer->BytesPerBlock;
3184  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3185  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3186  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3187  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3188 
3189  //
3190  // Insure that bps is a power of 2.
3191  // This corrects a problem with the HP 4020i CDR where it
3192  // returns an incorrect number for bytes per sector.
3193  //
3194 
3195  if (!bps) {
3196  bps = 2048;
3197  } else {
3198  lastBit = (ULONG) -1;
3199  while (bps) {
3200  lastBit++;
3201  bps = bps >> 1;
3202  }
3203 
3204  bps = 1 << lastBit;
3205  }
3206  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3207 
3208  DebugPrint((2,
3209  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3210  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3211 
3212  //
3213  // Copy last sector in reverse byte order.
3214  //
3215 
3216  tmp = readCapacityBuffer->LogicalBlockAddress;
3217  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3218  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3219  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3220  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3221 
3222  //
3223  // Calculate sector to byte shift.
3224  //
3225 
3226  WHICH_BIT(bps, deviceExtension->SectorShift);
3227 
3228  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3229  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3230 
3231  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3232  lastSector + 1));
3233 
3234  //
3235  // Calculate media capacity in bytes.
3236  //
3237 
3238  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3239 
3240  //
3241  // Calculate number of cylinders.
3242  //
3243 
3244  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3245 
3246  deviceExtension->PartitionLength.QuadPart =
3247  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3248 
3249  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3250 
3251  //
3252  // This device supports removable media.
3253  //
3254 
3255  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3256 
3257  } else {
3258 
3259  //
3260  // Assume media type is fixed disk.
3261  //
3262 
3263  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3264  }
3265 
3266  //
3267  // Assume sectors per track are 32;
3268  //
3269 
3270  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3271 
3272  //
3273  // Assume tracks per cylinder (number of heads) is 64.
3274  //
3275 
3276  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3277 
3278  //
3279  // Copy the device extension's geometry info into the user buffer.
3280  //
3281 
3282  geometryEx = realIrp->AssociatedIrp.SystemBuffer;
3283  RtlMoveMemory(&geometryEx->Geometry,
3284  &deviceExtension->DiskGeometry->Geometry,
3285  sizeof(DISK_GEOMETRY));
3286 
3287  //
3288  // Copy the extended information
3289  //
3290 
3291  geometryEx->DiskSize = deviceExtension->PartitionLength;
3292 
3293  //
3294  // update information field.
3295  //
3296 
3297  realIrp->IoStatus.Information = FIELD_OFFSET(DISK_GEOMETRY_EX, Data);
3298  break;
3299  }
3300 
3303 
3304  PREAD_CAPACITY_DATA readCapacityBuffer = srb->DataBuffer;
3305  ULONG lastSector;
3306  ULONG bps;
3307  ULONG lastBit;
3308  ULONG tmp;
3309 
3310  //
3311  // Swizzle bytes from Read Capacity and translate into
3312  // the necessary geometry information in the device extension.
3313  //
3314 
3315  tmp = readCapacityBuffer->BytesPerBlock;
3316  ((PFOUR_BYTE)&bps)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3317  ((PFOUR_BYTE)&bps)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3318  ((PFOUR_BYTE)&bps)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3319  ((PFOUR_BYTE)&bps)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3320 
3321  //
3322  // Insure that bps is a power of 2.
3323  // This corrects a problem with the HP 4020i CDR where it
3324  // returns an incorrect number for bytes per sector.
3325  //
3326 
3327  if (!bps) {
3328  bps = 2048;
3329  } else {
3330  lastBit = (ULONG) -1;
3331  while (bps) {
3332  lastBit++;
3333  bps = bps >> 1;
3334  }
3335 
3336  bps = 1 << lastBit;
3337  }
3338  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bps;
3339 
3340  DebugPrint((2,
3341  "CdRomDeviceControlCompletion: Calculated bps %#x\n",
3342  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3343 
3344  //
3345  // Copy last sector in reverse byte order.
3346  //
3347 
3348  tmp = readCapacityBuffer->LogicalBlockAddress;
3349  ((PFOUR_BYTE)&lastSector)->Byte0 = ((PFOUR_BYTE)&tmp)->Byte3;
3350  ((PFOUR_BYTE)&lastSector)->Byte1 = ((PFOUR_BYTE)&tmp)->Byte2;
3351  ((PFOUR_BYTE)&lastSector)->Byte2 = ((PFOUR_BYTE)&tmp)->Byte1;
3352  ((PFOUR_BYTE)&lastSector)->Byte3 = ((PFOUR_BYTE)&tmp)->Byte0;
3353 
3354  //
3355  // Calculate sector to byte shift.
3356  //
3357 
3358  WHICH_BIT(bps, deviceExtension->SectorShift);
3359 
3360  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
3361  deviceExtension->DiskGeometry->Geometry.BytesPerSector));
3362 
3363  DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
3364  lastSector + 1));
3365 
3366  //
3367  // Calculate media capacity in bytes.
3368  //
3369 
3370  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
3371 
3372  //
3373  // Calculate number of cylinders.
3374  //
3375 
3376  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(32 * 64));
3377 
3378  deviceExtension->PartitionLength.QuadPart =
3379  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
3380 
3381  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
3382 
3383  //
3384  // This device supports removable media.
3385  //
3386 
3387  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
3388 
3389  } else {
3390 
3391  //
3392  // Assume media type is fixed disk.
3393  //
3394 
3395  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
3396  }
3397 
3398  //
3399  // Assume sectors per track are 32;
3400  //
3401 
3402  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = 32;
3403 
3404  //
3405  // Assume tracks per cylinder (number of heads) is 64.
3406  //
3407 
3408  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = 64;
3409 
3410  //
3411  // Copy the device extension's geometry info into the user buffer.
3412  //
3413 
3414  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3415  deviceExtension->DiskGeometry,
3416  sizeof(DISK_GEOMETRY));
3417 
3418  //
3419  // update information field.
3420  //
3421 
3422  realIrp->IoStatus.Information = sizeof(DISK_GEOMETRY);
3423  break;
3424  }
3425 
3427 
3428  if((realIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_CHECK_VERIFY) &&
3429  (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength)) {
3430 
3431  *((PULONG)realIrp->AssociatedIrp.SystemBuffer) =
3432  physicalExtension->MediaChangeCount;
3433  realIrp->IoStatus.Information = sizeof(ULONG);
3434  } else {
3435  realIrp->IoStatus.Information = 0;
3436  }
3437 
3438  DebugPrint((2, "CdRomDeviceControlCompletion: [%lx] completing CHECK_VERIFY buddy irp %lx\n", realIrp, Irp));
3439  break;
3440 
3442  case IOCTL_CDROM_READ_TOC: {
3443 
3444  PCDROM_TOC toc = srb->DataBuffer;
3445 
3446  //
3447  // Copy the device extension's geometry info into the user buffer.
3448  //
3449 
3450  RtlMoveMemory(realIrp->AssociatedIrp.SystemBuffer,
3451  toc,
3452  srb->DataTransferLength);
3453 
3454  //
3455  // update information field.
3456  //
3457 
3458  realIrp->IoStatus.Information = srb->DataTransferLength;
3459  break;
3460  }
3461 
3463 
3464  PLAY_ACTIVE(deviceExtension) = TRUE;
3465 
3466  break;
3467 
3469 
3470  PSUB_Q_CHANNEL_DATA userChannelData = realIrp->AssociatedIrp.SystemBuffer;
3471 #if DBG
3472  PCDROM_SUB_Q_DATA_FORMAT inputBuffer = realIrp->AssociatedIrp.SystemBuffer;
3473 #endif
3474  PSUB_Q_CHANNEL_DATA subQPtr = srb->DataBuffer;
3475 
3476 #if DBG
3477  switch( inputBuffer->Format ) {
3478 
3480  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->CurrentPosition.Header.AudioStatus ));
3481  DebugPrint((2,"CdRomDeviceControlCompletion: ADR = 0x%x\n", subQPtr->CurrentPosition.ADR ));
3482  DebugPrint((2,"CdRomDeviceControlCompletion: Control = 0x%x\n", subQPtr->CurrentPosition.Control ));
3483  DebugPrint((2,"CdRomDeviceControlCompletion: Track = %u\n", subQPtr->CurrentPosition.TrackNumber ));
3484  DebugPrint((2,"CdRomDeviceControlCompletion: Index = %u\n", subQPtr->CurrentPosition.IndexNumber ));
3485  DebugPrint((2,"CdRomDeviceControlCompletion: Absolute Address = %x\n", *((PULONG)subQPtr->CurrentPosition.AbsoluteAddress) ));
3486  DebugPrint((2,"CdRomDeviceControlCompletion: Relative Address = %x\n", *((PULONG)subQPtr->CurrentPosition.TrackRelativeAddress) ));
3487  break;
3488 
3490  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->MediaCatalog.Header.AudioStatus ));
3491  DebugPrint((2,"CdRomDeviceControlCompletion: Mcval is %u\n", subQPtr->MediaCatalog.Mcval ));
3492  break;
3493 
3495  DebugPrint((2,"CdRomDeviceControlCompletion: Audio Status is %u\n", subQPtr->TrackIsrc.Header.AudioStatus ));
3496  DebugPrint((2,"CdRomDeviceControlCompletion: Tcval is %u\n", subQPtr->TrackIsrc.Tcval ));
3497  break;
3498 
3499  }
3500 #endif
3501 
3502  //
3503  // Update the play active status.
3504  //
3505 
3507 
3508  PLAY_ACTIVE(deviceExtension) = TRUE;
3509 
3510  } else {
3511 
3512  PLAY_ACTIVE(deviceExtension) = FALSE;
3513 
3514  }
3515 
3516  //
3517  // Check if output buffer is large enough to contain
3518  // the data.
3519  //
3520 
3521  if (realIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
3522  srb->DataTransferLength) {
3523 
3524  srb->DataTransferLength =
3525  realIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
3526  }
3527 
3528  //
3529  // Copy our buffer into users.
3530  //
3531 
3532  RtlMoveMemory(userChannelData,
3533  subQPtr,
3534  srb->DataTransferLength);
3535 
3536  realIrp->IoStatus.Information = srb->DataTransferLength;
3537  break;
3538  }
3539 
3541 
3542  PLAY_ACTIVE(deviceExtension) = FALSE;
3543  realIrp->IoStatus.Information = 0;
3544  break;
3545 
3547 
3548  realIrp->IoStatus.Information = 0;
3549  break;
3550 
3552 
3553  realIrp->IoStatus.Information = 0;
3554  break;
3555 
3557 
3558  PLAY_ACTIVE(deviceExtension) = FALSE;
3559 
3560  realIrp->IoStatus.Information = 0;
3561  break;
3562 
3563  case IOCTL_CDROM_GET_CONTROL: {
3564 
3565  PCDROM_AUDIO_CONTROL audioControl = srb->DataBuffer;
3566  PAUDIO_OUTPUT audioOutput;
3567  ULONG bytesTransferred;
3568 
3569  audioOutput = ScsiClassFindModePage((PCHAR)audioControl,
3570  srb->DataTransferLength,
3572  use6Byte);
3573  //
3574  // Verify the page is as big as expected.
3575  //
3576 
3577  bytesTransferred = (PCHAR) audioOutput - (PCHAR) audioControl +
3578  sizeof(AUDIO_OUTPUT);
3579 
3580  if (audioOutput != NULL &&
3581  srb->DataTransferLength >= bytesTransferred) {
3582 
3583  audioControl->LbaFormat = audioOutput->LbaFormat;
3584 
3585  audioControl->LogicalBlocksPerSecond =
3586  (audioOutput->LogicalBlocksPerSecond[0] << (UCHAR)8) |
3587  audioOutput->LogicalBlocksPerSecond[1];
3588 
3589  realIrp->IoStatus.Information = sizeof(CDROM_AUDIO_CONTROL);
3590 
3591  } else {
3592  realIrp->IoStatus.Information = 0;
3594  }
3595  break;
3596  }
3597 
3598  case IOCTL_CDROM_GET_VOLUME: {
3599 
3600  PAUDIO_OUTPUT audioOutput;
3601  PVOLUME_CONTROL volumeControl = srb->DataBuffer;
3602  ULONG i,bytesTransferred;
3603 
3604  audioOutput = ScsiClassFindModePage((PCHAR)volumeControl,
3605  srb->DataTransferLength,
3607  use6Byte);
3608 
3609  //
3610  // Verify the page is as big as expected.
3611  //
3612 
3613  bytesTransferred = (PCHAR) audioOutput - (PCHAR) volumeControl +
3614  sizeof(AUDIO_OUTPUT);
3615 
3616  if (audioOutput != NULL &&
3617  srb->DataTransferLength >= bytesTransferred) {
3618 
3619  for (i=0; i<4; i++) {
3620  volumeControl->PortVolume[i] =
3621  audioOutput->PortOutput[i].Volume;
3622  }
3623 
3624  //
3625  // Set bytes transferred in IRP.
3626  //
3627 
3628  realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL);
3629 
3630  } else {
3631  realIrp->IoStatus.Information = 0;
3633  }
3634 
3635  break;
3636  }
3637 
3639 
3640  realIrp->IoStatus.Information = sizeof(VOLUME_CONTROL);
3641  break;
3642 
3643  default:
3644 
3645  ASSERT(FALSE);
3646  realIrp->IoStatus.Information = 0;
3648 
3649  } // end switch()
3650  }
3651 
3652  //
3653  // Deallocate srb and sense buffer.
3654  //
3655 
3656  if (srb) {
3657  if (srb->DataBuffer) {
3658  ExFreePool(srb->DataBuffer);
3659  }
3660  if (srb->SenseInfoBuffer) {
3662  }
3663  ExFreePool(srb);
3664  }
3665 
3666  if (realIrp->PendingReturned) {
3667  IoMarkIrpPending(realIrp);
3668  }
3669 
3670  if (Irp->MdlAddress) {
3671  IoFreeMdl(Irp->MdlAddress);
3672  }
3673 
3674  IoFreeIrp(Irp);
3675 
3676  //
3677  // Set status in completing IRP.
3678  //
3679 
3680  realIrp->IoStatus.Status = status;
3681 
3682  //
3683  // Set the hard error if necessary.
3684  //
3685 
3687 
3688  //
3689  // Store DeviceObject for filesystem, and clear
3690  // in IoStatus.Information field.
3691  //
3692 
3693  DebugPrint((1, "CdRomDeviceCompletion - Setting Hard Error on realIrp %lx\n",
3694  realIrp));
3696  realIrp->IoStatus.Information = 0;
3697  }
3698 
3700 
3702 
3704 }
3705 
3706 NTSTATUS
3707 NTAPI
3710  IN PIRP Irp,
3711  IN PVOID Context
3712  )
3713 {
3714  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3716  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
3717  BOOLEAN use6Byte = cdData->XAFlags & XA_USE_6_BYTE;
3718  PIO_STACK_LOCATION realIrpStack;
3719  PIO_STACK_LOCATION realIrpNextStack;
3721  PIRP realIrp = NULL;
3722  NTSTATUS status;
3723  BOOLEAN retry;
3724 
3725  //
3726  // Extract the 'real' irp from the irpstack.
3727  //
3728 
3729  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
3730  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
3731  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
3732 
3733  //
3734  // Check SRB status for success of completing request.
3735  //
3736 
3737  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
3738 
3739  DebugPrint((2,
3740  "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n",
3741  Irp,
3742  srb,
3743  realIrp));
3744 
3745  //
3746  // Release the queue if it is frozen.
3747  //
3748 
3749  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
3751  }
3752 
3753 
3755  srb,
3756  irpStack->MajorFunction,
3757  irpStack->Parameters.DeviceIoControl.IoControlCode,
3758  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
3759  &status);
3760 
3761  if (status == STATUS_DATA_OVERRUN) {
3763  retry = FALSE;
3764  }
3765 
3766  //
3767  // If the status is verified required and the this request
3768  // should bypass verify required then retry the request.
3769  //
3770 
3771  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
3773 
3775  retry = TRUE;
3776  }
3777 
3778  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
3779 
3780  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
3781 
3782  //
3783  // Retry request.
3784  //
3785 
3786  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
3787 
3788 
3790  ExFreePool(srb->DataBuffer);
3791  ExFreePool(srb);
3792  if (Irp->MdlAddress) {
3793  IoFreeMdl(Irp->MdlAddress);
3794  }
3795 
3796  IoFreeIrp(Irp);
3797 
3798  //
3799  // Call StartIo directly since IoStartNextPacket hasn't been called,
3800  // the serialisation is still intact.
3801  //
3802  ScsiCdRomStartIo(DeviceObject, realIrp);
3804 
3805  }
3806 
3807  //
3808  // Exhausted retries. Fall through and complete the request with the appropriate status.
3809  //
3810 
3811  }
3812  } else {
3813 
3814  //
3815  // Set status for successful request.
3816  //
3817 
3819  }
3820 
3821  if (NT_SUCCESS(status)) {
3822 
3823  PAUDIO_OUTPUT audioInput = NULL;
3824  PAUDIO_OUTPUT audioOutput;
3825  PVOLUME_CONTROL volumeControl = realIrp->AssociatedIrp.SystemBuffer;
3826  ULONG i,bytesTransferred,headerLength;
3827  PVOID dataBuffer;
3828  PCDB cdb;
3829 
3830  audioInput = ScsiClassFindModePage((PCHAR)srb->DataBuffer,
3831  srb->DataTransferLength,
3833  use6Byte);
3834 
3835  //
3836  // Check to make sure the mode sense data is valid before we go on
3837  //
3838 
3839  if(audioInput == NULL) {
3840 
3841  DebugPrint((1, "Mode Sense Page %d not found\n",
3843 
3844  realIrp->IoStatus.Information = 0;
3845  realIrp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
3848  ExFreePool(srb);
3849  IoFreeMdl(Irp->MdlAddress);
3850  IoFreeIrp(Irp);
3852  }
3853 
3854  if (use6Byte) {
3855  headerLength = sizeof(MODE_PARAMETER_HEADER);
3856  } else {
3857  headerLength = sizeof(MODE_PARAMETER_HEADER10);
3858  }
3859 
3860  bytesTransferred = sizeof(AUDIO_OUTPUT) + headerLength;
3861 
3862  //
3863  // Allocate a new buffer for the mode select.
3864  //
3865 
3866  dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, bytesTransferred);
3867 
3868  if (!dataBuffer) {
3869  realIrp->IoStatus.Information = 0;
3870  realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3873  ExFreePool(srb);
3874  IoFreeMdl(Irp->MdlAddress);
3875  IoFreeIrp(Irp);
3877  }
3878 
3879  RtlZeroMemory(dataBuffer, bytesTransferred);
3880 
3881  //
3882  // Rebuild the data buffer to include the user requested values.
3883  //
3884 
3885  audioOutput = (PAUDIO_OUTPUT) ((PCHAR) dataBuffer + headerLength);
3886 
3887  for (i=0; i<4; i++) {
3888  audioOutput->PortOutput[i].Volume =
3889  volumeControl->PortVolume[i];
3890  audioOutput->PortOutput[i].ChannelSelection =
3891  audioInput->PortOutput[i].ChannelSelection;
3892  }
3893 
3894  audioOutput->CodePage = CDROM_AUDIO_CONTROL_PAGE;
3895  audioOutput->ParameterLength = sizeof(AUDIO_OUTPUT) - 2;
3896  audioOutput->Immediate = MODE_SELECT_IMMEDIATE;
3897 
3898  //
3899  // Free the old data buffer, mdl.
3900  //
3901 
3902  ExFreePool(srb->DataBuffer);
3903  IoFreeMdl(Irp->MdlAddress);
3904 
3905  //
3906  // rebuild the srb.
3907  //
3908 
3909  cdb = (PCDB)srb->Cdb;
3911 
3912  srb->SrbStatus = srb->ScsiStatus = 0;
3913  srb->SrbFlags = deviceExtension->SrbFlags;
3915  srb->DataTransferLength = bytesTransferred;
3916 
3917  if (use6Byte) {
3918 
3919  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
3920  cdb->MODE_SELECT.ParameterListLength = (UCHAR) bytesTransferred;
3921  cdb->MODE_SELECT.PFBit = 1;
3922  srb->CdbLength = 6;
3923  } else {
3924 
3925  cdb->MODE_SELECT10.OperationCode = SCSIOP_MODE_SELECT10;
3926  cdb->MODE_SELECT10.ParameterListLength[0] = (UCHAR) (bytesTransferred >> 8);
3927  cdb->MODE_SELECT10.ParameterListLength[1] = (UCHAR) (bytesTransferred & 0xFF);
3928  cdb->MODE_SELECT10.PFBit = 1;
3929  srb->CdbLength = 10;
3930  }
3931 
3932  //
3933  // Prepare the MDL
3934  //
3935 
3936  Irp->MdlAddress = IoAllocateMdl(dataBuffer,
3937  bytesTransferred,
3938  FALSE,
3939  FALSE,
3940  (PIRP) NULL);
3941 
3942  if (!Irp->MdlAddress) {
3943  realIrp->IoStatus.Information = 0;
3944  realIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3947  ExFreePool(srb);
3948  ExFreePool(dataBuffer);
3949  IoFreeIrp(Irp);
3951 
3952  }
3953 
3954  MmBuildMdlForNonPagedPool(Irp->MdlAddress);
3955  srb->DataBuffer = dataBuffer;
3956 
3957  irpStack = IoGetNextIrpStackLocation(Irp);
3959  irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
3960  irpStack->Parameters.Scsi.Srb = srb;
3961 
3962  //
3963  // reset the irp completion.
3964  //
3965 
3968  srb,
3969  TRUE,
3970  TRUE,
3971  TRUE);
3972  //
3973  // Call the port driver.
3974  //
3975 
3976  IoCallDriver(deviceExtension->PortDeviceObject, Irp);
3977 
3979  }
3980 
3981  //
3982  // Deallocate srb and sense buffer.
3983  //
3984 
3985  if (srb) {
3986  if (srb->DataBuffer) {
3987  ExFreePool(srb->DataBuffer);
3988  }
3989  if (srb->SenseInfoBuffer) {
3991  }
3992  ExFreePool(srb);
3993  }
3994 
3995  if (Irp->PendingReturned) {
3997  }
3998 
3999  if (realIrp->PendingReturned) {
4000  IoMarkIrpPending(realIrp);
4001  }
4002 
4003  if (Irp->MdlAddress) {
4004  IoFreeMdl(Irp->MdlAddress);
4005  }
4006 
4007  IoFreeIrp(Irp);
4008 
4009  //
4010  // Set status in completing IRP.
4011  //
4012 
4013  realIrp->IoStatus.Status = status;
4014 
4015  //
4016  // Set the hard error if necessary.
4017  //
4018 
4020 
4021  //
4022  // Store DeviceObject for filesystem, and clear
4023  // in IoStatus.Information field.
4024  //
4025 
4027  realIrp->IoStatus.Information = 0;
4028  }
4029 
4031 
4033 
4035 }
4036 
4037 
4038 NTSTATUS
4039 NTAPI
4042  IN PIRP Irp,
4043  IN PVOID Context
4044  )
4045 {
4046  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4048  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension + 1);
4049  PIO_STACK_LOCATION realIrpStack;
4050  PIO_STACK_LOCATION realIrpNextStack;
4052  PIRP realIrp = NULL;
4053  NTSTATUS status;
4054  BOOLEAN retry;
4055 
4056  //
4057  // Extract the 'real' irp from the irpstack.
4058  //
4059 
4060  realIrp = (PIRP) irpStack->Parameters.Others.Argument2;
4061  realIrpStack = IoGetCurrentIrpStackLocation(realIrp);
4062  realIrpNextStack = IoGetNextIrpStackLocation(realIrp);
4063 
4064  //
4065  // Check SRB status for success of completing request.
4066  //
4067 
4068  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
4069 
4070  DebugPrint((2,
4071  "CdRomSetVolumeIntermediateCompletion: Irp %lx, Srb %lx Real Irp\n",
4072  Irp,
4073  srb,
4074  realIrp));
4075 
4076  //
4077  // Release the queue if it is frozen.
4078  //
4079 
4080  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
4082  }
4083 
4084 
4086  srb,
4087  irpStack->MajorFunction,
4088  irpStack->Parameters.DeviceIoControl.IoControlCode,
4089  MAXIMUM_RETRIES - ((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1),
4090  &status);
4091 
4092  //
4093  // If the status is verified required and the this request
4094  // should bypass verify required then retry the request.
4095  //
4096 
4097  if (realIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
4099 
4101  retry = TRUE;
4102  }
4103 
4104  if (retry && (realIrpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1-1))) {
4105 
4106  if (((ULONG_PTR)realIrpNextStack->Parameters.Others.Argument1)) {
4107 
4108  //
4109  // Retry request.
4110  //
4111 
4112  DebugPrint((1, "Retry request %lx - Calling StartIo\n", Irp));
4113 
4114 
4116  ExFreePool(srb->DataBuffer);
4117  ExFreePool(srb);
4118  if (Irp->MdlAddress) {
4119  IoFreeMdl(Irp->MdlAddress);
4120  }
4121 
4122  IoFreeIrp(Irp);
4123 
4124  //
4125  // Call StartIo directly since IoStartNextPacket hasn't been called,
4126  // the serialisation is still intact.
4127  //
4128 
4129  ScsiCdRomStartIo(DeviceObject, realIrp);
4131 
4132  }
4133 
4134  //
4135  // Exhausted retries. Fall through and complete the request with the appropriate status.
4136  //
4137  }
4138  } else {
4139 
4140  //
4141  // Set status for successful request.
4142  //
4143 
4145  }
4146 
4147  if (NT_SUCCESS(status)) {
4148 
4149  ULONG sectorSize, startingSector, transferByteCount;
4150  PCDB cdb;
4151 
4152  //
4153  // Update device ext. to show which mode we are currently using.
4154  //
4155 
4156  sectorSize = cdData->u1.BlockDescriptor.BlockLength[0] << 16;
4157  sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[1] << 8);
4158  sectorSize |= (cdData->u1.BlockDescriptor.BlockLength[2]);
4159 
4160  cdData->RawAccess = (sectorSize == RAW_SECTOR_SIZE) ? TRUE : FALSE;
4161 
4162  //
4163  // Free the old data buffer, mdl.
4164  //
4165 
4166  ExFreePool(srb->DataBuffer);
4167  IoFreeMdl(Irp->MdlAddress);
4168  IoFreeIrp(Irp);
4169 
4170  //
4171  // rebuild the srb.
4172  //
4173 
4174  cdb = (PCDB)srb->Cdb;
4176 
4177 
4178  if (cdData->RawAccess) {
4179 
4180  PRAW_READ_INFO rawReadInfo =
4181  (PRAW_READ_INFO)realIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
4182 
4183  ULONG maximumTransferLength;
4184  ULONG transferPages;
4185 
4186  //
4187  // Calculate starting offset.
4188  //
4189 
4190  startingSector = (ULONG)(rawReadInfo->DiskOffset.QuadPart >> deviceExtension->SectorShift);
4191  transferByteCount = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
4192  maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
4193  transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress),
4194  transferByteCount);
4195 
4196  //
4197  // Determine if request is within limits imposed by miniport.
4198  // If the request is larger than the miniport's capabilities, split it.
4199  //
4200 
4201  if (transferByteCount > maximumTransferLength ||
4202  transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
4203 
4204  realIrp->IoStatus.Information = 0;
4205  realIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4207 
4209  ExFreePool(srb);
4210 
4212 
4214  }
4215 
4216  srb->OriginalRequest = realIrp;
4217  srb->SrbFlags = deviceExtension->SrbFlags;
4219  srb->DataTransferLength = transferByteCount;
4220  srb->TimeOutValue = deviceExtension->TimeOutValue;
4221  srb->CdbLength = 10;
4222  srb->DataBuffer = MmGetMdlVirtualAddress(realIrp->MdlAddress);
4223 
4224  if (rawReadInfo->TrackMode == CDDA) {
4225  if (cdData->XAFlags & PLEXTOR_CDDA) {
4226 
4227  srb->CdbLength = 12;
4228 
4229  cdb->PLXTR_READ_CDDA.LogicalUnitNumber = deviceExtension->Lun;
4230  cdb->PLXTR_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4231  cdb->PLXTR_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4232  cdb->PLXTR_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4233  cdb->PLXTR_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4234 
4235  cdb->PLXTR_READ_CDDA.TransferBlockByte3 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4236  cdb->PLXTR_READ_CDDA.TransferBlockByte2 = (UCHAR) (rawReadInfo->SectorCount >> 8);
4237  cdb->PLXTR_READ_CDDA.TransferBlockByte1 = 0;
4238  cdb->PLXTR_READ_CDDA.TransferBlockByte0 = 0;
4239 
4240  cdb->PLXTR_READ_CDDA.SubCode = 0;
4241  cdb->PLXTR_READ_CDDA.OperationCode = 0xD8;
4242 
4243  } else if (cdData->XAFlags & NEC_CDDA) {
4244 
4245  cdb->NEC_READ_CDDA.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4246  cdb->NEC_READ_CDDA.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4247  cdb->NEC_READ_CDDA.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4248  cdb->NEC_READ_CDDA.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4249 
4250  cdb->NEC_READ_CDDA.TransferBlockByte1 = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4251  cdb->NEC_READ_CDDA.TransferBlockByte0 = (UCHAR) (rawReadInfo->SectorCount >> 8);
4252 
4253  cdb->NEC_READ_CDDA.OperationCode = 0xD4;
4254  }
4255  } else {
4256  cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
4257 
4258  cdb->CDB10.TransferBlocksMsb = (UCHAR) (rawReadInfo->SectorCount >> 8);
4259  cdb->CDB10.TransferBlocksLsb = (UCHAR) (rawReadInfo->SectorCount & 0xFF);
4260 
4261  cdb->CDB10.LogicalBlockByte3 = (UCHAR) (startingSector & 0xFF);
4262  cdb->CDB10.LogicalBlockByte2 = (UCHAR) ((startingSector >> 8) & 0xFF);
4263  cdb->CDB10.LogicalBlockByte1 = (UCHAR) ((startingSector >> 16) & 0xFF);
4264  cdb->CDB10.LogicalBlockByte0 = (UCHAR) ((startingSector >> 24) & 0xFF);
4265 
4266  cdb->CDB10.OperationCode = SCSIOP_READ;
4267  }
4268 
4269  srb->SrbStatus = srb->ScsiStatus = 0;
4270 
4271 
4272  irpStack = IoGetNextIrpStackLocation(realIrp);
4273  irpStack->MajorFunction = IRP_MJ_SCSI;
4274  irpStack->Parameters.Scsi.Srb = srb;
4275 
4276  if (!(irpStack->Parameters.Others.Argument1)) {
4277 
4278  //
4279  // Only jam this in if it doesn't exist. The completion routines can
4280  // call StartIo directly in the case of retries and resetting it will
4281  // cause infinite loops.
4282  //
4283 
4284  irpStack->Parameters.Others.Argument1 = (PVOID) MAXIMUM_RETRIES;
4285  }
4286 
4287  //
4288  // Set up IoCompletion routine address.
4289  //
4290 
4291  IoSetCompletionRoutine(realIrp,
4293  srb,
4294  TRUE,
4295  TRUE,
4296  TRUE);
4297  } else {
4298 
4299  ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
4300  ULONG transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(realIrp->MdlAddress),
4301  realIrpStack->Parameters.Read.Length);
4302  //
4303  // Back to cooked sectors. Build and send a normal read.
4304  // The real work for setting offsets and checking for splitrequests was
4305  // done in startio
4306  //
4307 
4308  if ((realIrpStack->Parameters.Read.Length > maximumTransferLength) ||
4309  (transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages)) {
4310 
4311  //
4312  // Request needs to be split. Completion of each portion of the request will
4313  // fire off the next portion. The final request will signal Io to send a new request.
4314  //
4315 
4316  ScsiClassSplitRequest(DeviceObject, realIrp, maximumTransferLength);
4318 
4319  } else {
4320 
4321  //
4322  // Build SRB and CDB for this IRP.
4323  //
4324 
4326 
4327  }
4328  }
4329 
4330  //
4331  // Call the port driver.
4332  //
4333 
4334  IoCallDriver(deviceExtension->PortDeviceObject, realIrp);
4335 
4337  }
4338 
4339  //
4340  // Update device Extension flags to indicate that XA isn't supported.
4341  //
4342 
4343  cdData->XAFlags |= XA_NOT_SUPPORTED;
4344 
4345  //
4346  // Deallocate srb and sense buffer.
4347  //
4348 
4349  if (srb) {
4350  if (srb->DataBuffer) {
4351  ExFreePool(srb->DataBuffer);
4352  }
4353  if (srb->SenseInfoBuffer) {
4355  }
4356  ExFreePool(srb);
4357  }
4358 
4359  if (Irp->PendingReturned) {
4361  }
4362 
4363  if (realIrp->PendingReturned) {
4364  IoMarkIrpPending(realIrp);
4365  }
4366 
4367  if (Irp->MdlAddress) {
4368  IoFreeMdl(Irp->MdlAddress);
4369  }
4370 
4371  IoFreeIrp(Irp);
4372 
4373  //
4374  // Set status in completing IRP.
4375  //
4376 
4377  realIrp->IoStatus.Status = status;
4378 
4379  //
4380  // Set the hard error if necessary.
4381  //
4382 
4384 
4385  //
4386  // Store DeviceObject for filesystem, and clear
4387  // in IoStatus.Information field.
4388  //
4389 
4391  realIrp->IoStatus.Information = 0;
4392  }
4393 
4395 
4397 
4399 }
4400 
4401 NTSTATUS
4402 NTAPI
4405  IN PIRP Irp,
4406  IN PVOID Context
4407  )
4408 
4409 /*++
4410 
4411 Routine Description:
4412 
4413  This routine executes when the port driver has completed a request.
4414  It looks at the SRB status in the completing SRB and if not success
4415  it checks for valid request sense buffer information. If valid, the
4416  info is used to update status with more precise message of type of
4417  error. This routine deallocates the SRB.
4418 
4419 Arguments:
4420 
4421  DeviceObject - Supplies the device object which represents the logical
4422  unit.
4423 
4424  Irp - Supplies the Irp which has completed.
4425 
4426  Context - Supplies a pointer to the SRB.
4427 
4428 Return Value:
4429 
4430  NT status
4431 
4432 --*/
4433 
4434 {
4438  NTSTATUS status;
4439  BOOLEAN retry;
4440 
4441  //
4442  // Check SRB status for success of completing request.
4443  //
4444 
4445  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
4446 
4447  DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb));
4448 
4449  //
4450  // Release the queue if it is frozen.
4451  //
4452 
4453  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
4455  }
4456 
4458  DeviceObject,
4459  srb,
4460  irpStack->MajorFunction,
4461  irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
4462  MAXIMUM_RETRIES - ((ULONG_PTR)irpNextStack->Parameters.Others.Argument1),
4463  &status);
4464 
4465  //
4466  // If the status is verified required and the this request
4467  // should bypass verify required then retry the request.
4468  //
4469 
4470  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
4472 
4474  retry = TRUE;
4475  }
4476 
4477  if (retry && (irpNextStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)irpNextStack->Parameters.Others.Argument1-1))) {
4478 
4479  if (((ULONG_PTR)irpNextStack->Parameters.Others.Argument1)) {
4480 
4481  //
4482  // Retry request.
4483  //
4484 
4485  DebugPrint((1, "CdRomXACompletion: Retry request %lx - Calling StartIo\n", Irp));
4486 
4487 
4489  ExFreePool(srb->DataBuffer);
4490  ExFreePool(srb);
4491 
4492  //
4493  // Call StartIo directly since IoStartNextPacket hasn't been called,
4494  // the serialisation is still intact.
4495  //
4496 
4499 
4500  }
4501 
4502  //
4503  // Exhausted retries. Fall through and complete the request with the appropriate status.
4504  //
4505  }
4506  } else {
4507 
4508  //
4509  // Set status for successful request.
4510  //
4511 
4513 
4514  } // end if (SRB_STATUS(srb->SrbStatus) ...
4515 
4516  //
4517  // Return SRB to nonpaged pool.
4518  //
4519 
4520  ExFreePool(srb);
4521 
4522  //
4523  // Set status in completing IRP.
4524  //
4525 
4526  Irp->IoStatus.Status = status;
4527 
4528  //
4529  // Set the hard error if necessary.
4530  //
4531 
4533 
4534  //
4535  // Store DeviceObject for filesystem, and clear
4536  // in IoStatus.Information field.
4537  //
4538 
4540  Irp->IoStatus.Information = 0;
4541  }
4542 
4543  //
4544  // If pending has be returned for this irp then mark the current stack as
4545  // pending.
4546  //
4547 
4548  if (Irp->PendingReturned) {
4550  }
4551 
4552  //IoCompleteRequest(Irp, IO_DISK_INCREMENT);
4554 
4555  return status;
4556 }
4557 
4558 NTSTATUS
4559 NTAPI
4562  IN PIRP Irp
4563  )
4564 
4565 /*++
4566 
4567 Routine Description:
4568 
4569  This is the NT device control handler for CDROMs.
4570 
4571 Arguments:
4572 
4573  DeviceObject - for this CDROM
4574 
4575  Irp - IO Request packet
4576 
4577 Return Value:
4578 
4579  NTSTATUS
4580 
4581 --*/
4582 
4583 {
4585  PIO_STACK_LOCATION nextStack;
4586  PKEVENT deviceControlEvent;
4587  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4588  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1);
4589  SCSI_REQUEST_BLOCK srb;
4590  NTSTATUS status;
4591  KIRQL irql;
4592 
4593  ULONG ioctlCode;
4594  ULONG baseCode;
4595  ULONG functionCode;
4596 
4597 RetryControl:
4598 
4599  //
4600  // Zero the SRB on stack.
4601  //
4602 
4603  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
4604 
4605  Irp->IoStatus.Information = 0;
4606 
4607  //
4608  // if this is a class driver ioctl then we need to change the base code
4609  // to IOCTL_CDROM_BASE so that the switch statement can handle it.
4610  //
4611  // WARNING - currently the scsi class ioctl function codes are between
4612  // 0x200 & 0x300. this routine depends on that fact
4613  //
4614 
4615  ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
4616  baseCode = ioctlCode >> 16;
4617  functionCode = (ioctlCode & (~0xffffc003)) >> 2;
4618 
4619  DebugPrint((1, "CdRomDeviceControl: Ioctl Code = %#08lx, Base Code = %#lx,"
4620  " Function Code = %#lx\n",
4621  ioctlCode,
4622  baseCode,
4623  functionCode
4624  ));
4625 
4626  if((functionCode >= 0x200) && (functionCode <= 0x300)) {
4627 
4628  ioctlCode = (ioctlCode & 0x0000ffff) | CTL_CODE(IOCTL_CDROM_BASE, 0, 0, 0);
4629 
4630  DebugPrint((1, "CdRomDeviceControl: Class Code - new ioctl code is %#08lx\n",
4631  ioctlCode));
4632 
4633  irpStack->Parameters.DeviceIoControl.IoControlCode = ioctlCode;
4634 
4635  }
4636 
4637  switch (ioctlCode) {
4638 
4639  case IOCTL_CDROM_RAW_READ: {
4640 
4641  LARGE_INTEGER startingOffset;
4642  ULONG transferBytes;
4643  PRAW_READ_INFO rawReadInfo = (PRAW_READ_INFO)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
4644  PUCHAR userData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
4645 
4646  //
4647  // Ensure that XA reads are supported.
4648  //
4649 
4650  if (cdData->XAFlags & XA_NOT_SUPPORTED) {
4651 
4652  DebugPrint((1,
4653  "CdRomDeviceControl: XA Reads not supported. Flags (%x)\n",
4654  cdData->XAFlags));
4655 
4657  break;
4658  }
4659 
4660  //
4661  // Check that ending sector is on disc and buffers are there and of
4662  // correct size.
4663  //
4664 
4665  if (rawReadInfo == NULL) {
4666 
4667  //
4668  // Called from user space. Validate the buffers.
4669  //
4670 
4671  rawReadInfo = (PRAW_READ_INFO)userData;
4672  irpStack->Parameters.DeviceIoControl.Type3InputBuffer = (PVOID)userData;
4673 
4674  if (rawReadInfo == NULL) {
4675 
4676  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (No extent info\n"));
4677 
4678  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4679 
4681  return STATUS_INVALID_PARAMETER;
4682  }
4683 
4684  if (irpStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(RAW_READ_INFO)) {
4685 
4686  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Invalid info buffer\n"));
4687 
4688  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4689 
4691  return STATUS_INVALID_PARAMETER;
4692  }
4693  }
4694 
4695  startingOffset.QuadPart = rawReadInfo->DiskOffset.QuadPart;
4696  transferBytes = rawReadInfo->SectorCount * RAW_SECTOR_SIZE;
4697 
4698  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < transferBytes) {
4699 
4700  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Bad buffer size)\n"));
4701 
4702  //
4703  // Fail request with status of invalid parameters.
4704  //
4705 
4706  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
4707 
4709  return STATUS_INVALID_PARAMETER;
4710  }
4711 
4712  if ((startingOffset.QuadPart + transferBytes) > deviceExtension->PartitionLength.QuadPart) {
4713 
4714  DebugPrint((1,"CdRomDeviceControl: Invalid I/O parameters for XA Read (Request Out of Bounds)\n"));
4715 
4716  //
4717  // Fail request with status of invalid parameters.
4718  //
4719 
4721  break;
4722  }
4723 
4726 
4727  return STATUS_PENDING;
4728  }
4729 
4732 
4733  DebugPrint((2,"CdRomDeviceControl: Get drive geometry\n"));
4734 
4735  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4736  sizeof( DISK_GEOMETRY ) ) {
4737 
4739  break;
4740  }
4741 
4744 
4745  return STATUS_PENDING;
4746  }
4747 
4750 
4751  DebugPrint((2,"CdRomDeviceControl: Get drive geometry ex\n"));
4752 
4753  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4754  sizeof( DISK_GEOMETRY_EX ) ) {
4755 
4757  break;
4758  }
4759 
4762 
4763  return STATUS_PENDING;
4764  }
4765 
4767 
4768  DebugPrint((2,"CdRomDeviceControl: Get length info\n"));
4769 
4770  if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4771  sizeof( GET_LENGTH_INFORMATION ) ) {
4772 
4774  break;
4775  }
4776 
4779 
4780  return STATUS_PENDING;
4781  }
4782 
4784  case IOCTL_CDROM_READ_TOC: {
4785 
4786  //
4787  // If the cd is playing music then reject this request.
4788  //
4789 
4791  Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
4793  return STATUS_DEVICE_BUSY;
4794  }
4795 
4798 
4799  return STATUS_PENDING;
4800  }
4801 
4803 
4804  //
4805  // Play Audio MSF
4806  //
4807 
4808  DebugPrint((2,"CdRomDeviceControl: Play audio MSF\n"));
4809 
4810  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4811  sizeof(CDROM_PLAY_AUDIO_MSF)) {
4812 
4813  //
4814  // Indicate unsuccessful status.
4815  //
4816 
4818  break;
4819  }
4820 
4823 
4824  return STATUS_PENDING;
4825  }
4826 
4828 
4829 
4830  //
4831  // Seek Audio MSF
4832  //
4833 
4834  DebugPrint((2,"CdRomDeviceControl: Seek audio MSF\n"));
4835 
4836  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4837  sizeof(CDROM_SEEK_AUDIO_MSF)) {
4838 
4839  //
4840  // Indicate unsuccessful status.
4841  //
4842 
4844  break;
4845  } else {
4848 
4849  return STATUS_PENDING;
4850 
4851  }
4852  }
4853 
4854  case IOCTL_CDROM_PAUSE_AUDIO: {
4855 
4856  //
4857  // Pause audio
4858  //
4859 
4860  DebugPrint((2, "CdRomDeviceControl: Pause audio\n"));
4861 
4864 
4865  return STATUS_PENDING;
4866 
4867  break;
4868  }
4869 
4870  case IOCTL_CDROM_RESUME_AUDIO: {
4871 
4872  //
4873  // Resume audio
4874  //
4875 
4876  DebugPrint((2, "CdRomDeviceControl: Resume audio\n"));
4877 
4880 
4881  return STATUS_PENDING;
4882  }
4883 
4885 
4886  if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
4887  sizeof(CDROM_SUB_Q_DATA_FORMAT)) {
4888 
4890  Irp->IoStatus.Information = 0;
4891  break;
4892  }
4893 
4896 
4897  return STATUS_PENDING;
4898  }
4899 
4900  case IOCTL_CDROM_GET_CONTROL: {
4901 
4902  DebugPrint((2, "CdRomDeviceControl: Get audio control\n"));
4903 
4904  //
4905  // Verify user buffer is large enough for the data.
4906  //
4907 
4908  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4909  sizeof(CDROM_AUDIO_CONTROL)) {
4910 
4911  //
4912  // Indicate unsuccessful status and no data transferred.
4913  //
4914 
4916  Irp->IoStatus.Information = 0;
4917  break;
4918 
4919  } else {
4920 
4923 
4924  return STATUS_PENDING;
4925  }
4926  }
4927 
4928  case IOCTL_CDROM_GET_VOLUME: {
4929 
4930  DebugPrint((2, "CdRomDeviceControl: Get volume control\n"));
4931 
4932  //
4933  // Verify user buffer is large enough for data.
4934  //
4935 
4936  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
4937  sizeof(VOLUME_CONTROL)) {
4938 
4939  //
4940  // Indicate unsuccessful status and no data transferred.
4941  //
4942 
4944  Irp->IoStatus.Information = 0;
4945  break;
4946 
4947  } else {
4950 
4951  return STATUS_PENDING;
4952  }
4953  }
4954 
4955  case IOCTL_CDROM_SET_VOLUME: {
4956 
4957  DebugPrint((2, "CdRomDeviceControl: Set volume control\n"));
4958 
4959  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4960  sizeof(VOLUME_CONTROL)) {
4961 
4962  //
4963  // Indicate unsuccessful status.
4964  //
4965 
4967  break;
4968  } else {
4969 
4972 
4973  return STATUS_PENDING;
4974  }
4975  }
4976 
4977  case IOCTL_CDROM_STOP_AUDIO: {
4978 
4979  //
4980  // Stop play.
4981  //
4982 
4983  DebugPrint((2, "CdRomDeviceControl: Stop audio\n"));
4984 
4987 
4988  return STATUS_PENDING;
4989  }
4990 
4991  case IOCTL_CDROM_CHECK_VERIFY: {
4992  DebugPrint((1, "CdRomDeviceControl: [%lx] Check Verify\n", Irp));
4994 
4995  if((irpStack->Parameters.DeviceIoControl.OutputBufferLength) &&
4996  (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))) {
4997 
4998  DebugPrint((1, "CdRomDeviceControl: Check Verify: media count "
4999  "buffer too small\n"));
5000 
5002  break;
5003  }
5004 
5006 
5007  return STATUS_PENDING;
5008  }
5009 
5010  default: {
5011 
5012  //
5013  // allocate an event and stuff it into our stack location.
5014  //
5015 
5016  deviceControlEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
5017 
5018  if(!deviceControlEvent) {
5019 
5021 
5022  } else {
5023 
5024  PIO_STACK_LOCATION currentStack;
5025 
5026  KeInitializeEvent(deviceControlEvent, NotificationEvent, FALSE);
5027 
5028  currentStack = IoGetCurrentIrpStackLocation(Irp);
5029  nextStack = IoGetNextIrpStackLocation(Irp);
5030 
5031  //
5032  // Copy the stack down a notch
5033  //
5034 
5035  *nextStack = *currentStack;
5036 
5038  Irp,
5040  deviceControlEvent,
5041  TRUE,
5042  TRUE,
5043  TRUE
5044  );
5045 
5047 
5048  Irp->IoStatus.Status = STATUS_SUCCESS;
5049  Irp->IoStatus.Information = 0;
5050 
5051  //
5052  // Override volume verifies on this stack location so that we
5053  // will be forced through the synchronization. Once this location
5054  // goes away we get the old value back
5055  //
5056 
5057  nextStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
5058 
5060 
5062 
5063  //
5064  // Wait for CdRomClassIoctlCompletion to set the event. This
5065  // ensures serialization remains intact for these unhandled device
5066  // controls.
5067  //
5068 
5070  deviceControlEvent,
5071  Suspended,
5072  KernelMode,
5073  FALSE,
5074  NULL);
5075 
5076  ExFreePool(deviceControlEvent);
5077 
5078  DebugPrint((2, "CdRomDeviceControl: irp %#08lx synchronized\n", Irp));
5079 
5080  //
5081  // If an error occured then propagate that back up - we are no longer
5082  // guaranteed synchronization and the upper layers will have to
5083  // retry.
5084  //
5085  // If no error occured, call down to the class driver directly
5086  // then start up the next request.
5087  //
5088 
5089  if(Irp->IoStatus.Status == STATUS_SUCCESS) {
5090 
5092 
5094 
5096 
5097  KeLowerIrql(irql);
5098  }
5099  }
5100 
5101  return status;
5102  }
5103 
5104  } // end switch()
5105 
5106  if (status == STATUS_VERIFY_REQUIRED) {
5107 
5108  //
5109  // If the status is verified required and this request
5110  // should bypass verify required then retry the request.
5111  //
5112 
5113  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) {
5114 
5116  goto RetryControl;
5117 
5118  }
5119  }
5120 
5122 
5124 
5125  }
5126 
5127  //
5128  // Update IRP with completion status.
5129  //
5130 
5131  Irp->IoStatus.Status = status;
5132 
5133  //
5134  // Complete the request.
5135  //
5136 
5138  DebugPrint((2, "CdRomDeviceControl: Status is %lx\n", status));
5139  return status;
5140 
5141 } // end ScsiCdRomDeviceControl()
5142 
5143 VOID
5144 NTAPI
5147  PINQUIRYDATA InquiryData,
5148  PIO_SCSI_CAPABILITIES PortCapabilities
5149  )
5150 
5151 /*++
5152 
5153 Routine Description:
5154 
5155  This function checks to see if an SCSI logical unit requires an special
5156  initialization or error processing.
5157 
5158 Arguments:
5159 
5160  DeviceObject - Supplies the device object to be tested.
5161 
5162  InquiryData - Supplies the inquiry data returned by the device of interest.
5163 
5164  PortCapabilities - Supplies the capabilities of the device object.
5165 
5166 Return Value:
5167 
5168  None.
5169 
5170 --*/
5171 
5172 {
5173  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
5174  PCDROM_DATA cdData = (PCDROM_DATA)(deviceExtension+1);
5175 
5176  //
5177  // Look for a Hitachi CDR-1750. Read-ahead must be disabled in order
5178  // to get this cdrom drive to work on scsi adapters that use PIO.
5179  //
5180 
5181  if ((strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-1750S", strlen("HITACHI CDR-1750S")) == 0 ||
5182  strncmp((PCHAR)InquiryData->VendorId, "HITACHI CDR-3650/1650S", strlen("HITACHI CDR-3650/1650S")) == 0)
5183  && PortCapabilities->AdapterUsesPio) {
5184 
5185  DebugPrint((1, "CdRom ScanForSpecial: Found Hitachi CDR-1750S.\n"));
5186 
5187  //
5188  // Setup an error handler to reinitialize the cd rom after it is reset.
5189  //
5190 
5191  deviceExtension->ClassError = HitachProcessError;
5192 
5193  } else if (( RtlCompareMemory( InquiryData->VendorId,"FUJITSU", 7 ) == 7 ) &&
5194  (( RtlCompareMemory( InquiryData->ProductId,"FMCD-101", 8 ) == 8 ) ||
5195  ( RtlCompareMemory( InquiryData->ProductId,"FMCD-102", 8 ) == 8 ))) {
5196 
5197  //
5198  // When Read command is issued to FMCD-101 or FMCD-102 and there is a music
5199  // cd in it. It takes longer time than SCSI_CDROM_TIMEOUT before returning
5200  // error status.
5201  //
5202 
5203  deviceExtension->TimeOutValue = 20;
5204 
5205  } else if (( RtlCompareMemory( InquiryData->VendorId,"TOSHIBA", 7) == 7) &&
5206  (( RtlCompareMemory( InquiryData->ProductId,"CD-ROM XM-34", 12) == 12))) {
5207 
5208  SCSI_REQUEST_BLOCK srb;
5209  PCDB cdb;
5210  ULONG length;
5211  PUCHAR buffer;
5212  NTSTATUS status;
5213 
5214  //
5215  // Set the density code and the error handler.
5216  //
5217 
5219 
5220  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
5221 
5222  //
5223  // Build the MODE SENSE CDB.
5224  //
5225 
5226  srb.CdbLength = 6;
5227  cdb = (PCDB)srb.Cdb;
5228 
5229  //
5230  // Set timeout value from device extension.
5231  //
5232 
5233  srb.TimeOutValue = deviceExtension->TimeOutValue;
5234 
5235  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
5236  cdb->MODE_SENSE.PageCode = 0x1;
5237  cdb->MODE_SENSE.AllocationLength = (UCHAR)length;
5238 
5240  if (!buffer) {
5241  return;
5242  }
5243 
5245  &srb,
5246  buffer,
5247  length,
5248  FALSE);
5249 
5250  ((PERROR_RECOVERY_DATA)buffer)->BlockDescriptor.DensityCode = 0x83;
5251  ((PERROR_RECOVERY_DATA)buffer)->Header.ModeDataLength = 0x0;
5252 
5253  RtlCopyMemory(&cdData->u1.Header, buffer, sizeof(ERROR_RECOVERY_DATA));
5254 
5255  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
5256 
5257  //
5258  // Build the MODE SENSE CDB.
5259  //
5260 
5261  srb.CdbLength = 6;
5262  cdb = (PCDB)srb.Cdb;
5263 
5264  //
5265  // Set timeout value from device extension.
5266  //
5267 
5268  srb.TimeOutValue = deviceExtension->TimeOutValue;
5269 
5270  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
5271  cdb->MODE_SELECT.PFBit = 1;
5272  cdb->MODE_SELECT.ParameterListLength = (UCHAR)length;
5273 
5275  &srb,
5276  buffer,
5277  length,
5278  TRUE);
5279 
5280  if (!NT_SUCCESS(status)) {
5281  DebugPrint((1,
5282  "Cdrom.ScanForSpecial: Setting density code on Toshiba failed [%x]\n",
5283  status));
5284  }
5285 
5286  deviceExtension->ClassError = ToshibaProcessError;
5287 
5288  ExFreePool(buffer);
5289 
5290  }
5291 
5292  //
5293  // Determine special CD-DA requirements.
5294  //
5295 
5296  if (RtlCompareMemory( InquiryData->VendorId,"PLEXTOR",7) == 7) {
5297  cdData->XAFlags |= PLEXTOR_CDDA;
5298  } else if (RtlCompareMemory ( InquiryData->VendorId,"NEC",3) == 3) {
5299  cdData->XAFlags |= NEC_CDDA;
5300  }
5301 
5302  return;
5303 }
5304 
5305 VOID
5306 NTAPI
5310  NTSTATUS *Status,
5311  BOOLEAN *Retry
5312  )
5313 /*++
5314 
5315 Routine Description:
5316 
5317  This routine checks the type of error. If the error indicates CD-ROM the
5318  CD-ROM needs to be reinitialized then a Mode sense command is sent to the
5319  device. This command disables read-ahead for the device.
5320 
5321 Arguments:
5322 
5323  DeviceObject - Supplies a pointer to the device object.
5324 
5325  Srb - Supplies a pointer to the failing Srb.
5326 
5327  Status - Not used.
5328 
5329  Retry - Not used.
5330 
5331 Return Value:
5332 
5333  None.
5334 
5335 --*/
5336 
5337 {
5338  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
5339  PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
5340  LARGE_INTEGER largeInt;
5341  PUCHAR modePage;
5342  PIO_STACK_LOCATION irpStack;
5343  PIRP irp;
5344  PSCSI_REQUEST_BLOCK srb;
5346  PCDB cdb;
5347  ULONG alignment;
5348 
5351 
5352  largeInt.QuadPart = (LONGLONG) 1;
5353 
5354  //
5355  // Check the status. The initialization command only needs to be sent
5356  // if UNIT ATTENTION is returned.
5357  //
5358 
5359  if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) {
5360 
5361  //
5362  // The drive does not require reinitialization.
5363  //
5364 
5365  return;
5366  }
5367 
5368  //
5369  // Found a bad HITACHI cd-rom. These devices do not work with PIO
5370  // adapters when read-ahead is enabled. Read-ahead is disabled by
5371  // a mode select command. The mode select page code is zero and the
5372  // length is 6 bytes. All of the other bytes should be zero.
5373  //
5374 
5375 
5376  if ((senseBuffer->SenseKey & 0xf) == SCSI_SENSE_UNIT_ATTENTION) {
5377 
5378  DebugPrint((1, "HitachiProcessError: Reinitializing the CD-ROM.\n"));
5379 
5380  //
5381  // Send the special mode select command to disable read-ahead
5382  // on the CD-ROM reader.
5383  //
5384 
5385  alignment = DeviceObject->AlignmentRequirement ?
5387 
5389  NonPagedPool,
5390  sizeof(COMPLETION_CONTEXT) + HITACHI_MODE_DATA_SIZE + alignment
5391  );
5392 
5393  if (context == NULL) {
5394 
5395  //
5396  // If there is not enough memory to fulfill this request,
5397  // simply return. A subsequent retry will fail and another
5398  // chance to start the unit.
5399  //
5400 
5401  return;
5402  }
5403 
5404  context->DeviceObject = DeviceObject;
5405  srb = &context->Srb;
5406 
5408 
5409  //
5410  // Write length to SRB.
5411  //
5412 
5414 
5415  //
5416  // Set up SCSI bus address.
5417  //
5418 
5419  srb->PathId = deviceExtension->PathId;
5420  srb->TargetId = deviceExtension->TargetId;
5421  srb->Lun = deviceExtension->Lun;
5422 
5424  srb->TimeOutValue = deviceExtension->TimeOutValue;
5425 
5426  //
5427  // Set the transfer length.
5428  //
5429 
5432 
5433  //
5434  // The data buffer must be aligned.
5435  //
5436 
5437  srb->DataBuffer = (PVOID) (((ULONG_PTR) (context + 1) + (alignment - 1)) &
5438  ~(alignment - 1));
5439 
5440 
5441  //
5442  // Build the HITACHI read-ahead mode select CDB.
5443  //
5444 
5445  srb->CdbLength = 6;
5446  cdb = (PCDB)srb->Cdb;
5447  cdb->MODE_SENSE.LogicalUnitNumber = srb->Lun;
5448  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SELECT;
5449  cdb->MODE_SENSE.AllocationLength = HITACHI_MODE_DATA_SIZE;
5450 
5451  //
5452  // Initialize the mode sense data.
5453  //
5454 
5455  modePage = srb->DataBuffer;
5456 
5458 
5459  //
5460  // Set the page length field to 6.
5461  //
5462 
5463  modePage[5] = 6;
5464 
5465  //
5466  // Build the asynchronous request to be sent to the port driver.
5467  //
5468 
5470  DeviceObject,
5471  srb->DataBuffer,
5472  srb->DataTransferLength,
5473  &largeInt,
5474  NULL);
5475 
5478  context,
5479  TRUE,
5480  TRUE,
5481  TRUE);
5482 
5483  irpStack = IoGetNextIrpStackLocation(irp);
5484 
5485  irpStack->MajorFunction = IRP_MJ_SCSI;
5486 
5487  srb->OriginalRequest = irp;
5488 
5489  //
5490  // Save SRB address in next stack for port driver.
5491  //
5492 
5493  irpStack->Parameters.Scsi.Srb = (PVOID)srb;
5494 
5495  //
5496  // Set up IRP Address.
5497  //
5498 
5499  (VOID)IoCallDriver(deviceExtension->PortDeviceObject, irp);
5500 
5501  }
5502 }
5503 
5504 NTSTATUS
5505 NTAPI
5508  PIRP Irp,
5509  PVOID Context
5510  )
5511 
5512 /*++
5513 
5514 Routine Description:
5515 
5516  Completion routine for the ClassError routine to handle older Toshiba units
5517  that require setting the density code.
5518 
5519 Arguments:
5520 
5521  DeviceObject - Supplies a pointer to the device object.
5522 
5523  Irp - Pointer to irp created to set the density code.
5524 
5525  Context - Supplies a pointer to the Mode Select Srb.
5526 
5527 
5528 Return Value:
5529 
5530  STATUS_MORE_PROCESSING_REQUIRED
5531 
5532 --*/
5533 
5534 {
5535 
5537 
5538  //
5539  // Check for a frozen queue.
5540  //
5541 
5542  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
5543 
5544  //
5545  // Unfreeze the queue getting the device object from the context.
5546  //
5547 
5549  }
5550 
5551  //
5552  // Free all of the allocations.
5553  //
5554 
5555  ExFreePool(srb->DataBuffer);
5556  ExFreePool(srb);
5557  IoFreeMdl(Irp->MdlAddress);
5558  IoFreeIrp(Irp);
5559 
5560  //
5561  // Indicate the I/O system should stop processing the Irp completion.
5562  //
5563 
5565 }
5566 
5567 VOID
5568 NTAPI