From: Eric Biggers Date: Wed, 23 Apr 2014 17:20:41 +0000 (-0500) Subject: wimboot.c: Attach WoF driver if not running on target volume X-Git-Tag: v1.7.0~285 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=0a5a590bc1e8619efd1a0345adaf56a69027b44b;hp=0f7725a7cd14830b484b241d56f66bf7743d7351 wimboot.c: Attach WoF driver if not running on target volume --- diff --git a/src/wimboot.c b/src/wimboot.c index caefb654..beb4eab6 100644 --- a/src/wimboot.c +++ b/src/wimboot.c @@ -65,6 +65,47 @@ 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:) */ +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. * @@ -98,6 +139,7 @@ wimboot_alloc_data_source_id(const wchar_t *wim_path, int image, int ret; const wchar_t *prefix = L"\\??\\"; const size_t prefix_nchars = 4; + bool tried_to_attach_wof = false; ret = win32_get_drive_path(target, drive_path); if (ret) @@ -133,13 +175,14 @@ wimboot_alloc_data_source_id(const wchar_t *wim_path, int image, wmemcpy(&wim_info->wim_file_name[0], prefix, prefix_nchars); wmemcpy(&wim_info->wim_file_name[prefix_nchars], wim_path, wim_path_nchars); +retry_ioctl: h = CreateFile(drive_path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) { set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("Failed to open \"%ls\"", drive_path); + ERROR_WITH_ERRNO("Failed to open \"%ls\"", drive_path + 4); ret = WIMLIB_ERR_OPEN; goto out_free_in; } @@ -149,11 +192,29 @@ wimboot_alloc_data_source_id(const wchar_t *wim_path, int image, &data_source_id, sizeof(data_source_id), &bytes_returned, NULL)) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("Failed to add overlay source \"%ls\" " - "to volume \"%ls\"", wim_path, drive_path); - ret = WIMLIB_ERR_WIMBOOT; - goto out_close_handle; + DWORD err = GetLastError(); + if (err == ERROR_INVALID_FUNCTION) { + if (!tried_to_attach_wof) { + CloseHandle(h); + h = INVALID_HANDLE_VALUE; + tried_to_attach_wof = true; + if (try_to_attach_wof(drive_path + 4)) + goto retry_ioctl; + } + ERROR("The version of Windows you are running does not appear to support\n" + " the Windows Overlay File System Filter Driver. Therefore, wimlib\n" + " cannot apply WIMBoot information. Please run from Windows 8.1\n" + " Update 1 or later."); + ret = WIMLIB_ERR_UNSUPPORTED; + goto out_close_handle; + } else { + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("Failed to add overlay source \"%ls\" " + "to volume \"%ls\" (err=0x%08"PRIu32")", + wim_path, drive_path + 4, (uint32_t)err); + ret = WIMLIB_ERR_WIMBOOT; + goto out_close_handle; + } } if (bytes_returned != sizeof(data_source_id)) { @@ -161,7 +222,7 @@ wimboot_alloc_data_source_id(const wchar_t *wim_path, int image, ret = WIMLIB_ERR_WIMBOOT; ERROR("Unexpected result size when adding " "overlay source \"%ls\" to volume \"%ls\"", - wim_path, drive_path); + wim_path, drive_path + 4); goto out_close_handle; } @@ -219,7 +280,10 @@ wimboot_set_pointer(const wchar_t *path, u64 data_source_id, if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING, &in, sizeof(in), NULL, 0, &bytes_returned, NULL)) { - set_errno_from_GetLastError(); + DWORD err = GetLastError(); + set_errno_from_win32_error(err); + ERROR_WITH_ERRNO("\"%ls\": Couldn't set WIMBoot pointer data " + "(err=0x%08x)", path, (uint32_t)err); ret = WIMLIB_ERR_WIMBOOT; goto out_close_handle; }