From 8814944c357b23ad4ca413a33f9ee5f7eca65a1f Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 4 Oct 2022 11:58:30 +0100 Subject: [PATCH] [wue] improve Windows version reporting from ISO/.wim * Pick the version and build number directly from the install[.wim|.esd] XML index. This forces us to mount the ISO during scan, but it's the only way to get an accurate Build number... * Also drop linking to version.dll (along with the whole version.dll delay-loading shenanigans). --- .mingw/Makefile.am | 2 +- .mingw/Makefile.in | 2 +- .mingw/version.def | 4 -- .vs/rufus.vcxproj | 32 ++++++------ src/Makefile.am | 2 +- src/Makefile.in | 2 +- src/iso.c | 35 ------------- src/rufus.c | 34 +++++------- src/rufus.rc | 10 ++-- src/wue.c | 125 +++++++++++++++++++++++++++++++++++++++------ src/wue.h | 1 + 11 files changed, 147 insertions(+), 102 deletions(-) delete mode 100644 .mingw/version.def diff --git a/.mingw/Makefile.am b/.mingw/Makefile.am index 40c9e8be..c5ad8d7c 100644 --- a/.mingw/Makefile.am +++ b/.mingw/Makefile.am @@ -19,7 +19,7 @@ TARGET := $(word 1,$(subst -, ,$(TUPLE))) DEF_SUFFIX := $(if $(TARGET:x86_64=),.def,.def64) .PHONY: all -all: dwmapi-delaylib.lib version-delaylib.lib wintrust-delaylib.lib +all: dwmapi-delaylib.lib wintrust-delaylib.lib %.def64: %.def $(AM_V_SED) "s/@.*//" $< >$@ diff --git a/.mingw/Makefile.in b/.mingw/Makefile.in index 0dda8fb1..0af7e49c 100644 --- a/.mingw/Makefile.in +++ b/.mingw/Makefile.in @@ -367,7 +367,7 @@ uninstall-am: .PHONY: all -all: dwmapi-delaylib.lib version-delaylib.lib wintrust-delaylib.lib +all: dwmapi-delaylib.lib wintrust-delaylib.lib %.def64: %.def $(AM_V_SED) "s/@.*//" $< >$@ diff --git a/.mingw/version.def b/.mingw/version.def deleted file mode 100644 index d87e2606..00000000 --- a/.mingw/version.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS - GetFileVersionInfoW@16 - GetFileVersionInfoSizeW@8 - VerQueryValueA@16 diff --git a/.vs/rufus.vcxproj b/.vs/rufus.vcxproj index 15e92970..37441ae6 100644 --- a/.vs/rufus.vcxproj +++ b/.vs/rufus.vcxproj @@ -133,12 +133,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator true Windows MachineX86 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -158,12 +158,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator true Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -185,12 +185,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator true Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -217,12 +217,12 @@ /utf-8 $(ExternalCompilerOptions) %(AdditionalOptions) - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator true Windows MachineX64 - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -244,13 +244,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator false Windows MachineX86 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -272,13 +272,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator false Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\arm /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -302,13 +302,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;ole32.lib;advapi32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies) RequireAdministrator false Windows C:\Program Files (x86)\Windows Kits\10\Lib\10.0.16299.0\um\arm64 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;ole32.dll;advapi32.dll;gdi32.dll;shell32.dll;comdlg32.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) @@ -335,13 +335,13 @@ true - advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;version.lib;%(AdditionalDependencies) + advapi32.lib;comctl32.lib;comdlg32.lib;crypt32.lib;gdi32.lib;ole32.lib;dwmapi.lib;setupapi.lib;shell32.lib;shlwapi.lib;wintrust.lib;%(AdditionalDependencies) RequireAdministrator false Windows MachineX64 /BREPRO %(AdditionalOptions) - advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;version.dll;%(DelayLoadDLLs) + advapi32.dll;comctl32.dll;comdlg32.dll;crypt32.dll;gdi32.dll;ole32.dll;dwmapi.dll;setupapi.dll;shell32.dll;shlwapi.dll;wintrust.dll;%(DelayLoadDLLs) _UNICODE;UNICODE;RUFUS_LOC;%(PreprocessorDefinitions) diff --git a/src/Makefile.am b/src/Makefile.am index 7a461b6c..a97bdb7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller sys # As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version: NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomdlg32 -lcomctl32 -luuid # The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement: -VULNERABLE_LIBS = -ldwmapi-delaylib -lversion-delaylib -lwintrust-delaylib +VULNERABLE_LIBS = -ldwmapi-delaylib -lwintrust-delaylib noinst_PROGRAMS = rufus diff --git a/src/Makefile.in b/src/Makefile.in index 2a1be230..32421112 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -276,7 +276,7 @@ SUBDIRS = ../.mingw bled ext2fs ms-sys syslinux/libfat syslinux/libinstaller sys # As far as I can tell, the following libraries are *not* vulnerable to side-loading, so we link using their regular version: NONVULNERABLE_LIBS = -lsetupapi -lole32 -lgdi32 -lshlwapi -lcrypt32 -lcomdlg32 -lcomctl32 -luuid # The following libraries are vulnerable (or have an unknown vulnerability status), so we link using our delay-loaded replacement: -VULNERABLE_LIBS = -ldwmapi-delaylib -lversion-delaylib -lwintrust-delaylib +VULNERABLE_LIBS = -ldwmapi-delaylib -lwintrust-delaylib AM_V_WINDRES_0 = @echo " RC $@";$(WINDRES) AM_V_WINDRES_1 = $(WINDRES) AM_V_WINDRES_ = $(AM_V_WINDRES_$(AM_DEFAULT_VERBOSITY)) diff --git a/src/iso.c b/src/iso.c index 9236c315..3cbcda85 100644 --- a/src/iso.c +++ b/src/iso.c @@ -104,7 +104,6 @@ static const char* wininst_name[] = { "install.wim", "install.esd", "install.swm // If the disc was mastered properly, GRUB/EFI will take care of itself static const char* grub_dirname[] = { "/boot/grub/i386-pc", "/boot/grub2/i386-pc" }; static const char* grub_cfg[] = { "grub.cfg", "loopback.cfg" }; -static const char* compatresources_dll = "compatresources.dll"; static const char* menu_cfg = "menu.cfg"; // NB: Do not alter the order of the array below without validating hardcoded indexes in check_iso_props static const char* syslinux_cfg[] = { "isolinux.cfg", "syslinux.cfg", "extlinux.conf", "txt.cfg" }; @@ -290,9 +289,6 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const } } } - // Check for "compatresources.dll" in "###/sources/" - if (safe_stricmp(psz_basename, compatresources_dll) == 0) - img_report.has_compatresources_dll = TRUE; } } @@ -1164,37 +1160,6 @@ out: img_report.has_grub2 = 0; } } - if (img_report.has_compatresources_dll) { - // So that we don't have to extract the XML index from boot/install.wim - // to find if we're dealing with Windows 11, we isolate the version from - // sources/compatresources.dll, which is much faster... - VS_FIXEDFILEINFO* ver_info = NULL; - DWORD ver_handle = 0, ver_size; - UINT value_len = 0; - // coverity[swapped_arguments] - if (GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, path) != 0) { - // NB: Calling the GetFileVersion/VerQueryValue APIs create DLL sideloading issues. - // So make sure you delay-load 'version.dll' in your application if you use these. - size = (size_t)ExtractISOFile(src_iso, "sources/compatresources.dll", path, FILE_ATTRIBUTE_NORMAL); - ver_size = GetFileVersionInfoSizeU(path, &ver_handle); - if (ver_size != 0) { - buf = malloc(ver_size); - if ((buf != NULL) && GetFileVersionInfoU(path, ver_handle, ver_size, buf) && - VerQueryValueA(buf, "\\", (LPVOID)&ver_info, &value_len) && (value_len != 0)) { - if (ver_info->dwSignature == VS_FFI_SIGNATURE) { - img_report.win_version.major = HIWORD(ver_info->dwFileVersionMS); - img_report.win_version.minor = LOWORD(ver_info->dwFileVersionMS); - img_report.win_version.build = HIWORD(ver_info->dwFileVersionLS); - img_report.win_version.revision = LOWORD(ver_info->dwFileVersionLS); - if ((img_report.win_version.major == 10) && (img_report.win_version.build > 20000)) - img_report.win_version.major = 11; - } - } - free(buf); - } - DeleteFileU(path); - } - } StrArrayDestroy(&config_path); StrArrayDestroy(&isolinux_path); SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0); diff --git a/src/rufus.c b/src/rufus.c index f1ed421e..0a9cca72 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1274,7 +1274,7 @@ DWORD WINAPI ImageScanThread(LPVOID param) }; int i, len; uint8_t arch; - char tmp_path[MAX_PATH]; + char tmp_path[MAX_PATH], tmp_str[64]; if (image_path == NULL) goto out; @@ -1284,6 +1284,8 @@ DWORD WINAPI ImageScanThread(LPVOID param) memset(&img_report, 0, sizeof(img_report)); img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE); img_report.is_bootable_img = IsBootableImage(image_path); + if (img_report.wininst_index > 0 || img_report.is_windows_img) + PopulateWindowsVersion(); ComboBox_ResetContent(hImageOption); imop_win_sel = 0; @@ -1327,7 +1329,16 @@ DWORD WINAPI ImageScanThread(LPVOID param) } DeleteFileU(tmp_path); } - uprintf(" Image is %sa UEFI bootable Windows installation image", img_report.has_efi ? "" : "NOT "); + tmp_str[0] = 0; + if (img_report.win_version.major != 0) { + if (img_report.win_version.minor == 0) + static_sprintf(tmp_str, " %d (Build %d.%d)", img_report.win_version.major, + img_report.win_version.build, img_report.win_version.revision); + else + static_sprintf(tmp_str, " %d.%d (Build %d.%d)", img_report.win_version.major, + img_report.win_version.minor, img_report.win_version.build, img_report.win_version.revision); + } + uprintf(" Image is a %sUEFI bootable Windows%s installation image", img_report.has_efi ? "" : "NON-", tmp_str); } else if (IS_DD_BOOTABLE(img_report)) { if (img_report.is_bootable_img == 2) uprintf(" Image is a FORCED non-bootable image"); @@ -2254,24 +2265,6 @@ out: return ret; } -#ifdef RUFUS_TEST -extern BOOL ApplyWindowsCustomization(char drive_letter); - -static DWORD WINAPI TestThread(LPVOID param) -{ - static BOOL processing = FALSE; - - if (processing) { - uprintf("Test thread is already in progress!"); - ExitThread(1); - } - processing = TRUE; - ApplyWindowsCustomization('B'); - processing = FALSE; - ExitThread(0); -} -#endif - /* * Main dialog callback */ @@ -2308,7 +2301,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: #ifdef RUFUS_TEST if (LOWORD(wParam) == IDC_TEST) { - CreateThread(NULL, 0, TestThread, NULL, 0, NULL); break; } #endif diff --git a/src/rufus.rc b/src/rufus.rc index 2be9e53d..5c229ca8 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 3.21.1936" +CAPTION "Rufus 3.21.1937" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -395,8 +395,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,21,1936,0 - PRODUCTVERSION 3,21,1936,0 + FILEVERSION 3,21,1937,0 + PRODUCTVERSION 3,21,1937,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -414,13 +414,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.21.1936" + VALUE "FileVersion", "3.21.1937" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2022 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-3.21.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.21.1936" + VALUE "ProductVersion", "3.21.1937" END END BLOCK "VarFileInfo" diff --git a/src/wue.c b/src/wue.c index 5eb51d98..83735cb0 100644 --- a/src/wue.c +++ b/src/wue.c @@ -352,6 +352,110 @@ out: return r; } +/// +/// Populate the img_report Window version from an install[.wim|.esd] XML index +/// +/// The path of the extracted index XML. +/// The index of the occurrence to look for. +static void PopulateWindowsVersionFromXml(const char* xml_file, int index) +{ + char* val; + + val = get_token_data_file_indexed("MAJOR", xml_file, index); + img_report.win_version.major = (uint16_t)safe_atoi(val); + free(val); + val = get_token_data_file_indexed("MINOR", xml_file, index); + img_report.win_version.minor = (uint16_t)safe_atoi(val); + free(val); + val = get_token_data_file_indexed("BUILD", xml_file, index); + img_report.win_version.build = (uint16_t)safe_atoi(val); + free(val); + val = get_token_data_file_indexed("SPBUILD", xml_file, index); + img_report.win_version.revision = (uint16_t)safe_atoi(val); + free(val); + // Adjust versions so that we produce a more accurate report in the log + // (and yeah, I know we won't properly report Server, but I don't care) + if (img_report.win_version.major <= 5) { + // Don't want to support XP or earlier + img_report.win_version.major = 0; + img_report.win_version.minor = 0; + } else if (img_report.win_version.major == 6) { + // Don't want to support Vista + if (img_report.win_version.minor == 0) { + img_report.win_version.major = 0; + } else if (img_report.win_version.minor == 1) { + img_report.win_version.major = 7; + img_report.win_version.minor = 0; + } else if (img_report.win_version.minor == 2) { + img_report.win_version.major = 8; + img_report.win_version.minor = 0; + } else if (img_report.win_version.minor == 3) { + img_report.win_version.major = 8; + img_report.win_version.minor = 1; + } else if (img_report.win_version.minor == 4) { + img_report.win_version.major = 10; + img_report.win_version.minor = 0; + } + } else if (img_report.win_version.major == 10) { + if (img_report.win_version.build > 20000) + img_report.win_version.major = 11; + } +} + +/// +/// Populate the img_report Window version from an an install[.wim|.esd], mounting the +/// ISO if needed. Requires Windows 8 or later. +/// +/// (none) +/// TRUE on success, FALSE if we couldn't populate the version. +BOOL PopulateWindowsVersion(void) +{ + char *mounted_iso, mounted_image_path[128]; + char xml_file[MAX_PATH] = ""; + + img_report.win_version.major = 0; + img_report.win_version.minor = 0; + img_report.win_version.build = 0; + img_report.win_version.revision = 0; + + if ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck(TRUE) & 4) == 0)) + return FALSE; + + // If we're not using a straight install.wim, we need to mount the ISO to access it + if (!img_report.is_windows_img) { + mounted_iso = MountISO(image_path); + if (mounted_iso == NULL) { + uprintf("Could not mount Windows ISO for build number detection"); + return FALSE; + } + static_sprintf(mounted_image_path, "%s%s", mounted_iso, &img_report.wininst_path[0][2]); + } + + // Now take a look at the XML file in install.wim to list our versions + if ((GetTempFileNameU(temp_dir, APPLICATION_NAME, 0, xml_file) == 0) || (xml_file[0] == 0)) { + // Last ditch effort to get a tmp file - just extract it to the current directory + static_strcpy(xml_file, ".\\RufVXml.tmp"); + } + // GetTempFileName() may leave a file behind + DeleteFileU(xml_file); + + // Must use the Windows WIM API as 7z messes up the XML + if (!WimExtractFile_API(img_report.is_windows_img ? image_path : mounted_image_path, + 0, "[1].xml", xml_file, TRUE)) { + uprintf("Could not acquire WIM index"); + goto out; + } + + PopulateWindowsVersionFromXml(xml_file, 1); + +out: + DeleteFileU(xml_file); + if (!img_report.is_windows_img) + UnMountISO(); + + return (img_report.win_version.major != 0 && img_report.win_version.build != 0); +} + /// /// Checks which versions of Windows are available in an install image /// to set our extraction index. Asks the user to select one if needed. @@ -360,7 +464,7 @@ out: /// -2 on user cancel, -1 on other error, >=0 on success. int SetWinToGoIndex(void) { - char* mounted_iso, *val, mounted_image_path[128]; + char* mounted_iso, mounted_image_path[128]; char xml_file[MAX_PATH] = ""; char* install_names[MAX_WININST]; StrArray version_name, version_index; @@ -392,7 +496,7 @@ int SetWinToGoIndex(void) mounted_iso = MountISO(image_path); if (mounted_iso == NULL) { uprintf("Could not mount ISO for Windows To Go selection"); - return FALSE; + return -1; } static_sprintf(mounted_image_path, "%s%s", mounted_iso, &img_report.wininst_path[wininst_index][2]); } @@ -444,21 +548,8 @@ int SetWinToGoIndex(void) else wintogo_index = atoi(version_index.String[i - 1]); if (i > 0) { - // Get the version data from the XML index - val = get_token_data_file_indexed("MAJOR", xml_file, i); - img_report.win_version.major = (uint16_t)safe_atoi(val); - free(val); - val = get_token_data_file_indexed("MINOR", xml_file, i); - img_report.win_version.minor = (uint16_t)safe_atoi(val); - free(val); - val = get_token_data_file_indexed("BUILD", xml_file, i); - img_report.win_version.build = (uint16_t)safe_atoi(val); - free(val); - val = get_token_data_file_indexed("SPBUILD", xml_file, i); - img_report.win_version.revision = (uint16_t)safe_atoi(val); - free(val); - if ((img_report.win_version.major == 10) && (img_report.win_version.build > 20000)) - img_report.win_version.major = 11; + // re-populate the version data from the selected XML index + PopulateWindowsVersionFromXml(xml_file, i); // If we couldn't obtain the major and build, we have a problem if (img_report.win_version.major == 0 || img_report.win_version.build == 0) uprintf("Warning: Could not obtain version information from XML index (Nonstandard Windows image?)"); diff --git a/src/wue.h b/src/wue.h index 5b56ac32..d587cd37 100644 --- a/src/wue.h +++ b/src/wue.h @@ -30,3 +30,4 @@ BOOL ApplyWindowsCustomization(char drive_letter, int flags); int SetWinToGoIndex(void); BOOL SetupWinPE(char drive_letter); BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp); +BOOL PopulateWindowsVersion(void);