From d8722322eb55414fbc209d56fb87c3f5edb97d12 Mon Sep 17 00:00:00 2001 From: jaredhagel2 <159202343+jaredhagel2@users.noreply.github.com> Date: Mon, 22 Jun 2026 14:53:53 -0600 Subject: [PATCH 1/2] [core] improve raw image partition (re)mount * This improve the post-write drive letter assignation attempt when writing a multi-partition raw images. * Closes #3002. --- src/drive.c | 14 ++++---------- src/drive.h | 3 ++- src/format.c | 35 ++++++++++++++++++++++------------- src/rufus.rc | 10 +++++----- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/drive.c b/src/drive.c index 9bc65b4f..395bf3f6 100644 --- a/src/drive.c +++ b/src/drive.c @@ -1507,24 +1507,19 @@ BOOL AnalyzePBR(HANDLE hLogicalVolume) /* * This call returns the offset of the first ESP partition found - * on the relevant drive, or 0ULL if no ESP was found. + * on the relevant drive, or -1 if no ESP was found. */ -uint64_t GetEspOffset(DWORD DriveIndex) +int64_t GetEspOffset(HANDLE hPhysical) { - uint64_t ret = 0ULL; + int64_t ret = -1; BOOL r; - HANDLE hPhysical; DWORD size, i; BYTE layout[4096] = { 0 }; PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)(void*)layout; - hPhysical = GetPhysicalHandle(DriveIndex, FALSE, TRUE, TRUE); - if (hPhysical == INVALID_HANDLE_VALUE) - return FALSE; - r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, layout, sizeof(layout), &size, NULL); if (!r || size <= 0) { - uprintf("Could not get layout for drive 0x%02x: %s", DriveIndex, WindowsErrorString()); + uprintf("Could not get drive layout: %s", WindowsErrorString()); goto out; } @@ -1537,7 +1532,6 @@ uint64_t GetEspOffset(DWORD DriveIndex) } out: - safe_closehandle(hPhysical); return ret; } diff --git a/src/drive.h b/src/drive.h index 8dc0f7aa..d20cc49b 100644 --- a/src/drive.h +++ b/src/drive.h @@ -408,7 +408,8 @@ BOOL CyclePort(int index); int CycleDevice(int index); BOOL RefreshLayout(DWORD DriveIndex); BOOL GetOpticalMedia(IMG_SAVE* img_save); -uint64_t GetEspOffset(DWORD DriveIndex); +int64_t GetEspOffset(HANDLE hPhysical); BOOL ToggleEsp(DWORD DriveIndex, uint64_t PartitionOffset); +const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset); BOOL IsMsDevDrive(DWORD DriveIndex); BOOL IsFilteredDrive(DWORD DriveIndex); diff --git a/src/format.c b/src/format.c index c13f253c..bcad042e 100644 --- a/src/format.c +++ b/src/format.c @@ -1444,7 +1444,7 @@ out: */ DWORD WINAPI FormatThread(void* param) { - int r; + int i, r; BOOL ret, windows_to_go, actual_lock_drive = lock_drive, write_as_ext = FALSE; // Windows 11 and VDS (which I suspect is what fmifs.dll's FormatEx() is now calling behind the scenes) // require us to unlock the physical drive to format the drive, else access denied is returned. @@ -1517,7 +1517,9 @@ DWORD WINAPI FormatThread(void* param) } // Unassign all drives letters - drive_name[0] = RemoveDriveLetters(DriveIndex, TRUE, FALSE); + // For raw images, keep the primary partition on the earliest prior letter + // so we don't steal the secondary partition's former mountpoint. + drive_name[0] = RemoveDriveLetters(DriveIndex, !((boot_type == BT_IMAGE) && write_as_image), FALSE); if (drive_name[0] == 0) { uprintf("Unable to find a drive letter to use"); ErrorStatus = RUFUS_ERROR(APPERR(ERROR_CANT_ASSIGN_LETTER)); @@ -2042,18 +2044,25 @@ out: PrintInfo(0, MSG_320, lmprintf(MSG_307)); Sleep(200); VdsRescan(VDS_RESCAN_REFRESH, 0, TRUE); - // Trying to mount accessible partitions after writing an image leads to the - // creation of the infamous 'System Volume Information' folder on ESPs, which - // in turn leads to checksum errors for Ubuntu's boot/grub/efi.img (that maps - // to the Ubuntu ESP). So we only call the code below if there are no ESPs or - // if we're running a Ventoy image. - if ((GetEspOffset(DriveIndex) == 0) || (img_report.compression_type == BLED_COMPRESSION_VTSI)) { - WaitForLogical(DriveIndex, 0); - if (GetDrivePartitionData(SelectedDrive.DeviceNumber, fs_name, sizeof(fs_name), TRUE)) { - volume_name = GetLogicalName(DriveIndex, 0, TRUE, TRUE); - if ((volume_name != NULL) && (MountVolume(drive_name, volume_name))) - uprintf("Remounted %s as %c:", volume_name, toupper(drive_name[0])); + // Try to remount the first non ESP partition we see with a file system that Windows supports + hPhysicalDrive = GetPhysicalHandle(DriveIndex, FALSE, TRUE, TRUE); + if (hPhysicalDrive != INVALID_HANDLE_VALUE) { + int64_t esp_offset = GetEspOffset(hPhysicalDrive); + for (i = 0; i < SelectedDrive.nPartitions; i++) { + LARGE_INTEGER li = { .QuadPart = SelectedDrive.Partition[partition_index[i]].Offset }; + if (li.QuadPart == esp_offset) // Skip any ESP + continue; + const char* fs = GetFsName(hPhysicalDrive, li); + if (fs != NULL && (strcmp(fs, "NTFS") == 0 || strcmp(fs, "exFAT") == 0 || + strcmp(fs, "ReFS") == 0 || strncmp(fs, "FAT", 3) == 0)) { + WaitForLogical(DriveIndex, li.QuadPart); + volume_name = GetLogicalName(DriveIndex, li.QuadPart, TRUE, TRUE); + if ((volume_name != NULL) && (MountVolume(drive_name, volume_name))) + uprintf("Remounted %s as %c:", volume_name, toupper(drive_name[0])); + break; + } } + safe_closehandle(hPhysicalDrive); } } if (IS_ERROR(ErrorStatus)) { diff --git a/src/rufus.rc b/src/rufus.rc index f15ce6ca..b4fb81b4 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.15.2407" +CAPTION "Rufus 4.15.2408" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -409,8 +409,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,15,2407,0 - PRODUCTVERSION 4,15,2407,0 + FILEVERSION 4,15,2408,0 + PRODUCTVERSION 4,15,2408,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -428,13 +428,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.15.2407" + VALUE "FileVersion", "4.15.2408" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.15.2407" + VALUE "ProductVersion", "4.15.2408" END END BLOCK "VarFileInfo" From 875f221d5b4fa2c43cad1b85ae975d106964949f Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Mon, 28 Sep 2026 13:45:26 +0100 Subject: [PATCH 2/2] [misc] add more file systems to GetFsName() --- src/drive.c | 54 +++++++++++++++++++++++++++++++++++++++++++--------- src/rufus.rc | 10 +++++----- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/drive.c b/src/drive.c index 395bf3f6..ed7b2c5c 100644 --- a/src/drive.c +++ b/src/drive.c @@ -1725,10 +1725,33 @@ out: } // This is a crude attempt at detecting file systems through their superblock magic. -// Note that we only attempt to detect the file systems that Rufus can format as -// well as a couple other maintsream ones. const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset) { + typedef struct { + const char* name; + const uint8_t magic[4]; + } magic_type; + const magic_type magic_types[] = { + { "SquashFS", { 'h', 's', 'q', 's' } }, + { "CramFS", { 0x45, 0x3D, 0xCD, 0x28 } }, + { "XFS", { 'X', 'F', 'S', 'B' } }, + { "LUKS", { 'L', 'U', 'K', 'S' } }, + { "MD RAID", { 0xFC, 0x4E, 0x2B, 0xA9 } }, + { "U-Boot Legacy uImage", { 0x27, 0x05, 0x19, 0x56 } }, + { "Device Tree/U-Boot FIT", { 0xD0, 0x0D, 0xFE, 0xED } }, + { "Device Tree Overlay", { 0xD7, 0xB7, 0xAB, 0x1E } }, + { "Android Sparse Image", { 0x3A, 0xFF, 0x26, 0xED } }, + { "Android Verified Boot", { 'A', 'V', 'B', '0' } }, + { "Qualcomm Device Tree", { 'Q', 'C', 'D', 'T' } }, + { "Rockchip Resource Image", { 'R', 'S', 'C', 'E' } }, + { "Rockchip Kernel Image", { 'K', 'R', 'N', 'L' } }, + { "Rockchip Parameter Image", { 'P', 'A', 'R', 'M' } }, + { "Rockchip Firmware Image", { 'R', 'K', 'F', 'W' } }, + { "Amlogic Image", { '@', 'A', 'M', 'L' } }, + { "Allwinner Image", { 'e', 'G', 'O', 'N' } }, + { "Mediatek Image", { 0x88, 0x16, 0x88, 0x58 } }, + { "Mediatek Extension", { 0x88, 0x16, 0x89, 0x58 } }, + }; typedef struct { const char* name; const uint8_t magic[8]; @@ -1753,25 +1776,30 @@ const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset) { 0x00000013, 0x0000004C, 0x0003F780 } }; const char* ext_names[] = { "ext", "ext2", "ext3", "ext4" }; + const uint8_t erofs_magic[4] = { 0xE2, 0xE1, 0xF5, 0xE0 }; + const uint8_t f2fs_magic[4] = { 0x10, 0x20, 0xF5, 0xF2 }; const char* ret = "(Unrecognized)"; DWORD i, j, offset, size, sector_size = 512; uint8_t* buf = calloc(sector_size, 1); if (buf == NULL) goto out; - // 1. Try to detect ISO9660/FAT/exFAT/NTFS/ReFS/SquashFS through the 512 bytes superblock at offset 0 + // 1. Detect magic-based file systems through the 512 bytes superblock at offset 0 if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) goto out; if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) goto out; - if (memcmp("hsqs", buf, 4) == 0) { - ret = "SquashFS"; - goto out; - } if (strncmp("CD001", &buf[0x01], 5) == 0) { ret = "ISO9660"; goto out; } + for (i = 0; i < ARRAYSIZE(magic_types); i++) + if (memcmp(buf, magic_types[i].magic, 4) == 0) + break; + if (i < ARRAYSIZE(magic_types)) { + ret = magic_types[i].name; + goto out; + } // The beginning of a superblock for FAT/exFAT/NTFS/ReFS is pretty much always the same: // There are 3 bytes potentially used for a jump instruction, and then are 8 bytes of @@ -1819,8 +1847,8 @@ const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset) goto out; } - // 3. Try to detect ext2/ext3/ext4 through the 512 bytes superblock at offset 1024 - // We're already at the right offset + // 3. Try to detect ext2/ext3/ext4/EROFS/F2FS through the 512 bytes superblock at + // offset 1024 (which StartingOffset already points to) if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN)) goto out; if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size) @@ -1839,6 +1867,14 @@ const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset) ret = ext_names[rev]; goto out; } + if (memcmp(buf, erofs_magic, 4) == 0) { + ret = "EROFS"; + goto out; + } + if (memcmp(buf, f2fs_magic, 4) == 0) { + ret = "F2FS"; + goto out; + } // 4. Try to detect UDF through by looking for a "BEA01\0" string at offset 0xC001 // NB: This is not thorough UDF detection but good enough for our purpose. diff --git a/src/rufus.rc b/src/rufus.rc index b4fb81b4..27ac0fb0 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.15.2408" +CAPTION "Rufus 4.15.2409" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -409,8 +409,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,15,2408,0 - PRODUCTVERSION 4,15,2408,0 + FILEVERSION 4,15,2409,0 + PRODUCTVERSION 4,15,2409,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -428,13 +428,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.15.2408" + VALUE "FileVersion", "4.15.2409" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.15.2408" + VALUE "ProductVersion", "4.15.2409" END END BLOCK "VarFileInfo"