diff --git a/src/drive.c b/src/drive.c index bea54e79..d558befd 100644 --- a/src/drive.c +++ b/src/drive.c @@ -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; } diff --git a/src/drive.h b/src/drive.h index 36752572..9ec5c68d 100644 --- a/src/drive.h +++ b/src/drive.h @@ -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); diff --git a/src/format.c b/src/format.c index 16a5313d..e8430272 100644 --- a/src/format.c +++ b/src/format.c @@ -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])); diff --git a/src/missing.h b/src/missing.h index 54d6e342..88dc116c 100644 --- a/src/missing.h +++ b/src/missing.h @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Constants and defines missing from various toolchains -* Copyright © 2016-2022 Pete Batard +* Copyright © 2016-2024 Pete Batard * * 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) diff --git a/src/rufus.rc b/src/rufus.rc index 3df360bd..abe32f55 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -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" diff --git a/src/wue.c b/src/wue.c index d81fb25a..091fa3fe 100644 --- a/src/wue.c +++ b/src/wue.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Windows User Experience - * Copyright © 2022-2023 Pete Batard + * Copyright © 2022-2024 Pete Batard * * 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;