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 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 107 void Usage(void) 108 { 109 puts("Usage: partinfo <drive number>"); 110 } 111 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