*/
/*
- * 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
#include "wimlib/win32_common.h"
+#include "wimlib/assert.h"
#include "wimlib/error.h"
#include "wimlib/util.h"
+#include "wimlib/win32_vss.h"
static bool
win32_modify_privilege(const wchar_t *privilege, bool enable)
/* ntdll.dll */
-NTSTATUS (WINAPI *func_NtCreateFile)(PHANDLE FileHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PIO_STATUS_BLOCK IoStatusBlock,
- PLARGE_INTEGER AllocationSize,
- ULONG FileAttributes,
- ULONG ShareAccess,
- ULONG CreateDisposition,
- ULONG CreateOptions,
- PVOID EaBuffer,
- ULONG EaLength);
-
-NTSTATUS (WINAPI *func_NtOpenFile) (PHANDLE FileHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PIO_STATUS_BLOCK IoStatusBlock,
- ULONG ShareAccess,
- ULONG OpenOptions);
-
-NTSTATUS (WINAPI *func_NtReadFile) (HANDLE FileHandle,
- HANDLE Event,
- PIO_APC_ROUTINE ApcRoutine,
- PVOID ApcContext,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID Buffer,
- ULONG Length,
- PLARGE_INTEGER ByteOffset,
- PULONG Key);
-
-NTSTATUS (WINAPI *func_NtWriteFile) (HANDLE FileHandle,
- HANDLE Event,
- PIO_APC_ROUTINE ApcRoutine,
- PVOID ApcContext,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID Buffer,
- ULONG Length,
- PLARGE_INTEGER ByteOffset,
- PULONG Key);
-
-NTSTATUS (WINAPI *func_NtQueryInformationFile)(HANDLE FileHandle,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID FileInformation,
- ULONG Length,
- FILE_INFORMATION_CLASS FileInformationClass);
-
-NTSTATUS (WINAPI *func_NtQuerySecurityObject)(HANDLE handle,
- SECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- ULONG Length,
- PULONG LengthNeeded);
-
-NTSTATUS (WINAPI *func_NtQueryDirectoryFile) (HANDLE FileHandle,
- HANDLE Event,
- PIO_APC_ROUTINE ApcRoutine,
- PVOID ApcContext,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID FileInformation,
- ULONG Length,
- FILE_INFORMATION_CLASS FileInformationClass,
- BOOLEAN ReturnSingleEntry,
- PUNICODE_STRING FileName,
- BOOLEAN RestartScan);
-
-NTSTATUS (WINAPI *func_NtQueryVolumeInformationFile) (HANDLE FileHandle,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID FsInformation,
- ULONG Length,
- FS_INFORMATION_CLASS FsInformationClass);
-
-NTSTATUS (WINAPI *func_NtSetInformationFile)(HANDLE FileHandle,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID FileInformation,
- ULONG Length,
- FILE_INFORMATION_CLASS FileInformationClass);
-
-NTSTATUS (WINAPI *func_NtSetSecurityObject)(HANDLE Handle,
- SECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor);
-
-NTSTATUS (WINAPI *func_NtFsControlFile) (HANDLE FileHandle,
- HANDLE Event,
- PIO_APC_ROUTINE ApcRoutine,
- PVOID ApcContext,
- PIO_STATUS_BLOCK IoStatusBlock,
- ULONG FsControlCode,
- PVOID InputBuffer,
- ULONG InputBufferLength,
- PVOID OutputBuffer,
- ULONG OutputBufferLength);
-
-NTSTATUS (WINAPI *func_NtClose) (HANDLE Handle);
-
-DWORD (WINAPI *func_RtlNtStatusToDosError)(NTSTATUS status);
-
-BOOLEAN (WINAPI *func_RtlDosPathNameToNtPathName_U)
- (IN PCWSTR DosName,
- OUT PUNICODE_STRING NtName,
- OUT PCWSTR *PartName,
- OUT PRTL_RELATIVE_NAME_U RelativeName);
-
NTSTATUS (WINAPI *func_RtlDosPathNameToNtPathName_U_WithStatus)
(IN PCWSTR DosName,
OUT PUNICODE_STRING NtName,
struct dll_spec ntdll_spec = {
.name = L"ntdll.dll",
.syms = {
- DLL_SYM(NtCreateFile, true),
- DLL_SYM(NtOpenFile, true),
- DLL_SYM(NtReadFile, true),
- DLL_SYM(NtWriteFile, true),
- DLL_SYM(NtQueryInformationFile, true),
- DLL_SYM(NtQuerySecurityObject, true),
- DLL_SYM(NtQueryDirectoryFile, true),
- DLL_SYM(NtQueryVolumeInformationFile, true),
- DLL_SYM(NtSetInformationFile, true),
- DLL_SYM(NtSetSecurityObject, true),
- DLL_SYM(NtFsControlFile, true),
- DLL_SYM(NtClose, true),
- DLL_SYM(RtlNtStatusToDosError, true),
DLL_SYM(RtlCreateSystemVolumeInformationFolder, false),
- DLL_SYM(RtlDosPathNameToNtPathName_U, true),
DLL_SYM(RtlDosPathNameToNtPathName_U_WithStatus, false), /* Not present on XP */
{NULL, NULL},
},
void
win32_global_cleanup(void)
{
+ vss_global_cleanup();
+
if (acquired_privileges)
win32_release_capture_and_apply_privileges();
nt_path,
NULL, NULL);
} else {
- if ((*func_RtlDosPathNameToNtPathName_U)(win32_path, nt_path,
- NULL, NULL))
+ if (RtlDosPathNameToNtPathName_U(win32_path, nt_path, NULL, NULL))
status = STATUS_SUCCESS;
else
status = STATUS_NO_MEMORY;
va_end(va);
}
+/*
+ * Synchronously execute a filesystem control method. This is a wrapper around
+ * NtFsControlFile() that handles STATUS_PENDING. Note that SYNCHRONIZE
+ * permission is, in general, required on the handle.
+ */
+NTSTATUS
+winnt_fsctl(HANDLE h, u32 code, const void *in, u32 in_size,
+ void *out, u32 out_size_avail, u32 *actual_out_size_ret)
+{
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS status;
+
+ status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, code,
+ (void *)in, in_size, out, out_size_avail);
+ if (status == STATUS_PENDING) {
+ /* Beware: this case is often encountered with remote
+ * filesystems, but rarely with local filesystems. */
+
+ status = NtWaitForSingleObject(h, FALSE, NULL);
+ if (NT_SUCCESS(status)) {
+ status = iosb.Status;
+ } else {
+ /* We shouldn't be issuing ioctls on a handle to which
+ * we don't have SYNCHRONIZE access. Otherwise we have
+ * no way to wait for them to complete. */
+ wimlib_assert(status != STATUS_ACCESS_DENIED);
+ }
+ }
+
+ if (NT_SUCCESS(status) && actual_out_size_ret != NULL)
+ *actual_out_size_ret = (u32)iosb.Information;
+
+ return status;
+}
+
#endif /* __WIN32__ */