1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

[cmp] Enable extraction of zip archives outside of ISO copy mode

* This enables the use of Ctrl-SELECT to also extract files from a .zip
  when using non-bootable, DOS, UEFI-NTFS, etc.
* Also clean up some uprintf line terminations and some additional code.
* Also fix some Coverity and MinGW warnings.
This commit is contained in:
Pete Batard 2024-03-12 17:36:24 +00:00
parent abc33122a0
commit 5eae8a6441
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
10 changed files with 115 additions and 77 deletions

View file

@ -15,6 +15,9 @@ o v4.?? (202?.??.??)
- *NEW* MSG_343 "Uncompressed VHD Image" - *NEW* MSG_343 "Uncompressed VHD Image"
- *NEW* MSG_344 "Full Flash Update Image" - *NEW* MSG_344 "Full Flash Update Image"
- *NEW* MSG_345 "Some additional data must be downloaded from Microsoft to use this functionality (...)" - *NEW* MSG_345 "Some additional data must be downloaded from Microsoft to use this functionality (...)"
- *NEW* MSG_346 "Restrict Windows to S-Mode (INCOMPATIBLE with online account bypass)"
- *NEW* MSG_347 "Expert Mode"
- *NEW* MSG_348 "Extracting archive files: %s"
o v3.22 (2023.??.??) o v3.22 (2023.??.??)
// MSG_144 is aimed the the ISO download feature // MSG_144 is aimed the the ISO download feature

View file

@ -611,6 +611,7 @@ t MSG_345 "Some additional data must be downloaded from Microsoft to use this fu
"- Select 'No' to cancel the operation" "- Select 'No' to cancel the operation"
t MSG_346 "Restrict Windows to S-Mode (INCOMPATIBLE with online account bypass)" t MSG_346 "Restrict Windows to S-Mode (INCOMPATIBLE with online account bypass)"
t MSG_347 "Expert Mode" t MSG_347 "Expert Mode"
t MSG_348 "Extracting archive files: %s"
# The following messages are for the Windows Store listing only and are not used by the application # The following messages are for the Windows Store listing only and are not used by the application
t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc." t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc."
t MSG_901 "Official site: %s" t MSG_901 "Official site: %s"

View file

@ -75,6 +75,7 @@ extern uint32_t dur_mins, dur_secs;
extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files; extern uint32_t wim_nb_files, wim_proc_files, wim_extra_files;
extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing; extern BOOL force_large_fat32, enable_ntfs_compression, lock_drive, zero_drive, fast_zeroing, enable_file_indexing;
extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available, has_ffu_support; extern BOOL write_as_image, use_vds, write_as_esp, is_vds_available, has_ffu_support;
extern char* archive_path;
uint8_t *grub2_buf = NULL, *sec_buf = NULL; uint8_t *grub2_buf = NULL, *sec_buf = NULL;
long grub2_len; long grub2_len;
@ -707,7 +708,7 @@ static BOOL CheckDisk(char DriveLetter)
pfChkdsk(wDriveRoot, wFSType, FALSE, FALSE, FALSE, FALSE, NULL, NULL, ChkdskCallback); pfChkdsk(wDriveRoot, wFSType, FALSE, FALSE, FALSE, FALSE, NULL, NULL, ChkdskCallback);
if (!IS_ERROR(FormatStatus)) { if (!IS_ERROR(FormatStatus)) {
uprintf("NTFS Fixup completed.\n"); uprintf("NTFS Fixup completed.");
r = TRUE; r = TRUE;
} }
@ -797,7 +798,7 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive)
} }
if (!read_sectors(hPhysicalDrive, SelectedDrive.SectorSize, 0, 1, buffer)) { if (!read_sectors(hPhysicalDrive, SelectedDrive.SectorSize, 0, 1, buffer)) {
uprintf("Could not read MBR\n"); uprintf("Could not read MBR");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
goto out; goto out;
} }
@ -805,17 +806,17 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive)
switch (ComboBox_GetCurItemData(hFileSystem)) { switch (ComboBox_GetCurItemData(hFileSystem)) {
case FS_FAT16: case FS_FAT16:
if (buffer[0x1c2] == 0x0e) { if (buffer[0x1c2] == 0x0e) {
uprintf("Partition is already FAT16 LBA...\n"); uprintf("Partition is already FAT16 LBA...");
} else if ((buffer[0x1c2] != 0x04) && (buffer[0x1c2] != 0x06)) { } else if ((buffer[0x1c2] != 0x04) && (buffer[0x1c2] != 0x06)) {
uprintf("Warning: converting a non FAT16 partition to FAT16 LBA: FS type=0x%02x\n", buffer[0x1c2]); uprintf("Warning: converting a non FAT16 partition to FAT16 LBA: FS type=0x%02x", buffer[0x1c2]);
} }
buffer[0x1c2] = 0x0e; buffer[0x1c2] = 0x0e;
break; break;
case FS_FAT32: case FS_FAT32:
if (buffer[0x1c2] == 0x0c) { if (buffer[0x1c2] == 0x0c) {
uprintf("Partition is already FAT32 LBA...\n"); uprintf("Partition is already FAT32 LBA...");
} else if (buffer[0x1c2] != 0x0b) { } else if (buffer[0x1c2] != 0x0b) {
uprintf("Warning: converting a non FAT32 partition to FAT32 LBA: FS type=0x%02x\n", buffer[0x1c2]); uprintf("Warning: converting a non FAT32 partition to FAT32 LBA: FS type=0x%02x", buffer[0x1c2]);
} }
buffer[0x1c2] = 0x0c; buffer[0x1c2] = 0x0c;
break; break;
@ -824,11 +825,11 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive)
// Set first partition bootable - masquerade as per the DiskID selected // Set first partition bootable - masquerade as per the DiskID selected
buffer[0x1be] = IsChecked(IDC_RUFUS_MBR) ? buffer[0x1be] = IsChecked(IDC_RUFUS_MBR) ?
(BYTE)ComboBox_GetCurItemData(hDiskID):0x80; (BYTE)ComboBox_GetCurItemData(hDiskID):0x80;
uprintf("Set bootable USB partition as 0x%02X\n", buffer[0x1be]); uprintf("Set bootable USB partition as 0x%02X", buffer[0x1be]);
} }
if (!write_sectors(hPhysicalDrive, SelectedDrive.SectorSize, 0, 1, buffer)) { if (!write_sectors(hPhysicalDrive, SelectedDrive.SectorSize, 0, 1, buffer)) {
uprintf("Could not write MBR\n"); uprintf("Could not write MBR");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out; goto out;
} }
@ -897,7 +898,7 @@ windows_mbr:
notify: notify:
// Tell the system we've updated the disk properties // Tell the system we've updated the disk properties
if (!DeviceIoControl(hPhysicalDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL)) if (!DeviceIoControl(hPhysicalDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL))
uprintf("Failed to notify system about disk properties update: %s\n", WindowsErrorString()); uprintf("Failed to notify system about disk properties update: %s", WindowsErrorString());
out: out:
safe_mm_free(buffer); safe_mm_free(buffer);
@ -1022,7 +1023,7 @@ BOOL WritePBR(HANDLE hLogicalVolume)
} else if (boot_type == BT_REACTOS) { } else if (boot_type == BT_REACTOS) {
if (!write_fat_16_ros_br(fp, 0)) break; if (!write_fat_16_ros_br(fp, 0)) break;
} else if ((boot_type == BT_IMAGE) && HAS_KOLIBRIOS(img_report)) { } else if ((boot_type == BT_IMAGE) && HAS_KOLIBRIOS(img_report)) {
uprintf("FAT16 is not supported for KolibriOS\n"); break; uprintf("FAT16 is not supported for KolibriOS"); break;
} else { } else {
if (!write_fat_16_br(fp, 0)) break; if (!write_fat_16_br(fp, 0)) break;
} }
@ -1034,11 +1035,11 @@ BOOL WritePBR(HANDLE hLogicalVolume)
uprintf(using_msg, bt_to_name(), "FAT32"); uprintf(using_msg, bt_to_name(), "FAT32");
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (!is_fat_32_fs(fp)) { if (!is_fat_32_fs(fp)) {
uprintf("New volume does not have a %s FAT32 boot sector - aborting\n", i?"secondary":"primary"); uprintf("New volume does not have a %s FAT32 boot sector - aborting", i?"secondary":"primary");
break; break;
} }
uprintf("Confirmed new volume has a %s FAT32 boot sector\n", i?"secondary":"primary"); uprintf("Confirmed new volume has a %s FAT32 boot sector", i?"secondary":"primary");
uprintf("Setting %s FAT32 boot sector for boot...\n", i?"secondary":"primary"); uprintf("Setting %s FAT32 boot sector for boot...", i?"secondary":"primary");
if (boot_type == BT_FREEDOS) { if (boot_type == BT_FREEDOS) {
if (!write_fat_32_fd_br(fp, 0)) break; if (!write_fat_32_fd_br(fp, 0)) break;
} else if (boot_type == BT_REACTOS) { } else if (boot_type == BT_REACTOS) {
@ -1061,10 +1062,10 @@ BOOL WritePBR(HANDLE hLogicalVolume)
case FS_NTFS: case FS_NTFS:
uprintf(using_msg, bt_to_name(), "NTFS"); uprintf(using_msg, bt_to_name(), "NTFS");
if (!is_ntfs_fs(fp)) { if (!is_ntfs_fs(fp)) {
uprintf("New volume does not have an NTFS boot sector - aborting\n"); uprintf("New volume does not have an NTFS boot sector - aborting");
break; break;
} }
uprintf("Confirmed new volume has an NTFS boot sector\n"); uprintf("Confirmed new volume has an NTFS boot sector");
if (!write_ntfs_br(fp)) break; if (!write_ntfs_br(fp)) break;
// Note: NTFS requires a full remount after writing the PBR. We dismount when we lock // Note: NTFS requires a full remount after writing the PBR. We dismount when we lock
// and also go through a forced remount, so that shouldn't be an issue. // and also go through a forced remount, so that shouldn't be an issue.
@ -1075,7 +1076,7 @@ BOOL WritePBR(HANDLE hLogicalVolume)
case FS_EXT4: case FS_EXT4:
return TRUE; return TRUE;
default: default:
uprintf("Unsupported FS for FS BR processing - aborting\n"); uprintf("Unsupported FS for FS BR processing - aborting");
break; break;
} }
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
@ -1813,7 +1814,7 @@ DWORD WINAPI FormatThread(void* param)
// we forcibly removed them, so add yet another explicit call to RemoveDriveLetters() // we forcibly removed them, so add yet another explicit call to RemoveDriveLetters()
RemoveDriveLetters(DriveIndex, FALSE, TRUE); RemoveDriveLetters(DriveIndex, FALSE, TRUE);
if (!MountVolume(drive_name, volume_name)) { if (!MountVolume(drive_name, volume_name)) {
uprintf("Could not remount %s as %c: %s\n", volume_name, toupper(drive_name[0]), WindowsErrorString()); uprintf("Could not remount %s as %c: %s", volume_name, toupper(drive_name[0]), WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_MOUNT_VOLUME); FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_MOUNT_VOLUME);
goto out; goto out;
} }
@ -1982,6 +1983,14 @@ DWORD WINAPI FormatThread(void* param)
} }
} }
// Copy any additonal files from an optional zip archive selected by the user
if (!IS_ERROR(FormatStatus)) {
UpdateProgress(OP_EXTRACT_ZIP, 0.0f);
drive_name[2] = 0;
if (fs_type < FS_EXT2 && !ExtractZip(archive_path, drive_name) && !IS_ERROR(FormatStatus))
uprintf("Warning: Could not copy additional files");
}
out: out:
if ((write_as_esp || write_as_ext) && volume_name != NULL) if ((write_as_esp || write_as_ext) && volume_name != NULL)
AltUnmountVolume(volume_name, TRUE); AltUnmountVolume(volume_name, TRUE);

View file

@ -83,7 +83,6 @@ typedef struct {
RUFUS_IMG_REPORT img_report; RUFUS_IMG_REPORT img_report;
int64_t iso_blocking_status = -1; int64_t iso_blocking_status = -1;
extern BOOL preserve_timestamps, enable_ntfs_compression; extern BOOL preserve_timestamps, enable_ntfs_compression;
extern char* archive_path;
extern HANDLE format_thread; extern HANDLE format_thread;
BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32; BOOL enable_iso = TRUE, enable_joliet = TRUE, enable_rockridge = TRUE, has_ldlinux_c32;
#define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0)
@ -425,7 +424,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
} }
} }
if (patched) if (patched)
uprintf(" Patched %s: '%s' ➔ '%s'\n", src, iso_label, usb_label); uprintf(" Patched %s: '%s' ➔ '%s'", src, iso_label, usb_label);
// Since version 8.2, and https://github.com/rhinstaller/anaconda/commit/a7661019546ec1d8b0935f9cb0f151015f2e1d95, // Since version 8.2, and https://github.com/rhinstaller/anaconda/commit/a7661019546ec1d8b0935f9cb0f151015f2e1d95,
// Red Hat derivatives have changed their CD-ROM detection policy which leads to the installation source // Red Hat derivatives have changed their CD-ROM detection policy which leads to the installation source
// not being found. So we need to use 'inst.repo' instead of 'inst.stage2' in the kernel options. // not being found. So we need to use 'inst.repo' instead of 'inst.stage2' in the kernel options.
@ -442,7 +441,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
} }
} }
if (patched) if (patched)
uprintf(" Patched %s: '%s' ➔ '%s'\n", src, "inst.stage2", "inst.repo"); uprintf(" Patched %s: '%s' ➔ '%s'", src, "inst.stage2", "inst.repo");
} }
} }
safe_free(iso_label); safe_free(iso_label);
@ -455,7 +454,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
(!img_report.has_efi_syslinux) && (dst = safe_strdup(src)) ) { (!img_report.has_efi_syslinux) && (dst = safe_strdup(src)) ) {
dst[nul_pos-12] = 's'; dst[nul_pos-11] = 'y'; dst[nul_pos-10] = 's'; dst[nul_pos-12] = 's'; dst[nul_pos-11] = 'y'; dst[nul_pos-10] = 's';
CopyFileA(src, dst, TRUE); CopyFileA(src, dst, TRUE);
uprintf("Duplicated %s to %s\n", src, dst); uprintf("Duplicated %s to %s", src, dst);
free(dst); free(dst);
} }
@ -467,7 +466,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
safe_sprintf(iso_label, MAX_PATH, "cd9660:/dev/iso9660/%s", img_report.label); safe_sprintf(iso_label, MAX_PATH, "cd9660:/dev/iso9660/%s", img_report.label);
safe_sprintf(usb_label, MAX_PATH, "msdosfs:/dev/msdosfs/%s", img_report.usb_label); safe_sprintf(usb_label, MAX_PATH, "msdosfs:/dev/msdosfs/%s", img_report.usb_label);
if (replace_in_token_data(src, "set", iso_label, usb_label, TRUE) != NULL) { if (replace_in_token_data(src, "set", iso_label, usb_label, TRUE) != NULL) {
uprintf(" Patched %s: '%s' ➔ '%s'\n", src, iso_label, usb_label); uprintf(" Patched %s: '%s' ➔ '%s'", src, iso_label, usb_label);
modified = TRUE; modified = TRUE;
} }
} }
@ -547,7 +546,7 @@ static void print_extracted_file(char* psz_fullpath, uint64_t file_length)
to_windows_path(psz_fullpath); to_windows_path(psz_fullpath);
nul_pos = strlen(psz_fullpath); nul_pos = strlen(psz_fullpath);
safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, TRUE, FALSE)); safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, TRUE, FALSE));
uprintf("Extracting: %s\n", psz_fullpath); uprintf("Extracting: %s", psz_fullpath);
safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, FALSE, FALSE)); safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, FALSE, FALSE));
PrintStatus(0, MSG_000, psz_fullpath); // MSG_000 is "%s" PrintStatus(0, MSG_000, psz_fullpath); // MSG_000 is "%s"
// Remove the appended size for extraction // Remove the appended size for extraction
@ -556,12 +555,6 @@ static void print_extracted_file(char* psz_fullpath, uint64_t file_length)
to_unix_path(psz_fullpath); to_unix_path(psz_fullpath);
} }
static void alt_print_extracted_file(const char* psz_fullpath, uint64_t file_length)
{
uprintf("Extracting: %s (%s)", psz_fullpath, SizeToHumanReadable(file_length, FALSE, FALSE));
PrintStatus(0, MSG_000, psz_fullpath);
}
// Convert from time_t to FILETIME // Convert from time_t to FILETIME
// Uses 3 static entries so that we can convert 3 concurrent values at the same time // Uses 3 static entries so that we can convert 3 concurrent values at the same time
static LPFILETIME __inline to_filetime(time_t t) static LPFILETIME __inline to_filetime(time_t t)
@ -604,8 +597,10 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
uint8_t* buf = malloc(ISO_BUFFER_SIZE); uint8_t* buf = malloc(ISO_BUFFER_SIZE);
int64_t read, file_length; int64_t read, file_length;
if ((p_udf_dirent == NULL) || (psz_path == NULL) || (buf == NULL)) if ((p_udf_dirent == NULL) || (psz_path == NULL) || (buf == NULL)) {
safe_free(buf);
return 1; return 1;
}
if (psz_path[0] == 0) if (psz_path[0] == 0)
UpdateProgressWithInfoInit(NULL, TRUE); UpdateProgressWithInfoInit(NULL, TRUE);
@ -746,8 +741,10 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
lsn_t lsn; lsn_t lsn;
int64_t file_length; int64_t file_length;
if ((p_iso == NULL) || (psz_path == NULL) || (buf == NULL)) if ((p_iso == NULL) || (psz_path == NULL) || (buf == NULL)) {
safe_free(buf);
return 1; return 1;
}
length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
if (length < 0) if (length < 0)
@ -1090,10 +1087,10 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
StrArrayCreate(&isolinux_path, 8); StrArrayCreate(&isolinux_path, 8);
PrintInfo(0, MSG_202); PrintInfo(0, MSG_202);
} else { } else {
uprintf("Extracting files...\n"); uprintf("Extracting files...");
IGNORE_RETVAL(_chdirU(app_data_dir)); IGNORE_RETVAL(_chdirU(app_data_dir));
if (total_blocks == 0) { if (total_blocks == 0) {
uprintf("Error: ISO has not been properly scanned.\n"); uprintf("Error: ISO has not been properly scanned.");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
goto out; goto out;
} }
@ -1223,7 +1220,7 @@ out:
img_report.sl_version = sl_version; img_report.sl_version = sl_version;
sl_index = i; sl_index = i;
} else if ((img_report.sl_version != sl_version) || (safe_strcmp(img_report.sl_version_ext, ext) != 0)) { } else if ((img_report.sl_version != sl_version) || (safe_strcmp(img_report.sl_version_ext, ext) != 0)) {
uprintf(" Found conflicting isolinux versions:\n '%s' (%d.%02d%s) vs '%s' (%d.%02d%s)", uprintf(" Found conflicting isolinux versions:\r\n '%s' (%d.%02d%s) vs '%s' (%d.%02d%s)",
isolinux_path.String[sl_index], SL_MAJOR(img_report.sl_version), SL_MINOR(img_report.sl_version), isolinux_path.String[sl_index], SL_MAJOR(img_report.sl_version), SL_MINOR(img_report.sl_version),
img_report.sl_version_ext, isolinux_path.String[i], SL_MAJOR(sl_version), SL_MINOR(sl_version), ext); img_report.sl_version_ext, isolinux_path.String[i], SL_MAJOR(sl_version), SL_MINOR(sl_version), ext);
// Workaround for Antergos and other ISOs, that have multiple Syslinux versions. // Workaround for Antergos and other ISOs, that have multiple Syslinux versions.
@ -1270,7 +1267,7 @@ out:
if (tmp != NULL) { if (tmp != NULL) {
for (i = 0; i < strlen(tmp); i++) for (i = 0; i < strlen(tmp); i++)
tmp[i] = (char)tolower(tmp[i]); tmp[i] = (char)tolower(tmp[i]);
uprintf(" Checking txtsetup.sif:\n OsLoadOptions = %s", tmp); uprintf(" Checking txtsetup.sif:\r\n OsLoadOptions = %s", tmp);
img_report.uses_minint = (strstr(tmp, "/minint") != NULL); img_report.uses_minint = (strstr(tmp, "/minint") != NULL);
} }
DeleteFileU(tmp_sif); DeleteFileU(tmp_sif);
@ -1401,12 +1398,6 @@ out:
} }
} }
update_md5sum(); update_md5sum();
if (archive_path != NULL) {
uprintf("● Adding files from %s", archive_path);
bled_init(256 * KB, NULL, NULL, NULL, NULL, alt_print_extracted_file, NULL);
bled_uncompress_to_dir(archive_path, dest_dir, BLED_COMPRESSION_ZIP);
bled_exit();
}
} }
iso9660_close(p_iso); iso9660_close(p_iso);
udf_close(p_udf); udf_close(p_udf);
@ -1606,7 +1597,7 @@ int iso9660_readfat(intptr_t pp, void *buf, size_t secsize, libfat_sector_t sec)
if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf,
p_private->lsn + (lsn_t)((p_private->sec_start * secsize) / ISO_BLOCKSIZE), ISO_NB_BLOCKS) p_private->lsn + (lsn_t)((p_private->sec_start * secsize) / ISO_BLOCKSIZE), ISO_NB_BLOCKS)
!= ISO_NB_BLOCKS * ISO_BLOCKSIZE) { != ISO_NB_BLOCKS * ISO_BLOCKSIZE) {
uprintf("Error reading ISO-9660 file %s at LSN %lu\n", img_report.efi_img_path, uprintf("Error reading ISO-9660 file %s at LSN %lu", img_report.efi_img_path,
(long unsigned int)(p_private->lsn + (p_private->sec_start * secsize) / ISO_BLOCKSIZE)); (long unsigned int)(p_private->lsn + (p_private->sec_start * secsize) / ISO_BLOCKSIZE));
return 0; return 0;
} }
@ -1640,7 +1631,7 @@ BOOL HasEfiImgBootLoaders(void)
} }
p_statbuf = iso9660_ifs_stat_translate(p_iso, img_report.efi_img_path); p_statbuf = iso9660_ifs_stat_translate(p_iso, img_report.efi_img_path);
if (p_statbuf == NULL) { if (p_statbuf == NULL) {
uprintf("Could not get ISO-9660 file information for file %s\n", img_report.efi_img_path); uprintf("Could not get ISO-9660 file information for file %s", img_report.efi_img_path);
goto out; goto out;
} }
p_private = malloc(sizeof(iso9660_readfat_private)); p_private = malloc(sizeof(iso9660_readfat_private));
@ -1651,7 +1642,7 @@ BOOL HasEfiImgBootLoaders(void)
p_private->sec_start = 0; p_private->sec_start = 0;
// Populate our initial buffer // Populate our initial buffer
if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, p_private->lsn, ISO_NB_BLOCKS) != ISO_NB_BLOCKS * ISO_BLOCKSIZE) { if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, p_private->lsn, ISO_NB_BLOCKS) != ISO_NB_BLOCKS * ISO_BLOCKSIZE) {
uprintf("Error reading ISO-9660 file %s at LSN %lu\n", img_report.efi_img_path, (long unsigned int)p_private->lsn); uprintf("Error reading ISO-9660 file %s at LSN %lu", img_report.efi_img_path, (long unsigned int)p_private->lsn);
goto out; goto out;
} }
lf_fs = libfat_open(iso9660_readfat, (intptr_t)p_private); lf_fs = libfat_open(iso9660_readfat, (intptr_t)p_private);
@ -1728,7 +1719,7 @@ BOOL DumpFatDir(const char* path, int32_t cluster)
} }
p_statbuf = iso9660_ifs_stat_translate(p_iso, img_report.efi_img_path); p_statbuf = iso9660_ifs_stat_translate(p_iso, img_report.efi_img_path);
if (p_statbuf == NULL) { if (p_statbuf == NULL) {
uprintf("Could not get ISO-9660 file information for file %s\n", img_report.efi_img_path); uprintf("Could not get ISO-9660 file information for file %s", img_report.efi_img_path);
goto out; goto out;
} }
p_private = malloc(sizeof(iso9660_readfat_private)); p_private = malloc(sizeof(iso9660_readfat_private));
@ -1739,7 +1730,7 @@ BOOL DumpFatDir(const char* path, int32_t cluster)
p_private->sec_start = 0; p_private->sec_start = 0;
// Populate our initial buffer // Populate our initial buffer
if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, p_private->lsn, ISO_NB_BLOCKS) != ISO_NB_BLOCKS * ISO_BLOCKSIZE) { if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, p_private->lsn, ISO_NB_BLOCKS) != ISO_NB_BLOCKS * ISO_BLOCKSIZE) {
uprintf("Error reading ISO-9660 file %s at LSN %lu\n", img_report.efi_img_path, (long unsigned int)p_private->lsn); uprintf("Error reading ISO-9660 file %s at LSN %lu", img_report.efi_img_path, (long unsigned int)p_private->lsn);
goto out; goto out;
} }
lf_fs = libfat_open(iso9660_readfat, (intptr_t)p_private); lf_fs = libfat_open(iso9660_readfat, (intptr_t)p_private);
@ -1764,7 +1755,7 @@ BOOL DumpFatDir(const char* path, int32_t cluster)
if (diritem.attributes & 0x10) { if (diritem.attributes & 0x10) {
// Directory => Create directory // Directory => Create directory
if (!CreateDirectoryU(target, 0) && (GetLastError() != ERROR_ALREADY_EXISTS)) { if (!CreateDirectoryU(target, 0) && (GetLastError() != ERROR_ALREADY_EXISTS)) {
uprintf("Could not create directory '%s': %s\n", target, WindowsErrorString()); uprintf("Could not create directory '%s': %s", target, WindowsErrorString());
continue; continue;
} }
if (!DumpFatDir(target, dirpos.cluster)) if (!DumpFatDir(target, dirpos.cluster))

View file

@ -1146,6 +1146,13 @@ static __inline const char* _filenameU(const char* path)
return path; return path;
} }
static __inline uint64_t _filesizeU(const char* path)
{
struct __stat64 stat64 = { 0 };
_stat64U(path, &stat64);
return stat64.st_size;
}
// returned UTF-8 string must be freed // returned UTF-8 string must be freed
static __inline char* getenvU(const char* varname) static __inline char* getenvU(const char* varname)
{ {

View file

@ -2512,17 +2512,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// For now only zip archives are supported. // For now only zip archives are supported.
if (GetKeyState(VK_CONTROL) & 0x8000) { if (GetKeyState(VK_CONTROL) & 0x8000) {
EXT_DECL(arch_ext, NULL, __VA_GROUP__("*.zip"), __VA_GROUP__(lmprintf(MSG_309))); EXT_DECL(arch_ext, NULL, __VA_GROUP__("*.zip"), __VA_GROUP__(lmprintf(MSG_309)));
if (image_path == NULL)
break;
archive_path = FileDialog(FALSE, NULL, &arch_ext, NULL); archive_path = FileDialog(FALSE, NULL, &arch_ext, NULL);
if (archive_path != NULL) { if (archive_path != NULL) {
struct __stat64 stat64 = { 0 };
_stat64U(archive_path, &stat64);
img_report.projected_size -= img_report.archive_size;
img_report.archive_size = stat64.st_size;
img_report.projected_size += img_report.archive_size;
uprintf("Using archive: %s (%s)", _filenameU(archive_path), uprintf("Using archive: %s (%s)", _filenameU(archive_path),
SizeToHumanReadable(img_report.archive_size, FALSE, FALSE)); SizeToHumanReadable(_filesizeU(archive_path), FALSE, FALSE));
} }
break; break;
} }

View file

@ -25,6 +25,8 @@
#pragma warning(disable: 6258) // I know what I'm using TerminateThread for #pragma warning(disable: 6258) // I know what I'm using TerminateThread for
#pragma warning(disable: 26451) // Stop bugging me with casts already! #pragma warning(disable: 26451) // Stop bugging me with casts already!
#pragma warning(disable: 28159) // I'll keep using GetVersionEx(), thank you very much... #pragma warning(disable: 28159) // I'll keep using GetVersionEx(), thank you very much...
// Enable C11's _Static_assert (requires VS2015 or later)
#define _Static_assert static_assert
#endif #endif
#pragma once #pragma once
@ -143,12 +145,6 @@
#define IMOP_WINTOGO 0x01 #define IMOP_WINTOGO 0x01
#define IMOP_PERSISTENCE 0x02 #define IMOP_PERSISTENCE 0x02
#if (_MSC_VER >= 1900)
#define _Static_assert static_assert
#else
#define _Static_assert(...)
#endif
#define ComboBox_GetCurItemData(hCtrl) ComboBox_GetItemData(hCtrl, ComboBox_GetCurSel(hCtrl)) #define ComboBox_GetCurItemData(hCtrl) ComboBox_GetItemData(hCtrl, ComboBox_GetCurSel(hCtrl))
#define safe_free(p) do {free((void*)p); p = NULL;} while(0) #define safe_free(p) do {free((void*)p); p = NULL;} while(0)
@ -267,6 +263,7 @@ enum action_type {
OP_FILE_COPY, OP_FILE_COPY,
OP_PATCH, OP_PATCH,
OP_FINALIZE, OP_FINALIZE,
OP_EXTRACT_ZIP,
OP_MAX OP_MAX
}; };
@ -395,7 +392,6 @@ typedef struct {
char efi_boot_path[ARCH_MAX][30]; // paths of detected UEFI bootloaders char efi_boot_path[ARCH_MAX][30]; // paths of detected UEFI bootloaders
char efi_img_path[128]; // path to an efi.img file char efi_img_path[128]; // path to an efi.img file
uint64_t image_size; uint64_t image_size;
uint64_t archive_size;
uint64_t projected_size; uint64_t projected_size;
int64_t mismatch_size; int64_t mismatch_size;
uint32_t wininst_version; uint32_t wininst_version;
@ -665,6 +661,7 @@ extern SIZE GetTextSize(HWND hCtrl, char* txt);
extern BOOL ExtractAppIcon(const char* filename, BOOL bSilent); extern BOOL ExtractAppIcon(const char* filename, BOOL bSilent);
extern BOOL ExtractDOS(const char* path); extern BOOL ExtractDOS(const char* path);
extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
extern BOOL ExtractZip(const char* src_zip, const char* dest_dir);
extern int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file, DWORD attributes); extern int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file, DWORD attributes);
extern BOOL CopySKUSiPolicy(const char* drive_name); extern BOOL CopySKUSiPolicy(const char* drive_name);
extern BOOL HasEfiImgBootLoaders(void); extern BOOL HasEfiImgBootLoaders(void);

View file

@ -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.5.2115" CAPTION "Rufus 4.5.2116"
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
@ -392,8 +392,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,5,2115,0 FILEVERSION 4,5,2116,0
PRODUCTVERSION 4,5,2115,0 PRODUCTVERSION 4,5,2116,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -411,13 +411,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.5.2115" VALUE "FileVersion", "4.5.2116"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2024 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.5.exe" VALUE "OriginalFilename", "rufus-4.5.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.5.2115" VALUE "ProductVersion", "4.5.2116"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -40,6 +40,7 @@
#include "resource.h" #include "resource.h"
#include "msapi_utf8.h" #include "msapi_utf8.h"
#include "localization.h" #include "localization.h"
#include "bled/bled.h"
#define FACILITY_WIM 322 #define FACILITY_WIM 322
#define DEFAULT_BASE_ADDRESS 0x100000000ULL #define DEFAULT_BASE_ADDRESS 0x100000000ULL
@ -52,6 +53,7 @@ const HANDLE hRufus = (HANDLE)0x0000005275667573ULL; // "\0\0\0Rufus"
HWND hStatus; HWND hStatus;
size_t ubuffer_pos = 0; size_t ubuffer_pos = 0;
char ubuffer[UBUFFER_SIZE]; // Buffer for ubpushf() messages we don't log right away char ubuffer[UBUFFER_SIZE]; // Buffer for ubpushf() messages we don't log right away
static uint64_t archive_size;
#pragma pack(push, 1) #pragma pack(push, 1)
typedef struct { typedef struct {
@ -346,8 +348,8 @@ char* SizeToHumanReadable(uint64_t size, BOOL copy_to_log, BOOL fake_units)
static_sprintf(str_size, "%s%d%s %s", dir, (int)hr_size, dir, _msg_table[MSG_020 - MSG_000]); static_sprintf(str_size, "%s%d%s %s", dir, (int)hr_size, dir, _msg_table[MSG_020 - MSG_000]);
} else if (fake_units) { } else if (fake_units) {
if (hr_size < 8) { if (hr_size < 8) {
static_sprintf(str_size, (fabs((hr_size*10.0)-(floor(hr_size + 0.5)*10.0)) < 0.5)?"%0.0f%s":"%0.1f%s", static_sprintf(str_size, (fabs((hr_size * 10.0) - (floor(hr_size + 0.5) * 10.0)) < 0.5) ?
hr_size, _msg_table[MSG_020+suffix-MSG_000]); "%0.0f%s":"%0.1f%s", hr_size, _msg_table[MSG_020 + suffix - MSG_000]);
} else { } else {
t = (double)upo2((uint16_t)hr_size); t = (double)upo2((uint16_t)hr_size);
i_size = (uint16_t)((fabs(1.0f - (hr_size / t)) < 0.05f) ? t : hr_size); i_size = (uint16_t)((fabs(1.0f - (hr_size / t)) < 0.05f) ? t : hr_size);
@ -882,3 +884,35 @@ out:
pfSymCleanup(hRufus); pfSymCleanup(hRufus);
return r; return r;
} }
static void print_extracted_file(const char* file_path, uint64_t file_length)
{
char str[MAX_PATH];
if (file_path == NULL)
return;
static_sprintf(str, "%s (%s)", file_path, SizeToHumanReadable(file_length, TRUE, FALSE));
uprintf("Extracting: %s", str);
PrintStatus(0, MSG_000, str); // MSG_000 is "%s"
}
static void update_progress(const uint64_t processed_bytes)
{
UpdateProgressWithInfo(OP_EXTRACT_ZIP, MSG_348, processed_bytes, archive_size);
}
// Extract content from a zip archive onto the designated directory or drive
BOOL ExtractZip(const char* src_zip, const char* dest_dir)
{
int64_t extracted_bytes = 0;
if (src_zip == NULL)
return FALSE;
archive_size = _filesizeU(src_zip);
if (bled_init(256 * KB, NULL, NULL, NULL, update_progress, print_extracted_file, &FormatStatus) != 0)
return FALSE;
uprintf("● Copying files from '%s'", src_zip);
extracted_bytes = bled_uncompress_to_dir(src_zip, dest_dir, BLED_COMPRESSION_ZIP);
bled_exit();
return (extracted_bytes > 0);
}

View file

@ -46,7 +46,7 @@ UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU;
HIMAGELIST hUpImageList, hDownImageList; HIMAGELIST hUpImageList, hDownImageList;
extern BOOL use_vds, appstore_version; extern BOOL use_vds, appstore_version;
extern int imop_win_sel; extern int imop_win_sel;
extern char* unattend_xml_path; extern char *unattend_xml_path, *archive_path;
int update_progress_type = UPT_PERCENT; int update_progress_type = UPT_PERCENT;
int advanced_device_section_height, advanced_format_section_height; int advanced_device_section_height, advanced_format_section_height;
// (empty) check box width, (empty) drop down width, button height (for and without dropdown match) // (empty) check box width, (empty) drop down width, button height (for and without dropdown match)
@ -1205,6 +1205,9 @@ void InitProgress(BOOL bOnlyFormat)
nb_slots[OP_FINALIZE] = ((selection_default == BT_IMAGE) && (fs_type == FS_NTFS)) ? 3 : 2; nb_slots[OP_FINALIZE] = ((selection_default == BT_IMAGE) && (fs_type == FS_NTFS)) ? 3 : 2;
} }
} }
if (archive_path != NULL) {
nb_slots[OP_EXTRACT_ZIP] = -1;
}
for (i = 0; i < OP_MAX; i++) { for (i = 0; i < OP_MAX; i++) {
if (nb_slots[i] > 0) { if (nb_slots[i] > 0) {