diff --git a/src/iso.c b/src/iso.c index f0f8c552..af4c9938 100644 --- a/src/iso.c +++ b/src/iso.c @@ -44,6 +44,7 @@ #include "rufus.h" #include "ui.h" +#include "vhd.h" #include "drive.h" #include "libfat.h" #include "missing.h" @@ -69,8 +70,6 @@ _Static_assert(256 * KB >= ISO_BLOCKSIZE, "Can't set PROGRESS_THRESHOLD"); CdIo_t* cdio_open (const char* psz_source, driver_id_t driver_id) {return NULL;} void cdio_destroy (CdIo_t* p_cdio) {} -uint32_t GetInstallWimVersion(const char* iso); - typedef struct { BOOLEAN is_cfg; BOOLEAN is_conf; @@ -81,7 +80,10 @@ typedef struct { } EXTRACT_PROPS; RUFUS_IMG_REPORT img_report; +FILE* fd_md5sum = NULL; int64_t iso_blocking_status = -1; +uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks; + extern uint64_t md5sum_totalbytes; extern BOOL preserve_timestamps, enable_ntfs_compression, validate_md5sum; extern HANDLE format_thread; @@ -124,9 +126,7 @@ 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 uint8_t joliet_level = 0; static uint32_t md5sum_size = 0; -static uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks; static BOOL scan_only = FALSE; -static FILE* fd_md5sum = NULL; static StrArray config_path, isolinux_path; static char symlinked_syslinux[MAX_PATH], *md5sum_data = NULL, *md5sum_pos = NULL; @@ -161,6 +161,83 @@ static void log_handler (cdio_log_level_t level, const char *message) uprintf("libcdio: %s", message); } +// Returns TRUE if a path appears in md5sum.txt +static BOOL is_in_md5sum(char* path) +{ + BOOL found = FALSE; + char c[3], * p, * pos = md5sum_pos, * nul_pos; + + // If we are creating the md5sum file from scratch, every file is in it. + if (fd_md5sum != NULL) + return TRUE; + + // If we don't have an existing file at this stage, then no file is in it. + if (md5sum_size == 0 || md5sum_data == NULL) + return FALSE; + + // We should have a "X:/xyz" path + assert(path[1] == ':' && path[2] == '/'); + + // Modify the path to have " ./xyz" + c[0] = path[0]; + c[1] = path[1]; + path[0] = ' '; + path[1] = '.'; + + // Search for the string in the remainder of the md5sum.txt + // NB: md5sum_data is always NUL terminated. + p = strstr(pos, path); + // Cater for the case where we matched a partial string and look for the full one + while (p != NULL && p[strlen(path)] != '\n' && p[strlen(path)] != '\r' && p[strlen(path)] != '\0') { + pos = p + strlen(path); + p = strstr(pos, path); + } + found = (p != NULL); + // If not found in remainder and we have a remainder, loop to search from beginning + if (!found && pos != md5sum_data) { + nul_pos = pos; + c[2] = *nul_pos; + *nul_pos = 0; + p = strstr(md5sum_data, path); + while (p != NULL && p[strlen(path)] != '\n' && p[strlen(path)] != '\r' && p[strlen(path)] != '\0') { + pos = p + strlen(path); + p = strstr(pos, path); + } + *nul_pos = c[2]; + found = (p != NULL); + } + + path[0] = c[0]; + path[1] = c[1]; + if (found) + md5sum_pos = p + strlen(path); + return found; +} + +static void _print_extracted_file(char* psz_fullpath, uint64_t file_length, BOOL split) +{ + size_t nul_pos; + + if (psz_fullpath == NULL) + return; + // Replace slashes with backslashes and append the size to the path for UI display + to_windows_path(psz_fullpath); + nul_pos = strlen(psz_fullpath); + safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, TRUE, FALSE)); + uprintf(split ? "Splitting: %s" : "Extracting: %s", psz_fullpath); + safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, FALSE, FALSE)); + PrintStatus(0, MSG_000, psz_fullpath); // MSG_000 is "%s" + // Remove the appended size for extraction + psz_fullpath[nul_pos] = 0; + // ISO9660 cannot handle backslashes + to_unix_path(psz_fullpath); + // Update md5sum_totalbytes as needed + if (is_in_md5sum(psz_fullpath)) + md5sum_totalbytes += file_length; +} +#define print_extracted_file(p, l) _print_extracted_file(p, l, FALSE) +#define print_split_file(p, l) _print_extracted_file(p, l, TRUE) + /* * Scan and set ISO properties * Returns true if the the current file does not need to be processed further @@ -169,7 +246,7 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const const char* psz_fullpath, EXTRACT_PROPS *props) { size_t i, j, k, len; - char bootloader_name[32]; + char bootloader_name[32], path[MAX_PATH]; // Check for an isolinux/syslinux config file anywhere memset(props, 0, sizeof(EXTRACT_PROPS)); @@ -216,6 +293,26 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const uprintf("Skipping '%s' file from ISO image", psz_basename); return TRUE; } + + // Split a >4GB install.wim if the target filesystem is FAT + if (file_length >= 4 * GB && psz_dirname != NULL && IS_FAT(fs_type) && img_report.has_4GB_file == 0x81) { + if (safe_stricmp(&psz_dirname[max(0, ((int)safe_strlen(psz_dirname)) - + ((int)strlen(sources_str)))], sources_str) == 0) { + for (i = 0; i < ARRAYSIZE(wininst_name) - 1; i++) { + if (safe_stricmp(psz_basename, wininst_name[i]) == 0 && file_length >= 4 * GB) { + print_split_file((char*)psz_fullpath, file_length); + char* dst = safe_strdup(psz_fullpath); + dst[strlen(dst) - 3] = 's'; + dst[strlen(dst) - 2] = 'w'; + dst[strlen(dst) - 1] = 'm'; + static_sprintf(path, "%s|%s/%s", image_path, psz_dirname, psz_basename); + WimSplitFile(path, dst); + free(dst); + return TRUE; + } + } + } + } } else { // Scan-time checks // Check for GRUB artifacts for (i = 0; i < ARRAYSIZE(grub_dirname); i++) { @@ -327,6 +424,8 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const static_sprintf(img_report.wininst_path[img_report.wininst_index], "?:%s", psz_fullpath); img_report.wininst_index++; + if (file_length >= 4 * GB) + img_report.has_4GB_file |= 0x80; } } } @@ -357,7 +456,7 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const img_report.has_old_c32[i] = TRUE; } if (file_length >= 4 * GB) - img_report.has_4GB_file = TRUE; + img_report.has_4GB_file++; // Compute projected size needed (NB: ISO_BLOCKSIZE = UDF_BLOCKSIZE) if (file_length != 0) total_blocks += (file_length + (ISO_BLOCKSIZE - 1)) / ISO_BLOCKSIZE; @@ -498,81 +597,6 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha free(src); } -// Returns TRUE if a path appears in md5sum.txt -static BOOL is_in_md5sum(char* path) -{ - BOOL found = FALSE; - char c[3], *p, *pos = md5sum_pos, *nul_pos; - - // If we are creating the md5sum file from scratch, every file is in it. - if (fd_md5sum != NULL) - return TRUE; - - // If we don't have an existing file at this stage, then no file is in it. - if (md5sum_size == 0 || md5sum_data == NULL) - return FALSE; - - // We should have a "X:/xyz" path - assert(path[1] == ':' && path[2] == '/'); - - // Modify the path to have " ./xyz" - c[0] = path[0]; - c[1] = path[1]; - path[0] = ' '; - path[1] = '.'; - - // Search for the string in the remainder of the md5sum.txt - // NB: md5sum_data is always NUL terminated. - p = strstr(pos, path); - // Cater for the case where we matched a partial string and look for the full one - while (p != NULL && p[strlen(path)] != '\n' && p[strlen(path)] != '\r' && p[strlen(path)] != '\0') { - pos = p + strlen(path); - p = strstr(pos, path); - } - found = (p != NULL); - // If not found in remainder and we have a remainder, loop to search from beginning - if (!found && pos != md5sum_data) { - nul_pos = pos; - c[2] = *nul_pos; - *nul_pos = 0; - p = strstr(md5sum_data, path); - while (p != NULL && p[strlen(path)] != '\n' && p[strlen(path)] != '\r' && p[strlen(path)] != '\0') { - pos = p + strlen(path); - p = strstr(pos, path); - } - *nul_pos = c[2]; - found = (p != NULL); - } - - path[0] = c[0]; - path[1] = c[1]; - if (found) - md5sum_pos = p + strlen(path); - return found; -} - -static void print_extracted_file(char* psz_fullpath, uint64_t file_length) -{ - size_t nul_pos; - - if (psz_fullpath == NULL) - return; - // Replace slashes with backslashes and append the size to the path for UI display - to_windows_path(psz_fullpath); - nul_pos = strlen(psz_fullpath); - safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, TRUE, FALSE)); - uprintf("Extracting: %s", psz_fullpath); - safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(file_length, FALSE, FALSE)); - PrintStatus(0, MSG_000, psz_fullpath); // MSG_000 is "%s" - // Remove the appended size for extraction - psz_fullpath[nul_pos] = 0; - // ISO9660 cannot handle backslashes - to_unix_path(psz_fullpath); - // Update md5sum_totalbytes as needed - if (is_in_md5sum(psz_fullpath)) - md5sum_totalbytes += file_length; -} - // Convert from time_t to FILETIME // Uses 3 static entries so that we can convert 3 concurrent values at the same time static LPFILETIME __inline to_filetime(time_t t) @@ -1319,7 +1343,8 @@ out: safe_free(tmp); } if (HAS_WININST(img_report)) { - img_report.wininst_version = GetInstallWimVersion(src_iso); + static_sprintf(path, "%s|%s", image_path, &img_report.wininst_path[0][2]); + img_report.wininst_version = GetWimVersion(path); } if (img_report.has_grub2) { char grub_path[128]; @@ -1644,71 +1669,6 @@ out: return ret; } -uint32_t GetInstallWimVersion(const char* iso) -{ - char *wim_path = NULL, buf[UDF_BLOCKSIZE] = { 0 }; - uint32_t* wim_header = (uint32_t*)buf, r = 0xffffffff; - iso9660_t* p_iso = NULL; - udf_t* p_udf = NULL; - udf_dirent_t *p_udf_root = NULL, *p_udf_file = NULL; - iso9660_stat_t *p_statbuf = NULL; - - wim_path = safe_strdup(&img_report.wininst_path[0][2]); - if (wim_path == NULL) - goto out; - // UDF indiscriminately accepts slash or backslash delimiters, - // but ISO-9660 requires slash - to_unix_path(wim_path); - - // First try to open as UDF - fallback to ISO if it failed - p_udf = udf_open(iso); - if (p_udf == NULL) - goto try_iso; - - p_udf_root = udf_get_root(p_udf, true, 0); - if (p_udf_root == NULL) { - uprintf("Could not locate UDF root directory"); - goto out; - } - p_udf_file = udf_fopen(p_udf_root, wim_path); - if (!p_udf_file) { - uprintf("Could not locate file %s in ISO image", wim_path); - goto out; - } - if (udf_read_block(p_udf_file, buf, 1) != UDF_BLOCKSIZE) { - uprintf("Error reading UDF file %s", wim_path); - goto out; - } - r = wim_header[3]; - goto out; - -try_iso: - p_iso = iso9660_open_ext(iso, ISO_EXTENSION_MASK); - if (p_iso == NULL) { - uprintf("Could not open image '%s'", iso); - goto out; - } - p_statbuf = iso9660_ifs_stat_translate(p_iso, wim_path); - if (p_statbuf == NULL) { - uprintf("Could not get ISO-9660 file information for file %s", wim_path); - goto out; - } - if (iso9660_iso_seek_read(p_iso, buf, p_statbuf->lsn, 1) != ISO_BLOCKSIZE) { - uprintf("Error reading ISO-9660 file %s at LSN %d", wim_path, p_statbuf->lsn); - goto out; - } - r = wim_header[3]; - -out: - iso9660_stat_free(p_statbuf); - udf_dirent_free(p_udf_root); - udf_dirent_free(p_udf_file); - iso9660_close(p_iso); - udf_close(p_udf); - safe_free(wim_path); - return bswap_uint32(r); -} - #define ISO_NB_BLOCKS 16 typedef struct { iso9660_t* p_iso; diff --git a/src/rufus.c b/src/rufus.c index d316d991..8d22a9c4 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -188,8 +188,8 @@ static void SetAllowedFileSystems(void) break; case BT_IMAGE: allowed_filesystem[FS_NTFS] = TRUE; - // Don't allow anything besides NTFS if the image has a >4GB file or explicitly requires NTFS - if ((image_path != NULL) && (img_report.has_4GB_file || img_report.needs_ntfs)) + // Don't allow anything besides NTFS if the image is not compatible + if ((image_path != NULL) && !IS_FAT32_COMPAT(img_report)) break; if (!HAS_WINDOWS(img_report) || (target_type != TT_BIOS) || allow_dual_uefi_bios) { if (!HAS_WINTOGO(img_report) || (ComboBox_GetCurItemData(hImageOption) != IMOP_WIN_TO_GO)) { @@ -1561,7 +1561,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) MessageBoxExU(hMainDialog, lmprintf(MSG_189), lmprintf(MSG_099), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); goto out; } - if ((IS_FAT(fs_type)) && (img_report.has_4GB_file)) { + if (IS_FAT(fs_type) && !IS_FAT32_COMPAT(img_report)) { // This ISO image contains a file larger than 4GB file (FAT32) MessageBoxExU(hMainDialog, lmprintf(MSG_100), lmprintf(MSG_099), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid); goto out; @@ -3841,7 +3841,7 @@ extern int TestHashes(void); if (no_focus) continue; - // Alt +/- => Increase or decrease thread priority for format/file-copy/wim-apply operations + // Alt +/- => Increase or decrease thread priority for format/file-copy operations if ((msg.message == WM_SYSKEYDOWN) && ((msg.wParam == VK_OEM_PLUS) || (msg.wParam == VK_OEM_MINUS) || (msg.wParam == VK_ADD) || (msg.wParam == VK_SUBTRACT))) { int delta = ((msg.wParam == VK_OEM_PLUS) || (msg.wParam == VK_ADD)) ? +1 : -1; @@ -3912,6 +3912,7 @@ extern int TestHashes(void); WriteSettingBool(SETTING_ENABLE_WIN_DUAL_EFI_BIOS, allow_dual_uefi_bios); PrintStatusTimeout(lmprintf(MSG_266), allow_dual_uefi_bios); SetPartitionSchemeAndTargetSystem(FALSE); + SetFileSystemAndClusterSize(NULL); continue; } // Alt-F => Toggle detection of USB HDDs diff --git a/src/rufus.h b/src/rufus.h index f5e1e821..174e2a64 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -369,6 +369,7 @@ enum EFI_BOOT_TYPE { #define HAS_WIN7_EFI(r) ((r.has_efi == 1) && HAS_WININST(r)) #define IS_WINDOWS_1X(r) (r.has_bootmgr_efi && (r.win_version.major >= 10)) #define IS_WINDOWS_11(r) (r.has_bootmgr_efi && (r.win_version.major >= 11)) +#define IS_FAT32_COMPAT(r) ((r.has_4GB_file == 0 || (r.has_4GB_file == 0x81 && allow_dual_uefi_bios)) && !r.needs_ntfs) #define HAS_EFI_IMG(r) (r.efi_img_path[0] != 0) #define IS_DD_BOOTABLE(r) (r.is_bootable_img > 0) #define IS_DD_ONLY(r) ((r.is_bootable_img > 0) && (!r.is_iso || r.disable_iso)) @@ -437,7 +438,7 @@ typedef struct { uint8_t has_md5sum; uint8_t wininst_index; uint8_t has_symlinks; - BOOLEAN has_4GB_file; + uint8_t has_4GB_file; BOOLEAN has_long_filename; BOOLEAN has_deep_directories; BOOLEAN has_bootmgr; diff --git a/src/rufus.rc b/src/rufus.rc index 4a540eaf..d81117d8 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.8.2240" +CAPTION "Rufus 4.8.2241" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -407,8 +407,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,8,2240,0 - PRODUCTVERSION 4,8,2240,0 + FILEVERSION 4,8,2241,0 + PRODUCTVERSION 4,8,2241,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -426,13 +426,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.8.2240" + VALUE "FileVersion", "4.8.2241" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", " 2011-2025 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.8.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.8.2240" + VALUE "ProductVersion", "4.8.2241" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index c299967b..0798fa21 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Standard Windows function calls - * Copyright © 2013-2024 Pete Batard + * Copyright © 2013-2025 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -885,7 +885,17 @@ next_progress_line: }; } else { // TODO: Detect user cancellation here? - WaitForSingleObject(pi.hProcess, INFINITE); + switch (WaitForSingleObject(pi.hProcess, 1800000)) { + case WAIT_TIMEOUT: + uprintf("Command did not terminate within timeout duration"); + break; + case WAIT_OBJECT_0: + uprintf("Command was terminated by user"); + break; + default: + uprintf("Error while waiting for command to be terminated: %s", WindowsErrorString()); + break; + } } if (!GetExitCodeProcess(pi.hProcess, &ret)) diff --git a/src/stdio.c b/src/stdio.c index e42c63f2..5fa01f12 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -579,7 +579,17 @@ HANDLE CreateFileWithTimeout(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwS if (hThread != NULL) { if (WaitForSingleObject(hThread, dwTimeOut) == WAIT_TIMEOUT) { CancelSynchronousIo(hThread); - WaitForSingleObject(hThread, 30000); + switch (WaitForSingleObject(hThread, 30000)) { + case WAIT_TIMEOUT: + uprintf("File was not created within timeout duration"); + break; + case WAIT_OBJECT_0: + uprintf("File creation aborted by user"); + break; + default: + uprintf("Error while waiting for file to ne created: %s", WindowsErrorString()); + break; + } params.dwError = WAIT_TIMEOUT; } CloseHandle(hThread); diff --git a/src/vhd.c b/src/vhd.c index 1d5c4462..ef39afd7 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -49,10 +49,13 @@ extern char* save_image_type; extern BOOL ignore_boot_marker, has_ffu_support; extern RUFUS_DRIVE rufus_drive[MAX_DRIVES]; extern HANDLE format_thread; +extern FILE* fd_md5sum; +extern uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks; static char physical_path[128] = ""; static int progress_op = OP_FILE_COPY, progress_msg = MSG_267; static HANDLE mounted_handle = INVALID_HANDLE_VALUE; +static struct wimlib_progress_info_split last_split_progress; typedef struct { const char* ext; @@ -239,6 +242,29 @@ static enum wimlib_progress_status WimProgressFunc(enum wimlib_progress_msg msg_ if (info->extract.current_file_count >= info->extract.end_file_count) uprintf("\n"); break; + case WIMLIB_PROGRESS_MSG_SPLIT_BEGIN_PART: + last_split_progress = info->split; + uprintf("● %S", info->split.part_name); + break; + case WIMLIB_PROGRESS_MSG_SPLIT_END_PART: + if (fd_md5sum != NULL) { + // Don't bother computing the hash at write time - just do it post creation + uint8_t sum[MD5_HASHSIZE]; + char* filename = wchar_to_utf8(info->split.part_name); + if (filename != NULL) { + HashFile(HASH_MD5, filename, sum); + for (int j = 0; j < MD5_HASHSIZE; j++) + fprintf(fd_md5sum, "%02x", sum[j]); + fprintf(fd_md5sum, " ./%s\n", &filename[3]); + free(filename); + } + } + break; + case WIMLIB_PROGRESS_MSG_WRITE_STREAMS: + uint64_t completed_bytes = last_split_progress.completed_bytes + info->write_streams.completed_compressed_bytes; + nb_blocks = last_nb_blocks + completed_bytes / 2048; + UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks + extra_blocks); + break; default: break; } @@ -246,6 +272,27 @@ static enum wimlib_progress_status WimProgressFunc(enum wimlib_progress_msg msg_ return WIMLIB_PROGRESS_STATUS_CONTINUE; } +// Return the WIM version of an image +uint32_t GetWimVersion(const char* image) +{ + int r; + WIMStruct* wim; + struct wimlib_wim_info info; + + if (image == NULL) + return 0; + + r = wimlib_open_wimU(image, 0, &wim); + if (r == 0) { + r = wimlib_get_wim_info(wim, &info); + wimlib_free(wim); + if (r == 0) + return info.wim_version; + } + uprintf("WARNING: Could not get WIM version: Error %d", r); + return 0; +} + // Extract a file from a WIM image. Returns the allocated path of the extracted file or NULL on error. BOOL WimExtractFile(const char* image, int index, const char* src, const char* dst) { @@ -283,6 +330,29 @@ out: return (r == 0); } +// Split an install.wim for FAT32 limits +BOOL WimSplitFile(const char* src, const char* dst) +{ + int r = 1; + WIMStruct* wim; + + if ((src == NULL) || (dst == NULL)) + goto out; + + wimlib_global_init(0); + wimlib_set_print_errors(true); + r = wimlib_open_wimU(src, 0, &wim); + if (r == 0) { + wimlib_register_progress_function(wim, WimProgressFunc, NULL); + r = wimlib_splitU(wim, dst, 4094ULL * MB, WIMLIB_WRITE_FLAG_FSYNC); + wimlib_free(wim); + } + wimlib_global_cleanup(); + +out: + return (r == 0); +} + BOOL WimApplyImage(const char* image, int index, const char* dst) { int r = 1; diff --git a/src/vhd.h b/src/vhd.h index 4bf274d0..fccf4ca7 100644 --- a/src/vhd.h +++ b/src/vhd.h @@ -109,8 +109,10 @@ enum WIMMessage { WIM_MSG_ABORT_IMAGE = -1 }; +extern uint32_t GetWimVersion(const char* image); extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); extern BOOL WimApplyImage(const char* image, int index, const char* dst); +extern BOOL WimSplitFile(const char* src, const char* dst); extern int8_t IsBootableImage(const char* path); extern char* VhdMountImageAndGetSize(const char* path, uint64_t* disksize); #define VhdMountImage(path) VhdMountImageAndGetSize(path, NULL) diff --git a/src/wimlib/wimlib.h b/src/wimlib/wimlib.h index 7b2b6992..18cf7ef4 100644 --- a/src/wimlib/wimlib.h +++ b/src/wimlib/wimlib.h @@ -4434,6 +4434,20 @@ wimlib_split(WIMStruct *wim, uint64_t part_size, int write_flags); +#ifdef _RUFUS +static __inline int +wimlib_splitU(WIMStruct *wim, + const char *swm_name, + uint64_t part_size, + int write_flags) +{ + wconvert(swm_name); + int r = wimlib_split(wim, wswm_name, part_size, write_flags); + wfree(swm_name); + return r; +} +#endif + /** * @ingroup G_general *