https://git.reactos.org/?p=reactos.git;a=commitdiff;h=878186b0c5672f557437a…
commit 878186b0c5672f557437a6d93412d75946c45e58
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu Nov 26 03:15:32 2020 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Thu Nov 26 03:33:40 2020 +0100
[ROSAPPS:PARTINFO] Implement display of IOCTL_DISK_GET_DRIVE_LAYOUT_EX info, for both
MBR and GPT disks.
---
.../sysutils/utils/partinfo/partinfo.c | 299 ++++++++++++++++++---
1 file changed, 259 insertions(+), 40 deletions(-)
diff --git a/modules/rosapps/applications/sysutils/utils/partinfo/partinfo.c
b/modules/rosapps/applications/sysutils/utils/partinfo/partinfo.c
index 7d72e8cbacd..e1067bcd84e 100644
--- a/modules/rosapps/applications/sysutils/utils/partinfo/partinfo.c
+++ b/modules/rosapps/applications/sysutils/utils/partinfo/partinfo.c
@@ -1,7 +1,13 @@
/*
- * partinfo - partition info program
+ * PROJECT: ReactOS Partition Information Tool
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Displays disk and partition information for MBR and GPT disks.
+ * COPYRIGHT: Copyright 2001-2002 Eric Kohl
+ * Copyright 2020 Hermes Belusca-Maito
*/
+/* INCLUDES *****************************************************************/
+
#include <stdio.h>
#include <stdlib.h>
@@ -12,6 +18,24 @@
// #define DUMP_DATA
#define DUMP_SIZE_INFO
+
+/* FORMATTING HELPERS *******************************************************/
+
+static PCSTR PartitionStyleNames[] = {"MBR", "GPT", "RAW",
"Unknown"};
+#define PARTITION_STYLE_NAME(PartStyle) \
+ ( ((PartStyle) <= PARTITION_STYLE_RAW) \
+ ? PartitionStyleNames[(PartStyle)] \
+ : PartitionStyleNames[_countof(PartitionStyleNames)-1] )
+
+#define GUID_FORMAT_STR "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+#define GUID_ELEMENTS(Guid) \
+ (Guid)->Data1, (Guid)->Data2, (Guid)->Data3, \
+ (Guid)->Data4[0], (Guid)->Data4[1], (Guid)->Data4[2], (Guid)->Data4[3],
\
+ (Guid)->Data4[4], (Guid)->Data4[5], (Guid)->Data4[6], (Guid)->Data4[7]
+
+
+/* FUNCTIONS ****************************************************************/
+
#ifdef DUMP_DATA
void HexDump(
IN PVOID buffer,
@@ -54,11 +78,16 @@ int main(int argc, char *argv[])
ULONG ulDrive;
HANDLE hDisk;
DWORD dwRead;
+ DWORD dwLastError;
DWORD i;
SYSTEM_DEVICE_INFORMATION DeviceInfo;
DISK_GEOMETRY DiskGeometry;
+ ULONG BufferSize;
PDRIVE_LAYOUT_INFORMATION LayoutBuffer;
- CHAR DriveName[40];
+ PDRIVE_LAYOUT_INFORMATION_EX LayoutBufferEx;
+ PVOID ptr;
+ GUID Guid;
+ WCHAR DriveName[40];
if (argc != 2)
{
@@ -82,7 +111,7 @@ int main(int argc, char *argv[])
&i);
if (!NT_SUCCESS(Status))
{
- printf("NtQuerySystemInformation() failed (Status %lx)\n", Status);
+ printf("NtQuerySystemInformation() failed (Status 0x%lx)\n", Status);
return 0;
}
if (DeviceInfo.NumberOfDisks == 0)
@@ -93,16 +122,16 @@ int main(int argc, char *argv[])
if (ulDrive >= DeviceInfo.NumberOfDisks)
{
- printf("Invalid disk drive number! Valid drive numbers [0-%lu]\n",
+ printf("Invalid disk drive number! Valid drive numbers: [0-%lu]\n",
DeviceInfo.NumberOfDisks-1);
return 0;
}
/* Build the full drive name */
- sprintf(DriveName, "\\\\.\\PHYSICALDRIVE%lu", ulDrive);
+ swprintf(DriveName, L"\\\\.\\PHYSICALDRIVE%lu", ulDrive);
/* Open the drive */
- hDisk = CreateFileA(DriveName,
+ hDisk = CreateFileW(DriveName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
@@ -111,10 +140,11 @@ int main(int argc, char *argv[])
NULL);
if (hDisk == INVALID_HANDLE_VALUE)
{
- printf("Invalid disk handle!");
+ printf("Could not open drive!");
return 0;
}
+
/*
* Get the drive geometry.
*/
@@ -136,8 +166,10 @@ int main(int argc, char *argv[])
#ifdef DUMP_DATA
HexDump(&DiskGeometry, dwRead);
#endif
- printf("Drive number: %lu\n", ulDrive);
- printf("Cylinders: %I64u\nMediaType: %x\nTracksPerCylinder: %lu\n"
+ printf("Drive number: %lu\n\n", ulDrive);
+
+ printf("IOCTL_DISK_GET_DRIVE_GEOMETRY\n"
+ "Cylinders: %I64u\nMediaType: %x\nTracksPerCylinder: %lu\n"
"SectorsPerTrack: %lu\nBytesPerSector: %lu\n\n",
DiskGeometry.Cylinders.QuadPart,
DiskGeometry.MediaType,
@@ -150,58 +182,245 @@ int main(int argc, char *argv[])
// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX
#endif
+
/*
* Retrieve the legacy partition layout
*/
- LayoutBuffer = (PDRIVE_LAYOUT_INFORMATION)malloc(8192);
- if (LayoutBuffer == NULL)
+
+ /* Allocate a layout buffer with 4 partition entries first */
+ BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
+ ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
+ LayoutBuffer = malloc(BufferSize);
+ if (!LayoutBuffer)
{
printf("Out of memory!");
CloseHandle(hDisk);
return 0;
}
- memset(LayoutBuffer, 0, 8192);
+ memset(LayoutBuffer, 0, BufferSize);
- if (!DeviceIoControl(hDisk,
- IOCTL_DISK_GET_DRIVE_LAYOUT,
- NULL,
- 0,
- LayoutBuffer,
- 8192,
- &dwRead,
- NULL))
+ /* Keep looping while the drive layout buffer is too small */
+ for (;;)
{
- printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT) failed! Error:
%lu\n",
- GetLastError());
- CloseHandle(hDisk);
+ if (DeviceIoControl(hDisk,
+ IOCTL_DISK_GET_DRIVE_LAYOUT,
+ NULL,
+ 0,
+ LayoutBuffer,
+ BufferSize,
+ &dwRead,
+ NULL))
+ {
+ dwLastError = ERROR_SUCCESS;
+ break;
+ }
+
+ dwLastError = GetLastError();
+ if (dwLastError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT) failed! Error:
%lu\n",
+ dwLastError);
+
+ /* Bail out if any other error than "invalid function" has been
emitted.
+ * This happens for example when calling it on GPT disks. */
+ if (dwLastError != ERROR_INVALID_FUNCTION)
+ {
+ free(LayoutBuffer);
+ CloseHandle(hDisk);
+ return 0;
+ }
+ else
+ {
+ /* Just stop getting this information */
+ break;
+ }
+ }
+
+ /* Reallocate the buffer */
+ BufferSize += 4 * sizeof(PARTITION_INFORMATION);
+ ptr = realloc(LayoutBuffer, BufferSize);
+ if (!ptr)
+ {
+ printf("Out of memory!");
+ free(LayoutBuffer);
+ CloseHandle(hDisk);
+ return 0;
+ }
+ LayoutBuffer = ptr;
+ memset(LayoutBuffer, 0, BufferSize);
+ }
+
+ if (dwLastError == ERROR_SUCCESS)
+ {
+#ifdef DUMP_DATA
+ HexDump(LayoutBuffer, dwRead);
+#endif
+
+ printf("IOCTL_DISK_GET_DRIVE_LAYOUT\n"
+ "Partitions: %lu Signature: 0x%08lx\n",
+ LayoutBuffer->PartitionCount,
+ LayoutBuffer->Signature);
+
+ for (i = 0; i < LayoutBuffer->PartitionCount; i++)
+ {
+ printf(" %ld: nr: %ld boot: %1x type: %x start: 0x%016I64x count:
0x%016I64x hidden: 0x%lx\n",
+ i,
+ LayoutBuffer->PartitionEntry[i].PartitionNumber,
+ LayoutBuffer->PartitionEntry[i].BootIndicator,
+ LayoutBuffer->PartitionEntry[i].PartitionType,
+ LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart,
+ LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart,
+ LayoutBuffer->PartitionEntry[i].HiddenSectors);
+ }
+
free(LayoutBuffer);
+ }
+
+
+ /*
+ * Retrieve the extended partition layout
+ */
+ printf("\n");
+
+ /* Allocate a layout buffer with 4 partition entries first */
+ BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
+ ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX));
+ LayoutBufferEx = malloc(BufferSize);
+ if (!LayoutBufferEx)
+ {
+ printf("Out of memory!");
+ CloseHandle(hDisk);
return 0;
}
+ memset(LayoutBufferEx, 0, BufferSize);
- CloseHandle(hDisk);
+ /* Keep looping while the drive layout buffer is too small */
+ for (;;)
+ {
+ if (DeviceIoControl(hDisk,
+ IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
+ NULL,
+ 0,
+ LayoutBufferEx,
+ BufferSize,
+ &dwRead,
+ NULL))
+ {
+ dwLastError = ERROR_SUCCESS;
+ break;
+ }
+ dwLastError = GetLastError();
+ if (dwLastError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ printf("DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) failed! Error:
%lu\n",
+ dwLastError);
+
+ /* Bail out if any other error than "invalid function" has been
emitted */
+ if (dwLastError != ERROR_INVALID_FUNCTION)
+ {
+ free(LayoutBufferEx);
+ CloseHandle(hDisk);
+ return 0;
+ }
+ else
+ {
+ /* Just stop getting this information */
+ break;
+ }
+ }
+
+ /* Reallocate the buffer */
+ BufferSize += 4 * sizeof(PARTITION_INFORMATION_EX);
+ ptr = realloc(LayoutBufferEx, BufferSize);
+ if (!ptr)
+ {
+ printf("Out of memory!");
+ free(LayoutBufferEx);
+ CloseHandle(hDisk);
+ return 0;
+ }
+ LayoutBufferEx = ptr;
+ memset(LayoutBufferEx, 0, BufferSize);
+ }
+
+ if (dwLastError == ERROR_SUCCESS)
+ {
#ifdef DUMP_DATA
- HexDump(LayoutBuffer, dwRead);
+ HexDump(LayoutBufferEx, dwRead);
#endif
- printf("Partitions %lu Signature %lx\n",
- LayoutBuffer->PartitionCount,
- LayoutBuffer->Signature);
+ printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n"
+ "PartitionStyle: [%s]\n",
+ PARTITION_STYLE_NAME(LayoutBufferEx->PartitionStyle));
- for (i = 0; i < LayoutBuffer->PartitionCount; i++)
- {
- printf(" %ld: nr: %ld boot: %1x type: %x start: 0x%I64x count:
0x%I64x\n",
- i,
- LayoutBuffer->PartitionEntry[i].PartitionNumber,
- LayoutBuffer->PartitionEntry[i].BootIndicator,
- LayoutBuffer->PartitionEntry[i].PartitionType,
- LayoutBuffer->PartitionEntry[i].StartingOffset.QuadPart,
- LayoutBuffer->PartitionEntry[i].PartitionLength.QuadPart);
- }
+ if (LayoutBufferEx->PartitionStyle == PARTITION_STYLE_MBR)
+ {
+ printf("Partitions: %lu Signature: 0x%08lx",
+ LayoutBufferEx->PartitionCount,
+ LayoutBufferEx->Mbr.Signature);
+#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
+ printf(" Checksum 0x%08lx\n",
+ LayoutBufferEx->Mbr.CheckSum);
+#else
+ printf("\n");
+#endif
+
+ for (i = 0; i < LayoutBufferEx->PartitionCount; i++)
+ {
+ printf(" %ld: nr: %ld [%s] boot: %1x type: %x start: 0x%016I64x
count: 0x%016I64x hidden: 0x%lx\n",
+ i,
+ LayoutBufferEx->PartitionEntry[i].PartitionNumber,
+
PARTITION_STYLE_NAME(LayoutBufferEx->PartitionEntry[i].PartitionStyle),
+ LayoutBufferEx->PartitionEntry[i].Mbr.BootIndicator,
+ LayoutBufferEx->PartitionEntry[i].Mbr.PartitionType,
+ LayoutBufferEx->PartitionEntry[i].StartingOffset.QuadPart,
+ LayoutBufferEx->PartitionEntry[i].PartitionLength.QuadPart,
+ LayoutBufferEx->PartitionEntry[i].Mbr.HiddenSectors);
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
+ Guid = LayoutBufferEx->PartitionEntry[i].Mbr.PartitionId;
+ printf(" PartitionId: {" GUID_FORMAT_STR "}\n",
+ GUID_ELEMENTS(&Guid));
+#endif
+ }
+ }
+ else if (LayoutBufferEx->PartitionStyle == PARTITION_STYLE_GPT)
+ {
+ Guid = LayoutBufferEx->Gpt.DiskId;
+ printf("Partitions: %lu MaxPartitionCount: %lu\n"
+ "DiskId: {" GUID_FORMAT_STR "}\n"
+ "StartingUsableOffset: 0x%016I64x UsableLength:
0x%016I64x\n",
+ LayoutBufferEx->PartitionCount,
+ LayoutBufferEx->Gpt.MaxPartitionCount,
+ GUID_ELEMENTS(&Guid),
+ LayoutBufferEx->Gpt.StartingUsableOffset.QuadPart,
+ LayoutBufferEx->Gpt.UsableLength.QuadPart);
- free(LayoutBuffer);
+ for (i = 0; i < LayoutBufferEx->PartitionCount; i++)
+ {
+ printf(" %ld: nr: %ld [%s]\n"
+ " type : {" GUID_FORMAT_STR "}\n"
+ " id : {" GUID_FORMAT_STR "}\n"
+ " attrs: 0x%016I64x\n"
+ " name : '%.*S'\n"
+ " start: 0x%016I64x count: 0x%016I64x\n",
+ i,
+ LayoutBufferEx->PartitionEntry[i].PartitionNumber,
+
PARTITION_STYLE_NAME(LayoutBufferEx->PartitionEntry[i].PartitionStyle),
+
GUID_ELEMENTS(&LayoutBufferEx->PartitionEntry[i].Gpt.PartitionType),
+
GUID_ELEMENTS(&LayoutBufferEx->PartitionEntry[i].Gpt.PartitionId),
+ LayoutBufferEx->PartitionEntry[i].Gpt.Attributes,
+ _countof(LayoutBufferEx->PartitionEntry[i].Gpt.Name),
+ LayoutBufferEx->PartitionEntry[i].Gpt.Name,
+ LayoutBufferEx->PartitionEntry[i].StartingOffset.QuadPart,
+ LayoutBufferEx->PartitionEntry[i].PartitionLength.QuadPart);
+ }
+ }
- // TODO: Retrieve the extended partition layout
+ free(LayoutBufferEx);
+ }
+
+ CloseHandle(hDisk);
return 0;
}