Compare commits

...

2 Commits

Author SHA1 Message Date
Pete Batard 5eae8a6441
[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.
2024-03-12 17:41:27 +00:00
Pete Batard abc33122a0
[iso] increase write buffer size to work around a bug in the AMI UEFI NTFS driver
* The AMI UEFI NTFS driver (version 0x10000), which is used in many modern systems from
  ASUS, Gigabyte, intel and so on, has a major bug whereas depending on the size of the
  buffers that are used to write the data onto the NTFS volume from Windows, as well as
  read the data from the NTFS volume from UEFI, the data being read may be incorrect
  (for details on this, see https://github.com/pbatard/AmiNtfsBug).
* Especially, it appears that if the size of the buffer used to write data on Windows is
  smaller than the NTFS cluster size, the bug may be triggered.
* Because of this, we increase the size of ISO write buffer to 64 KB since, per
  https://support.microsoft.com/en-gb/topic/default-cluster-size-for-ntfs-fat-and-exfat-9772e6f1-e31a-00d7-e18f-73169155af95
  this is the maximum cluster size that can be used for NTFS volumes.
* This increase in size should also help with performance somewhat.
* Also add support for C11's _Static_assert() which may come handy.
2024-03-12 12:53:30 +00:00
10 changed files with 169 additions and 107 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);

138
src/iso.c
View File

@ -52,9 +52,10 @@
#include "localization.h" #include "localization.h"
#include "bled/bled.h" #include "bled/bled.h"
// How often should we update the progress bar (in 2K blocks) as updating // How often should we update the progress bar, as updating the
// the progress bar for every block will bring extraction to a crawl // progress bar too frequently will bring extraction to a crawl
#define PROGRESS_THRESHOLD 128 _Static_assert(256 * KB >= ISO_BLOCKSIZE, "Can't set PROGRESS_THRESHOLD");
#define PROGRESS_THRESHOLD ((256 * KB) / ISO_BLOCKSIZE)
// Needed for UDF symbolic link testing // Needed for UDF symbolic link testing
#define S_IFLNK 0xA000 #define S_IFLNK 0xA000
@ -82,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)
@ -122,7 +122,7 @@ static const char* stupid_antivirus = " NOTE: This is usually caused by a poorl
const char* old_c32_name[NB_OLD_C32] = OLD_C32_NAMES; const char* old_c32_name[NB_OLD_C32] = OLD_C32_NAMES;
static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD; static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD;
static uint8_t joliet_level = 0; static uint8_t joliet_level = 0;
static uint64_t total_blocks, extra_blocks, nb_blocks; static uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks;
static BOOL scan_only = FALSE; static BOOL scan_only = FALSE;
static StrArray config_path, isolinux_path, modified_path; static StrArray config_path, isolinux_path, modified_path;
static char symlinked_syslinux[MAX_PATH]; static char symlinked_syslinux[MAX_PATH];
@ -424,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.
@ -441,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);
@ -454,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);
} }
@ -466,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;
} }
} }
@ -546,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
@ -555,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)
@ -594,15 +588,19 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
EXTRACT_PROPS props; EXTRACT_PROPS props;
BOOL r, is_identical; BOOL r, is_identical;
int length; int length;
size_t i; size_t i, nb;
char tmp[128], *psz_fullpath = NULL, *psz_sanpath = NULL; char tmp[128], *psz_fullpath = NULL, *psz_sanpath = NULL;
const char* psz_basename; const char* psz_basename;
udf_dirent_t *p_udf_dirent2; udf_dirent_t *p_udf_dirent2;
uint8_t buf[UDF_BLOCKSIZE]; _Static_assert(ISO_BUFFER_SIZE % UDF_BLOCKSIZE == 0,
"ISO_BUFFER_SIZE is not a multiple of UDF_BLOCKSIZE");
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)) 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);
@ -672,22 +670,26 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
goto out; goto out;
} else { } else {
while (file_length > 0) { while (file_length > 0) {
if (FormatStatus) goto out; if (FormatStatus)
memset(buf, 0, UDF_BLOCKSIZE); goto out;
read = udf_read_block(p_udf_dirent, buf, 1); nb = MIN(ISO_BUFFER_SIZE / UDF_BLOCKSIZE, (file_length + UDF_BLOCKSIZE - 1) / UDF_BLOCKSIZE);
read = udf_read_block(p_udf_dirent, buf, nb);
if (read < 0) { if (read < 0) {
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]); uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
goto out; goto out;
} }
buf_size = (DWORD)MIN(file_length, read); buf_size = (DWORD)MIN(file_length, read);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) { if (!r || (wr_size != buf_size)) {
uprintf(" Error writing file: %s", WindowsErrorString()); uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
goto out; goto out;
} }
file_length -= read; file_length -= wr_size;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0) nb_blocks += nb;
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks); UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks);
last_nb_blocks = nb_blocks;
}
} }
} }
if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)), if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)),
@ -706,6 +708,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
} }
safe_free(psz_fullpath); safe_free(psz_fullpath);
} }
safe_free(buf);
return 0; return 0;
out: out:
@ -713,6 +716,7 @@ out:
ISO_BLOCKING(safe_closehandle(file_handle)); ISO_BLOCKING(safe_closehandle(file_handle));
safe_free(psz_sanpath); safe_free(psz_sanpath);
safe_free(psz_fullpath); safe_free(psz_fullpath);
safe_free(buf);
return 1; return 1;
} }
@ -727,26 +731,30 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL; char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
char tmp[128], target_path[256]; char tmp[128], target_path[256];
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
unsigned char buf[ISO_BLOCKSIZE]; _Static_assert(ISO_BUFFER_SIZE % ISO_BLOCKSIZE == 0,
"ISO_BUFFER_SIZE is not a multiple of ISO_BLOCKSIZE");
uint8_t* buf = malloc(ISO_BUFFER_SIZE);
CdioListNode_t* p_entnode; CdioListNode_t* p_entnode;
iso9660_stat_t *p_statbuf; iso9660_stat_t *p_statbuf;
CdioISO9660FileList_t* p_entlist; CdioISO9660FileList_t* p_entlist = NULL;
size_t i; size_t i, nb;
lsn_t lsn; lsn_t lsn;
int64_t file_length; int64_t file_length;
if ((p_iso == NULL) || (psz_path == 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)
return 1; goto out;
psz_basename = &psz_fullpath[length]; psz_basename = &psz_fullpath[length];
p_entlist = iso9660_ifs_readdir(p_iso, psz_path); p_entlist = iso9660_ifs_readdir(p_iso, psz_path);
if (!p_entlist) { if (!p_entlist) {
uprintf("Could not access directory %s", psz_path); uprintf("Could not access directory %s", psz_path);
return 1; goto out;
} }
if (psz_path[0] == 0) if (psz_path[0] == 0)
@ -913,25 +921,29 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
uprintf(" Error writing file: %s", WindowsErrorString()); uprintf(" Error writing file: %s", WindowsErrorString());
goto out; goto out;
} }
} else for (i = 0; file_length > 0; i++) { } else for (i = 0; file_length > 0; i += nb) {
if (FormatStatus) goto out; if (FormatStatus)
memset(buf, 0, ISO_BLOCKSIZE); goto out;
lsn = p_statbuf->lsn + (lsn_t)i; lsn = p_statbuf->lsn + (lsn_t)i;
if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { nb = MIN(ISO_BUFFER_SIZE / ISO_BLOCKSIZE, (file_length + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE);
if (iso9660_iso_seek_read(p_iso, buf, lsn, (long)nb) != (nb * ISO_BLOCKSIZE)) {
uprintf(" Error reading ISO9660 file %s at LSN %lu", uprintf(" Error reading ISO9660 file %s at LSN %lu",
psz_iso_name, (long unsigned int)lsn); psz_iso_name, (long unsigned int)lsn);
goto out; goto out;
} }
buf_size = (DWORD)MIN(file_length, ISO_BLOCKSIZE); buf_size = (DWORD)MIN(file_length, ISO_BUFFER_SIZE);
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
if (!r) { if (!r || wr_size != buf_size) {
uprintf(" Error writing file: %s", WindowsErrorString()); uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
goto out; goto out;
} }
file_length -= ISO_BLOCKSIZE; file_length -= wr_size;
if (nb_blocks++ % PROGRESS_THRESHOLD == 0) nb_blocks += nb;
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks + UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
((fs_type != FS_NTFS) ? extra_blocks : 0)); ((fs_type != FS_NTFS) ? extra_blocks : 0));
last_nb_blocks = nb_blocks;
}
} }
if (preserve_timestamps) { if (preserve_timestamps) {
LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm)); LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm));
@ -951,8 +963,10 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
out: out:
ISO_BLOCKING(safe_closehandle(file_handle)); ISO_BLOCKING(safe_closehandle(file_handle));
if (p_entlist != NULL)
iso9660_filelist_free(p_entlist); iso9660_filelist_free(p_entlist);
safe_free(psz_sanpath); safe_free(psz_sanpath);
safe_free(buf);
return r; return r;
} }
@ -1039,20 +1053,19 @@ void GetGrubVersion(char* buf, size_t buf_size)
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan) BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
{ {
size_t i, j, size, sl_index = 0; const char* basedir[] = { "i386", "amd64", "minint" };
uint16_t sl_version; const char* tmp_sif = ".\\txtsetup.sif~";
FILE* fd;
int k, r = 1; int k, r = 1;
char* tmp, * buf, * ext, * spacing = " ";
char path[MAX_PATH], path2[16];
uint16_t sl_version;
size_t i, j, size, sl_index = 0;
FILE* fd;
iso9660_t* p_iso = NULL; iso9660_t* p_iso = NULL;
iso9660_pvd_t pvd; iso9660_pvd_t pvd;
udf_t* p_udf = NULL; udf_t* p_udf = NULL;
udf_dirent_t* p_udf_root; udf_dirent_t* p_udf_root;
char *tmp, *buf, *ext;
char path[MAX_PATH], path2[16];
const char* basedir[] = { "i386", "amd64", "minint" };
const char* tmp_sif = ".\\txtsetup.sif~";
iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL; iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
char* spacing = " ";
if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL)) if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL))
return FALSE; return FALSE;
@ -1074,14 +1087,15 @@ 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;
} }
nb_blocks = 0; nb_blocks = 0;
last_nb_blocks = 0;
iso_blocking_status = 0; iso_blocking_status = 0;
symlinked_syslinux[0] = 0; symlinked_syslinux[0] = 0;
StrArrayCreate(&modified_path, 8); StrArrayCreate(&modified_path, 8);
@ -1206,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.
@ -1253,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);
@ -1384,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);
@ -1589,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;
} }
@ -1623,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));
@ -1634,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);
@ -1711,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));
@ -1722,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);
@ -1747,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
@ -106,6 +108,7 @@
#define FAT32_CLUSTER_THRESHOLD 1.011f // For FAT32, cluster size changes don't occur at power of 2 boundaries but slightly above #define FAT32_CLUSTER_THRESHOLD 1.011f // For FAT32, cluster size changes don't occur at power of 2 boundaries but slightly above
#define DD_BUFFER_SIZE (32 * 1024 * 1024) // Minimum size of buffer to use for DD operations #define DD_BUFFER_SIZE (32 * 1024 * 1024) // Minimum size of buffer to use for DD operations
#define UBUFFER_SIZE 4096 #define UBUFFER_SIZE 4096
#define ISO_BUFFER_SIZE (64 * KB) // Buffer size used for ISO data extraction
#define RSA_SIGNATURE_SIZE 256 #define RSA_SIGNATURE_SIZE 256
#define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256) #define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256)
#if defined(RUFUS_TEST) #if defined(RUFUS_TEST)
@ -260,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
}; };
@ -388,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;
@ -658,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.2114" 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,2114,0 FILEVERSION 4,5,2116,0
PRODUCTVERSION 4,5,2114,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.2114" 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.2114" 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 {
@ -334,28 +336,28 @@ char* SizeToHumanReadable(uint64_t size, BOOL copy_to_log, BOOL fake_units)
double hr_size = (double)size; double hr_size = (double)size;
double t; double t;
uint16_t i_size; uint16_t i_size;
char **_msg_table = copy_to_log?default_msg_table:msg_table; char **_msg_table = copy_to_log ? default_msg_table : msg_table;
const double divider = fake_units?1000.0:1024.0; const double divider = fake_units ? 1000.0 : 1024.0;
for (suffix=0; suffix<MAX_SIZE_SUFFIXES-1; suffix++) { for (suffix = 0; suffix < MAX_SIZE_SUFFIXES - 1; suffix++) {
if (hr_size < divider) if (hr_size < divider)
break; break;
hr_size /= divider; hr_size /= divider;
} }
if (suffix == 0) { if (suffix == 0) {
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);
static_sprintf(str_size, "%s%d%s %s", dir, i_size, dir, _msg_table[MSG_020+suffix-MSG_000]); static_sprintf(str_size, "%s%d%s %s", dir, i_size, dir, _msg_table[MSG_020 + suffix - MSG_000]);
} }
} else { } else {
static_sprintf(str_size, (hr_size * 10.0 - (floor(hr_size) * 10.0)) < 0.5? static_sprintf(str_size, (hr_size * 10.0 - (floor(hr_size) * 10.0)) < 0.5?
"%s%0.0f%s %s":"%s%0.1f%s %s", dir, hr_size, dir, _msg_table[MSG_020+suffix-MSG_000]); "%s%0.0f%s %s":"%s%0.1f%s %s", dir, hr_size, dir, _msg_table[MSG_020 + suffix - MSG_000]);
} }
return str_size; return str_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) {