[misc] refactor partition creation

This commit is contained in:
Pete Batard 2024-02-08 14:17:03 +00:00
parent 164d4b0ab0
commit 0f23c47184
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
6 changed files with 229 additions and 247 deletions

View File

@ -74,7 +74,7 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_
RUFUS_DRIVE_INFO SelectedDrive;
extern BOOL write_as_esp;
extern windows_version_t WindowsVersion;
uint64_t partition_offset[PI_MAX];
int partition_index[PI_MAX];
uint64_t persistence_size = 0;
/*
@ -392,7 +392,7 @@ char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTr
if (PartitionOffset == 0) {
i = 0;
} else if (matching_drive) {
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != SelectedDrive.PartitionOffset[i]); i++);
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != SelectedDrive.Partition[i].Offset); i++);
if (i >= MAX_PARTITIONS) {
suprintf("Error: Could not find a partition at offset %lld on this disk", PartitionOffset);
goto out;
@ -428,11 +428,11 @@ char* GetExtPartitionName(DWORD DriveIndex, uint64_t PartitionOffset)
if (DriveIndex != SelectedDrive.DeviceNumber)
goto out;
CheckDriveIndex(DriveIndex);
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != SelectedDrive.PartitionOffset[i]); i++);
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != SelectedDrive.Partition[i].Offset); i++);
if (i >= MAX_PARTITIONS)
goto out;
static_sprintf(volume_name, "\\\\.\\PhysicalDrive%lu %I64u %I64u", DriveIndex,
SelectedDrive.PartitionOffset[i], SelectedDrive.PartitionSize[i]);
SelectedDrive.Partition[i].Offset, SelectedDrive.Partition[i].Size);
ret = safe_strdup(volume_name);
out:
return ret;
@ -1868,8 +1868,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
return FALSE;
SelectedDrive.nPartitions = 0;
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize));
memset(SelectedDrive.Partition, 0, sizeof(SelectedDrive.Partition));
// Populate the filesystem data
FileSystemName[0] = 0;
volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE);
@ -1961,8 +1960,8 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
}
}
if (i < MAX_PARTITIONS) {
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
SelectedDrive.Partition[i].Offset = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
SelectedDrive.Partition[i].Size = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
}
suprintf(" Type: %s (0x%02x)\r\n Detected File System: %s\r\n"
" Size: %s (%lld bytes)\r\n Start Sector: %lld, Boot: %s",
@ -1992,12 +1991,13 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
for (i = 0; i < DriveLayout->PartitionCount; i++) {
if (i < MAX_PARTITIONS) {
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
SelectedDrive.Partition[i].Offset = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
SelectedDrive.Partition[i].Size = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
wcscpy(SelectedDrive.Partition[i].Name, DriveLayout->PartitionEntry[i].Gpt.Name);
}
SelectedDrive.nPartitions++;
isUefiNtfs = (wcscmp(DriveLayout->PartitionEntry[i].Gpt.Name, L"UEFI:NTFS") == 0);
suprintf("Partition %d%s:\r\n Type: %s", i+1, isUefiNtfs ? " (UEFI:NTFS)" : "",
suprintf("Partition %d%s:\r\n Type: %s", i + 1, isUefiNtfs ? " (UEFI:NTFS)" : "",
GetGPTPartitionType(&DriveLayout->PartitionEntry[i].Gpt.PartitionType));
if (DriveLayout->PartitionEntry[i].Gpt.Name[0] != 0)
suprintf(" Name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name);
@ -2232,15 +2232,17 @@ BOOL RemountVolume(char* drive_name, BOOL bSilent)
* (especially IOCTL_DISK_UPDATE_PROPERTIES is *USELESS*), and therefore the OS will try to
* read the file system data at an old location, even if the partition has just been deleted.
*/
static BOOL ClearPartition(HANDLE hDrive, LARGE_INTEGER offset, DWORD size)
static BOOL ClearPartition(HANDLE hDrive, uint64_t offset, DWORD size)
{
BOOL r = FALSE;
uint8_t* buffer = calloc(size, 1);
LARGE_INTEGER li_offset;
if (buffer == NULL)
return FALSE;
if (!SetFilePointerEx(hDrive, offset, NULL, FILE_BEGIN)) {
li_offset.QuadPart = offset;
if (!SetFilePointerEx(hDrive, li_offset, NULL, FILE_BEGIN)) {
free(buffer);
return FALSE;
}
@ -2260,17 +2262,14 @@ static BOOL ClearPartition(HANDLE hDrive, LARGE_INTEGER offset, DWORD size)
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions)
{
const char* PartitionTypeName[] = { "MBR", "GPT", "SFD" };
const wchar_t *extra_part_name = L"", *main_part_name = write_as_esp ? L"EFI System Partition" : L"Main Data Partition";
const LONGLONG main_part_size = write_as_esp ? MAX_ISO_TO_ESP_SIZE * MB : SelectedDrive.DiskSize;
const LONGLONG bytes_per_track = ((LONGLONG)SelectedDrive.SectorsPerTrack) * SelectedDrive.SectorSize;
const DWORD size_to_clear = MAX_SECTORS_TO_CLEAR * SelectedDrive.SectorSize;
uint8_t* buffer;
uint64_t last_offset = SelectedDrive.DiskSize;
size_t uefi_ntfs_size = 0;
DWORD pi = 0, mi, i, size, bufsize;
CREATE_DISK CreateDisk = { PARTITION_STYLE_RAW, { { 0 } } };
DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = { 0 };
BOOL r;
DWORD i, size, bufsize, pn = 0;
LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0;
// Go for a 260 MB sized ESP by default to keep everyone happy, including 4K sector users:
// https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions
// and folks using MacOS: https://github.com/pbatard/rufus/issues/979
@ -2288,17 +2287,19 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
if (extra_partitions & XP_UEFI_NTFS) {
uefi_ntfs_size = GetResourceSize(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA, "uefi-ntfs.img");
if (uefi_ntfs_size == 0)
if (uefi_ntfs_size == 0) {
uprintf("Could not access embedded 'uefi-ntfs.img'");
return FALSE;
}
}
memset(partition_offset, 0, sizeof(partition_offset));
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize));
// Compute the start offset of our first partition
memset(partition_index, 0, sizeof(partition_index));
memset(SelectedDrive.Partition, 0, sizeof(SelectedDrive.Partition));
// Compute the starting offset of the first partition
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) {
// Go with the MS 1 MB wastage at the beginning...
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = MB;
SelectedDrive.Partition[pi].Offset = 1 * MB;
} else {
// Some folks appear to think that 'Fixes for old BIOSes' is some kind of magic
// wand and are adamant to try to apply them when creating *MODERN* VHD drives.
@ -2308,11 +2309,10 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// CHS sizes that IBM imparted upon us. Long story short, we now align to a
// cylinder size that is itself aligned to the cluster size.
// If this actually breaks old systems, please send your complaints to IBM.
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart =
((bytes_per_track + (ClusterSize - 1)) / ClusterSize) * ClusterSize;
SelectedDrive.Partition[pi].Offset = HI_ALIGN_X_TO_Y(bytes_per_track, ClusterSize);
// GRUB2 no longer fits in the usual 31½ KB that the above computation provides
// so just unconditionally double that size and get on with it.
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart *= 2;
SelectedDrive.Partition[pi].Offset *= 2;
}
// Having the ESP up front may help (and is the Microsoft recommended way) but this
@ -2321,22 +2321,16 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
if (((SelectedDrive.MediaType == FixedMedia) || (WindowsVersion.BuildNumber > 15000)) &&
(extra_partitions & XP_ESP)) {
assert(partition_style == PARTITION_STYLE_GPT);
extra_part_name = L"EFI System Partition";
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = esp_size;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_GENERIC_ESP;
uprintf("● Creating %S (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, extra_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
// Zero the first sectors from this partition to avoid file system caching issues
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString());
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
partition_offset[PI_ESP] = SelectedDrive.PartitionOffset[pn];
pn++;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn - 1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn - 1].PartitionLength.QuadPart;
partition_index[PI_ESP] = pi;
wcscpy(SelectedDrive.Partition[pi].Name, L"EFI System Partition");
SelectedDrive.Partition[pi].Size = esp_size;
SelectedDrive.Partition[pi + 1].Offset = SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size;
// Align next partition to track and cluster
SelectedDrive.Partition[pi + 1].Offset = HI_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
if (ClusterSize % SelectedDrive.SectorSize == 0)
SelectedDrive.Partition[pi + 1].Offset = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
assert(SelectedDrive.Partition[pi + 1].Offset >= SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size);
pi++;
// Clear the extra partition we processed
extra_partitions &= ~(XP_ESP);
}
@ -2344,192 +2338,165 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// If required, set the MSR partition (GPT only - must be created before the data part)
if (extra_partitions & XP_MSR) {
assert(partition_style == PARTITION_STYLE_GPT);
extra_part_name = L"Microsoft Reserved Partition";
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = 128*MB;
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MICROSOFT_RESERVED;
uprintf("● Creating %S (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, extra_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
// Zero the first sectors from this partition to avoid file system caching issues
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString());
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
pn++;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
// Clear the extra partition we processed
wcscpy(SelectedDrive.Partition[pi].Name, L"Microsoft Reserved Partition");
SelectedDrive.Partition[pi].Size = 128 * MB;
SelectedDrive.Partition[pi + 1].Offset = SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size;
SelectedDrive.Partition[pi + 1].Offset = HI_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, bytes_per_track);
if (ClusterSize % SelectedDrive.SectorSize == 0)
SelectedDrive.Partition[pi + 1].Offset = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[pi + 1].Offset, ClusterSize);
assert(SelectedDrive.Partition[pi + 1].Offset >= SelectedDrive.Partition[pi].Offset + SelectedDrive.Partition[pi].Size);
pi++;
extra_partitions &= ~(XP_MSR);
}
// Set our main data partition
if (write_as_esp) {
// Align ESP to 64 MB while leaving at least 32 MB free space
esp_size = max(esp_size, ((((LONGLONG)img_report.projected_size / MB) + 96) / 64) * 64 * MB);
main_part_size_in_sectors = (esp_size - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) /
SelectedDrive.SectorSize;
} else {
main_part_size_in_sectors = (main_part_size - DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart) /
// Need 33 sectors at the end for secondary GPT
SelectedDrive.SectorSize - ((partition_style == PARTITION_STYLE_GPT) ? 33 : 0);
}
// Reserve an entry for the main partition
partition_index[PI_MAIN] = pi++;
// Shorthand for the main index.
mi = partition_index[PI_MAIN];
wcscpy(SelectedDrive.Partition[mi].Name, write_as_esp ? L"EFI System Partition" : L"Main Data Partition");
if (extra_partitions) {
// Adjust the size according to extra partitions (which we always align to a track)
if (extra_partitions & XP_ESP) {
extra_part_name = L"EFI System";
extra_part_size_in_tracks = (esp_size + bytes_per_track - 1) / bytes_per_track;
} else if (extra_partitions & XP_UEFI_NTFS) {
extra_part_name = L"UEFI:NTFS";
extra_part_size_in_tracks = (max(MIN_EXTRA_PART_SIZE, uefi_ntfs_size) + bytes_per_track - 1) / bytes_per_track;
} else if ((extra_partitions & XP_CASPER)) {
// TODO: Should we align these to cluster as well?
if (extra_partitions & XP_PERSISTENCE) {
assert(persistence_size != 0);
extra_part_name = L"Linux Persistence";
extra_part_size_in_tracks = persistence_size / bytes_per_track;
} else if (extra_partitions & XP_COMPAT) {
extra_part_name = L"BIOS Compatibility";
extra_part_size_in_tracks = 1; // One track for the extra partition
} else {
assert(FALSE);
partition_index[PI_CASPER] = pi;
wcscpy(SelectedDrive.Partition[pi].Name, L"Linux Persistence");
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(persistence_size, bytes_per_track);
}
// NB: Because we already subtracted the backup GPT size from the main partition size and
// this extra partition is indexed on main size, it does not overflow into the backup GPT.
main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.SectorsPerTrack) -
extra_part_size_in_tracks) * SelectedDrive.SectorsPerTrack;
if (extra_partitions & XP_ESP) {
partition_index[PI_ESP] = pi;
wcscpy(SelectedDrive.Partition[pi].Name, L"EFI System Partition");
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(esp_size, bytes_per_track);
} else if (extra_partitions & XP_UEFI_NTFS) {
partition_index[PI_UEFI_NTFS] = pi;
wcscpy(SelectedDrive.Partition[pi].Name, L"UEFI:NTFS");
SelectedDrive.Partition[pi++].Size = HI_ALIGN_X_TO_Y(uefi_ntfs_size, bytes_per_track);
} else if (extra_partitions & XP_COMPAT) {
wcscpy(SelectedDrive.Partition[pi].Name, L"BIOS Compatibility");
SelectedDrive.Partition[pi++].Size = bytes_per_track; // One track for the extra partition
}
assert(pi <= MAX_PARTITIONS);
}
// Compute the offsets of the extra partitions (which we always align to a track)
last_offset = SelectedDrive.DiskSize;
if (partition_style == PARTITION_STYLE_GPT)
last_offset -= 33 * SelectedDrive.SectorSize;
for (i = pi - 1; i > mi; i--) {
assert(SelectedDrive.Partition[i].Size < last_offset);
SelectedDrive.Partition[i].Offset = LO_ALIGN_X_TO_Y(last_offset - SelectedDrive.Partition[i].Size, bytes_per_track);
last_offset = SelectedDrive.Partition[i].Offset;
}
// With the above, Compute the main partition size (which we align to a track)
assert(last_offset > SelectedDrive.Partition[mi].Offset);
SelectedDrive.Partition[mi].Size = LO_ALIGN_X_TO_Y(last_offset - SelectedDrive.Partition[mi].Offset, bytes_per_track);
// Try to make sure that the main partition size is a multiple of the cluster size
// This can be especially important when trying to capture an NTFS partition as FFU, as, when
// the NTFS partition is aligned to cluster size, the FFU capture parses the NTFS allocated
// map to only record clusters that are in use, whereas, if not aligned, the FFU capture uses
// a full sector by sector scan of the NTFS partition and records any non-zero garbage, which
// may include garbage leftover data from a previous reformat...
if (ClusterSize % SelectedDrive.SectorSize == 0) {
main_part_size_in_sectors = (((main_part_size_in_sectors * SelectedDrive.SectorSize) /
ClusterSize) * ClusterSize) / SelectedDrive.SectorSize;
}
if (main_part_size_in_sectors <= 0) {
uprintf("Error: Invalid %S size", main_part_name);
if (ClusterSize % SelectedDrive.SectorSize == 0)
SelectedDrive.Partition[mi].Size = LO_ALIGN_X_TO_Y(SelectedDrive.Partition[mi].Size, ClusterSize);
if (SelectedDrive.Partition[mi].Size <= 0) {
uprintf("Error: Invalid %S size", SelectedDrive.Partition[mi].Name);
return FALSE;
}
uprintf("● Creating %S (offset: %lld, size: %s)", main_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
SizeToHumanReadable(main_part_size_in_sectors * SelectedDrive.SectorSize, TRUE, FALSE));
// Zero the beginning of this partition to avoid conflicting leftovers
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
uprintf("Could not zero %S: %s", main_part_name, WindowsErrorString());
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = main_part_size_in_sectors * SelectedDrive.SectorSize;
if (partition_style == PARTITION_STYLE_MBR) {
DriveLayoutEx.PartitionEntry[pn].Mbr.BootIndicator = (boot_type != BT_NON_BOOTABLE);
switch (file_system) {
case FS_FAT16:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0e; // FAT16 LBA
break;
case FS_NTFS:
case FS_EXFAT:
case FS_UDF:
case FS_REFS:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x07;
break;
case FS_EXT2:
case FS_EXT3:
case FS_EXT4:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83;
break;
case FS_FAT32:
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x0c; // FAT32 LBA
break;
default:
uprintf("Unsupported file system");
return FALSE;
}
} else {
if (write_as_esp)
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_GENERIC_ESP;
else if (IS_EXT(file_system))
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_LINUX_DATA;
else
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MICROSOFT_DATA;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, main_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
}
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
partition_offset[PI_MAIN] = SelectedDrive.PartitionOffset[pn];
pn++;
// Set the optional extra partition
if (extra_partitions) {
// Should end on a track boundary
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (extra_partitions & XP_UEFI_NTFS) ? uefi_ntfs_size :
extra_part_size_in_tracks * bytes_per_track;
uprintf("● Creating %S Partition (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
if (extra_partitions & XP_CASPER)
partition_offset[PI_CASPER] = SelectedDrive.PartitionOffset[pn];
else if (extra_partitions & XP_ESP)
partition_offset[PI_ESP] = SelectedDrive.PartitionOffset[pn];
if (partition_style == PARTITION_STYLE_GPT) {
if (extra_partitions & XP_ESP)
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_GENERIC_ESP;
else if (extra_partitions & XP_CASPER)
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_LINUX_DATA;
else
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = PARTITION_MICROSOFT_DATA;
if (extra_partitions & XP_UEFI_NTFS) {
// Build the DriveLayoutEx table
for (i = 0; i < pi; i++) {
uprintf("● Creating %S%s (offset: %lld, size: %s)", SelectedDrive.Partition[i].Name,
(wcsstr(SelectedDrive.Partition[i].Name, L"Partition") == NULL) ? " Partition" : "",
SelectedDrive.Partition[i].Offset,
SizeToHumanReadable(SelectedDrive.Partition[i].Size, TRUE, FALSE));
// Zero the first sectors of the partition to avoid file system caching issues
if (!ClearPartition(hDrive, SelectedDrive.Partition[i].Offset,
(DWORD)MIN(size_to_clear, SelectedDrive.Partition[i].Size)))
uprintf("Could not zero %S: %s", SelectedDrive.Partition[i].Name, WindowsErrorString());
DriveLayoutEx.PartitionEntry[i].PartitionStyle = partition_style;
DriveLayoutEx.PartitionEntry[i].StartingOffset.QuadPart = SelectedDrive.Partition[i].Offset;
DriveLayoutEx.PartitionEntry[i].PartitionLength.QuadPart = SelectedDrive.Partition[i].Size;
DriveLayoutEx.PartitionEntry[i].PartitionNumber = i + 1;
DriveLayoutEx.PartitionEntry[i].RewritePartition = TRUE;
if (partition_style == PARTITION_STYLE_MBR) {
if (i == mi) {
DriveLayoutEx.PartitionEntry[i].Mbr.BootIndicator = (boot_type != BT_NON_BOOTABLE);
switch (file_system) {
case FS_FAT16:
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0x0e; // FAT16 LBA
break;
case FS_NTFS:
case FS_EXFAT:
case FS_UDF:
case FS_REFS:
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0x07;
break;
case FS_EXT2:
case FS_EXT3:
case FS_EXT4:
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0x83;
break;
case FS_FAT32:
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0x0c; // FAT32 LBA
break;
default:
uprintf("Unsupported file system");
return FALSE;
}
}
// May override the the type of main partition if write_as_esp is active
if ((wcscmp(SelectedDrive.Partition[i].Name, L"EFI System Partition") == 0) ||
(wcscmp(SelectedDrive.Partition[i].Name, L"UEFI:NTFS") == 0))
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0xef;
else if (wcscmp(SelectedDrive.Partition[i].Name, L"Linux Persistence") == 0)
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = 0x83;
else if (wcscmp(SelectedDrive.Partition[i].Name, L"BIOS Compatibility") == 0)
DriveLayoutEx.PartitionEntry[i].Mbr.PartitionType = RUFUS_EXTRA_PARTITION_TYPE;
} else {
assert(partition_style == PARTITION_STYLE_GPT);
if (wcscmp(SelectedDrive.Partition[i].Name, L"UEFI:NTFS") == 0) {
DriveLayoutEx.PartitionEntry[i].Gpt.PartitionType = PARTITION_GENERIC_ESP;
// Prevent a drive letter from being assigned to the UEFI:NTFS partition
DriveLayoutEx.PartitionEntry[pn].Gpt.Attributes = GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER;
DriveLayoutEx.PartitionEntry[i].Gpt.Attributes = GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER;
#if !defined(_DEBUG)
// Also make the partition read-only for release versions
DriveLayoutEx.PartitionEntry[pn].Gpt.Attributes += GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY;
DriveLayoutEx.PartitionEntry[i].Gpt.Attributes += GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY;
#endif
}
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (extra_partitions & XP_ESP) ? L"EFI System Partition" : extra_part_name,
ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
} else {
if (extra_partitions & (XP_UEFI_NTFS | XP_ESP)) {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0xef;
} else if (extra_partitions & XP_CASPER) {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = 0x83;
} else if (extra_partitions & XP_COMPAT) {
DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = RUFUS_EXTRA_PARTITION_TYPE;
// Set the one track compatibility partition to be all hidden sectors
DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.SectorsPerTrack;
} else {
assert(FALSE);
}
} else if (wcscmp(SelectedDrive.Partition[i].Name, L"EFI System Partition") == 0)
DriveLayoutEx.PartitionEntry[i].Gpt.PartitionType = PARTITION_GENERIC_ESP;
else if (wcscmp(SelectedDrive.Partition[i].Name, L"Linux Persistence") == 0)
DriveLayoutEx.PartitionEntry[i].Gpt.PartitionType = PARTITION_LINUX_DATA;
else if (wcscmp(SelectedDrive.Partition[i].Name, L"Microsoft Reserved Partition") == 0)
DriveLayoutEx.PartitionEntry[i].Gpt.PartitionType = PARTITION_MICROSOFT_RESERVED;
else
DriveLayoutEx.PartitionEntry[i].Gpt.PartitionType = PARTITION_MICROSOFT_DATA;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[i].Gpt.PartitionId));
wcscpy(DriveLayoutEx.PartitionEntry[i].Gpt.Name, SelectedDrive.Partition[i].Name);
}
// We need to write the UEFI:NTFS partition before we refresh the disk
if (extra_partitions & XP_UEFI_NTFS) {
uprintf("Writing %S data...", extra_part_name);
if (!SetFilePointerEx(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, NULL, FILE_BEGIN)) {
uprintf("Could not set position");
return FALSE;
}
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA, "uefi-ntfs.img", &bufsize, FALSE);
if (buffer == NULL) {
uprintf("Could not access source image");
return FALSE;
}
if(!WriteFileWithRetry(hDrive, buffer, bufsize, &size, WRITE_RETRIES)) {
uprintf("Write error: %s", WindowsErrorString());
return FALSE;
}
}
pn++;
}
// Initialize the remaining partition data
for (i = 0; i < pn; i++) {
DriveLayoutEx.PartitionEntry[i].PartitionNumber = i + 1;
DriveLayoutEx.PartitionEntry[i].PartitionStyle = partition_style;
DriveLayoutEx.PartitionEntry[i].RewritePartition = TRUE;
// We need to write the UEFI:NTFS partition before we refresh the disk
if (extra_partitions & XP_UEFI_NTFS) {
LARGE_INTEGER li;
uprintf("Writing UEFI:NTFS data...", SelectedDrive.Partition[partition_index[PI_UEFI_NTFS]].Name);
li.QuadPart = SelectedDrive.Partition[partition_index[PI_UEFI_NTFS]].Offset;
if (!SetFilePointerEx(hDrive, li, NULL, FILE_BEGIN)) {
uprintf(" Could not set position");
return FALSE;
}
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_UEFI_NTFS), _RT_RCDATA,
"uefi-ntfs.img", &bufsize, FALSE);
if (buffer == NULL) {
uprintf(" Could not access source image");
return FALSE;
}
if(!WriteFileWithRetry(hDrive, buffer, bufsize, &size, WRITE_RETRIES)) {
uprintf(" Write error: %s", WindowsErrorString());
return FALSE;
}
}
switch (partition_style) {
@ -2558,7 +2525,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
CreateDisk.Gpt.MaxPartitionCount = MAX_PARTITIONS;
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT;
DriveLayoutEx.PartitionCount = pn;
DriveLayoutEx.PartitionCount = pi;
// At the very least, a GPT disk has 34 reserved sectors at the beginning and 33 at the end.
DriveLayoutEx.Type.Gpt.StartingUsableOffset.QuadPart = 34 * SelectedDrive.SectorSize;
DriveLayoutEx.Type.Gpt.UsableLength.QuadPart = SelectedDrive.DiskSize - (34+33) * SelectedDrive.SectorSize;
@ -2569,8 +2536,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// If you don't call IOCTL_DISK_CREATE_DISK, the IOCTL_DISK_SET_DRIVE_LAYOUT_EX call will fail
size = sizeof(CreateDisk);
r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL);
if (!r) {
if (!DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL)) {
uprintf("Could not reset disk: %s", WindowsErrorString());
return FALSE;
}
@ -2578,9 +2544,9 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// "The goggles, they do nothing!"
RefreshDriveLayout(hDrive);
size = sizeof(DriveLayoutEx) - ((partition_style == PARTITION_STYLE_GPT)?((4-pn)*sizeof(PARTITION_INFORMATION_EX)):0);
r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL);
if (!r) {
size = sizeof(DriveLayoutEx) - ((partition_style == PARTITION_STYLE_GPT) ?
((4 - pi) * sizeof(PARTITION_INFORMATION_EX)) : 0);
if (!DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL)) {
uprintf("Could not set drive layout: %s", WindowsErrorString());
return FALSE;
}

View File

@ -36,12 +36,13 @@
#define XP_ESP 0x02
#define XP_UEFI_NTFS 0x04
#define XP_COMPAT 0x08
#define XP_CASPER 0x10
#define XP_PERSISTENCE 0x10
#define PI_MAIN 0
#define PI_ESP 1
#define PI_CASPER 2
#define PI_MAX 3
#define PI_UEFI_NTFS 3
#define PI_MAX 4
// The following should match VDS_FSOF_FLAGS as much as possible
#define FP_FORCE 0x00000001
@ -362,8 +363,11 @@ typedef struct {
MEDIA_TYPE MediaType;
int PartitionStyle;
int nPartitions; // number of partitions we actually care about
uint64_t PartitionOffset[MAX_PARTITIONS];
uint64_t PartitionSize[MAX_PARTITIONS];
struct {
wchar_t Name[36];
uint64_t Offset;
uint64_t Size;
} Partition[MAX_PARTITIONS];
int FSType;
char proposed_label[16];
BOOL has_protective_mbr;
@ -374,7 +378,7 @@ typedef struct {
} ClusterSize[FS_MAX];
} RUFUS_DRIVE_INFO;
extern RUFUS_DRIVE_INFO SelectedDrive;
extern uint64_t partition_offset[PI_MAX];
extern int partition_index[PI_MAX];
BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled);

View File

@ -972,7 +972,7 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive)
}
// Ensure that we have sufficient space for the SBR
max_size = (DWORD)SelectedDrive.PartitionOffset[0];
max_size = (DWORD)SelectedDrive.Partition[0].Offset;
if (br_size + size > max_size) {
uprintf(" SBR size is too large - You may need to uncheck 'Add fixes for old BIOSes'.");
if (sub_type == BT_MAX)
@ -1456,23 +1456,32 @@ DWORD WINAPI FormatThread(void* param)
large_drive = (SelectedDrive.DiskSize > (1*TB));
if (large_drive)
uprintf("Notice: Large drive detected (may produce short writes)");
// Find out if we need to add any extra partitions
extra_partitions = 0;
if ((boot_type == BT_IMAGE) && !write_as_image && HAS_PERSISTENCE(img_report) && persistence_size)
extra_partitions |= XP_PERSISTENCE;
// According to Microsoft, every GPT disk (we RUN Windows from) must have an MSR due to not having hidden sectors
// https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-and-gpt-faq#disks-that-require-an-msr
if ((windows_to_go) && (target_type == TT_UEFI) && (partition_type == PARTITION_STYLE_GPT))
// According to Microsoft, every GPT disk (we RUN Windows from) must have an MSR due to not having hidden sectors
// https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-and-gpt-faq#disks-that-require-an-msr
extra_partitions = XP_ESP | XP_MSR;
else if ( ((fs_type == FS_NTFS) || (fs_type == FS_EXFAT)) &&
((boot_type == BT_UEFI_NTFS) || ((boot_type == BT_IMAGE) && IS_EFI_BOOTABLE(img_report) &&
((target_type == TT_UEFI) || (windows_to_go) || (allow_dual_uefi_bios) ||
(img_report.has_4GB_file) || (img_report.needs_ntfs)))) )
extra_partitions = XP_UEFI_NTFS;
else if ((boot_type == BT_IMAGE) && !write_as_image && HAS_PERSISTENCE(img_report) && persistence_size)
extra_partitions = XP_CASPER;
else if (IsChecked(IDC_OLD_BIOS_FIXES))
extra_partitions = XP_COMPAT;
extra_partitions |= XP_ESP | XP_MSR;
// If we have a bootable image with UEFI bootloaders and the target file system is NTFS or exFAT
// or the UEFI:NTFS option is selected, we add the UEFI:NTFS partition...
else if (((boot_type == BT_IMAGE) && IS_EFI_BOOTABLE(img_report)) && ((fs_type == FS_NTFS) || (fs_type == FS_EXFAT)) ||
(boot_type == BT_UEFI_NTFS)) {
extra_partitions |= XP_UEFI_NTFS;
// ...but only if we're not dealing with a Windows image in installer mode with target
// system set to BIOS and without dual BIOS+UEFI boot enabled.
if ((boot_type == BT_IMAGE) && HAS_BOOTMGR_BIOS(img_report) && (!windows_to_go) &&
(target_type == TT_BIOS) && (!allow_dual_uefi_bios))
extra_partitions &= ~XP_UEFI_NTFS;
}
if (IsChecked(IDC_OLD_BIOS_FIXES))
extra_partitions |= XP_COMPAT;
// On pre 1703 platforms (and even on later ones), anything with ext2/ext3 doesn't sit
// too well with Windows. Same with ESPs. Relaxing our locking rules seems to help...
if ((extra_partitions & (XP_ESP | XP_CASPER)) || IS_EXT(fs_type))
if ((extra_partitions & (XP_ESP | XP_PERSISTENCE)) || IS_EXT(fs_type))
actual_lock_drive = FALSE;
// Windows 11 is a lot more proactive in locking ESPs and MSRs than previous versions
// were, meaning that we also can't lock the drive without incurring errors...
@ -1710,13 +1719,13 @@ DWORD WINAPI FormatThread(void* param)
Sleep(200);
if (write_as_esp || write_as_ext) {
// Can't format ESPs or ext2/ext3 partitions unless we mount them ourselves
volume_name = AltMountVolume(DriveIndex, partition_offset[PI_MAIN], FALSE);
volume_name = AltMountVolume(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, FALSE);
if (volume_name == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_ASSIGN_LETTER);
goto out;
}
} else {
if (!WaitForLogical(DriveIndex, partition_offset[PI_MAIN])) {
if (!WaitForLogical(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset)) {
uprintf("Logical drive was not found - aborting");
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_TIMEOUT;
@ -1727,12 +1736,12 @@ DWORD WINAPI FormatThread(void* param)
// Format Casper partition if required. Do it before we format anything with
// a file system that Windows will recognize, to avoid concurrent access.
if (extra_partitions & XP_CASPER) {
if (extra_partitions & XP_PERSISTENCE) {
uint32_t ext_version = ReadSetting32(SETTING_USE_EXT_VERSION);
if ((ext_version < 2) || (ext_version > 4))
ext_version = 3;
uprintf("Using %s-like method to enable persistence", img_report.uses_casper ? "Ubuntu" : "Debian");
if (!FormatPartition(DriveIndex, partition_offset[PI_CASPER], 0, FS_EXT2 + (ext_version - 2),
if (!FormatPartition(DriveIndex, SelectedDrive.Partition[partition_index[PI_CASPER]].Offset, 0, FS_EXT2 + (ext_version - 2),
img_report.uses_casper ? "casper-rw" : "persistence",
(img_report.uses_casper ? 0 : FP_CREATE_PERSISTENCE_CONF) |
(IsChecked(IDC_QUICK_FORMAT) ? FP_QUICK : 0))) {
@ -1757,7 +1766,7 @@ DWORD WINAPI FormatThread(void* param)
if (write_as_esp)
Flags |= FP_LARGE_FAT32;
ret = FormatPartition(DriveIndex, partition_offset[PI_MAIN], ClusterSize, fs_type, label, Flags);
ret = FormatPartition(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, ClusterSize, fs_type, label, Flags);
if (!ret) {
// Error will be set by FormatPartition() in FormatStatus
uprintf("Format error: %s", StrError(FormatStatus, TRUE));
@ -1790,7 +1799,7 @@ DWORD WINAPI FormatThread(void* param)
// Try to continue
CHECK_FOR_USER_CANCEL;
volume_name = GetLogicalName(DriveIndex, partition_offset[PI_MAIN], TRUE, TRUE);
volume_name = GetLogicalName(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, TRUE, TRUE);
if (volume_name == NULL) {
uprintf("Could not get volume name");
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_NO_VOLUME_ID;
@ -1848,7 +1857,7 @@ DWORD WINAPI FormatThread(void* param)
} else {
// We still have a lock, which we need to modify the volume boot record
// => no need to reacquire the lock...
hLogicalVolume = GetLogicalHandle(DriveIndex, partition_offset[PI_MAIN], FALSE, TRUE, FALSE);
hLogicalVolume = GetLogicalHandle(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, FALSE, TRUE, FALSE);
if ((hLogicalVolume == INVALID_HANDLE_VALUE) || (hLogicalVolume == NULL)) {
uprintf("Could not re-mount volume for partition boot record access");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
@ -1999,7 +2008,7 @@ out:
}
}
if (IS_ERROR(FormatStatus)) {
volume_name = GetLogicalName(DriveIndex, partition_offset[PI_MAIN], TRUE, TRUE);
volume_name = GetLogicalName(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, TRUE, TRUE);
if (volume_name != NULL) {
if (MountVolume(drive_name, volume_name))
uprintf("Re-mounted volume as %c: after error", toupper(drive_name[0]));

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Constants and defines missing from various toolchains
* Copyright © 2016-2022 Pete Batard <pete@akeo.ie>
* Copyright © 2016-2024 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,6 +31,9 @@
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define LO_ALIGN_X_TO_Y(x, y) (((x) / (y)) * (y))
#define HI_ALIGN_X_TO_Y(x, y) ((((x) + (y) - 1) / (y)) * (y))
#if defined(__GNUC__)
#define ALIGNED(m) __attribute__ ((__aligned__(m)))
#elif defined(_MSC_VER)

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.5.2109"
CAPTION "Rufus 4.5.2110"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,5,2109,0
PRODUCTVERSION 4,5,2109,0
FILEVERSION 4,5,2110,0
PRODUCTVERSION 4,5,2110,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.5.2109"
VALUE "FileVersion", "4.5.2110"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.5.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.5.2109"
VALUE "ProductVersion", "4.5.2110"
END
END
BLOCK "VarFileInfo"

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Windows User Experience
* Copyright © 2022-2023 Pete Batard <pete@akeo.ie>
* Copyright © 2022-2024 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -690,14 +690,14 @@ BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
// VDS cannot list ESP volumes (talk about allegedly improving on the old disk and volume APIs, only to
// completely neuter it) and IVdsDiskPartitionMF::FormatPartitionEx(), which is what you are supposed to
// use for ESPs, explicitly states: "This method cannot be used to format removable media."
if (!FormatPartition(DriveIndex, partition_offset[PI_ESP], cluster_size, FS_FAT32, "",
if (!FormatPartition(DriveIndex, SelectedDrive.Partition[partition_index[PI_ESP]].Offset, cluster_size, FS_FAT32, "",
FP_QUICK | FP_FORCE | FP_LARGE_FAT32 | FP_NO_BOOT)) {
uprintf("Could not format EFI System Partition");
return FALSE;
}
Sleep(200);
// Need to have the ESP mounted to invoke bcdboot
ms_efi = AltMountVolume(DriveIndex, partition_offset[PI_ESP], FALSE);
ms_efi = AltMountVolume(DriveIndex, SelectedDrive.Partition[partition_index[PI_ESP]].Offset, FALSE);
if (ms_efi == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_ASSIGN_LETTER);
return FALSE;