From: Eric Biggers Date: Fri, 25 Sep 2015 00:57:06 +0000 (-0500) Subject: system compression: force bootloader-accessed files to uncompressed if image is not... X-Git-Tag: v1.8.3~100 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=2fed42ae0eee69e6352425c29ca2b12af99f8992 system compression: force bootloader-accessed files to uncompressed if image is not Windows 10 --- diff --git a/NEWS b/NEWS index 5a4d7ba2..7f9350a2 100644 --- a/NEWS +++ b/NEWS @@ -12,8 +12,8 @@ Version 1.8.3-BETA: Compact-mode extractions now work correctly with wofadk.sys on older versions of Windows. - For compatibility with the Windows bootloader, XPRESS4K - compression is now automatically forced on certain files. + For compatibility with the Windows bootloader, the requested + compression format now is overridden on certain files. Version 1.8.2: This release primarily contains various minor bug fixes and diff --git a/doc/man1/wimlib-imagex-apply.1 b/doc/man1/wimlib-imagex-apply.1 index b12f8fdb..ae519a6b 100644 --- a/doc/man1/wimlib-imagex-apply.1 +++ b/doc/man1/wimlib-imagex-apply.1 @@ -400,10 +400,9 @@ Exclusions are handled in the same way as with the \fB--wimboot\fR option. That is: if it exists, the [PrepopulateList] section of the file \\Windows\\System32\\WimBootCompress.ini in the WIM image will be read, and files matching any of the patterns in this section will not be compressed. -In addition, wimlib has a hardcoded list of files which it knows to, for -compatibility with the Windows bootloader which only supports -XPRESS4K-compressed files, always extract using either XPRESS4K or no -compression. +In addition, wimlib has a hardcoded list of files for which it knows, for +compatibility with the Windows bootloader, to override the requested compression +format. .SH NOTES \fIData integrity\fR: WIM files include SHA1 message digests for file data. \fBwimlib-imagex apply\fR calculates the SHA1 message digest of every file diff --git a/include/wimlib/xml.h b/include/wimlib/xml.h index 8562a0a9..209bb8c1 100644 --- a/include/wimlib/xml.h +++ b/include/wimlib/xml.h @@ -24,6 +24,9 @@ wim_info_set_wimboot(struct wim_info *info, int image, bool value); extern bool wim_info_get_wimboot(const struct wim_info *info, int image); +extern u64 +wim_info_get_windows_build_number(const struct wim_info *info, int image); + extern int xml_export_image(const struct wim_info *old_wim_info, int image, struct wim_info **new_wim_info_p, diff --git a/src/win32_apply.c b/src/win32_apply.c index 9a03aa11..c35fbec2 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -151,10 +151,16 @@ struct win32_apply_ctx { /* Number of files on which we couldn't set System Compression. */ unsigned long num_system_compression_failures; - /* The number of files on which we used XPRESS4K System Compression - * rather than a stronger variant, to be compatible with the Windows - * bootloader. */ - unsigned long num_xpress4k_forced_files; + /* The number of files which, for compatibility with the Windows + * bootloader, were not compressed using the requested system + * compression format. This includes matches with the hardcoded pattern + * list only; it does not include matches with patterns in + * [PrepopulateList]. */ + unsigned long num_system_compression_exclusions; + + /* The Windows build number of the image being applied, or 0 if unknown. + */ + u64 windows_build_number; /* Have we tried to enable short name support on the target volume yet? */ @@ -218,6 +224,14 @@ get_vol_flags(const wchar_t *target, DWORD *vol_flags_ret, } } +/* Is the image being extracted an OS image for Windows 10 or later? */ +static bool +is_image_windows_10_or_later(struct win32_apply_ctx *ctx) +{ + /* Note: if no build number is available, this returns false. */ + return ctx->windows_build_number >= 10240; +} + static const wchar_t * current_path(struct win32_apply_ctx *ctx); @@ -2320,11 +2334,9 @@ set_system_compression(HANDLE h, int format) return status; } -/* Hard-coded list of files which the Windows bootloader needs to access before - * the WOF driver has been loaded. Since the Windows bootloader only supports - * the XPRESS4K variant of System Compression, such files should not be - * compressed using other variants. */ -static wchar_t *xpress4k_only_pattern_strings[] = { +/* Hard-coded list of files which the Windows bootloader may need to access + * before the WOF driver has been loaded. */ +static wchar_t *bootloader_pattern_strings[] = { L"*winload.*", L"*winresume.*", L"\\Windows\\AppPatch\\drvmain.sdb", @@ -2355,9 +2367,9 @@ static wchar_t *xpress4k_only_pattern_strings[] = { L"\\Windows\\System32\\CodeIntegrity\\driver.stl", }; -static const struct string_set xpress4k_only_patterns = { - .strings = xpress4k_only_pattern_strings, - .num_strings = ARRAY_LEN(xpress4k_only_pattern_strings), +static const struct string_set bootloader_patterns = { + .strings = bootloader_pattern_strings, + .num_strings = ARRAY_LEN(bootloader_pattern_strings), }; static NTSTATUS @@ -2368,13 +2380,19 @@ set_system_compression_on_inode(struct wim_inode *inode, int format, NTSTATUS status; HANDLE h; - /* If needed, force the XPRESS4K format for this file. */ - if (format != FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K) { + /* If it may be needed for compatibility with the Windows bootloader, + * force this file to XPRESS4K or uncompressed format. The bootloader + * of Windows 10 supports XPRESS4K only; older versions don't support + * system compression at all. */ + if (!is_image_windows_10_or_later(ctx) || + format != FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K) + { /* We need to check the patterns against every name of the * inode, in case any of them match. */ struct wim_dentry *dentry; inode_for_each_extraction_alias(dentry, inode) { bool incompatible; + bool warned; if (calculate_dentry_full_path(dentry)) { ERROR("Unable to compute file path!"); @@ -2382,12 +2400,18 @@ set_system_compression_on_inode(struct wim_inode *inode, int format, } incompatible = match_pattern_list(dentry->d_full_path, - &xpress4k_only_patterns); + &bootloader_patterns); FREE(dentry->d_full_path); dentry->d_full_path = NULL; - if (incompatible) { - if (ctx->num_xpress4k_forced_files++ == 0) { + if (!incompatible) + continue; + + warned = (ctx->num_system_compression_exclusions++ > 0); + + if (is_image_windows_10_or_later(ctx)) { + /* Force to XPRESS4K */ + if (!warned) { WARNING("For compatibility with the " "Windows bootloader, some " "files are being\n" @@ -2399,7 +2423,19 @@ set_system_compression_on_inode(struct wim_inode *inode, int format, } format = FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K; break; + } else { + /* Force to uncompressed */ + if (!warned) { + WARNING("For compatibility with the " + "Windows bootloader, some " + "files will not\n" + " be compressed with" + " system compression " + "(\"compacted\")."); + } + return STATUS_SUCCESS; } + } } @@ -2902,6 +2938,9 @@ win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx) goto out; } + ctx->windows_build_number = wim_info_get_windows_build_number(ctx->common.wim->wim_info, + ctx->common.wim->current_image); + dentry_count = count_dentries(dentry_list); ret = start_file_structure_phase(&ctx->common, dentry_count); diff --git a/src/xml.c b/src/xml.c index 6450bb09..c71debbf 100644 --- a/src/xml.c +++ b/src/xml.c @@ -178,6 +178,12 @@ wim_info_get_wimboot(const struct wim_info *info, int image) return info->images[image - 1].wimboot; } +u64 +wim_info_get_windows_build_number(const struct wim_info *info, int image) +{ + return info->images[image - 1].windows_info.windows_version.build; +} + /* Architecture constants are from w64 mingw winnt.h */ #define PROCESSOR_ARCHITECTURE_INTEL 0 #define PROCESSOR_ARCHITECTURE_MIPS 1