AC_MSG_RESULT([$ENABLE_DEBUG])
if test "x$ENABLE_DEBUG" = "xyes"; then
AC_DEFINE([ENABLE_DEBUG], [1],
- [Define to 1 if including lots of debug messages.])
+ [Define to 1 if including lots of debug messages.])
fi
AC_MSG_CHECKING([whether to include more debugging messages])
AC_ARG_ENABLE([more_debug],
AS_HELP_STRING([--enable-more-debug],
- [include even more debugging messages]),
+ [include even more debugging messages]),
[ENABLE_MORE_DEBUG=$enableval],
[ENABLE_MORE_DEBUG=no]
)
AC_MSG_RESULT([$ENABLE_MORE_DEBUG])
if test "x$ENABLE_MORE_DEBUG" = "xyes"; then
AC_DEFINE([ENABLE_MORE_DEBUG], [1],
- [Define to 1 if including even more debug messages.])
+ [Define to 1 if including even more debug messages.])
fi
AC_MSG_CHECKING([whether to include error messages])
AC_ARG_ENABLE([error_messages],
AS_HELP_STRING([--disable-error-messages],
- [do not compile in error messsages]),
+ [do not compile in error messsages]),
[ENABLE_ERROR_MESSAGES=$enableval],
[ENABLE_ERROR_MESSAGES=yes]
)
AC_MSG_RESULT([$ENABLE_ERROR_MESSAGES])
if test "x$ENABLE_ERROR_MESSAGES" = "xyes"; then
AC_DEFINE([ENABLE_ERROR_MESSAGES], [1],
- [Define to 1 if including error messages])
+ [Define to 1 if including error messages])
fi
AC_MSG_CHECKING([whether to support custom memory allocation functions])
AC_MSG_CHECKING([whether to include support for multi-threaded compression])
AC_ARG_ENABLE([multithreaded-compression],
AS_HELP_STRING([--disable-multithreaded-compression],
- [do not compile in the code for multi-threaded compression]),
+ [do not compile in the code for multi-threaded compression]),
[ENABLE_MULTITHREADED_COMPRESSION=$enableval],
[ENABLE_MULTITHREADED_COMPRESSION=yes]
)
AC_MSG_RESULT([$ENABLE_MULTITHREADED_COMPRESSION])
if test "x$ENABLE_MULTITHREADED_COMPRESSION" = "xyes"; then
AC_DEFINE([ENABLE_MULTITHREADED_COMPRESSION], [1],
- [Define to 1 if including support for multithreaded
+ [Define to 1 if including support for multithreaded
compression])
fi
WINDOWS_LDADD="-lshlwapi"
ENABLE_XATTR_DEFAULT="no"
;;
- *-*-cygwin*)
+ *-*-cygwin*)
# Cygwin (WARNING: not well supported)
AC_MSG_WARN([wimlib has not been tested with Cygwin! Please do
a Windows-native build with MinGW-w64 instead])
esac
AC_ARG_WITH([ntdll],
- AS_HELP_STRING([--without-ntdll], [Windows only: do not link with
- ntdll. By default, in some parts of its code,
- wimlib uses Windows NT system calls to work around
- flaws in the Win32 API. This support can be omitted
- if needed, but some annoying bugs will surface (e.g.
- permission denied errors even when running as the
- Administrator).]),
+ AS_HELP_STRING([--without-ntdll], [Windows only: do not try to
+ use functions from ntdll. By default, in some parts
+ of its code, wimlib uses Windows NT system calls to
+ work around flaws in the Win32 API. This support
+ can be omitted if needed, but some annoying bugs
+ will surface (e.g. permission denied errors even
+ when running as the Administrator).]),
[WITH_NTDLL=$withval],
[WITH_NTDLL=yes])
if test "x$WINDOWS_NATIVE_BUILD" = "xyes"; then
if test "x$WITH_NTDLL" = "xyes"; then
- WINDOWS_LDADD="$WINDOWS_LDADD -lntdll"
- AC_DEFINE([WITH_NTDLL], [1], [Define to 1 if linking with ntdll])
+ WINDOWS_LDADD="$WINDOWS_LDADD"
+ AC_DEFINE([WITH_NTDLL], [1], [Define to 1 to try to use ntdll
+ functions])
fi
fi
AC_MSG_CHECKING([whether to use SSSE3-accelerated SHA1 ])
AC_ARG_ENABLE([ssse3-sha1],
AS_HELP_STRING([--enable-ssse3-sha1], [use assembly language implementation
- of SHA1 from Intel, accelerated with vector
+ of SHA1 from Intel, accelerated with vector
instructions (SSSE3-enabled CPU required)]),
[ENABLE_SSSE3_SHA1=$enableval],
[ENABLE_SSSE3_SHA1=no]
AC_MSG_RESULT([$ENABLE_SSSE3_SHA1])
if test "x$ENABLE_SSSE3_SHA1" = "xyes"; then
AC_DEFINE([ENABLE_SSSE3_SHA1], [1],
- [Define to 1 if using vectorized implementation of SHA1])
+ [Define to 1 if using vectorized implementation of SHA1])
SSSE3_SHA1_OBJ=sha1-ssse3.lo
AX_PROG_NASM
AC_SUBST([NASM], [$nasm])
else
AC_ARG_WITH([libcrypto],
AS_HELP_STRING([--without-libcrypto], [build in the SHA1 algorithm,
- rather than use external libcrypto from
+ rather than use external libcrypto from
OpenSSL (default is autodetect)]),
[WITH_LIBCRYPTO=$withval],
[AC_CHECK_LIB([crypto], [SHA1],
On Windows, \fB@IMAGEX_PROGNAME@ capture\fR and \fB@IMAGEX_PROGNAME@ append\fR
try to archive as much data and metadata as possible, including:
.IP \[bu] 4
-All data streams of all files, unless running on a version of Windows prior to
-Vista, in which case named data streams (if supported by the source filesystem)
-will not be captured.
+All data streams of all files.
.IP \[bu]
Reparse points, including symbolic links, junction points, and other reparse
points, if supported by the source filesystem. (Note: see \fB--rpfix\fR and
#include "wimlib/types.h"
#include "wimlib/win32.h"
+#ifdef WITH_NTDLL
+# include <ntstatus.h>
+# include <winternl.h>
+#endif
+
extern void
set_errno_from_GetLastError(void);
#ifdef WITH_NTDLL
extern void
-set_errno_from_nt_status(DWORD status);
+set_errno_from_nt_status(NTSTATUS status);
#endif
extern bool
const wchar_t *lpTargetFileName,
DWORD dwFlags);
+/* ntdll functions */
+
+#ifdef WITH_NTDLL
+
+extern NTSTATUS (WINAPI *func_NtQueryInformationFile)(HANDLE FileHandle,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID FileInformation,
+ ULONG Length,
+ FILE_INFORMATION_CLASS FileInformationClass);
+
+extern NTSTATUS (WINAPI *func_NtQuerySecurityObject)(HANDLE handle,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ ULONG Length,
+ PULONG LengthNeeded);
+
+extern 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);
+
+
+extern NTSTATUS (WINAPI *func_NtSetSecurityObject)(HANDLE Handle,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR SecurityDescriptor);
+
+extern DWORD (WINAPI *func_RtlNtStatusToDosError)(NTSTATUS status);
+#endif
+
+
+
extern bool
windows_version_is_at_least(unsigned major, unsigned minor);
#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)
{
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) {
+ ERROR_WITH_ERRNO("Can't open %ls (%u)", path, GetLastError());
+ goto error;
+ }
}
#endif
ret = 0;
out_close:
#ifdef WITH_NTDLL
- CloseHandle(h);
+ if (func_NtSetSecurityObject)
+ CloseHandle(h);
#endif
return ret;
#include "wimlib/paths.h"
#include "wimlib/reparse.h"
-#ifdef WITH_NTDLL
-# include <winternl.h>
-# include <ntstatus.h>
-
-NTSTATUS WINAPI
-NtQuerySecurityObject(HANDLE handle,
- SECURITY_INFORMATION SecurityInformation,
- PSECURITY_DESCRIPTOR SecurityDescriptor,
- ULONG Length,
- PULONG LengthNeeded);
-NTSTATUS WINAPI
-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);
-#endif
-
#define MAX_GET_SD_ACCESS_DENIED_WARNINGS 1
#define MAX_GET_SACL_PRIV_NOTHELD_WARNINGS 1
#define MAX_CAPTURE_LONG_PATH_WARNINGS 5
* call ourselves, and it saves a dumb call to FindFirstFile() which of
* course has to create its own handle. */
#ifdef WITH_NTDLL
- NTSTATUS status;
- IO_STATUS_BLOCK io_status;
- u8 buf[128] _aligned_attribute(8);
- const FILE_NAME_INFORMATION *info;
-
- status = NtQueryInformationFile(hFile, &io_status, buf, sizeof(buf),
- FileAlternateNameInformation);
- info = (const FILE_NAME_INFORMATION*)buf;
- if (status == STATUS_SUCCESS && info->FileNameLength != 0) {
- dentry->short_name = MALLOC(info->FileNameLength + 2);
- if (!dentry->short_name)
- return WIMLIB_ERR_NOMEM;
- memcpy(dentry->short_name, info->FileName,
- info->FileNameLength);
- dentry->short_name[info->FileNameLength / 2] = L'\0';
- dentry->short_name_nbytes = info->FileNameLength;
+ if (func_NtQueryInformationFile) {
+ NTSTATUS status;
+ IO_STATUS_BLOCK io_status;
+ u8 buf[128] _aligned_attribute(8);
+ const FILE_NAME_INFORMATION *info;
+
+ status = (*func_NtQueryInformationFile)(hFile, &io_status, buf, sizeof(buf),
+ FileAlternateNameInformation);
+ info = (const FILE_NAME_INFORMATION*)buf;
+ if (status == STATUS_SUCCESS && info->FileNameLength != 0) {
+ dentry->short_name = MALLOC(info->FileNameLength + 2);
+ if (!dentry->short_name)
+ return WIMLIB_ERR_NOMEM;
+ memcpy(dentry->short_name, info->FileName,
+ info->FileNameLength);
+ dentry->short_name[info->FileNameLength / 2] = L'\0';
+ dentry->short_name_nbytes = info->FileNameLength;
+ }
+ return 0;
}
- return 0;
-#else
+#endif
+
WIN32_FIND_DATAW dat;
HANDLE hFind;
int ret = 0;
FindClose(hFind);
}
return ret;
-#endif
}
/*
DWORD bufsize, DWORD *lengthNeeded)
{
#ifdef WITH_NTDLL
- NTSTATUS status;
-
- status = NtQuerySecurityObject(hFile, requestedInformation, buf,
- bufsize, lengthNeeded);
- /* Since it queries an already-open handle, NtQuerySecurityObject()
- * apparently returns STATUS_ACCESS_DENIED rather than
- * STATUS_PRIVILEGE_NOT_HELD. */
- if (status == STATUS_ACCESS_DENIED)
- return ERROR_PRIVILEGE_NOT_HELD;
- else
- return RtlNtStatusToDosError(status);
-#else
+ if (func_NtQuerySecurityObject) {
+ NTSTATUS status;
+
+ status = (*func_NtQuerySecurityObject)(hFile,
+ requestedInformation, buf,
+ bufsize, lengthNeeded);
+ /* Since it queries an already-open handle, NtQuerySecurityObject()
+ * apparently returns STATUS_ACCESS_DENIED rather than
+ * STATUS_PRIVILEGE_NOT_HELD. */
+ if (status == STATUS_ACCESS_DENIED)
+ return ERROR_PRIVILEGE_NOT_HELD;
+ else
+ return (*func_RtlNtStatusToDosError)(status);
+ }
+#endif
if (GetFileSecurity(path, requestedInformation, buf,
bufsize, lengthNeeded))
return ERROR_SUCCESS;
else
return GetLastError();
-#endif
}
static int
* which we opened with FILE_FLAG_BACKUP_SEMANTICS (probably not the
* case for the FindFirstFile() API; it's not documented). */
#ifdef WITH_NTDLL
- NTSTATUS status;
- IO_STATUS_BLOCK io_status;
- const size_t bufsize = 8192;
- u8 *buf;
- BOOL restartScan = TRUE;
- const FILE_NAMES_INFORMATION *info;
-
- buf = MALLOC(bufsize);
- if (!buf)
- return WIMLIB_ERR_NOMEM;
- for (;;) {
- status = NtQueryDirectoryFile(hDir, NULL, NULL, NULL,
- &io_status, buf, bufsize,
- FileNamesInformation,
- FALSE, NULL, restartScan);
- restartScan = FALSE;
- if (status != STATUS_SUCCESS) {
- if (status == STATUS_NO_MORE_FILES ||
- status == STATUS_NO_MORE_ENTRIES ||
- status == STATUS_NO_MORE_MATCHES) {
- ret = 0;
- } else {
- set_errno_from_nt_status(status);
- ERROR_WITH_ERRNO("Failed to read directory "
- "\"%ls\"", dir_path);
- ret = WIMLIB_ERR_READ;
- }
- goto out_free_buf;
- }
- wimlib_assert(io_status.Information != 0);
- info = (const FILE_NAMES_INFORMATION*)buf;
+ if (func_NtQueryDirectoryFile) {
+ NTSTATUS status;
+ IO_STATUS_BLOCK io_status;
+ const size_t bufsize = 8192;
+ u8 *buf;
+ BOOL restartScan = TRUE;
+ const FILE_NAMES_INFORMATION *info;
+
+ buf = MALLOC(bufsize);
+ if (!buf)
+ return WIMLIB_ERR_NOMEM;
for (;;) {
- if (!(info->FileNameLength == 2 && info->FileName[0] == L'.') &&
- !(info->FileNameLength == 4 && info->FileName[0] == L'.' &&
- info->FileName[1] == L'.'))
- {
- wchar_t *p;
- struct wim_dentry *child;
-
- p = dir_path + dir_path_num_chars;
- *p++ = L'\\';
- p = wmempcpy(p, info->FileName,
- info->FileNameLength / 2);
- *p = '\0';
-
- ret = win32_build_dentry_tree_recursive(
- &child,
- dir_path,
- p - dir_path,
- params,
- state,
- vol_flags);
-
- dir_path[dir_path_num_chars] = L'\0';
-
- if (ret)
- goto out_free_buf;
- if (child)
- dentry_add_child(root, child);
+ status = (*func_NtQueryDirectoryFile)(hDir, NULL, NULL, NULL,
+ &io_status, buf, bufsize,
+ FileNamesInformation,
+ FALSE, NULL, restartScan);
+ restartScan = FALSE;
+ if (status != STATUS_SUCCESS) {
+ if (status == STATUS_NO_MORE_FILES ||
+ status == STATUS_NO_MORE_ENTRIES ||
+ status == STATUS_NO_MORE_MATCHES) {
+ ret = 0;
+ } else {
+ set_errno_from_nt_status(status);
+ ERROR_WITH_ERRNO("Failed to read directory "
+ "\"%ls\"", dir_path);
+ ret = WIMLIB_ERR_READ;
+ }
+ goto out_free_buf;
+ }
+ wimlib_assert(io_status.Information != 0);
+ info = (const FILE_NAMES_INFORMATION*)buf;
+ for (;;) {
+ if (!(info->FileNameLength == 2 && info->FileName[0] == L'.') &&
+ !(info->FileNameLength == 4 && info->FileName[0] == L'.' &&
+ info->FileName[1] == L'.'))
+ {
+ wchar_t *p;
+ struct wim_dentry *child;
+
+ p = dir_path + dir_path_num_chars;
+ *p++ = L'\\';
+ p = wmempcpy(p, info->FileName,
+ info->FileNameLength / 2);
+ *p = '\0';
+
+ ret = win32_build_dentry_tree_recursive(
+ &child,
+ dir_path,
+ p - dir_path,
+ params,
+ state,
+ vol_flags);
+
+ dir_path[dir_path_num_chars] = L'\0';
+
+ if (ret)
+ goto out_free_buf;
+ if (child)
+ dentry_add_child(root, child);
+ }
+ if (info->NextEntryOffset == 0)
+ break;
+ info = (const FILE_NAMES_INFORMATION*)
+ ((const u8*)info + info->NextEntryOffset);
}
- if (info->NextEntryOffset == 0)
- break;
- info = (const FILE_NAMES_INFORMATION*)
- ((const u8*)info + info->NextEntryOffset);
}
+ out_free_buf:
+ FREE(buf);
+ return ret;
}
-out_free_buf:
- FREE(buf);
- return ret;
-#else
+#endif
WIN32_FIND_DATAW dat;
HANDLE hFind;
DWORD err;
out_find_close:
FindClose(hFind);
return ret;
-#endif
}
/* Reparse point fixup status code */
IO_STATUS_BLOCK io_status;
NTSTATUS status;
const FILE_STREAM_INFORMATION *info;
-#else
+#endif
HANDLE hFind;
DWORD err;
-#endif
DEBUG("Capturing streams from \"%ls\"", path);
if (!(vol_flags & FILE_NAMED_STREAMS))
goto unnamed_only;
-#ifndef WITH_NTDLL
- if (win32func_FindFirstStreamW == NULL)
- goto unnamed_only;
-#endif
#ifdef WITH_NTDLL
- buf = _buf;
- bufsize = sizeof(_buf);
+ if (func_NtQueryInformationFile) {
+ buf = _buf;
+ bufsize = sizeof(_buf);
- /* Get a buffer containing the stream information. */
- for (;;) {
- status = NtQueryInformationFile(*hFile_p, &io_status, buf, bufsize,
- FileStreamInformation);
- if (status == STATUS_SUCCESS) {
- break;
- } else if (status == STATUS_BUFFER_OVERFLOW) {
- u8 *newbuf;
+ /* Get a buffer containing the stream information. */
+ for (;;) {
+ status = (*func_NtQueryInformationFile)(*hFile_p, &io_status,
+ buf, bufsize,
+ FileStreamInformation);
+ if (status == STATUS_SUCCESS) {
+ break;
+ } else if (status == STATUS_BUFFER_OVERFLOW) {
+ u8 *newbuf;
- bufsize *= 2;
- if (buf == _buf)
- newbuf = MALLOC(bufsize);
- else
- newbuf = REALLOC(buf, bufsize);
+ bufsize *= 2;
+ if (buf == _buf)
+ newbuf = MALLOC(bufsize);
+ else
+ newbuf = REALLOC(buf, bufsize);
- if (!newbuf) {
- ret = WIMLIB_ERR_NOMEM;
+ if (!newbuf) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_buf;
+ }
+ buf = newbuf;
+ } else {
+ set_errno_from_nt_status(status);
+ ERROR_WITH_ERRNO("Failed to read streams of %ls", path);
+ ret = WIMLIB_ERR_READ;
goto out_free_buf;
}
- buf = newbuf;
- } else {
- set_errno_from_nt_status(status);
- ERROR_WITH_ERRNO("Failed to read streams of %ls", path);
- ret = WIMLIB_ERR_READ;
- goto out_free_buf;
}
- }
- if (io_status.Information == 0) {
- /* No stream information. */
- ret = 0;
- goto out_free_buf;
- }
-
- if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
- /* OpenEncryptedFileRaw() seems to fail with
- * ERROR_SHARING_VIOLATION if there are any handles opened to
- * the file. */
- CloseHandle(*hFile_p);
- *hFile_p = INVALID_HANDLE_VALUE;
- }
+ if (io_status.Information == 0) {
+ /* No stream information. */
+ ret = 0;
+ goto out_free_buf;
+ }
- /* Parse one or more stream information structures. */
- info = (const FILE_STREAM_INFORMATION*)buf;
- for (;;) {
- if (info->StreamNameLength <= sizeof(dat.cStreamName) - 2) {
- dat.StreamSize = info->StreamSize;
- memcpy(dat.cStreamName, info->StreamName, info->StreamNameLength);
- dat.cStreamName[info->StreamNameLength / 2] = L'\0';
-
- /* Capture the stream. */
- ret = win32_capture_stream(path, path_num_chars, inode,
- lookup_table, &dat);
- if (ret)
- goto out_free_buf;
+ if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
+ /* OpenEncryptedFileRaw() seems to fail with
+ * ERROR_SHARING_VIOLATION if there are any handles opened to
+ * the file. */
+ CloseHandle(*hFile_p);
+ *hFile_p = INVALID_HANDLE_VALUE;
}
- if (info->NextEntryOffset == 0) {
- /* No more stream information. */
- ret = 0;
- break;
+
+ /* Parse one or more stream information structures. */
+ info = (const FILE_STREAM_INFORMATION*)buf;
+ for (;;) {
+ if (info->StreamNameLength <= sizeof(dat.cStreamName) - 2) {
+ dat.StreamSize = info->StreamSize;
+ memcpy(dat.cStreamName, info->StreamName, info->StreamNameLength);
+ dat.cStreamName[info->StreamNameLength / 2] = L'\0';
+
+ /* Capture the stream. */
+ ret = win32_capture_stream(path, path_num_chars, inode,
+ lookup_table, &dat);
+ if (ret)
+ goto out_free_buf;
+ }
+ if (info->NextEntryOffset == 0) {
+ /* No more stream information. */
+ ret = 0;
+ break;
+ }
+ /* Advance to next stream information. */
+ info = (const FILE_STREAM_INFORMATION*)
+ ((const u8*)info + info->NextEntryOffset);
}
- /* Advance to next stream information. */
- info = (const FILE_STREAM_INFORMATION*)
- ((const u8*)info + info->NextEntryOffset);
+ out_free_buf:
+ /* Free buffer if allocated on heap. */
+ if (buf != _buf)
+ FREE(buf);
+ return ret;
}
-out_free_buf:
- /* Free buffer if allocated on heap. */
- if (buf != _buf)
- FREE(buf);
- return ret;
+#endif /* WITH_NTDLL */
-#else /* WITH_NTDLL */
+ if (win32func_FindFirstStreamW == NULL)
+ goto unnamed_only;
hFind = win32func_FindFirstStreamW(path, FindStreamInfoStandard, &dat, 0);
if (hFind == INVALID_HANDLE_VALUE) {
err = GetLastError();
out_find_close:
FindClose(hFind);
return ret;
-#endif /* !WITH_NTDLL */
unnamed_only:
/* FindFirstStream() API is not available, or the volume does not
DWORD dret;
bool need_prefix_free = false;
-#ifndef WITH_NTDLL
- if (!win32func_FindFirstStreamW) {
+ if (!win32func_FindFirstStreamW
+#ifdef WITH_NTDLL
+ && !func_NtQueryInformationFile
+#endif
+ )
+ {
WARNING("Running on Windows XP or earlier; "
"alternate data streams will not be captured.");
}
-#endif
path_nchars = wcslen(root_disk_path);
if (path_nchars > WINDOWS_NT_MAX_PATH)
#ifdef WITH_NTDLL
void
-set_errno_from_nt_status(DWORD status)
+set_errno_from_nt_status(NTSTATUS status)
{
- set_errno_from_win32_error(RtlNtStatusToDosError(status));
+ set_errno_from_win32_error((*func_RtlNtStatusToDosError)(status));
}
#endif
NULL /* hTemplateFile */);
}
-#ifndef WITH_NTDLL
/* Pointers to functions that are not available on all targetted versions of
* Windows (XP and later). NOTE: The WINAPI annotations seem to be important; I
* assume it specifies a certain calling convention. */
/* Vista and later */
BOOL (WINAPI *win32func_FindNextStreamW)(HANDLE hFindStream,
LPVOID lpFindStreamData) = NULL;
-#endif /* !WITH_NTDLL */
/* Vista and later */
BOOL (WINAPI *win32func_CreateSymbolicLinkW)(const wchar_t *lpSymlinkFileName,
const wchar_t *lpTargetFileName,
DWORD dwFlags) = NULL;
+#ifdef WITH_NTDLL
+
+DWORD (WINAPI *func_RtlNtStatusToDosError)(NTSTATUS status);
+
+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_NtSetSecurityObject)(HANDLE Handle,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR SecurityDescriptor);
+
+#endif /* WITH_NTDLL */
+
static OSVERSIONINFO windows_version_info = {
.dwOSVersionInfoSize = sizeof(OSVERSIONINFO),
};
static HMODULE hKernel32 = NULL;
+#ifdef WITH_NTDLL
+static HMODULE hNtdll = NULL;
+#endif
+
static bool acquired_privileges = false;
bool
hKernel32 = LoadLibrary(L"Kernel32.dll");
if (hKernel32) {
- #ifndef WITH_NTDLL
win32func_FindFirstStreamW = (void*)GetProcAddress(hKernel32,
"FindFirstStreamW");
if (win32func_FindFirstStreamW) {
if (!win32func_FindNextStreamW)
win32func_FindFirstStreamW = NULL;
}
- #endif /* !WITH_NTDLL */
win32func_CreateSymbolicLinkW = (void*)GetProcAddress(hKernel32,
"CreateSymbolicLinkW");
}
+
+#ifdef WITH_NTDLL
+ if (hNtdll == NULL)
+ hNtdll = LoadLibrary(L"ntdll.dll");
+
+ if (hNtdll) {
+ func_RtlNtStatusToDosError =
+ (void*)GetProcAddress(hNtdll, "RtlNtStatusToDosError");
+ if (func_RtlNtStatusToDosError) {
+
+ func_NtQuerySecurityObject =
+ (void*)GetProcAddress(hNtdll, "NtQuerySecurityObject");
+
+ func_NtQueryDirectoryFile =
+ (void*)GetProcAddress(hNtdll, "NtQueryDirectoryFile");
+
+ func_NtQueryInformationFile =
+ (void*)GetProcAddress(hNtdll, "NtQueryInformationFile");
+
+ func_NtSetSecurityObject =
+ (void*)GetProcAddress(hNtdll, "NtSetSecurityObject");
+ }
+ }
+
+ DEBUG("FindFirstStreamW @ %p", win32func_FindFirstStreamW);
+ DEBUG("FindNextStreamW @ %p", win32func_FindNextStreamW);
+ DEBUG("CreateSymbolicLinkW @ %p", win32func_CreateSymbolicLinkW);
+ DEBUG("RtlNtStatusToDosError @ %p", func_RtlNtStatusToDosError);
+ DEBUG("NtQuerySecurityObject @ %p", func_NtQuerySecurityObject);
+ DEBUG("NtQueryDirectoryFile @ %p", func_NtQueryDirectoryFile);
+ DEBUG("NtQueryInformationFile @ %p", func_NtQueryInformationFile);
+ DEBUG("NtSetSecurityObject @ %p", func_NtSetSecurityObject);
+#endif
+
return 0;
insufficient_privileges:
FreeLibrary(hKernel32);
hKernel32 = NULL;
}
+#ifdef WITH_NTDLL
+ if (hNtdll != NULL) {
+ FreeLibrary(hNtdll);
+ hNtdll = NULL;
+ }
+#endif
}
#endif /* __WIN32__ */