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 Hermes Belusca-Maito
9 /* INCLUDES *****************************************************************/
14 #define WIN32_NO_STATUS
19 #define DUMP_SIZE_INFO
22 /* FORMATTING HELPERS *******************************************************/
24 static PCSTR PartitionStyleNames
[] = {"MBR", "GPT", "RAW", "Unknown"};
25 #define PARTITION_STYLE_NAME(PartStyle) \
26 ( ((PartStyle) <= PARTITION_STYLE_RAW) \
27 ? PartitionStyleNames[(PartStyle)] \
28 : PartitionStyleNames[_countof(PartitionStyleNames)-1] )
30 #define GUID_FORMAT_STR "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
31 #define GUID_ELEMENTS(Guid) \
32 (Guid)->Data1, (Guid)->Data2, (Guid)->Data3, \
33 (Guid)->Data4[0], (Guid)->Data4[1], (Guid)->Data4[2], (Guid)->Data4[3], \
34 (Guid)->Data4[4], (Guid)->Data4[5], (Guid)->Data4[6], (Guid)->Data4[7]
37 /* FUNCTIONS ****************************************************************/
47 while (offset
< (size
& ~15))
49 ptr
= (PUCHAR
)((ULONG_PTR
)buffer
+ offset
);
50 printf("%08lx %02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx-%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx\n",
52 ptr
[0], ptr
[1], ptr
[2] , ptr
[3] , ptr
[4] , ptr
[5] , ptr
[6] , ptr
[7],
53 ptr
[8], ptr
[9], ptr
[10], ptr
[11], ptr
[12], ptr
[13], ptr
[14], ptr
[15]);
57 ptr
= (PUCHAR
)((ULONG_PTR
)buffer
+ offset
);
58 printf("%08lx ", offset
);
61 printf(" %02hx", *ptr
);
72 puts("Usage: partinfo <drive number>");
75 int main(int argc
, char *argv
[])
83 SYSTEM_DEVICE_INFORMATION DeviceInfo
;
84 DISK_GEOMETRY DiskGeometry
;
86 PDRIVE_LAYOUT_INFORMATION LayoutBuffer
;
87 PDRIVE_LAYOUT_INFORMATION_EX LayoutBufferEx
;
98 ulDrive
= strtoul(argv
[1], NULL
, 10);
101 printf("Error: Malformed drive number\n");
106 * Retrieve the number of disks on the system.
108 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
112 if (!NT_SUCCESS(Status
))
114 printf("NtQuerySystemInformation() failed (Status 0x%lx)\n", Status
);
117 if (DeviceInfo
.NumberOfDisks
== 0)
119 printf("No disk drive installed!\n");
123 if (ulDrive
>= DeviceInfo
.NumberOfDisks
)
125 printf("Invalid disk drive number! Valid drive numbers: [0-%lu]\n",
126 DeviceInfo
.NumberOfDisks
-1);
130 /* Build the full drive name */
131 swprintf(DriveName
, L
"\\\\.\\PHYSICALDRIVE%lu", ulDrive
);
134 hDisk
= CreateFileW(DriveName
,
136 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
141 if (hDisk
== INVALID_HANDLE_VALUE
)
143 printf("Could not open drive!");
149 * Get the drive geometry.
151 if (!DeviceIoControl(hDisk
,
152 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
156 sizeof(DiskGeometry
),
160 printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY) failed! Error: %lu\n",
167 HexDump(&DiskGeometry
, dwRead
);
169 printf("Drive number: %lu\n\n", ulDrive
);
171 printf("IOCTL_DISK_GET_DRIVE_GEOMETRY\n"
172 "Cylinders: %I64u\nMediaType: %x\nTracksPerCylinder: %lu\n"
173 "SectorsPerTrack: %lu\nBytesPerSector: %lu\n\n",
174 DiskGeometry
.Cylinders
.QuadPart
,
175 DiskGeometry
.MediaType
,
176 DiskGeometry
.TracksPerCylinder
,
177 DiskGeometry
.SectorsPerTrack
,
178 DiskGeometry
.BytesPerSector
);
181 /* Get extended drive geometry */
182 // IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
187 * Retrieve the legacy partition layout
190 /* Allocate a layout buffer with 4 partition entries first */
191 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION
) +
192 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION
));
193 LayoutBuffer
= malloc(BufferSize
);
196 printf("Out of memory!");
200 memset(LayoutBuffer
, 0, BufferSize
);
202 /* Keep looping while the drive layout buffer is too small */
205 if (DeviceIoControl(hDisk
,
206 IOCTL_DISK_GET_DRIVE_LAYOUT
,
214 dwLastError
= ERROR_SUCCESS
;
218 dwLastError
= GetLastError();
219 if (dwLastError
!= ERROR_INSUFFICIENT_BUFFER
)
221 printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT) failed! Error: %lu\n",
224 /* Bail out if any other error than "invalid function" has been emitted.
225 * This happens for example when calling it on GPT disks. */
226 if (dwLastError
!= ERROR_INVALID_FUNCTION
)
234 /* Just stop getting this information */
239 /* Reallocate the buffer */
240 BufferSize
+= 4 * sizeof(PARTITION_INFORMATION
);
241 ptr
= realloc(LayoutBuffer
, BufferSize
);
244 printf("Out of memory!");
250 memset(LayoutBuffer
, 0, BufferSize
);
253 if (dwLastError
== ERROR_SUCCESS
)
256 HexDump(LayoutBuffer
, dwRead
);
259 printf("IOCTL_DISK_GET_DRIVE_LAYOUT\n"
260 "Partitions: %lu Signature: 0x%08lx\n",
261 LayoutBuffer
->PartitionCount
,
262 LayoutBuffer
->Signature
);
264 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
++)
266 printf(" %ld: nr: %ld boot: %1x type: %x start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
268 LayoutBuffer
->PartitionEntry
[i
].PartitionNumber
,
269 LayoutBuffer
->PartitionEntry
[i
].BootIndicator
,
270 LayoutBuffer
->PartitionEntry
[i
].PartitionType
,
271 LayoutBuffer
->PartitionEntry
[i
].StartingOffset
.QuadPart
,
272 LayoutBuffer
->PartitionEntry
[i
].PartitionLength
.QuadPart
,
273 LayoutBuffer
->PartitionEntry
[i
].HiddenSectors
);
281 * Retrieve the extended partition layout
285 /* Allocate a layout buffer with 4 partition entries first */
286 BufferSize
= sizeof(DRIVE_LAYOUT_INFORMATION_EX
) +
287 ((4 - ANYSIZE_ARRAY
) * sizeof(PARTITION_INFORMATION_EX
));
288 LayoutBufferEx
= malloc(BufferSize
);
291 printf("Out of memory!");
295 memset(LayoutBufferEx
, 0, BufferSize
);
297 /* Keep looping while the drive layout buffer is too small */
300 if (DeviceIoControl(hDisk
,
301 IOCTL_DISK_GET_DRIVE_LAYOUT_EX
,
309 dwLastError
= ERROR_SUCCESS
;
313 dwLastError
= GetLastError();
314 if (dwLastError
!= ERROR_INSUFFICIENT_BUFFER
)
316 printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) failed! Error: %lu\n",
319 /* Bail out if any other error than "invalid function" has been emitted */
320 if (dwLastError
!= ERROR_INVALID_FUNCTION
)
322 free(LayoutBufferEx
);
328 /* Just stop getting this information */
333 /* Reallocate the buffer */
334 BufferSize
+= 4 * sizeof(PARTITION_INFORMATION_EX
);
335 ptr
= realloc(LayoutBufferEx
, BufferSize
);
338 printf("Out of memory!");
339 free(LayoutBufferEx
);
343 LayoutBufferEx
= ptr
;
344 memset(LayoutBufferEx
, 0, BufferSize
);
347 if (dwLastError
== ERROR_SUCCESS
)
350 HexDump(LayoutBufferEx
, dwRead
);
353 printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n"
354 "PartitionStyle: [%s]\n",
355 PARTITION_STYLE_NAME(LayoutBufferEx
->PartitionStyle
));
357 if (LayoutBufferEx
->PartitionStyle
== PARTITION_STYLE_MBR
)
359 printf("Partitions: %lu Signature: 0x%08lx",
360 LayoutBufferEx
->PartitionCount
,
361 LayoutBufferEx
->Mbr
.Signature
);
362 #if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
363 printf(" Checksum 0x%08lx\n",
364 LayoutBufferEx
->Mbr
.CheckSum
);
369 for (i
= 0; i
< LayoutBufferEx
->PartitionCount
; i
++)
371 printf(" %ld: nr: %ld [%s] boot: %1x type: %x start: 0x%016I64x count: 0x%016I64x hidden: 0x%lx\n",
373 LayoutBufferEx
->PartitionEntry
[i
].PartitionNumber
,
374 PARTITION_STYLE_NAME(LayoutBufferEx
->PartitionEntry
[i
].PartitionStyle
),
375 LayoutBufferEx
->PartitionEntry
[i
].Mbr
.BootIndicator
,
376 LayoutBufferEx
->PartitionEntry
[i
].Mbr
.PartitionType
,
377 LayoutBufferEx
->PartitionEntry
[i
].StartingOffset
.QuadPart
,
378 LayoutBufferEx
->PartitionEntry
[i
].PartitionLength
.QuadPart
,
379 LayoutBufferEx
->PartitionEntry
[i
].Mbr
.HiddenSectors
);
380 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
381 Guid
= LayoutBufferEx
->PartitionEntry
[i
].Mbr
.PartitionId
;
382 printf(" PartitionId: {" GUID_FORMAT_STR
"}\n",
383 GUID_ELEMENTS(&Guid
));
387 else if (LayoutBufferEx
->PartitionStyle
== PARTITION_STYLE_GPT
)
389 Guid
= LayoutBufferEx
->Gpt
.DiskId
;
390 printf("Partitions: %lu MaxPartitionCount: %lu\n"
391 "DiskId: {" GUID_FORMAT_STR
"}\n"
392 "StartingUsableOffset: 0x%016I64x UsableLength: 0x%016I64x\n",
393 LayoutBufferEx
->PartitionCount
,
394 LayoutBufferEx
->Gpt
.MaxPartitionCount
,
395 GUID_ELEMENTS(&Guid
),
396 LayoutBufferEx
->Gpt
.StartingUsableOffset
.QuadPart
,
397 LayoutBufferEx
->Gpt
.UsableLength
.QuadPart
);
399 for (i
= 0; i
< LayoutBufferEx
->PartitionCount
; i
++)
401 printf(" %ld: nr: %ld [%s]\n"
402 " type : {" GUID_FORMAT_STR
"}\n"
403 " id : {" GUID_FORMAT_STR
"}\n"
404 " attrs: 0x%016I64x\n"
406 " start: 0x%016I64x count: 0x%016I64x\n",
408 LayoutBufferEx
->PartitionEntry
[i
].PartitionNumber
,
409 PARTITION_STYLE_NAME(LayoutBufferEx
->PartitionEntry
[i
].PartitionStyle
),
410 GUID_ELEMENTS(&LayoutBufferEx
->PartitionEntry
[i
].Gpt
.PartitionType
),
411 GUID_ELEMENTS(&LayoutBufferEx
->PartitionEntry
[i
].Gpt
.PartitionId
),
412 LayoutBufferEx
->PartitionEntry
[i
].Gpt
.Attributes
,
413 _countof(LayoutBufferEx
->PartitionEntry
[i
].Gpt
.Name
),
414 LayoutBufferEx
->PartitionEntry
[i
].Gpt
.Name
,
415 LayoutBufferEx
->PartitionEntry
[i
].StartingOffset
.QuadPart
,
416 LayoutBufferEx
->PartitionEntry
[i
].PartitionLength
.QuadPart
);
420 free(LayoutBufferEx
);