From d39657cfe034df96df812a0b0d7cc9362a781c8a Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Wed, 24 Dec 2025 15:03:34 +0100 Subject: [PATCH] [VFATLIB] Add GPT partition support --- sdk/lib/fslib/vfatlib/fat12.c | 4 +- sdk/lib/fslib/vfatlib/fat16.c | 4 +- sdk/lib/fslib/vfatlib/fat32.c | 4 +- sdk/lib/fslib/vfatlib/vfatlib.c | 165 ++++++++++++++++++++------------ sdk/lib/fslib/vfatlib/vfatlib.h | 15 ++- 5 files changed, 122 insertions(+), 70 deletions(-) diff --git a/sdk/lib/fslib/vfatlib/fat12.c b/sdk/lib/fslib/vfatlib/fat12.c index 1668fc4670e..f5056fd4195 100644 --- a/sdk/lib/fslib/vfatlib/fat12.c +++ b/sdk/lib/fslib/vfatlib/fat12.c @@ -237,7 +237,7 @@ done: NTSTATUS Fat12Format(IN HANDLE FileHandle, - IN PPARTITION_INFORMATION PartitionInfo, + IN PPARTITION_INFORMATION_EX PartitionInfo, IN PDISK_GEOMETRY DiskGeometry, IN PUNICODE_STRING Label, IN BOOLEAN QuickFormat, @@ -289,7 +289,7 @@ Fat12Format(IN HANDLE FileHandle, BootSector.FATSectors = 0; /* Set later. See below. */ BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack; BootSector.Heads = DiskGeometry->TracksPerCylinder; - BootSector.HiddenSectors = PartitionInfo->HiddenSectors; + BootSector.HiddenSectors = (PartitionInfo->PartitionStyle == PARTITION_STYLE_MBR) ? PartitionInfo->Mbr.HiddenSectors : 0; BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0; BootSector.Drive = (DiskGeometry->MediaType == FixedMedia) ? 0x80 : 0x00; BootSector.ExtBootSignature = 0x29; diff --git a/sdk/lib/fslib/vfatlib/fat16.c b/sdk/lib/fslib/vfatlib/fat16.c index ac383115471..e293cff48de 100644 --- a/sdk/lib/fslib/vfatlib/fat16.c +++ b/sdk/lib/fslib/vfatlib/fat16.c @@ -236,7 +236,7 @@ done: NTSTATUS Fat16Format(IN HANDLE FileHandle, - IN PPARTITION_INFORMATION PartitionInfo, + IN PPARTITION_INFORMATION_EX PartitionInfo, IN PDISK_GEOMETRY DiskGeometry, IN PUNICODE_STRING Label, IN BOOLEAN QuickFormat, @@ -296,7 +296,7 @@ Fat16Format(IN HANDLE FileHandle, BootSector.FATSectors = 0; /* Set later. See below. */ BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack; BootSector.Heads = DiskGeometry->TracksPerCylinder; - BootSector.HiddenSectors = PartitionInfo->HiddenSectors; + BootSector.HiddenSectors = (PartitionInfo->PartitionStyle == PARTITION_STYLE_MBR) ? PartitionInfo->Mbr.HiddenSectors : 0; BootSector.SectorsHuge = (SectorCount >= 0x10000) ? (unsigned long)SectorCount : 0; BootSector.Drive = (DiskGeometry->MediaType == FixedMedia) ? 0x80 : 0x00; BootSector.ExtBootSignature = 0x29; diff --git a/sdk/lib/fslib/vfatlib/fat32.c b/sdk/lib/fslib/vfatlib/fat32.c index 4e789372d44..f1e3ace30c5 100644 --- a/sdk/lib/fslib/vfatlib/fat32.c +++ b/sdk/lib/fslib/vfatlib/fat32.c @@ -384,7 +384,7 @@ done: NTSTATUS Fat32Format(IN HANDLE FileHandle, - IN PPARTITION_INFORMATION PartitionInfo, + IN PPARTITION_INFORMATION_EX PartitionInfo, IN PDISK_GEOMETRY DiskGeometry, IN PUNICODE_STRING Label, IN BOOLEAN QuickFormat, @@ -441,7 +441,7 @@ Fat32Format(IN HANDLE FileHandle, BootSector.FATSectors = 0; BootSector.SectorsPerTrack = DiskGeometry->SectorsPerTrack; BootSector.Heads = DiskGeometry->TracksPerCylinder; - BootSector.HiddenSectors = PartitionInfo->HiddenSectors; + BootSector.HiddenSectors = (PartitionInfo->PartitionStyle == PARTITION_STYLE_MBR) ? PartitionInfo->Mbr.HiddenSectors : 0; BootSector.SectorsHuge = PartitionInfo->PartitionLength.QuadPart >> GetShiftCount(BootSector.BytesPerSector); /* Use shifting to avoid 64-bit division */ BootSector.FATSectors32 = 0; /* Set later */ diff --git a/sdk/lib/fslib/vfatlib/vfatlib.c b/sdk/lib/fslib/vfatlib/vfatlib.c index 0f2d7f07b64..d31832f863a 100644 --- a/sdk/lib/fslib/vfatlib/vfatlib.c +++ b/sdk/lib/fslib/vfatlib/vfatlib.c @@ -60,8 +60,9 @@ VfatFormat( DISK_GEOMETRY DiskGeometry; IO_STATUS_BLOCK Iosb; HANDLE FileHandle; - PARTITION_INFORMATION PartitionInfo; + PARTITION_INFORMATION_EX PartitionInfo; FORMAT_CONTEXT Context; + FAT_TYPE FatType = FAT_UNKNOWN; NTSTATUS Status, LockStatus; DPRINT("VfatFormat(DriveRoot '%wZ')\n", DriveRoot); @@ -128,94 +129,139 @@ VfatFormat( NULL, NULL, &Iosb, - IOCTL_DISK_GET_PARTITION_INFO, + IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &PartitionInfo, - sizeof(PARTITION_INFORMATION)); + sizeof(PARTITION_INFORMATION_EX)); if (!NT_SUCCESS(Status)) { - DPRINT("IOCTL_DISK_GET_PARTITION_INFO failed with status 0x%08x\n", Status); + DPRINT("IOCTL_DISK_GET_PARTITION_INFO_EX failed with status 0x%08x\n", Status); NtClose(FileHandle); return FALSE; } } else { - PartitionInfo.PartitionType = 0; + PartitionInfo.PartitionStyle = PARTITION_STYLE_MBR; + PartitionInfo.Mbr.PartitionType = 0; PartitionInfo.StartingOffset.QuadPart = 0ULL; PartitionInfo.PartitionLength.QuadPart = DiskGeometry.Cylinders.QuadPart * (ULONGLONG)DiskGeometry.TracksPerCylinder * (ULONGLONG)DiskGeometry.SectorsPerTrack * (ULONGLONG)DiskGeometry.BytesPerSector; - PartitionInfo.HiddenSectors = 0; + PartitionInfo.Mbr.HiddenSectors = 0; PartitionInfo.PartitionNumber = 0; - PartitionInfo.BootIndicator = FALSE; + PartitionInfo.Mbr.BootIndicator = FALSE; PartitionInfo.RewritePartition = FALSE; - PartitionInfo.RecognizedPartition = FALSE; + PartitionInfo.Mbr.RecognizedPartition = FALSE; } /* If it already has a FAT FS, we'll use that type. * If it doesn't, we will determine the FAT type based on size and offset */ - if (PartitionInfo.PartitionType != PARTITION_FAT_12 && - PartitionInfo.PartitionType != PARTITION_FAT_16 && - PartitionInfo.PartitionType != PARTITION_HUGE && - PartitionInfo.PartitionType != PARTITION_XINT13 && - PartitionInfo.PartitionType != PARTITION_FAT32 && - PartitionInfo.PartitionType != PARTITION_FAT32_XINT13) + + if (PartitionInfo.PartitionStyle == PARTITION_STYLE_MBR) + { + if (PartitionInfo.Mbr.PartitionType == PARTITION_FAT_12) + { + FatType = FAT_12; + } + else if (PartitionInfo.Mbr.PartitionType == PARTITION_FAT_16 || + PartitionInfo.Mbr.PartitionType == PARTITION_HUGE || + PartitionInfo.Mbr.PartitionType == PARTITION_XINT13) + { + FatType = FAT_16; + } + else if (PartitionInfo.Mbr.PartitionType == PARTITION_FAT32 || + PartitionInfo.Mbr.PartitionType == PARTITION_FAT32_XINT13) + { + FatType = FAT_32; + } + + if (FatType == FAT_UNKNOWN) + { + /* Determine the correct type based upon size and offset (copied from usetup) */ + if (PartitionInfo.PartitionLength.QuadPart < (4200LL * 1024LL)) + { + /* FAT12 CHS partition (disk is smaller than 4.1MB) */ + FatType = FAT_12; + } + else if (PartitionInfo.StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL)) + { + /* Partition starts below the 8.4GB boundary ==> CHS partition */ + + if (PartitionInfo.PartitionLength.QuadPart < (32LL * 1024LL * 1024LL)) + { + /* FAT16 CHS partition (partition size < 32MB) */ + FatType = FAT_16; + } + else if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) + { + /* FAT16 CHS partition (partition size < 512MB) */ + FatType = FAT_16; + } + else + { + /* FAT32 CHS partition (partition size >= 512MB) */ + FatType = FAT_32; + } + } + else + { + /* Partition starts above the 8.4GB boundary ==> LBA partition */ + + if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) + { + /* FAT16 LBA partition (partition size < 512MB) */ + FatType = FAT_16; + } + else + { + /* FAT32 LBA partition (partition size >= 512MB) */ + FatType = FAT_32; + } + } + } + + DPRINT("PartitionType 0x%x\n", PartitionInfo.Mbr.PartitionType); + DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); + DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); + DPRINT("HiddenSectors %lu\n", PartitionInfo.Mbr.HiddenSectors); + DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); + DPRINT("BootIndicator 0x%x\n", PartitionInfo.Mbr.BootIndicator); + DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); + DPRINT("RecognizedPartition %d\n", PartitionInfo.Mbr.RecognizedPartition); + } + else if (PartitionInfo.PartitionStyle == PARTITION_STYLE_GPT) { - /* Determine the correct type based upon size and offset (copied from usetup) */ if (PartitionInfo.PartitionLength.QuadPart < (4200LL * 1024LL)) { /* FAT12 CHS partition (disk is smaller than 4.1MB) */ - PartitionInfo.PartitionType = PARTITION_FAT_12; + FatType = FAT_12; } - else if (PartitionInfo.StartingOffset.QuadPart < (1024LL * 255LL * 63LL * 512LL)) + else if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) { - /* Partition starts below the 8.4GB boundary ==> CHS partition */ - - if (PartitionInfo.PartitionLength.QuadPart < (32LL * 1024LL * 1024LL)) - { - /* FAT16 CHS partition (partition size < 32MB) */ - PartitionInfo.PartitionType = PARTITION_FAT_16; - } - else if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) - { - /* FAT16 CHS partition (partition size < 512MB) */ - PartitionInfo.PartitionType = PARTITION_HUGE; - } - else - { - /* FAT32 CHS partition (partition size >= 512MB) */ - PartitionInfo.PartitionType = PARTITION_FAT32; - } + /* FAT16 partition (partition size < 512MB) */ + FatType = FAT_16; + } + else if (PartitionInfo.PartitionLength.QuadPart <= (32LL * 1024LL * 1024LL * 1024LL)) + { + /* FAT32 partition (partition size < 32GB) */ + FatType = FAT_32; } else { - /* Partition starts above the 8.4GB boundary ==> LBA partition */ - - if (PartitionInfo.PartitionLength.QuadPart < (512LL * 1024LL * 1024LL)) - { - /* FAT16 LBA partition (partition size < 512MB) */ - PartitionInfo.PartitionType = PARTITION_XINT13; - } - else - { - /* FAT32 LBA partition (partition size >= 512MB) */ - PartitionInfo.PartitionType = PARTITION_FAT32_XINT13; - } + DPRINT1("The partition ist too large (> 32 GB) for the FAT file system!\n"); + NtClose(FileHandle); + return FALSE; } - } - DPRINT("PartitionType 0x%x\n", PartitionInfo.PartitionType); - DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); - DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); - DPRINT("HiddenSectors %lu\n", PartitionInfo.HiddenSectors); - DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); - DPRINT("BootIndicator 0x%x\n", PartitionInfo.BootIndicator); - DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); - DPRINT("RecognizedPartition %d\n", PartitionInfo.RecognizedPartition); + DPRINT("StartingOffset %I64d\n", PartitionInfo.StartingOffset.QuadPart); + DPRINT("PartitionLength %I64d\n", PartitionInfo.PartitionLength.QuadPart); + DPRINT("PartitionNumber %d\n", PartitionInfo.PartitionNumber); + DPRINT("RewritePartition %d\n", PartitionInfo.RewritePartition); + } if (Callback != NULL) { @@ -238,7 +284,7 @@ VfatFormat( DPRINT1("WARNING: Failed to lock volume for formatting! Format may fail! (Status: 0x%x)\n", LockStatus); } - if (PartitionInfo.PartitionType == PARTITION_FAT_12) + if (FatType == FAT_12) { /* FAT12 */ Status = Fat12Format(FileHandle, @@ -249,9 +295,7 @@ VfatFormat( ClusterSize, &Context); } - else if (PartitionInfo.PartitionType == PARTITION_FAT_16 || - PartitionInfo.PartitionType == PARTITION_HUGE || - PartitionInfo.PartitionType == PARTITION_XINT13) + else if (FatType == FAT_16) { /* FAT16 */ Status = Fat16Format(FileHandle, @@ -262,8 +306,7 @@ VfatFormat( ClusterSize, &Context); } - else if (PartitionInfo.PartitionType == PARTITION_FAT32 || - PartitionInfo.PartitionType == PARTITION_FAT32_XINT13) + else if (FatType == FAT_32) { /* FAT32 */ Status = Fat32Format(FileHandle, diff --git a/sdk/lib/fslib/vfatlib/vfatlib.h b/sdk/lib/fslib/vfatlib/vfatlib.h index 20788510a78..5f852c09d55 100644 --- a/sdk/lib/fslib/vfatlib/vfatlib.h +++ b/sdk/lib/fslib/vfatlib/vfatlib.h @@ -109,12 +109,21 @@ typedef struct _FORMAT_CONTEXT ULONG Percent; } FORMAT_CONTEXT, *PFORMAT_CONTEXT; +typedef enum +{ + FAT_UNKNOWN, + FAT_12, + FAT_16, + FAT_32 +} FAT_TYPE; + + #include "common.h" NTSTATUS Fat12Format(HANDLE FileHandle, - PPARTITION_INFORMATION PartitionInfo, + PPARTITION_INFORMATION_EX PartitionInfo, PDISK_GEOMETRY DiskGeometry, PUNICODE_STRING Label, BOOLEAN QuickFormat, @@ -123,7 +132,7 @@ Fat12Format(HANDLE FileHandle, NTSTATUS Fat16Format(HANDLE FileHandle, - PPARTITION_INFORMATION PartitionInfo, + PPARTITION_INFORMATION_EX PartitionInfo, PDISK_GEOMETRY DiskGeometry, PUNICODE_STRING Label, BOOLEAN QuickFormat, @@ -132,7 +141,7 @@ Fat16Format(HANDLE FileHandle, NTSTATUS Fat32Format(HANDLE FileHandle, - PPARTITION_INFORMATION PartitionInfo, + PPARTITION_INFORMATION_EX PartitionInfo, PDISK_GEOMETRY DiskGeometry, PUNICODE_STRING Label, BOOLEAN QuickFormat,