From: Eric Biggers Date: Thu, 24 Sep 2015 03:30:34 +0000 (-0500) Subject: system compression: force XPRESS4K on files accessed by Windows bootloader X-Git-Tag: v1.8.3~103 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=658ee1d652613948b29c412d75b3732801c2a235;ds=sidebyside system compression: force XPRESS4K on files accessed by Windows bootloader --- diff --git a/doc/man1/wimlib-imagex-apply.1 b/doc/man1/wimlib-imagex-apply.1 index 5bab69b6..b12f8fdb 100644 --- a/doc/man1/wimlib-imagex-apply.1 +++ b/doc/man1/wimlib-imagex-apply.1 @@ -400,6 +400,10 @@ 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. .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/src/win32_apply.c b/src/win32_apply.c index ce62d6af..5bc1e51f 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -151,6 +151,11 @@ 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; + /* Have we tried to enable short name support on the target volume yet? */ bool tried_to_enable_short_names; @@ -2264,6 +2269,22 @@ get_system_compression_format(int extract_flags) return FILE_PROVIDER_COMPRESSION_FORMAT_LZX; } + +static const wchar_t * +get_system_compression_format_string(int format) +{ + switch (format) { + case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K: + return L"XPRESS4K"; + case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K: + return L"XPRESS8K"; + case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K: + return L"XPRESS16K"; + default: + return L"LZX"; + } +} + static NTSTATUS set_system_compression(HANDLE h, int format) { @@ -2299,6 +2320,43 @@ 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[] = { + L"*winload.*", + L"*winresume.*", + L"\\Windows\\AppPatch\\drvmain.sdb", + L"\\Windows\\Fonts\\vgaoem.fon", + L"\\Windows\\Fonts\\vgasys.fon", + L"\\Windows\\INF\\errata.inf", + L"\\Windows\\System32\\config\\*", + L"\\Windows\\System32\\ntkrnlpa.exe", + L"\\Windows\\System32\\ntoskrnl.exe", + L"\\Windows\\System32\\bootvid.dll", + L"\\Windows\\System32\\ci.dll", + L"\\Windows\\System32\\hal*.dll", + L"\\Windows\\System32\\mcupdate_AuthenticAMD.dll", + L"\\Windows\\System32\\mcupdate_GenuineIntel.dll", + L"\\Windows\\System32\\pshed.dll", + L"\\Windows\\System32\\apisetschema.dll", + L"\\Windows\\System32\\api-ms-win*.dll", + L"\\Windows\\System32\\ext-ms-win*.dll", + L"\\Windows\\System32\\KernelBase.dll", + L"\\Windows\\System32\\drivers\\*.sys", + L"\\Windows\\System32\\*.nls", + L"\\Windows\\System32\\kbd*.dll", + L"\\Windows\\System32\\kd*.dll", + L"\\Windows\\System32\\clfs.sys", + 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 NTSTATUS set_system_compression_on_inode(struct wim_inode *inode, int format, struct win32_apply_ctx *ctx) @@ -2307,6 +2365,41 @@ 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) { + /* 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; + + if (calculate_dentry_full_path(dentry)) { + ERROR("Unable to compute file path!"); + return STATUS_NO_MEMORY; + } + + incompatible = match_pattern_list(dentry->d_full_path, + &xpress4k_only_patterns); + FREE(dentry->d_full_path); + dentry->d_full_path = NULL; + + if (incompatible) { + if (ctx->num_xpress4k_forced_files++ == 0) { + WARNING("For compatibility with the " + "Windows bootloader, some " + "files are being\n" + " compacted " + "using the XPRESS4K format " + "instead of the %"TS" format\n" + " you requested.", + get_system_compression_format_string(format)); + } + format = FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K; + break; + } + } + } + /* Open the extracted file. */ status = create_file(&h, GENERIC_READ | GENERIC_WRITE, NULL, 0, FILE_OPEN, 0,