+ ret = wimboot_alloc_data_source_id(wim->filename,
+ wim->hdr.guid,
+ ctx->common.wim->current_image,
+ ctx->common.target,
+ &ctx->wimboot.wims[ctx->wimboot.num_wims].data_source_id,
+ &ctx->wimboot.wof_running);
+ if (ret)
+ return ret;
+
+ ctx->wimboot.num_wims++;
+ return 0;
+}
+
+/* Prepare for doing a "WIMBoot" extraction by registering each source WIM file
+ * with WOF on the target volume. */
+static int
+start_wimboot_extraction(struct list_head *dentry_list, struct win32_apply_ctx *ctx)
+{
+ int ret;
+ struct wim_dentry *dentry;
+
+ if (!wim_info_get_wimboot(ctx->common.wim->wim_info,
+ ctx->common.wim->current_image))
+ WARNING("The WIM image is not marked as WIMBoot compatible. This usually\n"
+ " means it is not intended to be used to back a Windows operating\n"
+ " system. Proceeding anyway.");
+
+ list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
+ struct blob_descriptor *blob;
+
+ ret = win32_will_back_from_wim(dentry, &ctx->common);
+ if (ret > 0) /* Error */
+ return ret;
+ if (ret < 0) /* Won't externally back */
+ continue;
+
+ blob = inode_get_blob_for_unnamed_data_stream_resolved(dentry->d_inode);
+ ret = register_wim_with_wof(blob->rdesc->wim, ctx);
+ if (ret)
+ return ret;
+ }
+
+ if (ctx->wimboot.have_wrong_version_wims) {
+ WARNING("At least one of the source WIM files uses a version of the WIM\n"
+" file format that not supported by Microsoft's wof.sys driver.\n"
+" Files whose data is contained in one of these WIM files will be\n"
+" extracted as full files rather than externally backed.");
+ }
+
+ if (ctx->wimboot.have_uncompressed_wims) {
+ WARNING("At least one of the source WIM files is uncompressed. Files whose\n"
+" data is contained in an uncompressed WIM file will be extracted as\n"
+" full files rather than externally backed, since uncompressed WIM\n"
+" files are not supported by Microsoft's wof.sys driver.");
+ }
+
+ if (ctx->wimboot.have_unsupported_compressed_resources) {
+ WARNING("At least one of the source WIM files uses a compression format that\n"
+" is not supported by Microsoft's wof.sys driver. Files whose data is\n"
+" contained in a compressed resource in one of these WIM files will be\n"
+" extracted as full files rather than externally backed. (The\n"
+" compression formats supported by wof.sys are: XPRESS 4K, XPRESS 8K,\n"
+" XPRESS 16K, XPRESS 32K, and LZX 32K.)");
+ }
+
+ if (ctx->wimboot.have_huge_resources) {
+ WARNING("Some files exceeded 4.2 GB in size. Such files will be extracted\n"
+" as full files rather than externally backed, since very large files\n"
+" are not supported by Microsoft's wof.sys driver.");
+ }
+
+ return 0;
+}
+
+static void
+build_win32_extraction_path(const struct wim_dentry *dentry,
+ struct win32_apply_ctx *ctx);
+
+/* Sets WimBoot=1 in the extracted SYSTEM registry hive.
+ *
+ * WIMGAPI does this, and it's possible that it's important.
+ * But I don't know exactly what this value means to Windows. */
+static int
+end_wimboot_extraction(struct win32_apply_ctx *ctx)
+{
+ struct wim_dentry *dentry;
+ wchar_t subkeyname[32];
+ LONG res;
+ LONG res2;
+ HKEY key;
+ DWORD value;
+
+ dentry = get_dentry(ctx->common.wim, L"\\Windows\\System32\\config\\SYSTEM",
+ WIMLIB_CASE_INSENSITIVE);
+
+ if (!dentry || !will_extract_dentry(dentry))
+ goto out;
+
+ if (!will_extract_dentry(wim_get_current_root_dentry(ctx->common.wim)))
+ goto out;
+
+ /* Not bothering to use the native routines (e.g. NtLoadKey()) for this.
+ * If this doesn't work, you probably also have many other problems. */
+
+ build_win32_extraction_path(dentry, ctx);
+
+ randomize_char_array_with_alnum(subkeyname, 20);
+ subkeyname[20] = L'\0';
+
+ res = RegLoadKey(HKEY_LOCAL_MACHINE, subkeyname, ctx->pathbuf.Buffer);
+ if (res)
+ goto out_check_res;
+
+ wcscpy(&subkeyname[20], L"\\Setup");
+
+ res = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkeyname, 0, NULL,
+ REG_OPTION_BACKUP_RESTORE, 0, NULL, &key, NULL);
+ if (res)
+ goto out_unload_key;
+
+ value = 1;
+
+ res = RegSetValueEx(key, L"WimBoot", 0, REG_DWORD,
+ (const BYTE *)&value, sizeof(DWORD));
+ if (res)
+ goto out_close_key;
+
+ res = RegFlushKey(key);
+
+out_close_key:
+ res2 = RegCloseKey(key);
+ if (!res)
+ res = res2;
+out_unload_key:
+ subkeyname[20] = L'\0';
+ RegUnLoadKey(HKEY_LOCAL_MACHINE, subkeyname);
+out_check_res:
+ if (res) {
+ /* Warning only. */
+ win32_warning(res, L"Failed to set \\Setup: dword \"WimBoot\"=1 "
+ "value in registry hive \"%ls\"",
+ ctx->pathbuf.Buffer);
+ }
+out:
+ return 0;