#include "wimlib/error.h"
#include "wimlib/lookup_table.h"
-#ifdef WITH_NTDLL
-# include <winternl.h>
-# include <ntstatus.h>
-NTSTATUS WINAPI
-NtSetSecurityObject(HANDLE Handle,
- SECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor);
-#endif
-
static int
win32_start_extract(const wchar_t *path, struct apply_ctx *ctx)
{
return 0;
}
+/* Create a normal file, overwriting one already present. */
static int
win32_create_file(const wchar_t *path, struct apply_ctx *ctx, u64 *cookie_ret)
{
HANDLE h;
-
- h = CreateFile(path, 0, 0, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (h == INVALID_HANDLE_VALUE)
- goto error;
+ unsigned retry_count = 0;
+ DWORD dwFlagsAndAttributes = FILE_FLAG_BACKUP_SEMANTICS;
+
+retry:
+ /* WRITE_OWNER and WRITE_DAC privileges are required for some reason,
+ * even through we're creating a new file. */
+ h = CreateFile(path, WRITE_OWNER | WRITE_DAC, 0, NULL,
+ CREATE_ALWAYS, dwFlagsAndAttributes, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ /* File couldn't be created. */
+ DWORD err = GetLastError();
+ if (err == ERROR_ACCESS_DENIED && retry_count == 0) {
+
+ /* Access denied error for the first time. Try
+ * adjusting file attributes. */
+
+ /* Get attributes of the existing file. */
+ DWORD attribs = GetFileAttributes(path);
+ if (attribs != INVALID_FILE_ATTRIBUTES &&
+ (attribs & (FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_READONLY)))
+ {
+ /* If the existing file has
+ * FILE_ATTRIBUTE_HIDDEN and/or
+ * FILE_ATTRIBUTE_SYSTEM, they must be set in
+ * the call to CreateFile(). This is true even
+ * when FILE_ATTRIBUTE_NORMAL was not specified,
+ * contrary to the MS "documentation". */
+ dwFlagsAndAttributes |= (attribs &
+ (FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_SYSTEM));
+ /* If the existing file has
+ * FILE_ATTRIBUTE_READONLY, it must be cleared
+ * before attempting to create a new file over
+ * it. This is true even when the process has
+ * the SE_RESTORE_NAME privilege and requested
+ * the FILE_FLAG_BACKUP_SEMANTICS flag to
+ * CreateFile(). */
+ if (attribs & FILE_ATTRIBUTE_READONLY) {
+ SetFileAttributes(path,
+ attribs & ~FILE_ATTRIBUTE_READONLY);
+ }
+ retry_count++;
+ goto retry;
+ }
+ }
+ set_errno_from_win32_error(err);
+ return WIMLIB_ERR_OPEN;
+ }
CloseHandle(h);
return 0;
-
-error:
- set_errno_from_GetLastError();
- return WIMLIB_ERR_OPEN;
}
static int
stream_path = alloca(sizeof(wchar_t) *
(wcslen(path) + 1 +
wcslen(stream_name) + 1));
- swprintf(stream_path, L"%ls:%ls", path, stream_name);
+ tsprintf(stream_path, L"%ls:%ls", path, stream_name);
}
h = CreateFile(stream_path, FILE_WRITE_DATA, 0, NULL,
ret = 0;
if (!lte)
goto out_close_handle;
- ret = extract_wim_resource(lte, wim_resource_size(lte),
- win32_extract_wim_chunk, h);
+ ret = extract_stream(lte, lte->size, win32_extract_wim_chunk, h);
out_close_handle:
if (!CloseHandle(h))
goto error;
unsigned long len = *len_p;
const struct wim_lookup_table_entry *lte = import_ctx->lte;
- len = min(len, wim_resource_size(lte) - import_ctx->offset);
+ len = min(len, lte->size - import_ctx->offset);
- if (read_partial_wim_resource_into_buf(lte, len, import_ctx->offset, data))
+ if (read_partial_wim_stream_into_buf(lte, len, import_ctx->offset, data))
return ERROR_READ_FAULT;
import_ctx->offset += len;
}
static int
-win32_extract_encrypted_stream(file_spec_t file,
+win32_extract_encrypted_stream(const wchar_t *path,
struct wim_lookup_table_entry *lte,
struct apply_ctx *ctx)
{
- const tchar *path = file.path;
void *file_ctx;
DWORD err;
int ret;
PSECURITY_DESCRIPTOR desc)
{
#ifdef WITH_NTDLL
- return RtlNtStatusToDosError(NtSetSecurityObject(h, info, desc));
-#else
+ if (func_NtSetSecurityObject) {
+ return (*func_RtlNtStatusToDosError)(
+ (*func_NtSetSecurityObject)(h, info, desc));
+ }
+#endif
if (SetFileSecurity(path, info, desc))
return ERROR_SUCCESS;
else
return GetLastError();
-#endif
}
static int
h = INVALID_HANDLE_VALUE;
#ifdef WITH_NTDLL
- h = win32_open_existing_file(path, MAXIMUM_ALLOWED);
- if (h == INVALID_HANDLE_VALUE) {
- ERROR_WITH_ERRNO("Can't open %ls (%u)", path, GetLastError());
- goto error;
+ if (func_NtSetSecurityObject) {
+ h = win32_open_existing_file(path, MAXIMUM_ALLOWED);
+ if (h == INVALID_HANDLE_VALUE) {
+ set_errno_from_GetLastError();
+ ERROR_WITH_ERRNO("Can't open %ls", path);
+ return WIMLIB_ERR_SET_SECURITY;
+ }
}
#endif
for (;;) {
err = do_win32_set_security_descriptor(h, path, info,
(PSECURITY_DESCRIPTOR)desc);
- if (err == ERROR_SUCCESS)
+ if (err == ERROR_SUCCESS) {
+ ret = 0;
break;
+ }
if ((err == ERROR_PRIVILEGE_NOT_HELD ||
err == ERROR_ACCESS_DENIED) &&
!(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
}
ctx->partial_security_descriptors--;
ctx->no_security_descriptors++;
+ ret = 0;
break;
}
- goto error;
+ set_errno_from_win32_error(err);
+ ret = WIMLIB_ERR_SET_SECURITY;
+ break;
}
- ret = 0;
-out_close:
#ifdef WITH_NTDLL
- CloseHandle(h);
+ if (func_NtSetSecurityObject)
+ CloseHandle(h);
#endif
return ret;
-
-error:
- set_errno_from_GetLastError();
- ret = WIMLIB_ERR_SET_SECURITY;
- goto out_close;
}
static int
.realpath_works_on_nonexisting_files = 1,
.root_directory_is_special = 1,
.requires_final_set_attributes_pass = 1,
+ .extract_encrypted_stream_creates_file = 1,
+ .requires_short_name_reordering = 1, /* TODO: check if this is really needed */
};
#endif /* __WIN32__ */