ReactOS 0.4.15-dev-7953-g1f49173
geometry.c
Go to the documentation of this file.
1/*++
2
3Copyright (C) Microsoft Corporation, 1991 - 1999
4
5Module Name:
6
7 geometry.c
8
9Abstract:
10
11 SCSI disk class driver - this module contains all the code for generating
12 disk geometries.
13
14Environment:
15
16 kernel mode only
17
18Notes:
19
20Revision 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
34DISK_GEOMETRY_SOURCE
35DiskUpdateGeometry(
36 IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
37 );
38
40DiskUpdateRemovableGeometry (
42 );
43
44VOID
45DiskScanBusDetectInfo(
47 IN HANDLE BusKey
48 );
49
51DiskSaveBusDetectInfo(
53 IN HANDLE TargetKey,
54 IN ULONG DiskNumber
55 );
56
58DiskSaveGeometryDetectInfo(
60 IN HANDLE HardwareKey
61 );
62
64DiskGetPortGeometry(
66 OUT PDISK_GEOMETRY Geometry
67 );
68
69typedef struct _DISK_DETECT_INFO {
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
83PDISK_DETECT_INFO DetectInfoList = NULL;
84ULONG DetectInfoCount = 0;
85LONG 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
104typedef 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
161DiskSaveDetectInfo(
163 )
164
165/*++
166
167Routine 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
175Arguments:
176
177 DriverObject - the driver being initialized. This is used to get to the
178 hardware database.
179
180Return 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
275VOID
276DiskCleanupDetectInfo(
278 )
279/*++
280
281Routine Description:
282
283 This routine will cleanup the data structure built by DiskSaveDetectInfo.
284
285Arguments:
286
287 DriverObject - a pointer to the kernel object for this driver.
288
289Return Value:
290
291 none
292
293--*/
294
295{
297 FREE_POOL(DetectInfoList);
298 return;
299}
300
301
303DiskSaveGeometryDetectInfo(
305 IN HANDLE HardwareKey
306 )
307{
308 UNICODE_STRING unicodeString;
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 =
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
432VOID
433DiskScanBusDetectInfo(
435 IN HANDLE BusKey
436 )
437/*++
438
439Routine 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
445Arguments:
446
447 DriverObject - the object for this driver.
448 BusKey - handle to the bus key to be enumerated.
449
450Return 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
605DiskSaveBusDetectInfo(
607 IN HANDLE TargetKey,
608 IN ULONG DiskNumber
609 )
610/*++
611
612Routine 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
618Arguments:
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
627Return Value:
628
629 status
630
631--*/
632{
633 PDISK_DETECT_INFO diskInfo;
634
635 UNICODE_STRING unicodeString;
636
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
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
771DISK_GEOMETRY_SOURCE
772DiskUpdateGeometry(
774 )
775/*++
776
777Routine 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
789Arguments:
790
791 DeviceExtension - Supplies a pointer to the device information for disk.
792
793Return 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
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
972DiskUpdateRemovableGeometry (
974 )
975
976/*++
977
978Routine 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
988Arguments:
989
990 Fdo - Supplies the functional device object whos size needs to be updated.
991
992Return 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
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
1030DiskGetPortGeometry(
1032 OUT PDISK_GEOMETRY Geometry
1033 )
1034/*++
1035
1036Routine 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
1042Arguments:
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
1049Return 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
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
1107BOOLEAN
1108DiskIsNT4Geometry(
1110 )
1111
1112/*++
1113
1114Routine 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 {
1168
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
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
1245 )
1246/*++
1247
1248Routine 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
1258Arguments:
1259
1260 Fdo - a pointer to the device object to be checked.
1261
1262Return Value:
1263
1264 status of ClassReadDriveCapacity.
1265
1266--*/
1267
1268{
1269 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
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
1284VOID
1285DiskDriverReinitialization(
1288 IN ULONG Count
1289 )
1290/*++
1291
1292Routine 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
1302Arguments:
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
1310Return 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
1537 OUT PDISK_DETECTION_INFO DetectInfo
1538 )
1539/*++
1540
1541Routine Description:
1542
1543 Get the Int13 information from the BIOS DetectInfoList.
1544
1545Arguments:
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
1552Return 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
1620DiskReadSignature(
1622 )
1623
1624/*++
1625
1626Routine 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
1633Arguments:
1634
1635 Fdo - Pointer to the FDO of a disk to read the signature for.
1636
1637Return Value:
1638
1639 NTSTATUS code.
1640
1641--*/
1642
1643
1644{
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) {
1662 diskData->Efi.DiskId = Signature.Gpt.DiskId;
1663 } else if (Signature.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 PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
const DWORD Style
Definition: appswitch.c:71
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
#define PARTITION_LDM
Definition: disk.h:101
#define FREE_POOL(_PoolPtr)
Definition: cdrom.h:782
#define TEST_FLAG(Flags, Bit)
Definition: cdrom.h:1495
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
IO_COMPLETION_ROUTINE ClassSignalCompletion
Definition: classpnp.h:1330
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR Signature[]
Definition: parser.c:141
_Must_inspect_result_ NTSTATUS NTAPI ClassReadDriveCapacity(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:2742
#define DiskGetDetectInfo(FdoExtension, DetectInfo)
Definition: disk.h:861
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:818
#define DISK_TAG_UPDATE_GEOM
Definition: disk.h:59
@ FdoExtension
Definition: precomp.h:48
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define PagedPool
Definition: env_spec_w32.h:308
NTSTATUS NTAPI IoReadDiskSignature(IN PDEVICE_OBJECT DeviceObject, IN ULONG BytesPerSector, OUT PDISK_SIGNATURE Signature)
Definition: fstubex.c:2171
MxDeviceObject deviceObject
FxIrp * irp
Status
Definition: gdiplustypes.h:25
struct _cl_event * event
Definition: glext.h:7739
GLuint buffer
Definition: glext.h:5915
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
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 _CM_FULL_RESOURCE_DESCRIPTOR CM_FULL_RESOURCE_DESCRIPTOR
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
boolean suppress
Definition: jpeglib.h:1006
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define KernelMode
Definition: asm.h:34
@ Initialized
Definition: ketypes.h:388
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
int Count
Definition: noreturn.cpp:7
@ KeyValueFullInformation
Definition: nt_native.h:1181
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:316
struct _DISK_GEOMETRY DISK_GEOMETRY
@ NotificationEvent
@ SynchronizationEvent
struct _PARTITION_DESCRIPTOR * PPARTITION_DESCRIPTOR
#define PARTITION_TABLE_OFFSET
Definition: hal.h:244
#define BOOT_SIGNATURE_OFFSET
Definition: hal.h:245
#define GET_ENDING_S_OF_CHS(p)
Definition: hal.h:259
struct _PARTITION_DESCRIPTOR PARTITION_DESCRIPTOR
#define GET_STARTING_SECTOR(p)
Definition: hal.h:253
#define NUM_PARTITION_TABLE_ENTRIES
Definition: hal.h:248
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
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
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
#define L(x)
Definition: ntvdm.h:50
#define BOOT_RECORD_SIGNATURE
Definition: parttest.c:17
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
@ Nothing
Definition: sacdrv.h:266
#define STATUS_SUCCESS
Definition: shellext.h:65
#define VALUE_BUFFER_SIZE
Definition: smutil.c:23
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@402 DeviceSpecificData
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PARTITION_STYLE PartitionStyle
Definition: disk.h:197
struct _DISK_DATA::@1055::@1059 Efi
struct _DISK_DATA::@1055::@1058 Mbr
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
ULONG BytesPerSector
Definition: ntdddisk.h:409
DISK_GEOMETRY DiskGeometry
Definition: classpnp.h:888
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
struct _IO_STACK_LOCATION::@1564::@1565 DeviceIoControl
union _IO_STACK_LOCATION::@1564 Parameters
UCHAR EndingTrack
Definition: hal.h:284
UCHAR StartingSectorMsb1
Definition: hal.h:290
UCHAR EndingCylinderMsb
Definition: hal.h:286
UCHAR StartingSectorMsb0
Definition: hal.h:289
UCHAR PartitionLengthMsb0
Definition: hal.h:293
UCHAR PartitionLengthLsb1
Definition: hal.h:292
UCHAR PartitionLengthMsb1
Definition: hal.h:294
UCHAR PartitionLengthLsb0
Definition: hal.h:291
UCHAR PartitionType
Definition: hal.h:283
UCHAR StartingCylinderLsb
Definition: hal.h:281
UCHAR StartingTrack
Definition: hal.h:280
UCHAR StartingCylinderMsb
Definition: hal.h:282
UCHAR StartingSectorLsb1
Definition: hal.h:288
UCHAR StartingSectorLsb0
Definition: hal.h:287
UCHAR ActiveFlag
Definition: hal.h:279
UCHAR EndingCylinderLsb
Definition: hal.h:285
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: ps.c:97
uint16_t * PWSTR
Definition: typedefs.h:56
int64_t LONGLONG
Definition: typedefs.h:68
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
LONGLONG QuadPart
Definition: typedefs.h:114
Definition: pdh_main.c:94
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFDEVICE Fdo
Definition: wdffdo.h:461
struct _CM_INT13_DRIVE_PARAMETER * PCM_INT13_DRIVE_PARAMETER
struct _CM_INT13_DRIVE_PARAMETER CM_INT13_DRIVE_PARAMETER
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
irpSp
Definition: iofuncs.h:2719
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
@ Executive
Definition: ketypes.h:415
#define NT_ASSERT
Definition: rtlfuncs.h:3310
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180