From cc108213611febd63c58d7ac77c1f7a1d686bca5 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Thu, 27 Aug 2015 18:22:27 +0100 Subject: [PATCH] [iso] disable To Go mode for Windows 10 ESD ISOs * Microsoft somehow managed to make their ESD WIMs incompatible with their own APIs (yes, EVEN the Windows 10 WIM API), so we must filter them out... --- src/iso.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rufus.c | 8 ++++++ src/rufus.h | 16 +++++++++++- src/rufus.rc | 10 +++---- 4 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/iso.c b/src/iso.c index 76121e70..443162c9 100644 --- a/src/iso.c +++ b/src/iso.c @@ -52,6 +52,8 @@ 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_syslinux_cfg; BOOLEAN is_grub_cfg; @@ -839,6 +841,9 @@ out: _unlink(tmp_sif); safe_free(tmp); } + if (HAS_INSTALL_WIM(iso_report)) { + iso_report.install_wim_version = GetInstallWimVersion(src_iso); + } if (iso_report.has_grub2) { // In case we have a GRUB2 based iso, we extract boot/grub/i386-pc/normal.mod to parse its version iso_report.grub2_version[0] = 0; @@ -1008,6 +1013,74 @@ out: return r; } +uint32_t GetInstallWimVersion(const char* iso) +{ + char *wim_path = NULL, *p, 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(&iso_report.install_wim_path[2]); + for (p = wim_path; p != 0; p++) + if (*p == '\\') *p = '/'; + + /* 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\n"); + 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\n", wim_path); + goto out; + } + if (udf_read_block(p_udf_file, buf, 1) != UDF_BLOCKSIZE) { + uprintf("Error reading UDF file %s\n", wim_path); + goto out; + } + r = wim_header[3]; + goto out; + +try_iso: + p_iso = iso9660_open(iso); + if (p_iso == NULL) { + uprintf("Unable to open image '%s'.\n", 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\n", wim_path); + goto out; + } + if (iso9660_iso_seek_read(p_iso, buf, p_statbuf->lsn, 1) != ISO_BLOCKSIZE) { + uprintf("Error reading ISO9660 file %s at LSN %lu\n", wim_path, (long unsigned int)p_statbuf->lsn); + goto out; + } + r = wim_header[3]; + +out: + if (p_statbuf != NULL) + safe_free(p_statbuf->rr.psz_symlink); + safe_free(p_statbuf); + if (p_udf_root != NULL) + udf_dirent_free(p_udf_root); + if (p_udf_file != NULL) + udf_dirent_free(p_udf_file); + if (p_iso != NULL) + iso9660_close(p_iso); + if (p_udf != NULL) + udf_close(p_udf); + safe_free(wim_path); + return bswap_32(r); +} + /* * The following is used for native ISO mounting in Windows 8 or later */ diff --git a/src/rufus.c b/src/rufus.c index b19b681c..1e0c7982 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -1002,6 +1002,14 @@ static void DisplayISOProps(void) uprintf(" Uses KolibriOS: %s", YesNo(iso_report.has_kolibrios)); uprintf(" Uses ReactOS: %s", YesNo(IS_REACTOS(iso_report))); uprintf(" Uses WinPE: %s%s", YesNo(IS_WINPE(iso_report.winpe)), (iso_report.uses_minint) ? " (with /minint)" : ""); + if (HAS_INSTALL_WIM(iso_report)) { + uprintf(" Uses Install.wim: Yes (version %d.%d.%d)", (iso_report.install_wim_version >> 24) & 0xff, + (iso_report.install_wim_version >> 16) & 0xff, (iso_report.install_wim_version >> 8) & 0xff); + // Microsoft somehow managed to make their ESD WIMs incompatible with their own APIs + // (yes, EVEN the Windows 10 APIs), so we must filter them out... + if (iso_report.install_wim_version >= MAX_WIM_VERSION) + uprintf(" Note: This WIM version is NOT compatible with Windows To Go"); + } // We don't support ToGo on Windows 7 or earlier, for lack of ISO mount capabilities // TODO: add install.wim extraction workaround for Windows 7 diff --git a/src/rufus.h b/src/rufus.h index 4b90a5ac..9f6e1f21 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -242,9 +242,10 @@ typedef struct { /* ISO details that the application may want */ #define WINPE_MININT 0x2A #define WINPE_I386 0x15 +#define MAX_WIM_VERSION 0x000E0000 #define HAS_SYSLINUX(r) (r.sl_version != 0) #define HAS_INSTALL_WIM(r) (r.install_wim_path[0] != 0) -#define HAS_TOGO(r) (r.has_bootmgr && r.has_efi && HAS_INSTALL_WIM(r)) +#define HAS_TOGO(r) (r.has_bootmgr && r.has_efi && HAS_INSTALL_WIM(r) && (r.install_wim_version < MAX_WIM_VERSION)) #define IS_WINPE(r) (((r & WINPE_MININT) == WINPE_MININT)||(( r & WINPE_I386) == WINPE_I386)) #define IS_WIN7_EFI(r) ((r.has_efi == 1) && HAS_INSTALL_WIM(r)) #define IS_REACTOS(r) (r.reactos_path[0] != 0) @@ -258,6 +259,7 @@ typedef struct { char reactos_path[128]; /* path to the ISO's freeldr.sys or setupldr.sys */ char install_wim_path[64]; /* path to install.wim or install.swm */ uint64_t projected_size; + uint32_t install_wim_version; uint8_t winpe; uint8_t has_efi; BOOLEAN has_4GB_file; @@ -461,6 +463,18 @@ static __inline void *_reallocf(void *ptr, size_t size) { return ret; } +static __inline uint16_t bswap_16(uint16_t x) { + return (x >> 8) | (x << 8); +} + +static __inline uint32_t bswap_32(uint32_t x) { + return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16)); +} + +static __inline uint64_t bswap_64(uint64_t x) { + return (((uint64_t) bswap_32(x & 0xffffffffull)) << 32) | (bswap_32(x >> 32)); +} + /* Hash tables */ typedef struct htab_entry { uint32_t used; diff --git a/src/rufus.rc b/src/rufus.rc index a5381ce7..59e0a5b4 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.3.704" +CAPTION "Rufus 2.3.705" FONT 8, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -317,8 +317,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,704,0 - PRODUCTVERSION 2,3,704,0 + FILEVERSION 2,3,705,0 + PRODUCTVERSION 2,3,705,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -335,13 +335,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.3.704" + VALUE "FileVersion", "2.3.705" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.3.704" + VALUE "ProductVersion", "2.3.705" END END BLOCK "VarFileInfo"