void *mem_prepopulate_pats;
u8 wim_lookup_table_hash[SHA1_HASH_SIZE];
bool wof_running;
+ bool tried_to_load_prepopulate_list;
} wimboot;
/* Open handle to the target directory */
void *mem;
struct text_file_section sec;
+ ctx->wimboot.tried_to_load_prepopulate_list = true;
+
dentry = get_dentry(ctx->common.wim, path, WIMLIB_CASE_INSENSITIVE);
if (!dentry ||
(dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
return WIM_BACKING_NOT_ENABLED;
+ if (!ctx->wimboot.tried_to_load_prepopulate_list) {
+ ret = load_prepopulate_pats(ctx);
+ if (ret == WIMLIB_ERR_NOMEM)
+ return ret;
+ }
+
if (dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_REPARSE_POINT |
FILE_ATTRIBUTE_ENCRYPTED))
}
static int
-set_external_backing(struct wim_dentry *dentry, struct win32_apply_ctx *ctx)
+set_external_backing(HANDLE h, struct wim_dentry *dentry, struct win32_apply_ctx *ctx)
{
int ret;
&info, ctx->common.progctx);
} else {
/* Externally backing. */
- return wimboot_set_pointer(&ctx->attr,
+ return wimboot_set_pointer(h,
current_path(ctx),
inode_unnamed_lte_resolved(dentry->d_inode),
ctx->wimboot.data_source_id,
int ret;
WIMStruct *wim = ctx->common.wim;
- ret = load_prepopulate_pats(ctx);
- if (ret == WIMLIB_ERR_NOMEM)
- return ret;
+ if (!ctx->wimboot.tried_to_load_prepopulate_list) {
+ ret = load_prepopulate_pats(ctx);
+ if (ret == WIMLIB_ERR_NOMEM)
+ return ret;
+ }
if (!wim_info_get_wimboot(wim->wim_info, wim->current_image))
WARNING("Image is not marked as WIMBoot compatible!");
* with the former case being removing the existing short name if
* present, rather than setting one.
*
- * FileName seemingly does not, however, need to be null-terminated in
- * any case.
+ * The null terminator is seemingly optional, but to be safe we include
+ * space for it and zero all unused space.
*/
size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
- max(dentry->short_name_nbytes, 2 * sizeof(wchar_t));
+ max(dentry->short_name_nbytes, sizeof(wchar_t)) +
+ sizeof(wchar_t);
u8 buf[bufsize] _aligned_attribute(8);
FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
NTSTATUS status;
+ memset(buf, 0, bufsize);
+
info->FileNameLength = dentry->short_name_nbytes;
memcpy(info->FileName, dentry->short_name, dentry->short_name_nbytes);
-
retry:
status = (*func_NtSetInformationFile)(h, &ctx->iosb, info, bufsize,
FileShortNameInformation);
/* If the root dentry is being extracted, it was already done so
* in prepare_target(). */
- if (dentry_is_root(dentry))
- continue;
-
- ret = create_directory(dentry, ctx);
- if (ret)
- return ret;
+ if (!dentry_is_root(dentry)) {
+ ret = create_directory(dentry, ctx);
+ if (ret)
+ return ret;
- ret = create_any_empty_ads(dentry, ctx);
- if (ret)
- return ret;
+ ret = create_any_empty_ads(dentry, ctx);
+ if (ret)
+ return ret;
+ }
ret = report_file_created(&ctx->common);
if (ret)
/* "WIMBoot" extraction: set external backing by the WIM file if needed. */
if (!ret && unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT))
- ret = set_external_backing(first_dentry, ctx);
+ ret = set_external_backing(h, first_dentry, ctx);
(*func_NtClose)(h);
return ret;
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
/* Call create_nondirectory() only once per inode */
- if (dentry != inode_first_extraction_dentry(inode))
- continue;
- ret = create_nondirectory(inode, ctx);
- if (ret)
- return ret;
+ if (dentry == inode_first_extraction_dentry(inode)) {
+ ret = create_nondirectory(inode, ctx);
+ if (ret)
+ return ret;
+ }
ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
}
+static uint64_t
+count_dentries(const struct list_head *dentry_list)
+{
+ const struct list_head *cur;
+ uint64_t count = 0;
+
+ list_for_each(cur, dentry_list)
+ count++;
+
+ return count;
+}
+
/* Extract files from a WIM image to a directory on Windows */
static int
win32_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
{
int ret;
struct win32_apply_ctx *ctx = (struct win32_apply_ctx *)_ctx;
+ uint64_t dentry_count;
ret = prepare_target(dentry_list, ctx);
if (ret)
goto out;
}
- reset_file_progress(&ctx->common);
+ dentry_count = count_dentries(dentry_list);
+
+ ret = start_file_structure_phase(&ctx->common, dentry_count);
+ if (ret)
+ goto out;
ret = create_directories(dentry_list, ctx);
if (ret)
if (ret)
goto out;
+ ret = end_file_structure_phase(&ctx->common);
+ if (ret)
+ goto out;
+
struct read_stream_list_callbacks cbs = {
.begin_stream = begin_extract_stream,
.begin_stream_ctx = ctx,
if (ret)
goto out;
- reset_file_progress(&ctx->common);
+ ret = start_file_metadata_phase(&ctx->common, dentry_count);
+ if (ret)
+ goto out;
ret = apply_metadata(dentry_list, ctx);
if (ret)
goto out;
+ ret = end_file_metadata_phase(&ctx->common);
+ if (ret)
+ goto out;
+
if (unlikely(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT)) {
ret = end_wimboot_extraction(ctx);
if (ret)