1 /*
2 * PROJECT: ReactOS Partition Information Tool
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Displays disk and partition information for MBR and GPT disks.
5 * COPYRIGHT: Copyright 2001-2002 Eric Kohl
6 * Copyright 2020-2021 Hermes Belusca-Maito
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #define WIN32_NO_STATUS
15 #include <windows.h>
16 #include <ntndk.h>
17
18 /* The maximum information a DISK_GEOMETRY_EX dynamic structure can contain */
19 typedef struct _DISK_GEOMETRY_EX_INTERNAL
20 {
21 DISK_GEOMETRY Geometry;
22 LARGE_INTEGER DiskSize;
23 DISK_PARTITION_INFO Partition;
24 DISK_DETECTION_INFO Detection;
25 } DISK_GEOMETRY_EX_INTERNAL, *PDISK_GEOMETRY_EX_INTERNAL;
26
27 #define DRIVE_LAYOUT_INFO_ENTRY_SIZE \
28 RTL_FIELD_SIZE(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0])
29
30 #define DRIVE_LAYOUT_INFO_SIZE(n) \
31 (FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry) + \
32 ((n) * DRIVE_LAYOUT_INFO_ENTRY_SIZE))
33
34 #define DRIVE_LAYOUT_INFOEX_ENTRY_SIZE \
35 RTL_FIELD_SIZE(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0])
36
37 #define DRIVE_LAYOUT_INFOEX_SIZE(n) \
38 (FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry) + \
39 ((n) * DRIVE_LAYOUT_INFOEX_ENTRY_SIZE))
40
41
42 /* Rounding up for number; not the same as ROUND_UP() with power-of-two sizes */
43 #define ROUND_UP_NUM(num, up) ((((num) + (up) - 1) / (up)) * (up))
44
45
46 // #define DUMP_DATA
47
48
49 /* FORMATTING HELPERS *******************************************************/
50
51 static PCSTR PartitionStyleNames[] = {"MBR", "GPT", "RAW", "Unknown"};
52 #define PARTITION_STYLE_NAME(PartStyle) \
53 ( ((PartStyle) <= PARTITION_STYLE_RAW) \
54 ? PartitionStyleNames[(PartStyle)] \
55 : PartitionStyleNames[_countof(PartitionStyleNames)-1] )
56
57 static PCSTR DetectTypeNames[] = { "None", "DetectInt13", "DetectExInt13", "Unknown" };
58 #define DETECT_TYPE_NAME(DetectType) \
59 ( ((DetectType) <= DetectExInt13) \
60 ? DetectTypeNames[(DetectType)] \
61 : DetectTypeNames[_countof(DetectTypeNames)-1] )
62
63 #define GUID_FORMAT_STR "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
64 #define GUID_ELEMENTS(Guid) \
65 (Guid)->Data1, (Guid)->Data2, (Guid)->Data3, \
66 (Guid)->Data4[0], (Guid)->Data4[1], (Guid)->Data4[2], (Guid)->Data4[3], \
67 (Guid)->Data4[4], (Guid)->Data4[5], (Guid)->Data4[6], (Guid)->Data4[7]
68
69
70 /* FUNCTIONS ****************************************************************/
71
72 #ifdef DUMP_DATA
HexDump(IN PVOID buffer,IN ULONG size)73 void HexDump(
74 IN PVOID buffer,
75 IN ULONG size)
76 {
77 ULONG_PTR offset = 0;
78 PUCHAR ptr;
79
80 while (offset < (size & ~15))
81 {
82 ptr = (PUCHAR)((ULONG_PTR)buffer + offset);
83 printf("%08lx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx-%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx\n",
84 offset,
85 ptr[0], ptr[1], ptr[2] , ptr[3] , ptr[4] , ptr[5] , ptr[6] , ptr[7],
86 ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
87 offset += 16;
88 }
89
90 if (offset < size)
91 {
92 ptr = (PUCHAR)((ULONG_PTR)buffer + offset);
93 printf("%08lx ", offset);
94 while (offset < size)
95 {
96 printf(" %02hx", *ptr);
97 offset++;
98 ptr++;
99 }
100 printf("\n");
101 }
102
103 printf("\n");
104 }
105 #endif
106
Usage(void)107 void Usage(void)
108 {
109 puts("Usage: partinfo <drive number>");
110 }
111
main(int argc,char * argv[])112 int main(int argc, char *argv[])
113 {
114 NTSTATUS Status;
115 ULONG ulDrive;
116 HANDLE hDisk;
117 ULONG i;
118 SYSTEM_DEVICE_INFORMATION DeviceInfo;
119 IO_STATUS_BLOCK Iosb;
120 ULONG BufferSize;
121 union
122 {
123 DISK_GEOMETRY Info;
124 DISK_GEOMETRY_EX_INTERNAL InfoEx;
125 } DiskGeometry;
126 PDISK_GEOMETRY pDiskGeometry;
127 union
128 {
129 PARTITION_INFORMATION Info;
130 PARTITION_INFORMATION_EX InfoEx;
131 } PartInfo;
132 PPARTITION_INFORMATION pPartInfo;
133 PPARTITION_INFORMATION_EX pPartInfoEx;
134 union
135 {
136 PDRIVE_LAYOUT_INFORMATION Info;
137 PDRIVE_LAYOUT_INFORMATION_EX InfoEx;
138 } LayoutBuffer;
139 PVOID ptr;
140 WCHAR DriveName[40];
141
142 if (argc != 2)
143 {
144 Usage();
145 return 0;
146 }
147
148 ulDrive = strtoul(argv[1], NULL, 10);
149 if (errno != 0)
150 {
151 printf("Error: Malformed drive number\n");
152 return 0;
153 }
154
155 /*
156 * Retrieve the number of disks on the system.
157 */
158 Status = NtQuerySystemInformation(SystemDeviceInformation,
159 &DeviceInfo,
160 sizeof(DeviceInfo),
161 &i);
162 if (!NT_SUCCESS(Status))
163 {
164 printf("NtQuerySystemInformation() failed (Status 0x%lx)\n", Status);
165 return 0;
166 }
167 if (DeviceInfo.NumberOfDisks == 0)
168 {
169 printf("No disk drive installed!\n");
170 return 0;
171 }
172
173 if (ulDrive >= DeviceInfo.NumberOfDisks)
174 {
175 printf("Invalid disk drive number! Valid drive numbers: [0-%lu]\n",
176 DeviceInfo.NumberOfDisks-1);
177 return 0;
178 }
179
180 /* Build the full drive name */
181 swprintf(DriveName, L"\\\\.\\PHYSICALDRIVE%lu", ulDrive);
182
183 /* Open the drive */
184 hDisk = CreateFileW(DriveName,
185 GENERIC_READ,
186 FILE_SHARE_READ | FILE_SHARE_WRITE,
187 NULL,
188 OPEN_EXISTING,
189 0,
190 NULL);
191 if (hDisk == INVALID_HANDLE_VALUE)
192 {
193 printf("Could not open drive!");
194 return 0;
195 }
196
197 printf("Drive number: %lu\n\n", ulDrive);
198
199
200 /*
201 * Get the drive geometry.
202 */
203 Status = NtDeviceIoControlFile(hDisk,
204 NULL,
205 NULL,
206 NULL,
207 &Iosb,
208 IOCTL_DISK_GET_DRIVE_GEOMETRY,
209 NULL,
210 0,
211 &DiskGeometry.Info,
212 sizeof(DiskGeometry.Info));
213 if (!NT_SUCCESS(Status))
214 {
215 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_GEOMETRY) failed! (Status 0x%lx)\n", Status);
216 }
217 else
218 {
219 pDiskGeometry = &DiskGeometry.Info;
220
221 #ifdef DUMP_DATA
222 HexDump(&DiskGeometry.Info, (ULONG)Iosb.Information);
223 #endif
224 printf("IOCTL_DISK_GET_DRIVE_GEOMETRY\n"
225 "Cylinders: %I64u\nMediaType: 0x%x\nTracksPerCylinder: %lu\n"
226 "SectorsPerTrack: %lu\nBytesPerSector: %lu\n",
227 pDiskGeometry->Cylinders.QuadPart,
228 pDiskGeometry->MediaType,
229 pDiskGeometry->TracksPerCylinder,
230 pDiskGeometry->SectorsPerTrack,
231 pDiskGeometry->BytesPerSector);
232 }
233
234
235 /*
236 * Get the extended drive geometry.
237 */
238 printf("\n");
239 Status = NtDeviceIoControlFile(hDisk,
240 NULL,
241 NULL,
242 NULL,
243 &Iosb,
244 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
245 NULL,
246 0,
247 &DiskGeometry.InfoEx,
248 sizeof(DiskGeometry.InfoEx));
249 if (!NT_SUCCESS(Status))
250 {
251 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) failed! (Status 0x%lx)\n", Status);
252 }
253 else
254 {
255 // PDISK_DETECTION_INFO DiskDetectInfo = &DiskGeometry.InfoEx.Detection; // DiskGeometryGetDetect(&DiskGeometry.InfoEx);
256 // PDISK_PARTITION_INFO DiskPartInfo = &DiskGeometry.InfoEx.Partition; // DiskGeometryGetPartition(&DiskGeometry.InfoEx);
257 pDiskGeometry = &DiskGeometry.InfoEx.Geometry;
258
259 #ifdef DUMP_DATA
260 HexDump(&DiskGeometry.InfoEx, (ULONG)Iosb.Information);
261 #endif
262 printf("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX\n"
263 "Cylinders: %I64u\nMediaType: 0x%x\nTracksPerCylinder: %lu\n"
264 "SectorsPerTrack: %lu\nBytesPerSector: %lu\n"
265 "DiskSize: %I64u\n",
266 pDiskGeometry->Cylinders.QuadPart,
267 pDiskGeometry->MediaType,
268 pDiskGeometry->TracksPerCylinder,
269 pDiskGeometry->SectorsPerTrack,
270 pDiskGeometry->BytesPerSector,
271 DiskGeometry.InfoEx.DiskSize.QuadPart);
272
273 printf("SizeOfDetectInfo: %lu DetectionType: %u (%s)\n",
274 DiskGeometry.InfoEx.Detection.SizeOfDetectInfo,
275 DiskGeometry.InfoEx.Detection.DetectionType,
276 DETECT_TYPE_NAME(DiskGeometry.InfoEx.Detection.DetectionType));
277 switch (DiskGeometry.InfoEx.Detection.DetectionType)
278 {
279 case DetectInt13:
280 {
281 PDISK_INT13_INFO pInt13 = &DiskGeometry.InfoEx.Detection.Int13;
282 printf(" DriveSelect: %u MaxCylinders: %lu SectorsPerTrack: %u MaxHeads: %u NumberDrives: %u\n",
283 pInt13->DriveSelect, pInt13->MaxCylinders,
284 pInt13->SectorsPerTrack, pInt13->MaxHeads,
285 pInt13->NumberDrives);
286 break;
287 }
288
289 case DetectExInt13:
290 {
291 PDISK_EX_INT13_INFO pExInt13 = &DiskGeometry.InfoEx.Detection.ExInt13;
292 printf(" ExBufferSize: %u ExFlags: %u\n"
293 " ExCylinders: %lu ExHeads: %lu ExSectorsPerTrack: %lu\n"
294 " ExSectorsPerDrive: %I64u ExSectorSize: %u ExReserved: %u\n",
295 pExInt13->ExBufferSize, pExInt13->ExFlags,
296 pExInt13->ExCylinders, pExInt13->ExHeads,
297 pExInt13->ExSectorsPerTrack, pExInt13->ExSectorsPerDrive,
298 pExInt13->ExSectorSize, pExInt13->ExReserved);
299 break;
300 }
301
302 case DetectNone:
303 default:
304 break;
305 }
306
307 printf("SizeOfPartitionInfo: %lu PartitionStyle: %u [%s]\n",
308 DiskGeometry.InfoEx.Partition.SizeOfPartitionInfo,
309 DiskGeometry.InfoEx.Partition.PartitionStyle,
310 PARTITION_STYLE_NAME(DiskGeometry.InfoEx.Partition.PartitionStyle));
311
312 if (DiskGeometry.InfoEx.Partition.PartitionStyle == PARTITION_STYLE_MBR)
313 {
314 printf(" Signature: 0x%08lx Checksum 0x%08lx\n",
315 DiskGeometry.InfoEx.Partition.Mbr.Signature,
316 DiskGeometry.InfoEx.Partition.Mbr.CheckSum);
317 }
318 else if (DiskGeometry.InfoEx.Partition.PartitionStyle == PARTITION_STYLE_GPT)
319 {
320 printf(" DiskId: {" GUID_FORMAT_STR "}\n",
321 GUID_ELEMENTS(&DiskGeometry.InfoEx.Partition.Gpt.DiskId));
322 }
323 else
324 {
325 /* Unknown */
326 printf("\n");
327 }
328 }
329
330
331 /*
332 * Display partition 0 (i.e. the whole disk) information.
333 */
334 printf("\n");
335 Status = NtDeviceIoControlFile(hDisk,
336 NULL,
337 NULL,
338 NULL,
339 &Iosb,
340 IOCTL_DISK_GET_PARTITION_INFO,
341 NULL,
342 0,
343 &PartInfo.Info,
344 sizeof(PartInfo.Info));
345 if (!NT_SUCCESS(Status))
346 {
347 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_PARTITION_INFO) failed! (Status 0x%lx)\n", Status);
348 }
349 else
350 {
351 pPartInfo = &PartInfo.Info;
352
353 #ifdef DUMP_DATA
354 HexDump(&PartInfo.Info, (ULONG)Iosb.Information);
355 #endif
356 printf("IOCTL_DISK_GET_PARTITION_INFO\n"
357 "nr: %ld boot: %1x type: 0x%x (%s) start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
358 pPartInfo->PartitionNumber,
359 pPartInfo->BootIndicator,
360 pPartInfo->PartitionType,
361 pPartInfo->RecognizedPartition ? "Recognized" : "Not recognized",
362 pPartInfo->StartingOffset.QuadPart,
363 pPartInfo->PartitionLength.QuadPart,
364 pPartInfo->HiddenSectors);
365 }
366
367 printf("\n");
368 Status = NtDeviceIoControlFile(hDisk,
369 NULL,
370 NULL,
371 NULL,
372 &Iosb,
373 IOCTL_DISK_GET_PARTITION_INFO_EX,
374 NULL,
375 0,
376 &PartInfo.InfoEx,
377 sizeof(PartInfo.InfoEx));
378 if (!NT_SUCCESS(Status))
379 {
380 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_PARTITION_INFO_EX) failed! (Status 0x%lx)\n", Status);
381 }
382 else
383 {
384 pPartInfoEx = &PartInfo.InfoEx;
385
386 #ifdef DUMP_DATA
387 HexDump(&PartInfo.InfoEx, (ULONG)Iosb.Information);
388 #endif
389 printf("IOCTL_DISK_GET_PARTITION_INFO_EX\n");
390
391 if (pPartInfoEx->PartitionStyle == PARTITION_STYLE_MBR)
392 {
393 printf("nr: %ld [%s] boot: %1x type: 0x%x (%s) start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
394 pPartInfoEx->PartitionNumber,
395 PARTITION_STYLE_NAME(pPartInfoEx->PartitionStyle),
396 pPartInfoEx->Mbr.BootIndicator,
397 pPartInfoEx->Mbr.PartitionType,
398 pPartInfoEx->Mbr.RecognizedPartition ? "Recognized" : "Not recognized",
399 pPartInfoEx->StartingOffset.QuadPart,
400 pPartInfoEx->PartitionLength.QuadPart,
401 pPartInfoEx->Mbr.HiddenSectors);
402 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
403 printf(" PartitionId: {" GUID_FORMAT_STR "}\n",
404 GUID_ELEMENTS(&pPartInfoEx->Mbr.PartitionId));
405 #endif
406 }
407 else if (pPartInfoEx->PartitionStyle == PARTITION_STYLE_GPT)
408 {
409 printf("nr: %ld [%s]\n"
410 " type : {" GUID_FORMAT_STR "}\n"
411 " id : {" GUID_FORMAT_STR "}\n"
412 " attrs: 0x%016I64x\n"
413 " name : '%.*S'\n"
414 " start: 0x%016I64x count: 0x%016I64x\n",
415 pPartInfoEx->PartitionNumber,
416 PARTITION_STYLE_NAME(pPartInfoEx->PartitionStyle),
417 GUID_ELEMENTS(&pPartInfoEx->Gpt.PartitionType),
418 GUID_ELEMENTS(&pPartInfoEx->Gpt.PartitionId),
419 pPartInfoEx->Gpt.Attributes,
420 (int)_countof(pPartInfoEx->Gpt.Name),
421 pPartInfoEx->Gpt.Name,
422 pPartInfoEx->StartingOffset.QuadPart,
423 pPartInfoEx->PartitionLength.QuadPart);
424 }
425 }
426
427
428 /*
429 * Retrieve the legacy partition layout
430 */
431 printf("\n");
432
433 /* Allocate a layout buffer with initially 4 partition entries (or 16 for NEC PC-98) */
434 BufferSize = DRIVE_LAYOUT_INFO_SIZE(IsNEC_98 ? 16 : 4);
435 LayoutBuffer.Info = RtlAllocateHeap(RtlGetProcessHeap(),
436 HEAP_ZERO_MEMORY,
437 BufferSize);
438 if (!LayoutBuffer.Info)
439 {
440 printf("Out of memory!");
441 goto Quit;
442 }
443
444 /*
445 * Keep looping while the drive layout buffer is too small.
446 * Iosb.Information or PartitionCount only contain actual info only
447 * once NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_LAYOUT) succeeds.
448 */
449 for (;;)
450 {
451 Status = NtDeviceIoControlFile(hDisk,
452 NULL,
453 NULL,
454 NULL,
455 &Iosb,
456 IOCTL_DISK_GET_DRIVE_LAYOUT,
457 NULL,
458 0,
459 LayoutBuffer.Info,
460 BufferSize);
461 if (NT_SUCCESS(Status))
462 {
463 /* We succeeded; compactify the layout structure but keep the
464 * number of partition entries rounded up to a multiple of 4. */
465 #if 1
466 BufferSize = DRIVE_LAYOUT_INFO_SIZE(ROUND_UP_NUM(LayoutBuffer.Info->PartitionCount, 4));
467 #else
468 BufferSize = (ULONG)Iosb.Information;
469 #endif
470 ptr = RtlReAllocateHeap(RtlGetProcessHeap(),
471 HEAP_REALLOC_IN_PLACE_ONLY,
472 LayoutBuffer.Info, BufferSize);
473 if (!ptr)
474 {
475 printf("Compactification failed; keeping original structure.\n");
476 }
477 else
478 {
479 LayoutBuffer.Info = ptr;
480 }
481 Status = STATUS_SUCCESS;
482 break;
483 }
484
485 if (Status != STATUS_BUFFER_TOO_SMALL)
486 {
487 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_LAYOUT) failed! (Status 0x%lx)\n", Status);
488
489 /* Bail out if any other error than "invalid function" has been emitted.
490 * This happens for example when calling it on GPT disks. */
491 if (Status != STATUS_INVALID_DEVICE_REQUEST)
492 {
493 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.Info);
494 goto Quit;
495 }
496 else
497 {
498 /* Just stop getting this information */
499 break;
500 }
501 }
502
503 /* Reallocate the buffer by chunks of 4 entries */
504 BufferSize += 4 * DRIVE_LAYOUT_INFO_ENTRY_SIZE;
505 ptr = RtlReAllocateHeap(RtlGetProcessHeap(),
506 HEAP_ZERO_MEMORY,
507 LayoutBuffer.Info, BufferSize);
508 if (!ptr)
509 {
510 printf("Out of memory!");
511 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.Info);
512 goto Quit;
513 }
514 LayoutBuffer.Info = ptr;
515 }
516
517 if (Status == STATUS_SUCCESS)
518 {
519 #ifdef DUMP_DATA
520 HexDump(LayoutBuffer.Info, (ULONG)Iosb.Information);
521 #endif
522 printf("IOCTL_DISK_GET_DRIVE_LAYOUT\n"
523 "Partitions: %lu Signature: 0x%08lx\n",
524 LayoutBuffer.Info->PartitionCount,
525 LayoutBuffer.Info->Signature);
526
527 for (i = 0; i < LayoutBuffer.Info->PartitionCount; i++)
528 {
529 pPartInfo = &LayoutBuffer.Info->PartitionEntry[i];
530
531 printf(" %ld: nr: %ld boot: %1x type: 0x%x (%s) start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
532 i,
533 pPartInfo->PartitionNumber,
534 pPartInfo->BootIndicator,
535 pPartInfo->PartitionType,
536 pPartInfo->RecognizedPartition ? "Recognized" : "Not recognized",
537 pPartInfo->StartingOffset.QuadPart,
538 pPartInfo->PartitionLength.QuadPart,
539 pPartInfo->HiddenSectors);
540 }
541 }
542 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.Info);
543
544
545 /*
546 * Retrieve the extended partition layout
547 */
548 printf("\n");
549
550 /* Allocate a layout buffer with initially 4 partition entries (or 16 for NEC PC-98) */
551 BufferSize = DRIVE_LAYOUT_INFOEX_SIZE(IsNEC_98 ? 16 : 4);
552 LayoutBuffer.InfoEx = RtlAllocateHeap(RtlGetProcessHeap(),
553 HEAP_ZERO_MEMORY,
554 BufferSize);
555 if (!LayoutBuffer.InfoEx)
556 {
557 printf("Out of memory!");
558 goto Quit;
559 }
560
561 /*
562 * Keep looping while the drive layout buffer is too small.
563 * Iosb.Information or PartitionCount only contain actual info only
564 * once NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) succeeds.
565 */
566 for (;;)
567 {
568 Status = NtDeviceIoControlFile(hDisk,
569 NULL,
570 NULL,
571 NULL,
572 &Iosb,
573 IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
574 NULL,
575 0,
576 LayoutBuffer.InfoEx,
577 BufferSize);
578 if (NT_SUCCESS(Status))
579 {
580 /* We succeeded; compactify the layout structure but keep the
581 * number of partition entries rounded up to a multiple of 4. */
582 #if 1
583 BufferSize = DRIVE_LAYOUT_INFOEX_SIZE(ROUND_UP_NUM(LayoutBuffer.InfoEx->PartitionCount, 4));
584 #else
585 BufferSize = (ULONG)Iosb.Information;
586 #endif
587 ptr = RtlReAllocateHeap(RtlGetProcessHeap(),
588 HEAP_REALLOC_IN_PLACE_ONLY,
589 LayoutBuffer.InfoEx, BufferSize);
590 if (!ptr)
591 {
592 printf("Compactification failed; keeping original structure.\n");
593 }
594 else
595 {
596 LayoutBuffer.InfoEx = ptr;
597 }
598 Status = STATUS_SUCCESS;
599 break;
600 }
601
602 if (Status != STATUS_BUFFER_TOO_SMALL)
603 {
604 printf("NtDeviceIoControlFile(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) failed! (Status 0x%lx)\n", Status);
605
606 /* Bail out if any other error than "invalid function" has been emitted */
607 if (Status != STATUS_INVALID_DEVICE_REQUEST)
608 {
609 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.InfoEx);
610 goto Quit;
611 }
612 else
613 {
614 /* Just stop getting this information */
615 break;
616 }
617 }
618
619 /* Reallocate the buffer by chunks of 4 entries */
620 BufferSize += 4 * DRIVE_LAYOUT_INFOEX_ENTRY_SIZE;
621 ptr = RtlReAllocateHeap(RtlGetProcessHeap(),
622 HEAP_ZERO_MEMORY,
623 LayoutBuffer.InfoEx, BufferSize);
624 if (!ptr)
625 {
626 printf("Out of memory!");
627 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.InfoEx);
628 goto Quit;
629 }
630 LayoutBuffer.InfoEx = ptr;
631 }
632
633 if (Status == STATUS_SUCCESS)
634 {
635 #ifdef DUMP_DATA
636 HexDump(LayoutBuffer.InfoEx, (ULONG)Iosb.Information);
637 #endif
638 printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n"
639 "PartitionStyle: %lu [%s]\n",
640 LayoutBuffer.InfoEx->PartitionStyle,
641 PARTITION_STYLE_NAME(LayoutBuffer.InfoEx->PartitionStyle));
642
643 if (LayoutBuffer.InfoEx->PartitionStyle == PARTITION_STYLE_MBR)
644 {
645 printf("Partitions: %lu Signature: 0x%08lx",
646 LayoutBuffer.InfoEx->PartitionCount,
647 LayoutBuffer.InfoEx->Mbr.Signature);
648 #if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
649 printf(" Checksum 0x%08lx\n",
650 LayoutBuffer.InfoEx->Mbr.CheckSum);
651 #else
652 printf("\n");
653 #endif
654
655 for (i = 0; i < LayoutBuffer.InfoEx->PartitionCount; i++)
656 {
657 pPartInfoEx = &LayoutBuffer.InfoEx->PartitionEntry[i];
658
659 printf(" %ld: nr: %ld [%s] boot: %1x type: 0x%x (%s) start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
660 i,
661 pPartInfoEx->PartitionNumber,
662 PARTITION_STYLE_NAME(pPartInfoEx->PartitionStyle),
663 pPartInfoEx->Mbr.BootIndicator,
664 pPartInfoEx->Mbr.PartitionType,
665 pPartInfoEx->Mbr.RecognizedPartition ? "Recognized" : "Not recognized",
666 pPartInfoEx->StartingOffset.QuadPart,
667 pPartInfoEx->PartitionLength.QuadPart,
668 pPartInfoEx->Mbr.HiddenSectors);
669 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
670 printf(" PartitionId: {" GUID_FORMAT_STR "}\n",
671 GUID_ELEMENTS(&pPartInfoEx->Mbr.PartitionId));
672 #endif
673 }
674 }
675 else if (LayoutBuffer.InfoEx->PartitionStyle == PARTITION_STYLE_GPT)
676 {
677 printf("Partitions: %lu MaxPartitionCount: %lu\n"
678 "DiskId: {" GUID_FORMAT_STR "}\n"
679 "StartingUsableOffset: 0x%016I64x UsableLength: 0x%016I64x\n",
680 LayoutBuffer.InfoEx->PartitionCount,
681 LayoutBuffer.InfoEx->Gpt.MaxPartitionCount,
682 GUID_ELEMENTS(&LayoutBuffer.InfoEx->Gpt.DiskId),
683 LayoutBuffer.InfoEx->Gpt.StartingUsableOffset.QuadPart,
684 LayoutBuffer.InfoEx->Gpt.UsableLength.QuadPart);
685
686 for (i = 0; i < LayoutBuffer.InfoEx->PartitionCount; i++)
687 {
688 pPartInfoEx = &LayoutBuffer.InfoEx->PartitionEntry[i];
689
690 printf(" %ld: nr: %ld [%s]\n"
691 " type : {" GUID_FORMAT_STR "}\n"
692 " id : {" GUID_FORMAT_STR "}\n"
693 " attrs: 0x%016I64x\n"
694 " name : '%.*S'\n"
695 " start: 0x%016I64x count: 0x%016I64x\n",
696 i,
697 pPartInfoEx->PartitionNumber,
698 PARTITION_STYLE_NAME(pPartInfoEx->PartitionStyle),
699 GUID_ELEMENTS(&pPartInfoEx->Gpt.PartitionType),
700 GUID_ELEMENTS(&pPartInfoEx->Gpt.PartitionId),
701 pPartInfoEx->Gpt.Attributes,
702 (int)_countof(pPartInfoEx->Gpt.Name),
703 pPartInfoEx->Gpt.Name,
704 pPartInfoEx->StartingOffset.QuadPart,
705 pPartInfoEx->PartitionLength.QuadPart);
706 }
707 }
708 }
709 RtlFreeHeap(RtlGetProcessHeap(), 0, LayoutBuffer.InfoEx);
710
711 Quit:
712 CloseHandle(hDisk);
713 return 0;
714 }
715