*/
/*
- * Copyright (C) 2013-2018 Eric Biggers
+ * Copyright 2013-2023 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"
}
}
-/* Is the image being extracted an OS image for Windows 10 or later? */
-static bool
-is_image_windows_10_or_later(struct win32_apply_ctx *ctx)
-{
- /* Note: if no build number is available, this returns false. */
- return ctx->windows_build_number >= 10240;
-}
-
static const wchar_t *
current_path(struct win32_apply_ctx *ctx);
path_max = compute_path_max(dentry_list);
/* Add some extra for building Win32 paths for the file encryption APIs,
- * and ensure we have at least enough to potentially use a 8.3 name for
+ * and ensure we have at least enough to potentially use an 8.3 name for
* the last component. */
path_max += max(2 + (ctx->target_ntpath.Length / sizeof(wchar_t)),
8 + 1 + 3);
HANDLE h;
size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
(13 * sizeof(wchar_t));
- u8 buf[bufsize] _aligned_attribute(8);
+ u8 buf[bufsize] __attribute__((aligned(8)));
bool retried = false;
FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
size_t bufsize = offsetof(FILE_NAME_INFORMATION, FileName) +
max(dentry->d_short_name_nbytes, sizeof(wchar_t)) +
sizeof(wchar_t);
- u8 buf[bufsize] _aligned_attribute(8);
+ u8 buf[bufsize] __attribute__((aligned(8)));
FILE_NAME_INFORMATION *info = (FILE_NAME_INFORMATION *)buf;
NTSTATUS status;
bool tried_to_remove_existing = false;
if (unlikely(!NT_SUCCESS(status))) {
winnt_error(status, L"Can't open \"%ls\" for deletion "
"(perms=%x, flags=%x)",
- current_path(ctx), perms, flags);
+ current_path(ctx), (u32)perms, (u32)flags);
return WIMLIB_ERR_OPEN;
}
if (strm->stream_type == STREAM_TYPE_REPARSE_POINT &&
ctx->common.supported_features.reparse_points)
{
- u8 buf[REPARSE_DATA_OFFSET] _aligned_attribute(8);
+ u8 buf[REPARSE_DATA_OFFSET] __attribute__((aligned(8)));
struct reparse_buffer_disk *rpbuf =
(struct reparse_buffer_disk *)buf;
complete_reparse_point(rpbuf, inode, 0);
size_t bufsize = offsetof(FILE_LINK_INFORMATION, FileName) +
ctx->pathbuf.Length + sizeof(wchar_t);
- u8 buf[bufsize] _aligned_attribute(8);
+ u8 buf[bufsize] __attribute__((aligned(8)));
FILE_LINK_INFORMATION *info = (FILE_LINK_INFORMATION *)buf;
NTSTATUS status;
info->FileNameLength = ctx->pathbuf.Length;
memcpy(info->FileName, ctx->pathbuf.Buffer, ctx->pathbuf.Length);
info->FileName[info->FileNameLength / 2] = L'\0';
+ /*
+ * Note: the null terminator isn't actually necessary, but if
+ * you don't add the extra character, you get
+ * STATUS_INFO_LENGTH_MISMATCH when FileNameLength is 2.
+ */
- /* Note: the null terminator isn't actually necessary,
- * but if you don't add the extra character, you get
- * STATUS_INFO_LENGTH_MISMATCH when FileNameLength
- * happens to be 2 */
-
- status = NtSetInformationFile(h, &ctx->iosb, info, bufsize,
- FileLinkInformation);
- if (NT_SUCCESS(status))
- return 0;
+ /*
+ * When fuzzing with wlfuzz.exe, creating a hard link sometimes
+ * fails with STATUS_ACCESS_DENIED. However, it eventually
+ * succeeds when re-attempted...
+ */
+ int i = 0;
+ do {
+ status = NtSetInformationFile(h, &ctx->iosb, info,
+ bufsize,
+ FileLinkInformation);
+ if (NT_SUCCESS(status))
+ return 0;
+ } while (++i < 32);
winnt_error(status, L"Failed to create link \"%ls\"",
current_path(ctx));
return WIMLIB_ERR_LINK;
get_system_compression_format(int extract_flags)
{
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS4K)
- return FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K;
+ return FILE_PROVIDER_COMPRESSION_XPRESS4K;
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS8K)
- return FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K;
+ return FILE_PROVIDER_COMPRESSION_XPRESS8K;
if (extract_flags & WIMLIB_EXTRACT_FLAG_COMPACT_XPRESS16K)
- return FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K;
+ return FILE_PROVIDER_COMPRESSION_XPRESS16K;
- return FILE_PROVIDER_COMPRESSION_FORMAT_LZX;
+ return FILE_PROVIDER_COMPRESSION_LZX;
}
get_system_compression_format_string(int format)
{
switch (format) {
- case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K:
+ case FILE_PROVIDER_COMPRESSION_XPRESS4K:
return L"XPRESS4K";
- case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS8K:
+ case FILE_PROVIDER_COMPRESSION_XPRESS8K:
return L"XPRESS8K";
- case FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS16K:
+ case FILE_PROVIDER_COMPRESSION_XPRESS16K:
return L"XPRESS16K";
default:
return L"LZX";
{
NTSTATUS status;
struct {
- struct wof_external_info wof_info;
- struct file_provider_external_info file_info;
+ WOF_EXTERNAL_INFO wof_info;
+ FILE_PROVIDER_EXTERNAL_INFO_V1 file_info;
} in = {
.wof_info = {
- .version = WOF_CURRENT_VERSION,
- .provider = WOF_PROVIDER_FILE,
+ .Version = WOF_CURRENT_VERSION,
+ .Provider = WOF_PROVIDER_FILE,
},
.file_info = {
- .version = FILE_PROVIDER_CURRENT_VERSION,
- .compression_format = format,
+ .Version = FILE_PROVIDER_CURRENT_VERSION,
+ .Algorithm = format,
},
};
.num_strings = ARRAY_LEN(bootloader_pattern_strings),
};
+/* Returns true if the specified system compression format is supported by the
+ * bootloader of the image being applied. */
+static bool
+bootloader_supports_compression_format(struct win32_apply_ctx *ctx, int format)
+{
+ /* Windows 10 and later support XPRESS4K */
+ if (format == FILE_PROVIDER_COMPRESSION_XPRESS4K)
+ return ctx->windows_build_number >= 10240;
+
+ /*
+ * Windows 10 version 1903 and later support the other formats;
+ * see https://wimlib.net/forums/viewtopic.php?f=1&t=444
+ */
+ return ctx->windows_build_number >= 18362;
+}
+
static NTSTATUS
set_system_compression_on_inode(struct wim_inode *inode, int format,
struct win32_apply_ctx *ctx)
HANDLE h;
/* If it may be needed for compatibility with the Windows bootloader,
- * force this file to XPRESS4K or uncompressed format. The bootloader
- * of Windows 10 supports XPRESS4K only; older versions don't support
- * system compression at all. */
- if (!is_image_windows_10_or_later(ctx) ||
- format != FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K)
- {
+ * force this file to XPRESS4K or uncompressed format. */
+ if (!bootloader_supports_compression_format(ctx, format)) {
/* We need to check the patterns against every name of the
* inode, in case any of them match. */
struct wim_dentry *dentry;
warned = (ctx->num_system_compression_exclusions++ > 0);
- if (is_image_windows_10_or_later(ctx)) {
+ if (bootloader_supports_compression_format(ctx,
+ FILE_PROVIDER_COMPRESSION_XPRESS4K))
+ {
/* Force to XPRESS4K */
if (!warned) {
WARNING("For compatibility with the "
" you requested.",
get_system_compression_format_string(format));
}
- format = FILE_PROVIDER_COMPRESSION_FORMAT_XPRESS4K;
+ format = FILE_PROVIDER_COMPRESSION_XPRESS4K;
break;
} else {
/* Force to uncompressed */
u32 len;
const struct wim_xattr_entry *entry;
size_t bufsize = 0;
- u8 _buf[1024] _aligned_attribute(4);
+ u8 _buf[1024] __attribute__((aligned(4)));
u8 *buf = _buf;
FILE_FULL_EA_INFORMATION *ea, *ea_prev;
NTSTATUS status;
.context_size = sizeof(struct win32_apply_ctx),
};
-#endif /* __WIN32__ */
+#endif /* _WIN32 */