#ifndef BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_
#define BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_
#include <boost/filesystem/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/file_status.hpp>
#include <boost/system/error_code.hpp>
#include <boost/scope/unique_resource.hpp>
#include <boost/winapi/basic_types.hpp>
#include <windows.h>
#include <boost/filesystem/detail/header.hpp>
#ifndef IO_REPARSE_TAG_DEDUP
#define IO_REPARSE_TAG_DEDUP (0x80000013L)
#endif
#ifndef IO_REPARSE_TAG_MOUNT_POINT
#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
#endif
#ifndef IO_REPARSE_TAG_SYMLINK
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
#endif
namespace boost {
namespace filesystem {
namespace detail {
struct handle_deleter
{
using result_type = void;
result_type operator() (HANDLE h) const noexcept
{
::CloseHandle(h);
}
};
struct handle_resource_traits
{
static HANDLE make_default() noexcept
{
return INVALID_HANDLE_VALUE;
}
static bool is_allocated(HANDLE h) noexcept
{
return h != INVALID_HANDLE_VALUE && h != nullptr;
}
};
using unique_handle = boost::scope::unique_resource< HANDLE, handle_deleter, handle_resource_traits >;
BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST wchar_t colon = L':';
BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST wchar_t questionmark = L'?';
inline bool is_letter(wchar_t c)
{
return (c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z');
}
inline bool equal_extension(wchar_t const* p, wchar_t const (&x1)[5], wchar_t const (&x2)[5])
{
return (p[0] == x1[0] || p[0] == x2[0]) &&
(p[1] == x1[1] || p[1] == x2[1]) &&
(p[2] == x1[2] || p[2] == x2[2]) &&
(p[3] == x1[3] || p[3] == x2[3]) &&
p[4] == 0;
}
inline boost::filesystem::perms make_permissions(boost::filesystem::path const& p, DWORD attr)
{
boost::filesystem::perms prms = boost::filesystem::owner_read | boost::filesystem::group_read | boost::filesystem::others_read;
if ((attr & FILE_ATTRIBUTE_READONLY) == 0u)
prms |= boost::filesystem::owner_write | boost::filesystem::group_write | boost::filesystem::others_write;
boost::filesystem::path ext = detail::path_algorithms::extension_v4(p);
wchar_t const* q = ext.c_str();
if (equal_extension(q, L".exe", L".EXE") || equal_extension(q, L".com", L".COM") || equal_extension(q, L".bat", L".BAT") || equal_extension(q, L".cmd", L".CMD"))
prms |= boost::filesystem::owner_exe | boost::filesystem::group_exe | boost::filesystem::others_exe;
return prms;
}
ULONG get_reparse_point_tag_ioctl(HANDLE h, boost::filesystem::path const& p, boost::system::error_code* ec);
inline bool is_reparse_point_tag_a_symlink(ULONG reparse_point_tag)
{
return reparse_point_tag == IO_REPARSE_TAG_SYMLINK
|| reparse_point_tag == IO_REPARSE_TAG_MOUNT_POINT; }
struct directory_iterator_params
{
HANDLE dir_handle;
bool close_handle;
};
struct io_status_block
{
union
{
boost::winapi::NTSTATUS_ Status;
PVOID Pointer;
};
ULONG_PTR Information;
};
struct unicode_string
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
};
struct object_attributes
{
ULONG Length;
HANDLE RootDirectory;
unicode_string* ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
};
#ifndef OBJ_CASE_INSENSITIVE
#define OBJ_CASE_INSENSITIVE 0x00000040
#endif
#ifndef OBJ_DONT_REPARSE
#define OBJ_DONT_REPARSE 0x00001000
#endif
#ifndef FILE_SUPERSEDE
#define FILE_SUPERSEDE 0x00000000
#endif
#ifndef FILE_OPEN
#define FILE_OPEN 0x00000001
#endif
#ifndef FILE_CREATE
#define FILE_CREATE 0x00000002
#endif
#ifndef FILE_OPEN_IF
#define FILE_OPEN_IF 0x00000003
#endif
#ifndef FILE_OVERWRITE
#define FILE_OVERWRITE 0x00000004
#endif
#ifndef FILE_OVERWRITE_IF
#define FILE_OVERWRITE_IF 0x00000005
#endif
#ifndef FILE_DIRECTORY_FILE
#define FILE_DIRECTORY_FILE 0x00000001
#endif
#ifndef FILE_SYNCHRONOUS_IO_NONALERT
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#endif
#ifndef FILE_OPEN_FOR_BACKUP_INTENT
#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000
#endif
#ifndef FILE_OPEN_REPARSE_POINT
#define FILE_OPEN_REPARSE_POINT 0x00200000
#endif
typedef boost::winapi::NTSTATUS_ (NTAPI NtCreateFile_t)(
PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
object_attributes* ObjectAttributes,
io_status_block* IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength);
extern NtCreateFile_t* nt_create_file_api;
typedef VOID (NTAPI* pio_apc_routine) (PVOID ApcContext, io_status_block* IoStatusBlock, ULONG Reserved);
enum file_information_class
{
file_directory_information_class = 1
};
typedef boost::winapi::NTSTATUS_ (NTAPI NtQueryDirectoryFile_t)(
HANDLE FileHandle,
HANDLE Event,
pio_apc_routine ApcRoutine,
PVOID ApcContext,
io_status_block* IoStatusBlock,
PVOID FileInformation,
ULONG Length,
file_information_class FileInformationClass,
BOOLEAN ReturnSingleEntry,
unicode_string* FileName,
BOOLEAN RestartScan);
extern NtQueryDirectoryFile_t* nt_query_directory_file_api;
enum file_info_by_handle_class
{
file_basic_info_class = 0,
file_disposition_info_class = 4,
file_attribute_tag_info_class = 9,
file_id_both_directory_info_class = 10,
file_id_both_directory_restart_info_class = 11,
file_full_directory_info_class = 14,
file_full_directory_restart_info_class = 15,
file_id_extd_directory_info_class = 19,
file_id_extd_directory_restart_info_class = 20,
file_disposition_info_ex_class = 21
};
struct file_attribute_tag_info
{
DWORD FileAttributes;
DWORD ReparseTag;
};
typedef BOOL (WINAPI GetFileInformationByHandleEx_t)(
HANDLE hFile,
file_info_by_handle_class FileInformationClass, LPVOID lpFileInformation,
DWORD dwBufferSize);
extern GetFileInformationByHandleEx_t* get_file_information_by_handle_ex_api;
inline unique_handle create_file_handle
(
boost::filesystem::path const& p,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile = nullptr
)
{
return unique_handle(::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile));
}
boost::winapi::NTSTATUS_ nt_create_file_handle_at
(
unique_handle& out,
HANDLE basedir_handle,
boost::filesystem::path const& p,
ULONG FileAttributes,
ACCESS_MASK DesiredAccess,
ULONG ShareMode,
ULONG CreateDisposition,
ULONG CreateOptions
);
filesystem::file_status status_by_handle(HANDLE h, path const& p, system::error_code* ec);
} } }
#include <boost/filesystem/detail/footer.hpp>
#endif