mirror of
https://github.com/pbatard/rufus.git
synced 2026-10-22 22:34:26 +00:00
Compare commits
2 commits
942ed3a4ed
...
875f221d5b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
875f221d5b |
||
|
|
d8722322eb |
4 changed files with 78 additions and 38 deletions
68
src/drive.c
68
src/drive.c
|
|
@ -1507,24 +1507,19 @@ BOOL AnalyzePBR(HANDLE hLogicalVolume)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This call returns the offset of the first ESP partition found
|
* 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;
|
BOOL r;
|
||||||
HANDLE hPhysical;
|
|
||||||
DWORD size, i;
|
DWORD size, i;
|
||||||
BYTE layout[4096] = { 0 };
|
BYTE layout[4096] = { 0 };
|
||||||
PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)(void*)layout;
|
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);
|
r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, layout, sizeof(layout), &size, NULL);
|
||||||
if (!r || size <= 0) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1537,7 +1532,6 @@ uint64_t GetEspOffset(DWORD DriveIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
safe_closehandle(hPhysical);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1731,10 +1725,33 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a crude attempt at detecting file systems through their superblock magic.
|
// 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)
|
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 {
|
typedef struct {
|
||||||
const char* name;
|
const char* name;
|
||||||
const uint8_t magic[8];
|
const uint8_t magic[8];
|
||||||
|
|
@ -1759,25 +1776,30 @@ const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset)
|
||||||
{ 0x00000013, 0x0000004C, 0x0003F780 }
|
{ 0x00000013, 0x0000004C, 0x0003F780 }
|
||||||
};
|
};
|
||||||
const char* ext_names[] = { "ext", "ext2", "ext3", "ext4" };
|
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)";
|
const char* ret = "(Unrecognized)";
|
||||||
DWORD i, j, offset, size, sector_size = 512;
|
DWORD i, j, offset, size, sector_size = 512;
|
||||||
uint8_t* buf = calloc(sector_size, 1);
|
uint8_t* buf = calloc(sector_size, 1);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
goto out;
|
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))
|
if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN))
|
||||||
goto out;
|
goto out;
|
||||||
if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size)
|
if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size)
|
||||||
goto out;
|
goto out;
|
||||||
if (memcmp("hsqs", buf, 4) == 0) {
|
|
||||||
ret = "SquashFS";
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (strncmp("CD001", &buf[0x01], 5) == 0) {
|
if (strncmp("CD001", &buf[0x01], 5) == 0) {
|
||||||
ret = "ISO9660";
|
ret = "ISO9660";
|
||||||
goto out;
|
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:
|
// 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
|
// 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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Try to detect ext2/ext3/ext4 through the 512 bytes superblock at offset 1024
|
// 3. Try to detect ext2/ext3/ext4/EROFS/F2FS through the 512 bytes superblock at
|
||||||
// We're already at the right offset
|
// offset 1024 (which StartingOffset already points to)
|
||||||
if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN))
|
if (!SetFilePointerEx(hPhysical, StartingOffset, NULL, FILE_BEGIN))
|
||||||
goto out;
|
goto out;
|
||||||
if (!ReadFile(hPhysical, buf, sector_size, &size, NULL) || size != sector_size)
|
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];
|
ret = ext_names[rev];
|
||||||
goto out;
|
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
|
// 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.
|
// NB: This is not thorough UDF detection but good enough for our purpose.
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,8 @@ BOOL CyclePort(int index);
|
||||||
int CycleDevice(int index);
|
int CycleDevice(int index);
|
||||||
BOOL RefreshLayout(DWORD DriveIndex);
|
BOOL RefreshLayout(DWORD DriveIndex);
|
||||||
BOOL GetOpticalMedia(IMG_SAVE* img_save);
|
BOOL GetOpticalMedia(IMG_SAVE* img_save);
|
||||||
uint64_t GetEspOffset(DWORD DriveIndex);
|
int64_t GetEspOffset(HANDLE hPhysical);
|
||||||
BOOL ToggleEsp(DWORD DriveIndex, uint64_t PartitionOffset);
|
BOOL ToggleEsp(DWORD DriveIndex, uint64_t PartitionOffset);
|
||||||
|
const char* GetFsName(HANDLE hPhysical, LARGE_INTEGER StartingOffset);
|
||||||
BOOL IsMsDevDrive(DWORD DriveIndex);
|
BOOL IsMsDevDrive(DWORD DriveIndex);
|
||||||
BOOL IsFilteredDrive(DWORD DriveIndex);
|
BOOL IsFilteredDrive(DWORD DriveIndex);
|
||||||
|
|
|
||||||
35
src/format.c
35
src/format.c
|
|
@ -1444,7 +1444,7 @@ out:
|
||||||
*/
|
*/
|
||||||
DWORD WINAPI FormatThread(void* param)
|
DWORD WINAPI FormatThread(void* param)
|
||||||
{
|
{
|
||||||
int r;
|
int i, r;
|
||||||
BOOL ret, windows_to_go, actual_lock_drive = lock_drive, write_as_ext = FALSE;
|
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)
|
// 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.
|
// 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
|
// 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) {
|
if (drive_name[0] == 0) {
|
||||||
uprintf("Unable to find a drive letter to use");
|
uprintf("Unable to find a drive letter to use");
|
||||||
ErrorStatus = RUFUS_ERROR(APPERR(ERROR_CANT_ASSIGN_LETTER));
|
ErrorStatus = RUFUS_ERROR(APPERR(ERROR_CANT_ASSIGN_LETTER));
|
||||||
|
|
@ -2042,18 +2044,25 @@ out:
|
||||||
PrintInfo(0, MSG_320, lmprintf(MSG_307));
|
PrintInfo(0, MSG_320, lmprintf(MSG_307));
|
||||||
Sleep(200);
|
Sleep(200);
|
||||||
VdsRescan(VDS_RESCAN_REFRESH, 0, TRUE);
|
VdsRescan(VDS_RESCAN_REFRESH, 0, TRUE);
|
||||||
// Trying to mount accessible partitions after writing an image leads to the
|
// Try to remount the first non ESP partition we see with a file system that Windows supports
|
||||||
// creation of the infamous 'System Volume Information' folder on ESPs, which
|
hPhysicalDrive = GetPhysicalHandle(DriveIndex, FALSE, TRUE, TRUE);
|
||||||
// in turn leads to checksum errors for Ubuntu's boot/grub/efi.img (that maps
|
if (hPhysicalDrive != INVALID_HANDLE_VALUE) {
|
||||||
// to the Ubuntu ESP). So we only call the code below if there are no ESPs or
|
int64_t esp_offset = GetEspOffset(hPhysicalDrive);
|
||||||
// if we're running a Ventoy image.
|
for (i = 0; i < SelectedDrive.nPartitions; i++) {
|
||||||
if ((GetEspOffset(DriveIndex) == 0) || (img_report.compression_type == BLED_COMPRESSION_VTSI)) {
|
LARGE_INTEGER li = { .QuadPart = SelectedDrive.Partition[partition_index[i]].Offset };
|
||||||
WaitForLogical(DriveIndex, 0);
|
if (li.QuadPart == esp_offset) // Skip any ESP
|
||||||
if (GetDrivePartitionData(SelectedDrive.DeviceNumber, fs_name, sizeof(fs_name), TRUE)) {
|
continue;
|
||||||
volume_name = GetLogicalName(DriveIndex, 0, TRUE, TRUE);
|
const char* fs = GetFsName(hPhysicalDrive, li);
|
||||||
if ((volume_name != NULL) && (MountVolume(drive_name, volume_name)))
|
if (fs != NULL && (strcmp(fs, "NTFS") == 0 || strcmp(fs, "exFAT") == 0 ||
|
||||||
uprintf("Remounted %s as %c:", volume_name, toupper(drive_name[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)) {
|
if (IS_ERROR(ErrorStatus)) {
|
||||||
|
|
|
||||||
10
src/rufus.rc
10
src/rufus.rc
|
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 4.15.2407"
|
CAPTION "Rufus 4.15.2409"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
|
@ -409,8 +409,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,15,2407,0
|
FILEVERSION 4,15,2409,0
|
||||||
PRODUCTVERSION 4,15,2407,0
|
PRODUCTVERSION 4,15,2409,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
|
@ -428,13 +428,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "4.15.2407"
|
VALUE "FileVersion", "4.15.2409"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-4.15.exe"
|
VALUE "OriginalFilename", "rufus-4.15.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "4.15.2407"
|
VALUE "ProductVersion", "4.15.2409"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue