*
* Support for creating WIMBoot pointer files.
*
- * See http://technet.microsoft.com/en-us/library/dn594399.aspx for general
- * information about WIMBoot.
+ * For general information about WIMBoot, see
+ * https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-8.1-and-8/dn594399(v=win.10)
*
* Note that WIMBoot pointer files are actually implemented on top of the
- * Windows Overlay File System Filter (WOF). See wof.h for more info.
+ * Windows Overlay Filesystem filter (WOF). See wof.h for more info.
*/
/*
- * Copyright (C) 2014 Eric Biggers
+ * Copyright (C) 2014-2021 Eric Biggers
*
* 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
* details.
*
* 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/.
+ * along with this file; if not, see https://www.gnu.org/licenses/.
*/
-#ifdef __WIN32__
+#ifdef _WIN32
#ifdef HAVE_CONFIG_H
# include "config.h"
return ret;
}
-/*
- * Allocate a new WIM data source ID.
- *
- * @old_hdr
- * Previous WimOverlay.dat contents, or NULL if file did not exist.
- *
- * Returns the new data source ID.
- */
-static u64
-alloc_new_data_source_id(const struct WimOverlay_dat_header *old_hdr)
-{
- if (!old_hdr)
- return 0;
-
- for (u64 id = 0; ; id++) {
- for (u32 i = 0; i < old_hdr->num_entries_1; i++)
- if (id == old_hdr->entry_1s[i].data_source_id)
- goto next;
- return id;
- next:
- ;
- }
-}
-
/*
* Calculate the size of WimOverlay.dat with one entry added.
*
size_64 = sizeof(struct WimOverlay_dat_header);
if (old_hdr) {
- for (u32 i = 0; i < old_hdr->num_entries_1; i++) {
+ for (u32 i = 0; i < old_hdr->num_entries; i++) {
size_64 += sizeof(struct WimOverlay_dat_entry_1);
size_64 += old_hdr->entry_1s[i].entry_2_length;
}
new_hdr->magic = WIMOVERLAY_DAT_MAGIC;
new_hdr->wim_provider_version = WIM_PROVIDER_CURRENT_VERSION;
new_hdr->unknown_0x08 = 0x00000028;
- new_hdr->num_entries_1 = (old_hdr ? old_hdr->num_entries_1 : 0) + 1;
- new_hdr->num_entries_2 = (old_hdr ? old_hdr->num_entries_2 : 0) + 1;
- new_hdr->unknown_0x14 = 0x00000000;
+ new_hdr->num_entries = (old_hdr ? old_hdr->num_entries : 0) + 1;
+ new_hdr->next_data_source_id = (old_hdr ? old_hdr->next_data_source_id : 0) + 1;
p += sizeof(struct WimOverlay_dat_header);
/* Copy WIM-specific information for old entries */
entry_2_offset = sizeof(struct WimOverlay_dat_header) +
- (new_hdr->num_entries_1 * sizeof(struct WimOverlay_dat_entry_1));
+ (new_hdr->num_entries * sizeof(struct WimOverlay_dat_entry_1));
if (old_hdr) {
- for (u32 i = 0; i < old_hdr->num_entries_1; i++) {
+ for (u32 i = 0; i < old_hdr->num_entries; i++) {
new_entry_1 = (struct WimOverlay_dat_entry_1 *)p;
p = mempcpy(p, &old_hdr->entry_1s[i],
/* Copy WIM location information for old entries */
if (old_hdr) {
- for (u32 i = 0; i < old_hdr->num_entries_1; i++) {
+ for (u32 i = 0; i < old_hdr->num_entries; i++) {
wimlib_assert(new_hdr->entry_1s[i].entry_2_offset == p - buf);
wimlib_assert(old_hdr->entry_1s[i].entry_2_length ==
new_hdr->entry_1s[i].entry_2_length);
if (ret)
return ret;
- new_data_source_id = alloc_new_data_source_id(old_hdr);
+ new_data_source_id = old_hdr ? old_hdr->next_data_source_id : 0;
new_entry_2_size = sizeof(struct WimOverlay_dat_entry_2) +
((wcslen(wim_path) - 2 + 1) * sizeof(wchar_t));
return 0;
}
+static bool
+valid_wim_filename(const struct WimOverlay_dat_entry_2 *entry, size_t name_len)
+{
+ size_t i;
+
+ if (name_len % sizeof(wchar_t))
+ return false;
+ name_len /= sizeof(wchar_t);
+ if (name_len < 2)
+ return false;
+ for (i = 0; i < name_len && entry->wim_file_name[i] != 0; i++)
+ ;
+ return i == name_len - 1;
+}
+
/*
* Reads and validates a WimOverlay.dat file.
*
status = (*func_RtlCreateSystemVolumeInformationFolder)(&str);
- err2 = (*func_RtlNtStatusToDosError)(status);
+ err2 = RtlNtStatusToDosError(status);
if (err2 == ERROR_SUCCESS) {
if (!already_retried) {
already_retried = true;
if (hdr->magic != WIMOVERLAY_DAT_MAGIC ||
hdr->wim_provider_version != WIM_PROVIDER_CURRENT_VERSION ||
- hdr->unknown_0x08 != 0x00000028 ||
- (hdr->num_entries_1 != hdr->num_entries_2) ||
- hdr->unknown_0x14 != 0x00000000)
+ hdr->unknown_0x08 != 0x00000028)
{
ERROR("\"%ls\": Header contains unexpected data:", path);
if (wimlib_print_errors) {
goto out_free_contents;
}
- if ((u64)hdr->num_entries_1 * sizeof(struct WimOverlay_dat_entry_1) >
+ if ((u64)hdr->num_entries * sizeof(struct WimOverlay_dat_entry_1) >
info.nFileSizeLow - sizeof(struct WimOverlay_dat_header))
{
ERROR("\"%ls\": File is unexpectedly small "
"(only %"PRIu32" bytes, but has %"PRIu32" entries)",
- path, (u32)info.nFileSizeLow, hdr->num_entries_1);
+ path, (u32)info.nFileSizeLow, hdr->num_entries);
ret = WIMLIB_ERR_UNSUPPORTED;
goto out_free_contents;
}
- for (u32 i = 0; i < hdr->num_entries_1; i++) {
+ for (u32 i = 0; i < hdr->num_entries; i++) {
const struct WimOverlay_dat_entry_1 *entry_1;
const struct WimOverlay_dat_entry_2 *entry_2;
u32 wim_file_name_length;
entry_1 = &hdr->entry_1s[i];
+ if (entry_1->data_source_id >= hdr->next_data_source_id) {
+ ERROR("\"%ls\": value of next_data_source_id "
+ "(0x%016"PRIx64") is unexpected, since entry "
+ "%"PRIu32" has data source ID 0x%016"PRIx64,
+ path, hdr->next_data_source_id,
+ i, entry_1->data_source_id);
+ ret = WIMLIB_ERR_UNSUPPORTED;
+ goto out_free_contents;
+ }
+
if (((u64)entry_1->entry_2_offset +
(u64)entry_1->entry_2_length) >
info.nFileSizeLow)
wim_file_name_length = entry_1->entry_2_length -
sizeof(struct WimOverlay_dat_entry_2);
- if ((wim_file_name_length < 2 * sizeof(wchar_t)) ||
- (wim_file_name_length % sizeof(wchar_t) != 0) ||
- (wmemchr(entry_2->wim_file_name, L'\0',
- wim_file_name_length / sizeof(wchar_t))
- != &entry_2->wim_file_name[wim_file_name_length /
- sizeof(wchar_t) - 1]))
- {
+ if (!valid_wim_filename(entry_2, wim_file_name_length)) {
ERROR("\"%ls\": entry %"PRIu32" (2) "
"(data source ID 0x%016"PRIx64") "
"has invalid WIM file name",
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' &&
size_t wim_file_name_length;
void *in;
size_t insize;
- struct wof_external_info *wof_info;
- struct wim_provider_add_overlay_input *wim_info;
+ WOF_EXTERNAL_INFO *wof_info;
+ WIM_PROVIDER_ADD_OVERLAY_INPUT *wim_info;
+ wchar_t *WimFileName;
HANDLE h;
u64 data_source_id;
DWORD bytes_returned;
wim_file_name_length = sizeof(wchar_t) *
(wim_path_nchars + prefix_nchars);
- insize = sizeof(struct wof_external_info) +
- sizeof(struct wim_provider_add_overlay_input) +
- wim_file_name_length;
-
- in = MALLOC(insize);
+ insize = sizeof(*wof_info) + sizeof(*wim_info) + wim_file_name_length;
+ in = CALLOC(1, insize);
if (!in) {
ret = WIMLIB_ERR_NOMEM;
goto out;
}
- wof_info = (struct wof_external_info *)in;
- wof_info->version = WOF_CURRENT_VERSION;
- wof_info->provider = WOF_PROVIDER_WIM;
+ wof_info = (WOF_EXTERNAL_INFO *)in;
+ wof_info->Version = WOF_CURRENT_VERSION;
+ wof_info->Provider = WOF_PROVIDER_WIM;
- wim_info = (struct wim_provider_add_overlay_input *)(wof_info + 1);
- wim_info->wim_type = WIM_BOOT_NOT_OS_WIM;
- wim_info->wim_index = image;
- wim_info->wim_file_name_offset = offsetof(struct wim_provider_add_overlay_input,
- wim_file_name);
- wim_info->wim_file_name_length = wim_file_name_length;
- wmemcpy(&wim_info->wim_file_name[0], prefix, prefix_nchars);
- wmemcpy(&wim_info->wim_file_name[prefix_nchars], wim_path, wim_path_nchars);
+ wim_info = (WIM_PROVIDER_ADD_OVERLAY_INPUT *)(wof_info + 1);
+ wim_info->WimType = WIM_BOOT_NOT_OS_WIM;
+ wim_info->WimIndex = image;
+ wim_info->WimFileNameOffset = sizeof(*wim_info);
+ wim_info->WimFileNameLength = wim_file_name_length;
+ WimFileName = (wchar_t *)(wim_info + 1);
+ wmemcpy(WimFileName, prefix, prefix_nchars);
+ wmemcpy(&WimFileName[prefix_nchars], wim_path, wim_path_nchars);
retry_ioctl:
h = open_file(drive_path, GENERIC_WRITE);
FREE(in);
out:
if (ret == WIMLIB_ERR_UNSUPPORTED) {
- #if 0
- WARNING(
- "The version of Windows you are running does not appear to support\n"
- " the Windows Overlay File System Filter Driver. This is normally\n"
- " available on Windows 8.1 Update 1 or later. Therefore, wimlib\n"
- " will attempt to update the WimOverlay.dat file directly.\n");
- #else
WARNING("WOF driver is not available; updating WimOverlay.dat directly.");
- #endif
ret = update_wimoverlay_manually(drive_path + 4, wim_path,
wim_guid, image,
data_source_id_ret);
* using FSCTL_SET_EXTERNAL_BACKING. */
unsigned int max_retries = 4;
struct {
- struct wof_external_info wof_info;
- struct wim_provider_external_info wim_info;
+ WOF_EXTERNAL_INFO wof_info;
+ 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.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.unnamed_data_stream_hash, blob->hash);
+ in.wim_info.Version = WIM_PROVIDER_CURRENT_VERSION;
+ in.wim_info.Flags = 0;
+ in.wim_info.DataSourceId.QuadPart = data_source_id;
+ copy_hash(in.wim_info.ResourceHash, blob->hash);
/* blob_table_hash is not necessary */
le16 rpdatalen;
le16 rpreserved;
} hdr;
- struct wof_external_info wof_info;
+ WOF_EXTERNAL_INFO wof_info;
struct wim_provider_rpdata wim_info;
} in;
STATIC_ASSERT(sizeof(in) == 8 +
- sizeof(struct wof_external_info) +
+ sizeof(WOF_EXTERNAL_INFO) +
sizeof(struct wim_provider_rpdata));
in.hdr.rptag = WIM_IO_REPARSE_TAG_WOF;
in.hdr.rpdatalen = sizeof(in) - sizeof(in.hdr);
in.hdr.rpreserved = 0;
- in.wof_info.version = WOF_CURRENT_VERSION;
- in.wof_info.provider = WOF_PROVIDER_WIM;
+ in.wof_info.Version = WOF_CURRENT_VERSION;
+ in.wof_info.Provider = WOF_PROVIDER_WIM;
in.wim_info.version = 2;
in.wim_info.flags = 0;
return true;
}
-#endif /* __WIN32__ */
+#endif /* _WIN32 */