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