1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2026-10-22 22:34:26 +00:00

Compare commits

...

2 commits

Author SHA1 Message Date
Pete Batard
875f221d5b
[misc] add more file systems to GetFsName() 2026-09-28 13:45:26 +01:00
jaredhagel2
d8722322eb
[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.
2026-09-25 18:35:15 +01:00
4 changed files with 78 additions and 38 deletions

View file

@ -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;
}
@ -1731,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];
@ -1759,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
@ -1825,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)
@ -1845,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.

View file

@ -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);

View file

@ -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,19 +2044,26 @@ 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);
// 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)) {
volume_name = GetLogicalName(DriveIndex, SelectedDrive.Partition[partition_index[PI_MAIN]].Offset, TRUE, TRUE);

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.15.2407"
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,2407,0
PRODUCTVERSION 4,15,2407,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.2407"
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.2407"
VALUE "ProductVersion", "4.15.2409"
END
END
BLOCK "VarFileInfo"