X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwin32_apply.c;h=49e25d4b50bd30d156b6a669cd0f6a9f6ab0d0a1;hp=7eb0ce27c0cb78d34dfe58ed8d243caf849667d8;hb=a8d148d9b2a765ba7fcbce927ea2546f917afe53;hpb=c5fd49890aca1059262b986942a66542127c63af diff --git a/src/win32_apply.c b/src/win32_apply.c index 7eb0ce27..49e25d4b 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -36,10 +36,10 @@ #include "wimlib/error.h" #include "wimlib/metadata.h" #include "wimlib/paths.h" +#include "wimlib/pattern.h" #include "wimlib/reparse.h" #include "wimlib/textfile.h" #include "wimlib/xml.h" -#include "wimlib/wildcard.h" #include "wimlib/wimboot.h" struct win32_apply_ctx { @@ -341,28 +341,15 @@ load_prepopulate_pats(struct win32_apply_ctx *ctx) return 0; } -/* Returns %true if the specified absolute path to a file in the WIM image - * matches a pattern in [PrepopulateList] of WimBootCompress.ini. Otherwise - * returns %false. */ -static bool -in_prepopulate_list(const wchar_t *path, size_t path_nchars, - const struct win32_apply_ctx *ctx) -{ - const struct string_set *pats = ctx->wimboot.prepopulate_pats; - - if (!pats || !pats->num_strings) - return false; - - return match_pattern_list(path, path_nchars, pats); -} - /* Returns %true if the specified absolute path to a file in the WIM image can * be subject to external backing when extracted. Otherwise returns %false. */ static bool -can_externally_back_path(const wchar_t *path, size_t path_nchars, - const struct win32_apply_ctx *ctx) +can_externally_back_path(const wchar_t *path, const struct win32_apply_ctx *ctx) { - if (in_prepopulate_list(path, path_nchars, ctx)) + /* Does the path match a pattern given in the [PrepopulateList] section + * of WimBootCompress.ini? */ + if (ctx->wimboot.prepopulate_pats && + match_pattern_list(path, ctx->wimboot.prepopulate_pats)) return false; /* Since we attempt to modify the SYSTEM registry after it's extracted @@ -374,8 +361,7 @@ can_externally_back_path(const wchar_t *path, size_t path_nchars, * However, a WIM that wasn't specifically captured in "WIMBoot mode" * may contain SYSTEM.* files. So to make things "just work", hard-code * the pattern. */ - if (match_path(path, path_nchars, L"\\Windows\\System32\\config\\SYSTEM*", - OS_PREFERRED_PATH_SEPARATOR, false)) + if (match_path(path, L"\\Windows\\System32\\config\\SYSTEM*", false)) return false; return true; @@ -492,9 +478,7 @@ will_externally_back_inode(struct wim_inode *inode, struct win32_apply_ctx *ctx, if (ret) return ret; - if (!can_externally_back_path(dentry->_full_path, - wcslen(dentry->_full_path), ctx)) - { + if (!can_externally_back_path(dentry->d_full_path, ctx)) { if (excluded_dentry_ret) *excluded_dentry_ret = dentry; return WIM_BACKING_EXCLUDED; @@ -557,7 +541,7 @@ set_external_backing(HANDLE h, struct wim_inode *inode, struct win32_apply_ctx * build_extraction_path(excluded_dentry, ctx); - info.wimboot_exclude.path_in_wim = excluded_dentry->_full_path; + info.wimboot_exclude.path_in_wim = excluded_dentry->d_full_path; info.wimboot_exclude.extraction_path = current_path(ctx); return call_progress(ctx->common.progfunc, @@ -1464,44 +1448,104 @@ retry: return WIMLIB_ERR_OPEN; } +/* Set the reparse point @rpbuf of length @rpbuflen on the extracted file + * corresponding to the WIM dentry @dentry. */ +static int +do_set_reparse_point(const struct wim_dentry *dentry, + const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, + struct win32_apply_ctx *ctx) +{ + NTSTATUS status; + HANDLE h; + + status = create_file(&h, GENERIC_WRITE, NULL, + 0, FILE_OPEN, 0, dentry, ctx); + if (!NT_SUCCESS(status)) + goto fail; + + status = (*func_NtFsControlFile)(h, NULL, NULL, NULL, + &ctx->iosb, FSCTL_SET_REPARSE_POINT, + (void *)rpbuf, rpbuflen, + NULL, 0); + (*func_NtClose)(h); + + if (NT_SUCCESS(status)) + return 0; + + /* On Windows, by default only the Administrator can create symbolic + * links for some reason. By default we just issue a warning if this + * appears to be the problem. Use WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS + * to get a hard error. */ + if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS) + && (status == STATUS_PRIVILEGE_NOT_HELD || + status == STATUS_ACCESS_DENIED) + && (dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK || + dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT)) + { + WARNING("Can't create symbolic link \"%ls\"! \n" + " (Need Administrator rights, or at least " + "the\n" + " SeCreateSymbolicLink privilege.)", + current_path(ctx)); + return 0; + } + +fail: + winnt_error(status, L"Can't set reparse data on \"%ls\"", + current_path(ctx)); + return WIMLIB_ERR_SET_REPARSE_DATA; +} + /* - * Create empty named data streams for the specified file, if there are any. + * Create empty named data streams and potentially a reparse point for the + * specified file, if any. * * Since these won't have blob descriptors, they won't show up in the call to * extract_blob_list(). Hence the need for the special case. */ static int -create_empty_named_data_streams(const struct wim_dentry *dentry, - struct win32_apply_ctx *ctx) +create_empty_streams(const struct wim_dentry *dentry, + struct win32_apply_ctx *ctx) { const struct wim_inode *inode = dentry->d_inode; - bool path_modified = false; - int ret = 0; - - if (!ctx->common.supported_features.named_data_streams) - return 0; + int ret; for (unsigned i = 0; i < inode->i_num_streams; i++) { const struct wim_inode_stream *strm = &inode->i_streams[i]; - HANDLE h; - if (!stream_is_named_data_stream(strm) || - stream_blob_resolved(strm) != NULL) + if (stream_blob_resolved(strm) != NULL) continue; - build_extraction_path_with_ads(dentry, ctx, - strm->stream_name, - utf16le_len_chars(strm->stream_name)); - path_modified = true; - ret = supersede_file_or_stream(ctx, &h); - if (ret) - break; - (*func_NtClose)(h); + if (strm->stream_type == STREAM_TYPE_REPARSE_POINT && + ctx->common.supported_features.reparse_points) + { + u8 buf[REPARSE_DATA_OFFSET] _aligned_attribute(8); + struct reparse_buffer_disk *rpbuf = + (struct reparse_buffer_disk *)buf; + complete_reparse_point(rpbuf, inode, 0); + ret = do_set_reparse_point(dentry, rpbuf, + REPARSE_DATA_OFFSET, ctx); + if (ret) + return ret; + } else if (stream_is_named_data_stream(strm) && + ctx->common.supported_features.named_data_streams) + { + HANDLE h; + + build_extraction_path_with_ads(dentry, ctx, + strm->stream_name, + utf16le_len_chars(strm->stream_name)); + ret = supersede_file_or_stream(ctx, &h); + + build_extraction_path(dentry, ctx); + + if (ret) + return ret; + (*func_NtClose)(h); + } } - /* Restore the path to the dentry itself */ - if (path_modified) - build_extraction_path(dentry, ctx); - return ret; + + return 0; } /* @@ -1587,7 +1631,7 @@ create_directories(struct list_head *dentry_list, ret = create_directory(dentry, ctx); if (!ret) - ret = create_empty_named_data_streams(dentry, ctx); + ret = create_empty_streams(dentry, ctx); ret = check_apply_error(dentry, ctx, ret); if (ret) @@ -1624,7 +1668,7 @@ create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry, if (ret) goto out_close; - ret = create_empty_named_data_streams(dentry, ctx); + ret = create_empty_streams(dentry, ctx); if (ret) goto out_close; @@ -1881,54 +1925,6 @@ begin_extract_blob_instance(const struct blob_descriptor *blob, return 0; } -/* Set the reparse point @rpbuf of length @rpbuflen on the extracted file - * corresponding to the WIM dentry @dentry. */ -static int -do_set_reparse_point(const struct wim_dentry *dentry, - const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, - struct win32_apply_ctx *ctx) -{ - NTSTATUS status; - HANDLE h; - - status = create_file(&h, GENERIC_WRITE, NULL, - 0, FILE_OPEN, 0, dentry, ctx); - if (!NT_SUCCESS(status)) - goto fail; - - status = (*func_NtFsControlFile)(h, NULL, NULL, NULL, - &ctx->iosb, FSCTL_SET_REPARSE_POINT, - (void *)rpbuf, rpbuflen, - NULL, 0); - (*func_NtClose)(h); - - if (NT_SUCCESS(status)) - return 0; - - /* On Windows, by default only the Administrator can create symbolic - * links for some reason. By default we just issue a warning if this - * appears to be the problem. Use WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS - * to get a hard error. */ - if (!(ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS) - && (status == STATUS_PRIVILEGE_NOT_HELD || - status == STATUS_ACCESS_DENIED) - && (dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_SYMLINK || - dentry->d_inode->i_reparse_tag == WIM_IO_REPARSE_TAG_MOUNT_POINT)) - { - WARNING("Can't create symbolic link \"%ls\"! \n" - " (Need Administrator rights, or at least " - "the\n" - " SeCreateSymbolicLink privilege.)", - current_path(ctx)); - return 0; - } - -fail: - winnt_error(status, L"Can't set reparse data on \"%ls\"", - current_path(ctx)); - return WIMLIB_ERR_SET_REPARSE_DATA; -} - /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a * pointer to the suffix of the path that begins with the device directly, such * as e:\Windows\System32. */