ReactOS  0.4.15-dev-4570-g4f8bbd1
geometry.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4 
5 Module Name:
6 
7  geometry.c
8 
9 Abstract:
10 
11  SCSI disk class driver - this module contains all the code for generating
12  disk geometries.
13 
14 Environment:
15 
16  kernel mode only
17 
18 Notes:
19 
20 Revision History:
21 
22 --*/
23 
24 
25 #include "disk.h"
26 #include "ntddstor.h"
27 
28 #ifdef DEBUG_USE_WPP
29 #include "geometry.tmh"
30 #endif
31 
32 #if defined(_X86_) || defined(_AMD64_)
33 
34 DISK_GEOMETRY_SOURCE
35 DiskUpdateGeometry(
36  IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
37  );
38 
40 DiskUpdateRemovableGeometry (
42  );
43 
44 VOID
45 DiskScanBusDetectInfo(
47  IN HANDLE BusKey
48  );
49 
51 DiskSaveBusDetectInfo(
53  IN HANDLE TargetKey,
54  IN ULONG DiskNumber
55  );
56 
58 DiskSaveGeometryDetectInfo(
60  IN HANDLE HardwareKey
61  );
62 
64 DiskGetPortGeometry(
66  OUT PDISK_GEOMETRY Geometry
67  );
68 
69 typedef struct _DISK_DETECT_INFO {
71  ULONG Style;
73  ULONG MbrCheckSum;
75  CM_INT13_DRIVE_PARAMETER DriveParameters;
76 } DISK_DETECT_INFO, *PDISK_DETECT_INFO;
77 
78 //
79 // Information about the disk geometries collected and saved into the registry
80 // by NTDETECT.COM or the system firmware.
81 //
82 
83 PDISK_DETECT_INFO DetectInfoList = NULL;
84 ULONG DetectInfoCount = 0;
85 LONG DetectInfoUsedCount = 0;
86 
87 #define GET_STARTING_SECTOR(p) ( \
88  (ULONG) (p->StartingSectorLsb0) + \
89  (ULONG) (p->StartingSectorLsb1 << 8 ) + \
90  (ULONG) (p->StartingSectorMsb0 << 16) + \
91  (ULONG) (p->StartingSectorMsb1 << 24) )
92 
93 #define GET_ENDING_S_OF_CHS(p) ( \
94  (UCHAR) (p->EndingCylinderLsb & 0x3F) )
95 
96 //
97 // Definitions from hal.h
98 //
99 
100 //
101 // Boot record disk partition table entry structure format
102 //
103 
104 typedef struct _PARTITION_DESCRIPTOR
105 {
122 
124 
125 //
126 // Number of partition table entries
127 //
128 
129 #define NUM_PARTITION_TABLE_ENTRIES 4
130 
131 //
132 // Partition table record and boot signature offsets in 16-bit words
133 //
134 
135 #define PARTITION_TABLE_OFFSET ( 0x1be / 2)
136 #define BOOT_SIGNATURE_OFFSET ((0x200 / 2) - 1)
137 
138 //
139 // Boot record signature value
140 //
141 
142 #define BOOT_RECORD_SIGNATURE (0xaa55)
143 
144 
145 #ifdef ALLOC_PRAGMA
146 #pragma alloc_text(INIT, DiskSaveDetectInfo)
147 #pragma alloc_text(INIT, DiskScanBusDetectInfo)
148 #pragma alloc_text(INIT, DiskSaveBusDetectInfo)
149 #pragma alloc_text(INIT, DiskSaveGeometryDetectInfo)
150 
151 #pragma alloc_text(PAGE, DiskUpdateGeometry)
152 #pragma alloc_text(PAGE, DiskUpdateRemovableGeometry)
153 #pragma alloc_text(PAGE, DiskGetPortGeometry)
154 #pragma alloc_text(PAGE, DiskIsNT4Geometry)
155 #pragma alloc_text(PAGE, DiskGetDetectInfo)
156 #pragma alloc_text(PAGE, DiskReadSignature)
157 #endif
158 
159 
160 NTSTATUS
161 DiskSaveDetectInfo(
163  )
164 
165 /*++
166 
167 Routine Description:
168 
169  This routine saves away the firmware information about the disks which has
170  been saved in the registry. It generates a list (DetectInfoList) which
171  contains the disk geometries, signatures & checksums of all drives which
172  were examined by NtDetect. This list is later used to assign geometries
173  to disks as they are initialized.
174 
175 Arguments:
176 
177  DriverObject - the driver being initialized. This is used to get to the
178  hardware database.
179 
180 Return Value:
181 
182  status.
183 
184 --*/
185 
186 {
187  OBJECT_ATTRIBUTES objectAttributes = {0};
188  HANDLE hardwareKey;
189 
190  UNICODE_STRING unicodeString;
191  HANDLE busKey;
192 
194 
195  PAGED_CODE();
196 
198  &objectAttributes,
199  DriverObject->HardwareDatabase,
201  NULL,
202  NULL);
203 
204  //
205  // Create the hardware base key.
206  //
207 
208  status = ZwOpenKey(&hardwareKey, KEY_READ, &objectAttributes);
209 
210  if(!NT_SUCCESS(status)) {
211  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveDetectInfo: Cannot open hardware data. "
212  "Name: %wZ\n",
213  DriverObject->HardwareDatabase));
214  return status;
215  }
216 
217  status = DiskSaveGeometryDetectInfo(DriverObject, hardwareKey);
218 
219  if(!NT_SUCCESS(status)) {
220  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveDetectInfo: Can't query configuration data "
221  "(%#08lx)\n",
222  status));
223  ZwClose(hardwareKey);
224  return status;
225  }
226 
227  //
228  // Open EISA bus key.
229  //
230 
231  RtlInitUnicodeString(&unicodeString, L"EisaAdapter");
232  InitializeObjectAttributes(&objectAttributes,
233  &unicodeString,
235  hardwareKey,
236  NULL);
237 
238  status = ZwOpenKey(&busKey,
239  KEY_READ,
240  &objectAttributes);
241 
242  if(NT_SUCCESS(status)) {
243  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskSaveDetectInfo: Opened EisaAdapter key\n"));
244  DiskScanBusDetectInfo(DriverObject, busKey);
245  ZwClose(busKey);
246  }
247 
248  //
249  // Open MultiFunction bus key.
250  //
251 
252  RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter");
253  InitializeObjectAttributes(&objectAttributes,
254  &unicodeString,
256  hardwareKey,
257  NULL);
258 
259  status = ZwOpenKey(&busKey,
260  KEY_READ,
261  &objectAttributes);
262 
263  if(NT_SUCCESS(status)) {
264  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskSaveDetectInfo: Opened MultifunctionAdapter key\n"));
265  DiskScanBusDetectInfo(DriverObject, busKey);
266  ZwClose(busKey);
267  }
268 
269  ZwClose(hardwareKey);
270 
271  return STATUS_SUCCESS;
272 }
273 
274 
275 VOID
276 DiskCleanupDetectInfo(
278  )
279 /*++
280 
281 Routine Description:
282 
283  This routine will cleanup the data structure built by DiskSaveDetectInfo.
284 
285 Arguments:
286 
287  DriverObject - a pointer to the kernel object for this driver.
288 
289 Return Value:
290 
291  none
292 
293 --*/
294 
295 {
297  FREE_POOL(DetectInfoList);
298  return;
299 }
300 
301 
302 NTSTATUS
303 DiskSaveGeometryDetectInfo(
305  IN HANDLE HardwareKey
306  )
307 {
308  UNICODE_STRING unicodeString;
310  ULONG length;
311 
312  PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
313  PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
314 
315  PCM_INT13_DRIVE_PARAMETER driveParameters;
316  ULONG numberOfDrives;
317 
318  ULONG i;
319 
321 
322  PAGED_CODE();
324 
325  //
326  // Get disk BIOS geometry information.
327  //
328 
329  RtlInitUnicodeString(&unicodeString, L"Configuration Data");
330 
334 
335  if(keyData == NULL) {
336  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveGeometryDetectInfo: Can't allocate config "
337  "data buffer\n"));
339  }
340 
341  status = ZwQueryValueKey(HardwareKey,
342  &unicodeString,
344  keyData,
346  &length);
347 
348  if(!NT_SUCCESS(status)) {
349  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveGeometryDetectInfo: Can't query configuration "
350  "data (%#08lx)\n",
351  status));
352  FREE_POOL(keyData);
353  return status;
354  }
355 
356  //
357  // Extract the resource list out of the key data.
358  //
359 
360  fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
361  (((PUCHAR) keyData) + keyData->DataOffset);
362  partialDescriptor =
363  fullDescriptor->PartialResourceList.PartialDescriptors;
364  length = partialDescriptor->u.DeviceSpecificData.DataSize;
365 
366  if((keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) ||
367  (fullDescriptor->PartialResourceList.Count == 0) ||
368  (partialDescriptor->Type != CmResourceTypeDeviceSpecific) ||
369  (length < sizeof(ULONG))) {
370 
371  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveGeometryDetectInfo: BIOS header data too small "
372  "or invalid\n"));
373  FREE_POOL(keyData);
375  }
376 
377  //
378  // Point to the BIOS data. THe BIOS data is located after the first
379  // partial Resource list which should be device specific data.
380  //
381 
382  {
383  PUCHAR buffer = (PUCHAR) keyData;
384  buffer += keyData->DataOffset;
386  driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer;
387  }
388 
389  numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
390 
391  //
392  // Allocate our detect info list now that we know how many entries there
393  // are going to be. No other routine allocates detect info and this is
394  // done out of DriverEntry so we don't need to synchronize it's creation.
395  //
396 
397  length = sizeof(DISK_DETECT_INFO) * numberOfDrives;
398  DetectInfoList = ExAllocatePoolWithTag(PagedPool,
399  length,
401 
402  if(DetectInfoList == NULL) {
403  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveGeometryDetectInfo: Couldn't allocate %x bytes "
404  "for DetectInfoList\n",
405  length));
406 
407  FREE_POOL(keyData);
409  }
410 
411  DetectInfoCount = numberOfDrives;
412 
413  RtlZeroMemory(DetectInfoList, length);
414 
415  //
416  // Copy the information out of the key data and into the list we've
417  // allocated.
418  //
419 
420  for(i = 0; i < numberOfDrives; i++) {
421 #ifdef _MSC_VER
422 #pragma warning(suppress: 6386) // PREFast bug means it doesn't correctly remember the size of DetectInfoList
423 #endif
424  DetectInfoList[i].DriveParameters = driveParameters[i];
425  }
426 
427  FREE_POOL(keyData);
428  return STATUS_SUCCESS;
429 }
430 
431 
432 VOID
433 DiskScanBusDetectInfo(
435  IN HANDLE BusKey
436  )
437 /*++
438 
439 Routine Description:
440 
441  The routine queries the registry to determine which disks are visible to
442  the BIOS. If a disk is visable to the BIOS then the geometry information
443  is updated with the disk's signature and MBR checksum.
444 
445 Arguments:
446 
447  DriverObject - the object for this driver.
448  BusKey - handle to the bus key to be enumerated.
449 
450 Return Value:
451 
452  status
453 
454 --*/
455 {
456  ULONG busNumber;
457 
459 
460  for(busNumber = 0; ; busNumber++) {
461 
462  WCHAR buffer[32] = { 0 };
463  UNICODE_STRING unicodeString;
464 
465  OBJECT_ATTRIBUTES objectAttributes = {0};
466 
467  HANDLE spareKey;
468  HANDLE adapterKey;
469 
470  ULONG adapterNumber;
471 
472  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Scanning bus %d\n", busNumber));
473 
474  //
475  // Open controller name key.
476  //
477 
478  status = RtlStringCchPrintfW(buffer, sizeof(buffer) / sizeof(buffer[0]) - 1, L"%d", busNumber);
479  if (!NT_SUCCESS(status)) {
480  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Format symbolic link failed with error: 0x%X\n", status));
481  break;
482  }
483 
484  RtlInitUnicodeString(&unicodeString, buffer);
485 
486  InitializeObjectAttributes(&objectAttributes,
487  &unicodeString,
489  BusKey,
490  NULL);
491 
492  status = ZwOpenKey(&spareKey, KEY_READ, &objectAttributes);
493 
494  if(!NT_SUCCESS(status)) {
495  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Error %#08lx opening bus "
496  "key %#x\n",
497  status, busNumber));
498  break;
499  }
500 
501  //
502  // Open up a controller ordinal key.
503  //
504 
505  RtlInitUnicodeString(&unicodeString, L"DiskController");
506  InitializeObjectAttributes(&objectAttributes,
507  &unicodeString,
509  spareKey,
510  NULL);
511 
512  status = ZwOpenKey(&adapterKey, KEY_READ, &objectAttributes);
513  ZwClose(spareKey);
514 
515  if(!NT_SUCCESS(status)) {
516  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Error %#08lx opening "
517  "DiskController key\n",
518  status));
519  continue;
520  }
521 
522  for(adapterNumber = 0; ; adapterNumber++) {
523 
524  HANDLE diskKey;
525  ULONG diskNumber;
526 
527  //
528  // Open disk key.
529  //
530 
531  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Scanning disk key "
532  "%d\\DiskController\\%d\\DiskPeripheral\n",
533  busNumber, adapterNumber));
534 
535  status = RtlStringCchPrintfW(buffer, sizeof(buffer) / sizeof(buffer[0]) - 1, L"%d\\DiskPeripheral", adapterNumber);
536  if (!NT_SUCCESS(status)) {
537  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Format symbolic link failed with error: 0x%X\n", status));
538  break;
539  }
540 
541  RtlInitUnicodeString(&unicodeString, buffer);
542 
543  InitializeObjectAttributes(&objectAttributes,
544  &unicodeString,
546  adapterKey,
547  NULL);
548 
549  status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
550 
551  if(!NT_SUCCESS(status)) {
552  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Error %#08lx opening "
553  "disk key\n",
554  status));
555  break;
556  }
557 
558  for(diskNumber = 0; ; diskNumber++) {
559 
560  HANDLE targetKey;
561 
562  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Scanning target key "
563  "%d\\DiskController\\%d\\DiskPeripheral\\%d\n",
564  busNumber, adapterNumber, diskNumber));
565 
566  status = RtlStringCchPrintfW(buffer, sizeof(buffer) / sizeof(buffer[0]) - 1, L"%d", diskNumber);
567  if (!NT_SUCCESS(status)) {
568  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Format symbolic link failed with error: 0x%X\n", status));
569  break;
570  }
571 
572  RtlInitUnicodeString(&unicodeString, buffer);
573 
574  InitializeObjectAttributes(&objectAttributes,
575  &unicodeString,
577  diskKey,
578  NULL);
579 
580  status = ZwOpenKey(&targetKey, KEY_READ, &objectAttributes);
581 
582  if(!NT_SUCCESS(status)) {
583  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskScanBusDetectInfo: Error %#08lx "
584  "opening target key\n",
585  status));
586  break;
587  }
588 
589  DiskSaveBusDetectInfo(DriverObject, targetKey, diskNumber);
590 
591  ZwClose(targetKey);
592  }
593 
594  ZwClose(diskKey);
595  }
596 
597  ZwClose(adapterKey);
598  }
599 
600  return;
601 }
602 
603 
604 NTSTATUS
605 DiskSaveBusDetectInfo(
607  IN HANDLE TargetKey,
608  IN ULONG DiskNumber
609  )
610 /*++
611 
612 Routine Description:
613 
614  This routine will transfer the firmware/ntdetect reported information
615  in the specified target key into the appropriate entry in the
616  DetectInfoList.
617 
618 Arguments:
619 
620  DriverObject - the object for this driver.
621 
622  TargetKey - the key for the disk being saved.
623 
624  DiskNumber - the ordinal of the entry in the DiskPeripheral tree for this
625  entry
626 
627 Return Value:
628 
629  status
630 
631 --*/
632 {
633  PDISK_DETECT_INFO diskInfo;
634 
635  UNICODE_STRING unicodeString;
636 
638  ULONG length;
639 
641 
642  PAGED_CODE();
644 
645  if (DiskNumber >= DetectInfoCount)
646  {
647  return STATUS_UNSUCCESSFUL;
648  }
649 
650  diskInfo = &(DetectInfoList[DiskNumber]);
651 
652  if(diskInfo->Initialized) {
653 
654  NT_ASSERT(FALSE);
655  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: disk entry %#x already has a "
656  "signature of %#08lx and mbr checksum of %#08lx\n",
657  DiskNumber,
658  diskInfo->Signature,
659  diskInfo->MbrCheckSum));
660  return STATUS_UNSUCCESSFUL;
661  }
662 
663  RtlInitUnicodeString(&unicodeString, L"Identifier");
664 
668 
669  if(keyData == NULL) {
670  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: Couldn't allocate space for "
671  "registry data\n"));
673  }
674 
675  //
676  // Get disk peripheral identifier.
677  //
678 
679  status = ZwQueryValueKey(TargetKey,
680  &unicodeString,
682  keyData,
684  &length);
685 
686  if(!NT_SUCCESS(status)) {
687  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: Error %#08lx getting "
688  "Identifier\n",
689  status));
690  FREE_POOL(keyData);
691  return status;
692 
693  } else if (keyData->DataLength < 9*sizeof(WCHAR)) {
694 
695  //
696  // the data is too short to use (we subtract 9 chars in normal path)
697  //
698  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: Saved data was invalid, "
699  "not enough data in registry!\n"));
700  FREE_POOL(keyData);
701  return STATUS_UNSUCCESSFUL;
702 
703  } else {
704 
705  UNICODE_STRING identifier;
706  ULONG value;
707 
708  //
709  // Complete unicode string.
710  //
711 
712  identifier.Buffer = (PWSTR) ((PUCHAR)keyData + keyData->DataOffset);
713  identifier.Length = (USHORT) keyData->DataLength;
714  identifier.MaximumLength = (USHORT) keyData->DataLength;
715 
716  //
717  // Get the first value out of the identifier - this will be the MBR
718  // checksum.
719  //
720 
721  status = RtlUnicodeStringToInteger(&identifier, 16, &value);
722 
723  if(!NT_SUCCESS(status)) {
724  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: Error %#08lx converting "
725  "identifier %wZ into MBR xsum\n",
726  status,
727  &identifier));
728  FREE_POOL(keyData);
729  return status;
730  }
731 
732  diskInfo->MbrCheckSum = value;
733 
734  //
735  // Shift the string over to get the disk signature
736  //
737 
738  identifier.Buffer += 9;
739  identifier.Length -= 9 * sizeof(WCHAR);
740  identifier.MaximumLength -= 9 * sizeof(WCHAR);
741 
742  status = RtlUnicodeStringToInteger(&identifier, 16, &value);
743 
744  if(!NT_SUCCESS(status)) {
745  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskSaveBusDetectInfo: Error %#08lx converting "
746  "identifier %wZ into disk signature\n",
747  status,
748  &identifier));
749  value = 0;
750  }
751 
752  diskInfo->Signature = value;
753  }
754 
755  //
756  // Here is where we would save away the extended int13 data.
757  //
758 
759  //
760  // Mark this entry as initialized so we can make sure not to do it again.
761  //
762 
763  diskInfo->Initialized = TRUE;
764 
765  FREE_POOL(keyData);
766 
767  return STATUS_SUCCESS;
768 }
769 
770 
771 DISK_GEOMETRY_SOURCE
772 DiskUpdateGeometry(
774  )
775 /*++
776 
777 Routine Description:
778 
779  This routine checks the DetectInfoList saved away during disk driver init
780  to see if any geometry information was reported for this drive. If the
781  geometry data exists (determined by matching non-zero signatures or
782  non-zero MBR checksums) then it will be saved in the RealGeometry member
783  of the disk data block.
784 
785  ClassReadDriveCapacity MUST be called after calling this routine to update
786  the cylinder count based on the size of the disk and the presence of any
787  disk management software.
788 
789 Arguments:
790 
791  DeviceExtension - Supplies a pointer to the device information for disk.
792 
793 Return Value:
794 
795  Inidicates whether the "RealGeometry" in the data block is now valid.
796 
797 --*/
798 
799 {
800  PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
801 
802  ULONG i;
803  PDISK_DETECT_INFO diskInfo = NULL;
804 
805  BOOLEAN found = FALSE;
806 
808 
809  PAGED_CODE();
810 
811 
812  NT_ASSERT((FdoExtension->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0);
813 
814  //
815  // If we've already set a non-default geometry for this drive then there's
816  // no need to try and update again.
817  //
818 
819  if(diskData->GeometrySource != DiskGeometryUnknown) {
820  return diskData->GeometrySource;
821  }
822 
823  //
824  // Scan through the saved detect info to see if we can find a match
825  // for this device.
826  //
827 
828  for(i = 0; i < DetectInfoCount; i++) {
829 
830  NT_ASSERT(DetectInfoList != NULL);
831 
832  diskInfo = &(DetectInfoList[i]);
833 
834  if((diskData->Mbr.Signature != 0) &&
835  (diskData->Mbr.Signature == diskInfo->Signature)) {
836  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: found match for signature "
837  "%#08lx\n",
838  diskData->Mbr.Signature));
839  found = TRUE;
840  break;
841  } else if((diskData->Mbr.Signature == 0) &&
842  (diskData->Mbr.MbrCheckSum != 0) &&
843  (diskData->Mbr.MbrCheckSum == diskInfo->MbrCheckSum)) {
844  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: found match for xsum %#08lx\n",
845  diskData->Mbr.MbrCheckSum));
846  found = TRUE;
847  break;
848  }
849  }
850 
851  if(found) {
852 
853  ULONG cylinders;
854  ULONG sectorsPerTrack;
855  ULONG tracksPerCylinder;
856 
857  ULONG length;
858 
859  //
860  // Point to the array of drive parameters.
861  //
862 
863  cylinders = diskInfo->DriveParameters.MaxCylinders + 1;
864  sectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
865  tracksPerCylinder = diskInfo->DriveParameters.MaxHeads + 1;
866 
867  //
868  // Since the BIOS may not report the full drive, recalculate the drive
869  // size based on the volume size and the BIOS values for tracks per
870  // cylinder and sectors per track..
871  //
872 
873  length = tracksPerCylinder * sectorsPerTrack;
874 
875  if (length == 0) {
876 
877  //
878  // The BIOS information is bogus.
879  //
880 
881  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: H (%d) or S(%d) is zero\n",
882  tracksPerCylinder, sectorsPerTrack));
883  return DiskGeometryUnknown;
884  }
885 
886  //
887  // since we are copying the structure RealGeometry here, we should
888  // really initialize all the fields, especially since a zero'd
889  // BytesPerSector field would cause a trap in xHalReadPartitionTable()
890  //
891 
892  diskData->RealGeometry = FdoExtension->DiskGeometry;
893 
894  //
895  // Save the geometry information away in the disk data block and
896  // set the bit indicating that we found a valid one.
897  //
898 
899  diskData->RealGeometry.SectorsPerTrack = sectorsPerTrack;
900  diskData->RealGeometry.TracksPerCylinder = tracksPerCylinder;
901  diskData->RealGeometry.Cylinders.QuadPart = (LONGLONG)cylinders;
902 
903  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: BIOS spt %#x, #heads %#x, "
904  "#cylinders %#x\n",
905  sectorsPerTrack, tracksPerCylinder, cylinders));
906 
907  diskData->GeometrySource = DiskGeometryFromBios;
908  diskInfo->Device = FdoExtension->DeviceObject;
909 
910  //
911  // Increment the count of used geometry entries.
912  //
913 
914  InterlockedIncrement(&DetectInfoUsedCount);
915 
916  } else {
917 
918  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: no match found for signature %#08lx\n", diskData->Mbr.Signature));
919  }
920 
921  if(diskData->GeometrySource == DiskGeometryUnknown) {
922 
923  //
924  // We couldn't find a geometry from the BIOS. Check with the port
925  // driver and see if it can provide one.
926  //
927 
928  status = DiskGetPortGeometry(FdoExtension, &(diskData->RealGeometry));
929 
930  if(NT_SUCCESS(status)) {
931 
932  //
933  // Check the geometry to make sure it's valid.
934  //
935 
936  if((diskData->RealGeometry.TracksPerCylinder *
937  diskData->RealGeometry.SectorsPerTrack) != 0) {
938 
939  diskData->GeometrySource = DiskGeometryFromPort;
940  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskUpdateGeometry: using Port geometry for disk %#p\n", FdoExtension));
941 
942  if (diskData->RealGeometry.BytesPerSector == 0) {
943 
944  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskDriverReinit: Port driver failed to "
945  "set BytesPerSector in the RealGeometry\n"));
946  diskData->RealGeometry.BytesPerSector =
947  FdoExtension->DiskGeometry.BytesPerSector;
948  if (diskData->RealGeometry.BytesPerSector == 0) {
949  NT_ASSERT(!"BytesPerSector is still zero!");
950  }
951 
952  }
953  }
954  }
955  }
956 
957  //
958  // If we came up with a "real" geometry for this drive then set it in the
959  // device extension.
960  //
961 
962  if (diskData->GeometrySource != DiskGeometryUnknown) {
963 
964  FdoExtension->DiskGeometry = diskData->RealGeometry;
965  }
966 
967  return diskData->GeometrySource;
968 }
969 
970 
971 NTSTATUS
972 DiskUpdateRemovableGeometry (
974  )
975 
976 /*++
977 
978 Routine Description:
979 
980  This routine updates the geometry of the disk. It will query the port
981  driver to see if it can provide any geometry info. If not it will use
982  the current head & sector count.
983 
984  Based on these values & the capacity of the drive as reported by
985  ClassReadDriveCapacity it will determine a new cylinder count for the
986  device.
987 
988 Arguments:
989 
990  Fdo - Supplies the functional device object whos size needs to be updated.
991 
992 Return Value:
993 
994  Returns the status of the opertion.
995 
996 --*/
997 {
998  PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
999  PDISK_DATA diskData = commonExtension->DriverData;
1000  PDISK_GEOMETRY geometry = &(diskData->RealGeometry);
1001 
1002  NTSTATUS status;
1003 
1004  PAGED_CODE();
1005 
1006  if (FdoExtension->DeviceDescriptor) {
1007  NT_ASSERT(FdoExtension->DeviceDescriptor->RemovableMedia);
1008  }
1009  NT_ASSERT(TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
1011 
1012  //
1013  // Attempt to determine the disk geometry. First we'll check with the
1014  // port driver to see what it suggests for a value.
1015  //
1016 
1017  status = DiskGetPortGeometry(FdoExtension, geometry);
1018 
1019  if(NT_SUCCESS(status) &&
1020  ((geometry->TracksPerCylinder * geometry->SectorsPerTrack) != 0)) {
1021 
1022  FdoExtension->DiskGeometry = (*geometry);
1023  }
1024 
1025  return status;
1026 }
1027 
1028 
1029 NTSTATUS
1030 DiskGetPortGeometry(
1032  OUT PDISK_GEOMETRY Geometry
1033  )
1034 /*++
1035 
1036 Routine Description:
1037 
1038  This routine will query the port driver for disk geometry. Some port
1039  drivers (in particular IDEPORT) may be able to provide geometry for the
1040  device.
1041 
1042 Arguments:
1043 
1044  FdoExtension - the device object for the disk.
1045 
1046  Geometry - a structure to save the geometry information into (if any is
1047  available)
1048 
1049 Return Value:
1050 
1051  STATUS_SUCCESS if geometry information can be provided or
1052  error status indicating why it can't.
1053 
1054 --*/
1055 {
1056  PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
1057  PIRP irp;
1058  PIO_STACK_LOCATION irpStack;
1059  KEVENT event;
1060 
1061  NTSTATUS status;
1062 
1063  PAGED_CODE();
1064 
1065  //
1066  // Build an irp to send IOCTL_DISK_GET_DRIVE_GEOMETRY to the lower driver.
1067  //
1068 
1069  irp = IoAllocateIrp(commonExtension->LowerDeviceObject->StackSize, FALSE);
1070 
1071  if(irp == NULL) {
1073  }
1074 
1075  irpStack = IoGetNextIrpStackLocation(irp);
1076 
1078 
1079  irpStack->Parameters.DeviceIoControl.IoControlCode =
1081  irpStack->Parameters.DeviceIoControl.OutputBufferLength =
1082  sizeof(DISK_GEOMETRY);
1083 
1084  irp->AssociatedIrp.SystemBuffer = Geometry;
1085 
1087 
1090  &event,
1091  TRUE,
1092  TRUE,
1093  TRUE);
1094 
1095  status = IoCallDriver(commonExtension->LowerDeviceObject, irp);
1096  if (status == STATUS_PENDING) {
1098  status = irp->IoStatus.Status;
1099  }
1100 
1101  IoFreeIrp(irp);
1102 
1103  return status;
1104 }
1105 
1106 
1107 BOOLEAN
1108 DiskIsNT4Geometry(
1110  )
1111 
1112 /*++
1113 
1114 Routine Description:
1115 
1116  The default geometry that was used in partitioning disks under Windows NT 4.0 was
1117 
1118  Sectors per Track = 0x20 = 32
1119  Tracks per Cylinder = 0x40 = 64
1120 
1121  This was changed in Windows 2000 to
1122 
1123  Sectors per Track = 0x3F = 63
1124  Tracks per Cylinder = 0xFF = 255
1125 
1126  If neither the BIOS nor the port driver can report the correct geometry, we will
1127  default to the new numbers on such disks. Now LVM uses the geometry when creating
1128  logical volumes and dynamic disks. So reporting an incorrect geometry will cause
1129  the entire extended partition / dynamic disk to be destroyed
1130 
1131  In this routine, we will look at the Master Boot Record. In 90% of the cases, the
1132  first entry corresponds to a partition that starts on the first track. If this is
1133  so, we shall retrieve the logical block address associated with it and calculate
1134  the correct geometry. Now, all partitions start on a cylinder boundary. So, for
1135  the remaining 10% we will look at the ending CHS number to determine the geometry
1136 
1137 --*/
1138 
1139 {
1140  PUSHORT readBuffer = NULL;
1141  BOOLEAN bFoundNT4 = FALSE;
1142 
1143  PAGED_CODE();
1144 
1145  readBuffer = ExAllocatePoolWithTag(NonPagedPoolNx, FdoExtension->DiskGeometry.BytesPerSector, DISK_TAG_UPDATE_GEOM);
1146 
1147  if (readBuffer)
1148  {
1149  KEVENT event;
1150  LARGE_INTEGER diskOffset;
1151  IO_STATUS_BLOCK ioStatus = { 0 };
1152  PIRP irp;
1153 
1155 
1156  //
1157  // Read the Master Boot Record at disk offset 0
1158  //
1159 
1160  diskOffset.QuadPart = 0;
1161 
1162  irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, FdoExtension->DeviceObject, readBuffer, FdoExtension->DiskGeometry.BytesPerSector, &diskOffset, &event, &ioStatus);
1163 
1164  if (irp)
1165  {
1167  NTSTATUS status;
1168 
1169  irpSp->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1170 
1171  status = IoCallDriver(FdoExtension->DeviceObject, irp);
1172 
1173  if (status == STATUS_PENDING)
1174  {
1176  status = ioStatus.Status;
1177  }
1178 
1179  if (NT_SUCCESS(status))
1180  {
1181  //
1182  // Match the boot record signature
1183  //
1184 
1185  if (readBuffer[BOOT_SIGNATURE_OFFSET] == BOOT_RECORD_SIGNATURE)
1186  {
1187  PPARTITION_DESCRIPTOR partitionTableEntry = (PPARTITION_DESCRIPTOR)&readBuffer[PARTITION_TABLE_OFFSET];
1188  ULONG uCount = 0;
1189 
1190  //
1191  // Walk the entries looking for a clue as to what the geometry might be
1192  //
1193 
1194  for (uCount = 0; uCount < NUM_PARTITION_TABLE_ENTRIES; uCount++)
1195  {
1196  //
1197  // We are only concerned if there might be a logical volume or if this disk is part of a dynamic set
1198  //
1199 
1200  if (IsContainerPartition(partitionTableEntry->PartitionType) || partitionTableEntry->PartitionType == PARTITION_LDM)
1201  {
1202  //
1203  // In 90% of the cases, the first entry corresponds to a partition that starts on the first track
1204  //
1205 
1206  if (partitionTableEntry->StartingTrack == 1 && GET_STARTING_SECTOR(partitionTableEntry) == 0x20)
1207  {
1208  bFoundNT4 = TRUE;
1209  break;
1210  }
1211 
1212  //
1213  // In almost every case, the ending CHS number is on a cylinder boundary
1214  //
1215 
1216  if (partitionTableEntry->EndingTrack == 0x3F && GET_ENDING_S_OF_CHS(partitionTableEntry) == 0x20)
1217  {
1218  bFoundNT4 = TRUE;
1219  break;
1220  }
1221  }
1222 
1223  partitionTableEntry++;
1224  }
1225  }
1226  else
1227  {
1228  //
1229  // The Master Boot Record is invalid
1230  //
1231  }
1232  }
1233  }
1234 
1235  FREE_POOL(readBuffer);
1236  }
1237 
1238  return bFoundNT4;
1239 }
1240 
1241 
1242 NTSTATUS
1245  )
1246 /*++
1247 
1248 Routine Description:
1249 
1250  This routine is used by disk.sys as a wrapper for the classpnp API
1251  ClassReadDriveCapacity. It will perform some additional operations to
1252  attempt to determine drive geometry before it calls the classpnp version
1253  of the routine.
1254 
1255  For fixed disks this involves calling DiskUpdateGeometry which will check
1256  various sources (the BIOS, the port driver) for geometry information.
1257 
1258 Arguments:
1259 
1260  Fdo - a pointer to the device object to be checked.
1261 
1262 Return Value:
1263 
1264  status of ClassReadDriveCapacity.
1265 
1266 --*/
1267 
1268 {
1269  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
1270  NTSTATUS status;
1271 
1272  if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
1273  DiskUpdateRemovableGeometry(fdoExtension);
1274  } else {
1275  DiskUpdateGeometry(fdoExtension);
1276  }
1277 
1279 
1280  return status;
1281 }
1282 
1283 
1284 VOID
1285 DiskDriverReinitialization(
1287  IN PVOID Nothing,
1288  IN ULONG Count
1289  )
1290 /*++
1291 
1292 Routine Description:
1293 
1294  This routine will scan through the current list of disks and attempt to
1295  match them to any remaining geometry information. This will only be done
1296  on the first call to the routine.
1297 
1298  Note: This routine assumes that the system will not be adding or removing
1299  devices during this phase of the init process. This is very likely
1300  a bad assumption but it greatly simplifies the code.
1301 
1302 Arguments:
1303 
1304  DriverObject - a pointer to the object for the disk driver.
1305 
1306  Nothing - unused
1307 
1308  Count - an indication of how many times this routine has been called.
1309 
1310 Return Value:
1311 
1312  none
1313 
1314 --*/
1315 
1316 {
1318  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
1319  PDISK_DATA diskData;
1320 
1321  ULONG unmatchedDiskCount;
1322  PDEVICE_OBJECT unmatchedDisk = NULL;
1323 
1324  ULONG i;
1325  PDISK_DETECT_INFO diskInfo = NULL;
1326 
1328 
1329  if(Count != 1) {
1330  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "DiskDriverReinitialization: ignoring call %d\n",
1331  Count));
1332  return;
1333  }
1334 
1335  //
1336  // Check to see how many entries in the detect info list have been matched.
1337  // If there's only one remaining we'll see if we can find a disk to go with
1338  // it.
1339  //
1340 
1341  if(DetectInfoCount == 0) {
1342  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "DiskDriverReinitialization: no detect info saved\n"));
1343  return;
1344  }
1345 
1346  if((DetectInfoCount - DetectInfoUsedCount) != 1) {
1347  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "DiskDriverReinitialization: %d of %d geometry entries "
1348  "used - will not attempt match\n", DetectInfoUsedCount, DetectInfoCount));
1349  return;
1350  }
1351 
1352  //
1353  // Scan through the list of disks and see if any of them are missing
1354  // geometry information. If there is only one such disk we'll try to
1355  // match it to the unmatched geometry.
1356  //
1357 
1358 
1359  //
1360  // ISSUE-2000/5/24-henrygab - figure out if there's a way to keep
1361  // removals from happening while doing this.
1362  //
1363  unmatchedDiskCount = 0;
1364  for(deviceObject = DriverObject->DeviceObject;
1365  deviceObject != NULL;
1366 #ifdef _MSC_VER
1367 #pragma prefast(suppress:28175, "Need to access the opaque field to scan through the list of disks")
1368 #endif
1369  deviceObject = deviceObject->NextDevice) {
1370 
1371  fdoExtension = deviceObject->DeviceExtension;
1372 
1373  if (!fdoExtension->CommonExtension.IsFdo) {
1374  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskDriverReinit: %#p is not an FDO\n",
1375  deviceObject));
1376  continue;
1377  }
1378 
1379  //
1380  // If the geometry for this one is already known then skip it.
1381  //
1382 
1383  diskData = fdoExtension->CommonExtension.DriverData;
1384  if(diskData->GeometrySource != DiskGeometryUnknown) {
1385  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskDriverReinit: FDO %#p has a geometry\n",
1386  deviceObject));
1387  continue;
1388  }
1389 
1390  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "DiskDriverReinit: FDO %#p has no geometry\n",
1391  deviceObject));
1392 
1393  //
1394  // Mark this one as using the default. It's past the time when disk
1395  // might blunder across the geometry info. If we set the geometry
1396  // from the bios we'll reset this field down below.
1397  //
1398 
1399  diskData->GeometrySource = DiskGeometryFromDefault;
1400 
1401  //
1402  // As long as we've only got one unmatched disk we're fine.
1403  //
1404 
1405  unmatchedDiskCount++;
1406  if(unmatchedDiskCount > 1) {
1407  NT_ASSERT(unmatchedDisk != NULL);
1408  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_GENERAL, "DiskDriverReinit: FDO %#p also has no geometry\n",
1409  unmatchedDisk));
1410  unmatchedDisk = NULL;
1411  break;
1412  }
1413 
1414  unmatchedDisk = deviceObject;
1415  }
1416 
1417  //
1418  // If there's more or less than one ungeometried disk then we can't do
1419  // anything about the geometry.
1420  //
1421 
1422  if(unmatchedDiskCount != 1) {
1423  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL, "DiskDriverReinit: Unable to match geometry\n"));
1424  return;
1425 
1426  }
1427 
1428  fdoExtension = unmatchedDisk->DeviceExtension;
1429  diskData = fdoExtension->CommonExtension.DriverData;
1430 
1431  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskDriverReinit: Found possible match\n"));
1432 
1433  //
1434  // Find the geometry which wasn't assigned.
1435  //
1436 
1437  for(i = 0; i < DetectInfoCount; i++) {
1438  if(DetectInfoList[i].Device == NULL) {
1439  diskInfo = &(DetectInfoList[i]);
1440  break;
1441  }
1442  }
1443 
1444  if (diskInfo != NULL)
1445  {
1446  //
1447  // Save the geometry information away in the disk data block and
1448  // set the bit indicating that we found a valid one.
1449  //
1450 
1451  ULONG cylinders;
1452  ULONG sectorsPerTrack;
1453  ULONG tracksPerCylinder;
1454 
1455  ULONG length;
1456 
1457  //
1458  // Point to the array of drive parameters.
1459  //
1460 
1461  cylinders = diskInfo->DriveParameters.MaxCylinders + 1;
1462  sectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
1463  tracksPerCylinder = diskInfo->DriveParameters.MaxHeads + 1;
1464 
1465  //
1466  // Since the BIOS may not report the full drive, recalculate the drive
1467  // size based on the volume size and the BIOS values for tracks per
1468  // cylinder and sectors per track..
1469  //
1470 
1471  length = tracksPerCylinder * sectorsPerTrack;
1472 
1473  if (length == 0) {
1474 
1475  //
1476  // The BIOS information is bogus.
1477  //
1478 
1479  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskDriverReinit: H (%d) or S(%d) is zero\n",
1480  tracksPerCylinder, sectorsPerTrack));
1481  return;
1482  }
1483 
1484  //
1485  // since we are copying the structure RealGeometry here, we should
1486  // really initialize all the fields, especially since a zero'd
1487  // BytesPerSector field would cause a trap in xHalReadPartitionTable()
1488  //
1489 
1490  diskData->RealGeometry = fdoExtension->DiskGeometry;
1491 
1492  //
1493  // Save the geometry information away in the disk data block and
1494  // set the bit indicating that we found a valid one.
1495  //
1496 
1497  diskData->RealGeometry.SectorsPerTrack = sectorsPerTrack;
1498  diskData->RealGeometry.TracksPerCylinder = tracksPerCylinder;
1499  diskData->RealGeometry.Cylinders.QuadPart = (LONGLONG)cylinders;
1500 
1501  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskDriverReinit: BIOS spt %#x, #heads %#x, "
1502  "#cylinders %#x\n",
1503  sectorsPerTrack, tracksPerCylinder, cylinders));
1504 
1505  diskData->GeometrySource = DiskGeometryGuessedFromBios;
1506  diskInfo->Device = unmatchedDisk;
1507 
1508  //
1509  // Now copy the geometry over to the fdo extension and call
1510  // classpnp to redetermine the disk size and cylinder count.
1511  //
1512 
1513  fdoExtension->DiskGeometry = diskData->RealGeometry;
1514 
1515  (VOID)ClassReadDriveCapacity(unmatchedDisk);
1516 
1517  if (diskData->RealGeometry.BytesPerSector == 0) {
1518 
1519  //
1520  // if the BytesPerSector field is set to zero for a disk
1521  // listed in the bios, then the system will bugcheck in
1522  // xHalReadPartitionTable(). assert here since it is
1523  // easier to determine what is happening this way.
1524  //
1525 
1526  NT_ASSERT(!"RealGeometry not set to non-zero bps\n");
1527  }
1528  }
1529 
1530  return;
1531 }
1532 
1533 
1534 NTSTATUS
1537  OUT PDISK_DETECTION_INFO DetectInfo
1538  )
1539 /*++
1540 
1541 Routine Description:
1542 
1543  Get the Int13 information from the BIOS DetectInfoList.
1544 
1545 Arguments:
1546 
1547  FdoExtension - Supplies a pointer to the FDO extension that we want to
1548  obtain the detect information for.
1549 
1550  DetectInfo - A buffer where the detect information will be copied to.
1551 
1552 Return Value:
1553 
1554  NTSTATUS code.
1555 
1556 --*/
1557 {
1558  ULONG i;
1559  BOOLEAN found = FALSE;
1560  PDISK_DETECT_INFO diskInfo = NULL;
1561  PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
1562 
1563  PAGED_CODE ();
1564 
1565  //
1566  // Fail for non-fixed drives.
1567  //
1568 
1569  if (TEST_FLAG (FdoExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
1570  return STATUS_NOT_SUPPORTED;
1571  }
1572 
1573  //
1574  // There is no GPT detection info, so fail this.
1575  //
1576 
1577  if (diskData->PartitionStyle == PARTITION_STYLE_GPT) {
1578  return STATUS_NOT_SUPPORTED;
1579  }
1580 
1581  for(i = 0; i < DetectInfoCount; i++) {
1582 
1583 
1584  NT_ASSERT(DetectInfoList != NULL);
1585 
1586  diskInfo = &(DetectInfoList[i]);
1587 
1588  if((diskData->Mbr.Signature != 0) &&
1589  (diskData->Mbr.Signature == diskInfo->Signature)) {
1590  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskGetDetectInfo: found match for signature "
1591  "%#08lx\n",
1592  diskData->Mbr.Signature));
1593  found = TRUE;
1594  break;
1595  } else if((diskData->Mbr.Signature == 0) &&
1596  (diskData->Mbr.MbrCheckSum != 0) &&
1597  (diskData->Mbr.MbrCheckSum == diskInfo->MbrCheckSum)) {
1598  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_GENERAL, "DiskGetDetectInfo: found match for xsum %#08lx\n",
1599  diskData->Mbr.MbrCheckSum));
1600  found = TRUE;
1601  break;
1602  }
1603  }
1604 
1605  if ( found ) {
1606  DetectInfo->DetectionType = DetectInt13;
1607  DetectInfo->Int13.DriveSelect = diskInfo->DriveParameters.DriveSelect;
1608  DetectInfo->Int13.MaxCylinders = diskInfo->DriveParameters.MaxCylinders;
1609  DetectInfo->Int13.SectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
1610  DetectInfo->Int13.MaxHeads = diskInfo->DriveParameters.MaxHeads;
1611  DetectInfo->Int13.NumberDrives = diskInfo->DriveParameters.NumberDrives;
1612  RtlZeroMemory (&DetectInfo->ExInt13, sizeof (DetectInfo->ExInt13));
1613  }
1614 
1615  return (found ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
1616 }
1617 
1618 
1619 NTSTATUS
1620 DiskReadSignature(
1622  )
1623 
1624 /*++
1625 
1626 Routine Description:
1627 
1628  Read the disks signature from the drive. The signature can be either
1629  a MBR signature or a GPT/EFI signature.
1630 
1631  The low-level signature reading is done by IoReadDiskSignature().
1632 
1633 Arguments:
1634 
1635  Fdo - Pointer to the FDO of a disk to read the signature for.
1636 
1637 Return Value:
1638 
1639  NTSTATUS code.
1640 
1641 --*/
1642 
1643 
1644 {
1645  NTSTATUS Status;
1646  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
1647  PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
1648  DISK_SIGNATURE Signature = { 0 };
1649 
1650  PAGED_CODE();
1651 
1653  fdoExtension->DiskGeometry.BytesPerSector,
1654  &Signature);
1655 
1656  if (!NT_SUCCESS (Status)) {
1657  return Status;
1658  }
1659 
1660  if (Signature.PartitionStyle == PARTITION_STYLE_GPT) {
1661  diskData->PartitionStyle = PARTITION_STYLE_GPT;
1662  diskData->Efi.DiskId = Signature.Gpt.DiskId;
1663  } else if (Signature.PartitionStyle == PARTITION_STYLE_MBR) {
1664  diskData->PartitionStyle = PARTITION_STYLE_MBR;
1665  diskData->Mbr.Signature = Signature.Mbr.Signature;
1666  diskData->Mbr.MbrCheckSum = Signature.Mbr.CheckSum;
1667  } else {
1668  NT_ASSERT (FALSE);
1670  }
1671 
1672  return Status;
1673 }
1674 
1675 #endif // defined(_X86_) || defined(_AMD64_)
1676 
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
struct _CM_INT13_DRIVE_PARAMETER CM_INT13_DRIVE_PARAMETER
#define IN
Definition: typedefs.h:39
return STATUS_NOT_SUPPORTED
Definition: pdh_main.c:93
boolean suppress
Definition: jpeglib.h:1006
#define GET_STARTING_SECTOR(p)
Definition: hal.h:253
#define PARTITION_LDM
Definition: disk.h:101
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UCHAR StartingTrack
Definition: hal.h:280
UCHAR StartingSectorMsb0
Definition: hal.h:289
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct _DISK_DATA::@1012::@1016 Efi
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
NTSTATUS NTAPI IoReadDiskSignature(IN PDEVICE_OBJECT DeviceObject, IN ULONG BytesPerSector, OUT PDISK_SIGNATURE Signature)
Definition: fstubex.c:2165
UCHAR PartitionLengthLsb0
Definition: hal.h:291
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
UCHAR EndingCylinderMsb
Definition: hal.h:286
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
unsigned char * PUCHAR
Definition: retypes.h:3
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
UCHAR EndingCylinderLsb
Definition: hal.h:285
#define PARTITION_TABLE_OFFSET
Definition: hal.h:244
GLuint buffer
Definition: glext.h:5915
struct _CM_FULL_RESOURCE_DESCRIPTOR CM_FULL_RESOURCE_DESCRIPTOR
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:316
ULONG BytesPerSector
Definition: ntdddisk.h:409
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
#define VALUE_BUFFER_SIZE
Definition: smutil.c:23
#define GET_ENDING_S_OF_CHS(p)
Definition: hal.h:259
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
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
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
UCHAR PartitionLengthLsb1
Definition: hal.h:292
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
long LONG
Definition: pedump.c:60
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
UCHAR StartingSectorLsb0
Definition: hal.h:287
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
UCHAR PartitionLengthMsb0
Definition: hal.h:293
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
PARTITION_STYLE PartitionStyle
Definition: disk.h:197
struct _PARTITION_DESCRIPTOR PARTITION_DESCRIPTOR
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
int Count
Definition: noreturn.cpp:7
#define DISK_TAG_UPDATE_GEOM
Definition: disk.h:59
const DWORD Style
Definition: appswitch.c:71
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
UCHAR StartingSectorMsb1
Definition: hal.h:290
UCHAR PartitionType
Definition: hal.h:283
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
irpSp
Definition: iofuncs.h:2719
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379::@388 DeviceSpecificData
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
unsigned char UCHAR
Definition: xmlstorage.h:181
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
#define VOID
Definition: acefi.h:82
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:245
#define DiskGetDetectInfo(FdoExtension, DetectInfo)
Definition: disk.h:861
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@379 u
GLsizei const GLfloat * value
Definition: glext.h:6069
struct _cl_event * event
Definition: glext.h:7739
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
UCHAR StartingCylinderLsb
Definition: hal.h:281
MxDeviceObject deviceObject
UCHAR ActiveFlag
Definition: hal.h:279
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
struct _DISK_GEOMETRY DISK_GEOMETRY
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
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
unsigned short USHORT
Definition: pedump.c:61
UCHAR StartingCylinderMsb
Definition: hal.h:282
UCHAR PartitionLengthMsb1
Definition: hal.h:294
#define NULL
Definition: types.h:112
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:818
#define IRP_MJ_READ
Definition: rdpdr.c:46
struct _CM_INT13_DRIVE_PARAMETER * PCM_INT13_DRIVE_PARAMETER
UCHAR StartingSectorLsb1
Definition: hal.h:288
#define OUT
Definition: typedefs.h:40
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:248
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
static const WCHAR Signature[]
Definition: parser.c:141
static SERVICE_STATUS status
Definition: service.c:31
UCHAR EndingTrack
Definition: hal.h:284
unsigned short * PUSHORT
Definition: retypes.h:2
FxIrp * irp
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
LONGLONG QuadPart
Definition: typedefs.h:114
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define PAGED_CODE()
#define NT_ASSERT
Definition: rtlfuncs.h:3310
struct _DISK_DATA::@1012::@1015 Mbr
Definition: ps.c:97