ReactOS  0.4.13-dev-52-g0efcfec
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 (IsFloppyDevice(deviceObject) && deviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
973  (((PINQUIRYDATA)LunInfo->InquiryData)->DeviceType == DIRECT_ACCESS_DEVICE)) {
974 
976  goto CreateDiskDeviceObjectsExit;
977  }
978 
979  DisableWriteCache(deviceObject,LunInfo);
980 
981  //writeCache = deviceExtension->DeviceFlags & DEV_WRITE_CACHE;
982 
983  //
984  // NOTE: At this point one device object has been successfully created.
985  // from here on out return success.
986  //
987 
988  //
989  // Do READ CAPACITY. This SCSI command
990  // returns the number of bytes on a device.
991  // Device extension is updated with device size.
992  //
993 
994  status = ScsiClassReadDriveCapacity(deviceObject);
995 
996  //
997  // If the read capacity failed then just return, unless this is a
998  // removable disk where a device object partition needs to be created.
999  //
1000 
1001  if (!NT_SUCCESS(status) &&
1002  !(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
1003 
1004  DebugPrint((1,
1005  "CreateDiskDeviceObjects: Can't read capacity for device %s\n",
1006  ntNameBuffer));
1007 
1008  return(STATUS_SUCCESS);
1009 
1010  } else {
1011 
1012  //
1013  // Make sure the volume verification bit is off so that
1014  // IoReadPartitionTable will work.
1015  //
1016 
1017  deviceObject->Flags &= ~DO_VERIFY_VOLUME;
1018  }
1019 
1021 
1022  if (NT_SUCCESS(status))
1023  return STATUS_SUCCESS;
1024 
1025 
1026 CreateDiskDeviceObjectsExit:
1027 
1028  //
1029  // Release the device since an error occurred.
1030  //
1031 
1032  ScsiClassClaimDevice(PortDeviceObject,
1033  LunInfo,
1034  TRUE,
1035  NULL);
1036 
1037  if (diskGeometry != NULL) {
1038  ExFreePool(diskGeometry);
1039  }
1040 
1041  if (senseData != NULL) {
1042  ExFreePool(senseData);
1043  }
1044 
1045  if (deviceObject != NULL) {
1046 
1047  if (srbListInitialized) {
1048  ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
1049  }
1050 
1051  IoDeleteDevice(deviceObject);
1052  }
1053 
1054  //
1055  // Delete directory and return.
1056  //
1057 
1058  if (!NT_SUCCESS(status)) {
1060  }
1061 
1062  ZwClose(handle);
1063 
1064  return(status);
1065 
1066 } // end CreateDiskDeviceObjects()
1067 
1068 
1069 NTSTATUS
1070 NTAPI
1074  )
1075 {
1076  CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
1077  ULONG partitionNumber = 0;
1078  NTSTATUS status;
1079  PDEVICE_OBJECT deviceObject = NULL;
1080  PDISK_GEOMETRY_EX diskGeometry = NULL;
1081  PDRIVE_LAYOUT_INFORMATION partitionList = NULL;
1082  PDEVICE_EXTENSION deviceExtension;
1083  PDEVICE_EXTENSION physicalDeviceExtension;
1084  PCLASS_INIT_DATA initData = NULL;
1085  PDISK_DATA diskData;
1086  PDISK_DATA physicalDiskData;
1087  ULONG bytesPerSector;
1088  UCHAR sectorShift;
1089  ULONG srbFlags;
1090  ULONG dmByteSkew = 0;
1091  PULONG dmSkew;
1092  BOOLEAN dmActive = FALSE;
1093  ULONG numberListElements = 0;
1094 
1095 
1096  //
1097  // Get physical device geometry information for partition table reads.
1098  //
1099 
1100  physicalDeviceExtension = PhysicalDeviceObject->DeviceExtension;
1101  diskGeometry = physicalDeviceExtension->DiskGeometry;
1102  bytesPerSector = diskGeometry->Geometry.BytesPerSector;
1103 
1104  //
1105  // Make sure sector size is not zero.
1106  //
1107 
1108  if (bytesPerSector == 0) {
1109 
1110  //
1111  // Default sector size for disk is 512.
1112  //
1113 
1114  bytesPerSector = diskGeometry->Geometry.BytesPerSector = 512;
1115  }
1116 
1117  sectorShift = physicalDeviceExtension->SectorShift;
1118 
1119  //
1120  // Set pointer to disk data area that follows device extension.
1121  //
1122 
1123  diskData = (PDISK_DATA)(physicalDeviceExtension + 1);
1124  diskData->PartitionListState = Initializing;
1125 
1126  //
1127  // Determine is DM Driver is loaded on an IDE drive that is
1128  // under control of Atapi - this could be either a crashdump or
1129  // an Atapi device is sharing the controller with an IDE disk.
1130  //
1131 
1133  physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector,
1134  (ULONG)0x54,
1135  (PVOID)&dmSkew);
1136 
1137  if (dmSkew) {
1138 
1139  //
1140  // Update the device extension, so that the call to IoReadPartitionTable
1141  // will get the correct information. Any I/O to this disk will have
1142  // to be skewed by *dmSkew sectors aka DMByteSkew.
1143  //
1144 
1145  physicalDeviceExtension->DMSkew = *dmSkew;
1146  physicalDeviceExtension->DMActive = TRUE;
1147  physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector;
1148 
1149  //
1150  // Save away the information that we need, since this deviceExtension will soon be
1151  // blown away.
1152  //
1153 
1154  dmActive = TRUE;
1155  dmByteSkew = physicalDeviceExtension->DMByteSkew;
1156 
1157  }
1158 
1159 #ifdef __REACTOS__
1160  //
1161  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
1162  // for removable devices and avoid an infinite recursive loop between
1163  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
1164  //
1165  diskData->UpdateRemovableGeometryCount = 0;
1166 #endif
1167 
1168  //
1169  // Create objects for all the partitions on the device.
1170  //
1171 
1173  physicalDeviceExtension->DiskGeometry->Geometry.BytesPerSector,
1174  TRUE,
1175  (PVOID)&partitionList);
1176 
1177  //
1178  // If the I/O read partition table failed and this is a removable device,
1179  // then fix up the partition list to make it look like there is one
1180  // zero length partition.
1181  //
1182  DPRINT("IoReadPartitionTable() status: 0x%08X\n", status);
1183  if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) &&
1184  PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1185 
1186  if (!NT_SUCCESS(status)) {
1187 
1188  //
1189  // Remember this disk is not ready.
1190  //
1191 
1192  diskData->DriveNotReady = TRUE;
1193 
1194  } else {
1195 
1196  //
1197  // Free the partition list allocated by IoReadPartitionTable.
1198  //
1199 
1200  ExFreePool(partitionList);
1201  }
1202 
1203  //
1204  // Allocate and zero a partition list.
1205  //
1206 
1207  partitionList = ExAllocatePool(NonPagedPool, sizeof(*partitionList));
1208 
1209 
1210  if (partitionList != NULL) {
1211 
1212  RtlZeroMemory( partitionList, sizeof( *partitionList ));
1213 
1214  //
1215  // Set the partition count to one and the status to success
1216  // so one device object will be created. Set the partition type
1217  // to a bogus value.
1218  //
1219 
1220  partitionList->PartitionCount = 1;
1221 
1223  }
1224  }
1225 
1226  if (NT_SUCCESS(status)) {
1227 
1228  //
1229  // Record disk signature.
1230  //
1231 
1232  diskData->Signature = partitionList->Signature;
1233 
1234  //
1235  // If disk signature is zero, then calculate the MBR checksum.
1236  //
1237 
1238  if (!diskData->Signature) {
1239 
1240  if (!CalculateMbrCheckSum(physicalDeviceExtension,
1241  &diskData->MbrCheckSum)) {
1242 
1243  DebugPrint((1,
1244  "SCSIDISK: Can't calculate MBR checksum for disk %x\n",
1245  physicalDeviceExtension->DeviceNumber));
1246  } else {
1247 
1248  DebugPrint((2,
1249  "SCSIDISK: MBR checksum for disk %x is %x\n",
1250  physicalDeviceExtension->DeviceNumber,
1251  diskData->MbrCheckSum));
1252  }
1253  }
1254 
1255  //
1256  // Check the registry and determine if the BIOS knew about this drive. If
1257  // it did then update the geometry with the BIOS information.
1258  //
1259 
1260  UpdateGeometry(physicalDeviceExtension);
1261 
1262  srbFlags = physicalDeviceExtension->SrbFlags;
1263 
1264  initData = ExAllocatePool(NonPagedPool, sizeof(CLASS_INIT_DATA));
1265  if (!initData)
1266  {
1267  DebugPrint((1,
1268  "Disk.CreatePartitionDeviceObjects - Allocation of initData failed\n"));
1269 
1271  goto CreatePartitionDeviceObjectsExit;
1272  }
1273 
1274  RtlZeroMemory(initData, sizeof(CLASS_INIT_DATA));
1275 
1276  initData->InitializationDataSize = sizeof(CLASS_INIT_DATA);
1278  initData->DeviceType = FILE_DEVICE_DISK;
1279  initData->DeviceCharacteristics = PhysicalDeviceObject->Characteristics;
1280  initData->ClassError = physicalDeviceExtension->ClassError;
1281  initData->ClassReadWriteVerification = physicalDeviceExtension->ClassReadWriteVerification;
1282  initData->ClassFindDevices = physicalDeviceExtension->ClassFindDevices;
1283  initData->ClassDeviceControl = physicalDeviceExtension->ClassDeviceControl;
1284  initData->ClassShutdownFlush = physicalDeviceExtension->ClassShutdownFlush;
1285  initData->ClassCreateClose = physicalDeviceExtension->ClassCreateClose;
1286  initData->ClassStartIo = physicalDeviceExtension->ClassStartIo;
1287 
1288  //
1289  // Create device objects for the device partitions (if any).
1290  // PartitionCount includes physical device partition 0,
1291  // so only one partition means no objects to create.
1292  //
1293 
1294  DebugPrint((2,
1295  "CreateDiskDeviceObjects: Number of partitions is %d\n",
1296  partitionList->PartitionCount));
1297 
1298  for (partitionNumber = 0; partitionNumber <
1299  partitionList->PartitionCount; partitionNumber++) {
1300 
1301  //
1302  // Create partition object and set up partition parameters.
1303  //
1304 
1305  sprintf(ntNameBuffer,
1306  "\\Device\\Harddisk%lu\\Partition%lu",
1307  physicalDeviceExtension->DeviceNumber,
1308  partitionNumber + 1);
1309 
1310  DebugPrint((2,
1311  "CreateDiskDeviceObjects: Create device object %s\n",
1312  ntNameBuffer));
1313 
1315  ntNameBuffer,
1317  &deviceObject,
1318  initData);
1319 
1320  if (!NT_SUCCESS(status)) {
1321 
1322  DebugPrint((1, "CreateDiskDeviceObjects: Can't create device object for %s\n", ntNameBuffer));
1323 
1324  break;
1325  }
1326 
1327  //
1328  // Set up device object fields.
1329  //
1330 
1331  deviceObject->Flags |= DO_DIRECT_IO;
1332 
1333  //
1334  // Check if this is during initialization. If not indicate that
1335  // system initialization already took place and this disk is ready
1336  // to be accessed.
1337  //
1338 
1339  if (!RegistryPath) {
1340  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1341  }
1342 
1343  deviceObject->StackSize = (CCHAR)physicalDeviceExtension->PortDeviceObject->StackSize + 1;
1344 
1345  //
1346  // Set up device extension fields.
1347  //
1348 
1349  deviceExtension = deviceObject->DeviceExtension;
1350 
1351  if (dmActive) {
1352 
1353  //
1354  // Restore any saved DM values.
1355  //
1356 
1357  deviceExtension->DMByteSkew = dmByteSkew;
1358  deviceExtension->DMSkew = *dmSkew;
1359  deviceExtension->DMActive = TRUE;
1360 
1361  }
1362 
1363  //
1364  // Link new device extension to previous disk data
1365  // to support dynamic partitioning.
1366  //
1367 
1368  diskData->NextPartition = deviceExtension;
1369 
1370  //
1371  // Get pointer to new disk data.
1372  //
1373 
1374  diskData = (PDISK_DATA)(deviceExtension + 1);
1375 
1376  //
1377  // Set next partition pointer to NULL in case this is the
1378  // last partition.
1379  //
1380 
1381  diskData->NextPartition = NULL;
1382 
1383  //
1384  // Allocate spinlock for zoning for split-request completion.
1385  //
1386 
1387  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
1388 
1389  //
1390  // Copy port device object pointer to device extension.
1391  //
1392 
1393  deviceExtension->PortDeviceObject = physicalDeviceExtension->PortDeviceObject;
1394 
1395  //
1396  // Set the alignment requirements for the device based on the
1397  // host adapter requirements
1398  //
1399 
1400  if (physicalDeviceExtension->PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
1401  deviceObject->AlignmentRequirement = physicalDeviceExtension->PortDeviceObject->AlignmentRequirement;
1402  }
1403 
1404 
1405  if (srbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
1406  numberListElements = 30;
1407  } else {
1408  numberListElements = 8;
1409  }
1410 
1411  //
1412  // Build the lookaside list for srb's for this partition based on
1413  // whether the adapter and disk can do tagged queueing.
1414  //
1415 
1416  ScsiClassInitializeSrbLookasideList(deviceExtension,
1417  numberListElements);
1418 
1419  deviceExtension->SrbFlags = srbFlags;
1420 
1421  //
1422  // Set the sense-data pointer in the device extension.
1423  //
1424 
1425  deviceExtension->SenseData = physicalDeviceExtension->SenseData;
1426  deviceExtension->PortCapabilities = physicalDeviceExtension->PortCapabilities;
1427  deviceExtension->DiskGeometry = diskGeometry;
1428  diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1;
1429  diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType;
1430  diskData->BootIndicator = partitionList->PartitionEntry[partitionNumber].BootIndicator;
1431 
1432  DebugPrint((2, "CreateDiskDeviceObjects: Partition type is %x\n",
1433  diskData->PartitionType));
1434 
1435  deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset;
1436  deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength;
1437  diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors;
1438  deviceExtension->PortNumber = physicalDeviceExtension->PortNumber;
1439  deviceExtension->PathId = physicalDeviceExtension->PathId;
1440  deviceExtension->TargetId = physicalDeviceExtension->TargetId;
1441  deviceExtension->Lun = physicalDeviceExtension->Lun;
1442 
1443  //
1444  // Check for removable media support.
1445  //
1446 
1447  if (PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1448  deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
1449  }
1450 
1451  //
1452  // Set timeout value in seconds.
1453  //
1454 
1455  deviceExtension->TimeOutValue = physicalDeviceExtension->TimeOutValue;
1456  deviceExtension->DiskGeometry->Geometry.BytesPerSector = bytesPerSector;
1457  deviceExtension->SectorShift = sectorShift;
1458  deviceExtension->DeviceObject = deviceObject;
1459  deviceExtension->DeviceFlags |= physicalDeviceExtension->DeviceFlags;
1460 
1461  } // end for (partitionNumber) ...
1462 
1463  //
1464  // Free the buffer allocated by reading the
1465  // partition table.
1466  //
1467 
1468  ExFreePool(partitionList);
1469 
1470  if (dmSkew) {
1471  ExFreePool(dmSkew);
1472  }
1473 
1474  } else {
1475 
1476 CreatePartitionDeviceObjectsExit:
1477 
1478  if (partitionList) {
1479  ExFreePool(partitionList);
1480  }
1481  if (initData) {
1482  ExFreePool(initData);
1483  }
1484 
1485  if (dmSkew) {
1486  ExFreePool(dmSkew);
1487  }
1488 
1489  return status;
1490 
1491  } // end if...else
1492 
1493 
1494  physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
1495  physicalDiskData->PartitionListState = Initialized;
1496 
1497  return(STATUS_SUCCESS);
1498 
1499 
1500 } // end CreatePartitionDeviceObjects()
1501 
1502 
1503 NTSTATUS
1504 NTAPI
1507  IN PIRP Irp
1508  )
1509 
1510 /*++
1511 
1512 Routine Description:
1513 
1514  I/O System entry for read and write requests to SCSI disks.
1515 
1516 Arguments:
1517 
1518  DeviceObject - Pointer to driver object created by system.
1519  Irp - IRP involved.
1520 
1521 Return Value:
1522 
1523  NT Status
1524 
1525 --*/
1526 
1527 {
1528  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1530  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1531  LARGE_INTEGER startingOffset;
1532 
1533  //
1534  // HACK: How can we end here with null sector size?!
1535  //
1536 
1537  if (deviceExtension->DiskGeometry->Geometry.BytesPerSector == 0) {
1538  DPRINT1("Hack! Received invalid sector size\n");
1539  deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512;
1540  }
1541 
1542  //
1543  // Verify parameters of this request.
1544  // Check that ending sector is within partition and
1545  // that number of bytes to transfer is a multiple of
1546  // the sector size.
1547  //
1548 
1549  startingOffset.QuadPart = (currentIrpStack->Parameters.Read.ByteOffset.QuadPart +
1550  transferByteCount);
1551 
1552  if ((startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) ||
1553  (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1))) {
1554 
1555  //
1556  // This error maybe caused by the fact that the drive is not ready.
1557  //
1558 
1559  if (((PDISK_DATA)(deviceExtension + 1))->DriveNotReady) {
1560 
1561  //
1562  // Flag this as a user error so that a popup is generated.
1563  //
1564 
1565  Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
1567 
1568  } else {
1569 
1570  //
1571  // Note fastfat depends on this parameter to determine when to
1572  // remount do to a sector size change.
1573  //
1574 
1575  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1576  }
1577 
1578  if (startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) {
1579  DPRINT1("Reading beyond partition end! startingOffset: %I64d, PartitionLength: %I64d\n", startingOffset.QuadPart, deviceExtension->PartitionLength.QuadPart);
1580  }
1581 
1582  if (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1)) {
1583  DPRINT1("Not reading sectors! TransferByteCount: %lu, BytesPerSector: %lu\n", transferByteCount, deviceExtension->DiskGeometry->Geometry.BytesPerSector);
1584  }
1585 
1586  if (Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) {
1587  DPRINT1("Failing due to device not ready!\n");
1588  }
1589 
1590  return STATUS_INVALID_PARAMETER;
1591  }
1592 
1593  return STATUS_SUCCESS;
1594 
1595 } // end ScsiDiskReadWrite()
1596 
1597 
1598 NTSTATUS
1599 NTAPI
1602  PIRP Irp
1603  )
1604 
1605 /*++
1606 
1607 Routine Description:
1608 
1609  I/O system entry for device controls to SCSI disks.
1610 
1611 Arguments:
1612 
1613  DeviceObject - Pointer to driver object created by system.
1614  Irp - IRP involved.
1615 
1616 Return Value:
1617 
1618  Status is returned.
1619 
1620 --*/
1621 
1622 {
1624  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1625  PDISK_DATA diskData = (PDISK_DATA)(deviceExtension + 1);
1626  PSCSI_REQUEST_BLOCK srb;
1627  PCDB cdb;
1628  PMODE_PARAMETER_HEADER modeData;
1629  PIRP irp2;
1630  ULONG length;
1631  NTSTATUS status;
1632  KEVENT event;
1633  IO_STATUS_BLOCK ioStatus;
1634 
1635  PAGED_CODE();
1636 
1638 
1639  if (srb == NULL) {
1640 
1641  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1644  }
1645 
1646  //
1647  // Write zeros to Srb.
1648  //
1649 
1651 
1652  cdb = (PCDB)srb->Cdb;
1653 
1654  switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
1655 
1656  case SMART_GET_VERSION: {
1657 
1658  ULONG_PTR buffer;
1659  PSRB_IO_CONTROL srbControl;
1660  PGETVERSIONINPARAMS versionParams;
1661 
1662  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1663  sizeof(GETVERSIONINPARAMS)) {
1665  break;
1666  }
1667 
1668  //
1669  // Create notification event object to be used to signal the
1670  // request completion.
1671  //
1672 
1674 
1675  srbControl = ExAllocatePool(NonPagedPool,
1676  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
1677 
1678  if (!srbControl) {
1680  break;
1681  }
1682 
1683  //
1684  // fill in srbControl fields
1685  //
1686 
1687  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
1688  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
1689  srbControl->Timeout = deviceExtension->TimeOutValue;
1690  srbControl->Length = sizeof(GETVERSIONINPARAMS);
1692 
1693  //
1694  // Point to the 'buffer' portion of the SRB_CONTROL
1695  //
1696 
1697  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1698 
1699  //
1700  // Ensure correct target is set in the cmd parameters.
1701  //
1702 
1703  versionParams = (PGETVERSIONINPARAMS)buffer;
1704  versionParams->bIDEDeviceMap = deviceExtension->TargetId;
1705 
1706  //
1707  // Copy the IOCTL parameters to the srb control buffer area.
1708  //
1709 
1710  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(GETVERSIONINPARAMS));
1711 
1712 
1714  deviceExtension->PortDeviceObject,
1715  srbControl,
1716  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
1717  srbControl,
1718  sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
1719  FALSE,
1720  &event,
1721  &ioStatus);
1722 
1723  if (irp2 == NULL) {
1725  break;
1726  }
1727 
1728  //
1729  // Call the port driver with the request and wait for it to complete.
1730  //
1731 
1732  status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
1733 
1734  if (status == STATUS_PENDING) {
1736  status = ioStatus.Status;
1737  }
1738 
1739  //
1740  // If successful, copy the data received into the output buffer.
1741  // This should only fail in the event that the IDE driver is older than this driver.
1742  //
1743 
1744  if (NT_SUCCESS(status)) {
1745 
1746  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1747 
1748  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, sizeof(GETVERSIONINPARAMS));
1749  Irp->IoStatus.Information = sizeof(GETVERSIONINPARAMS);
1750  }
1751 
1752  ExFreePool(srbControl);
1753  break;
1754  }
1755 
1756  case SMART_RCV_DRIVE_DATA: {
1757 
1758  PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
1759  ULONG controlCode = 0;
1760  PSRB_IO_CONTROL srbControl;
1761  ULONG_PTR buffer;
1762 
1763  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
1764  (sizeof(SENDCMDINPARAMS) - 1)) {
1766  break;
1767 
1768  } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1769  (sizeof(SENDCMDOUTPARAMS) + 512 - 1)) {
1771  break;
1772  }
1773 
1774  //
1775  // Create notification event object to be used to signal the
1776  // request completion.
1777  //
1778 
1780 
1781  if (cmdInParameters->irDriveRegs.bCommandReg == ID_CMD) {
1782 
1784  controlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
1785 
1786  } else if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
1787  switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
1788  case READ_ATTRIBUTES:
1791  break;
1792  case READ_THRESHOLDS:
1795  break;
1796  default:
1798  break;
1799  }
1800  } else {
1801 
1803  }
1804 
1805  if (controlCode == 0) {
1807  break;
1808  }
1809 
1810  srbControl = ExAllocatePool(NonPagedPool,
1811  sizeof(SRB_IO_CONTROL) + length);
1812 
1813  if (!srbControl) {
1815  break;
1816  }
1817 
1818  //
1819  // fill in srbControl fields
1820  //
1821 
1822  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
1823  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
1824  srbControl->Timeout = deviceExtension->TimeOutValue;
1825  srbControl->Length = length;
1826  srbControl->ControlCode = controlCode;
1827 
1828  //
1829  // Point to the 'buffer' portion of the SRB_CONTROL
1830  //
1831 
1832  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1833 
1834  //
1835  // Ensure correct target is set in the cmd parameters.
1836  //
1837 
1838  cmdInParameters->bDriveNumber = deviceExtension->TargetId;
1839 
1840  //
1841  // Copy the IOCTL parameters to the srb control buffer area.
1842  //
1843 
1844  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
1845 
1847  deviceExtension->PortDeviceObject,
1848  srbControl,
1849  sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
1850  srbControl,
1851  sizeof(SRB_IO_CONTROL) + length,
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  //
1875 
1876  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
1877 
1878  if (NT_SUCCESS(status)) {
1879 
1880  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length - 1);
1881  Irp->IoStatus.Information = length - 1;
1882 
1883  } else {
1884 
1885  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, (sizeof(SENDCMDOUTPARAMS) - 1));
1886  Irp->IoStatus.Information = sizeof(SENDCMDOUTPARAMS) - 1;
1887 
1888  }
1889 
1890  ExFreePool(srbControl);
1891  break;
1892 
1893  }
1894 
1895  case SMART_SEND_DRIVE_COMMAND: {
1896 
1897  PSENDCMDINPARAMS cmdInParameters = ((PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer);
1898  PSRB_IO_CONTROL srbControl;
1899  ULONG controlCode = 0;
1900  ULONG_PTR buffer;
1901 
1902  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
1903  (sizeof(SENDCMDINPARAMS) - 1)) {
1905  break;
1906 
1907  } else if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1908  (sizeof(SENDCMDOUTPARAMS) - 1)) {
1910  break;
1911  }
1912 
1913  //
1914  // Create notification event object to be used to signal the
1915  // request completion.
1916  //
1917 
1919 
1920  length = 0;
1921 
1922  if (cmdInParameters->irDriveRegs.bCommandReg == SMART_CMD) {
1923  switch (cmdInParameters->irDriveRegs.bFeaturesReg) {
1924 
1925  case ENABLE_SMART:
1926  controlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
1927  break;
1928 
1929  case DISABLE_SMART:
1930  controlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
1931  break;
1932 
1933  case RETURN_SMART_STATUS:
1934 
1935  //
1936  // Ensure bBuffer is at least 2 bytes (to hold the values of
1937  // cylinderLow and cylinderHigh).
1938  //
1939 
1940  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
1941  (sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS))) {
1942 
1944  break;
1945  }
1946 
1947  controlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
1948  length = sizeof(IDEREGS);
1949  break;
1950 
1953  break;
1954 
1955  case SAVE_ATTRIBUTE_VALUES:
1957  break;
1958 
1959  case EXECUTE_OFFLINE_DIAGS:
1961  break;
1962 
1963  default:
1965  break;
1966  }
1967  } else {
1968 
1970  }
1971 
1972  if (controlCode == 0) {
1974  break;
1975  }
1976 
1977  length += (sizeof(SENDCMDOUTPARAMS) > sizeof(SENDCMDINPARAMS)) ? sizeof(SENDCMDOUTPARAMS) : sizeof(SENDCMDINPARAMS);
1978  srbControl = ExAllocatePool(NonPagedPool,
1979  sizeof(SRB_IO_CONTROL) + length);
1980 
1981  if (!srbControl) {
1983  break;
1984  }
1985 
1986  //
1987  // fill in srbControl fields
1988  //
1989 
1990  srbControl->HeaderLength = sizeof(SRB_IO_CONTROL);
1991  RtlMoveMemory (srbControl->Signature, "SCSIDISK", 8);
1992  srbControl->Timeout = deviceExtension->TimeOutValue;
1993  srbControl->Length = length;
1994 
1995  //
1996  // Point to the 'buffer' portion of the SRB_CONTROL
1997  //
1998 
1999  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
2000 
2001  //
2002  // Ensure correct target is set in the cmd parameters.
2003  //
2004 
2005  cmdInParameters->bDriveNumber = deviceExtension->TargetId;
2006 
2007  //
2008  // Copy the IOCTL parameters to the srb control buffer area.
2009  //
2010 
2011  RtlMoveMemory((PVOID)buffer, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
2012 
2013  srbControl->ControlCode = controlCode;
2014 
2016  deviceExtension->PortDeviceObject,
2017  srbControl,
2018  sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
2019  srbControl,
2020  sizeof(SRB_IO_CONTROL) + length,
2021  FALSE,
2022  &event,
2023  &ioStatus);
2024 
2025  if (irp2 == NULL) {
2027  break;
2028  }
2029 
2030  //
2031  // Call the port driver with the request and wait for it to complete.
2032  //
2033 
2034  status = IoCallDriver(deviceExtension->PortDeviceObject, irp2);
2035 
2036  if (status == STATUS_PENDING) {
2038  status = ioStatus.Status;
2039  }
2040 
2041  //
2042  // Copy the data received into the output buffer. Since the status buffer
2043  // contains error information also, always perform this copy. IO will will
2044  // either pass this back to the app, or zero it, in case of error.
2045  //
2046 
2047  buffer = (ULONG_PTR)srbControl + srbControl->HeaderLength;
2048 
2049  //
2050  // Update the return buffer size based on the sub-command.
2051  //
2052 
2053  if (cmdInParameters->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS) {
2054  length = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
2055  } else {
2056  length = sizeof(SENDCMDOUTPARAMS) - 1;
2057  }
2058 
2059  RtlMoveMemory ( Irp->AssociatedIrp.SystemBuffer, (PVOID)buffer, length);
2060  Irp->IoStatus.Information = length;
2061 
2062  ExFreePool(srbControl);
2063  break;
2064 
2065  }
2066 
2069  {
2070 
2071  PDEVICE_EXTENSION physicalDeviceExtension;
2072  PDISK_DATA physicalDiskData;
2073  BOOLEAN removable = FALSE;
2074  BOOLEAN listInitialized = FALSE;
2075  ULONG copyLength;
2076 
2077  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) {
2078  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) {
2080  break;
2081  }
2082 
2083  copyLength = sizeof(DISK_GEOMETRY);
2084  } else {
2085  ASSERT(irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX);
2086  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) {
2088  break;
2089  }
2090 
2091  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(DISK_GEOMETRY_EX)) {
2092  copyLength = sizeof(DISK_GEOMETRY_EX);
2093  } else {
2094  copyLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data);
2095  }
2096  }
2097 
2099 
2100  physicalDeviceExtension = deviceExtension->PhysicalDevice->DeviceExtension;
2101  physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
2102 
2103  removable = (BOOLEAN)DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA;
2104  listInitialized = (physicalDiskData->PartitionListState == Initialized);
2105 
2106  if (removable || (!listInitialized))
2107  {
2108  //
2109  // Issue ReadCapacity to update device extension
2110  // with information for current media.
2111  //
2112 
2113  status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
2114 
2115  }
2116 
2117  if (removable) {
2118 
2119  if (!NT_SUCCESS(status)) {
2120 
2121  //
2122  // Note the drive is not ready.
2123  //
2124 
2125  diskData->DriveNotReady = TRUE;
2126 
2127  break;
2128  }
2129 
2130  //
2131  // Note the drive is now ready.
2132  //
2133 
2134  diskData->DriveNotReady = FALSE;
2135 
2136  } else if (NT_SUCCESS(status)) {
2137 
2138  // ReadDriveCapacity was alright, create Partition Objects
2139 
2140  if (physicalDiskData->PartitionListState == NotInitialized) {
2141  status = CreatePartitionDeviceObjects(deviceExtension->PhysicalDevice, NULL);
2142  }
2143  }
2144 
2145  if (NT_SUCCESS(status)) {
2146 
2147  //
2148  // Copy drive geometry information from device extension.
2149  //
2150 
2151  RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
2152  deviceExtension->DiskGeometry,
2153  copyLength);
2154 
2156  Irp->IoStatus.Information = copyLength;
2157  }
2158 
2159  break;
2160 
2161  }
2162 
2163  case IOCTL_DISK_VERIFY:
2164 
2165  {
2166 
2167  PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
2168  LARGE_INTEGER byteOffset;
2169  ULONG sectorOffset;
2171 
2172  //
2173  // Validate buffer length.
2174  //
2175 
2176  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2177  sizeof(VERIFY_INFORMATION)) {
2178 
2180  break;
2181  }
2182 
2183  //
2184  // Verify sectors
2185  //
2186 
2187  srb->CdbLength = 10;
2188 
2189  cdb->CDB10.OperationCode = SCSIOP_VERIFY;
2190 
2191  //
2192  // Add disk offset to starting sector.
2193  //
2194 
2195  byteOffset.QuadPart = deviceExtension->StartingOffset.QuadPart +
2196  verifyInfo->StartingOffset.QuadPart;
2197 
2198  //
2199  // Convert byte offset to sector offset.
2200  //
2201 
2202  sectorOffset = (ULONG)(byteOffset.QuadPart >> deviceExtension->SectorShift);
2203 
2204  //
2205  // Convert ULONG byte count to USHORT sector count.
2206  //
2207 
2208  sectorCount = (USHORT)(verifyInfo->Length >> deviceExtension->SectorShift);
2209 
2210  //
2211  // Move little endian values into CDB in big endian format.
2212  //
2213 
2214  cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&sectorOffset)->Byte3;
2215  cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
2216  cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
2217  cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;
2218 
2219  cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
2220  cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->Byte0;
2221 
2222  //
2223  // The verify command is used by the NT FORMAT utility and
2224  // requests are sent down for 5% of the volume size. The
2225  // request timeout value is calculated based on the number of
2226  // sectors verified.
2227  //
2228 
2229  srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) *
2230  deviceExtension->TimeOutValue;
2231 
2233  srb,
2234  Irp,
2235  NULL,
2236  0,
2237  FALSE);
2238 
2239  return(status);
2240 
2241  }
2242 
2244 
2245  //
2246  // Return the information about the partition specified by the device
2247  // object. Note that no information is ever returned about the size
2248  // or partition type of the physical disk, as this doesn't make any
2249  // sense.
2250  //
2251 
2252  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2253  sizeof(PARTITION_INFORMATION)) {
2254 
2256  break;
2257  }
2258 
2259  //
2260  // Update the geometry in case it has changed.
2261  //
2262 
2264 
2265  if (!NT_SUCCESS(status)) {
2266 
2267  //
2268  // Note the drive is not ready.
2269  //
2270 
2271  diskData->DriveNotReady = TRUE;
2272  break;
2273  }
2274 
2275  //
2276  // Note the drive is now ready.
2277  //
2278 
2279  diskData->DriveNotReady = FALSE;
2280 
2281  //
2282  // Handle the case were we query the whole disk
2283  //
2284 
2285  if (diskData->PartitionNumber == 0) {
2286 
2287  PPARTITION_INFORMATION outputBuffer;
2288 
2289  outputBuffer =
2290  (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2291 
2292  outputBuffer->PartitionType = PARTITION_ENTRY_UNUSED;
2293  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2294  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2295  outputBuffer->HiddenSectors = 0;
2296  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2297  outputBuffer->BootIndicator = FALSE;
2298  outputBuffer->RewritePartition = FALSE;
2299  outputBuffer->RecognizedPartition = FALSE;
2300 
2302  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
2303 
2304  } else {
2305 
2306  PPARTITION_INFORMATION outputBuffer;
2307 
2308  //
2309  // We query a single partition here
2310  // FIXME: this can only work for MBR-based disks, check for this!
2311  //
2312 
2313  outputBuffer =
2314  (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2315 
2316  outputBuffer->PartitionType = diskData->PartitionType;
2317  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2318  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2319  outputBuffer->HiddenSectors = diskData->HiddenSectors;
2320  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2321  outputBuffer->BootIndicator = diskData->BootIndicator;
2322  outputBuffer->RewritePartition = FALSE;
2323  outputBuffer->RecognizedPartition =
2325 
2327  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
2328  }
2329 
2330  break;
2331 
2333 
2334  //
2335  // Return the information about the partition specified by the device
2336  // object. Note that no information is ever returned about the size
2337  // or partition type of the physical disk, as this doesn't make any
2338  // sense.
2339  //
2340 
2341  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2342  sizeof(PARTITION_INFORMATION_EX)) {
2343 
2345 
2346  }
2347 #if 0 // HACK: ReactOS partition numbers must be wrong
2348  else if (diskData->PartitionNumber == 0) {
2349 
2350  //
2351  // Partition zero is not a partition so this is not a
2352  // reasonable request.
2353  //
2354 
2356 
2357  }
2358 #endif
2359  else {
2360 
2361  PPARTITION_INFORMATION_EX outputBuffer;
2362 
2363  if (diskData->PartitionNumber == 0) {
2364  DPRINT1("HACK: Handling partition 0 request!\n");
2365  //ASSERT(FALSE);
2366  }
2367 
2368  //
2369  // Update the geometry in case it has changed.
2370  //
2371 
2373 
2374  if (!NT_SUCCESS(status)) {
2375 
2376  //
2377  // Note the drive is not ready.
2378  //
2379 
2380  diskData->DriveNotReady = TRUE;
2381  break;
2382  }
2383 
2384  //
2385  // Note the drive is now ready.
2386  //
2387 
2388  diskData->DriveNotReady = FALSE;
2389 
2390  if (diskData->PartitionType == 0 && (diskData->PartitionNumber > 0)) {
2391 
2393  break;
2394  }
2395 
2396  outputBuffer =
2397  (PPARTITION_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
2398 
2399  //
2400  // FIXME: hack of the year, assume that partition is MBR
2401  // Thing that can obviously be wrong...
2402  //
2403 
2404  outputBuffer->PartitionStyle = PARTITION_STYLE_MBR;
2405  outputBuffer->Mbr.PartitionType = diskData->PartitionType;
2406  outputBuffer->StartingOffset = deviceExtension->StartingOffset;
2407  outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
2408  outputBuffer->Mbr.HiddenSectors = diskData->HiddenSectors;
2409  outputBuffer->PartitionNumber = diskData->PartitionNumber;
2410  outputBuffer->Mbr.BootIndicator = diskData->BootIndicator;
2411  outputBuffer->RewritePartition = FALSE;
2412  outputBuffer->Mbr.RecognizedPartition =
2414 
2416  Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION_EX);
2417  }
2418 
2419  break;
2420 
2422 
2423  if (diskData->PartitionNumber == 0) {
2424 
2426 
2427  } else {
2428 
2429  PSET_PARTITION_INFORMATION inputBuffer =
2430  (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
2431 
2432  //
2433  // Validate buffer length.
2434  //
2435 
2436  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2437  sizeof(SET_PARTITION_INFORMATION)) {
2438 
2440  break;
2441  }
2442 
2443  //
2444  // The HAL routines IoGet- and IoSetPartitionInformation were
2445  // developed before support of dynamic partitioning and therefore
2446  // don't distinguish between partition ordinal (that is the order
2447  // of a partition on a disk) and the partition number. (The
2448  // partition number is assigned to a partition to identify it to
2449  // the system.) Use partition ordinals for these legacy calls.
2450  //
2451 
2453  deviceExtension->PhysicalDevice,
2454  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2455  diskData->PartitionOrdinal,
2456  inputBuffer->PartitionType);
2457 
2458  if (NT_SUCCESS(status)) {
2459 
2460  diskData->PartitionType = inputBuffer->PartitionType;
2461  }
2462  }
2463 
2464  break;
2465 
2467 
2468  //
2469  // Return the partition layout for the physical drive. Note that
2470  // the layout is returned for the actual physical drive, regardless
2471  // of which partition was specified for the request.
2472  //
2473 
2474  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2475  sizeof(DRIVE_LAYOUT_INFORMATION)) {
2477 
2478  } else {
2479 
2480  PDRIVE_LAYOUT_INFORMATION partitionList;
2481  PDEVICE_EXTENSION physicalExtension = deviceExtension;
2482  PPARTITION_INFORMATION partitionEntry;
2483  PDISK_DATA diskData;
2484  ULONG tempSize;
2485  ULONG i;
2486 
2487  //
2488  // Read partition information.
2489  //
2490 
2491  status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
2492  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2493  FALSE,
2494  &partitionList);
2495 
2496  if (!NT_SUCCESS(status)) {
2497  break;
2498  }
2499 
2500  //
2501  // The disk layout has been returned in the partitionList
2502  // buffer. Determine its size and, if the data will fit
2503  // into the intermediary buffer, return it.
2504  //
2505 
2506  tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,PartitionEntry[0]);
2507  tempSize += partitionList->PartitionCount *
2508  sizeof(PARTITION_INFORMATION);
2509 
2510  if (tempSize >
2511  irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
2512 
2514  ExFreePool(partitionList);
2515  break;
2516  }
2517 
2518  //
2519  // Walk partition list to associate partition numbers with
2520  // partition entries.
2521  //
2522 
2523  for (i = 0; i < partitionList->PartitionCount; i++) {
2524 
2525  //
2526  // Walk partition chain anchored at physical disk extension.
2527  //
2528 
2529  deviceExtension = physicalExtension;
2530  diskData = (PDISK_DATA)(deviceExtension + 1);
2531 
2532  do {
2533 
2534  deviceExtension = diskData->NextPartition;
2535 
2536  //
2537  // Check if this is the last partition in the chain.
2538  //
2539 
2540  if (!deviceExtension) {
2541  break;
2542  }
2543 
2544  //
2545  // Get the partition device extension from disk data.
2546  //
2547 
2548  diskData = (PDISK_DATA)(deviceExtension + 1);
2549 
2550  //
2551  // Check if this partition is not currently being used.
2552  //
2553 
2554  if (!deviceExtension->PartitionLength.QuadPart) {
2555  continue;
2556  }
2557 
2558  partitionEntry = &partitionList->PartitionEntry[i];
2559 
2560  //
2561  // Check if empty, or describes extended partition or hasn't changed.
2562  //
2563 
2564  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
2565  IsContainerPartition(partitionEntry->PartitionType)) {
2566  continue;
2567  }
2568 
2569  //
2570  // Check if new partition starts where this partition starts.
2571  //
2572 
2573  if (partitionEntry->StartingOffset.QuadPart !=
2574  deviceExtension->StartingOffset.QuadPart) {
2575  continue;
2576  }
2577 
2578  //
2579  // Check if partition length is the same.
2580  //
2581 
2582  if (partitionEntry->PartitionLength.QuadPart ==
2583  deviceExtension->PartitionLength.QuadPart) {
2584 
2585  //
2586  // Partitions match. Update partition number.
2587  //
2588 
2589  partitionEntry->PartitionNumber =
2590  diskData->PartitionNumber;
2591  break;
2592  }
2593 
2594  } while (TRUE);
2595  }
2596 
2597  //
2598  // Copy partition information to system buffer.
2599  //
2600 
2601  RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
2602  partitionList,
2603  tempSize);
2605  Irp->IoStatus.Information = tempSize;
2606 
2607  //
2608  // Finally, free the buffer allocated by reading the
2609  // partition table.
2610  //
2611 
2612  ExFreePool(partitionList);
2613  }
2614 
2615  break;
2616 
2618 
2619  {
2620 
2621  //
2622  // Update the disk with new partition information.
2623  //
2624 
2625  PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer;
2626 
2627  //
2628  // Validate buffer length.
2629  //
2630 
2631  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2632  sizeof(DRIVE_LAYOUT_INFORMATION)) {
2633 
2635  break;
2636  }
2637 
2638  length = sizeof(DRIVE_LAYOUT_INFORMATION) +
2639  (partitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION);
2640 
2641 
2642  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2643  length) {
2644 
2646  break;
2647  }
2648 
2649  //
2650  // Verify that device object is for physical disk.
2651  //
2652 
2653  if (deviceExtension->PhysicalDevice->DeviceExtension != deviceExtension) {
2655  break;
2656  }
2657 
2658  //
2659  // Walk through partition table comparing partitions to
2660  // existing partitions to create, delete and change
2661  // device objects as necessary.
2662  //
2663 
2665  Irp);
2666 
2667  //
2668  // Write changes to disk.
2669  //
2670 
2672  deviceExtension->DeviceObject,
2673  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
2674  deviceExtension->DiskGeometry->Geometry.SectorsPerTrack,
2675  deviceExtension->DiskGeometry->Geometry.TracksPerCylinder,
2676  partitionList);
2677  }
2678 
2679  //
2680  // Update IRP with bytes returned.
2681  //
2682 
2683  if (NT_SUCCESS(status)) {
2684  Irp->IoStatus.Information = length;
2685  }
2686 
2687  break;
2688 
2690 
2691  //
2692  // Map defective blocks to new location on disk.
2693  //
2694 
2695  {
2696 
2697  PREASSIGN_BLOCKS badBlocks = Irp->AssociatedIrp.SystemBuffer;
2698  ULONG bufferSize;
2699  ULONG blockNumber;
2700  ULONG blockCount;
2701 
2702  //
2703  // Validate buffer length.
2704  //
2705 
2706  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2707  sizeof(REASSIGN_BLOCKS)) {
2708 
2710  break;
2711  }
2712 
2713  bufferSize = sizeof(REASSIGN_BLOCKS) +
2714  (badBlocks->Count - 1) * sizeof(ULONG);
2715 
2716  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
2717  bufferSize) {
2718 
2720  break;
2721  }
2722 
2723  //
2724  // Build the data buffer to be transferred in the input buffer.
2725  // The format of the data to the device is:
2726  //
2727  // 2 bytes Reserved
2728  // 2 bytes Length
2729  // x * 4 btyes Block Address
2730  //
2731  // All values are big endian.
2732  //
2733 
2734  badBlocks->Reserved = 0;
2735  blockCount = badBlocks->Count;
2736 
2737  //
2738  // Convert # of entries to # of bytes.
2739  //
2740 
2741  blockCount *= 4;
2742  badBlocks->Count = (USHORT) ((blockCount >> 8) & 0XFF);
2743  badBlocks->Count |= (USHORT) ((blockCount << 8) & 0XFF00);
2744 
2745  //
2746  // Convert back to number of entries.
2747  //
2748 
2749  blockCount /= 4;
2750 
2751  for (; blockCount > 0; blockCount--) {
2752 
2753  blockNumber = badBlocks->BlockNumber[blockCount-1];
2754 
2755  REVERSE_BYTES((PFOUR_BYTE) &badBlocks->BlockNumber[blockCount-1],
2756  (PFOUR_BYTE) &blockNumber);
2757  }
2758 
2759  srb->CdbLength = 6;
2760 
2761  cdb->CDB6GENERIC.OperationCode = SCSIOP_REASSIGN_BLOCKS;
2762 
2763  //
2764  // Set timeout value.
2765  //
2766 
2767  srb->TimeOutValue = deviceExtension->TimeOutValue;
2768 
2770  srb,
2771  badBlocks,
2772  bufferSize,
2773  TRUE);
2774 
2775  Irp->IoStatus.Status = status;
2776  Irp->IoStatus.Information = 0;
2777  ExFreePool(srb);
2779  }
2780 
2781  return(status);
2782 
2784 
2785  //
2786  // Determine if the device is writable.
2787  //
2788 
2790 
2791  if (modeData == NULL) {
2793  break;
2794  }
2795 
2796  RtlZeroMemory(modeData, MODE_DATA_SIZE);
2797 
2799  (PCHAR) modeData,
2802 
2803  if (length < sizeof(MODE_PARAMETER_HEADER)) {
2804 
2805  //
2806  // Retry the request in case of a check condition.
2807  //
2808 
2810  (PCHAR) modeData,
2813 
2814  if (length < sizeof(MODE_PARAMETER_HEADER)) {
2816  ExFreePool(modeData);
2817  break;
2818  }
2819  }
2820 
2821  if (modeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT) {
2823  } else {
2825  }
2826 
2827  ExFreePool(modeData);
2828  break;
2829 
2831 
2832  //
2833  // If the caller is kernel mode, set the verify bit.
2834  //
2835 
2836  if (Irp->RequestorMode == KernelMode) {
2838  }
2840  break;
2841 
2843 
2844  //
2845  // If the caller is kernel mode, clear the verify bit.
2846  //
2847 
2848  if (Irp->RequestorMode == KernelMode) {
2850  }
2852  break;
2853 
2855 
2856  //
2857  // Search for devices that have been powered on since the last
2858  // device search or system initialization.
2859  //
2860 
2861  DebugPrint((3,"CdRomDeviceControl: Find devices\n"));
2862  status = DriverEntry(DeviceObject->DriverObject,
2863  NULL);
2864 
2865  Irp->IoStatus.Status = status;
2866  ExFreePool(srb);
2868  return status;
2869 
2871 
2872  //
2873  // If the disk is not removable then don't allow this command.
2874  //
2875 
2876  if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
2878  break;
2879  }
2880 
2881  //
2882  // Fall through and let the class driver process the request.
2883  //
2884 
2886 
2887  //
2888  // Validate buffer length.
2889  //
2890 
2891  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
2892  sizeof(GET_LENGTH_INFORMATION)) {
2894 
2895  } else {
2896 
2897  PGET_LENGTH_INFORMATION lengthInformation = Irp->AssociatedIrp.SystemBuffer;
2898 
2899  //
2900  // Update the geometry in case it has changed.
2901  //
2902 
2904 
2905  if (!NT_SUCCESS(status)) {
2906 
2907  //
2908  // Note the drive is not ready.
2909  //
2910 
2911  diskData->DriveNotReady = TRUE;
2912  break;
2913  }
2914 
2915  //
2916  // Note the drive is now ready.
2917  //
2918 
2919  diskData->DriveNotReady = FALSE;
2920 
2921  //
2922  // Output data, and return
2923  //
2924 
2925  lengthInformation->Length.QuadPart = deviceExtension->PartitionLength.QuadPart;
2927  Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION);
2928  }
2929 
2930  break;
2931 
2932  default:
2933 
2934  //
2935  // Free the Srb, since it is not needed.
2936  //
2937 
2938  ExFreePool(srb);
2939 
2940  //
2941  // Pass the request to the common device control routine.
2942  //
2943 
2945 
2946  break;
2947 
2948  } // end switch( ...
2949 
2950  Irp->IoStatus.Status = status;
2951 
2953 
2955  }
2956 
2958  ExFreePool(srb);
2959  return(status);
2960 
2961 } // end ScsiDiskDeviceControl()
2962 
2963 NTSTATUS
2964 NTAPI
2967  IN PIRP Irp
2968  )
2969 
2970 /*++
2971 
2972 Routine Description:
2973 
2974  This routine is called for a shutdown and flush IRPs. These are sent by the
2975  system before it actually shuts down or when the file system does a flush.
2976  A synchronize cache command is sent to the device if it is write caching.
2977  If the device is removable an unlock command will be sent. This routine
2978  will sent a shutdown or flush Srb to the port driver.
2979 
2980 Arguments:
2981 
2982  DriverObject - Pointer to device object to being shutdown by system.
2983 
2984  Irp - IRP involved.
2985 
2986 Return Value:
2987 
2988  NT Status
2989 
2990 --*/
2991 
2992 {
2993  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2994  PIO_STACK_LOCATION irpStack;
2995  PSCSI_REQUEST_BLOCK srb;
2996  NTSTATUS status;
2997  PCDB cdb;
2998 
2999  //
3000  // Allocate SCSI request block.
3001  //
3002 
3004 
3005  if (srb == NULL) {
3006 
3007  //
3008  // Set the status and complete the request.
3009  //
3010 
3011  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3014  }
3015 
3017 
3018  //
3019  // Write length to SRB.
3020  //
3021 
3023 
3024  //
3025  // Set SCSI bus address.
3026  //
3027 
3028  srb->PathId = deviceExtension->PathId;
3029  srb->TargetId = deviceExtension->TargetId;
3030  srb->Lun = deviceExtension->Lun;
3031 
3032  //
3033  // Set timeout value and mark the request as not being a tagged request.
3034  //
3035 
3036  srb->TimeOutValue = deviceExtension->TimeOutValue * 4;
3037  srb->QueueTag = SP_UNTAGGED;
3039  srb->SrbFlags = deviceExtension->SrbFlags;
3040 
3041  //
3042  // If the write cache is enabled then send a synchronize cache request.
3043  //
3044 
3045  if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
3046 
3048  srb->CdbLength = 10;
3049 
3050  srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
3051 
3053  srb,
3054  NULL,
3055  0,
3056  TRUE);
3057 
3058  DebugPrint((1, "ScsiDiskShutdownFlush: Synchronize cache sent. Status = %lx\n", status ));
3059  }
3060 
3061  //
3062  // Unlock the device if it is removable and this is a shutdown.
3063  //
3064 
3065  irpStack = IoGetCurrentIrpStackLocation(Irp);
3066 
3067  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
3068  irpStack->MajorFunction == IRP_MJ_SHUTDOWN) {
3069 
3070  srb->CdbLength = 6;
3071  cdb = (PVOID) srb->Cdb;
3072  cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
3073  cdb->MEDIA_REMOVAL.Prevent = FALSE;
3074 
3075  //
3076  // Set timeout value.
3077  //
3078 
3079  srb->TimeOutValue = deviceExtension->TimeOutValue;
3081  srb,
3082  NULL,
3083  0,
3084  TRUE);
3085 
3086  DebugPrint((1, "ScsiDiskShutdownFlush: Unlock device request sent. Status = %lx\n", status ));
3087  }
3088 
3089  srb->CdbLength = 0;
3090 
3091  //
3092  // Save a few parameters in the current stack location.
3093  //
3094 
3095  srb->Function = irpStack->MajorFunction == IRP_MJ_SHUTDOWN ?
3097 
3098  //
3099  // Set the retry count to zero.
3100  //
3101 
3102  irpStack->Parameters.Others.Argument4 = (PVOID) 0;
3103 
3104  //
3105  // Set up IoCompletion routine address.
3106  //
3107 
3109 
3110  //
3111  // Get next stack location and
3112  // set major function code.
3113  //
3114 
3115  irpStack = IoGetNextIrpStackLocation(Irp);
3116 
3117  irpStack->MajorFunction = IRP_MJ_SCSI;
3118 
3119  //
3120  // Set up SRB for execute scsi request.
3121  // Save SRB address in next stack for port driver.
3122  //
3123 
3124  irpStack->Parameters.Scsi.Srb = srb;
3125 
3126  //
3127  // Set up Irp Address.
3128  //
3129 
3130  srb->OriginalRequest = Irp;
3131 
3132  //
3133  // Call the port driver to process the request.
3134  //
3135 
3136  return(IoCallDriver(deviceExtension->PortDeviceObject, Irp));
3137 
3138 } // end ScsiDiskShutdown()
3139 
3140 
3141 BOOLEAN
3142 NTAPI
3145  )
3146 /*++
3147 
3148 Routine Description:
3149 
3150  The routine performs the necessary functions to determine if a device is
3151  really a floppy rather than a harddisk. This is done by a mode sense
3152  command. First, a check is made to see if the media type is set. Second
3153  a check is made for the flexible parameters mode page. Also a check is
3154  made to see if the write cache is enabled.
3155 
3156 Arguments:
3157 
3158  DeviceObject - Supplies the device object to be tested.
3159 
3160 Return Value:
3161 
3162  Return TRUE if the indicated device is a floppy.
3163 
3164 --*/
3165 {
3166  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3167  PVOID modeData;
3168  PUCHAR pageData;
3169  ULONG length;
3170 
3171  PAGED_CODE();
3172 
3174 
3175  if (modeData == NULL) {
3176  return(FALSE);
3177  }
3178 
3179  RtlZeroMemory(modeData, MODE_DATA_SIZE);
3180 
3182  modeData,
3185 
3186  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3187 
3188  //
3189  // Retry the request in case of a check condition.
3190  //
3191 
3193  modeData,
3196 
3197  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3198 
3199  ExFreePool(modeData);
3200  return(FALSE);
3201 
3202  }
3203  }
3204 
3205  //
3206  // If the length is greater than length indicated by the mode data reset
3207  // the data to the mode data.
3208  //
3209 
3210  if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) {
3211  length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1;
3212  }
3213 
3214  //
3215  // Look for the flexible disk mode page.
3216  //
3217 
3218  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE);
3219 
3220  if (pageData != NULL) {
3221 
3222  DebugPrint((1, "Scsidisk: Flexible disk page found, This is a floppy.\n"));
3223  ExFreePool(modeData);
3224  return(TRUE);
3225  }
3226 
3227  //
3228  // Check to see if the write cache is enabled.
3229  //
3230 
3231  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE);
3232 
3233  //
3234  // Assume that write cache is disabled or not supported.
3235  //
3236 
3237  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3238 
3239  //
3240  // Check if valid caching page exists.
3241  //
3242 
3243  if (pageData != NULL) {
3244 
3245  //
3246  // Check if write cache is disabled.
3247  //
3248 
3249  if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) {
3250 
3251  DebugPrint((1,
3252  "SCSIDISK: Disk write cache enabled\n"));
3253 
3254  //
3255  // Check if forced unit access (FUA) is supported.
3256  //
3257 
3258  if (((PMODE_PARAMETER_HEADER)modeData)->DeviceSpecificParameter & MODE_DSP_FUA_SUPPORTED) {
3259 
3260  deviceExtension->DeviceFlags |= DEV_WRITE_CACHE;
3261 
3262  } else {
3263 
3264  DebugPrint((1,
3265  "SCSIDISK: Disk does not support FUA or DPO\n"));
3266 
3267  //
3268  // TODO: Log this.
3269  //
3270 
3271  }
3272  }
3273  }
3274 
3275  ExFreePool(modeData);
3276  return(FALSE);
3277 
3278 } // end IsFloppyDevice()
3279 
3280 
3281 BOOLEAN
3282 NTAPI
3285  IN PCHAR ModeSelectBuffer,
3286  IN ULONG Length,
3287  IN BOOLEAN SavePage
3288  )
3289 
3290 /*++
3291 
3292 Routine Description:
3293 
3294  This routine sends a mode select command.
3295 
3296 Arguments:
3297 
3298  DeviceObject - Supplies the device object associated with this request.
3299 
3300  ModeSelectBuffer - Supplies a buffer containing the page data.
3301 
3302  Length - Supplies the length in bytes of the mode select buffer.
3303 
3304  SavePage - Indicates that parameters should be written to disk.
3305 
3306 Return Value:
3307 
3308  Length of the transferred data is returned.
3309 
3310 --*/
3311 {
3312  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3313  PCDB cdb;
3314  SCSI_REQUEST_BLOCK srb;
3315  ULONG retries = 1;
3316  ULONG length2;
3317  NTSTATUS status;
3318  ULONG_PTR buffer;
3319  PMODE_PARAMETER_BLOCK blockDescriptor;
3320 
3321  PAGED_CODE();
3322 
3323  length2 = Length + sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
3324 
3325  //
3326  // Allocate buffer for mode select header, block descriptor, and mode page.
3327  //
3328 
3330 
3331  RtlZeroMemory((PVOID)buffer, length2);
3332 
3333  //
3334  // Set length in header to size of mode page.
3335  //
3336 
3337  ((PMODE_PARAMETER_HEADER)buffer)->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
3338 
3339  blockDescriptor = (PMODE_PARAMETER_BLOCK)(buffer + 1);
3340 
3341  //
3342  // Set size
3343  //
3344 
3345  blockDescriptor->BlockLength[1]=0x02;
3346 
3347  //
3348  // Copy mode page to buffer.
3349  //
3350 
3351  RtlCopyMemory((PVOID)(buffer + 3), ModeSelectBuffer, Length);
3352 
3353  //
3354  // Zero SRB.
3355  //
3356 
3357  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
3358 
3359  //
3360  // Build the MODE SELECT CDB.
3361  //
3362 
3363  srb.CdbLength = 6;
3364  cdb = (PCDB)srb.Cdb;
3365 
3366  //
3367  // Set timeout value from device extension.
3368  //
3369 
3370  srb.TimeOutValue = deviceExtension->TimeOutValue * 2;
3371 
3372  cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
3373  cdb->MODE_SELECT.SPBit = SavePage;
3374  cdb->MODE_SELECT.PFBit = 1;
3375  cdb->MODE_SELECT.ParameterListLength = (UCHAR)(length2);
3376 
3377 Retry:
3378 
3380  &srb,
3381  (PVOID)buffer,
3382  length2,
3383  TRUE);
3384 
3385 
3386  if (status == STATUS_VERIFY_REQUIRED) {
3387 
3388  //
3389  // Routine ScsiClassSendSrbSynchronous does not retry requests returned with
3390  // this status.
3391  //
3392 
3393  if (retries--) {
3394 
3395  //
3396  // Retry request.
3397  //
3398 
3399  goto Retry;
3400  }
3401 
3402  } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
3404  }
3405 
3407 
3408  if (NT_SUCCESS(status)) {
3409  return(TRUE);
3410  } else {
3411  return(FALSE);
3412  }
3413 
3414 } // end SciDiskModeSelect()
3415 
3416 
3417 VOID
3418 NTAPI
3421  IN PSCSI_INQUIRY_DATA LunInfo
3422  )
3423 
3424 {
3425  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3426  PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
3427  BAD_CONTROLLER_INFORMATION const *controller;
3428  ULONG j,length;
3429  PVOID modeData;
3430  PUCHAR pageData;
3431 
3432  for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) {
3433 
3434  controller = &ScsiDiskBadControllers[j];
3435 
3436  if (!controller->DisableWriteCache || strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) {
3437  continue;
3438  }
3439 
3440  DebugPrint((1, "ScsiDisk.DisableWriteCache, Found bad controller! %s\n", controller->InquiryString));
3441 
3443 
3444  if (modeData == NULL) {
3445 
3446  DebugPrint((1,
3447  "ScsiDisk.DisableWriteCache: Check for write-cache enable failed\n"));
3448  return;
3449  }
3450 
3451  RtlZeroMemory(modeData, MODE_DATA_SIZE);
3452 
3454  modeData,
3457 
3458  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3459 
3460  //
3461  // Retry the request in case of a check condition.
3462  //
3463 
3465  modeData,
3468 
3469  if (length < sizeof(MODE_PARAMETER_HEADER)) {
3470 
3471 
3472  DebugPrint((1,
3473  "ScsiDisk.DisableWriteCache: Mode Sense failed\n"));
3474 
3475  ExFreePool(modeData);
3476  return;
3477 
3478  }
3479  }
3480 
3481  //
3482  // If the length is greater than length indicated by the mode data reset
3483  // the data to the mode data.
3484  //
3485 
3486  if (length > (ULONG) ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1) {
3487  length = ((PMODE_PARAMETER_HEADER) modeData)->ModeDataLength + 1;
3488  }
3489 
3490  //
3491  // Check to see if the write cache is enabled.
3492  //
3493 
3494  pageData = ScsiClassFindModePage( modeData, length, MODE_PAGE_CACHING, TRUE);
3495 
3496  //
3497  // Assume that write cache is disabled or not supported.
3498  //
3499 
3500  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3501 
3502  //
3503  // Check if valid caching page exists.
3504  //
3505 
3506  if (pageData != NULL) {
3507 
3508  BOOLEAN savePage = FALSE;
3509 
3510  savePage = (BOOLEAN)(((PMODE_CACHING_PAGE)pageData)->PageSavable);
3511 
3512  //
3513  // Check if write cache is disabled.
3514  //
3515 
3516  if (((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable) {
3517 
3518  PIO_ERROR_LOG_PACKET errorLogEntry;
3519  LONG errorCode;
3520 
3521 
3522  //
3523  // Disable write cache and ensure necessary fields are zeroed.
3524  //
3525 
3526  ((PMODE_CACHING_PAGE)pageData)->WriteCacheEnable = FALSE;
3527  ((PMODE_CACHING_PAGE)pageData)->Reserved = 0;
3528  ((PMODE_CACHING_PAGE)pageData)->PageSavable = 0;
3529  ((PMODE_CACHING_PAGE)pageData)->Reserved2 = 0;
3530 
3531  //
3532  // Extract length from caching page.
3533  //
3534 
3535  length = ((PMODE_CACHING_PAGE)pageData)->PageLength;
3536 
3537  //
3538  // Compensate for page code and page length.
3539  //
3540 
3541  length += 2;
3542 
3543  //
3544  // Issue mode select to set the parameter.
3545  //
3546 
3548  (PCHAR)pageData,
3549  length,
3550  savePage)) {
3551 
3552  DebugPrint((1,
3553  "SCSIDISK: Disk write cache disabled\n"));
3554 
3555  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3556  errorCode = IO_WRITE_CACHE_DISABLED;
3557 
3558  } else {
3560  (PCHAR)pageData,
3561  length,
3562  savePage)) {
3563 
3564  DebugPrint((1,
3565  "SCSIDISK: Disk write cache disabled\n"));
3566 
3567 
3568  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
3569  errorCode = IO_WRITE_CACHE_DISABLED;
3570 
3571  } else {
3572 
3573  DebugPrint((1,
3574  "SCSIDISK: Mode select to disable write cache failed\n"));
3575 
3576  deviceExtension->DeviceFlags |= DEV_WRITE_CACHE;
3577  errorCode = IO_WRITE_CACHE_ENABLED;
3578  }
3579  }
3580 
3581  //
3582  // Log the appropriate informational or error entry.
3583  //
3584 
3586  DeviceObject,
3587  sizeof(IO_ERROR_LOG_PACKET) + 3
3588  * sizeof(ULONG));
3589 
3590  if (errorLogEntry != NULL) {
3591 
3592  errorLogEntry->FinalStatus = STATUS_SUCCESS;
3593  errorLogEntry->ErrorCode = errorCode;
3594  errorLogEntry->SequenceNumber = 0;
3595  errorLogEntry->MajorFunctionCode = IRP_MJ_SCSI;
3596  errorLogEntry->IoControlCode = 0;
3597  errorLogEntry->RetryCount = 0;
3598  errorLogEntry->UniqueErrorValue = 0x1;
3599  errorLogEntry->DumpDataSize = 3 * sizeof(ULONG);
3600  errorLogEntry->DumpData[0] = LunInfo->PathId;
3601  errorLogEntry->DumpData[1] = LunInfo->TargetId;
3602  errorLogEntry->DumpData[2] = LunInfo->Lun;
3603 
3604  //
3605  // Write the error log packet.
3606  //
3607 
3608  IoWriteErrorLogEntry(errorLogEntry);
3609  }
3610  }
3611  }
3612 
3613  //
3614  // Found device so exit the loop and return.
3615  //
3616 
3617  break;
3618  }
3619 
3620  return;
3621 }
3622 
3623 
3624 BOOLEAN
3625 NTAPI
3627  IN PDEVICE_EXTENSION DeviceExtension,
3628  OUT PULONG Checksum
3629  )
3630 
3631 /*++
3632 
3633 Routine Description:
3634 
3635  Read MBR and calculate checksum.
3636 
3637 Arguments:
3638 
3639  DeviceExtension - Supplies a pointer to the device information for disk.
3640  Checksum - Memory location to return MBR checksum.
3641 
3642 Return Value:
3643 
3644  Returns TRUE if checksum is valid.
3645 
3646 --*/
3647 {
3648  LARGE_INTEGER sectorZero;
3649  PIRP irp;
3650  IO_STATUS_BLOCK ioStatus;
3651  KEVENT event;
3652  NTSTATUS status;
3653  ULONG sectorSize;
3654  PULONG mbr;
3655  ULONG i;
3656 
3657  PAGED_CODE();
3658  sectorZero.QuadPart = (LONGLONG) 0;
3659 
3660  //
3661  // Create notification event object to be used to signal the inquiry
3662  // request completion.
3663  //
3664 
3666 
3667  //
3668  // Get sector size.
3669  //
3670 
3671  sectorSize = DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
3672 
3673  //
3674  // Make sure sector size is at least 512 bytes.
3675  //
3676 
3677  if (sectorSize < 512) {
3678  sectorSize = 512;
3679  }
3680 
3681  //
3682  // Allocate buffer for sector read.
3683  //
3684 
3685  mbr = ExAllocatePool(NonPagedPoolCacheAligned, sectorSize);
3686 
3687  if (!mbr) {
3688  return FALSE;
3689  }
3690 
3691  //
3692  // Build IRP to read MBR.
3693  //
3694 
3696  DeviceExtension->DeviceObject,
3697  mbr,
3698  sectorSize,
3699  &sectorZero,
3700  &event,
3701  &ioStatus );
3702 
3703  if (!irp) {
3704  ExFreePool(mbr);
3705  return FALSE;
3706  }
3707 
3708  //
3709  // Pass request to port driver and wait for request to complete.
3710  //
3711 
3712  status = IoCallDriver(DeviceExtension->DeviceObject,
3713  irp);
3714 
3715  if (status == STATUS_PENDING) {
3717  Suspended,
3718  KernelMode,
3719  FALSE,
3720  NULL);
3721  status = ioStatus.Status;
3722  }
3723 
3724  if (!NT_SUCCESS(status)) {
3725  ExFreePool(mbr);
3726  return FALSE;
3727  }
3728 
3729  //
3730  // Calculate MBR checksum.
3731  //
3732 
3733  *Checksum = 0;
3734 
3735  for (i = 0; i < 128; i++) {
3736  *Checksum += mbr[i];
3737  }
3738 
3739  *Checksum = ~*Checksum + 1;
3740 
3741  ExFreePool(mbr);
3742  return TRUE;
3743 }
3744 
3745 
3746 BOOLEAN
3747 NTAPI
3749  IN PDEVICE_EXTENSION DeviceExtension,
3750  HANDLE BusKey,
3751  PULONG DiskNumber
3752  )
3753 
3754 /*++
3755 
3756 Routine Description:
3757 
3758  The routine queries the registry to determine if this disk is visible to
3759  the BIOS. If the disk is visible to the BIOS, then the geometry information
3760  is updated.
3761 
3762 Arguments:
3763 
3764  DeviceExtension - Supplies a pointer to the device information for disk.
3765  Signature - Unique identifier recorded in MBR.
3766  BusKey - Handle of bus key.
3767  DiskNumber - Returns ordinal of disk as BIOS sees it.
3768 
3769 Return Value:
3770 
3771  TRUE is disk signature matched.
3772 
3773 --*/
3774 {
3775  PDISK_DATA diskData = (PDISK_DATA)(DeviceExtension + 1);
3776  BOOLEAN diskFound = FALSE;
3777  OBJECT_ATTRIBUTES objectAttributes;
3778  UNICODE_STRING unicodeString;
3779  UNICODE_STRING identifier;
3780  ULONG busNumber;
3781  ULONG adapterNumber;
3782  ULONG diskNumber;
3783  HANDLE adapterKey;
3784  HANDLE spareKey;
3785  HANDLE diskKey;
3786  HANDLE targetKey;
3787  NTSTATUS status;
3788  STRING string;
3789  STRING anotherString;
3790  ULONG length;
3791  UCHAR buffer[20];
3793 
3794  PAGED_CODE();
3795 
3796  for (busNumber = 0; ; busNumber++) {
3797 
3798  //
3799  // Open controller name key.
3800  //
3801 
3802  sprintf((PCHAR)buffer,
3803  "%lu",
3804  busNumber);
3805 
3806  RtlInitString(&string,
3807  (PCSZ)buffer);
3808 
3809  status = RtlAnsiStringToUnicodeString(&unicodeString,
3810  &string,
3811  TRUE);
3812 
3813  if (!NT_SUCCESS(status)){
3814  break;
3815  }
3816 
3817  InitializeObjectAttributes(&objectAttributes,
3818  &unicodeString,
3820  BusKey,
3822 
3823  status = ZwOpenKey(&spareKey,
3824  KEY_READ,
3825  &objectAttributes);
3826 
3827  RtlFreeUnicodeString(&unicodeString);
3828 
3829  if (!NT_SUCCESS(status)) {
3830  break;
3831  }
3832 
3833  //
3834  // Open up controller ordinal key.
3835  //
3836 
3837  RtlInitUnicodeString(&unicodeString, L"DiskController");
3838  InitializeObjectAttributes(&objectAttributes,
3839  &unicodeString,
3841  spareKey,
3843 
3844  status = ZwOpenKey(&adapterKey,
3845  KEY_READ,
3846  &objectAttributes);
3847 
3848  //
3849  // This could fail even with additional adapters of this type
3850  // to search.
3851  //
3852 
3853  if (!NT_SUCCESS(status)) {
3854  continue;
3855  }
3856 
3857  for (adapterNumber = 0; ; adapterNumber++) {
3858 
3859  //
3860  // Open disk key.
3861  //
3862 
3863  sprintf((PCHAR)buffer,
3864  "%lu\\DiskPeripheral",
3865  adapterNumber);
3866 
3867  RtlInitString(&string,
3868  (PCSZ)buffer);
3869 
3870  status = RtlAnsiStringToUnicodeString(&unicodeString,
3871  &string,
3872  TRUE);
3873 
3874  if (!NT_SUCCESS(status)){
3875  break;
3876  }
3877 
3878  InitializeObjectAttributes(&objectAttributes,
3879  &unicodeString,
3881  adapterKey,
3883 
3884  status = ZwOpenKey(&diskKey,
3885  KEY_READ,
3886  &objectAttributes);
3887 
3888  RtlFreeUnicodeString(&unicodeString);
3889 
3890  if (!NT_SUCCESS(status)) {
3891  break;
3892  }
3893 
3894  for (diskNumber = 0; ; diskNumber++) {
3895 
3896  sprintf((PCHAR)buffer,
3897  "%lu",
3898  diskNumber);
3899 
3900  RtlInitString(&string,
3901  (PCSZ)buffer);
3902 
3903  status = RtlAnsiStringToUnicodeString(&unicodeString,
3904  &string,
3905  TRUE);
3906 
3907  if (!NT_SUCCESS(status)){
3908  break;
3909  }
3910 
3911  InitializeObjectAttributes(&objectAttributes,
3912  &unicodeString,
3914  diskKey,
3916 
3917  status = ZwOpenKey(&targetKey,
3918  KEY_READ,
3919  &objectAttributes);
3920 
3921  RtlFreeUnicodeString(&unicodeString);
3922 
3923  if (!NT_SUCCESS(status)) {
3924  break;
3925  }
3926 
3927  //
3928  // Allocate buffer for registry query.
3929  //
3930 
3932 
3933  if (keyData == NULL) {
3934  ZwClose(targetKey);
3935  continue;
3936  }
3937 
3938  //
3939  // Get disk peripheral identifier.
3940  //
3941 
3942  RtlInitUnicodeString(&unicodeString, L"Identifier");
3943  status = ZwQueryValueKey(targetKey,
3944  &unicodeString,
3946  keyData,
3948  &length);
3949 
3950  ZwClose(targetKey);
3951 
3952  if (!NT_SUCCESS(status)) {
3953  ExFreePool(keyData);
3954  continue;
3955  }
3956 
3957  if (keyData->DataLength < 9*sizeof(WCHAR)) {
3958  //
3959  // the data is too short to use (we subtract 9 chars in normal path)
3960  //
3961  DebugPrint((1, "EnumerateBusKey: Saved data was invalid, "
3962  "not enough data in registry!\n"));
3963  ExFreePool(keyData);
3964  continue;
3965  }
3966 
3967  //
3968  // Complete unicode string.
3969  //
3970 
3971  identifier.Buffer =
3972  (PWSTR)((PUCHAR)keyData + keyData->DataOffset);
3973  identifier.Length = (USHORT)keyData->DataLength;
3974  identifier.MaximumLength = (USHORT)keyData->DataLength;
3975 
3976  //
3977  // Convert unicode identifier to ansi string.
3978  //
3979 
3980  status =
3981  RtlUnicodeStringToAnsiString(&anotherString,
3982  &identifier,
3983  TRUE);
3984 
3985  if (!NT_SUCCESS(status)) {
3986  ExFreePool(keyData);
3987  continue;
3988  }
3989 
3990  //
3991  // If checksum is zero, then the MBR is valid and
3992  // the signature is meaningful.
3993  //
3994 
3995  if (diskData->MbrCheckSum) {
3996 
3997  //
3998  // Convert checksum to ansi string.
3999  //
4000 
4001  sprintf((PCHAR)buffer, "%08lx", diskData->MbrCheckSum);
4002 
4003  } else {
4004 
4005  //
4006  // Convert signature to ansi string.
4007  //
4008 
4009  sprintf((PCHAR)buffer, "%08lx", diskData->Signature);
4010 
4011  //
4012  // Make string point at signature. Can't use scan
4013  // functions because they are not exported for driver use.
4014  //
4015 
4016  anotherString.Buffer+=9;
4017  }
4018 
4019  //
4020  // Convert to ansi string.
4021  //
4022 
4023  RtlInitString(&string,
4024  (PCSZ)buffer);
4025 
4026 
4027  //
4028  // Make string lengths equal.
4029  //
4030 
4031  anotherString.Length = string.Length;
4032 
4033  //
4034  // Check if strings match.
4035  //
4036 
4037  if (RtlCompareString(&string,
4038  &anotherString,
4039  TRUE) == 0) {
4040 
4041  diskFound = TRUE;
4042  *DiskNumber = diskNumber;
4043  }
4044 
4045  ExFreePool(keyData);
4046 
4047  //
4048  // Readjust identifier string if necessary.
4049  //
4050 
4051  if (!diskData->MbrCheckSum) {
4052  anotherString.Buffer-=9;
4053  }
4054 
4055  RtlFreeAnsiString(&anotherString);
4056 
4057  if (diskFound) {
4058  break;
4059  }
4060  }
4061 
4062  ZwClose(diskKey);
4063  }
4064 
4065  ZwClose(adapterKey);
4066  }
4067 
4068  ZwClose(BusKey);
4069  return diskFound;
4070 
4071 } // end EnumerateBusKey()
4072 
4073 
4074 VOID
4075 NTAPI
4077  IN PDEVICE_EXTENSION DeviceExtension
4078  )
4079 /*++
4080 
4081 Routine Description:
4082 
4083  The routine queries the registry to determine if this disk is visible to
4084  the BIOS. If the disk is visible to the BIOS, then the geometry information
4085  is updated.
4086 
4087 Arguments:
4088 
4089  DeviceExtension - Supplies a pointer to the device information for disk.
4090 
4091 Return Value:
4092 
4093  None.
4094 
4095 --*/
4096 
4097 {
4098  OBJECT_ATTRIBUTES objectAttributes;
4099  UNICODE_STRING unicodeString;
4100  NTSTATUS status;
4101  HANDLE hardwareKey;
4102  HANDLE busKey;
4103  PCM_INT13_DRIVE_PARAMETER driveParameters;
4104  PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor;
4106  ULONG diskNumber;
4107  PUCHAR buffer;
4108  ULONG length;
4109  ULONG numberOfDrives;
4110  ULONG cylinders;
4111  ULONG sectors;
4112  ULONG sectorsPerTrack;
4113  ULONG tracksPerCylinder;
4114  BOOLEAN foundEZHooker;
4115  PVOID tmpPtr;
4116 
4117  PAGED_CODE();
4118 
4119  //
4120  // Initialize the object for the key.
4121  //
4122 
4123  InitializeObjectAttributes(&objectAttributes,
4124  DeviceExtension->DeviceObject->DriverObject->HardwareDatabase,
4126  NULL,
4128 
4129  //
4130  // Create the hardware base key.
4131  //
4132 
4133  status = ZwOpenKey(&hardwareKey,
4134  KEY_READ,
4135  &objectAttributes);
4136 
4137 
4138  if (!NT_SUCCESS(status)) {
4139  DebugPrint((1, "ScsiDisk UpdateParameters: Cannot open hardware data. Name: %wZ\n", DeviceExtension->DeviceObject->DriverObject->HardwareDatabase));
4140  return;
4141  }
4142 
4143 
4144  //
4145  // Get disk BIOS geometry information.
4146  //
4147 
4148  RtlInitUnicodeString(&unicodeString, L"Configuration Data");
4149 
4151 
4152  if (keyData == NULL) {
4153  ZwClose(hardwareKey);
4154  return;
4155  }
4156 
4157  status = ZwQueryValueKey(hardwareKey,
4158  &unicodeString,
4160  keyData,
4162  &length);
4163 
4164  if (!NT_SUCCESS(status)) {
4165  DebugPrint((1,
4166  "SCSIDISK: ExtractBiosGeometry: Can't query configuration data (%x)\n",
4167  status));
4168  ZwClose(hardwareKey);
4169  ExFreePool(keyData);
4170  return;
4171  }
4172 
4173  //
4174  // Open EISA bus key.
4175  //
4176 
4177  RtlInitUnicodeString(&unicodeString, L"EisaAdapter");
4178 
4179  InitializeObjectAttributes(&objectAttributes,
4180  &unicodeString,
4182  hardwareKey,
4184 
4185  status = ZwOpenKey(&busKey,
4186  KEY_READ,
4187  &objectAttributes);
4188 
4189  if (!NT_SUCCESS(status)) {
4190  goto openMultiKey;
4191  }
4192 
4193  DebugPrint((3,
4194  "SCSIDISK: UpdateGeometry: Opened EisaAdapter key\n"));
4195  if (EnumerateBusKey(DeviceExtension,
4196  busKey,
4197  &diskNumber)) {
4198 
4199  ZwClose(hardwareKey);
4200  goto diskMatched;
4201  }
4202 
4203 openMultiKey:
4204 
4205  //
4206  // Open Multifunction bus key.
4207  //
4208 
4209  RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter");
4210 
4211  InitializeObjectAttributes(&objectAttributes,
4212  &unicodeString,
4214  hardwareKey,
4216 
4217  status = ZwOpenKey(&busKey,
4218  KEY_READ,
4219  &objectAttributes);
4220 
4221  ZwClose(hardwareKey);
4222  if (NT_SUCCESS(status)) {
4223  DebugPrint((3,
4224  "SCSIDISK: UpdateGeometry: Opened MultifunctionAdapter key\n"));
4225  if (EnumerateBusKey(DeviceExtension,
4226  busKey,
4227  &diskNumber)) {
4228 
4229  goto diskMatched;
4230  }
4231  }
4232 
4233  ExFreePool(keyData);
4234  return;
4235 
4236 diskMatched:
4237 
4238  resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)keyData +
4239  keyData->DataOffset);
4240 
4241  //
4242  // Check that the data is long enough to hold a full resource descriptor,
4243  // and that the last resource list is device-specific and long enough.
4244  //
4245 
4246  if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) ||
4247  resourceDescriptor->PartialResourceList.Count == 0 ||
4248  resourceDescriptor->PartialResourceList.PartialDescriptors[0].Type !=
4250  resourceDescriptor->PartialResourceList.PartialDescriptors[0]
4251  .u.DeviceSpecificData.DataSize < sizeof(ULONG)) {
4252 
4253  DebugPrint((1, "SCSIDISK: ExtractBiosGeometry: BIOS header data too small or invalid\n"));
4254  ExFreePool(keyData);
4255  return;
4256  }
4257 
4258  length =
4259  resourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize;
4260 
4261  //
4262  // Point to the BIOS data. The BIOS data is located after the first
4263  // partial Resource list which should be device specific data.
4264  //
4265 
4266  buffer = (PUCHAR) keyData + keyData->DataOffset +
4268 
4269 
4270  numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
4271 
4272  //
4273  // Use the defaults if the drive number is greater than the
4274  // number of drives detected by the BIOS.
4275  //
4276 
4277  if (numberOfDrives <= diskNumber) {
4278  ExFreePool(keyData);
4279  return;
4280  }
4281 
4282  //
4283  // Point to the array of drive parameters.
4284  //
4285 
4286  driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer + diskNumber;
4287  cylinders = driveParameters->MaxCylinders + 1;
4288  sectorsPerTrack = driveParameters->SectorsPerTrack;
4289  tracksPerCylinder = driveParameters->MaxHeads +1;
4290 
4291  //
4292  // Calculate the actual number of sectors.
4293  //
4294 
4295  sectors = (ULONG)(DeviceExtension->PartitionLength.QuadPart >>
4296  DeviceExtension->SectorShift);
4297 
4298 #if DBG
4299  if (sectors >= cylinders * tracksPerCylinder * sectorsPerTrack) {
4300  DebugPrint((1, "ScsiDisk: UpdateGeometry: Disk smaller than BIOS indicated\n"
4301  "SCSIDISK: Sectors: %x, Cylinders: %x, Track per Cylinder: %x Sectors per track: %x\n",
4302  sectors, cylinders, tracksPerCylinder, sectorsPerTrack));
4303  }
4304 #endif
4305 
4306  //
4307  // Since the BIOS may not report the full drive, recalculate the drive
4308  // size based on the volume size and the BIOS values for tracks per
4309  // cylinder and sectors per track..
4310  //
4311 
4312  length = tracksPerCylinder * sectorsPerTrack;
4313 
4314  if (length == 0) {
4315 
4316  //
4317  // The BIOS information is bogus.
4318  //
4319 
4320  DebugPrint((1, "ScsiDisk UpdateParameters: sectorPerTrack zero\n"));
4321  ExFreePool(keyData);
4322  return;
4323  }
4324 
4325  cylinders = sectors / length;
4326 
4327  //
4328  // Update the actual geometry information.
4329  //
4330 
4331  DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack = sectorsPerTrack;
4332  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder;
4333  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)cylinders;
4334  DeviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG)cylinders * tracksPerCylinder * sectorsPerTrack *
4335  DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
4336 
4337  DebugPrint((3,
4338  "SCSIDISK: UpdateGeometry: BIOS spt %x, #heads %x, #cylinders %x\n",
4339  sectorsPerTrack,
4340  tracksPerCylinder,
4341  cylinders));
4342 
4343  ExFreePool(keyData);
4344 
4345  foundEZHooker = FALSE;
4346 
4347  if (!DeviceExtension->DMActive) {
4348 
4349  HalExamineMBR(DeviceExtension->DeviceObject,
4350  DeviceExtension->DiskGeometry->Geometry.BytesPerSector,
4351  (ULONG)0x55,
4352  &tmpPtr
4353  );
4354 
4355  if (tmpPtr) {
4356 
4357  ExFreePool(tmpPtr);
4358  foundEZHooker = TRUE;
4359 
4360  }
4361 
4362  }
4363 
4364  if (DeviceExtension->DMActive || foundEZHooker) {
4365 
4366  while (cylinders > 1024) {
4367 
4368  tracksPerCylinder = tracksPerCylinder*2;
4369  cylinders = cylinders/2;
4370 
4371  }
4372 
4373  //
4374  // int 13 values are always 1 less.
4375  //
4376 
4377  tracksPerCylinder -= 1;
4378  cylinders -= 1;
4379 
4380  //
4381  // DM reserves the CE cylinder
4382  //
4383 
4384  cylinders -= 1;
4385 
4386  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = cylinders + 1;
4387  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder + 1;
4388 
4389  DeviceExtension->PartitionLength.QuadPart =
4390  DeviceExtension->DiskGeometry->DiskSize.QuadPart =
4391  DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart *
4392  DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack *
4393  DeviceExtension->DiskGeometry->Geometry.BytesPerSector *
4394  DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder;
4395 
4396  if (DeviceExtension->DMActive) {
4397 
4398  DeviceExtension->DMByteSkew = DeviceExtension->DMSkew * DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
4399 
4400  }
4401 
4402  } else {
4403 
4404  DeviceExtension->DMByteSkew = 0;
4405 
4406  }
4407 
4408  return;
4409 
4410 } // end UpdateGeometry()
4411 
4412 
4413 
4414 NTSTATUS
4415 NTAPI
4418  IN PIRP Irp
4419  )
4420 
4421 /*++
4422 
4423 Routine Description:
4424 
4425  This routines updates the size and starting offset of the device. This is
4426  used when the media on the device may have changed thereby changing the
4427  size of the device. If this is the physical device then a
4428  ScsiClassReadDriveCapacity is done; otherewise, a read partition table is done.
4429 
4430 Arguments:
4431 
4432  DeviceObject - Supplies the device object whos size needs to be updated.
4433 
4434  Irp - Supplies a reference where the status can be updated.
4435 
4436 Return Value:
4437 
4438  Returns the status of the operation.
4439 
4440 --*/
4441 {
4442 
4443  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4444  PDRIVE_LAYOUT_INFORMATION partitionList;
4445  NTSTATUS status;
4446  PDISK_DATA diskData;
4447  ULONG partitionNumber;
4448 
4449  //
4450  // Determine if the size of the partition may have changed because
4451  // the media has changed.
4452  //
4453 
4454  if (!(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
4455 
4456  return(STATUS_SUCCESS);
4457 
4458  }
4459 
4460  //
4461  // If this request is for partition zero then do a read drive
4462  // capacity otherwise do a I/O read partition table.
4463  //
4464 
4465  diskData = (PDISK_DATA) (deviceExtension + 1);
4466 
4467  //
4468  // Read the drive capacity. If that fails, give up.
4469  //
4470 
4471  status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
4472 
4473  if (!NT_SUCCESS(status)) {
4474  return(status);
4475  }
4476 
4477 #ifdef __REACTOS__
4478  //
4479  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
4480  // for removable devices and avoid an infinite recursive loop between
4481  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
4482  //
4483  // Check whether the update-count is greater or equal than one
4484  // (and increase it) and if so, reset it and return success.
4485  if (diskData->UpdateRemovableGeometryCount++ >= 1)
4486  {
4487  diskData->UpdateRemovableGeometryCount = 0;
4488  return(STATUS_SUCCESS);
4489  }
4490 #endif
4491 
4492  //
4493  // Read the partition table again.
4494  //
4495 
4496  status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
4497  deviceExtension->DiskGeometry->Geometry.BytesPerSector,
4498  TRUE,
4499  &partitionList);
4500 
4501 #ifdef __REACTOS__
4502  //
4503  // HACK so that we can use NT5+ NTOS functions with this NT4 driver
4504  // for removable devices and avoid an infinite recursive loop between
4505  // disk!UpdateRemovableGeometry() and ntos!IoReadPartitionTable().
4506  //
4507  // Inconditionally reset the update-count.
4508  diskData->UpdateRemovableGeometryCount = 0;
4509 #endif
4510 
4511  if (!NT_SUCCESS(status)) {
4512 
4513  //
4514  // Fail the request.
4515  //
4516 
4517  return(status);
4518  }
4519 
4520  if (diskData->PartitionNumber != 0 &&
4521  diskData->PartitionNumber <= partitionList->PartitionCount ) {
4522 
4523  partitionNumber = diskData->PartitionNumber - 1;
4524 
4525  //
4526  // Update the partition information for this partition.
4527  //
4528 
4529  diskData->PartitionType =
4530  partitionList->PartitionEntry[partitionNumber].PartitionType;
4531 
4532  diskData->BootIndicator =
4533  partitionList->PartitionEntry[partitionNumber].BootIndicator;
4534 
4535  deviceExtension->StartingOffset =
4536  partitionList->PartitionEntry[partitionNumber].StartingOffset;
4537 
4538  deviceExtension->PartitionLength =
4539  partitionList->PartitionEntry[partitionNumber].PartitionLength;
4540 
4541  diskData->HiddenSectors =
4542  partitionList->PartitionEntry[partitionNumber].HiddenSectors;
4543 
4544  deviceExtension->SectorShift = ((PDEVICE_EXTENSION)
4545  deviceExtension->PhysicalDevice->DeviceExtension)->SectorShift;
4546 
4547  } else if (diskData->PartitionNumber != 0) {
4548 
4549  //
4550  // The partition does not exist. Zero all the data.
4551  //
4552 
4553  diskData->PartitionType = 0;
4554  diskData->BootIndicator = 0;
4555  diskData->HiddenSectors = 0;
4556  deviceExtension->StartingOffset.QuadPart = (LONGLONG)0;
4557  deviceExtension->PartitionLength.QuadPart = (LONGLONG)0;
4558  }
4559 
4560  //
4561  // Free the partition list allocate by I/O read partition table.
4562  //
4563 
4564  ExFreePool(partitionList);
4565 
4566 
4567  return(STATUS_SUCCESS);
4568 }
4569 
4570 
4571 VOID
4572 NTAPI
4576  NTSTATUS *Status,
4577  BOOLEAN *Retry
4578  )
4579 /*++
4580 
4581 Routine Description:
4582 
4583  This routine checks the type of error. If the error indicates an underrun
4584  then indicate the request should be retried.
4585 
4586 Arguments:
4587 
4588  DeviceObject - Supplies a pointer to the device object.
4589 
4590  Srb - Supplies a pointer to the failing Srb.
4591 
4592  Status - Status with which the IRP will be completed.
4593 
4594  Retry - Indication of whether the request will be retried.
4595 
4596 Return Value:
4597 
4598  None.
4599 
4600 --*/
4601 
4602 {
4603  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4604 
4605  if (*Status == STATUS_DATA_OVERRUN &&
4606  ( Srb->Cdb[0] == SCSIOP_WRITE || Srb->Cdb[0] == SCSIOP_READ)) {
4607 
4608  *Retry = TRUE;
4609 
4610  //
4611  // Update the error count for the device.
4612  //
4613 
4614  deviceExtension->ErrorCount++;
4615  }
4616 
4617  if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_ERROR &&
4618  Srb->ScsiStatus == SCSISTAT_BUSY) {
4619 
4620  //
4621  // The disk drive should never be busy this long. Reset the scsi bus
4622  // maybe this will clear the condition.
4623  //
4624 
4626 
4627  //
4628  // Update the error count for the device.
4629  //
4630 
4631  deviceExtension->ErrorCount++;
4632  }
4633 }
4634 
4635 VOID
4636 NTAPI
4639  PSCSI_INQUIRY_DATA LunInfo,
4640  PIO_SCSI_CAPABILITIES PortCapabilities
4641  )
4642 
4643 /*++
4644 
4645 Routine Description:
4646 
4647  This function checks to see if an SCSI logical unit requires special
4648  flags to be set.
4649 
4650 Arguments:
4651 
4652  DeviceObject - Supplies the device object to be tested.
4653 
4654  InquiryData - Supplies the inquiry data returned by the device of interest.
4655 
4656  PortCapabilities - Supplies the capabilities of the device object.
4657 
4658 Return Value:
4659 
4660  None.
4661 
4662 --*/
4663 
4664 {
4665  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4666  PINQUIRYDATA InquiryData = (PINQUIRYDATA)LunInfo->InquiryData;
4667  BAD_CONTROLLER_INFORMATION const *controller;
4668  ULONG j;
4669 
4670  for (j = 0; j < NUMBER_OF_BAD_CONTROLLERS; j++) {
4671 
4672  controller = &ScsiDiskBadControllers[j];
4673 
4674  if (strncmp(controller->InquiryString, (PCCHAR)InquiryData->VendorId, strlen(controller->InquiryString))) {
4675  continue;
4676  }
4677 
4678  DebugPrint((1, "ScsiDisk ScanForSpecial, Found bad controller! %s\n", controller->InquiryString));
4679 
4680  //
4681  // Found a listed controller. Determine what must be done.
4682  //
4683 
4684  if (controller->DisableTaggedQueuing) {
4685 
4686  //
4687  // Disable tagged queuing.
4688  //
4689 
4690  deviceExtension->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
4691  }
4692 
4693  if (controller->DisableSynchronousTransfers) {
4694 
4695  //
4696  // Disable synchronous data transfers.
4697  //
4698 
4699  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
4700 
4701  }
4702 
4703  if (controller->DisableDisconnects) {
4704 
4705  //
4706  // Disable disconnects.
4707  //
4708 
4709  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
4710 
4711  }
4712 
4713  //
4714  // Found device so exit the loop and return.
4715  //
4716 
4717  break;
4718  }
4719 
4720  //
4721  // Set the StartUnit flag appropriately.
4722  //
4723 
4724  if (DeviceObject->DeviceType == FILE_DEVICE_DISK) {
4725  deviceExtension->DeviceFlags |= DEV_SAFE_START_UNIT;
4726 
4727  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
4728  if (_strnicmp((PCCHAR)InquiryData->VendorId, "iomega", strlen("iomega"))) {
4729  deviceExtension->DeviceFlags &= ~DEV_SAFE_START_UNIT;
4730  }
4731  }
4732  }
4733 
4734  return;
4735 }
4736 
4737 VOID
4738 NTAPI
4741  )
4742 
4743 /*++
4744 
4745 Routine Description:
4746 
4747  This command sends a reset bus command to the SCSI port driver.
4748 
4749 Arguments:
4750 
4751  DeviceObject - The device object for the logical unit with
4752  hardware problem.
4753 
4754 Return Value:
4755 
4756  None.
4757 
4758 --*/
4759 {
4760  PIO_STACK_LOCATION irpStack;
4761  PIRP irp;
4762  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4763  PSCSI_REQUEST_BLOCK srb;
4765 
4766  DebugPrint((1, "ScsiDisk ResetScsiBus: Sending reset bus request to port driver.\n"));
4767 
4768  //
4769  // Allocate Srb from nonpaged pool.
4770  //
4771 
4773  sizeof(COMPLETION_CONTEXT));
4774 
4775  //
4776  // Save the device object in the context for use by the completion
4777  // routine.
4778  //
4779 
4780  context->DeviceObject = DeviceObject;
4781  srb = &context->Srb;
4782 
4783  //
4784  // Zero out srb.
4785  //
4786 
4788 
4789  //
4790  // Write length to SRB.
4791  //
4792 
4794 
4795  //
4796  // Set up SCSI bus address.
4797  //
4798 
4799  srb->PathId = deviceExtension->PathId;
4800  srb->TargetId = deviceExtension->TargetId;
4801  srb->Lun = deviceExtension->Lun;
4802 
4804 
4805  //
4806  // Build the asynchronous request to be sent to the port driver.
4807  // Since this routine is called from a DPC the IRP should always be
4808  // available.
4809  //
4810 
4812 
4815  context,
4816  TRUE,
4817  TRUE,
4818  TRUE);
4819 
4820  irpStack = IoGetNextIrpStackLocation(irp);
4821 
4822  irpStack->MajorFunction = IRP_MJ_SCSI;
4823 
4824  srb->OriginalRequest = irp;
4825 
4826  //
4827  // Store the SRB address in next stack for port driver.
4828  //
4829 
4830  irpStack->Parameters.Scsi.Srb = srb;
4831 
4832  //
4833  // Call the port driver with the IRP.
4834  //
4835 
4836  IoCallDriver(deviceExtension->PortDeviceObject, irp);
4837 
4838  return;
4839 
4840 } // end ResetScsiBus()
4841 
4842 
4843 VOID
4844 NTAPI
4846  IN PDEVICE_OBJECT PhysicalDisk,
4847  IN PIRP Irp
4848  )
4849 
4850 /*++
4851 
4852 Routine Description:
4853 
4854  This routine creates, deletes and changes device objects when
4855  the IOCTL_SET_DRIVE_LAYOUT is called. This routine also updates
4856  the drive layout information for the user. It is possible to
4857  call this routine even in the GET_LAYOUT case because RewritePartition
4858  will be false.
4859 
4860 Arguments:
4861 
4862  DeviceObject - Device object for physical disk.
4863  Irp - IO Request Packet (IRP).
4864 
4865 Return Value:
4866 
4867  None.
4868 
4869 --*/
4870 {
4871  PDEVICE_EXTENSION physicalExtension = PhysicalDisk->DeviceExtension;
4872  PDRIVE_LAYOUT_INFORMATION partitionList = Irp->AssociatedIrp.SystemBuffer;
4873  ULONG partition;
4874  ULONG partitionNumber;
4875  ULONG partitionCount;
4876  ULONG lastPartition;
4877  ULONG partitionOrdinal;
4878  PPARTITION_INFORMATION partitionEntry;
4879  CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
4880  STRING ntNameString;
4881  UNICODE_STRING ntUnicodeString;
4882  PDEVICE_OBJECT deviceObject;
4883  PDEVICE_EXTENSION deviceExtension;
4884  PDISK_DATA diskData;
4885  NTSTATUS status;
4886  ULONG numberListElements;
4887  BOOLEAN found;
4888 
4889  partitionCount = ((partitionList->PartitionCount + 3) / 4) * 4;
4890 
4891  //
4892  // Zero all of the partition numbers.
4893  //
4894 
4895  for (partition = 0; partition < partitionCount; partition++) {
4896  partitionEntry = &partitionList->PartitionEntry[partition];
4897  partitionEntry->PartitionNumber = 0;
4898  }
4899 
4900  //
4901  // Walk through chain of partitions for this disk to determine
4902  // which existing partitions have no match.
4903  //
4904 
4905  deviceExtension = physicalExtension;
4906  diskData = (PDISK_DATA)(deviceExtension + 1);
4907  lastPartition = 0;
4908 
4909  do {
4910 
4911  deviceExtension = diskData->NextPartition;
4912 
4913  //
4914  // Check if this is the last partition in the chain.
4915  //
4916 
4917  if (!deviceExtension) {
4918  break;
4919  }
4920 
4921  //
4922  // Get the partition device extension from disk data.
4923  //
4924 
4925  diskData = (PDISK_DATA)(deviceExtension + 1);
4926 
4927  //
4928  // Check for highest partition number this far.
4929  //
4930 
4931  if (diskData->PartitionNumber > lastPartition) {
4932  lastPartition = diskData->PartitionNumber;
4933  }
4934 
4935  //
4936  // Check if this partition is not currently being used.
4937  //
4938 
4939  if (!deviceExtension->PartitionLength.QuadPart) {
4940  continue;
4941  }
4942 
4943  //
4944  // Loop through partition information to look for match.
4945  //
4946 
4947  found = FALSE;
4948  partitionOrdinal = 0;
4949 
4950  for (partition = 0; partition < partitionCount; partition++) {
4951 
4952  //
4953  // Get partition descriptor.
4954  //
4955 
4956  partitionEntry = &partitionList->PartitionEntry[partition];
4957 
4958  //
4959  // Check if empty, or describes extended partition or hasn't changed.
4960  //
4961 
4962  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
4963  IsContainerPartition(partitionEntry->PartitionType)) {
4964  continue;
4965  }
4966 
4967  //
4968  // Advance partition ordinal.
4969  //
4970 
4971  partitionOrdinal++;
4972 
4973  //
4974  // Check if new partition starts where this partition starts.
4975  //
4976 
4977  if (partitionEntry->StartingOffset.QuadPart !=
4978  deviceExtension->StartingOffset.QuadPart) {
4979  continue;
4980  }
4981 
4982  //
4983  // Check if partition length is the same.
4984  //
4985 
4986  if (partitionEntry->PartitionLength.QuadPart ==
4987  deviceExtension->PartitionLength.QuadPart) {
4988 
4989  DebugPrint((3,
4990  "UpdateDeviceObjects: Found match for \\Harddisk%d\\Partition%d\n",
4991  physicalExtension->DeviceNumber,
4992  diskData->PartitionNumber));
4993 
4994  //
4995  // Indicate match is found and set partition number
4996  // in user buffer.
4997  //
4998 
4999  found = TRUE;
5000  partitionEntry->PartitionNumber = diskData->PartitionNumber;
5001  break;
5002  }
5003  }
5004 
5005  if (found) {
5006 
5007  //
5008  // A match is found.
5009  //
5010 
5011  diskData = (PDISK_DATA)(deviceExtension + 1);
5012 
5013  //
5014  // If this partition is marked for update then update partition type.
5015  //
5016 
5017  if (partitionEntry->RewritePartition) {
5018  diskData->PartitionType = partitionEntry->PartitionType;
5019  }
5020 
5021  //
5022  // Update partitional ordinal for calls to HAL routine
5023  // IoSetPartitionInformation.
5024  //
5025 
5026  diskData->PartitionOrdinal = partitionOrdinal;
5027 
5028  DebugPrint((1,
5029  "UpdateDeviceObjects: Disk %d ordinal %d is partition %d\n",
5030  physicalExtension->DeviceNumber,
5031  diskData->PartitionOrdinal,
5032  diskData->PartitionNumber));
5033 
5034  } else {
5035 
5036  //
5037  // no match was found, indicate this partition is gone.
5038  //
5039 
5040  DebugPrint((1,
5041  "UpdateDeviceObjects: Deleting \\Device\\Harddisk%x\\Partition%x\n",
5042  physicalExtension->DeviceNumber,
5043  diskData->PartitionNumber));
5044 
5045  deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0;
5046  }
5047 
5048  } while (TRUE);
5049 
5050  //
5051  // Walk through partition loop to find new partitions and set up
5052  // device extensions to describe them. In some cases new device
5053  // objects will be created.
5054  //
5055 
5056  partitionOrdinal = 0;
5057 
5058  for (partition = 0;
5059  partition < partitionCount;
5060  partition++) {
5061 
5062  //
5063  // Get partition descriptor.
5064  //
5065 
5066  partitionEntry = &partitionList->PartitionEntry[partition];
5067 
5068  //
5069  // Check if empty, or describes an extended partition.
5070  //
5071 
5072  if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
5073  IsContainerPartition(partitionEntry->PartitionType)) {
5074  continue;
5075  }
5076 
5077  //
5078  // Keep track of position on the disk for calls to IoSetPartitionInformation.
5079  //
5080 
5081  partitionOrdinal++;
5082 
5083  //
5084  // Check if this entry should be rewritten.
5085  //
5086 
5087  if (!partitionEntry->RewritePartition) {
5088  continue;
5089  }
5090 
5091  if (partitionEntry->PartitionNumber) {
5092 
5093  //
5094  // Partition is an exact match with an existing partition, but is
5095  // being written anyway.
5096  //
5097 
5098  continue;
5099  }
5100 
5101  //
5102  // Check first if existing device object is available by
5103  // walking partition extension list.
5104  //
5105 
5106  partitionNumber = 0;
5107  deviceExtension = physicalExtension;
5108  diskData = (PDISK_DATA)(deviceExtension + 1);
5109 
5110  do {
5111 
5112  //
5113  // Get next partition device extension from disk data.
5114  //
5115 
5116  deviceExtension = diskData->NextPartition;
5117 
5118  if (!deviceExtension) {
5119  break;
5120  }
5121 
5122  diskData = (PDISK_DATA)(deviceExtension + 1);
5123 
5124  //
5125  // A device object is free if the partition length is set to zero.
5126  //
5127 
5128  if (!deviceExtension->PartitionLength.QuadPart) {
5129  partitionNumber = diskData->PartitionNumber;
5130  break;
5131  }
5132 
5133  } while (TRUE);
5134 
5135  //
5136  // If partition number is still zero then a new device object
5137  // must be created.
5138  //
5139 
5140  if (partitionNumber == 0) {
5141 
5142  lastPartition++;
5143  partitionNumber = lastPartition;
5144 
5145  //
5146  // Get or create partition object and set up partition parameters.
5147  //
5148 
5149  sprintf(ntNameBuffer,
5150  "\\Device\\Harddisk%lu\\Partition%lu",
5151  physicalExtension->DeviceNumber,
5152  partitionNumber);
5153 
5154  RtlInitString(&ntNameString,
5155  ntNameBuffer);
5156 
5157  status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
5158  &ntNameString,
5159  TRUE);
5160 
5161  if (!NT_SUCCESS(status)) {
5162  continue;
5163  }
5164 
5165  DebugPrint((3,
5166  "UpdateDeviceObjects: Create device object %s\n",
5167  ntNameBuffer));
5168 
5169  //
5170  // This is a new name. Create the device object to represent it.
5171  //
5172 
5173  status = IoCreateDevice(PhysicalDisk->DriverObject,
5175  &ntUnicodeString,
5177  0,
5178  FALSE,
5179  &deviceObject);
5180 
5181  if (!NT_SUCCESS(status)) {
5182  DebugPrint((1,
5183  "UpdateDeviceObjects: Can't create device %s\n",
5184  ntNameBuffer));
5185  RtlFreeUnicodeString(&ntUnicodeString);
5186  continue;
5187  }
5188 
5189  //
5190  // Set up device object fields.
5191  //
5192 
5193  deviceObject->Flags |= DO_DIRECT_IO;
5194  deviceObject->StackSize = PhysicalDisk->StackSize;
5195 
5196  //
5197  // Set up device extension fields.
5198  //
5199 
5200  deviceExtension = deviceObject->DeviceExtension;
5201 
5202  //
5203  // Copy physical disk extension to partition extension.
5204  //
5205 
5206  RtlMoveMemory(deviceExtension,
5207  physicalExtension,
5208  sizeof(DEVICE_EXTENSION));
5209 
5210  //
5211  // Initialize the new S-List.
5212  //
5213 
5214  if (deviceExtension->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
5215  numberListElements = 30;
5216  } else {
5217  numberListElements = 8;
5218  }
5219 
5220  //
5221  // Build the lookaside list for srb's for this partition based on
5222  // whether the adapter and disk can do tagged queueing.
5223  //
5224 
5225  ScsiClassInitializeSrbLookasideList(deviceExtension,
5226  numberListElements);
5227 
5228  //
5229  // Allocate spinlock for zoning for split-request completion.
5230  //
5231 
5232  KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
5233 
5234  //
5235  // Write back partition number used in creating object name.
5236  //
5237 
5238  partitionEntry->PartitionNumber = partitionNumber;
5239 
5240  //
5241  // Clear flags initializing bit.
5242  //
5243 
5244  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
5245 
5246  //
5247  // Point back at device object.
5248  //
5249 
5250  deviceExtension->DeviceObject = deviceObject;
5251 
5252  RtlFreeUnicodeString(&ntUnicodeString);
5253 
5254  //
5255  // Link to end of partition chain using previous disk data.
5256  //
5257 
5258  diskData->NextPartition = deviceExtension;
5259 
5260  //
5261  // Get new disk data and zero next partition pointer.
5262  //
5263 
5264  diskData = (PDISK_DATA)(deviceExtension + 1);
5265  diskData->NextPartition = NULL;
5266 
5267  } else {
5268 
5269  //
5270  // Set pointer to disk data area that follows device extension.
5271  //
5272 
5273  diskData = (PDISK_DATA)(deviceExtension + 1);
5274 
5275  DebugPrint((1,
5276  "UpdateDeviceObjects: Used existing device object \\Device\\Harddisk%x\\Partition%x\n",
5277  physicalExtension->DeviceNumber,
5278  partitionNumber));
5279  }
5280 
5281  //
5282  // Update partition information in partition device extension.
5283  //
5284 
5285  diskData->PartitionNumber = partitionNumber;
5286  diskData->PartitionType = partitionEntry->PartitionType;
5287  diskData->BootIndicator = partitionEntry->BootIndicator;
5288  deviceExtension->StartingOffset = partitionEntry->StartingOffset;
5289  deviceExtension->PartitionLength = partitionEntry->PartitionLength;
5290  diskData->HiddenSectors = partitionEntry->HiddenSectors;
5291  diskData->PartitionOrdinal = partitionOrdinal;
5292 
5293  DebugPrint((1,
5294  "UpdateDeviceObjects: Ordinal %d is partition %d\n",
5295  diskData->PartitionOrdinal,
5296  diskData->PartitionNumber));
5297 
5298  //
5299  // Update partition number passed in to indicate the
5300  // device name for this partition.
5301  //
5302 
5303  partitionEntry->PartitionNumber = partitionNumber;
5304  }
5305 
5306 } // end UpdateDeviceObjects()
5307 
#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:1071
#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
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
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:1965
_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:5030
#define ENABLE_DISABLE_AUTOSAVE
Definition: ntdddisk.h:626
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
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369 u
#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:612
VOID NTAPI ScsiDiskProcessError(PDEVICE_OBJECT DeviceObject, PSCSI_REQUEST_BLOCK Srb, NTSTATUS *Status, BOOLEAN *Retry)
Definition: disk.c:4573
#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
#define DISABLE_SMART
Definition: ntdddisk.h:632
VOID NTAPI UpdateGeometry(IN PDEVICE_EXTENSION DeviceExtension)
Definition: disk.c:4076
ULONG NextInquiryDataOffset
Definition: scsi_port.h:118
UCHAR QueueAction
Definition: srb.h:249
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:3283
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:1505
PCLASS_READ_WRITE ClassReadWriteVerification
Definition: class2.h:87
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define MAXIMUM_FILENAME_LENGTH
Definition: env_spec_w32.h:41
#define ENABLE_SMART
Definition: ntdddisk.h:631
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 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:4739
#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:1963
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:567
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:4637
long LONG
Definition: pedump.c:60
#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:4845
smooth NULL
Definition: ftsmooth.c:416
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:467
#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
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@369::@378 DeviceSpecificData
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:613
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
switch(r->id)
Definition: btrfs.c:2691
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:633
ULONG InquiryDataOffset
Definition: scsi_port.h:98
#define READ_ATTRIBUTE_BUFFER_SIZE
Definition: ntdddisk.h:611
#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:628
#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:4616
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:3419
#define ID_CMD
Definition: helper.h:20
#define READ_THRESHOLDS
Definition: ntdddisk.h:625
BOOLEAN DriveNotReady
Definition: disk.c:111
#define SAVE_ATTRIBUTE_VALUES
Definition: ntdddisk.h:627
ULONG NTAPI ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject, IN PCHAR ModeSenseBuffer, IN ULONG Length, IN UCHAR PageMode)
Definition: class2.c:3513
ULONG Signature
Definition: disk.c:52
IDEREGS irDriveRegs
Definition: helper.h:32
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:393
char CCHAR
Definition: typedefs.h:50
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define IOCTL_DISK_INTERNAL_CLEAR_VERIFY
Definition: ntdddisk.h:106
BOOLEAN DisableSynchronousTransfers
Definition: disk.c:138
#define MODE_DSP_FUA_SUPPORTED
Definition: cdrw_hw.h:2522
UCHAR Function
Definition: srb.h:242
#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
Definition: cdrw_hw.h:1466
#define IOCTL_SCSI_MINIPORT_RETURN_STATUS
Definition: cdrw_hw.h:1463
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:271
UCHAR bCommandReg
Definition: helper.h:15
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
#define for
Definition: utility.h:88
BOOLEAN DisableDisconnects
Definition: disk.c:139
PCLASS_CREATE_CLOSE ClassCreateClose
Definition: class2.h:92
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define IOCTL_SCSI_MINIPORT_ENABLE_SMART
Definition: cdrw_hw.h:1461
USHORT Length
Definition: srb.h:241
LARGE_INTEGER PartitionLength
Definition: imports.h:222
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
#define READ_ATTRIBUTES
Definition: ntdddisk.h:624
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS NTAPI ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: class2.c:1806
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define SCSIOP_VERIFY
Definition: cdrw_hw.h:912
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
std::wstring STRING
Definition: fontsub.cpp:33
#define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES
Definition: cdrw_hw.h:1465
BOOLEAN RewritePartition
Definition: ntdddisk.h:400
UCHAR BlockLength[3]
Definition: cdrw_hw.h:2531
BOOLEAN NTAPI EnumerateBusKey(IN PDEVICE_EXTENSION DeviceExtension, HANDLE BusKey, PULONG DiskNumber)
Definition: disk.c:3748
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:388
LARGE_INTEGER StartingOffset
Definition: imports.h:221
unsigned char UCHAR
Definition: xmlstorage.h:181
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:88
#define PARTITION0_LIST_SIZE
Definition: disk.c:167
#define NUMBER_OF_BAD_CONTROLLERS
Definition: disk.c:161
static const WCHAR L[]
Definition: oid.c:1250
BOOLEAN NTAPI ScsiDiskDeviceVerification(IN PINQUIRYDATA InquiryData)
Definition: disk.c:408
_In_ PVOID _In_ PCLASS_INIT_DATA InitializationData
Definition: classpnp.h:680
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
BOOLEAN NTAPI FindScsiDisks(IN PDRIVER_OBJECT DriveObject, IN PUNICODE_STRING RegistryPath, IN PCLASS_INIT_DATA InitializationData, IN PDEVICE_OBJECT PortDeviceObject, IN ULONG PortNumber)
Definition: disk.c:443