From 878186b0c5672f557437a6d93412d75946c45e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Thu, 26 Nov 2020 03:15:32 +0100 Subject: [PATCH] [ROSAPPS:PARTINFO] Implement display of IOCTL_DISK_GET_DRIVE_LAYOUT_EX info, for both MBR and GPT disks. --- .../sysutils/utils/partinfo/partinfo.c | 311 +++++++++++++++--- 1 file changed, 265 insertions(+), 46 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 #include @@ -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); + + /* 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(LayoutBufferEx, dwRead); +#endif + + printf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX\n" + "PartitionStyle: [%s]\n", + PARTITION_STYLE_NAME(LayoutBufferEx->PartitionStyle)); + + 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); + + 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); + } + } + + free(LayoutBufferEx); + } CloseHandle(hDisk); -#ifdef DUMP_DATA - HexDump(LayoutBuffer, dwRead); -#endif - - printf("Partitions %lu Signature %lx\n", - LayoutBuffer->PartitionCount, - LayoutBuffer->Signature); - - 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); - } - - free(LayoutBuffer); - - // TODO: Retrieve the extended partition layout - return 0; }