*/
/*
- * Copyright (C) 2013, 2014, 2015 Eric Biggers
+ * Copyright (C) 2013-2016 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
{
const bool compressed = (dentry->d_inode->i_attributes &
FILE_ATTRIBUTE_COMPRESSED);
+ FILE_BASIC_INFORMATION info;
+ USHORT compression_state;
+ NTSTATUS status;
if (ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)
return 0;
if (!ctx->common.supported_features.compressed_files)
return 0;
- FILE_BASIC_INFORMATION info;
- NTSTATUS status;
- USHORT compression_state;
- DWORD bytes_returned;
/* Get current attributes */
status = (*func_NtQueryInformationFile)(h, &ctx->iosb,
else
compression_state = COMPRESSION_FORMAT_NONE;
- /* Note: don't use NtFsControlFile() here unless prepared to handle
- * STATUS_PENDING. */
- if (DeviceIoControl(h, FSCTL_SET_COMPRESSION,
- &compression_state, sizeof(USHORT), NULL, 0,
- &bytes_returned, NULL))
- return 0;
+ status = winnt_fsctl(h, FSCTL_SET_COMPRESSION,
+ &compression_state, sizeof(USHORT), NULL, 0, NULL);
+ if (NT_SUCCESS(status))
+ return status;
- win32_error(GetLastError(), L"Can't %s compression attribute on \"%ls\"",
+ winnt_error(status, L"Can't %s compression attribute on \"%ls\"",
(compressed ? "set" : "clear"), current_path(ctx));
return WIMLIB_ERR_SET_ATTRIBUTES;
}
* A wrapper around NtCreateFile() to make it slightly more usable...
* This uses the path currently constructed in ctx->pathbuf.
*
- * Also, we always specify FILE_OPEN_FOR_BACKUP_INTENT and
+ * Also, we always specify SYNCHRONIZE access, FILE_OPEN_FOR_BACKUP_INTENT, and
* FILE_OPEN_REPARSE_POINT.
*/
static NTSTATUS
struct win32_apply_ctx *ctx)
{
return (*func_NtCreateFile)(FileHandle,
- DesiredAccess,
+ DesiredAccess | SYNCHRONIZE,
&ctx->attr,
&ctx->iosb,
AllocationSize,
if (!NT_SUCCESS(status))
goto fail;
- status = (*func_NtFsControlFile)(h, NULL, NULL, NULL,
- &ctx->iosb, FSCTL_SET_REPARSE_POINT,
- (void *)rpbuf, rpbuflen,
- NULL, 0);
+ status = winnt_fsctl(h, FSCTL_SET_REPARSE_POINT,
+ rpbuf, rpbuflen, NULL, 0, NULL);
(*func_NtClose)(h);
if (NT_SUCCESS(status))
goto retry;
}
}
- winnt_error(status, L"Can't create directory \"%ls\"",
- current_path(ctx));
+ const wchar_t *path = current_path(ctx);
+ winnt_error(status, L"Can't create directory \"%ls\"", path);
+
+ /* Check for known issue with WindowsApps directory. */
+ if (status == STATUS_ACCESS_DENIED &&
+ (wcsstr(path, L"\\WindowsApps\\") ||
+ wcsstr(path, L"\\InfusedApps\\"))) {
+ ERROR(
+"You seem to be trying to extract files to the WindowsApps directory.\n"
+" Windows 8.1 and later use new file permissions in this directory that\n"
+" cannot be overridden, even by backup/restore programs. To extract your\n"
+" files anyway, you need to choose a different target directory, delete\n"
+" the WindowsApps directory entirely, reformat the volume, do the\n"
+" extraction from a non-broken operating system such as Windows 7 or\n"
+" Linux, or wait for Microsoft to fix the design flaw in their operating\n"
+" system. This is *not* a bug in wimlib. See this thread for more\n"
+" information: https://wimlib.net/forums/viewtopic.php?f=1&t=261");
+ }
return WIMLIB_ERR_MKDIR;
}
target_ntpath_nchars = ctx->target_ntpath.Length / sizeof(wchar_t);
+ /* If the target directory is a filesystem root, such as \??\C:\, then
+ * it already will have a trailing slash. Don't include this slash if
+ * we are already adding slashes via 'relpath'. This prevents an extra
+ * slash from being generated each time the link is extracted. And
+ * unlike on UNIX, the number of slashes in paths on Windows can be
+ * significant; Windows won't understand the link target if it contains
+ * too many slashes. */
+ if (target_ntpath_nchars > 0 && relpath_nchars > 0 &&
+ ctx->target_ntpath.Buffer[target_ntpath_nchars - 1] == L'\\')
+ target_ntpath_nchars--;
+
+ /* Also remove extra slashes from the beginning of 'relpath'. Normally
+ * this isn't needed, but this is here to make the extra slash(es) added
+ * by wimlib pre-v1.9.1 get removed automatically. */
+ while (relpath_nchars >= 2 &&
+ relpath[0] == L'\\' && relpath[1] == L'\\') {
+ relpath++;
+ relpath_nchars--;
+ }
+
fixed_subst_name_nchars = target_ntpath_nchars + relpath_nchars;
wchar_t fixed_subst_name[fixed_subst_name_nchars];
set_system_compression(HANDLE h, int format)
{
NTSTATUS status;
- IO_STATUS_BLOCK iosb;
struct {
struct wof_external_info wof_info;
struct file_provider_external_info file_info;
* versions of Windows (before Windows 10?). This can be a problem if
* the WOFADK driver is being used rather than the regular WOF, since
* WOFADK can be used on older versions of Windows. */
- status = (*func_NtFsControlFile)(h, NULL, NULL, NULL, &iosb,
- FSCTL_SET_EXTERNAL_BACKING,
- &in, sizeof(in), NULL, 0);
+ status = winnt_fsctl(h, FSCTL_SET_EXTERNAL_BACKING,
+ &in, sizeof(in), NULL, 0, NULL);
if (status == 0xC000046F) /* "Compressing this object would not save space." */
return STATUS_SUCCESS;