4 * Support for creating WIMBoot pointer files.
6 * See http://technet.microsoft.com/en-us/library/dn594399.aspx for general
7 * information about WIMBoot.
9 * Note that WIMBoot pointer files are actually implemented on top of the
10 * Windows Overlay File System Filter (WOF). See wof.h for more info.
14 * Copyright (C) 2014 Eric Biggers
16 * This file is part of wimlib, a library for working with WIM files.
18 * wimlib is free software; you can redistribute it and/or modify it under the
19 * terms of the GNU General Public License as published by the Free
20 * Software Foundation; either version 3 of the License, or (at your option)
23 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
24 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
25 * A PARTICULAR PURPOSE. See the GNU General Public License for more
28 * You should have received a copy of the GNU General Public License
29 * along with wimlib; if not, see http://www.gnu.org/licenses/.
33 # error "This file contains Windows code!"
40 #include "wimlib/win32_common.h"
41 #include "wimlib/win32.h"
42 #include "wimlib/assert.h"
43 #include "wimlib/error.h"
44 #include "wimlib/util.h"
45 #include "wimlib/wimboot.h"
46 #include "wimlib/wof.h"
49 win32_get_drive_path(const wchar_t *file_path, wchar_t drive_path[7])
53 file_abspath = realpath(file_path, NULL);
55 return WIMLIB_ERR_NOMEM;
57 if (file_abspath[0] == L'\0' || file_abspath[1] != L':') {
58 ERROR("\"%ls\": Path format not recognized", file_abspath);
60 return WIMLIB_ERR_UNSUPPORTED;
63 wsprintf(drive_path, L"\\\\.\\%lc:", file_abspath[0]);
69 * Allocate a WOF data source ID for a WIM file.
72 * Absolute path to the WIM file. This must include a drive letter and use
73 * backslash path separators.
75 * Index of the image in the WIM being applied.
77 * Path to the target drive.
79 * On success, an identifier for the backing WIM file will be returned
82 * Returns 0 on success, or a positive error code on failure.
85 wimboot_alloc_data_source_id(const wchar_t *wim_path, int image,
86 const wchar_t *target, u64 *data_source_id_ret)
89 size_t wim_path_nchars;
90 size_t wim_file_name_length;
93 struct wof_external_info *wof_info;
94 struct wim_provider_add_overlay_input *wim_info;
99 const wchar_t *prefix = L"\\??\\";
100 const size_t prefix_nchars = 4;
102 ret = win32_get_drive_path(target, drive_path);
106 wimlib_assert(!wcschr(wim_path, L'/'));
107 wimlib_assert(wim_path[0] != L'\0' && wim_path[1] == L':');
109 wim_path_nchars = wcslen(wim_path);
110 wim_file_name_length = sizeof(wchar_t) *
111 (wim_path_nchars + prefix_nchars);
113 insize = sizeof(struct wof_external_info) +
114 sizeof(struct wim_provider_add_overlay_input) +
115 wim_file_name_length;
119 ret = WIMLIB_ERR_NOMEM;
123 wof_info = (struct wof_external_info *)in;
124 wof_info->version = WOF_CURRENT_VERSION;
125 wof_info->provider = WOF_PROVIDER_WIM;
127 wim_info = (struct wim_provider_add_overlay_input *)(wof_info + 1);
128 wim_info->wim_type = WIM_BOOT_NOT_OS_WIM;
129 wim_info->wim_index = image;
130 wim_info->wim_file_name_offset = offsetof(struct wim_provider_add_overlay_input,
132 wim_info->wim_file_name_length = wim_file_name_length;
133 wmemcpy(&wim_info->wim_file_name[0], prefix, prefix_nchars);
134 wmemcpy(&wim_info->wim_file_name[prefix_nchars], wim_path, wim_path_nchars);
136 h = CreateFile(drive_path, GENERIC_WRITE,
137 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
138 NULL, OPEN_EXISTING, 0, NULL);
140 if (h == INVALID_HANDLE_VALUE) {
141 set_errno_from_GetLastError();
142 ERROR_WITH_ERRNO("Failed to open \"%ls\"", drive_path);
143 ret = WIMLIB_ERR_OPEN;
147 if (!DeviceIoControl(h, FSCTL_ADD_OVERLAY,
149 &data_source_id, sizeof(data_source_id),
150 &bytes_returned, NULL))
152 set_errno_from_GetLastError();
153 ERROR_WITH_ERRNO("Failed to add overlay source \"%ls\" "
154 "to volume \"%ls\"", wim_path, drive_path);
155 ret = WIMLIB_ERR_WIMBOOT;
156 goto out_close_handle;
159 if (bytes_returned != sizeof(data_source_id)) {
160 set_errno_from_win32_error(ERROR_INVALID_DATA);
161 ret = WIMLIB_ERR_WIMBOOT;
162 ERROR("Unexpected result size when adding "
163 "overlay source \"%ls\" to volume \"%ls\"",
164 wim_path, drive_path);
165 goto out_close_handle;
168 *data_source_id_ret = data_source_id;
181 * Set WIMBoot information on the specified file.
184 * Path to extracted file (already created).
186 * Identifier for backing WIM file.
188 * SHA-1 message digest of the file's unnamed data stream.
190 * Returns 0 on success, or a positive error code on failure.
193 wimboot_set_pointer(const wchar_t *path, u64 data_source_id,
197 struct wof_external_info wof_info;
198 struct wim_provider_external_info wim_info;
201 DWORD bytes_returned;
204 in.wof_info.version = WOF_CURRENT_VERSION;
205 in.wof_info.provider = WOF_PROVIDER_WIM;
207 in.wim_info.version = WIM_PROVIDER_CURRENT_VERSION;
208 in.wim_info.flags = 0;
209 in.wim_info.data_source_id = data_source_id;
210 memcpy(in.wim_info.resource_hash, hash, 20);
212 h = win32_open_existing_file(path, GENERIC_WRITE);
213 if (h == INVALID_HANDLE_VALUE) {
214 set_errno_from_GetLastError();
215 ret = WIMLIB_ERR_OPEN;
219 if (!DeviceIoControl(h, FSCTL_SET_EXTERNAL_BACKING,
220 &in, sizeof(in), NULL, 0, &bytes_returned, NULL))
222 set_errno_from_GetLastError();
223 ret = WIMLIB_ERR_WIMBOOT;
224 goto out_close_handle;