X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwimboot.c;h=1650de99bb2fc99b986c603e31693ca125cc6acc;hp=914f20fbcbd66c02d645183661819e4e5c24296e;hb=ef03f83cc940d87f75140b7a8bc1199f4ff22aab;hpb=b996daae67735460fe19ca39029fdc8e2941f186 diff --git a/src/wimboot.c b/src/wimboot.c index 914f20fb..1650de99 100644 --- a/src/wimboot.c +++ b/src/wimboot.c @@ -13,34 +13,35 @@ /* * Copyright (C) 2014 Eric Biggers * - * This file is part of wimlib, a library for working with WIM files. + * This file is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) any + * later version. * - * wimlib is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) - * any later version. - * - * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * - * You should have received a copy of the GNU General Public License - * along with wimlib; if not, see http://www.gnu.org/licenses/. + * You should have received a copy of the GNU Lesser General Public License + * along with this file; if not, see http://www.gnu.org/licenses/. */ +#ifdef __WIN32__ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "wimlib/win32_common.h" -#include "wimlib/win32.h" + #include "wimlib/assert.h" +#include "wimlib/blob_table.h" +#include "wimlib/inode.h" #include "wimlib/error.h" -#include "wimlib/lookup_table.h" #include "wimlib/util.h" #include "wimlib/wimboot.h" +#include "wimlib/win32.h" #include "wimlib/wof.h" static HANDLE @@ -76,19 +77,17 @@ query_device(HANDLE h, DWORD code, void *out, DWORD out_size) */ static int query_partition_and_disk_info(const wchar_t *path, - PARTITION_INFORMATION_EX *part_info_ret, + PARTITION_INFORMATION_EX *part_info, DRIVE_LAYOUT_INFORMATION_EX *drive_info_ret) { - HANDLE h; wchar_t vol_name[] = L"\\\\.\\X:"; wchar_t disk_name[] = L"\\\\?\\PhysicalDriveXXXXXXXXXX"; - - PARTITION_INFORMATION_EX part_info; - size_t extents_size = sizeof(VOLUME_DISK_EXTENTS) + 4 * sizeof(DISK_EXTENT); - VOLUME_DISK_EXTENTS *extents = alloca(extents_size); - size_t drive_info_size = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + - 8 * sizeof(PARTITION_INFORMATION_EX); - DRIVE_LAYOUT_INFORMATION_EX *drive_info = alloca(drive_info_size); + HANDLE h = INVALID_HANDLE_VALUE; + VOLUME_DISK_EXTENTS *extents = NULL; + size_t extents_size; + DRIVE_LAYOUT_INFORMATION_EX *drive_info = NULL; + size_t drive_info_size; + int ret; wimlib_assert(path[0] != L'\0' && path[1] == L':'); @@ -96,36 +95,52 @@ query_partition_and_disk_info(const wchar_t *path, h = open_file(vol_name, GENERIC_READ); if (h == INVALID_HANDLE_VALUE) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't open volume device", vol_name); - return WIMLIB_ERR_OPEN; + win32_error(GetLastError(), L"\"%ls\": Can't open volume device", + vol_name); + ret = WIMLIB_ERR_OPEN; + goto out; } if (!query_device(h, IOCTL_DISK_GET_PARTITION_INFO_EX, - &part_info, sizeof(part_info))) + part_info, sizeof(PARTITION_INFORMATION_EX))) { - ERROR("\"%ls\": Can't get partition info (err=0x%08"PRIx32")", - vol_name, (u32)GetLastError()); - CloseHandle(h); - return WIMLIB_ERR_READ; + win32_error(GetLastError(), + L"\"%ls\": Can't get partition info", vol_name); + ret = WIMLIB_ERR_READ; + goto out; } - if (!query_device(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, - extents, extents_size)) - { - ERROR("\"%ls\": Can't get volume extent info (err=0x%08"PRIx32")", - vol_name, (u32)GetLastError()); - CloseHandle(h); - return WIMLIB_ERR_READ; + extents_size = sizeof(VOLUME_DISK_EXTENTS); + for (;;) { + extents_size += 4 * sizeof(DISK_EXTENT); + extents = MALLOC(extents_size); + if (!extents) { + ret = WIMLIB_ERR_NOMEM; + goto out; + } + + if (query_device(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, + extents, extents_size)) + break; + if (GetLastError() != ERROR_MORE_DATA) { + win32_error(GetLastError(), + L"\"%ls\": Can't get volume extent info", + vol_name); + ret = WIMLIB_ERR_READ; + goto out; + } + FREE(extents); } CloseHandle(h); + h = INVALID_HANDLE_VALUE; if (extents->NumberOfDiskExtents != 1) { ERROR("\"%ls\": This volume has %"PRIu32" disk extents, " "but this code is untested for more than 1", vol_name, (u32)extents->NumberOfDiskExtents); - return WIMLIB_ERR_UNSUPPORTED; + ret = WIMLIB_ERR_UNSUPPORTED; + goto out; } wsprintf(wcschr(disk_name, L'X'), L"%"PRIu32, @@ -133,52 +148,74 @@ query_partition_and_disk_info(const wchar_t *path, h = open_file(disk_name, GENERIC_READ); if (h == INVALID_HANDLE_VALUE) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't open disk device", disk_name); - return WIMLIB_ERR_OPEN; + win32_error(GetLastError(), + L"\"%ls\": Can't open disk device", disk_name); + ret = WIMLIB_ERR_OPEN; + goto out; } - if (!query_device(h, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, - drive_info, drive_info_size)) - { - ERROR("\"%ls\": Can't get disk info (err=0x%08"PRIx32")", - disk_name, (u32)GetLastError()); - CloseHandle(h); - return WIMLIB_ERR_READ; + drive_info_size = sizeof(DRIVE_LAYOUT_INFORMATION_EX); + for (;;) { + drive_info_size += 4 * sizeof(PARTITION_INFORMATION_EX); + drive_info = MALLOC(drive_info_size); + if (!drive_info) { + ret = WIMLIB_ERR_NOMEM; + goto out; + } + + if (query_device(h, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, + drive_info, drive_info_size)) + break; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + win32_error(GetLastError(), + L"\"%ls\": Can't get disk info", disk_name); + ret = WIMLIB_ERR_READ; + goto out; + } + FREE(drive_info); } + *drive_info_ret = *drive_info; /* doesn't include partitions */ CloseHandle(h); + h = INVALID_HANDLE_VALUE; - if (drive_info->PartitionStyle != part_info.PartitionStyle) { + if (drive_info->PartitionStyle != part_info->PartitionStyle) { ERROR("\"%ls\", \"%ls\": Inconsistent partition table type!", vol_name, disk_name); - return WIMLIB_ERR_UNSUPPORTED; + ret = WIMLIB_ERR_UNSUPPORTED; + goto out; } - if (part_info.PartitionStyle == PARTITION_STYLE_GPT) { - BUILD_BUG_ON(sizeof(part_info.Gpt.PartitionId) != - sizeof(drive_info->Gpt.DiskId)); - if (!memcmp(&part_info.Gpt.PartitionId, + if (part_info->PartitionStyle == PARTITION_STYLE_GPT) { + STATIC_ASSERT(sizeof(part_info->Gpt.PartitionId) == + sizeof(drive_info->Gpt.DiskId)); + if (!memcmp(&part_info->Gpt.PartitionId, &drive_info->Gpt.DiskId, sizeof(drive_info->Gpt.DiskId))) { ERROR("\"%ls\", \"%ls\": Partition GUID is the " "same as the disk GUID???", vol_name, disk_name); - return WIMLIB_ERR_UNSUPPORTED; + ret = WIMLIB_ERR_UNSUPPORTED; + goto out; } } - if (part_info.PartitionStyle != PARTITION_STYLE_MBR && - part_info.PartitionStyle != PARTITION_STYLE_GPT) + if (part_info->PartitionStyle != PARTITION_STYLE_MBR && + part_info->PartitionStyle != PARTITION_STYLE_GPT) { ERROR("\"%ls\": Unknown partition style 0x%08"PRIx32, - vol_name, (u32)part_info.PartitionStyle); - return WIMLIB_ERR_UNSUPPORTED; + vol_name, (u32)part_info->PartitionStyle); + ret = WIMLIB_ERR_UNSUPPORTED; + goto out; } - *part_info_ret = part_info; - *drive_info_ret = *drive_info; - return 0; + ret = 0; +out: + FREE(extents); + FREE(drive_info); + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + return ret; } /* @@ -256,23 +293,24 @@ write_wimoverlay_dat(const wchar_t *path, const void *contents, u32 size) h = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't open file for writing", path); + win32_error(GetLastError(), + L"\"%ls\": Can't open file for writing", path); return WIMLIB_ERR_OPEN; } + SetLastError(0); if (!WriteFile(h, contents, size, &bytes_written, NULL) || bytes_written != size) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't write file", path); + win32_error(GetLastError(), + L"\"%ls\": Can't write file", path); CloseHandle(h); return WIMLIB_ERR_WRITE; } if (!CloseHandle(h)) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't close handle", path); + win32_error(GetLastError(), + L"\"%ls\": Can't close handle", path); return WIMLIB_ERR_WRITE; } @@ -309,7 +347,7 @@ static u8 * fill_in_wimoverlay_dat(u8 *buf, const struct WimOverlay_dat_header *old_hdr, const wchar_t *wim_path, - const u8 wim_guid[WIM_GUID_LEN], + const u8 wim_guid[GUID_SIZE], int image, u64 new_data_source_id, const PARTITION_INFORMATION_EX *part_info, @@ -357,8 +395,8 @@ fill_in_wimoverlay_dat(u8 *buf, new_entry_1->entry_2_length = new_entry_2_size; new_entry_1->wim_type = WIM_BOOT_NOT_OS_WIM; new_entry_1->wim_index = image; - BUILD_BUG_ON(sizeof(new_entry_1->guid) != WIM_GUID_LEN); - memcpy(new_entry_1->guid, wim_guid, WIM_GUID_LEN); + STATIC_ASSERT(sizeof(new_entry_1->guid) == GUID_SIZE); + copy_guid(new_entry_1->guid, wim_guid); p += sizeof(struct WimOverlay_dat_entry_1); @@ -400,21 +438,21 @@ fill_in_wimoverlay_dat(u8 *buf, new_entry_2->disk.mbr.padding[1] = 0x00000000; new_entry_2->disk.mbr.padding[2] = 0x00000000; } else { - BUILD_BUG_ON(sizeof(new_entry_2->partition.gpt.part_unique_guid) != - sizeof(part_info->Gpt.PartitionId)); + STATIC_ASSERT(sizeof(new_entry_2->partition.gpt.part_unique_guid) == + sizeof(part_info->Gpt.PartitionId)); memcpy(new_entry_2->partition.gpt.part_unique_guid, &part_info->Gpt.PartitionId, sizeof(part_info->Gpt.PartitionId)); new_entry_2->partition_table_type = WIMOVERLAY_PARTITION_TYPE_GPT; - BUILD_BUG_ON(sizeof(new_entry_2->disk.gpt.disk_guid) != - sizeof(disk_info->Gpt.DiskId)); + STATIC_ASSERT(sizeof(new_entry_2->disk.gpt.disk_guid) == + sizeof(disk_info->Gpt.DiskId)); memcpy(new_entry_2->disk.gpt.disk_guid, &disk_info->Gpt.DiskId, sizeof(disk_info->Gpt.DiskId)); - BUILD_BUG_ON(sizeof(new_entry_2->disk.gpt.disk_guid) != - sizeof(new_entry_2->partition.gpt.part_unique_guid)); + STATIC_ASSERT(sizeof(new_entry_2->disk.gpt.disk_guid) == + sizeof(new_entry_2->partition.gpt.part_unique_guid)); } new_entry_2->unknown_0x58[0] = 0x00000000; new_entry_2->unknown_0x58[1] = 0x00000000; @@ -454,7 +492,7 @@ fill_in_wimoverlay_dat(u8 *buf, static int prepare_wimoverlay_dat(const struct WimOverlay_dat_header *old_hdr, const wchar_t *wim_path, - const u8 wim_guid[WIM_GUID_LEN], + const u8 wim_guid[GUID_SIZE], int image, void **new_contents_ret, u32 *new_contents_size_ret, @@ -548,7 +586,7 @@ retry: status = (*func_RtlCreateSystemVolumeInformationFolder)(&str); - err2 = (*func_RtlNtStatusToDosError)(status); + err2 = RtlNtStatusToDosError(status); if (err2 == ERROR_SUCCESS) { if (!already_retried) { already_retried = true; @@ -558,13 +596,11 @@ retry: err = err2; } } - set_errno_from_win32_error(err); - ERROR_WITH_ERRNO("\"%ls\": Can't open for reading", path); + win32_error(err, L"\"%ls\": Can't open for reading", path); return WIMLIB_ERR_OPEN; } if (!GetFileInformationByHandle(h, &info)) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't query metadata", path); + win32_error(GetLastError(), L"\"%ls\": Can't query metadata", path); CloseHandle(h); return WIMLIB_ERR_STAT; } @@ -578,11 +614,11 @@ retry: return WIMLIB_ERR_NOMEM; } + SetLastError(0); if (!ReadFile(h, contents, info.nFileSizeLow, &bytes_read, NULL) || bytes_read != info.nFileSizeLow) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("\"%ls\": Can't read data", path); + win32_error(GetLastError(), L"\"%ls\": Can't read data", path); CloseHandle(h); ret = WIMLIB_ERR_READ; goto out_free_contents; @@ -609,8 +645,8 @@ retry: if (wimlib_print_errors) { print_byte_field((const u8 *)hdr, sizeof(struct WimOverlay_dat_header), - stderr); - fputc('\n', stderr); + wimlib_error_file); + fputc('\n', wimlib_error_file); } ret = WIMLIB_ERR_UNSUPPORTED; goto out_free_contents; @@ -680,8 +716,9 @@ retry: path, i, entry_1->data_source_id); if (wimlib_print_errors) { print_byte_field((const u8 *)entry_2->wim_file_name, - wim_file_name_length, stderr); - fputc('\n', stderr); + wim_file_name_length, + wimlib_error_file); + fputc('\n', wimlib_error_file); } ret = WIMLIB_ERR_UNSUPPORTED; goto out_free_contents; @@ -718,8 +755,8 @@ retry: if (wimlib_print_errors) { print_byte_field((const u8 *)entry_2, entry_1->entry_2_length, - stderr); - fputc('\n', stderr); + wimlib_error_file); + fputc('\n', wimlib_error_file); } ret = WIMLIB_ERR_UNSUPPORTED; goto out_free_contents; @@ -754,17 +791,17 @@ out_free_contents: */ static int update_wimoverlay_manually(const wchar_t *drive, const wchar_t *wim_path, - const u8 wim_guid[WIM_GUID_LEN], + const u8 wim_guid[GUID_SIZE], int image, u64 *data_source_id_ret) { wchar_t path_main[] = L"A:\\System Volume Information\\WimOverlay.dat"; wchar_t path_backup[] = L"A:\\System Volume Information\\WimOverlay.backup"; wchar_t path_wimlib_backup[] = L"A:\\System Volume Information\\WimOverlay.wimlib_backup"; wchar_t path_new[] = L"A:\\System Volume Information\\WimOverlay.wimlib_new"; - void *old_contents; - void *new_contents; - u32 new_contents_size; - u64 new_data_source_id; + void *old_contents = NULL; + void *new_contents = NULL; + u32 new_contents_size = 0; + u64 new_data_source_id = -1; int ret; wimlib_assert(drive[0] != L'\0' && @@ -805,6 +842,7 @@ update_wimoverlay_manually(const wchar_t *drive, const wchar_t *wim_path, if (ret) { ERROR_WITH_ERRNO("Can't rename \"%ls\" => \"%ls\"", path_main, path_wimlib_backup); + ret = WIMLIB_ERR_RENAME; goto out_free_new_contents; } } @@ -814,6 +852,7 @@ update_wimoverlay_manually(const wchar_t *drive, const wchar_t *wim_path, if (ret) { ERROR_WITH_ERRNO("Can't rename \"%ls\" => \"%ls\"", path_new, path_main); + ret = WIMLIB_ERR_RENAME; } out_free_new_contents: FREE(new_contents); @@ -827,67 +866,6 @@ out: return ret; } -static int -win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7]) -{ - tchar *file_abspath; - - file_abspath = realpath(file_path, NULL); - if (!file_abspath) - return WIMLIB_ERR_NOMEM; - - if (file_abspath[0] == L'\0' || file_abspath[1] != L':') { - ERROR("\"%ls\": Path format not recognized", file_abspath); - FREE(file_abspath); - return WIMLIB_ERR_UNSUPPORTED; - } - - wsprintf(drive_path, L"\\\\.\\%lc:", file_abspath[0]); - FREE(file_abspath); - 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. * @@ -908,7 +886,7 @@ try_to_attach_wof(const wchar_t *drive) */ int wimboot_alloc_data_source_id(const wchar_t *wim_path, - const u8 wim_guid[WIM_GUID_LEN], + const u8 wim_guid[GUID_SIZE], int image, const wchar_t *target, u64 *data_source_id_ret, bool *wof_running_ret) { @@ -965,8 +943,8 @@ retry_ioctl: h = open_file(drive_path, GENERIC_WRITE); if (h == INVALID_HANDLE_VALUE) { - set_errno_from_GetLastError(); - ERROR_WITH_ERRNO("Failed to open \"%ls\"", drive_path + 4); + win32_error(GetLastError(), + L"Failed to open \"%ls\"", drive_path + 4); ret = WIMLIB_ERR_OPEN; goto out_free_in; } @@ -982,23 +960,20 @@ 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; 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"PRIx32")", - wim_path, drive_path + 4, (u32)err); + win32_error(err, L"Failed to add overlay source \"%ls\" " + "to volume \"%ls\"", wim_path, drive_path + 4); ret = WIMLIB_ERR_WIMBOOT; goto out_close_handle; } } if (bytes_returned != sizeof(data_source_id)) { - set_errno_from_win32_error(ERROR_INVALID_DATA); ret = WIMLIB_ERR_WIMBOOT; ERROR("Unexpected result size when adding " "overlay source \"%ls\" to volume \"%ls\"", @@ -1040,70 +1015,70 @@ out: * This turns it into a reparse point that redirects accesses to it, to the * corresponding resource in the WIM archive. * - * @attr - * Object attributes that specify the path to the file. - * @printable_name - * Printable representation of the path encoded in @attr. - * @lte - * Unnamed data stream of the file. + * @h + * Open handle to the file, with GENERIC_WRITE access. + * @blob + * The blob for the unnamed data stream of the file. * @data_source_id * Allocated identifier for the WIM data source on the destination volume. - * @lookup_table_hash - * SHA-1 message digest of the WIM's lookup table. + * @blob_table_hash + * SHA-1 message digest of the WIM's blob table. * @wof_running * %true if the WOF driver appears to be available and working; %false if * not. * - * Returns 0 on success, or a positive error code on failure. + * Returns %true on success, or %false on failure with GetLastError() set. */ -int -wimboot_set_pointer(OBJECT_ATTRIBUTES *attr, - const wchar_t *printable_name, - const struct wim_lookup_table_entry *lte, +bool +wimboot_set_pointer(HANDLE h, + const struct blob_descriptor *blob, u64 data_source_id, - const u8 lookup_table_hash[SHA1_HASH_SIZE], + const u8 blob_table_hash[SHA1_HASH_SIZE], bool wof_running) { - int ret; - HANDLE h = NULL; - NTSTATUS status; - IO_STATUS_BLOCK iosb; DWORD bytes_returned; - DWORD err; - - status = (*func_NtOpenFile)(&h, GENERIC_WRITE | SYNCHRONIZE, attr, - &iosb, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT | - FILE_OPEN_REPARSE_POINT | - FILE_SYNCHRONOUS_IO_NONALERT); - if (!NT_SUCCESS(status)) { - SetLastError((*func_RtlNtStatusToDosError)(status)); - goto fail; - } if (wof_running) { /* The WOF driver is running. We can create the reparse point * using FSCTL_SET_EXTERNAL_BACKING. */ - + unsigned int max_retries = 4; struct { struct wof_external_info wof_info; struct wim_provider_external_info wim_info; } in; + retry: + memset(&in, 0, sizeof(in)); + in.wof_info.version = WOF_CURRENT_VERSION; in.wof_info.provider = WOF_PROVIDER_WIM; in.wim_info.version = WIM_PROVIDER_CURRENT_VERSION; in.wim_info.flags = 0; in.wim_info.data_source_id = data_source_id; - copy_hash(in.wim_info.resource_hash, lte->hash); + copy_hash(in.wim_info.unnamed_data_stream_hash, blob->hash); - /* lookup_table_hash is not necessary */ + /* blob_table_hash is not necessary */ if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING, &in, sizeof(in), NULL, 0, &bytes_returned, NULL)) - goto fail; + { + /* Try to track down sporadic errors */ + if (wimlib_print_errors) { + WARNING("FSCTL_SET_EXTERNAL_BACKING failed (err=%u); data was %zu bytes:", + (u32)GetLastError(), sizeof(in)); + print_byte_field((const u8 *)&in, sizeof(in), wimlib_error_file); + putc('\n', wimlib_error_file); + } + if (--max_retries) { + WARNING("Retrying after 100ms..."); + Sleep(100); + goto retry; + } + WARNING("Too many retries; returning failure"); + return false; + } } else { /* The WOF driver is running. We need to create the reparse @@ -1119,11 +1094,11 @@ wimboot_set_pointer(OBJECT_ATTRIBUTES *attr, struct wim_provider_rpdata wim_info; } in; - BUILD_BUG_ON(sizeof(in) != 8 + - sizeof(struct wof_external_info) + - sizeof(struct wim_provider_rpdata)); + STATIC_ASSERT(sizeof(in) == 8 + + sizeof(struct wof_external_info) + + sizeof(struct wim_provider_rpdata)); - in.hdr.rptag = WIMLIB_REPARSE_TAG_WOF; + in.hdr.rptag = WIM_IO_REPARSE_TAG_WOF; in.hdr.rpdatalen = sizeof(in) - sizeof(in.hdr); in.hdr.rpreserved = 0; @@ -1133,15 +1108,15 @@ wimboot_set_pointer(OBJECT_ATTRIBUTES *attr, in.wim_info.version = 2; in.wim_info.flags = 0; in.wim_info.data_source_id = data_source_id; - copy_hash(in.wim_info.resource_hash, lte->hash); - copy_hash(in.wim_info.wim_lookup_table_hash, lookup_table_hash); - in.wim_info.stream_uncompressed_size = lte->size; - in.wim_info.stream_compressed_size = lte->rspec->size_in_wim; - in.wim_info.stream_offset_in_wim = lte->rspec->offset_in_wim; + copy_hash(in.wim_info.unnamed_data_stream_hash, blob->hash); + copy_hash(in.wim_info.blob_table_hash, blob_table_hash); + in.wim_info.unnamed_data_stream_size = blob->size; + in.wim_info.unnamed_data_stream_size_in_wim = blob->rdesc->size_in_wim; + in.wim_info.unnamed_data_stream_offset_in_wim = blob->rdesc->offset_in_wim; if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, &in, sizeof(in), NULL, 0, &bytes_returned, NULL)) - goto fail; + return false; /* We also need to create an unnamed data stream of the correct * size. Otherwise the file shows up as zero length. It can be @@ -1149,29 +1124,18 @@ wimboot_set_pointer(OBJECT_ATTRIBUTES *attr, * are unimportant. */ if (!DeviceIoControl(h, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytes_returned, NULL)) - goto fail; + return false; if (!SetFilePointerEx(h, - (LARGE_INTEGER){ .QuadPart = lte->size}, + (LARGE_INTEGER){ .QuadPart = blob->size}, NULL, FILE_BEGIN)) - goto fail; + return false; if (!SetEndOfFile(h)) - goto fail; + return false; } - ret = 0; - goto out; - -fail: - err = GetLastError(); - set_errno_from_win32_error(err); - ERROR_WITH_ERRNO("\"%ls\": Couldn't set WIMBoot pointer data " - "(err=%"PRIu32")", printable_name, (u32)err); - ret = WIMLIB_ERR_WIMBOOT; -out: - if (h) - (*func_NtClose)(h); - return ret; - + return true; } + +#endif /* __WIN32__ */