From: Eric Biggers Date: Thu, 24 Sep 2015 02:54:32 +0000 (-0500) Subject: system compression: try to attach WOF if compression fails X-Git-Tag: v1.8.3~105 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=0ae7e5538476723feb14f07a478b92210e24a21b system compression: try to attach WOF if compression fails --- diff --git a/include/wimlib/win32_common.h b/include/wimlib/win32_common.h index 9b873550..0e2db438 100644 --- a/include/wimlib/win32_common.h +++ b/include/wimlib/win32_common.h @@ -154,6 +154,9 @@ win32_path_to_nt_path(const wchar_t *win32_path, UNICODE_STRING *nt_path); extern int win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]); +extern bool +win32_try_to_attach_wof(const wchar_t *drive); + extern void win32_warning(DWORD err, const wchar_t *format, ...) _cold_attribute; diff --git a/src/wimboot.c b/src/wimboot.c index d4643d67..467f9fb3 100644 --- a/src/wimboot.c +++ b/src/wimboot.c @@ -866,47 +866,6 @@ out: return ret; } -/* Try to attach an instance of the Windows Overlay File System Filter Driver to - * the specified drive (such as C:) */ -static bool -try_to_attach_wof(const wchar_t *drive) -{ - HMODULE fltlib; - bool retval = false; - - /* Use FilterAttach() from Fltlib.dll. */ - - fltlib = LoadLibrary(L"Fltlib.dll"); - - if (!fltlib) { - WARNING("Failed to load Fltlib.dll"); - return retval; - } - - HRESULT (WINAPI *func_FilterAttach)(LPCWSTR lpFilterName, - LPCWSTR lpVolumeName, - LPCWSTR lpInstanceName, - DWORD dwCreatedInstanceNameLength, - LPWSTR lpCreatedInstanceName); - - func_FilterAttach = (void *)GetProcAddress(fltlib, "FilterAttach"); - - if (func_FilterAttach) { - HRESULT res; - - res = (*func_FilterAttach)(L"WoF", drive, NULL, 0, NULL); - - if (res == S_OK) - retval = true; - } else { - WARNING("FilterAttach() does not exist in Fltlib.dll"); - } - - FreeLibrary(fltlib); - - return retval; -} - /* * Allocate a WOF data source ID for a WIM file. * @@ -1001,7 +960,7 @@ retry_ioctl: CloseHandle(h); h = INVALID_HANDLE_VALUE; tried_to_attach_wof = true; - if (try_to_attach_wof(drive_path + 4)) + if (win32_try_to_attach_wof(drive_path + 4)) goto retry_ioctl; } ret = WIMLIB_ERR_UNSUPPORTED; diff --git a/src/win32_apply.c b/src/win32_apply.c index 7a93c419..ce62d6af 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -2299,6 +2299,38 @@ set_system_compression(HANDLE h, int format) return status; } +static NTSTATUS +set_system_compression_on_inode(struct wim_inode *inode, int format, + struct win32_apply_ctx *ctx) +{ + bool retried = false; + NTSTATUS status; + HANDLE h; + + /* Open the extracted file. */ + status = create_file(&h, GENERIC_READ | GENERIC_WRITE, NULL, + 0, FILE_OPEN, 0, + inode_first_extraction_dentry(inode), ctx); + + if (!NT_SUCCESS(status)) + return status; +retry: + /* Compress the file. If the attempt fails with "invalid device + * request", then attach wof.sys (or wofadk.sys) and retry. */ + status = set_system_compression(h, format); + if (unlikely(status == STATUS_INVALID_DEVICE_REQUEST && !retried)) { + wchar_t drive_path[7]; + if (!win32_get_drive_path(ctx->common.target, drive_path) && + win32_try_to_attach_wof(drive_path + 4)) { + retried = true; + goto retry; + } + } + + (*func_NtClose)(h); + return status; +} + /* * This function is called when doing a "compact-mode" extraction and we just * finished extracting a blob to one or more locations. For each location that @@ -2325,7 +2357,6 @@ handle_system_compression(struct blob_descriptor *blob, struct win32_apply_ctx * for (u32 i = 0; i < blob->out_refcnt; i++) { struct wim_inode *inode = targets[i].inode; struct wim_inode_stream *strm = targets[i].stream; - HANDLE h; NTSTATUS status; if (!stream_is_unnamed_data_stream(strm)) @@ -2334,14 +2365,9 @@ handle_system_compression(struct blob_descriptor *blob, struct win32_apply_ctx * if (will_externally_back_inode(inode, ctx, NULL, false) != 0) continue; - status = create_file(&h, GENERIC_READ | GENERIC_WRITE, NULL, - 0, FILE_OPEN, 0, - inode_first_extraction_dentry(inode), ctx); - - if (NT_SUCCESS(status)) { - status = set_system_compression(h, format); - (*func_NtClose)(h); - } + status = set_system_compression_on_inode(inode, format, ctx); + if (likely(NT_SUCCESS(status))) + continue; if (status == STATUS_INVALID_DEVICE_REQUEST) { WARNING( @@ -2353,16 +2379,14 @@ handle_system_compression(struct blob_descriptor *blob, struct win32_apply_ctx * return; } - if (!NT_SUCCESS(status)) { - ctx->num_system_compression_failures++; - if (ctx->num_system_compression_failures < 10) { - winnt_warning(status, L"\"%ls\": Failed to compress " - "extracted file using System Compression", - current_path(ctx)); - } else if (ctx->num_system_compression_failures == 10) { - WARNING("Suppressing further warnings about " - "System Compression failures."); - } + ctx->num_system_compression_failures++; + if (ctx->num_system_compression_failures < 10) { + winnt_warning(status, L"\"%ls\": Failed to compress " + "extracted file using System Compression", + current_path(ctx)); + } else if (ctx->num_system_compression_failures == 10) { + WARNING("Suppressing further warnings about " + "System Compression failures."); } } } diff --git a/src/win32_common.c b/src/win32_common.c index aa5be377..3b0d9e84 100644 --- a/src/win32_common.c +++ b/src/win32_common.c @@ -379,6 +379,48 @@ win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]) return 0; } +/* Try to attach an instance of the Windows Overlay File System Filter Driver to + * the specified drive (such as C:) */ +bool +win32_try_to_attach_wof(const wchar_t *drive) +{ + HMODULE fltlib; + bool retval = false; + + /* Use FilterAttach() from Fltlib.dll. */ + + fltlib = LoadLibrary(L"Fltlib.dll"); + + if (!fltlib) { + WARNING("Failed to load Fltlib.dll"); + return retval; + } + + HRESULT (WINAPI *func_FilterAttach)(LPCWSTR lpFilterName, + LPCWSTR lpVolumeName, + LPCWSTR lpInstanceName, + DWORD dwCreatedInstanceNameLength, + LPWSTR lpCreatedInstanceName); + + func_FilterAttach = (void *)GetProcAddress(fltlib, "FilterAttach"); + + if (func_FilterAttach) { + HRESULT res; + + res = (*func_FilterAttach)(L"WoF", drive, NULL, 0, NULL); + + if (res == S_OK) + retval = true; + } else { + WARNING("FilterAttach() does not exist in Fltlib.dll"); + } + + FreeLibrary(fltlib); + + return retval; +} + + static void windows_msg(u32 code, const wchar_t *format, va_list va, bool is_ntstatus, bool is_error)