ReactOS  0.4.14-dev-114-gc8cbd56
disk.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/disk/disk.c
5  * PURPOSE: Disk class driver
6  * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
7  */
8 
9 #include <ntddk.h>
10 #include <ntdddisk.h>
11 #include <scsi.h>
12 #include <ntddscsi.h>
13 #include <mountdev.h>
14 #include <mountmgr.h>
15 #include <ntiologc.h>
16 #include <include/class2.h>
17 #include <stdio.h>
18 
19 #define NDEBUG
20 #include <debug.h>
21 
22 
23 #ifdef POOL_TAGGING
24 #ifdef ExAllocatePool
25 #undef ExAllocatePool
26 #endif
27 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'DscS')
28 #endif
29 
30 typedef enum {
35 
36 //
37 // Disk device data
38 //
39 
40 typedef struct _DISK_DATA {
41 
42  //
43  // Partition chain
44  //
45 
47 
48  //
49  // Disk signature (from MBR)
50  //
51 
53 
54  //
55  // MBR checksum
56  //
57 
59 
60  //
61  // Number of hidden sectors for BPB.
62  //
63 
65 
66  //
67  // Partition number of this device object
68  //
69  // This field is set during driver initialization or when the partition
70  // is created to identify a partition to the system.
71  //
72 
74 
75  //
76  // This field is the ordinal of a partition as it appears on a disk.
77  //
78 
80 
81  //
82  // Partition type of this device object
83  //
84  // This field is set by:
85  //
86  // 1) Initially set according to the partition list entry partition
87  // type returned by IoReadPartitionTable.
88  //
89  // 2) Subsequently set by the IOCTL_DISK_SET_PARTITION_INFORMATION
90  // I/O control function when IoSetPartitionInformation function
91  // successfully updates the partition type on the disk.
92  //
93 
95 
96  //
97  // Boot indicator - indicates whether this partition is a bootable (active)
98  // partition for this device
99  //
100  // This field is set according to the partition list entry boot indicator
101  // returned by IoReadPartitionTable.
102  //
103 
105 
106  //
107  // DriveNotReady - indicates that the this device is currently not ready
108  // because there is no media in the device.
109  //
110 
112 
113  //
114  // State of PartitionList initialization
115  //
116 
118 
119 #ifdef __REACTOS__
120  //
121  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
122  // for removable devices and avoid an infinite recursive loop between
123  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
124  //
125  ULONG UpdateRemovableGeometryCount;
126 #endif
127 
129 
130 //
131 // Define a general structure of identifying disk controllers with bad
132 // hardware.
133 //
134 
142 
144  { "TOSHIBA MK538FB 60", TRUE, FALSE, FALSE, FALSE },
145  { "CONNER CP3500", FALSE, TRUE, FALSE, FALSE },
146  { "OLIVETTICP3500", FALSE, TRUE, FALSE, FALSE },
147  { "SyQuest SQ5110 CHC", TRUE, TRUE, FALSE, FALSE },
148  { "SEAGATE ST41601N 0102", FALSE, TRUE, FALSE, FALSE },
149  { "SEAGATE ST3655N", FALSE, FALSE, FALSE, TRUE },
150  { "SEAGATE ST3390N", FALSE, FALSE, FALSE, TRUE },
151  { "SEAGATE ST12550N", FALSE, FALSE, FALSE, TRUE },
152  { "SEAGATE ST32430N", FALSE, FALSE, FALSE, TRUE },
153  { "SEAGATE ST31230N", FALSE, FALSE, FALSE, TRUE },
154  { "SEAGATE ST15230N", FALSE, FALSE, FALSE, TRUE },
155  { "FUJITSU M2652S-512", TRUE, FALSE, FALSE, FALSE },
156  { "MAXTOR MXT-540SL I1.2", TRUE, FALSE, FALSE, FALSE },
157  { "COMPAQ PD-1", FALSE, TRUE, FALSE, FALSE }
158 };
159 
160 
161 #define NUMBER_OF_BAD_CONTROLLERS (sizeof(ScsiDiskBadControllers) / sizeof(BAD_CONTROLLER_INFORMATION))
162 #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA)
163 
164 #define MODE_DATA_SIZE 192
165 #define VALUE_BUFFER_SIZE 2048
166 #define SCSI_DISK_TIMEOUT 10
167 #define PARTITION0_LIST_SIZE 4
168 
169 
170 NTSTATUS
171 NTAPI
175  );
176 
177 BOOLEAN
178 NTAPI
180  IN PINQUIRYDATA InquiryData
181  );
182 
183 BOOLEAN
184 NTAPI
186  IN PDRIVER_OBJECT DriveObject,
189  IN PDEVICE_OBJECT PortDeviceObject,
191  );
192 
193 NTSTATUS
194 NTAPI
197  IN PIRP Irp
198  );
199 
200 NTSTATUS
201 NTAPI
204  IN PIRP Irp
205  );
206 
207 NTSTATUS
208 NTAPI
211  IN PIRP Irp
212  );
213 
214 VOID
215 NTAPI
219  NTSTATUS *Status,
220  BOOLEAN *Retry
221  );
222 
223 NTSTATUS
224 NTAPI
227  IN PIRP Irp
228  );
229 
230 VOID
231 NTAPI
234  IN PSCSI_INQUIRY_DATA LunInfo
235  );
236 
237 BOOLEAN
238 NTAPI
241  IN PCHAR ModeSelectBuffer,
242  IN ULONG Length,
243  IN BOOLEAN SavePage
244  );
245 
246 BOOLEAN
247 NTAPI
250  );
251 
252 BOOLEAN
253 NTAPI
255  IN PDEVICE_EXTENSION DeviceExtension,
256  OUT PULONG Checksum
257  );
258 
259 BOOLEAN
260 NTAPI
262  IN PDEVICE_EXTENSION DeviceExtension,
263  HANDLE BusKey,
264  PULONG DiskNumber
265  );
266 
267 VOID
268 NTAPI
270  IN PDEVICE_EXTENSION DeviceExtension
271  );
272 
273 NTSTATUS
274 NTAPI
277  IN PIRP Irp
278  );
279 
280 NTSTATUS
281 NTAPI
285  IN PDEVICE_OBJECT PortDeviceObject,
288  IN PIO_SCSI_CAPABILITIES PortCapabilities,
289  IN PSCSI_INQUIRY_DATA LunInfo,
290  IN PCLASS_INIT_DATA InitData
291  );
292 
293 NTSTATUS
294 NTAPI
298  );
299 
300 VOID
301 NTAPI
304  IN PIRP Irp
305  );
306 
307 VOID
308 NTAPI
311  PSCSI_INQUIRY_DATA LunInfo,
312  PIO_SCSI_CAPABILITIES PortCapabilities
313  );
314 
315 VOID
316 NTAPI
319  );
320 
321 NTSTATUS
322 NTAPI
324  PIRP Irp);
325 
326 #ifdef ALLOC_PRAGMA
327 #pragma alloc_text(PAGE, DriverEntry)
328 #pragma alloc_text(PAGE, FindScsiDisks)
329 #pragma alloc_text(PAGE, CreateDiskDeviceObject)
330 #pragma alloc_text(PAGE, CalculateMbrCheckSum)
331 #pragma alloc_text(PAGE, EnumerateBusKey)
332 #pragma alloc_text(PAGE, UpdateGeometry)
333 #pragma alloc_text(PAGE, IsFloppyDevice)
334 #pragma alloc_text(PAGE, ScanForSpecial)
335 #pragma alloc_text(PAGE, ScsiDiskDeviceControl)
336 #pragma alloc_text(PAGE, ScsiDiskModeSelect)
337 #endif
338 
339 
340 NTSTATUS
341 NTAPI
345  )
346 
347 /*++
348 
349 Routine Description:
350 
351  This routine initializes the SCSI hard disk class driver.
352 
353 Arguments:
354 
355  DriverObject - Pointer to driver object created by system.
356 
357  RegistryPath - Pointer to the name of the services node for this driver.
358 
359 Return Value:
360 
361  The function value is the final status from the initialization operation.
362 
363 --*/
364 
365 {
367 
368  //
369  // Zero InitData
370  //
371 
373 
374  //
375  // Set sizes
376  //
377 
378  InitializationData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
379  InitializationData.DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
380 
382  InitializationData.DeviceCharacteristics = 0;
383 
384  //
385  // Set entry points
386  //
387 
389  InitializationData.ClassReadWriteVerification = ScsiDiskReadWriteVerification;
390  InitializationData.ClassFindDevices = FindScsiDisks;
391  InitializationData.ClassFindDeviceCallBack = ScsiDiskDeviceVerification;
392  InitializationData.ClassDeviceControl = ScsiDiskDeviceControl;
393  InitializationData.ClassShutdownFlush = ScsiDiskShutdownFlush;
394  InitializationData.ClassCreateClose = NULL;
395 
396  //
397  // Call the class init routine
398  //
399 
401 
402 } // end DriverEntry()
403 
404 
405 
406 BOOLEAN
407 NTAPI
409  IN PINQUIRYDATA InquiryData
410  )
411 
412 /*++
413 
414 Routine Description:
415 
416  This routine checks InquiryData for the correct device type and qualifier.
417 
418 Arguments:
419 
420  InquiryData - Pointer to the inquiry data for the device in question.
421 
422 Return Value:
423 
424  True is returned if the correct device type is found.
425 
426 --*/
427 {
428 
429  if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
430  (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
431  InquiryData->DeviceTypeQualifier == 0) {
432 
433  return TRUE;
434 
435  } else {
436  return FALSE;
437  }
438 }
439 
440 
441 BOOLEAN
442 NTAPI
447  IN PDEVICE_OBJECT PortDeviceObject,
449  )
450 
451 /*++
452 
453 Routine Description:
454 
455  This routine gets a port drivers capabilities, obtains the
456  inquiry data, searches the SCSI bus for the port driver and creates
457  the device objects for the disks found.
458 
459 Arguments:
460 
461  DriverObject - Pointer to driver object created by system.
462 
463  PortDeviceObject - Device object use to send requests to port driver.
464 
465  PortNumber - Number for port driver. Used to pass on to
466  CreateDiskDeviceObjects() and create device objects.
467 
468 Return Value:
469 
470  True is returned if one disk was found and successfully created.
471 
472 --*/
473 
474 {
475  PIO_SCSI_CAPABILITIES portCapabilities;
476  PULONG diskCount;
477  PCONFIGURATION_INFORMATION configurationInformation;
478  PCHAR buffer;
479  PSCSI_INQUIRY_DATA lunInfo;
480  PSCSI_ADAPTER_BUS_INFO adapterInfo;
481  PINQUIRYDATA inquiryData;
482  ULONG scsiBus;
483  ULONG adapterDisk;
485  BOOLEAN foundOne = FALSE;
486 
487  PAGED_CODE();
488 
489  //
490  // Call port driver to get adapter capabilities.
491  //
492 
493  status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
494 
495  if (!NT_SUCCESS(status)) {
496  DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
497  return(FALSE);
498  }
499 
500  //
501  // Call port driver to get inquiry information to find disks.
502  //
503 
505 
506  if (!NT_SUCCESS(status)) {
507  DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
508  return(FALSE);
509  }
510 
511  //
512  // Do a quick scan of the devices on this adapter to determine how many
513  // disks are on this adapter. This is used to determine the number of
514  // SRB zone elements to allocate.
515  //
516 
517  adapterInfo = (PVOID) buffer;
518 
519  adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo);
520 
521  //
522  // Allocate a zone of SRB for disks on this adapter.
523  //
524 
525  if (adapterDisk == 0) {
526 
527  //
528  // No free disks were found.
529  //
530 
531  return(FALSE);
532  }
533 
534  //
535  // Get the number of disks already initialized.
536  //
537 
538  configurationInformation = IoGetConfigurationInformation();
539  diskCount = &configurationInformation->DiskCount;
540 
541  //
542  // For each SCSI bus this adapter supports ...
543  //
544 
545  for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) {
546 
547  //
548  // Get the SCSI bus scan data for this bus.
549  //
550 
551  lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
552 
553  //
554  // Search list for unclaimed disk devices.
555  //
556 
557  while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
558 
559  inquiryData = (PVOID)lunInfo->InquiryData;
560 
561  if (((inquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
562  (inquiryData->DeviceType == OPTICAL_DEVICE)) &&
563  inquiryData->DeviceTypeQualifier == 0 &&
564  (!lunInfo->DeviceClaimed)) {
565 
566  DebugPrint((1,
567  "FindScsiDevices: Vendor string is %.24s\n",
568  inquiryData->VendorId));
569 
570  //
571  // Create device objects for disk
572  //
573 
575  RegistryPath,
576  PortDeviceObject,
577  PortNumber,
578  diskCount,
579  portCapabilities,
580  lunInfo,
582 
583  if (NT_SUCCESS(status)) {
584 
585  //
586  // Increment system disk device count.
587  //
588 
589  (*diskCount)++;
590  foundOne = TRUE;
591 
592  }
593  }
594 
595  //
596  // Get next LunInfo.
597  //
598 
599  if (lunInfo->NextInquiryDataOffset == 0) {
600  break;
601  }
602 
603  lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
604 
605  }
606  }
607 
608  //
609  // Buffer is allocated by ScsiClassGetInquiryData and must be free returning.
610  //
611 
613 
614  return(foundOne);
615 
616 } // end FindScsiDisks()
617 
618 
619 NTSTATUS
620 NTAPI
624  IN PDEVICE_OBJECT PortDeviceObject,
627  IN PIO_SCSI_CAPABILITIES PortCapabilities,
628  IN PSCSI_INQUIRY_DATA LunInfo,
629  IN PCLASS_INIT_DATA InitData
630  )
631 
632 /*++
633 
634 Routine Description:
635 
636  This routine creates an object for the physical device and then searches
637  the device for partitions and creates an object for each partition.
638 
639 Arguments:
640 
641  DriverObject - Pointer to driver object created by system.
642 
643  PortDeviceObject - Miniport device object.
644 
645  PortNumber - port number. Used in creating disk objects.
646 
647  DeviceCount - Number of previously installed devices.
648 
649  PortCapabilities - Capabilities of this SCSI port.
650 
651  LunInfo - LUN specific information.
652 
653 Return Value:
654 
655  NTSTATUS
656 
657 --*/
658 {
659  CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
660  STRING ntNameString;
661  UNICODE_STRING ntUnicodeString;
662  OBJECT_ATTRIBUTES objectAttributes;
663  HANDLE handle;
665  PDEVICE_OBJECT deviceObject = NULL;
666  //PDEVICE_OBJECT physicalDevice;
667  PDISK_GEOMETRY_EX diskGeometry = NULL;
668  PDEVICE_EXTENSION deviceExtension = NULL;
669  //PDEVICE_EXTENSION physicalDeviceExtension;
670  UCHAR pathId = LunInfo->PathId;
671  UCHAR targetId = LunInfo->TargetId;
672  UCHAR lun = LunInfo->Lun;
673  //BOOLEAN writeCache;
674  PVOID senseData = NULL;
675  //ULONG srbFlags;
676  ULONG timeOut = 0;
677  BOOLEAN srbListInitialized = FALSE;
678 
679 
680  PAGED_CODE();
681 
682  //
683  // Set up an object directory to contain the objects for this
684  // device and all its partitions.
685  //
686 
687  sprintf(ntNameBuffer,
688  "\\Device\\Harddisk%lu",
689  *DeviceCount);
690 
691  RtlInitString(&ntNameString,
692  ntNameBuffer);
693 
694  status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
695  &ntNameString,
696  TRUE);
697 
698  if (!NT_SUCCESS(status)) {
699  return(status);
700  }
701 
702  InitializeObjectAttributes(&objectAttributes,
703  &ntUnicodeString,
705  NULL,
706  NULL);
707 
710  &objectAttributes);
711 
712  RtlFreeUnicodeString(&ntUnicodeString);
713 
714  if (!NT_SUCCESS(status)) {
715 
716  DebugPrint((1,
717  "CreateDiskDeviceObjects: Could not create directory %s\n",
718  ntNameBuffer));
719 
720  return(status);
721  }
722 
723  //
724  // Claim the device.
725  //
726 
727  status = ScsiClassClaimDevice(PortDeviceObject,
728  LunInfo,
729  FALSE,
730  &PortDeviceObject);
731 
732  if (!NT_SUCCESS(status)) {
734  ZwClose(handle);
735  return status;
736  }
737 
738  //
739  // Create a device object for this device. Each physical disk will
740  // have at least one device object. The required device object
741  // describes the entire device. Its directory path is
742  // \Device\HarddiskN\Partition0, where N = device number.
743  //
744 
745  sprintf(ntNameBuffer,
746  "\\Device\\Harddisk%lu\\Partition0",
747  *DeviceCount);
748 
749 
751  ntNameBuffer,
752  NULL,
753  &deviceObject,
754  InitData);
755 
756  if (!NT_SUCCESS(status)) {
757 
758  DebugPrint((1,
759  "CreateDiskDeviceObjects: Can not create device object %s\n",
760  ntNameBuffer));
761 
762  goto CreateDiskDeviceObjectsExit;
763  }
764 
765  //
766  // Indicate that IRPs should include MDLs for data transfers.
767  //
768 
769  deviceObject->Flags |= DO_DIRECT_IO;
770 
771  //
772  // Check if this is during initialization. If not indicate that
773  // system initialization already took place and this disk is ready
774  // to be accessed.
775  //
776 
777  if (!RegistryPath) {
778  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
779  }
780 
781  //
782  // Check for removable media support.
783  //
784 
785  if (((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) {
786  deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
787  }
788 
789  //
790  // Set up required stack size in device object.
791  //
792 
793  deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
794 
795  deviceExtension = deviceObject->DeviceExtension;
796 
797  //
798  // Allocate spinlock for split request completion.
799  //
800 
801  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
802 
803  //
804  // Initialize lock count to zero. The lock count is used to
805  // disable the ejection mechanism on devices that support
806  // removable media. Only the lock count in the physical
807  // device extension is used.
808  //
809 
810  deviceExtension->LockCount = 0;
811 
812  //
813  // Save system disk number.
814  //
815 
816  deviceExtension->DeviceNumber = *DeviceCount;
817 
818  //
819  // Copy port device object pointer to the device extension.
820  //
821 
822  deviceExtension->PortDeviceObject = PortDeviceObject;
823 
824  //
825  // Set the alignment requirements for the device based on the
826  // host adapter requirements
827  //
828 
829  if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
830  deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
831  }
832 
833  //
834  // This is the physical device object.
835  //
836 
837  //physicalDevice = deviceObject;
838  //physicalDeviceExtension = deviceExtension;
839 
840  //
841  // Save address of port driver capabilities.
842  //
843 
844  deviceExtension->PortCapabilities = PortCapabilities;
845 
846  //
847  // Build the lookaside list for srb's for the physical disk. Should only
848  // need a couple.
849  //
850 
851  ScsiClassInitializeSrbLookasideList(deviceExtension,
853 
854  srbListInitialized = TRUE;
855 
856  //
857  // Initialize the srb flags.
858  //
859 
860  if (((PINQUIRYDATA)LunInfo->InquiryData)->CommandQueue &&
861  PortCapabilities->TaggedQueuing) {
862 
863  deviceExtension->SrbFlags = SRB_FLAGS_QUEUE_ACTION_ENABLE;
864 
865  } else {
866 
867  deviceExtension->SrbFlags = 0;
868 
869  }
870 
871  //
872  // Allow queued requests if this is not removable media.
873  //
874 
875  if (!(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
876 
877  deviceExtension->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE;
878 
879  }
880 
881  //
882  // Look for controller that require special flags.
883  //
884 
885  ScanForSpecial(deviceObject,
886  LunInfo,
887  PortCapabilities);
888 
889  //srbFlags = deviceExtension->SrbFlags;
890 
891  //
892  // Allocate buffer for drive geometry.
893  //
894 
895  diskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY_EX));
896 
897  if (diskGeometry == NULL) {
898 
899  DebugPrint((1,
900  "CreateDiskDeviceObjects: Can not allocate disk geometry buffer\n"));
902  goto CreateDiskDeviceObjectsExit;
903  }
904 
905  deviceExtension->DiskGeometry = diskGeometry;
906 
907  //
908  // Allocate request sense buffer.
909  //
910 
912 
913  if (senseData == NULL) {
914 
915  //
916  // The buffer can not be allocated.
917  //
918 
919  DebugPrint((1,
920  "CreateDiskDeviceObjects: Can not allocate request sense buffer\n"));
921 
923  goto CreateDiskDeviceObjectsExit;
924  }
925 
926  //
927  // Set the sense data pointer in the device extension.
928  //
929 
930  deviceExtension->SenseData = senseData;
931 
932  //
933  // Physical device object will describe the entire
934  // device, starting at byte offset 0.
935  //
936 
937  deviceExtension->StartingOffset.QuadPart = (LONGLONG)(0);
938 
939  //
940  // TargetId/LUN describes a device location on the SCSI bus.
941  // This information comes from the inquiry buffer.
942  //
943 
944  deviceExtension->PortNumber = (UCHAR)PortNumber;
945  deviceExtension->PathId = pathId;
946  deviceExtension->TargetId = targetId;
947  deviceExtension->Lun = lun;
948 
949  //
950  // Set timeout value in seconds.
951  //
952 
954  if (timeOut) {
955  deviceExtension->TimeOutValue = timeOut;
956  } else {
957  deviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
958  }
959 
960  //
961  // Back pointer to device object.
962  //
963 
964  deviceExtension->DeviceObject = deviceObject;
965 
966  //
967  // If this is a removable device, then make sure it is not a floppy.
968  // Perform a mode sense command to determine the media type. Note
969  // IsFloppyDevice also checks for write cache enabled.
970  //
971 
972 #if 0
973  if (IsFloppyDevice(deviceObject) && deviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
974  (((PINQUIRYDATA)LunInfo->InquiryData)->DeviceType == DIRECT_ACCESS_DEVICE)) {
975 
977  goto CreateDiskDeviceObjectsExit;
978  }
979 #endif
980 
981  DisableWriteCache(deviceObject,LunInfo);
982 
983  //writeCache = deviceExtension->DeviceFlags & DEV_WRITE_CACHE;
984 
985  //
986  // NOTE: At this point one device object has been successfully created.
987  // from here on out return success.
988  //
989 
990  //
991  // Do READ CAPACITY. This SCSI command
992  // returns the number of bytes on a device.
993  // Device extension is updated with device size.
994  //
995 
996  status = ScsiClassReadDriveCapacity(deviceObject);
997 
998  //
999  // If the read capacity failed then just return, unless this is a
1000  // removable disk where a device object partition needs to be created.
1001  //
1002 
1003  if (!NT_SUCCESS(status) &&
1004  !(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
1005 
1006  DebugPrint((1,
1007  "CreateDiskDeviceObjects: Can't read capacity for device %s\n",
1008  ntNameBuffer));
1009 
1010  return(STATUS_SUCCESS);
1011 
1012  } else {
1013 
1014  //
1015  // Make sure the volume verification bit is off so that
1016  // IoReadPartitionTable will work.
1017  //
1018 
1019  deviceObject->Flags &= ~DO_VERIFY_VOLUME;
1020  }
1021 
1023 
1024  if (NT_SUCCESS(status))
1025  return STATUS_SUCCESS;
1026 
1027 
1028 CreateDiskDeviceObjectsExit:
1029 
1030  //
1031  // Release the device since an error occurred.
1032  //
1033 
1034  ScsiClassClaimDevice(PortDeviceObject,
1035  LunInfo,
1036  TRUE,
1037  NULL);
1038 
1039  if (diskGeometry != NULL) {
1040  ExFreePool(diskGeometry);
1041  }
1042 
1043  if (senseData != NULL) {
1044  ExFreePool(senseData);
1045  }
1046 
1047  if (deviceObject != NULL) {
1048 
1049  if (srbListInitialized) {
1050  ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
1051  }
1052 
1053  IoDeleteDevice(deviceObject);
1054  }
1055 
1056  //
1057  // Delete directory and return.
1058  //
1059 
1060  if (!NT_SUCCESS(status)) {
1062  }
1063 
1064  ZwClose(handle);
1065 
1066  return(status);
1067 
1068 } // end CreateDiskDeviceObjects()
1069 
1070 
1071 VOID
1072 NTAPI
1075  )
1076 
1077 /*++
1078 
1079 Routine Description:
1080 
1081  This routine reports the creation of a disk device object to the
1082  MountMgr to fake PnP.
1083 
1084 Arguments:
1085 
1086  DiskDeviceObject - Pointer to the created disk device.
1087 
1088 Return Value:
1089 
1090  VOID
1091 
1092 --*/
1093 {
1094  NTSTATUS status;
1095  UNICODE_STRING mountMgrDevice;
1096  PDEVICE_OBJECT deviceObject;
1097  PFILE_OBJECT fileObject;
1098  PMOUNTMGR_TARGET_NAME mountTarget;
1099  ULONG diskLen;
1100  PDEVICE_EXTENSION deviceExtension;
1101  PIRP irp;
1102  KEVENT event;
1103  IO_STATUS_BLOCK ioStatus;
1104 
1105  //
1106  // First, get MountMgr DeviceObject.
1107  //
1108 
1109  RtlInitUnicodeString(&mountMgrDevice, MOUNTMGR_DEVICE_NAME);
1111  &fileObject, &deviceObject);
1112 
1113  if (!NT_SUCCESS(status)) {
1114 
1115  DebugPrint((1,
1116  "ReportToMountMgr: Can't get MountMgr pointers %lx\n",
1117  status));
1118 
1119  return;
1120  }
1121 
1122  deviceExtension = DiskDeviceObject->DeviceExtension;
1123  diskLen = deviceExtension->DeviceName.Length;
1124 
1125  //
1126  // Allocate input buffer to report our partition device.
1127  //
1128 
1129  mountTarget = ExAllocatePool(NonPagedPool,
1130  sizeof(MOUNTMGR_TARGET_NAME) + diskLen);
1131 
1132  if (!mountTarget) {
1133 
1134  DebugPrint((1,
1135  "ReportToMountMgr: Allocation of mountTarget failed\n"));
1136 
1137  ObDereferenceObject(fileObject);
1138  return;
1139  }
1140 
1141  mountTarget->DeviceNameLength = diskLen;
1142  RtlCopyMemory(mountTarget->DeviceName, deviceExtension->DeviceName.Buffer, diskLen);
1143 
1145 
1146  //
1147  // Build the IRP used to communicate with the MountMgr.
1148  //
1149 
1151  deviceObject,
1152  mountTarget,
1153  sizeof(MOUNTMGR_TARGET_NAME) + diskLen,
1154  NULL,
1155  0,
1156  FALSE,
1157  &event,
1158  &ioStatus);
1159 
1160  if (!irp) {
1161 
1162  DebugPrint((1,
1163  "ReportToMountMgr: Allocation of irp failed\n"));
1164 
1165  ExFreePool(mountTarget);
1166  ObDereferenceObject(fileObject);
1167  return;
1168  }
1169 
1170  //
1171  // Call the MountMgr.
1172  //
1173 
1174  status = IoCallDriver(deviceObject, irp);
1175 
1176  if (status == STATUS_PENDING) {
1178  status = ioStatus.Status;
1179  }
1180 
1181  //
1182  // We're done.
1183  //
1184 
1185  DPRINT1("Reported to the MountMgr: %lx\n", status);
1186 
1187  ExFreePool(mountTarget);
1188  ObDereferenceObject(fileObject);
1189 
1190  return;
1191 }
1192 
1193 
1194 NTSTATUS
1195 NTAPI
1199  )
1200 {
1201  CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
1202  ULONG partitionNumber = 0;
1203  NTSTATUS status;
1204  PDEVICE_OBJECT deviceObject = NULL;
1205  PDISK_GEOMETRY_EX diskGeometry = NULL;
1206  PDRIVE_LAYOUT_INFORMATION partitionList = NULL;
1207  PDEVICE_EXTENSION deviceExtension;
1208  PDEVICE_EXTENSION physicalDeviceExtension;
1209  PCLASS_INIT_DATA initData = NULL;
1210  PDISK_DATA diskData;
1211  PDISK_DATA physicalDiskData;
1212  ULONG bytesPerSector;
1213  UCHAR sectorShift;
1214  ULONG srbFlags;
1215  ULONG dmByteSkew = 0;
1216  PULONG dmSkew;
1217  BOOLEAN dmActive = FALSE;
1218  ULONG numberListElements = 0;
1219 
1220 
1221  //
1222  // Get physical device geometry information for partition table reads.
1223  //
1224 
1225  physicalDeviceExtension = PhysicalDeviceObject->DeviceExtension;
1226  diskGeometry = physicalDeviceExtension->DiskGeometry;
1227  bytesPerSector = diskGeometry->Geometry.BytesPerSector;
1228 
1229  //
1230  // Make sure sector size is not zero.
1231  //
1232 
1233  if (bytesPerSector == 0) {
1234 
1235  //
1236  // Default sector size for disk is 512.
1237  //
1238 
1239  bytesPerSector = diskGeometry->Geometry.BytesPerSector = 512;
1240  }
1241 
1242  sectorShift = physicalDeviceExtension->SectorShift;
1243 
1244  //
1245  // Set pointer to disk data area that follows device extension.
1246  //
1247 
1248  diskData = (PDISK_DATA)(physicalDeviceExtension + 1);
1249  diskData->PartitionListState = Initializing;
1250 
1251  //
1252  // Determine is DM Driver is loaded on an IDE drive that is
1253  // under control of Atapi - this could be either a crashdump or
1254  // an Atapi device is sharing the controller with an IDE disk.
1255  //
1256 
1258  physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector,
1259  (ULONG)0x54,
1260  (PVOID)&dmSkew);
1261 
1262  if (dmSkew) {
1263 
1264  //
1265  // Update the device extension, so that the call to IoReadPartitionTable
1266  // will get the correct information. Any I/O to this disk will have
1267  // to be skewed by *dmSkew sectors aka DMByteSkew.
1268  //
1269 
1270  physicalDeviceExtension->DMSkew = *dmSkew;
1271  physicalDeviceExtension->DMActive = TRUE;
1272  physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector;
1273 
1274  //
1275  // Save away the information that we need, since this deviceExtension will soon be
1276  // blown away.
1277  //
1278 
1279  dmActive = TRUE;
1280  dmByteSkew = physicalDeviceExtension->DMByteSkew;
1281 
1282  }
1283 
1284 #ifdef __REACTOS__
1285  //
1286  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
1287  // for removable devices and avoid an infinite recursive loop between
1288  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
1289  //
1290  diskData->UpdateRemovableGeometryCount = 0;
1291 #endif
1292 
1293  //
1294  // Create objects for all the partitions on the device.
1295  //
1296 
1298  physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector,
1299  TRUE,
1300  (PVOID)&partitionList);
1301 
1302  //
1303  // If the I/O read partition table failed and this is a removable device,
1304  // then fix up the partition list to make it look like there is one
1305  // zero length partition.
1306  //
1307  DPRINT("IoReadPartitionTable() status: 0x%08X\n", status);
1308  if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) &&
1309  PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1310 
1311  if (!NT_SUCCESS(status)) {
1312 
1313  //
1314  // Remember this disk is not ready.
1315  //
1316 
1317  diskData->DriveNotReady = TRUE;
1318 
1319  } else {
1320 
1321  //
1322  // Free the partition list allocated by IoReadPartitionTable.
1323  //
1324 
1325  ExFreePool(partitionList);
1326  }
1327 
1328  //
1329  // Allocate and zero a partition list.
1330  //
1331 
1332  partitionList = ExAllocatePool(NonPagedPool, sizeof(*partitionList));
1333 
1334 
1335  if (partitionList != NULL) {
1336 
1337  RtlZeroMemory( partitionList, sizeof( *partitionList ));
1338 
1339  //
1340  // Set the partition count to one and the status to success
1341  // so one device object will be created. Set the partition type
1342  // to a bogus value.
1343  //
1344 
1345  partitionList->PartitionCount = 1;
1346 
1348  }
1349  }
1350 
1351  if (NT_SUCCESS(status)) {
1352 
1353  //
1354  // Record disk signature.
1355  //
1356 
1357  diskData->Signature = partitionList->Signature;
1358 
1359  //
1360  // If disk signature is zero, then calculate the MBR checksum.
1361  //
1362 
1363  if (!diskData->Signature) {
1364 
1365  if (!CalculateMbrCheckSum(physicalDeviceExtension,
1366  &diskData->MbrCheckSum)) {
1367 
1368  DebugPrint((1,
1369  "SCSIDISK: Can't calculate MBR checksum for disk %x\n",
1370  physicalDeviceExtension->DeviceNumber));
1371  } else {
1372 
1373  DebugPrint((2,
1374  "SCSIDISK: MBR checksum for disk %x is %x\n",
1375  physicalDeviceExtension->DeviceNumber,
1376  diskData->MbrCheckSum));
1377  }
1378  }
1379 
1380  //
1381  // Check the registry and determine if the BIOS knew about this drive. If
1382  // it did then update the geometry with the BIOS information.
1383  //
1384 
1385  UpdateGeometry(physicalDeviceExtension);
1386 
1387  srbFlags = physicalDeviceExtension->SrbFlags;
1388 
1389  initData = ExAllocatePool(NonPagedPool, sizeof(CLASS_INIT_DATA));
1390  if (!initData)
1391  {
1392  DebugPrint((1,
1393  "Disk.CreatePartitionDeviceObjects - Allocation of initData failed\n"));
1394 
1396  goto CreatePartitionDeviceObjectsExit;
1397  }
1398 
1399  RtlZeroMemory(initData, sizeof(CLASS_INIT_DATA));
1400 
1401  initData->InitializationDataSize = sizeof(CLASS_INIT_DATA);
1403  initData->DeviceType = FILE_DEVICE_DISK;
1404  initData->DeviceCharacteristics = PhysicalDeviceObject->Characteristics;
1405  initData->ClassError = physicalDeviceExtension->ClassError;
1406  initData->ClassReadWriteVerification = physicalDeviceExtension->ClassReadWriteVerification;
1407  initData->ClassFindDevices = physicalDeviceExtension->ClassFindDevices;
1408  initData->ClassDeviceControl = physicalDeviceExtension->ClassDeviceControl;
1409  initData->ClassShutdownFlush = physicalDeviceExtension->ClassShutdownFlush;
1410  initData->ClassCreateClose = physicalDeviceExtension->ClassCreateClose;
1411  initData->ClassStartIo = physicalDeviceExtension->ClassStartIo;
1412 
1413  //
1414  // Create device objects for the device partitions (if any).
1415  // PartitionCount includes physical device partition 0,
1416  // so only one partition means no objects to create.
1417  //
1418 
1419  DebugPrint((2,
1420  "CreateDiskDeviceObjects: Number of partitions is %d\n",
1421  partitionList->PartitionCount));
1422 
1423  for (partitionNumber = 0; partitionNumber <
1424  partitionList->PartitionCount; partitionNumber++) {
1425 
1426  //
1427  // Create partition object and set up partition parameters.
1428  //
1429 
1430  sprintf(ntNameBuffer,
1431  "\\Device\\Harddisk%lu\\Partition%lu",
1432  physicalDeviceExtension->DeviceNumber,
1433  partitionNumber + 1);
1434 
1435  DebugPrint((2,
1436  "CreateDiskDeviceObjects: Create device object %s\n",
1437  ntNameBuffer));
1438 
1440  ntNameBuffer,
1442  &deviceObject,
1443  initData);
1444 
1445  if (!NT_SUCCESS(status)) {
1446 
1447  DebugPrint((1, "CreateDiskDeviceObjects: Can't create device object for %s\n", ntNameBuffer));
1448 
1449  break;
1450  }
1451 
1452  //
1453  // Set up device object fields.
1454  //
1455 
1456  deviceObject->Flags |= DO_DIRECT_IO;
1457 
1458  //
1459  // Check if this is during initialization. If not indicate that
1460  // system initialization already took place and this disk is ready
1461  // to be accessed.
1462  //
1463 
1464  if (!RegistryPath) {
1465  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1466  }
1467 
1468  deviceObject->StackSize = (CCHAR)physicalDeviceExtension->PortDeviceObject->StackSize + 1;
1469 
1470  //
1471  // Set up device extension fields.
1472  //
1473 
1474  deviceExtension = deviceObject->DeviceExtension;
1475 
1476  if (dmActive) {
1477 
1478  //
1479  // Restore any saved DM values.
1480  //
1481 
1482  deviceExtension->DMByteSkew = dmByteSkew;
1483  deviceExtension->DMSkew = *dmSkew;
1484  deviceExtension->DMActive = TRUE;
1485 
1486  }
1487 
1488  //
1489  // Link new device extension to previous disk data
1490  // to support dynamic partitioning.
1491  //
1492 
1493  diskData->NextPartition = deviceExtension;
1494 
1495  //
1496  // Get pointer to new disk data.
1497  //
1498 
1499  diskData = (PDISK_DATA)(deviceExtension + 1);
1500 
1501  //
1502  // Set next partition pointer to NULL in case this is the
1503  // last partition.
1504  //
1505 
1506  diskData->NextPartition = NULL;
1507 
1508  //
1509  // Allocate spinlock for zoning for split-request completion.
1510  //
1511 
1512  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
1513 
1514  //
1515  // Copy port device object pointer to device extension.
1516  //
1517 
1518  deviceExtension->PortDeviceObject = physicalDeviceExtension->PortDeviceObject;
1519 
1520  //
1521  // Set the alignment requirements for the device based on the
1522  // host adapter requirements
1523  //
1524 
1525  if (physicalDeviceExtension->PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
1526  deviceObject->AlignmentRequirement = physicalDeviceExtension->PortDeviceObject->AlignmentRequirement;
1527  }
1528 
1529 
1530  if (srbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
1531  numberListElements = 30;
1532  } else {
1533  numberListElements = 8;
1534  }
1535 
1536  //
1537  // Build the lookaside list for srb's for this partition based on
1538  // whether the adapter and disk can do tagged queueing.
1539  //
1540 
1541  ScsiClassInitializeSrbLookasideList(deviceExtension,
1542  numberListElements);
1543 
1544  deviceExtension->SrbFlags = srbFlags;
1545 
1546  //
1547  // Set the sense-data pointer in the device extension.
1548  //
1549 
1550  deviceExtension->SenseData = physicalDeviceExtension->SenseData;
1551  deviceExtension->PortCapabilities = physicalDeviceExtension->PortCapabilities;
1552  deviceExtension->DiskGeometry = diskGeometry;
1553  diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1;
1554  diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType;
1555  diskData->BootIndicator = partitionList->PartitionEntry[partitionNumber].BootIndicator;
1556 
1557  DebugPrint((2, "CreateDiskDeviceObjects: Partition type is %x\n",
1558  diskData->PartitionType));
1559 
1560  deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset;
1561  deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength;
1562  diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors;
1563  deviceExtension->PortNumber = physicalDeviceExtension->PortNumber;
1564  deviceExtension->PathId = physicalDeviceExtension->PathId;
1565  deviceExtension->TargetId = physicalDeviceExtension->TargetId;
1566  deviceExtension->Lun = physicalDeviceExtension->Lun;
1567 
1568  //
1569  // Check for removable media support.
1570  //
1571 
1572  if (PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1573  deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
1574  }
1575 
1576  //
1577  // Set timeout value in seconds.
1578  //
1579 
1580  deviceExtension->TimeOutValue = physicalDeviceExtension->TimeOutValue;
1581  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bytesPerSector;
1582  deviceExtension->SectorShift = sectorShift;
1583  deviceExtension->DeviceObject = deviceObject;
1584  deviceExtension->DeviceFlags |= physicalDeviceExtension->DeviceFlags;
1585 
1586  //
1587  // Now we're done, report to the MountMgr.
1588  // This is a HACK required to have the driver
1589  // handle the associated DosDevices.
1590  //
1591 
1592  ReportToMountMgr(deviceObject);
1593 
1594  } // end for (partitionNumber) ...
1595 
1596  //
1597  // Free the buffer allocated by reading the
1598  // partition table.
1599  //
1600 
1601  ExFreePool(partitionList);
1602 
1603  if (dmSkew) {
1604  ExFreePool(dmSkew);
1605  }
1606 
1607  } else {
1608 
1609 CreatePartitionDeviceObjectsExit:
1610 
1611  if (partitionList) {
1612  ExFreePool(partitionList);
1613  }
1614  if (initData) {
1615  ExFreePool(initData);
1616  }
1617 
1618  if (dmSkew) {
1619  ExFreePool(dmSkew);
1620  }
1621 
1622  return status;
1623 
1624  } // end if...else
1625 
1626 
1627  physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
1628  physicalDiskData->PartitionListState = Initialized;
1629 
1630  return(STATUS_SUCCESS);
1631 
1632 
1633 } // end CreatePartitionDeviceObjects()
1634 
1635 
1636 NTSTATUS
1637 NTAPI
1640  IN PIRP Irp
1641  )
1642 
1643 /*++
1644 
1645 Routine Description:
1646 
1647  I/O System entry for read and write requests to SCSI disks.
1648 
1649 Arguments:
1650 
1651  DeviceObject - Pointer to driver object created by system.
1652  Irp - IRP involved.
1653 
1654 Return Value:
1655 
1656  NT Status
1657 
1658 --*/
1659 
1660 {
1661  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1663  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1664  LARGE_INTEGER startingOffset;
1665 
1666  //
1667  // HACK: How can we end here with null sector size?!
1668  //
1669 
1670  if (deviceExtension->DiskGeometry->Geometry.BytesPerSector == 0) {
1671  DPRINT1("Hack! Received invalid sector size\n");
1672  deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512;
1673  }
1674 
1675  //
1676  // Verify parameters of this request.
1677  // Check that ending sector is within partition and
1678  // that number of bytes to transfer is a multiple of
1679  // the sector size.
1680  //
1681 
1682  startingOffset.QuadPart = (currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
1683  transferByteCount);
1684 
1685  if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) ||
1686  (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) {
1687 
1688  //
1689  // This error maybe caused by the fact that the drive is not ready.
1690  //
1691 
1692  if (((PDISK_DATA)(deviceExtension + 1))->DriveNotReady) {
1693 
1694  //
1695  // Flag this as a user error so that a popup is generated.
1696  //
1697 
1698  Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
1700 
1701  } else {
1702 
1703  //
1704  // Note fastfat depends on this parameter to determine when to
1705  // remount do to a sector size change.
1706  //
1707 
1708  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1709  }
1710 
1711  if (startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) {
1712  DPRINT1("Reading beyond partition end! startingOffset: %I64d, PartitionLength: %I64d\n", startingOffset.QuadPart, deviceExtension->PartitionLength.QuadPart);
1713  }
1714 
1715  if (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1)) {
1716  DPRINT1("Not reading sectors! TransferByteCount: %lu, BytesPerSector: %lu\n", transferByteCount, deviceExtension->DiskGeometry->Geometry.BytesPerSector);
1717  }
1718 
1719  if (Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) {
1720  DPRINT1("Failing due to device not ready!\n");
1721  }
1722 
1723  return STATUS_INVALID_PARAMETER;
1724  }
1725 
1726  return STATUS_SUCCESS;
1727 
1728 } // end ScsiDiskReadWrite()
1729 
1730 
1731 NTSTATUS
1732 NTAPI
1735  PIRP Irp
1736  )
1737 
1738 /*++
1739 
1740 Routine Description:
1741 
1742  I/O system entry for device controls to SCSI disks.
1743 
1744 Arguments:
1745 
1746  DeviceObject - Pointer to driver object created by system.
1747  Irp - IRP involved.
1748 
1749 Return Value:
1750 
1751  Status is returned.
1752 
1753 --*/
1754 
1755 {
1757  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1758  PDISK_DATA diskData = (PDISK_DATA)(deviceExtension + 1);
1759  PSCSI_REQUEST_BLOCK srb;
1760  PCDB cdb;
1761  PMODE_PARAMETER_HEADER modeData;
1762  PIRP irp2;
1763  ULONG length;
1764  NTSTATUS status;
1765  KEVENT event;
1766  IO_STATUS_BLOCK ioStatus;
1767 
1768  PAGED_CODE();
1769 
1771 
1772  if (srb == NULL) {
1773 
1774  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1777  }
1778 
1779  //
1780  // Write zeros to Srb.
1781  //
1782 
1784 
1785  cdb = (PCDB)srb->Cdb;
1786 
1787  switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
1788 
1789  case SMART_GET_VERSION: {
1790 
1791  ULONG_PTR buffer;
1792  PSRB_IO_CONTROL srbControl;
1793  PGETVERSIONINPARAMS versionParams;
1794 
1795  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1796  sizeof(GETVERSIONINPARAMS)) {
1798  break;
1799  }
1800 
1801  //
1802  // Create notification event object to be used to signal the
1803  // request completion.
1804  //
1805 
1807 
1808  srbControl = ExAllocatePool(NonPagedPool,
1809  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
1810 
1811  if (!srbControl) {
1813  break;
1814  }
1815 
1816  //
1817  // fill in srbControl fields
1818  //
1819 
1820  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
1821  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
1822  srbControl->Timeout = deviceExtension->TimeOutValue;
1823  srbControl->Length = sizeof(GETVERSIONINPARAMS);
1825 
1826  //
1827  // Point to the 'buffer' portion of the SRB_CONTROL
1828  //
1829 
1830  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1831 
1832  //
1833  // Ensure correct target is set in the cmd parameters.
1834  //
1835 
1836  versionParams = (PGETVERSIONINPARAMS)buffer;
1837  versionParams->bIDEDeviceMap = deviceExtension->TargetId;
1838 
1839  //
1840  // Copy the IOCTL parameters to the srb control buffer area.
1841  //
1842 
1843  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(GETVERSIONINPARAMS));
1844 
1845 
1847  deviceExtension->PortDeviceObject,
1848  srbControl,
1849  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
1850  srbControl,
1851  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
1852  FALSE,
1853  &event,
1854  &ioStatus);
1855 
1856  if (irp2 == NULL) {
1858  break;
1859  }
1860 
1861  //
1862  // Call the port driver with the request and wait for it to complete.
1863  //
1864 
1865  status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
1866 
1867  if (status == STATUS_PENDING) {
1869  status = ioStatus.Status;
1870  }
1871 
1872  //
1873  // If successful, copy the data received into the output buffer.
1874  // This should only fail in the event that the IDE driver is older than this driver.
1875  //
1876 
1877  if (NT_SUCCESS(status)) {
1878 
1879  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1880 
1881  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, sizeof(GETVERSIONINPARAMS));
1882  Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
1883  }
1884 
1885  ExFreePool(srbControl);
1886  break;
1887  }
1888 
1889  case SMART_RCV_DRIVE_DATA: {
1890 
1891  PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
1892  ULONG controlCode = 0;
1893  PSRB_IO_CONTROL srbControl;
1894  ULONG_PTR buffer;
1895 
1896  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
1897  (sizeof(SENDCMDINPARAMS) - 1)) {
1899  break;
1900 
1901  } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1902  (sizeof(SENDCMDOUTPARAMS) + 512 - 1)) {
1904  break;
1905  }
1906 
1907  //
1908  // Create notification event object to be used to signal the
1909  // request completion.
1910  //
1911 
1913 
1914  if (cmdInParameters->irDriveRegs.bCommandReg == ID_CMD) {
1915 
1917  controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
1918 
1919  } else if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
1920  switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
1921  case READ_ATTRIBUTES:
1924  break;
1925  case READ_THRESHOLDS:
1928  break;
1929  default:
1931  break;
1932  }
1933  } else {
1934 
1936  }
1937 
1938  if (controlCode == 0) {
1940  break;
1941  }
1942 
1943  srbControl = ExAllocatePool(NonPagedPool,
1944  sizeof(SRB_IO_CONTROL) + length);
1945 
1946  if (!srbControl) {
1948  break;
1949  }
1950 
1951  //
1952  // fill in srbControl fields
1953  //
1954 
1955  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
1956  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
1957  srbControl->Timeout = deviceExtension->TimeOutValue;
1958  srbControl->Length = length;
1959  srbControl->ControlCode = controlCode;
1960 
1961  //
1962  // Point to the 'buffer' portion of the SRB_CONTROL
1963  //
1964 
1965  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1966 
1967  //
1968  // Ensure correct target is set in the cmd parameters.
1969  //
1970 
1971  cmdInParameters->bDriveNumber = deviceExtension->TargetId;
1972 
1973  //
1974  // Copy the IOCTL parameters to the srb control buffer area.
1975  //
1976 
1977  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
1978 
1980  deviceExtension->PortDeviceObject,
1981  srbControl,
1982  sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
1983  srbControl,
1984  sizeof(SRB_IO_CONTROL) + length,
1985  FALSE,
1986  &event,
1987  &ioStatus);
1988 
1989  if (irp2 == NULL) {
1991  break;
1992  }
1993 
1994  //
1995  // Call the port driver with the request and wait for it to complete.
1996  //
1997 
1998  status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
1999 
2000  if (status == STATUS_PENDING) {
2002  status = ioStatus.Status;
2003  }
2004 
2005  //
2006  // If successful, copy the data received into the output buffer
2007  //
2008 
2009  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
2010 
2011  if (NT_SUCCESS(status)) {
2012 
2013  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length - 1);
2014  Irp->IoStatus.Information = length - 1;
2015 
2016  } else {
2017 
2018  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, (sizeof(SENDCMDOUTPARAMS) - 1));
2019  Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
2020 
2021  }
2022 
2023  ExFreePool(srbControl);
2024  break;
2025 
2026  }
2027 
2028  case SMART_SEND_DRIVE_COMMAND: {
2029 
2030  PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
2031  PSRB_IO_CONTROL srbControl;
2032  ULONG controlCode = 0;
2033  ULONG_PTR buffer;
2034 
2035  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2036  (sizeof(SENDCMDINPARAMS) - 1)) {
2038  break;
2039 
2040  } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2041  (sizeof(SENDCMDOUTPARAMS) - 1)) {
2043  break;
2044  }
2045 
2046  //
2047  // Create notification event object to be used to signal the
2048  // request completion.
2049  //
2050 
2052 
2053  length = 0;
2054 
2055  if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
2056  switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
2057 
2058  case ENABLE_SMART:
2059  controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
2060  break;
2061 
2062  case DISABLE_SMART:
2063  controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
2064  break;
2065 
2066  case RETURN_SMART_STATUS:
2067 
2068  //
2069  // Ensure bBuffer is at least 2 bytes (to hold the values of
2070  // cylinderLow and cylinderHigh).
2071  //
2072 
2073  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2074  (sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS))) {
2075 
2077  break;
2078  }
2079 
2080  controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
2081  length = sizeof(IDEREGS);
2082  break;
2083 
2086  break;
2087 
2088  case SAVE_ATTRIBUTE_VALUES:
2090  break;
2091 
2092  case EXECUTE_OFFLINE_DIAGS:
2094  break;
2095 
2096  default:
2098  break;
2099  }
2100  } else {
2101 
2103  }
2104 
2105  if (controlCode == 0) {
2107  break;
2108  }
2109 
2110  length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? sizeof(SENDCMDOUTPARAMS) : sizeof(SENDCMDINPARAMS);
2111  srbControl = ExAllocatePool(NonPagedPool,
2112  sizeof(SRB_IO_CONTROL) + length);
2113 
2114  if (!srbControl) {
2116  break;
2117  }
2118 
2119  //
2120  // fill in srbControl fields
2121  //
2122 
2123  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
2124  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
2125  srbControl->Timeout = deviceExtension->TimeOutValue;
2126  srbControl->Length = length;
2127 
2128  //
2129  // Point to the 'buffer' portion of the SRB_CONTROL
2130  //
2131 
2132  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
2133 
2134  //
2135  // Ensure correct target is set in the cmd parameters.
2136  //
2137 
2138  cmdInParameters->bDriveNumber = deviceExtension->TargetId;
2139 
2140  //
2141  // Copy the IOCTL parameters to the srb control buffer area.
2142  //
2143 
2144  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
2145 
2146  srbControl->ControlCode = controlCode;
2147 
2149  deviceExtension->PortDeviceObject,
2150  srbControl,
2151  sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
2152  srbControl,
2153  sizeof(SRB_IO_CONTROL) + length,
2154  FALSE,
2155  &event,
2156  &ioStatus);
2157 
2158  if (irp2 == NULL) {
2160  break;
2161  }
2162 
2163  //
2164  // Call the port driver with the request and wait for it to complete.
2165  //
2166 
2167  status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2168 
2169  if (status == STATUS_PENDING) {
2171  status = ioStatus.Status;
2172  }
2173 
2174  //
2175  // Copy the data received into the output buffer. Since the status buffer
2176  // contains error information also, always perform this copy. IO will will
2177  // either pass this back to the app, or zero it, in case of error.
2178  //
2179 
2180  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
2181 
2182  //
2183  // Update the return buffer size based on the sub-command.
2184  //
2185 
2186  if (cmdInParameters->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) {
2187  length = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
2188  } else {
2189  length = sizeof(SENDCMDOUTPARAMS) - 1;
2190  }
2191 
2192  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length);
2193  Irp->IoStatus.Information = length;
2194 
2195  ExFreePool(srbControl);
2196  break;
2197 
2198  }
2199 
2202  {
2203 
2204  PDEVICE_EXTENSION physicalDeviceExtension;
2205  PDISK_DATA physicalDiskData;
2206  BOOLEAN removable = FALSE;
2207  BOOLEAN listInitialized = FALSE;
2208  ULONG copyLength;
2209 
2210  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) {
2211  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) {
2213  break;
2214  }
2215 
2216  copyLength = sizeof(DISK_GEOMETRY);
2217  } else {
2218  ASSERT(irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX);
2219  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) {
2221  break;
2222  }
2223 
2224  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(DISK_GEOMETRY_EX)) {
2225  copyLength = sizeof(DISK_GEOMETRY_EX);
2226  } else {
2227  copyLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data);
2228  }
2229  }
2230 
2232 
2233  physicalDeviceExtension = deviceExtension->PhysicalDevice->DeviceExtension;
2234  physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
2235 
2236  removable = (BOOLEAN)DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA;
2237  listInitialized = (physicalDiskData->PartitionListState == Initialized);
2238 
2239  if (removable || (!listInitialized))
2240  {
2241  //
2242  // Issue ReadCapacity to update device extension
2243  // with information for current media.
2244  //
2245 
2246  status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
2247 
2248  }
2249 
2250  if (removable) {
2251 
2252  if (!NT_SUCCESS(status)) {
2253 
2254  //
2255  // Note the drive is not ready.
2256  //
2257 
2258  diskData->DriveNotReady = TRUE;
2259 
2260  break;
2261  }
2262 
2263  //
2264  // Note the drive is now ready.
2265  //
2266 
2267  diskData->DriveNotReady = FALSE;
2268 
2269  } else if (NT_SUCCESS(status)) {
2270 
2271  // ReadDriveCapacity was alright, create Partition Objects
2272 
2273  if (physicalDiskData->PartitionListState == NotInitialized) {
2274  status = CreatePartitionDeviceObjects(deviceExtension->PhysicalDevice, NULL);
2275  }
2276  }
2277 
2278  if (NT_SUCCESS(status)) {
2279 
2280  //
2281  // Copy drive geometry information from device extension.
2282  //
2283 
2284  RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
2285  deviceExtension->DiskGeometry,
2286  copyLength);
2287 
2289  Irp->IoStatus.Information = copyLength;
2290  }
2291 
2292  break;
2293 
2294  }
2295 
2296  case IOCTL_DISK_VERIFY:
2297 
2298  {
2299 
2300  PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
2301  LARGE_INTEGER byteOffset;
2302  ULONG sectorOffset;
2304 
2305  //
2306  // Validate buffer length.
2307  //
2308 
2309  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2310  sizeof(VERIFY_INFORMATION)) {
2311 
2313  break;
2314  }
2315 
2316  //
2317  // Verify sectors
2318  //
2319 
2320  srb->CdbLength = 10;
2321 
2322  cdb->CDB10.OperationCode = SCSIOP_VERIFY;
2323 
2324  //
2325  // Add disk offset to starting sector.
2326  //
2327 
2328  byteOffset.QuadPart = deviceExtension->StartingOffset.QuadPart +
2329  verifyInfo->StartingOffset.QuadPart;
2330 
2331  //
2332  // Convert byte offset to sector offset.
2333  //
2334 
2335  sectorOffset = (ULONG)(byteOffset.QuadPart >> deviceExtension->SectorShift);
2336 
2337  //
2338  // Convert ULONG byte count to USHORT sector count.
2339  //
2340 
2341  sectorCount = (USHORT)(verifyInfo->Length >> deviceExtension->SectorShift);
2342 
2343  //
2344  // Move little endian values into CDB in big endian format.
2345  //
2346 
2347  cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&sectorOffset)->Byte3;
2348  cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
2349  cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
2350  cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;
2351 
2352  cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
2353  cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->Byte0;
2354 
2355  //
2356  // The verify command is used by the NT FORMAT utility and
2357  // requests are sent down for 5% of the volume size. The
2358  // request timeout value is calculated based on the number of
2359  // sectors verified.
2360  //
2361 
2362  srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) *
2363  deviceExtension->TimeOutValue;
2364 
2366  srb,
2367  Irp,
2368  NULL,
2369  0,
2370  FALSE);
2371 
2372  return(status);
2373 
2374  }
2375 
2377 
2378  //
2379  // Return the information about the partition specified by the device
2380  // object. Note that no information is ever returned about the size
2381  // or partition type of the physical disk, as this doesn't make any
2382  // sense.
2383  //
2384 
2385  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2386  sizeof(PARTITION_INFORMATION)) {
2387 
2389  break;
2390  }
2391 
2392  //
2393  // Update the geometry in case it has changed.
2394  //
2395 
2397 
2398  if (!NT_SUCCESS(status)) {
2399 
2400  //
2401  // Note the drive is not ready.
2402  //
2403 
2404  diskData->DriveNotReady = TRUE;
2405  break;
2406  }
2407 
2408  //
2409  // Note the drive is now ready.
2410  //
2411 
2412  diskData->DriveNotReady = FALSE;
2413 
2414  //
2415  // Handle the case were we query the whole disk
2416  //
2417 
2418  if (diskData->PartitionNumber == 0) {
2419 
2420  PPARTITION_INFORMATION outputBuffer;
2421 
2422  outputBuffer =
2423  (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2424 
2425  outputBuffer->PartitionType = PARTITION_ENTRY_UNUSED;
2426  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2427  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2428  outputBuffer->HiddenSectors = 0;
2429  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2430  outputBuffer->BootIndicator = FALSE;
2431  outputBuffer->RewritePartition = FALSE;
2432  outputBuffer->RecognizedPartition = FALSE;
2433 
2435  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
2436 
2437  } else {
2438 
2439  PPARTITION_INFORMATION outputBuffer;
2440 
2441  //
2442  // We query a single partition here
2443  // FIXME: this can only work for MBR-based disks, check for this!
2444  //
2445 
2446  outputBuffer =
2447  (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2448 
2449  outputBuffer->PartitionType = diskData->PartitionType;
2450  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2451  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2452  outputBuffer->HiddenSectors = diskData->HiddenSectors;
2453  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2454  outputBuffer->BootIndicator = diskData->BootIndicator;
2455  outputBuffer->RewritePartition = FALSE;
2456  outputBuffer->RecognizedPartition =
2458 
2460  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
2461  }
2462 
2463  break;
2464 
2466 
2467  //
2468  // Return the information about the partition specified by the device
2469  // object. Note that no information is ever returned about the size
2470  // or partition type of the physical disk, as this doesn't make any
2471  // sense.
2472  //
2473 
2474  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2475  sizeof(PARTITION_INFORMATION_EX)) {
2476 
2478 
2479  }
2480 #if 0 // HACK: ReactOS partition numbers must be wrong
2481  else if (diskData->PartitionNumber == 0) {
2482 
2483  //
2484  // Partition zero is not a partition so this is not a
2485  // reasonable request.
2486  //
2487 
2489 
2490  }
2491 #endif
2492  else {
2493 
2494  PPARTITION_INFORMATION_EX outputBuffer;
2495 
2496  if (diskData->PartitionNumber == 0) {
2497  DPRINT1("HACK: Handling partition 0 request!\n");
2498  //ASSERT(FALSE);
2499  }
2500 
2501  //
2502  // Update the geometry in case it has changed.
2503  //
2504 
2506 
2507  if (!NT_SUCCESS(status)) {
2508 
2509  //
2510  // Note the drive is not ready.
2511  //
2512 
2513  diskData->DriveNotReady = TRUE;
2514  break;
2515  }
2516 
2517  //
2518  // Note the drive is now ready.
2519  //
2520 
2521  diskData->DriveNotReady = FALSE;
2522 
2523  if (diskData->PartitionType == 0 && (diskData->PartitionNumber > 0)) {
2524 
2526  break;
2527  }
2528 
2529  outputBuffer =
2530  (PPARTITION_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
2531 
2532  //
2533  // FIXME: hack of the year, assume that partition is MBR
2534  // Thing that can obviously be wrong...
2535  //
2536 
2537  outputBuffer->PartitionStyle = PARTITION_STYLE_MBR;
2538  outputBuffer->Mbr.PartitionType = diskData->PartitionType;
2539  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2540  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2541  outputBuffer->Mbr.HiddenSectors = diskData->HiddenSectors;
2542  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2543  outputBuffer->Mbr.BootIndicator = diskData->BootIndicator;
2544  outputBuffer->RewritePartition = FALSE;
2545  outputBuffer->Mbr.RecognizedPartition =
2547 
2549  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
2550  }
2551 
2552  break;
2553 
2555 
2556  if (diskData->PartitionNumber == 0) {
2557 
2559 
2560  } else {
2561 
2562  PSET_PARTITION_INFORMATION inputBuffer =
2563  (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2564 
2565  //
2566  // Validate buffer length.
2567  //
2568 
2569  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2570  sizeof(SET_PARTITION_INFORMATION)) {
2571 
2573  break;
2574  }
2575 
2576  //
2577  // The HAL routines IoGet- and IoSetPartitionInformation were
2578  // developed before support of dynamic partitioning and therefore
2579  // don't distinguish between partition ordinal (that is the order
2580  // of a partition on a disk) and the partition number. (The
2581  // partition number is assigned to a partition to identify it to
2582  // the system.) Use partition ordinals for these legacy calls.
2583  //
2584 
2586  deviceExtension->PhysicalDevice,
2587  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2588  diskData->PartitionOrdinal,
2589  inputBuffer->PartitionType);
2590 
2591  if (NT_SUCCESS(status)) {
2592 
2593  diskData->PartitionType = inputBuffer->PartitionType;
2594  }
2595  }
2596 
2597  break;
2598 
2600 
2601  //
2602  // Return the partition layout for the physical drive. Note that
2603  // the layout is returned for the actual physical drive, regardless
2604  // of which partition was specified for the request.
2605  //
2606 
2607  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2608  sizeof(DRIVE_LAYOUT_INFORMATION)) {
2610 
2611  } else {
2612 
2613  PDRIVE_LAYOUT_INFORMATION partitionList;
2614  PDEVICE_EXTENSION physicalExtension = deviceExtension;
2615  PPARTITION_INFORMATION partitionEntry;
2616  PDISK_DATA diskData;
2617  ULONG tempSize;
2618  ULONG i;
2619 
2620  //
2621  // Read partition information.
2622  //
2623 
2624  status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
2625  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2626  FALSE,
2627  &partitionList);
2628 
2629  if (!NT_SUCCESS(status)) {
2630  break;
2631  }
2632 
2633  //
2634  // The disk layout has been returned in the partitionList
2635  // buffer. Determine its size and, if the data will fit
2636  // into the intermediary buffer, return it.
2637  //
2638 
2639  tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,PartitionEntry[0]);
2640  tempSize += partitionList->PartitionCount *
2641  sizeof(PARTITION_INFORMATION);
2642 
2643  if (tempSize >
2644  irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
2645 
2647  ExFreePool(partitionList);
2648  break;
2649  }
2650 
2651  //
2652  // Walk partition list to associate partition numbers with
2653  // partition entries.
2654  //
2655 
2656  for (i = 0; i < partitionList->PartitionCount; i++) {
2657 
2658  //
2659  // Walk partition chain anchored at physical disk extension.
2660  //
2661 
2662  deviceExtension = physicalExtension;
2663  diskData = (PDISK_DATA)(deviceExtension + 1);
2664 
2665  do {
2666 
2667  deviceExtension = diskData->NextPartition;
2668 
2669  //
2670  // Check if this is the last partition in the chain.
2671  //
2672 
2673  if (!deviceExtension) {
2674  break;
2675  }
2676 
2677  //
2678  // Get the partition device extension from disk data.
2679  //
2680 
2681  diskData = (PDISK_DATA)(deviceExtension + 1);
2682 
2683  //
2684  // Check if this partition is not currently being used.
2685  //
2686 
2687  if (!deviceExtension->PartitionLength.QuadPart) {
2688  continue;
2689  }
2690 
2691  partitionEntry = &partitionList->PartitionEntry[i];
2692 
2693  //
2694  // Check if empty, or describes extended partition or hasn't changed.
2695  //
2696 
2697  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
2698  IsContainerPartition(partitionEntry->PartitionType)) {
2699  continue;
2700  }
2701 
2702  //
2703  // Check if new partition starts where this partition starts.
2704  //
2705 
2706  if (partitionEntry->StartingOffset.QuadPart !=
2707  deviceExtension->StartingOffset.QuadPart) {
2708  continue;
2709  }
2710 
2711  //
2712  // Check if partition length is the same.
2713  //
2714 
2715  if (partitionEntry->PartitionLength.QuadPart ==
2716  deviceExtension->PartitionLength.QuadPart) {
2717 
2718  //
2719  // Partitions match. Update partition number.
2720  //
2721 
2722  partitionEntry->PartitionNumber =
2723  diskData->PartitionNumber;
2724  break;
2725  }
2726 
2727  } while (TRUE);
2728  }
2729 
2730  //
2731  // Copy partition information to system buffer.
2732  //
2733 
2734  RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
2735  partitionList,
2736  tempSize);
2738  Irp->IoStatus.Information = tempSize;
2739 
2740  //
2741  // Finally, free the buffer allocated by reading the
2742  // partition table.
2743  //
2744 
2745  ExFreePool(partitionList);
2746  }
2747 
2748  break;
2749 
2751 
2752  {
2753 
2754  //
2755  // Update the disk with new partition information.
2756  //
2757 
2758  PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer;
2759 
2760  //
2761  // Validate buffer length.
2762  //
2763 
2764  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2765  sizeof(DRIVE_LAYOUT_INFORMATION)) {
2766 
2768  break;
2769  }
2770 
2771  length = sizeof(DRIVE_LAYOUT_INFORMATION) +
2772  (partitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION);
2773 
2774 
2775  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2776  length) {
2777 
2779  break;
2780  }
2781 
2782  //
2783  // Verify that device object is for physical disk.
2784  //
2785 
2786  if (deviceExtension->PhysicalDevice->DeviceExtension != deviceExtension) {
2788  break;
2789  }
2790 
2791  //
2792  // Walk through partition table comparing partitions to
2793  // existing partitions to create, delete and change
2794  // device objects as necessary.
2795  //
2796 
2798  Irp);
2799 
2800  //
2801  // Write changes to disk.
2802  //
2803 
2805  deviceExtension->DeviceObject,
2806  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2807  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack,
2808  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder,
2809  partitionList);
2810  }
2811 
2812  //
2813  // Update IRP with bytes returned.
2814  //
2815 
2816  if (NT_SUCCESS(status)) {
2817  Irp->IoStatus.Information = length;
2818  }
2819 
2820  break;
2821 
2823 
2824  //
2825  // Map defective blocks to new location on disk.
2826  //
2827 
2828  {
2829 
2830  PREASSIGN_BLOCKS badBlocks = Irp->AssociatedIrp.SystemBuffer;
2831  ULONG bufferSize;
2832  ULONG blockNumber;
2833  ULONG blockCount;
2834 
2835  //
2836  // Validate buffer length.
2837  //
2838 
2839  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2840  sizeof(REASSIGN_BLOCKS)) {
2841 
2843  break;
2844  }
2845 
2846  bufferSize = sizeof(REASSIGN_BLOCKS) +
2847  (badBlocks->Count - 1) * sizeof(ULONG);
2848 
2849  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2850  bufferSize) {
2851 
2853  break;
2854  }
2855 
2856  //
2857  // Build the data buffer to be transferred in the input buffer.
2858  // The format of the data to the device is:
2859  //
2860  // 2 bytes Reserved
2861  // 2 bytes Length
2862  // x * 4 btyes Block Address
2863  //
2864  // All values are big endian.
2865  //
2866 
2867  badBlocks->Reserved = 0;
2868  blockCount = badBlocks->Count;
2869 
2870  //
2871  // Convert # of entries to # of bytes.
2872  //
2873 
2874  blockCount *= 4;
2875  badBlocks->Count = (USHORT) ((blockCount >> 8) & 0XFF);
2876  badBlocks->Count |= (USHORT) ((blockCount << 8) & 0XFF00);
2877 
2878  //
2879  // Convert back to number of entries.
2880  //
2881 
2882  blockCount /= 4;
2883 
2884  for (; blockCount > 0; blockCount--) {
2885 
2886  blockNumber = badBlocks->BlockNumber[blockCount-1];
2887 
2888  REVERSE_BYTES((PFOUR_BYTE) &badBlocks->BlockNumber[blockCount-1],
2889  (PFOUR_BYTE) &blockNumber);
2890  }
2891 
2892  srb->CdbLength = 6;
2893 
2894  cdb->CDB6GENERIC.OperationCode = SCSIOP_REASSIGN_BLOCKS;
2895 
2896  //
2897  // Set timeout value.
2898  //
2899 
2900  srb->TimeOutValue = deviceExtension->TimeOutValue;
2901 
2903  srb,
2904  badBlocks,
2905  bufferSize,
2906  TRUE);
2907 
2908  Irp->IoStatus.Status = status;
2909  Irp->IoStatus.Information = 0;
2910  ExFreePool(srb);
2912  }
2913 
2914  return(status);
2915 
2917 
2918  //
2919  // Determine if the device is writable.
2920  //
2921 
2923 
2924  if (modeData == NULL) {
2926  break;
2927  }
2928 
2929  RtlZeroMemory(modeData, MODE_DATA_SIZE);
2930 
2932  (PCHAR) modeData,
2935 
2936  if (length < sizeof(MODE_PARAMETER_HEADER)) {
2937 
2938  //
2939  // Retry the request in case of a check condition.
2940  //
2941 
2943  (PCHAR) modeData,
2946 
2947  if (length < sizeof(MODE_PARAMETER_HEADER)) {
2949  ExFreePool(modeData);
2950  break;
2951  }
2952  }
2953 
2954  if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) {
2956  } else {
2958  }
2959 
2960  ExFreePool(modeData);
2961  break;
2962 
2964 
2965  //
2966  // If the caller is kernel mode, set the verify bit.
2967  //
2968 
2969  if (Irp->RequestorMode == KernelMode) {
2971  }
2973  break;
2974 
2976 
2977  //
2978  // If the caller is kernel mode, clear the verify bit.
2979  //
2980 
2981  if (Irp->RequestorMode == KernelMode) {
2983  }
2985  break;
2986 
2988 
2989  //
2990  // Search for devices that have been powered on since the last
2991  // device search or system initialization.
2992  //
2993 
2994  DebugPrint((3,"CdRomDeviceControl: Find devices\n"));
2995  status = DriverEntry(DeviceObject->DriverObject,
2996  NULL);
2997 
2998  Irp->IoStatus.Status = status;
2999  ExFreePool(srb);
3001  return status;
3002 
3004 
3005  //
3006  // If the disk is not removable then don't allow this command.
3007  //
3008 
3009  if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
3011  break;
3012  }
3013 
3014  //
3015  // Fall through and let the class driver process the request.
3016  //
3017 
3019 
3020  //
3021  // Validate buffer length.
3022  //
3023 
3024  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
3025  sizeof(GET_LENGTH_INFORMATION)) {
3027 
3028  } else {
3029 
3030  PGET_LENGTH_INFORMATION lengthInformation = Irp->AssociatedIrp.SystemBuffer;
3031 
3032  //
3033  // Update the geometry in case it has changed.
3034  //
3035 
3037 
3038  if (!NT_SUCCESS(status)) {
3039 
3040  //
3041  // Note the drive is not ready.
3042  //
3043 
3044  diskData->DriveNotReady = TRUE;
3045  break;
3046  }
3047 
3048  //
3049  // Note the drive is now ready.
3050  //
3051 
3052  diskData->DriveNotReady = FALSE;
3053 
3054  //
3055  // Output data, and return
3056  //
3057 
3058  lengthInformation->Length.QuadPart = deviceExtension->PartitionLength.QuadPart;
3060  Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
3061  }
3062 
3063  break;
3064 
3065  default:
3066 
3067  //
3068  // Free the Srb, since it is not needed.
3069  //
3070 
3071  ExFreePool(srb);
3072 
3073  //
3074  // Pass the request to the common device control routine.
3075  //
3076 
3078 
3079  break;
3080 
3081  } // end switch( ...
3082 
3083  Irp->IoStatus.Status = status;
3084 
3086 
3088  }
3089 
3091  ExFreePool(srb);
3092  return(status);
3093 
3094 } // end ScsiDiskDeviceControl()
3095 
3096 NTSTATUS
3097 NTAPI
3100  IN PIRP Irp
3101  )
3102 
3103 /*++
3104 
3105 Routine Description:
3106 
3107  This routine is called for a shutdown and flush IRPs. These are sent by the
3108  system before it actually shuts down or when the file system does a flush.
3109  A synchronize cache command is sent to the device if it is write caching.
3110  If the device is removable an unlock command will be sent. This routine
3111  will sent a shutdown or flush Srb to the port driver.
3112 
3113 Arguments:
3114 
3115  DriverObject - Pointer to device object to being shutdown by system.
3116 
3117  Irp - IRP involved.
3118 
3119 Return Value:
3120 
3121  NT Status
3122 
3123 --*/
3124 
3125 {
3126  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3127  PIO_STACK_LOCATION irpStack;
3128  PSCSI_REQUEST_BLOCK srb;
3129  NTSTATUS status;
3130  PCDB cdb;
3131 
3132  //
3133  // Allocate SCSI request block.
3134  //
3135 
3137 
3138  if (srb == NULL) {
3139 
3140  //
3141  // Set the status and complete the request.
3142  //
3143 
3144  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3147  }
3148 
3150 
3151  //
3152  // Write length to SRB.
3153  //
3154 
3156 
3157  //
3158  // Set SCSI bus address.
3159  //
3160 
3161  srb->PathId = deviceExtension->PathId;
3162  srb->TargetId = deviceExtension->TargetId;
3163  srb->Lun = deviceExtension->Lun;
3164 
3165  //
3166  // Set timeout value and mark the request as not being a tagged request.
3167  //
3168 
3169  srb->TimeOutValue = deviceExtension->TimeOutValue * 4;
3170  srb->QueueTag = SP_UNTAGGED;
3172  srb->SrbFlags = deviceExtension->SrbFlags;
3173 
3174  //
3175  // If the write cache is enabled then send a synchronize cache request.
3176  //
3177 
3178  if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
3179 
3181  srb->CdbLength = 10;
3182 
3183  srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
3184 
3186  srb,
3187  NULL,
3188  0,
3189  TRUE);
3190 
3191  DebugPrint((1, "ScsiDiskShutdownFlush: Synchronize cache sent. Status = %lx\n", status ));
3192  }
3193 
3194  //
3195  // Unlock the device if it is removable and this is a shutdown.
3196  //
3197 
3198  irpStack = IoGetCurrentIrpStackLocation(Irp);
3199 
3200  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
3201  irpStack->MajorFunction == IRP_MJ_SHUTDOWN) {
3202 
3203  srb->CdbLength = 6;
3204  cdb = (PVOID) srb->Cdb;
3205  cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
3206  cdb->MEDIA_REMOVAL.Prevent = FALSE;
3207 
3208  //
3209  // Set timeout value.
3210  //
3211 
3212  srb->TimeOutValue = deviceExtension->TimeOutValue;
3214  srb,
3215  NULL,
3216  0,
3217  TRUE);
3218 
3219  DebugPrint((1, "ScsiDiskShutdownFlush: Unlock device request sent. Status = %lx\n", status ));
3220  }
3221 
3222  srb->CdbLength = 0;
3223 
3224  //
3225  // Save a few parameters in the current stack location.
3226  //
3227 
3228  srb->Function = irpStack->MajorFunction == IRP_MJ_SHUTDOWN ?
3230 
3231  //
3232  // Set the retry count to zero.
3233  //
3234 
3235  irpStack->Parameters.Others.Argument4 = (PVOID) 0;
3236 
3237  //
3238  // Set up IoCompletion routine address.
3239  //
3240 
3242 
3243  //
3244  // Get next stack location and
3245  // set major function code.
3246  //
3247 
3248  irpStack = IoGetNextIrpStackLocation(Irp);
3249 
3250  irpStack->MajorFunction = IRP_MJ_SCSI;
3251 
3252  //
3253  // Set up SRB for execute scsi request.
3254  // Save SRB address in next stack for port driver.
3255  //
3256 
3257  irpStack->Parameters.Scsi.Srb = srb;
3258 
3259  //
3260  // Set up Irp Address.
3261  //
3262 
3263  srb->OriginalRequest = Irp;
3264 
3265  //
3266  // Call the port driver to process the request.
3267  //
3268 
3269  return(IoCallDriver(deviceExtension->PortDeviceObject, Irp));
3270 
3271 } // end ScsiDiskShutdown()
3272 
3273 
3274 BOOLEAN
3275 NTAPI
3278  )
3279 /*++
3280 
3281 Routine Description:
3282 
3283  The routine performs the necessary functions to determine if a device is
3284  really a floppy rather than a harddisk. This is done by a mode sense
3285  command. First, a check is made to see if the media type is set. Second
3286  a check is made for the flexible parameters mode page. Also a check is
3287  made to see if the write cache is enabled.
3288 
3289 Arguments:
3290 
3291  DeviceObject - Supplies the device object to be tested.
3292 
3293 Return Value:
3294 
3295  Return TRUE if the indicated device is a floppy.
3296 
3297 --*/
3298 {
3299  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3300  PVOID modeData;
3301  PUCHAR pageData;
3302  ULONG length;
3303 
3304  PAGED_CODE();
3305 
3307 
3308  if (modeData == NULL) {
3309  return(FALSE);
3310  }
3311 
3312  RtlZeroMemory(modeData, MODE_DATA_SIZE);
3313 
3315  modeData,
3318 
3319  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3320 
3321  //
3322  // Retry the request in case of a check condition.
3323  //
3324 
3326  modeData,
3329 
3330  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3331 
3332  ExFreePool(modeData);
3333  return(FALSE);
3334 
3335  }
3336  }
3337 
3338  //
3339  // If the length is greater than length indicated by the mode data reset
3340  // the data to the mode data.
3341  //
3342 
3343  if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) {
3344  length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1;
3345  }
3346 
3347  //
3348  // Look for the flexible disk mode page.
3349  //
3350 
3351  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE);
3352 
3353  if (pageData != NULL) {
3354 
3355  DebugPrint((1, "Scsidisk: Flexible disk page found, This is a floppy.\n"));
3356  ExFreePool(modeData);
3357  return(TRUE);
3358  }
3359 
3360  //
3361  // Check to see if the write cache is enabled.
3362  //
3363 
3364  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE);
3365 
3366  //
3367  // Assume that write cache is disabled or not supported.
3368  //
3369 
3370  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3371 
3372  //
3373  // Check if valid caching page exists.
3374  //
3375 
3376  if (pageData != NULL) {
3377 
3378  //
3379  // Check if write cache is disabled.
3380  //
3381 
3382  if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) {
3383 
3384  DebugPrint((1,
3385  "SCSIDISK: Disk write cache enabled\n"));
3386 
3387  //
3388  // Check if forced unit access (FUA) is supported.
3389  //
3390 
3391  if (((PMODE_PARAMETER_HEADER)modeData)->DeviceSpecificParameter & MODE_DSP_FUA_SUPPORTED) {
3392 
3393  deviceExtension->DeviceFlags |= DEV_WRITE_CACHE;
3394 
3395  } else {
3396 
3397  DebugPrint((1,
3398  "SCSIDISK: Disk does not support FUA or DPO\n"));
3399 
3400  //
3401  // TODO: Log this.
3402  //
3403 
3404  }
3405  }
3406  }
3407 
3408  ExFreePool(modeData);
3409  return(FALSE);
3410 
3411 } // end IsFloppyDevice()
3412 
3413 
3414 BOOLEAN
3415 NTAPI
3418  IN PCHAR ModeSelectBuffer,
3419  IN ULONG Length,
3420  IN BOOLEAN SavePage
3421  )
3422 
3423 /*++
3424 
3425 Routine Description:
3426 
3427  This routine sends a mode select command.
3428 
3429 Arguments:
3430 
3431  DeviceObject - Supplies the device object associated with this request.
3432 
3433  ModeSelectBuffer - Supplies a buffer containing the page data.
3434 
3435  Length - Supplies the length in bytes of the mode select buffer.
3436 
3437  SavePage - Indicates that parameters should be written to disk.
3438 
3439 Return Value:
3440 
3441  Length of the transferred data is returned.
3442 
3443 --*/
3444 {
3445  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3446  PCDB cdb;
3447  SCSI_REQUEST_BLOCK srb;
3448  ULONG retries = 1;
3449  ULONG length2;
3450  NTSTATUS status;
3451  ULONG_PTR buffer;
3452  PMODE_PARAMETER_BLOCK blockDescriptor;
3453 
3454  PAGED_CODE();
3455 
3456  length2 = Length + sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
3457 
3458  //
3459  // Allocate buffer for mode select header, block descriptor, and mode page.
3460  //
3461 
3463 
3464  RtlZeroMemory((PVOID)buffer, length2);
3465 
3466  //
3467  // Set length in header to size of mode page.
3468  //
3469 
3470  ((PMODE_PARAMETER_HEADER)buffer)->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
3471 
3472  blockDescriptor = (PMODE_PARAMETER_BLOCK)(buffer + 1);
3473 
3474  //
3475  // Set size
3476  //
3477 
3478  blockDescriptor->BlockLength[1]=0x02;
3479 
3480  //
3481  // Copy mode page to buffer.
3482  //
3483 
3484  RtlCopyMemory((PVOID)(buffer + 3), ModeSelectBuffer, Length);
3485 
3486  //
3487  // Zero SRB.
3488  //
3489 
3490  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
3491 
3492  //
3493  // Build the MODE SELECT CDB.
3494  //
3495 
3496  srb.CdbLength = 6;
3497  cdb = (PCDB)srb.Cdb;
3498 
3499  //
3500  // Set timeout value from device extension.
3501  //
3502 
3503  srb.TimeOutValue = deviceExtension->TimeOutValue * 2;
3504 
3505  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
3506  cdb->MODE_SELECT.SPBit = SavePage;
3507  cdb->MODE_SELECT.PFBit = 1;
3508  cdb->MODE_SELECT.ParameterListLength = (UCHAR)(length2);
3509 
3510 Retry:
3511 
3513  &srb,
3514  (PVOID)buffer,
3515  length2,
3516  TRUE);
3517 
3518 
3519  if (status == STATUS_VERIFY_REQUIRED) {
3520 
3521  //
3522  // Routine ScsiClassSendSrbSynchronous does not retry requests returned with
3523  // this status.
3524  //
3525 
3526  if (retries--) {
3527 
3528  //
3529  // Retry request.
3530  //
3531 
3532  goto Retry;
3533  }
3534 
3535  } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
3537  }
3538 
3540 
3541  if (NT_SUCCESS(status)) {
3542  return(TRUE);
3543  } else {
3544  return(FALSE);
3545  }
3546 
3547 } // end SciDiskModeSelect()
3548 
3549 
3550 VOID
3551 NTAPI
3554  IN PSCSI_INQUIRY_DATA LunInfo
3555  )
3556 
3557 {
3558  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3559  PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
3560  BAD_CONTROLLER_INFORMATION const *controller;
3561  ULONG j,length;
3562  PVOID modeData;
3563  PUCHAR pageData;
3564 
3565  for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) {
3566 
3567  controller = &ScsiDiskBadControllers[j];
3568 
3569  if (!controller->DisableWriteCache || strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) {
3570  continue;
3571  }
3572 
3573  DebugPrint((1, "ScsiDisk.DisableWriteCache, Found bad controller! %s\n", controller->InquiryString));
3574 
3576 
3577  if (modeData == NULL) {
3578 
3579  DebugPrint((1,
3580  "ScsiDisk.DisableWriteCache: Check for write-cache enable failed\n"));
3581  return;
3582  }
3583 
3584  RtlZeroMemory(modeData, MODE_DATA_SIZE);
3585 
3587  modeData,
3590 
3591  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3592 
3593  //
3594  // Retry the request in case of a check condition.
3595  //
3596 
3598  modeData,
3601 
3602  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3603 
3604 
3605  DebugPrint((1,
3606  "ScsiDisk.DisableWriteCache: Mode Sense failed\n"));
3607 
3608  ExFreePool(modeData);
3609  return;
3610 
3611  }
3612  }
3613 
3614  //
3615  // If the length is greater than length indicated by the mode data reset
3616  // the data to the mode data.
3617  //
3618 
3619  if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) {
3620  length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1;
3621  }
3622 
3623  //
3624  // Check to see if the write cache is enabled.
3625  //
3626 
3627  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE);
3628 
3629  //
3630  // Assume that write cache is disabled or not supported.
3631  //
3632 
3633  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3634 
3635  //
3636  // Check if valid caching page exists.
3637  //
3638 
3639  if (pageData != NULL) {
3640 
3641  BOOLEAN savePage = FALSE;
3642 
3643  savePage = (BOOLEAN)(((PMODE_CACHING_PAGE)pageData)->PageSavable);
3644 
3645  //
3646  // Check if write cache is disabled.
3647  //
3648 
3649  if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) {
3650 
3651  PIO_ERROR_LOG_PACKET errorLogEntry;
3652  LONG errorCode;
3653 
3654 
3655  //
3656  // Disable write cache and ensure necessary fields are zeroed.
3657  //
3658 
3659  ((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable = FALSE;
3660  ((PMODE_CACHING_PAGE)pageData)->Reserved = 0;
3661  ((PMODE_CACHING_PAGE)pageData)->PageSavable = 0;
3662  ((PMODE_CACHING_PAGE)pageData)->Reserved2 = 0;
3663 
3664  //
3665  // Extract length from caching page.
3666  //
3667 
3668  length = ((PMODE_CACHING_PAGE)pageData)->PageLength;
3669 
3670  //
3671  // Compensate for page code and page length.
3672  //
3673 
3674  length += 2;
3675 
3676  //
3677  // Issue mode select to set the parameter.
3678  //
3679 
3681  (PCHAR)pageData,
3682  length,
3683  savePage)) {
3684 
3685  DebugPrint((1,
3686  "SCSIDISK: Disk write cache disabled\n"));
3687 
3688  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3689  errorCode = IO_WRITE_CACHE_DISABLED;
3690 
3691  } else {
3693  (PCHAR)pageData,
3694  length,
3695  savePage)) {
3696 
3697  DebugPrint((1,
3698  "SCSIDISK: Disk write cache disabled\n"));
3699 
3700 
3701  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3702  errorCode = IO_WRITE_CACHE_DISABLED;
3703 
3704  } else {
3705 
3706  DebugPrint((1,
3707  "SCSIDISK: Mode select to disable write cache failed\n"));
3708 
3709  deviceExtension->DeviceFlags |= DEV_WRITE_CACHE;
3710  errorCode = IO_WRITE_CACHE_ENABLED;
3711  }
3712  }
3713 
3714  //
3715  // Log the appropriate informational or error entry.
3716  //
3717 
3719  DeviceObject,
3720  sizeof(IO_ERROR_LOG_PACKET) + 3
3721  * sizeof(ULONG));
3722 
3723  if (errorLogEntry != NULL) {
3724 
3725  errorLogEntry->FinalStatus = STATUS_SUCCESS;
3726  errorLogEntry->ErrorCode = errorCode;
3727  errorLogEntry->SequenceNumber = 0;
3728  errorLogEntry->MajorFunctionCode = IRP_MJ_SCSI;
3729  errorLogEntry->IoControlCode = 0;
3730  errorLogEntry->RetryCount = 0;
3731  errorLogEntry->UniqueErrorValue = 0x1;
3732  errorLogEntry->DumpDataSize = 3 * sizeof(ULONG);
3733  errorLogEntry->DumpData[0] = LunInfo->PathId;
3734  errorLogEntry->DumpData[1] = LunInfo->TargetId;
3735  errorLogEntry->DumpData[2] = LunInfo->Lun;
3736 
3737  //
3738  // Write the error log packet.
3739  //
3740 
3741  IoWriteErrorLogEntry(errorLogEntry);
3742  }
3743  }
3744  }
3745 
3746  //
3747  // Found device so exit the loop and return.
3748  //
3749 
3750  break;
3751  }
3752 
3753  return;
3754 }
3755 
3756 
3757 BOOLEAN
3758 NTAPI
3760  IN PDEVICE_EXTENSION DeviceExtension,
3761  OUT PULONG Checksum
3762  )
3763 
3764 /*++
3765 
3766 Routine Description:
3767 
3768  Read MBR and calculate checksum.
3769 
3770 Arguments:
3771 
3772  DeviceExtension - Supplies a pointer to the device information for disk.
3773  Checksum - Memory location to return MBR checksum.
3774 
3775 Return Value:
3776 
3777  Returns TRUE if checksum is valid.
3778 
3779 --*/
3780 {
3781  LARGE_INTEGER sectorZero;
3782  PIRP irp;
3783  IO_STATUS_BLOCK ioStatus;
3784  KEVENT event;
3785  NTSTATUS status;
3786  ULONG sectorSize;
3787  PULONG mbr;
3788  ULONG i;
3789 
3790  PAGED_CODE();
3791  sectorZero.QuadPart = (LONGLONG) 0;
3792 
3793  //
3794  // Create notification event object to be used to signal the inquiry
3795  // request completion.
3796  //
3797 
3799 
3800  //
3801  // Get sector size.
3802  //
3803 
3804  sectorSize = DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
3805 
3806  //
3807  // Make sure sector size is at least 512 bytes.
3808  //
3809 
3810  if (sectorSize < 512) {
3811  sectorSize = 512;
3812  }
3813 
3814  //
3815  // Allocate buffer for sector read.
3816  //
3817 
3818  mbr = ExAllocatePool(NonPagedPoolCacheAligned, sectorSize);
3819 
3820  if (!mbr) {
3821  return FALSE;
3822  }
3823 
3824  //
3825  // Build IRP to read MBR.
3826  //
3827 
3829  DeviceExtension->DeviceObject,
3830  mbr,
3831  sectorSize,
3832  &sectorZero,
3833  &event,
3834  &ioStatus );
3835 
3836  if (!irp) {
3837  ExFreePool(mbr);
3838  return FALSE;
3839  }
3840 
3841  //
3842  // Pass request to port driver and wait for request to complete.
3843  //
3844 
3845  status = IoCallDriver(DeviceExtension->DeviceObject,
3846  irp);
3847 
3848  if (status == STATUS_PENDING) {
3850  Suspended,
3851  KernelMode,
3852  FALSE,
3853  NULL);
3854  status = ioStatus.Status;
3855  }
3856 
3857  if (!NT_SUCCESS(status)) {
3858  ExFreePool(mbr);
3859  return FALSE;
3860  }
3861 
3862  //
3863  // Calculate MBR checksum.
3864  //
3865 
3866  *Checksum = 0;
3867 
3868  for (i = 0; i < 128; i++) {
3869  *Checksum += mbr[i];
3870  }
3871 
3872  *Checksum = ~*Checksum + 1;
3873 
3874  ExFreePool(mbr);
3875  return TRUE;
3876 }
3877 
3878 
3879 BOOLEAN
3880 NTAPI
3882  IN PDEVICE_EXTENSION DeviceExtension,
3883  HANDLE BusKey,
3884  PULONG DiskNumber
3885  )
3886 
3887 /*++
3888 
3889 Routine Description:
3890 
3891  The routine queries the registry to determine if this disk is visible to
3892  the BIOS. If the disk is visible to the BIOS, then the geometry information
3893  is updated.
3894 
3895 Arguments:
3896 
3897  DeviceExtension - Supplies a pointer to the device information for disk.
3898  Signature - Unique identifier recorded in MBR.
3899  BusKey - Handle of bus key.
3900  DiskNumber - Returns ordinal of disk as BIOS sees it.
3901 
3902 Return Value:
3903 
3904  TRUE is disk signature matched.
3905 
3906 --*/
3907 {
3908  PDISK_DATA diskData = (PDISK_DATA)(DeviceExtension + 1);
3909  BOOLEAN diskFound = FALSE;
3910  OBJECT_ATTRIBUTES objectAttributes;
3911  UNICODE_STRING unicodeString;
3912  UNICODE_STRING identifier;
3913  ULONG busNumber;
3914  ULONG adapterNumber;
3915  ULONG diskNumber;
3916  HANDLE adapterKey;
3917  HANDLE spareKey;
3918  HANDLE diskKey;
3919  HANDLE targetKey;
3920  NTSTATUS status;
3921  STRING string;
3922  STRING anotherString;
3923  ULONG length;
3924  UCHAR buffer[20];
3926 
3927  PAGED_CODE();
3928 
3929  for (busNumber = 0; ; busNumber++) {
3930 
3931  //
3932  // Open controller name key.
3933  //
3934 
3935  sprintf((PCHAR)buffer,
3936  "%lu",
3937  busNumber);
3938 
3939  RtlInitString(&string,
3940  (PCSZ)buffer);
3941 
3942  status = RtlAnsiStringToUnicodeString(&unicodeString,
3943  &string,
3944  TRUE);
3945 
3946  if (!NT_SUCCESS(status)){
3947  break;
3948  }
3949 
3950  InitializeObjectAttributes(&objectAttributes,
3951  &unicodeString,
3953  BusKey,
3955 
3956  status = ZwOpenKey(&spareKey,
3957  KEY_READ,
3958  &objectAttributes);
3959 
3960  RtlFreeUnicodeString(&unicodeString);
3961 
3962  if (!NT_SUCCESS(status)) {
3963  break;
3964  }
3965 
3966  //
3967  // Open up controller ordinal key.
3968  //
3969 
3970  RtlInitUnicodeString(&unicodeString, L"DiskController");
3971  InitializeObjectAttributes(&objectAttributes,
3972  &unicodeString,
3974  spareKey,
3976 
3977  status = ZwOpenKey(&adapterKey,
3978  KEY_READ,
3979  &objectAttributes);
3980 
3981  //
3982  // This could fail even with additional adapters of this type
3983  // to search.
3984  //
3985 
3986  if (!NT_SUCCESS(status)) {
3987  continue;
3988  }
3989 
3990  for (adapterNumber = 0; ; adapterNumber++) {
3991 
3992  //
3993  // Open disk key.
3994  //
3995 
3996  sprintf((PCHAR)buffer,
3997  "%lu\\DiskPeripheral",
3998  adapterNumber);
3999 
4000  RtlInitString(&string,
4001  (PCSZ)buffer);
4002 
4003  status = RtlAnsiStringToUnicodeString(&unicodeString,
4004  &string,
4005  TRUE);
4006 
4007  if (!NT_SUCCESS(status)){
4008  break;
4009  }
4010 
4011  InitializeObjectAttributes(&objectAttributes,
4012  &unicodeString,
4014  adapterKey,
4016 
4017  status = ZwOpenKey(&diskKey,
4018  KEY_READ,
4019  &objectAttributes);
4020 
4021  RtlFreeUnicodeString(&unicodeString);
4022 
4023  if (!NT_SUCCESS(status)) {
4024  break;
4025  }
4026 
4027  for (diskNumber = 0; ; diskNumber++) {
4028 
4029  sprintf((PCHAR)buffer,
4030  "%lu",
4031  diskNumber);
4032 
4033  RtlInitString(&string,
4034  (PCSZ)buffer);
4035 
4036  status = RtlAnsiStringToUnicodeString(&unicodeString,
4037  &string,
4038  TRUE);
4039 
4040  if (!NT_SUCCESS(status)){
4041  break;
4042  }
4043 
4044  InitializeObjectAttributes(&objectAttributes,
4045  &unicodeString,
4047  diskKey,
4049 
4050  status = ZwOpenKey(&targetKey,
4051  KEY_READ,
4052  &objectAttributes);
4053 
4054  RtlFreeUnicodeString(&unicodeString);
4055 
4056  if (!NT_SUCCESS(status)) {
4057  break;
4058  }
4059 
4060  //
4061  // Allocate buffer for registry query.
4062  //
4063 
4065 
4066  if (keyData == NULL) {
4067  ZwClose(targetKey);
4068  continue;
4069  }
4070 
4071  //
4072  // Get disk peripheral identifier.
4073  //
4074 
4075  RtlInitUnicodeString(&unicodeString, L"Identifier");
4076  status = ZwQueryValueKey(targetKey,
4077  &unicodeString,
4079  keyData,
4081  &length);
4082 
4083  ZwClose(targetKey);
4084 
4085  if (!NT_SUCCESS(status)) {
4086  ExFreePool(keyData);
4087  continue;
4088  }
4089 
4090  if (keyData->DataLength < 9*sizeof(WCHAR)) {
4091  //
4092  // the data is too short to use (we subtract 9 chars in normal path)
4093  //
4094  DebugPrint((1, "EnumerateBusKey: Saved data was invalid, "
4095  "not enough data in registry!\n"));
4096  ExFreePool(keyData);
4097  continue;
4098  }
4099 
4100  //
4101  // Complete unicode string.
4102  //
4103 
4104  identifier.Buffer =
4105  (PWSTR)((PUCHAR)keyData + keyData->DataOffset);
4106  identifier.Length = (USHORT)keyData->DataLength;
4107  identifier.MaximumLength = (USHORT)keyData->DataLength;
4108 
4109  //
4110  // Convert unicode identifier to ansi string.
4111  //
4112 
4113  status =
4114  RtlUnicodeStringToAnsiString(&anotherString,
4115  &identifier,
4116  TRUE);
4117 
4118  if (!NT_SUCCESS(status)) {
4119  ExFreePool(keyData);
4120  continue;
4121  }
4122 
4123  //
4124  // If checksum is zero, then the MBR is valid and
4125  // the signature is meaningful.
4126  //
4127 
4128  if (diskData->MbrCheckSum) {
4129 
4130  //
4131  // Convert checksum to ansi string.
4132  //
4133 
4134  sprintf((PCHAR)buffer, "%08lx", diskData->MbrCheckSum);
4135 
4136  } else {
4137 
4138  //
4139  // Convert signature to ansi string.
4140  //
4141 
4142  sprintf((PCHAR)buffer, "%08lx", diskData->Signature);
4143 
4144  //
4145  // Make string point at signature. Can't use scan
4146  // functions because they are not exported for driver use.
4147  //
4148 
4149  anotherString.Buffer+=9;
4150  }
4151 
4152  //
4153  // Convert to ansi string.
4154  //
4155 
4156  RtlInitString(&string,
4157  (PCSZ)buffer);
4158 
4159 
4160  //
4161  // Make string lengths equal.
4162  //
4163 
4164  anotherString.Length = string.Length;
4165 
4166  //
4167  // Check if strings match.
4168  //
4169 
4170  if (RtlCompareString(&string,
4171  &anotherString,
4172  TRUE) == 0) {
4173 
4174  diskFound = TRUE;
4175  *DiskNumber = diskNumber;
4176  }
4177 
4178  ExFreePool(keyData);
4179 
4180  //
4181  // Readjust identifier string if necessary.
4182  //
4183 
4184  if (!diskData->MbrCheckSum) {
4185  anotherString.Buffer-=9;
4186  }
4187 
4188  RtlFreeAnsiString(&anotherString);
4189 
4190  if (diskFound) {
4191  break;
4192  }
4193  }
4194 
4195  ZwClose(diskKey);
4196  }
4197 
4198  ZwClose(adapterKey);
4199  }
4200 
4201  ZwClose(BusKey);
4202  return diskFound;
4203 
4204 } // end EnumerateBusKey()
4205 
4206 
4207 VOID
4208 NTAPI
4210  IN PDEVICE_EXTENSION DeviceExtension
4211  )
4212 /*++
4213 
4214 Routine Description:
4215 
4216  The routine queries the registry to determine if this disk is visible to
4217  the BIOS. If the disk is visible to the BIOS, then the geometry information
4218  is updated.
4219 
4220 Arguments:
4221 
4222  DeviceExtension - Supplies a pointer to the device information for disk.
4223 
4224 Return Value:
4225 
4226  None.
4227 
4228 --*/
4229 
4230 {
4231  OBJECT_ATTRIBUTES objectAttributes;
4232  UNICODE_STRING unicodeString;
4233  NTSTATUS status;
4234  HANDLE hardwareKey;
4235  HANDLE busKey;
4236  PCM_INT13_DRIVE_PARAMETER driveParameters;
4237  PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor;
4239  ULONG diskNumber;
4240  PUCHAR buffer;
4241  ULONG length;
4242  ULONG numberOfDrives;
4243  ULONG cylinders;
4244  ULONG sectors;
4245  ULONG sectorsPerTrack;
4246  ULONG tracksPerCylinder;
4247  BOOLEAN foundEZHooker;
4248  PVOID tmpPtr;
4249 
4250  PAGED_CODE();
4251 
4252  //
4253  // Initialize the object for the key.
4254  //
4255 
4256  InitializeObjectAttributes(&objectAttributes,
4257  DeviceExtension->DeviceObject->DriverObject->HardwareDatabase,
4259  NULL,
4261 
4262  //
4263  // Create the hardware base key.
4264  //
4265 
4266  status = ZwOpenKey(&hardwareKey,
4267  KEY_READ,
4268  &objectAttributes);
4269 
4270 
4271  if (!NT_SUCCESS(status)) {
4272  DebugPrint((1, "ScsiDisk UpdateParameters: Cannot open hardware data. Name: %wZ\n", DeviceExtension->DeviceObject->DriverObject->HardwareDatabase));
4273  return;
4274  }
4275 
4276 
4277  //
4278  // Get disk BIOS geometry information.
4279  //
4280 
4281  RtlInitUnicodeString(&unicodeString, L"Configuration Data");
4282 
4284 
4285  if (keyData == NULL) {
4286  ZwClose(hardwareKey);
4287  return;
4288  }
4289 
4290  status = ZwQueryValueKey(hardwareKey,
4291  &unicodeString,
4293  keyData,
4295  &length);
4296 
4297  if (!NT_SUCCESS(status)) {
4298  DebugPrint((1,
4299  "SCSIDISK: ExtractBiosGeometry: Can't query configuration data (%x)\n",
4300  status));
4301  ZwClose(hardwareKey);
4302  ExFreePool(keyData);
4303  return;
4304  }
4305 
4306  //
4307  // Open EISA bus key.
4308  //
4309 
4310  RtlInitUnicodeString(&unicodeString, L"EisaAdapter");
4311 
4312  InitializeObjectAttributes(&objectAttributes,
4313  &unicodeString,
4315  hardwareKey,
4317 
4318  status = ZwOpenKey(&busKey,
4319  KEY_READ,
4320  &objectAttributes);
4321 
4322  if (!NT_SUCCESS(status)) {
4323  goto openMultiKey;
4324  }
4325 
4326  DebugPrint((3,
4327  "SCSIDISK: UpdateGeometry: Opened EisaAdapter key\n"));
4328  if (EnumerateBusKey(DeviceExtension,
4329  busKey,
4330  &diskNumber)) {
4331 
4332  ZwClose(hardwareKey);
4333  goto diskMatched;
4334  }
4335 
4336 openMultiKey:
4337 
4338  //
4339  // Open Multifunction bus key.
4340  //
4341 
4342  RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter");
4343 
4344  InitializeObjectAttributes(&objectAttributes,
4345  &unicodeString,
4347  hardwareKey,
4349 
4350  status = ZwOpenKey(&busKey,
4351  KEY_READ,
4352  &objectAttributes);
4353 
4354  ZwClose(hardwareKey);
4355  if (NT_SUCCESS(status)) {
4356  DebugPrint((3,
4357  "SCSIDISK: UpdateGeometry: Opened MultifunctionAdapter key\n"));
4358  if (EnumerateBusKey(DeviceExtension,
4359  busKey,
4360  &diskNumber)) {
4361 
4362  goto diskMatched;
4363  }
4364  }
4365 
4366  ExFreePool(keyData);
4367  return;
4368 
4369 diskMatched:
4370 
4371  resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)keyData +
4372  keyData->DataOffset);
4373 
4374  //
4375  // Check that the data is long enough to hold a full resource descriptor,
4376  // and that the last resource list is device-specific and long enough.
4377  //
4378 
4379  if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) ||
4380  resourceDescriptor->PartialResourceList.Count == 0 ||
4381  resourceDescriptor->PartialResourceList.PartialDescriptors[0].Type !=
4383  resourceDescriptor->PartialResourceList.PartialDescriptors[0]
4384  .u.DeviceSpecificData.DataSize < sizeof(ULONG)) {
4385 
4386  DebugPrint((1, "SCSIDISK: ExtractBiosGeometry: BIOS header data too small or invalid\n"));
4387  ExFreePool(keyData);
4388  return;
4389  }
4390 
4391  length =
4392  resourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize;
4393 
4394  //
4395  // Point to the BIOS data. The BIOS data is located after the first
4396  // partial Resource list which should be device specific data.
4397  //
4398 
4399  buffer = (PUCHAR) keyData + keyData->DataOffset +
4401 
4402 
4403  numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
4404 
4405  //
4406  // Use the defaults if the drive number is greater than the
4407  // number of drives detected by the BIOS.
4408  //
4409 
4410  if (numberOfDrives <= diskNumber) {
4411  ExFreePool(keyData);
4412  return;
4413  }
4414 
4415  //
4416  // Point to the array of drive parameters.
4417  //
4418 
4419  driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer + diskNumber;
4420  cylinders = driveParameters->MaxCylinders + 1;
4421  sectorsPerTrack = driveParameters->SectorsPerTrack;
4422  tracksPerCylinder = driveParameters->MaxHeads +1;
4423 
4424  //
4425  // Calculate the actual number of sectors.
4426  //
4427 
4428  sectors = (ULONG)(DeviceExtension->PartitionLength.QuadPart >>
4429  DeviceExtension->SectorShift);
4430 
4431 #if DBG
4432  if (sectors >= cylinders * tracksPerCylinder * sectorsPerTrack) {
4433  DebugPrint((1, "ScsiDisk: UpdateGeometry: Disk smaller than BIOS indicated\n"
4434  "SCSIDISK: Sectors: %x, Cylinders: %x, Track per Cylinder: %x Sectors per track: %x\n",
4435  sectors, cylinders, tracksPerCylinder, sectorsPerTrack));
4436  }
4437 #endif
4438 
4439  //
4440  // Since the BIOS may not report the full drive, recalculate the drive
4441  // size based on the volume size and the BIOS values for tracks per
4442  // cylinder and sectors per track..
4443  //
4444 
4445  length = tracksPerCylinder * sectorsPerTrack;
4446 
4447  if (length == 0) {
4448 
4449  //
4450  // The BIOS information is bogus.
4451  //
4452 
4453  DebugPrint((1, "ScsiDisk UpdateParameters: sectorPerTrack zero\n"));
4454  ExFreePool(keyData);
4455  return;
4456  }
4457 
4458  cylinders = sectors / length;
4459 
4460  //
4461  // Update the actual geometry information.
4462  //
4463 
4464  DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack = sectorsPerTrack;
4465  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder;
4466  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)cylinders;
4467  DeviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG)cylinders * tracksPerCylinder * sectorsPerTrack *
4468  DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
4469 
4470  DebugPrint((3,
4471  "SCSIDISK: UpdateGeometry: BIOS spt %x, #heads %x, #cylinders %x\n",
4472  sectorsPerTrack,
4473  tracksPerCylinder,
4474  cylinders));
4475 
4476  ExFreePool(keyData);
4477 
4478  foundEZHooker = FALSE;
4479 
4480  if (!DeviceExtension->DMActive) {
4481 
4482  HalExamineMBR(DeviceExtension->DeviceObject,
4483  DeviceExtension->DiskGeometry->Geometry.BytesPerSector,
4484  (ULONG)0x55,
4485  &tmpPtr
4486  );
4487 
4488  if (tmpPtr) {
4489 
4490  ExFreePool(tmpPtr);
4491  foundEZHooker = TRUE;
4492 
4493  }
4494 
4495  }
4496 
4497  if (DeviceExtension->DMActive || foundEZHooker) {
4498 
4499  while (cylinders > 1024) {
4500 
4501  tracksPerCylinder = tracksPerCylinder*2;
4502  cylinders = cylinders/2;
4503 
4504  }
4505 
4506  //
4507  // int 13 values are always 1 less.
4508  //
4509 
4510  tracksPerCylinder -= 1;
4511  cylinders -= 1;
4512 
4513  //
4514  // DM reserves the CE cylinder
4515  //
4516 
4517  cylinders -= 1;
4518 
4519  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = cylinders + 1;
4520  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder + 1;
4521 
4522  DeviceExtension->PartitionLength.QuadPart =
4523  DeviceExtension->DiskGeometry->DiskSize.QuadPart =
4524  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart *
4525  DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack *
4526  DeviceExtension->DiskGeometry->Geometry.BytesPerSector *
4527  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder;
4528 
4529  if (DeviceExtension->DMActive) {
4530 
4531  DeviceExtension->DMByteSkew = DeviceExtension->DMSkew * DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
4532 
4533  }
4534 
4535  } else {
4536 
4537  DeviceExtension->DMByteSkew = 0;
4538 
4539  }
4540 
4541  return;
4542 
4543 } // end UpdateGeometry()
4544 
4545 
4546 
4547 NTSTATUS
4548 NTAPI
4551  IN PIRP Irp
4552  )
4553 
4554 /*++
4555 
4556 Routine Description:
4557 
4558  This routines updates the size and starting offset of the device. This is
4559  used when the media on the device may have changed thereby changing the
4560  size of the device. If this is the physical device then a
4561  ScsiClassReadDriveCapacity is done; otherewise, a read partition table is done.
4562 
4563 Arguments:
4564 
4565  DeviceObject - Supplies the device object whos size needs to be updated.
4566 
4567  Irp - Supplies a reference where the status can be updated.
4568 
4569 Return Value:
4570 
4571  Returns the status of the operation.
4572 
4573 --*/
4574 {
4575 
4576  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4577  PDRIVE_LAYOUT_INFORMATION partitionList;
4578  NTSTATUS status;
4579  PDISK_DATA diskData;
4580  ULONG partitionNumber;
4581 
4582  //
4583  // Determine if the size of the partition may have changed because
4584  // the media has changed.
4585  //
4586 
4587  if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
4588 
4589  return(STATUS_SUCCESS);
4590 
4591  }
4592 
4593  //
4594  // If this request is for partition zero then do a read drive
4595  // capacity otherwise do a I/O read partition table.
4596  //
4597 
4598  diskData = (PDISK_DATA) (deviceExtension + 1);
4599 
4600  //
4601  // Read the drive capacity. If that fails, give up.
4602  //
4603 
4604  status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
4605 
4606  if (!NT_SUCCESS(status)) {
4607  return(status);
4608  }
4609 
4610 #ifdef __REACTOS__
4611  //
4612  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
4613  // for removable devices and avoid an infinite recursive loop between
4614  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
4615  //
4616  // Check whether the update-count is greater or equal than one
4617  // (and increase it) and if so, reset it and return success.
4618  if (diskData->UpdateRemovableGeometryCount++ >= 1)
4619  {
4620  diskData->UpdateRemovableGeometryCount = 0;
4621  return(STATUS_SUCCESS);
4622  }
4623 #endif
4624 
4625  //
4626  // Read the partition table again.
4627  //
4628 
4629  status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
4630  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
4631  TRUE,
4632  &partitionList);
4633 
4634 #ifdef __REACTOS__
4635  //
4636  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
4637  // for removable devices and avoid an infinite recursive loop between
4638  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
4639  //
4640  // Inconditionally reset the update-count.
4641  diskData->UpdateRemovableGeometryCount = 0;
4642 #endif
4643 
4644  if (!NT_SUCCESS(status)) {
4645 
4646  //
4647  // Fail the request.
4648  //
4649 
4650  return(status);
4651  }
4652 
4653  if (diskData->PartitionNumber != 0 &&
4654  diskData->PartitionNumber <= partitionList->PartitionCount ) {
4655 
4656  partitionNumber = diskData->PartitionNumber - 1;
4657 
4658  //
4659  // Update the partition information for this partition.
4660  //
4661 
4662  diskData->PartitionType =
4663  partitionList->PartitionEntry[partitionNumber].PartitionType;
4664 
4665  diskData->BootIndicator =
4666  partitionList->PartitionEntry[partitionNumber].BootIndicator;
4667 
4668  deviceExtension->StartingOffset =
4669  partitionList->PartitionEntry[partitionNumber].StartingOffset;
4670 
4671  deviceExtension->PartitionLength =
4672  partitionList->PartitionEntry[partitionNumber].PartitionLength;
4673 
4674  diskData->HiddenSectors =
4675  partitionList->PartitionEntry[partitionNumber].HiddenSectors;
4676 
4677  deviceExtension->SectorShift = ((PDEVICE_EXTENSION)
4678  deviceExtension->PhysicalDevice->DeviceExtension)->SectorShift;
4679 
4680  } else if (diskData->PartitionNumber != 0) {
4681 
4682  //
4683  // The partition does not exist. Zero all the data.
4684  //
4685 
4686  diskData->PartitionType = 0;
4687  diskData->BootIndicator = 0;
4688  diskData->HiddenSectors = 0;
4689  deviceExtension->StartingOffset.QuadPart = (LONGLONG)0;
4690  deviceExtension->PartitionLength.QuadPart = (LONGLONG)0;
4691  }
4692 
4693  //
4694  // Free the partition list allocate by I/O read partition table.
4695  //
4696 
4697  ExFreePool(partitionList);
4698 
4699 
4700  return(STATUS_SUCCESS);
4701 }
4702 
4703 
4704 VOID
4705 NTAPI
4709  NTSTATUS *Status,
4710  BOOLEAN *Retry
4711  )
4712 /*++
4713 
4714 Routine Description:
4715 
4716  This routine checks the type of error. If the error indicates an underrun
4717  then indicate the request should be retried.
4718 
4719 Arguments:
4720 
4721  DeviceObject - Supplies a pointer to the device object.
4722 
4723  Srb - Supplies a pointer to the failing Srb.
4724 
4725  Status - Status with which the IRP will be completed.
4726 
4727  Retry - Indication of whether the request will be retried.
4728 
4729 Return Value:
4730 
4731  None.
4732 
4733 --*/
4734 
4735 {
4736  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4737 
4738  if (*Status == STATUS_DATA_OVERRUN &&
4739  ( Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_READ)) {
4740 
4741  *Retry = TRUE;
4742 
4743  //
4744  // Update the error count for the device.
4745  //
4746 
4747  deviceExtension->ErrorCount++;
4748  }
4749 
4750  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_ERROR &&
4751  Srb->ScsiStatus == SCSISTAT_BUSY) {
4752 
4753  //
4754  // The disk drive should never be busy this long. Reset the scsi bus
4755  // maybe this will clear the condition.
4756  //
4757 
4759 
4760  //
4761  // Update the error count for the device.
4762  //
4763 
4764  deviceExtension->ErrorCount++;
4765  }
4766 }
4767 
4768 VOID
4769 NTAPI
4772  PSCSI_INQUIRY_DATA LunInfo,
4773  PIO_SCSI_CAPABILITIES PortCapabilities
4774  )
4775 
4776 /*++
4777 
4778 Routine Description:
4779 
4780  This function checks to see if an SCSI logical unit requires special
4781  flags to be set.
4782 
4783 Arguments:
4784 
4785  DeviceObject - Supplies the device object to be tested.
4786 
4787  InquiryData - Supplies the inquiry data returned by the device of interest.
4788 
4789  PortCapabilities - Supplies the capabilities of the device object.
4790 
4791 Return Value:
4792 
4793  None.
4794 
4795 --*/
4796 
4797 {
4798  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4799  PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
4800  BAD_CONTROLLER_INFORMATION const *controller;
4801  ULONG j;
4802 
4803  for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) {
4804 
4805  controller = &ScsiDiskBadControllers[j];
4806 
4807  if (strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) {
4808  continue;
4809  }
4810 
4811  DebugPrint((1, "ScsiDisk ScanForSpecial, Found bad controller! %s\n", controller->InquiryString));
4812 
4813  //
4814  // Found a listed controller. Determine what must be done.
4815  //
4816 
4817  if (controller->DisableTaggedQueuing) {
4818 
4819  //
4820  // Disable tagged queuing.
4821  //
4822 
4823  deviceExtension->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
4824  }
4825 
4826  if (controller->DisableSynchronousTransfers) {
4827 
4828  //
4829  // Disable synchronous data transfers.
4830  //
4831 
4832  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
4833 
4834  }
4835 
4836  if (controller->DisableDisconnects) {
4837 
4838  //
4839  // Disable disconnects.
4840  //
4841 
4842  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
4843 
4844  }
4845 
4846  //
4847  // Found device so exit the loop and return.
4848  //
4849 
4850  break;
4851  }
4852 
4853  //
4854  // Set the StartUnit flag appropriately.
4855  //
4856 
4857  if (DeviceObject->DeviceType == FILE_DEVICE_DISK) {
4858  deviceExtension->DeviceFlags |= DEV_SAFE_START_UNIT;
4859 
4860  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
4861  if (_strnicmp((PCCHAR)InquiryData->VendorId, "iomega", strlen("iomega"))) {
4862  deviceExtension->DeviceFlags &= ~DEV_SAFE_START_UNIT;
4863  }
4864  }
4865  }
4866 
4867  return;
4868 }
4869 
4870 VOID
4871 NTAPI
4874  )
4875 
4876 /*++
4877 
4878 Routine Description:
4879 
4880  This command sends a reset bus command to the SCSI port driver.
4881 
4882 Arguments:
4883 
4884  DeviceObject - The device object for the logical unit with
4885  hardware problem.
4886 
4887 Return Value:
4888 
4889  None.
4890 
4891 --*/
4892 {
4893  PIO_STACK_LOCATION irpStack;
4894  PIRP irp;
4895  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4896  PSCSI_REQUEST_BLOCK srb;
4898 
4899  DebugPrint((1, "ScsiDisk ResetScsiBus: Sending reset bus request to port driver.\n"));
4900 
4901  //
4902  // Allocate Srb from nonpaged pool.
4903  //
4904 
4906  sizeof(COMPLETION_CONTEXT));
4907 
4908  //
4909  // Save the device object in the context for use by the completion
4910  // routine.
4911  //
4912 
4913  context->DeviceObject = DeviceObject;
4914  srb = &context->Srb;
4915 
4916  //
4917  // Zero out srb.
4918  //
4919 
4921 
4922  //
4923  // Write length to SRB.
4924  //
4925 
4927 
4928  //
4929  // Set up SCSI bus address.
4930  //
4931 
4932  srb->PathId = deviceExtension->PathId;
4933  srb->TargetId = deviceExtension->TargetId;
4934  srb->Lun = deviceExtension->Lun;
4935 
4937 
4938  //
4939  // Build the asynchronous request to be sent to the port driver.
4940  // Since this routine is called from a DPC the IRP should always be
4941  // available.
4942  //
4943 
4945 
4948  context,
4949  TRUE,
4950  TRUE,
4951  TRUE);
4952 
4953  irpStack = IoGetNextIrpStackLocation(irp);
4954 
4955  irpStack->MajorFunction = IRP_MJ_SCSI;
4956 
4957  srb->OriginalRequest = irp;
4958 
4959  //
4960  // Store the SRB address in next stack for port driver.
4961  //
4962 
4963  irpStack->Parameters.Scsi.Srb = srb;
4964 
4965  //
4966  // Call the port driver with the IRP.
4967  //
4968 
4969  IoCallDriver(deviceExtension->PortDeviceObject, irp);
4970 
4971  return;
4972 
4973 } // end ResetScsiBus()
4974 
4975 
4976 VOID
4977 NTAPI
4979  IN PDEVICE_OBJECT PhysicalDisk,
4980  IN PIRP Irp
4981  )
4982 
4983 /*++
4984 
4985 Routine Description:
4986 
4987  This routine creates, deletes and changes device objects when
4988  the IOCTL_SET_DRIVE_LAYOUT is called. This routine also updates
4989  the drive layout information for the user. It is possible to
4990  call this routine even in the GET_LAYOUT case because RewritePartition
4991  will be false.
4992 
4993 Arguments:
4994 
4995  DeviceObject - Device object for physical disk.
4996  Irp - IO Request Packet (IRP).
4997 
4998 Return Value:
4999 
5000  None.
5001 
5002 --*/
5003 {
5004  PDEVICE_EXTENSION physicalExtension = PhysicalDisk->DeviceExtension;
5005  PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer;
5006  ULONG partition;
5007  ULONG partitionNumber;
5008  ULONG partitionCount;
5009  ULONG lastPartition;
5010  ULONG partitionOrdinal;
5011  PPARTITION_INFORMATION partitionEntry;
5012  CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
5013  STRING ntNameString;
5014  UNICODE_STRING ntUnicodeString;
5015  PDEVICE_OBJECT deviceObject;
5016  PDEVICE_EXTENSION deviceExtension;
5017  PDISK_DATA diskData;
5018  NTSTATUS status;
5019  ULONG numberListElements;
5020  BOOLEAN found;
5021 
5022  partitionCount = ((partitionList->PartitionCount + 3) / 4) * 4;
5023 
5024  //
5025  // Zero all of the partition numbers.
5026  //
5027 
5028  for (partition = 0; partition < partitionCount; partition++) {
5029  partitionEntry = &partitionList->PartitionEntry[partition];
5030  partitionEntry->PartitionNumber = 0;
5031  }
5032 
5033  //
5034  // Walk through chain of partitions for this disk to determine
5035  // which existing partitions have no match.
5036  //
5037 
5038  deviceExtension = physicalExtension;
5039  diskData = (PDISK_DATA)(deviceExtension + 1);
5040  lastPartition = 0;
5041 
5042  do {
5043 
5044  deviceExtension = diskData->NextPartition;
5045 
5046  //
5047  // Check if this is the last partition in the chain.
5048  //
5049 
5050  if (!deviceExtension) {
5051  break;
5052  }
5053 
5054  //
5055  // Get the partition device extension from disk data.
5056  //
5057 
5058  diskData = (PDISK_DATA)(deviceExtension + 1);
5059 
5060  //
5061  // Check for highest partition number this far.
5062  //
5063 
5064  if (diskData->PartitionNumber > lastPartition) {
5065  lastPartition = diskData->PartitionNumber;
5066  }
5067 
5068  //
5069  // Check if this partition is not currently being used.
5070  //
5071 
5072  if (!deviceExtension->PartitionLength.QuadPart) {
5073  continue;
5074  }
5075 
5076  //
5077  // Loop through partition information to look for match.
5078  //
5079 
5080  found = FALSE;
5081  partitionOrdinal = 0;
5082 
5083  for (partition = 0; partition < partitionCount; partition++) {
5084 
5085  //
5086  // Get partition descriptor.
5087  //
5088 
5089  partitionEntry = &partitionList->PartitionEntry[partition];
5090 
5091  //
5092  // Check if empty, or describes extended partition or hasn't changed.
5093  //
5094 
5095  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
5096  IsContainerPartition(partitionEntry->PartitionType)) {
5097  continue;
5098  }
5099 
5100  //
5101  // Advance partition ordinal.
5102  //
5103 
5104  partitionOrdinal++;
5105 
5106  //
5107  // Check if new partition starts where this partition starts.
5108  //
5109 
5110  if (partitionEntry->StartingOffset.QuadPart !=
5111  deviceExtension->StartingOffset.QuadPart) {
5112  continue;
5113  }
5114 
5115  //
5116  // Check if partition length is the same.
5117  //
5118 
5119  if (partitionEntry->PartitionLength.QuadPart ==
5120  deviceExtension->PartitionLength.QuadPart) {
5121 
5122  DebugPrint((3,
5123  "UpdateDeviceObjects: Found match for \\Harddisk%d\\Partition%d\n",
5124  physicalExtension->DeviceNumber,
5125  diskData->PartitionNumber));
5126 
5127  //
5128  // Indicate match is found and set partition number
5129  // in user buffer.
5130  //
5131 
5132  found = TRUE;
5133  partitionEntry->PartitionNumber = diskData->PartitionNumber;
5134  break;
5135  }
5136  }
5137 
5138  if (found) {
5139 
5140  //
5141  // A match is found.
5142  //
5143 
5144  diskData = (PDISK_DATA)(deviceExtension + 1);
5145 
5146  //
5147  // If this partition is marked for update then update partition type.
5148  //
5149 
5150  if (partitionEntry->RewritePartition) {
5151  diskData->PartitionType = partitionEntry->PartitionType;
5152  }
5153 
5154  //
5155  // Update partitional ordinal for calls to HAL routine
5156  // IoSetPartitionInformation.
5157  //
5158 
5159  diskData->PartitionOrdinal = partitionOrdinal;
5160 
5161  DebugPrint((1,
5162  "UpdateDeviceObjects: Disk %d ordinal %d is partition %d\n",
5163  physicalExtension->DeviceNumber,
5164  diskData->PartitionOrdinal,
5165  diskData->PartitionNumber));
5166 
5167  } else {
5168 
5169  //
5170  // no match was found, indicate this partition is gone.
5171  //
5172 
5173  DebugPrint((1,
5174  "UpdateDeviceObjects: Deleting \\Device\\Harddisk%x\\Partition%x\n",
5175  physicalExtension->DeviceNumber,
5176  diskData->PartitionNumber));
5177 
5178  deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0;
5179  }
5180 
5181  } while (TRUE);
5182 
5183  //
5184  // Walk through partition loop to find new partitions and set up
5185  // device extensions to describe them. In some cases new device
5186  // objects will be created.
5187  //
5188 
5189  partitionOrdinal = 0;
5190 
5191  for (partition = 0;
5192  partition < partitionCount;
5193  partition++) {
5194 
5195  //
5196  // Get partition descriptor.
5197  //
5198 
5199  partitionEntry = &partitionList->PartitionEntry[partition];
5200 
5201  //
5202  // Check if empty, or describes an extended partition.
5203  //
5204 
5205  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
5206  IsContainerPartition(partitionEntry->PartitionType)) {
5207  continue;
5208  }
5209 
5210  //
5211  // Keep track of position on the disk for calls to IoSetPartitionInformation.
5212  //
5213 
5214  partitionOrdinal++;
5215 
5216  //
5217  // Check if this entry should be rewritten.
5218  //
5219 
5220  if (!partitionEntry->RewritePartition) {
5221  continue;
5222  }
5223 
5224  if (partitionEntry->PartitionNumber) {
5225 
5226  //
5227  // Partition is an exact match with an existing partition, but is
5228  // being written anyway.
5229  //
5230 
5231  continue;
5232  }
5233 
5234  //
5235  // Check first if existing device object is available by
5236  // walking partition extension list.
5237  //
5238 
5239  partitionNumber = 0;
5240  deviceExtension = physicalExtension;
5241  diskData = (PDISK_DATA)(deviceExtension + 1);
5242 
5243  do {
5244 
5245  //
5246  // Get next partition device extension from disk data.
5247  //
5248 
5249  deviceExtension = diskData->NextPartition;
5250 
5251  if (!deviceExtension) {
5252  break;
5253  }
5254 
5255  diskData = (PDISK_DATA)(deviceExtension + 1);
5256 
5257  //
5258  // A device object is free if the partition length is set to zero.
5259  //
5260 
5261  if (!deviceExtension->PartitionLength.QuadPart) {
5262  partitionNumber = diskData->PartitionNumber;
5263  break;
5264  }
5265 
5266  } while (TRUE);
5267 
5268  //
5269  // If partition number is still zero then a new device object
5270  // must be created.
5271  //
5272 
5273  if (partitionNumber == 0) {
5274 
5275  lastPartition++;
5276  partitionNumber = lastPartition;
5277 
5278  //
5279  // Get or create partition object and set up partition parameters.
5280  //
5281 
5282  sprintf(ntNameBuffer,
5283  "\\Device\\Harddisk%lu\\Partition%lu",
5284  physicalExtension->DeviceNumber,
5285  partitionNumber);
5286 
5287  RtlInitString(&ntNameString,
5288  ntNameBuffer);
5289 
5290  status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
5291  &ntNameString,
5292  TRUE);
5293 
5294  if (!NT_SUCCESS(status)) {
5295  continue;
5296  }
5297 
5298  DebugPrint((3,
5299  "UpdateDeviceObjects: Create device object %s\n",
5300  ntNameBuffer));
5301 
5302  //
5303  // This is a new name. Create the device object to represent it.
5304  //
5305 
5306  status = IoCreateDevice(PhysicalDisk->DriverObject,
5308  &ntUnicodeString,
5310  0,
5311  FALSE,
5312  &deviceObject);
5313 
5314  if (!NT_SUCCESS(status)) {
5315  DebugPrint((1,
5316  "UpdateDeviceObjects: Can't create device %s\n",
5317  ntNameBuffer));
5318  RtlFreeUnicodeString(&ntUnicodeString);
5319  continue;
5320  }
5321 
5322  //
5323  // Set up device object fields.
5324  //
5325 
5326  deviceObject->Flags |= DO_DIRECT_IO;
5327  deviceObject->StackSize = PhysicalDisk->StackSize;
5328 
5329  //
5330  // Set up device extension fields.
5331  //
5332 
5333  deviceExtension = deviceObject->DeviceExtension;
5334 
5335  //
5336  // Copy physical disk extension to partition extension.
5337  //
5338 
5339  RtlMoveMemory(deviceExtension,
5340  physicalExtension,
5341  sizeof(DEVICE_EXTENSION));
5342 
5343  //
5344  // Initialize the new S-List.
5345  //
5346 
5347  if (deviceExtension->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
5348  numberListElements = 30;
5349  } else {
5350  numberListElements = 8;
5351  }
5352 
5353  //
5354  // Build the lookaside list for srb's for this partition based on
5355  // whether the adapter and disk can do tagged queueing.
5356  //
5357 
5358  ScsiClassInitializeSrbLookasideList(deviceExtension,
5359  numberListElements);
5360 
5361  //
5362  // Allocate spinlock for zoning for split-request completion.
5363  //
5364 
5365  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
5366 
5367  //
5368  // Write back partition number used in creating object name.
5369  //
5370 
5371  partitionEntry->PartitionNumber = partitionNumber;
5372 
5373  //
5374  // Clear flags initializing bit.
5375  //
5376 
5377  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
5378 
5379  //
5380  // Point back at device object.
5381  //
5382 
5383  deviceExtension->DeviceObject = deviceObject;
5384 
5385  RtlFreeUnicodeString(&ntUnicodeString);
5386 
5387  //
5388  // Link to end of partition chain using previous disk data.
5389  //
5390 
5391  diskData->NextPartition = deviceExtension;
5392 
5393  //
5394  // Get new disk data and zero next partition pointer.
5395  //
5396 
5397  diskData = (PDISK_DATA)(deviceExtension + 1);
5398  diskData->NextPartition = NULL;
5399 
5400  } else {
5401 
5402  //
5403  // Set pointer to disk data area that follows device extension.
5404  //
5405 
5406  diskData = (PDISK_DATA)(deviceExtension + 1);
5407 
5408  DebugPrint((1,
5409  "UpdateDeviceObjects: Used existing device object \\Device\\Harddisk%x\\Partition%x\n",
5410  physicalExtension->DeviceNumber,
5411  partitionNumber));
5412  }
5413 
5414  //
5415  // Update partition information in partition device extension.
5416  //
5417 
5418  diskData->PartitionNumber = partitionNumber;
5419  diskData->PartitionType = partitionEntry->PartitionType;
5420  diskData->BootIndicator = partitionEntry->BootIndicator;
5421  deviceExtension->StartingOffset = partitionEntry->StartingOffset;
5422  deviceExtension->PartitionLength = partitionEntry->PartitionLength;
5423  diskData->HiddenSectors = partitionEntry->HiddenSectors;
5424  diskData->PartitionOrdinal = partitionOrdinal;
5425 
5426  DebugPrint((1,
5427  "UpdateDeviceObjects: Ordinal %d is partition %d\n",
5428  diskData->PartitionOrdinal,
5429  diskData->PartitionNumber));
5430 
5431  //
5432  // Update partition number passed in to indicate the
5433  // device name for this partition.
5434  //
5435 
5436  partitionEntry->PartitionNumber = partitionNumber;
5437  }
5438 
5439 } // end UpdateDeviceObjects()
5440 
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
signed char * PCHAR
Definition: retypes.h:7
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
Definition: ntddk_ex.h:208
struct _FOUR_BYTE * PFOUR_BYTE
CONST char * PCSZ
Definition: umtypes.h:125
NTSTATUS NTAPI CreatePartitionDeviceObjects(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PUNICODE_STRING RegistryPath)
Definition: disk.c:1196
#define IO_WRITE_CACHE_ENABLED
Definition: ntiologc.h:59
#define SCSIOP_REASSIGN_BLOCKS
Definition: cdrw_hw.h:873
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
struct _CM_INT13_DRIVE_PARAMETER CM_INT13_DRIVE_PARAMETER
struct _DISK_DATA * PDISK_DATA
#define IN
Definition: typedefs.h:38
#define FILE_DEVICE_DISK
Definition: winioctl.h:112
VOID NTAPI ReportToMountMgr(IN PDEVICE_OBJECT DiskDeviceObject)
Definition: disk.c:1073
NTSTATUS NTAPI CreateDiskDeviceObject(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath, IN PDEVICE_OBJECT PortDeviceObject, IN ULONG PortNumber, IN PULONG DeviceCount, IN PIO_SCSI_CAPABILITIES PortCapabilities, IN PSCSI_INQUIRY_DATA LunInfo, IN PCLASS_INIT_DATA InitData)
Definition: disk.c:621
WCHAR DeviceName[1]
Definition: imports.h:155
DEVICE_TYPE DeviceType
Definition: class2.h:84
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define SCSIOP_SYNCHRONIZE_CACHE
Definition: cdrw_hw.h:918
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:394
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
Definition: cdrw_hw.h:1459
ULONG SrbFlags
Definition: srb.h:252
struct _MODE_PARAMETER_HEADER MODE_PARAMETER_HEADER
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
NTSYSAPI LONG NTAPI RtlCompareString(PSTRING String1, PSTRING String2, BOOLEAN CaseInSensitive)
PVOID OriginalRequest
Definition: srb.h:258
#define IO_WRITE_CACHE_DISABLED
Definition: ntiologc.h:61
UCHAR Cdb[16]
Definition: srb.h:271
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
#define STATUS_DATA_OVERRUN
Definition: udferr_usr.h:152
#define MODE_PAGE_CACHING
Definition: cdrw_hw.h:846
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define IOCTL_DISK_INTERNAL_SET_VERIFY
Definition: ntdddisk.h:109
Definition: http.c:6587
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
struct _BAD_CONTROLLER_INFORMATION BAD_CONTROLLER_INFORMATION
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
PDRIVER_STARTIO ClassStartIo
Definition: class2.h:93
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Definition: iorsrce.c:830
#define IRP_MJ_SHUTDOWN
#define IOCTL_SCSI_MINIPORT
Definition: scsi_port.h:48
NTSTATUS FinalStatus
Definition: iotypes.h:1966
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define KEY_READ
Definition: nt_native.h:1023
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define MODE_DSP_WRITE_PROTECT
Definition: cdrw_hw.h:2523
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
BOOLEAN BootIndicator
Definition: disk.c:104
#define SMART_GET_VERSION
Definition: ntdddisk.h:194
PCLASS_FIND_DEVICES ClassFindDevices
Definition: class2.h:89
unsigned char * PUCHAR
Definition: retypes.h:3
VOID NTAPI ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension, IN ULONG NumberElements)
Definition: class2.c:5093
#define ENABLE_DISABLE_AUTOSAVE
Definition: ntdddisk.h:630
struct _MODE_PARAMETER_BLOCK MODE_PARAMETER_BLOCK
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI ScsiDiskCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:2707
BOOLEAN NTAPI IsFloppyDevice(IN PDEVICE_OBJECT DeviceObject)
ULONG NTAPI ScsiClassInitialize(IN PVOID Argument1, IN PVOID Argument2, IN PCLASS_INIT_DATA InitializationData)
Definition: class2.c:451
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define MODE_SENSE_RETURN_ALL
Definition: cdrw_hw.h:857
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
struct _SENDCMDOUTPARAMS SENDCMDOUTPARAMS
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
UCHAR CdbLength
Definition: srb.h:250
#define OBJ_PERMANENT
Definition: winternl.h:226
GLuint buffer
Definition: glext.h:5915
#define IDENTIFY_BUFFER_SIZE
Definition: ntdddisk.h:616
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
VOID NTAPI ScsiDiskProcessError(PDEVICE_OBJECT DeviceObject, PSCSI_REQUEST_BLOCK Srb, NTSTATUS *Status, BOOLEAN *Retry)
Definition: disk.c:4706
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:245
ULONG HiddenSectors
Definition: disk.c:64
ULONG ControlCode
Definition: scsi_port.h:128
struct _INQUIRYDATA * PINQUIRYDATA
ULONG BytesPerSector
Definition: ntdddisk.h:376
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define DISABLE_SMART
Definition: ntdddisk.h:636
VOID NTAPI UpdateGeometry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: disk.c:4209
ULONG NextInquiryDataOffset
Definition: scsi_port.h:118
UCHAR QueueAction
Definition: srb.h:249
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1114
struct _CDB::_CDB10 CDB10
UCHAR VendorId[8]
Definition: cdrw_hw.h:1132
NTSTATUS ScsiClassGetInquiryData(IN PDEVICE_OBJECT PortDeviceObject, IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo)
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
struct _PARTITION_INFORMATION PARTITION_INFORMATION
BOOLEAN NTAPI ScsiDiskModeSelect(IN PDEVICE_OBJECT DeviceObject, IN PCHAR ModeSelectBuffer, IN ULONG Length, IN BOOLEAN SavePage)
Definition: disk.c:3416
ULONG TimeOutValue
Definition: srb.h:254
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
UCHAR SrbStatus
Definition: srb.h:243
#define SRB_STATUS(Status)
Definition: srb.h:381
VOID NTAPI IoWriteErrorLogEntry(IN PVOID ElEntry)
Definition: error.c:620
NTSTATUS NTAPI ScsiDiskReadWriteVerification(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: disk.c:1638
PCLASS_READ_WRITE ClassReadWriteVerification
Definition: class2.h:87
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:76
#define MAXIMUM_FILENAME_LENGTH
Definition: env_spec_w32.h:41
#define ENABLE_SMART
Definition: ntdddisk.h:635
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
#define PAGED_CODE()
Definition: video.h:57
LARGE_INTEGER Length
Definition: imports.h:232
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION
Definition: imports.h:130
#define DEV_WRITE_CACHE
Definition: class2.h:21
#define DEVICE_EXTENSION_SIZE
Definition: disk.c:162
ULONG PartitionOrdinal
Definition: disk.c:79
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
#define IOCTL_DISK_FIND_NEW_DEVICES
Definition: cdrw_usr.h:181
PDEVICE_EXTENSION NextPartition
Definition: disk.c:46
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define SP_UNTAGGED
Definition: srb.h:225
#define IRP_MJ_SCSI
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SRB_STATUS_ERROR
Definition: srb.h:336
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
struct _DISK_GEOMETRY_EX DISK_GEOMETRY_EX
SCSI_BUS_DATA BusData[1]
Definition: scsi_port.h:106
#define sprintf(buf, format,...)
Definition: sprintf.c:55
ULONG PartitionNumber
Definition: disk.c:73
PARTITION_STYLE PartitionStyle
Definition: imports.h:220
struct _BAD_CONTROLLER_INFORMATION * PBAD_CONTROLLER_INFORMATION
VOID NTAPI ResetScsiBus(IN PDEVICE_OBJECT DeviceObject)
Definition: disk.c:4872
#define VALUE_BUFFER_SIZE
Definition: disk.c:165
struct _SENDCMDINPARAMS SENDCMDINPARAMS
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
NTSTATUS ErrorCode
Definition: iotypes.h:1964
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
NTSTATUS NTAPI ScsiDiskDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
Definition: cdrw_hw.h:1464
#define MODE_DATA_SIZE
Definition: disk.c:164
VOID NTAPI ScanForSpecial(PDEVICE_OBJECT DeviceObject, PSCSI_INQUIRY_DATA LunInfo, PIO_SCSI_CAPABILITIES PortCapabilities)
Definition: disk.c:4770
long LONG
Definition: pedump.c:60
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@375 u
#define IOCTL_DISK_VERIFY
Definition: cdrw_usr.h:170
PVOID NTAPI ScsiClassFindModePage(IN PCHAR ModeSenseBuffer, IN ULONG Length, IN UCHAR PageMode, IN BOOLEAN Use6Byte)
Definition: class2.c:3610
ULONG DeviceCount
Definition: mpu401.c:26
NTSTATUS NTAPI ScsiDiskFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
struct _DRIVE_LAYOUT_INFORMATION DRIVE_LAYOUT_INFORMATION
#define SCSIOP_READ
Definition: cdrw_hw.h:905
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
DISK_GEOMETRY Geometry
Definition: ntdddisk.h:380
struct _GET_LENGTH_INFORMATION GET_LENGTH_INFORMATION
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
NTSYSAPI NTSTATUS NTAPI ZwCreateDirectoryObject(_Out_ PHANDLE DirectoryHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
Definition: class2.c:1029
ULONG PortNumber
Definition: storport.c:18
PVOID DeviceExtension
Definition: env_spec_w32.h:418
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
VOID NTAPI UpdateDeviceObjects(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: disk.c:4978
smooth NULL
Definition: ftsmooth.c:416
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:471
#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
Definition: cdrw_hw.h:1460
ULONG DeviceExtensionSize
Definition: class2.h:83
struct _REASSIGN_BLOCKS REASSIGN_BLOCKS
UCHAR PartitionType
Definition: disk.c:94
union _CDB * PCDB
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define IoCompleteRequest
Definition: irp.c:1240
IN PSCSI_REQUEST_BLOCK IN OUT NTSTATUS IN OUT BOOLEAN * Retry
Definition: class2.h:49
void DPRINT(...)
Definition: polytest.cpp:61
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
struct _MODE_PARAMETER_HEADER * PMODE_PARAMETER_HEADER
UCHAR DeviceTypeQualifier
Definition: cdrw_hw.h:1117
#define READ_THRESHOLD_BUFFER_SIZE
Definition: ntdddisk.h:617
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
switch(r->id)
Definition: btrfs.c:2932
void * PVOID
Definition: retypes.h:9
UCHAR QueueTag
Definition: srb.h:248
UCHAR TargetId
Definition: srb.h:246
#define RETURN_SMART_STATUS
Definition: ntdddisk.h:637
ULONG InquiryDataOffset
Definition: scsi_port.h:98
#define READ_ATTRIBUTE_BUFFER_SIZE
Definition: ntdddisk.h:615
#define IOCTL_DISK_SET_PARTITION_INFO
Definition: ntdddisk.h:176
struct _DISK_DATA DISK_DATA
#define SCSI_DISK_TIMEOUT
Definition: disk.c:166
#define SMART_RCV_DRIVE_DATA
Definition: ntdddisk.h:197
#define EXECUTE_OFFLINE_DIAGS
Definition: ntdddisk.h:632
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
struct _CDB::_MODE_SELECT MODE_SELECT
#define SRB_FUNCTION_FLUSH
Definition: srb.h:315
NTSTATUS NTAPI ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN PCCHAR ObjectNameBuffer, IN OPTIONAL PDEVICE_OBJECT PhysicalDeviceObject, IN OUT PDEVICE_OBJECT *DeviceObject, IN PCLASS_INIT_DATA InitializationData)
Definition: class2.c:4679
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
PVOID NTAPI IoAllocateErrorLogEntry(IN PVOID IoObject, IN UCHAR EntrySize)
Definition: error.c:520
#define DIRECT_ACCESS_DEVICE
Definition: cdrw_hw.h:1144
int64_t LONGLONG
Definition: typedefs.h:66
VOID NTAPI DisableWriteCache(IN PDEVICE_OBJECT DeviceObject, IN PSCSI_INQUIRY_DATA LunInfo)
Definition: disk.c:3552
#define ID_CMD
Definition: helper.h:20
#define READ_THRESHOLDS
Definition: ntdddisk.h:629
BOOLEAN DriveNotReady
Definition: disk.c:111
#define SAVE_ATTRIBUTE_VALUES
Definition: ntdddisk.h:631
ULONG NTAPI ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject, IN PCHAR ModeSenseBuffer, IN ULONG Length, IN UCHAR PageMode)
Definition: class2.c:3513
_Outptr_ PDEVICE_OBJECT * DiskDeviceObject
Definition: fltkernel.h:1673
ULONG Signature
Definition: disk.c:52
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@375::@384 DeviceSpecificData
IDEREGS irDriveRegs
Definition: helper.h:32
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCE