Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'include/afio/v2.0/detail/impl/windows/import.hpp')
-rw-r--r--include/afio/v2.0/detail/impl/windows/import.hpp1164
1 files changed, 1164 insertions, 0 deletions
diff --git a/include/afio/v2.0/detail/impl/windows/import.hpp b/include/afio/v2.0/detail/impl/windows/import.hpp
new file mode 100644
index 00000000..4fd27f41
--- /dev/null
+++ b/include/afio/v2.0/detail/impl/windows/import.hpp
@@ -0,0 +1,1164 @@
+/* Declarations for Microsoft Windows system APIs
+(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (14 commits)
+File Created: Dec 2015
+
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License in the accompanying file
+Licence.txt or at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file Licence.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_AFIO_WINDOWS_H
+#define BOOST_AFIO_WINDOWS_H
+
+#include "../../../handle.hpp"
+#include <memory> // for unique_ptr
+
+#ifndef _WIN32
+#error You should not include windows/import.hpp on not Windows platforms
+#endif
+
+#include <sal.h>
+
+// At some future point we will not do this, and instead import symbols manually
+// to avoid the windows.h inclusion
+#if 1
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#include <winternl.h>
+
+#else
+#error todo
+#endif
+
+BOOST_AFIO_V2_NAMESPACE_BEGIN
+
+namespace windows_nt_kernel
+{
+// Weirdly these appear to be undefined sometimes?
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((LONG) 0x00000000L)
+#endif
+#ifndef STATUS_ALERTED
+#define STATUS_ALERTED ((LONG) 0x00000101L)
+#endif
+#ifndef STATUS_DELETE_PENDING
+#define STATUS_DELETE_PENDING ((LONG) 0xC0000056)
+#endif
+
+ // From http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/FILE_INFORMATION_CLASS.html
+ typedef enum _FILE_INFORMATION_CLASS {
+ FileDirectoryInformation = 1,
+ FileFullDirectoryInformation,
+ FileBothDirectoryInformation,
+ FileBasicInformation,
+ FileStandardInformation,
+ FileInternalInformation,
+ FileEaInformation,
+ FileAccessInformation,
+ FileNameInformation,
+ FileRenameInformation,
+ FileLinkInformation,
+ FileNamesInformation,
+ FileDispositionInformation,
+ FilePositionInformation,
+ FileFullEaInformation,
+ FileModeInformation,
+ FileAlignmentInformation,
+ FileAllInformation,
+ FileAllocationInformation,
+ FileEndOfFileInformation,
+ FileAlternateNameInformation,
+ FileStreamInformation,
+ FilePipeInformation,
+ FilePipeLocalInformation,
+ FilePipeRemoteInformation,
+ FileMailslotQueryInformation,
+ FileMailslotSetInformation,
+ FileCompressionInformation,
+ FileObjectIdInformation,
+ FileCompletionInformation,
+ FileMoveClusterInformation,
+ FileQuotaInformation,
+ FileReparsePointInformation,
+ FileNetworkOpenInformation,
+ FileAttributeTagInformation,
+ FileTrackingInformation,
+ FileIdBothDirectoryInformation,
+ FileIdFullDirectoryInformation,
+ FileValidDataLengthInformation,
+ FileShortNameInformation,
+ FileIoCompletionNotificationInformation,
+ FileIoStatusBlockRangeInformation,
+ FileIoPriorityHintInformation,
+ FileSfioReserveInformation,
+ FileSfioVolumeInformation,
+ FileHardLinkInformation,
+ FileProcessIdsUsingFileInformation,
+ FileNormalizedNameInformation,
+ FileNetworkPhysicalNameInformation,
+ FileIdGlobalTxDirectoryInformation,
+ FileIsRemoteDeviceInformation,
+ FileAttributeCacheInformation,
+ FileNumaNodeInformation,
+ FileStandardLinkInformation,
+ FileRemoteProtocolInformation,
+ FileMaximumInformation
+ } FILE_INFORMATION_CLASS,
+ *PFILE_INFORMATION_CLASS;
+
+ typedef enum {
+ FileFsVolumeInformation = 1,
+ FileFsLabelInformation = 2,
+ FileFsSizeInformation = 3,
+ FileFsDeviceInformation = 4,
+ FileFsAttributeInformation = 5,
+ FileFsControlInformation = 6,
+ FileFsFullSizeInformation = 7,
+ FileFsObjectIdInformation = 8,
+ FileFsDriverPathInformation = 9,
+ FileFsVolumeFlagsInformation = 10,
+ FileFsSectorSizeInformation = 11
+ } FS_INFORMATION_CLASS;
+
+ typedef enum { ObjectBasicInformation = 0, ObjectNameInformation = 1, ObjectTypeInformation = 2 } OBJECT_INFORMATION_CLASS;
+
+#ifndef NTSTATUS
+#define NTSTATUS LONG
+#endif
+#ifndef STATUS_TIMEOUT
+#define STATUS_TIMEOUT ((NTSTATUS) 0x00000102)
+#endif
+#ifndef STATUS_PENDING
+#define STATUS_PENDING ((NTSTATUS) 0x00000103)
+#endif
+#ifndef STATUS_BUFFER_OVERFLOW
+#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
+#endif
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff550671(v=vs.85).aspx
+ typedef struct _IO_STATUS_BLOCK
+ {
+ union {
+ NTSTATUS Status;
+ PVOID Pointer;
+ };
+ ULONG_PTR Information;
+ } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/aa380518(v=vs.85).aspx
+ typedef struct _LSA_UNICODE_STRING
+ {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+ } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff557749(v=vs.85).aspx
+ typedef struct _OBJECT_ATTRIBUTES
+ {
+ ULONG Length;
+ HANDLE RootDirectory;
+ PUNICODE_STRING ObjectName;
+ ULONG Attributes;
+ PVOID SecurityDescriptor;
+ PVOID SecurityQualityOfService;
+ } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+
+ typedef VOID(NTAPI *PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved);
+
+ typedef struct _IMAGEHLP_LINE64
+ {
+ DWORD SizeOfStruct;
+ PVOID Key;
+ DWORD LineNumber;
+ PTSTR FileName;
+ DWORD64 Address;
+ } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
+
+ typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT, *PSECTION_INHERIT;
+
+ typedef struct _WIN32_MEMORY_RANGE_ENTRY
+ {
+ PVOID VirtualAddress;
+ SIZE_T NumberOfBytes;
+ } WIN32_MEMORY_RANGE_ENTRY, *PWIN32_MEMORY_RANGE_ENTRY;
+
+ // From https://msdn.microsoft.com/en-us/library/bb432383%28v=vs.85%29.aspx
+ typedef NTSTATUS(NTAPI *NtQueryObject_t)(_In_opt_ HANDLE Handle, _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, _Out_opt_ PVOID ObjectInformation, _In_ ULONG ObjectInformationLength, _Out_opt_ PULONG ReturnLength);
+
+ // From http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryInformationFile.html
+ // and http://msdn.microsoft.com/en-us/library/windows/hardware/ff567052(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtQueryInformationFile_t)(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _Out_ PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass);
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff567070(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtQueryVolumeInformationFile_t)(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _Out_ PVOID FsInformation, _In_ ULONG Length, _In_ FS_INFORMATION_CLASS FsInformationClass);
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff566492(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtOpenDirectoryObject_t)(_Out_ PHANDLE DirectoryHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes);
+
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff567011(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtOpenFile_t)(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions);
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff566424(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtCreateFile_t)(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_opt_ PLARGE_INTEGER AllocationSize, _In_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition,
+ _In_ ULONG CreateOptions, _In_opt_ PVOID EaBuffer, _In_ ULONG EaLength);
+
+ typedef NTSTATUS(NTAPI *NtDeleteFile_t)(_In_ POBJECT_ATTRIBUTES ObjectAttributes);
+
+ typedef NTSTATUS(NTAPI *NtClose_t)(_Out_ HANDLE FileHandle);
+
+ // From http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryDirectoryFile.html
+ // and http://msdn.microsoft.com/en-us/library/windows/hardware/ff567047(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtQueryDirectoryFile_t)(_In_ HANDLE FileHandle, _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _Out_ PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass,
+ _In_ BOOLEAN ReturnSingleEntry, _In_opt_ PUNICODE_STRING FileName, _In_ BOOLEAN RestartScan);
+
+ // From http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtSetInformationFile.html
+ // and http://msdn.microsoft.com/en-us/library/windows/hardware/ff567096(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtSetInformationFile_t)(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ PVOID FileInformation, _In_ ULONG Length, _In_ FILE_INFORMATION_CLASS FileInformationClass);
+
+ // From http://msdn.microsoft.com/en-us/library/ms648412(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtWaitForSingleObject_t)(_In_ HANDLE Handle, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout);
+
+ typedef enum _OBJECT_WAIT_TYPE { WaitAllObject, WaitAnyObject } OBJECT_WAIT_TYPE, *POBJECT_WAIT_TYPE;
+
+ typedef NTSTATUS(NTAPI *NtWaitForMultipleObjects_t)(_In_ ULONG Count, _In_ HANDLE Object[], _In_ OBJECT_WAIT_TYPE WaitType, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Time);
+
+ typedef NTSTATUS(NTAPI *NtDelayExecution_t)(_In_ BOOLEAN Alertable, _In_opt_ LARGE_INTEGER *Interval);
+
+ // From https://msdn.microsoft.com/en-us/library/windows/hardware/ff566474(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtLockFile_t)(_In_ HANDLE FileHandle, _In_opt_ HANDLE Event, _In_opt_ PIO_APC_ROUTINE ApcRoutine, _In_opt_ PVOID ApcContext, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ PLARGE_INTEGER ByteOffset, _In_ PLARGE_INTEGER Length, _In_ ULONG Key, _In_ BOOLEAN FailImmediately,
+ _In_ BOOLEAN ExclusiveLock);
+
+ // From https://msdn.microsoft.com/en-us/library/windows/hardware/ff567118(v=vs.85).aspx
+ typedef NTSTATUS(NTAPI *NtUnlockFile_t)(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ PLARGE_INTEGER ByteOffset, _In_ PLARGE_INTEGER Length, _In_ ULONG Key);
+
+ typedef NTSTATUS(NTAPI *NtCreateSection_t)(_Out_ PHANDLE SectionHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ PLARGE_INTEGER MaximumSize, _In_ ULONG SectionPageProtection, _In_ ULONG AllocationAttributes, _In_opt_ HANDLE FileHandle);
+
+ typedef NTSTATUS(NTAPI *NtExtendSection_t)(_In_ HANDLE SectionHandle, _In_opt_ PLARGE_INTEGER MaximumSize);
+
+ typedef NTSTATUS(NTAPI *NtMapViewOfSection_t)(_In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, _Inout_ PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_ SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType,
+ _In_ ULONG Win32Protect);
+
+ typedef NTSTATUS(NTAPI *NtUnmapViewOfSection_t)(_In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress);
+
+ typedef NTSTATUS(NTAPI *NtFlushBuffersFileEx_t)(_In_ HANDLE FileHandle, _In_ ULONG Flags, _Out_ PIO_STATUS_BLOCK IoStatusBlock);
+
+ typedef BOOLEAN(NTAPI *RtlGenRandom_t)(_Out_ PVOID RandomBuffer, _In_ ULONG RandomBufferLength);
+
+ typedef BOOL(WINAPI *OpenProcessToken_t)(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Out_ PHANDLE TokenHandle);
+
+ typedef BOOL(WINAPI *LookupPrivilegeValue_t)(_In_opt_ LPCTSTR lpSystemName, _In_ LPCTSTR lpName, _Out_ PLUID lpLuid);
+
+ typedef BOOL(WINAPI *AdjustTokenPrivileges_t)(_In_ HANDLE TokenHandle, _In_ BOOL DisableAllPrivileges, _In_opt_ PTOKEN_PRIVILEGES NewState, _In_ DWORD BufferLength, _Out_opt_ PTOKEN_PRIVILEGES PreviousState, _Out_opt_ PDWORD ReturnLength);
+
+ typedef BOOL(WINAPI *PrefetchVirtualMemory_t)(_In_ HANDLE hProcess, _In_ ULONG_PTR NumberOfEntries, _In_ PWIN32_MEMORY_RANGE_ENTRY VirtualAddresses, _In_ ULONG Flags);
+
+ typedef BOOL(WINAPI *DiscardVirtualMemory_t)(_In_ PVOID VirtualAddress, _In_ SIZE_T Size);
+
+ typedef USHORT(WINAPI *RtlCaptureStackBackTrace_t)(_In_ ULONG FramesToSkip, _In_ ULONG FramesToCapture, _Out_ PVOID *BackTrace, _Out_opt_ PULONG BackTraceHash);
+
+ typedef BOOL(WINAPI *SymInitialize_t)(_In_ HANDLE hProcess, _In_opt_ PCTSTR UserSearchPath, _In_ BOOL fInvadeProcess);
+
+ typedef BOOL(WINAPI *SymGetLineFromAddr64_t)(_In_ HANDLE hProcess, _In_ DWORD64 dwAddr, _Out_ PDWORD pdwDisplacement, _Out_ PIMAGEHLP_LINE64 Line);
+
+ typedef BOOLEAN(WINAPI *RtlDosPathNameToNtPathName_U_t)(__in PCWSTR DosFileName, __out PUNICODE_STRING NtFileName, __out_opt PWSTR *FilePart, __out_opt PVOID RelativeName);
+
+
+ typedef struct _FILE_BASIC_INFORMATION
+ {
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ ULONG FileAttributes;
+ } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
+
+ typedef struct _FILE_STANDARD_INFORMATION
+ {
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+ } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION;
+
+ typedef struct _FILE_INTERNAL_INFORMATION
+ {
+ LARGE_INTEGER IndexNumber;
+ } FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION;
+
+ typedef struct _FILE_EA_INFORMATION
+ {
+ union {
+ ULONG EaSize;
+ ULONG ReparsePointTag;
+ };
+ } FILE_EA_INFORMATION, *PFILE_EA_INFORMATION;
+
+ typedef struct _FILE_ACCESS_INFORMATION
+ {
+ ACCESS_MASK AccessFlags;
+ } FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION;
+
+ typedef struct _FILE_POSITION_INFORMATION
+ {
+ LARGE_INTEGER CurrentByteOffset;
+ } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;
+
+ typedef struct _FILE_MODE_INFORMATION
+ {
+ ULONG Mode;
+ } FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION;
+
+ typedef struct _FILE_ALIGNMENT_INFORMATION
+ {
+ ULONG AlignmentRequirement;
+ } FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION;
+
+ typedef struct _FILE_NAME_INFORMATION
+ {
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+ } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+
+ typedef struct _FILE_RENAME_INFORMATION
+ {
+ BOOLEAN ReplaceIfExists;
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+ } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
+
+ typedef struct _FILE_LINK_INFORMATION
+ {
+ BOOLEAN ReplaceIfExists;
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+ } FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;
+
+ typedef struct _FILE_DISPOSITION_INFORMATION
+ {
+ BOOLEAN _DeleteFile;
+ } FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION;
+
+ typedef struct _FILE_ALL_INFORMATION
+ {
+ FILE_BASIC_INFORMATION BasicInformation;
+ FILE_STANDARD_INFORMATION StandardInformation;
+ FILE_INTERNAL_INFORMATION InternalInformation;
+ FILE_EA_INFORMATION EaInformation;
+ FILE_ACCESS_INFORMATION AccessInformation;
+ FILE_POSITION_INFORMATION PositionInformation;
+ FILE_MODE_INFORMATION ModeInformation;
+ FILE_ALIGNMENT_INFORMATION AlignmentInformation;
+ FILE_NAME_INFORMATION NameInformation;
+ } FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION;
+
+ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
+ {
+ ULONG FileSystemAttributes;
+ LONG MaximumComponentNameLength;
+ ULONG FileSystemNameLength;
+ WCHAR FileSystemName[1];
+ } FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
+
+ typedef struct _FILE_FS_FULL_SIZE_INFORMATION
+ {
+ LARGE_INTEGER TotalAllocationUnits;
+ LARGE_INTEGER CallerAvailableAllocationUnits;
+ LARGE_INTEGER ActualAvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+ } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
+
+ typedef struct _FILE_FS_OBJECTID_INFORMATION
+ {
+ UCHAR ObjectId[16];
+ UCHAR ExtendedInfo[48];
+ } FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION;
+
+ typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION
+ {
+ ULONG LogicalBytesPerSector;
+ ULONG PhysicalBytesPerSectorForAtomicity;
+ ULONG PhysicalBytesPerSectorForPerformance;
+ ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
+ ULONG Flags;
+ ULONG ByteOffsetForSectorAlignment;
+ ULONG ByteOffsetForPartitionAlignment;
+ } FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff540310(v=vs.85).aspx
+ typedef struct _FILE_ID_FULL_DIR_INFORMATION
+ {
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ union {
+ ULONG EaSize;
+ ULONG ReparsePointTag;
+ };
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+ } FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
+
+ // From https://msdn.microsoft.com/en-us/library/windows/hardware/ff540354(v=vs.85).aspx
+ typedef struct _FILE_REPARSE_POINT_INFORMATION
+ {
+ LARGE_INTEGER FileReference;
+ ULONG Tag;
+ } FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
+ typedef struct _REPARSE_DATA_BUFFER
+ {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct
+ {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct
+ {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct
+ {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+ } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+ static NtQueryObject_t NtQueryObject;
+ static NtQueryInformationFile_t NtQueryInformationFile;
+ static NtQueryVolumeInformationFile_t NtQueryVolumeInformationFile;
+ static NtOpenDirectoryObject_t NtOpenDirectoryObject;
+ static NtOpenFile_t NtOpenFile;
+ static NtCreateFile_t NtCreateFile;
+ static NtDeleteFile_t NtDeleteFile;
+ static NtClose_t NtClose;
+ static NtQueryDirectoryFile_t NtQueryDirectoryFile;
+ static NtSetInformationFile_t NtSetInformationFile;
+ static NtWaitForSingleObject_t NtWaitForSingleObject;
+ static NtWaitForMultipleObjects_t NtWaitForMultipleObjects;
+ static NtDelayExecution_t NtDelayExecution;
+ static NtLockFile_t NtLockFile;
+ static NtUnlockFile_t NtUnlockFile;
+ static NtCreateSection_t NtCreateSection;
+ static NtExtendSection_t NtExtendSection;
+ static NtMapViewOfSection_t NtMapViewOfSection;
+ static NtUnmapViewOfSection_t NtUnmapViewOfSection;
+ static NtFlushBuffersFileEx_t NtFlushBuffersFileEx;
+ static RtlGenRandom_t RtlGenRandom;
+ static OpenProcessToken_t OpenProcessToken;
+ static LookupPrivilegeValue_t LookupPrivilegeValue;
+ static AdjustTokenPrivileges_t AdjustTokenPrivileges;
+ static PrefetchVirtualMemory_t PrefetchVirtualMemory_;
+ static DiscardVirtualMemory_t DiscardVirtualMemory_;
+ static SymInitialize_t SymInitialize;
+ static SymGetLineFromAddr64_t SymGetLineFromAddr64;
+ static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace;
+ static RtlDosPathNameToNtPathName_U_t RtlDosPathNameToNtPathName_U;
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4706) // assignment within conditional
+#pragma warning(disable : 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail (hah!)
+#endif
+ static inline void doinit()
+ {
+ if(RtlDosPathNameToNtPathName_U)
+ return;
+ static stl11::mutex lock;
+ stl11::lock_guard<decltype(lock)> g(lock);
+ static HMODULE ntdllh = GetModuleHandleA("NTDLL.DLL");
+ static HMODULE kernel32 = GetModuleHandleA("KERNEL32.DLL");
+ if(!NtQueryObject)
+ if(!(NtQueryObject = (NtQueryObject_t) GetProcAddress(ntdllh, "NtQueryObject")))
+ abort();
+ if(!NtQueryInformationFile)
+ if(!(NtQueryInformationFile = (NtQueryInformationFile_t) GetProcAddress(ntdllh, "NtQueryInformationFile")))
+ abort();
+ if(!NtQueryVolumeInformationFile)
+ if(!(NtQueryVolumeInformationFile = (NtQueryVolumeInformationFile_t) GetProcAddress(ntdllh, "NtQueryVolumeInformationFile")))
+ abort();
+ if(!NtOpenDirectoryObject)
+ if(!(NtOpenDirectoryObject = (NtOpenDirectoryObject_t) GetProcAddress(ntdllh, "NtOpenDirectoryObject")))
+ abort();
+ if(!NtOpenFile)
+ if(!(NtOpenFile = (NtOpenFile_t) GetProcAddress(ntdllh, "NtOpenFile")))
+ abort();
+ if(!NtCreateFile)
+ if(!(NtCreateFile = (NtCreateFile_t) GetProcAddress(ntdllh, "NtCreateFile")))
+ abort();
+ if(!NtDeleteFile)
+ if(!(NtDeleteFile = (NtDeleteFile_t) GetProcAddress(ntdllh, "NtDeleteFile")))
+ abort();
+ if(!NtClose)
+ if(!(NtClose = (NtClose_t) GetProcAddress(ntdllh, "NtClose")))
+ abort();
+ if(!NtQueryDirectoryFile)
+ if(!(NtQueryDirectoryFile = (NtQueryDirectoryFile_t) GetProcAddress(ntdllh, "NtQueryDirectoryFile")))
+ abort();
+ if(!NtSetInformationFile)
+ if(!(NtSetInformationFile = (NtSetInformationFile_t) GetProcAddress(ntdllh, "NtSetInformationFile")))
+ abort();
+ if(!NtWaitForSingleObject)
+ if(!(NtWaitForSingleObject = (NtWaitForSingleObject_t) GetProcAddress(ntdllh, "NtWaitForSingleObject")))
+ abort();
+ if(!NtWaitForMultipleObjects)
+ if(!(NtWaitForMultipleObjects = (NtWaitForMultipleObjects_t) GetProcAddress(ntdllh, "NtWaitForMultipleObjects")))
+ abort();
+ if(!NtDelayExecution)
+ if(!(NtDelayExecution = (NtDelayExecution_t) GetProcAddress(ntdllh, "NtDelayExecution")))
+ abort();
+ if(!NtLockFile)
+ if(!(NtLockFile = (NtLockFile_t) GetProcAddress(ntdllh, "NtLockFile")))
+ abort();
+ if(!NtUnlockFile)
+ if(!(NtUnlockFile = (NtUnlockFile_t) GetProcAddress(ntdllh, "NtUnlockFile")))
+ abort();
+ if(!NtCreateSection)
+ if(!(NtCreateSection = (NtCreateSection_t) GetProcAddress(ntdllh, "NtCreateSection")))
+ abort();
+ if(!NtExtendSection)
+ if(!(NtExtendSection = (NtExtendSection_t) GetProcAddress(ntdllh, "NtExtendSection")))
+ abort();
+ if(!NtMapViewOfSection)
+ if(!(NtMapViewOfSection = (NtMapViewOfSection_t) GetProcAddress(ntdllh, "NtMapViewOfSection")))
+ abort();
+ if(!NtUnmapViewOfSection)
+ if(!(NtUnmapViewOfSection = (NtUnmapViewOfSection_t) GetProcAddress(ntdllh, "NtUnmapViewOfSection")))
+ abort();
+ if(!NtFlushBuffersFileEx)
+ if(!(NtFlushBuffersFileEx = (NtFlushBuffersFileEx_t) GetProcAddress(ntdllh, "NtFlushBuffersFileEx")))
+ abort();
+ HMODULE advapi32 = LoadLibraryA("ADVAPI32.DLL");
+ if(!RtlGenRandom)
+ if(!(RtlGenRandom = (RtlGenRandom_t) GetProcAddress(advapi32, "SystemFunction036")))
+ abort();
+ if(!OpenProcessToken)
+ if(!(OpenProcessToken = (OpenProcessToken_t) GetProcAddress(advapi32, "OpenProcessToken")))
+ abort();
+ if(!LookupPrivilegeValue)
+ if(!(LookupPrivilegeValue = (LookupPrivilegeValue_t) GetProcAddress(advapi32, "LookupPrivilegeValueW")))
+ abort();
+ if(!AdjustTokenPrivileges)
+ if(!(AdjustTokenPrivileges = (AdjustTokenPrivileges_t) GetProcAddress(advapi32, "AdjustTokenPrivileges")))
+ abort();
+ // Only provided on Windows 8 and above
+ if(!PrefetchVirtualMemory_)
+ PrefetchVirtualMemory_ = (PrefetchVirtualMemory_t) GetProcAddress(kernel32, "PrefetchVirtualMemory");
+ if(!DiscardVirtualMemory_)
+ DiscardVirtualMemory_ = (DiscardVirtualMemory_t) GetProcAddress(kernel32, "DiscardVirtualMemory");
+#ifdef BOOST_AFIO_OP_STACKBACKTRACEDEPTH
+ if(dbghelp)
+ {
+ HMODULE dbghelp = LoadLibraryA("DBGHELP.DLL");
+ if(!(SymInitialize = (SymInitialize_t) GetProcAddress(dbghelp, "SymInitializeW")))
+ abort();
+ if(!SymInitialize(GetCurrentProcess(), nullptr, true))
+ abort();
+ if(!(SymGetLineFromAddr64 = (SymGetLineFromAddr64_t) GetProcAddress(dbghelp, "SymGetLineFromAddrW64")))
+ abort();
+ }
+#endif
+ if(!RtlCaptureStackBackTrace)
+ if(!(RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_t) GetProcAddress(ntdllh, "RtlCaptureStackBackTrace")))
+ abort();
+
+ if(!RtlDosPathNameToNtPathName_U)
+ if(!(RtlDosPathNameToNtPathName_U = (RtlDosPathNameToNtPathName_U_t) GetProcAddress(ntdllh, "RtlDosPathNameToNtPathName_U")))
+ abort();
+ // MAKE SURE you update the early exit check at the top to whatever the last of these is!
+ }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ static inline void init()
+ {
+ static bool initialised = false;
+ if(!initialised)
+ {
+ doinit();
+ initialised = true;
+ }
+ }
+
+ static inline stl1z::filesystem::file_type to_st_type(ULONG FileAttributes, ULONG ReparsePointTag)
+ {
+#ifdef BOOST_AFIO_USE_LEGACY_FILESYSTEM_SEMANTICS
+ if(FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && (ReparsePointTag == IO_REPARSE_TAG_MOUNT_POINT || ReparsePointTag == IO_REPARSE_TAG_SYMLINK))
+ return filesystem::file_type::symlink_file;
+ // return filesystem::file_type::reparse_file;
+ else if(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ return filesystem::file_type::directory_file;
+ else
+ return filesystem::file_type::regular_file;
+#else
+ if(FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && (ReparsePointTag == IO_REPARSE_TAG_MOUNT_POINT || ReparsePointTag == IO_REPARSE_TAG_SYMLINK))
+ return stl1z::filesystem::file_type::symlink;
+ // return stl1z::filesystem::file_type::reparse_file;
+ else if(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ return stl1z::filesystem::file_type::directory;
+ else
+ return stl1z::filesystem::file_type::regular;
+#endif
+ }
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 6326) // comparison of constants
+#endif
+ static inline stl11::chrono::system_clock::time_point to_timepoint(LARGE_INTEGER time)
+ {
+ // For speed we make the big assumption that the STL's system_clock is based on the time_t epoch 1st Jan 1970.
+ static constexpr unsigned long long FILETIME_OFFSET_TO_1970 = ((27111902ULL << 32U) + 3577643008ULL);
+ // Need to have this self-adapt to the STL being used
+ static constexpr unsigned long long STL_TICKS_PER_SEC = (unsigned long long) stl11::chrono::system_clock::period::den / stl11::chrono::system_clock::period::num;
+ static constexpr unsigned long long multiplier = STL_TICKS_PER_SEC >= 10000000ULL ? STL_TICKS_PER_SEC / 10000000ULL : 1;
+ static constexpr unsigned long long divider = STL_TICKS_PER_SEC >= 10000000ULL ? 1 : 10000000ULL / STL_TICKS_PER_SEC;
+
+ unsigned long long ticks_since_1970 = (time.QuadPart - FILETIME_OFFSET_TO_1970); // In 100ns increments
+ stl11::chrono::system_clock::duration duration(ticks_since_1970 * multiplier / divider);
+ return stl11::chrono::system_clock::time_point(duration);
+ }
+ static inline LARGE_INTEGER from_timepoint(stl11::chrono::system_clock::time_point time)
+ {
+ // For speed we make the big assumption that the STL's system_clock is based on the time_t epoch 1st Jan 1970.
+ static constexpr unsigned long long FILETIME_OFFSET_TO_1970 = ((27111902ULL << 32U) + 3577643008ULL);
+ static const stl11::chrono::system_clock::time_point time_point_1970 = stl11::chrono::system_clock::from_time_t(0);
+
+ LARGE_INTEGER ret;
+ ret.QuadPart = FILETIME_OFFSET_TO_1970 + stl11::chrono::duration_cast<stl11::chrono::nanoseconds>(time - time_point_1970).count() / 100;
+ return ret;
+ }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// Adapted from http://www.cprogramming.com/snippets/source-code/convert-ntstatus-win32-error
+// Could use RtlNtStatusToDosError() instead
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 6387) // MSVC sanitiser warns on misuse of GetOverlappedResult
+#endif
+ static inline DWORD win32_error_from_nt_status(NTSTATUS ntstatus)
+ {
+ DWORD br;
+ OVERLAPPED o;
+
+ o.Internal = ntstatus;
+ o.InternalHigh = 0;
+ o.Offset = 0;
+ o.OffsetHigh = 0;
+ o.hEvent = 0;
+ GetOverlappedResult(NULL, &o, &br, FALSE);
+ return GetLastError();
+ }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+} // namespace
+
+// disable to prevent accidental usage
+template <class T> inline result<T> make_errored_result(NTSTATUS e, const char *extended = nullptr)
+{
+ (void) e;
+ (void) extended;
+ static_assert(!std::is_same<T, T>::value, "Use make_errored_result_nt<T>(NTSTATUS).");
+}
+template <class T> inline outcome<T> make_errored_outcome(NTSTATUS e, const char *extended = nullptr)
+{
+ (void) e;
+ (void) extended;
+ static_assert(!std::is_same<T, T>::value, "Use make_errored_outcome_nt<T>(NTSTATUS).");
+}
+template <class T> inline result<T> make_errored_result_nt(NTSTATUS e, const char *extended = nullptr)
+{
+ return make_errored_result<T>(windows_nt_kernel::win32_error_from_nt_status(e), extended);
+}
+template <class T> inline outcome<T> make_errored_outcome_nt(NTSTATUS e, const char *extended = nullptr)
+{
+ return make_errored_outcome<T>(windows_nt_kernel::win32_error_from_nt_status(e), extended);
+}
+
+#if 0
+static inline void fill_stat_t(stat_t &stat, BOOST_AFIO_POSIX_STAT_STRUCT s, metadata_flags wanted)
+{
+#ifndef _WIN32
+ if (!!(wanted&metadata_flags::dev)) { stat.st_dev = s.st_dev; }
+#endif
+ if (!!(wanted&metadata_flags::ino)) { stat.st_ino = s.st_ino; }
+ if (!!(wanted&metadata_flags::type)) { stat.st_type = to_st_type(s.st_mode); }
+#ifndef _WIN32
+ if (!!(wanted&metadata_flags::perms)) { stat.st_mode = s.st_perms; }
+#endif
+ if (!!(wanted&metadata_flags::nlink)) { stat.st_nlink = s.st_nlink; }
+#ifndef _WIN32
+ if (!!(wanted&metadata_flags::uid)) { stat.st_uid = s.st_uid; }
+ if (!!(wanted&metadata_flags::gid)) { stat.st_gid = s.st_gid; }
+ if (!!(wanted&metadata_flags::rdev)) { stat.st_rdev = s.st_rdev; }
+#endif
+ if (!!(wanted&metadata_flags::atim)) { stat.st_atim = chrono::system_clock::from_time_t(s.st_atime); }
+ if (!!(wanted&metadata_flags::mtim)) { stat.st_mtim = chrono::system_clock::from_time_t(s.st_mtime); }
+ if (!!(wanted&metadata_flags::birthtim)) { stat.st_birthtim = chrono::system_clock::from_time_t(s.st_ctime); }
+ if (!!(wanted&metadata_flags::size)) { stat.st_size = s.st_size; }
+}
+#endif
+
+// Utility routines for implementing deadline sleeps on Windows which only provides interval sleeps
+#if 0 // This is the win32 edition. The NT kernel edition is much cleaner and lower overhead.
+struct win_handle_deleter
+{
+ void operator()(HANDLE h) { CloseHandle(h); }
+};
+static inline std::unique_ptr<void, win_handle_deleter> create_waitable_timer()
+{
+ HANDLE ret = CreateWaitableTimer(nullptr, true, nullptr);
+ if(INVALID_HANDLE_VALUE == ret)
+ throw std::system_error(GetLastError(), std::system_category());
+ return std::unique_ptr<void, win_handle_deleter>(ret);
+}
+static inline HANDLE get_thread_local_waitable_timer()
+{
+ static thread_local auto self = create_waitable_timer();
+ return self.get();
+}
+
+/*! Defines a number of variables into its scope:
+- began_steady: Set to the steady clock at the beginning of a sleep
+- end_utc: Set to the system clock when the sleep must end
+- sleep_interval: Set to the number of steady milliseconds until the sleep must end
+- sleep_object: Set to a primed deadline timer HANDLE which will signal when the system clock reaches the deadline
+*/
+#define BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
+ stl11::chrono::steady_clock::time_point began_steady; \
+ \
+stl11::chrono::system_clock::time_point end_utc; \
+ \
+if(d) \
+ \
+{ \
+ if((d).steady) \
+ began_steady = stl11::chrono::steady_clock::now(); \
+ else \
+ end_utc = (d).to_time_point(); \
+ \
+} \
+ \
+DWORD sleep_interval = INFINITE; \
+ \
+HANDLE sleep_object = nullptr;
+
+#define BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
+ \
+if(d) \
+ \
+{ \
+ if((d).steady) \
+ { \
+ stl11::chrono::milliseconds ms; \
+ ms = stl11::chrono::duration_cast<stl11::chrono::milliseconds>((began_steady + stl11::chrono::nanoseconds(d.nsecs)) - stl11::chrono::steady_clock::now()); \
+ if(ms.count() < 0) \
+ sleep_interval = 0; \
+ else \
+ sleep_interval = (DWORD) ms.count(); \
+ } \
+ else \
+ { \
+ sleep_object = get_thread_local_waitable_timer(); \
+ LARGE_INTEGER due_time = windows_nt_kernel::from_timepoint(end_utc); \
+ if(!SetWaitableTimer(sleep_object, &due_time, 0, nullptr, nullptr, false)) \
+ throw std::system_error(GetLastError(), std::system_category()); \
+ } \
+ \
+}
+
+#define BOOST_AFIO_WIN_DEADLINE_TO_TIMEOUT(type, d) \
+ \
+if(d) \
+ \
+{ \
+ if((d).steady) \
+ { \
+ if(stl11::chrono::steady_clock::now() >= (began_steady + stl11::chrono::nanoseconds((d).nsecs))) \
+ return make_errored_result<type>(stl11::errc::timed_out); \
+ } \
+ else \
+ { \
+ if(stl11::chrono::system_clock::now() >= end_utc) \
+ return make_errored_result<type>(stl11::errc::timed_out); \
+ } \
+ \
+}
+#else
+/*! Defines a number of variables into its scope:
+- began_steady: Set to the steady clock at the beginning of a sleep
+- end_utc: Set to the system clock when the sleep must end
+- sleep_interval: Set to the number of steady milliseconds until the sleep must end
+- sleep_object: Set to a primed deadline timer HANDLE which will signal when the system clock reaches the deadline
+*/
+#define BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d) \
+ stl11::chrono::steady_clock::time_point began_steady; \
+ \
+stl11::chrono::system_clock::time_point end_utc; \
+ \
+alignas(8) LARGE_INTEGER _timeout; \
+ \
+memset(&_timeout, 0, sizeof(_timeout)); \
+ \
+LARGE_INTEGER *timeout = nullptr; \
+ \
+if(d) \
+ \
+{ \
+ if((d).steady) \
+ began_steady = stl11::chrono::steady_clock::now(); \
+ else \
+ { \
+ end_utc = (d).to_time_point(); \
+ _timeout = windows_nt_kernel::from_timepoint(end_utc); \
+ } \
+ timeout = &_timeout; \
+ \
+}
+
+#define BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d) \
+ if((d) && (d).steady) \
+ { \
+ stl11::chrono::nanoseconds ns; \
+ ns = stl11::chrono::duration_cast<stl11::chrono::nanoseconds>((began_steady + stl11::chrono::nanoseconds(d.nsecs)) - stl11::chrono::steady_clock::now()); \
+ if(ns.count() < 0) \
+ _timeout.QuadPart = 0; \
+ else \
+ _timeout.QuadPart = ns.count() / -100; \
+ }
+
+#define BOOST_AFIO_WIN_DEADLINE_TO_PARTIAL_DEADLINE(nd, d) \
+ if(d) \
+ { \
+ if((d).steady) \
+ { \
+ stl11::chrono::nanoseconds ns = stl11::chrono::duration_cast<stl11::chrono::nanoseconds>((began_steady + stl11::chrono::nanoseconds((d).nsecs)) - stl11::chrono::steady_clock::now()); \
+ if(ns.count() < 0) \
+ (nd).nsecs = 0; \
+ else \
+ (nd).nsecs = ns.count(); \
+ } \
+ else \
+ (nd) = (d); \
+ }
+
+#define BOOST_AFIO_WIN_DEADLINE_TO_TIMEOUT(type, d) \
+ \
+if(d) \
+ \
+{ \
+ if((d).steady) \
+ { \
+ if(stl11::chrono::steady_clock::now() >= (began_steady + stl11::chrono::nanoseconds((d).nsecs))) \
+ return make_errored_result<type>(stl11::errc::timed_out); \
+ } \
+ else \
+ { \
+ if(stl11::chrono::system_clock::now() >= end_utc) \
+ return make_errored_result<type>(stl11::errc::timed_out); \
+ } \
+ \
+}
+#endif
+
+// Initialise an IO_STATUS_BLOCK for later wait operations
+static inline windows_nt_kernel::IO_STATUS_BLOCK make_iostatus() noexcept
+{
+ windows_nt_kernel::IO_STATUS_BLOCK isb;
+ memset(&isb, 0, sizeof(isb));
+ isb.Status = -1;
+ return isb;
+}
+
+// Wait for an overlapped handle to complete a specific operation
+static inline NTSTATUS ntwait(HANDLE h, windows_nt_kernel::IO_STATUS_BLOCK &isb, const deadline &d) noexcept
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ do // needs to be a do, not while in order to flip auto reset event objects etc.
+ {
+ BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
+ // Pump alerts and APCs
+ NTSTATUS ntstat = NtWaitForSingleObject(h, true, timeout);
+ if(STATUS_TIMEOUT == ntstat)
+ {
+ DWORD expected = (DWORD) -1;
+ // Have to be very careful here, atomically swap timed out for the -1 only
+ InterlockedCompareExchange(&isb.Status, ntstat, expected);
+ // If it's no longer -1 or the i/o completes, that's fine.
+ return isb.Status;
+ }
+ } while(isb.Status == -1);
+ return isb.Status;
+}
+static inline NTSTATUS ntwait(HANDLE h, OVERLAPPED &ol, const deadline &d) noexcept
+{
+ return ntwait(h, reinterpret_cast<windows_nt_kernel::IO_STATUS_BLOCK &>(ol), d);
+}
+
+// Sleep the thread until some deadline
+static inline bool ntsleep(const deadline &d, bool return_on_alert = false) noexcept
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
+ for(;;)
+ {
+ BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_LOOP(d);
+ // Pump alerts and APCs
+ NTSTATUS ntstat = NtDelayExecution(true, timeout);
+ (void) ntstat;
+ if((d).steady)
+ {
+ if(stl11::chrono::steady_clock::now() >= (began_steady + stl11::chrono::nanoseconds((d).nsecs)))
+ return false;
+ }
+ else
+ {
+ if(stl11::chrono::system_clock::now() >= end_utc)
+ return false;
+ }
+ if(return_on_alert)
+ return true;
+ }
+}
+
+
+// Utility routines for building an ACCESS_MASK from a handle::mode
+static inline result<ACCESS_MASK> access_mask_from_handle_mode(native_handle_type &nativeh, handle::mode _mode)
+{
+ ACCESS_MASK access = SYNCHRONIZE;
+ switch(_mode)
+ {
+ case handle::mode::unchanged:
+ return make_errored_result<ACCESS_MASK>(stl11::errc::invalid_argument);
+ case handle::mode::none:
+ break;
+ case handle::mode::attr_read:
+ access |= FILE_READ_ATTRIBUTES;
+ break;
+ case handle::mode::attr_write:
+ access |= FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
+ break;
+ case handle::mode::read:
+ access |= GENERIC_READ;
+ nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable;
+ break;
+ case handle::mode::write:
+ access |= GENERIC_WRITE | GENERIC_READ;
+ nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable | native_handle_type::disposition::writable;
+ break;
+ case handle::mode::append:
+ access |= FILE_APPEND_DATA;
+ nativeh.behaviour |= native_handle_type::disposition::writable | native_handle_type::disposition::append_only;
+ break;
+ }
+ return access;
+}
+
+static inline result<DWORD> attributes_from_handle_caching_and_flags(native_handle_type &nativeh, handle::caching _caching, handle::flag flags)
+{
+ DWORD attribs = 0;
+ if(flags & handle::flag::overlapped)
+ {
+ attribs |= FILE_FLAG_OVERLAPPED;
+ nativeh.behaviour |= native_handle_type::disposition::overlapped;
+ }
+ switch(_caching)
+ {
+ case handle::caching::unchanged:
+ return make_errored_result<DWORD>(stl11::errc::invalid_argument);
+ case handle::caching::none:
+ attribs |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
+ nativeh.behaviour |= native_handle_type::disposition::aligned_io;
+ break;
+ case handle::caching::only_metadata:
+ attribs |= FILE_FLAG_NO_BUFFERING;
+ nativeh.behaviour |= native_handle_type::disposition::aligned_io;
+ break;
+ case handle::caching::reads:
+ case handle::caching::reads_and_metadata:
+ attribs |= FILE_FLAG_WRITE_THROUGH;
+ break;
+ case handle::caching::all:
+ case handle::caching::safety_fsyncs:
+ break;
+ case handle::caching::temporary:
+ attribs |= FILE_ATTRIBUTE_TEMPORARY;
+ break;
+ }
+ if(flags & handle::flag::unlink_on_close)
+ attribs |= FILE_FLAG_DELETE_ON_CLOSE;
+ return attribs;
+}
+
+/* Our own custom CreateFileW() implementation.
+
+The Win32 CreateFileW() implementation is unfortunately slow. It also, very annoyingly,
+maps STATUS_DELETE_PENDING onto ERROR_ACCESS_DENIED instead of to ERROR_DELETE_PENDING
+which means our file open routines return EACCES, which is useless to us for detecting
+when we are trying to open files being deleted. We therefore reimplement CreateFileW()
+with a non-broken version.
+
+This edition does pretty much the same as the Win32 edition, minus support for file
+templates and lpFileName being anything but a file path.
+*/
+static inline HANDLE CreateFileW_(_In_ LPCTSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile)
+{
+ windows_nt_kernel::init();
+ using namespace windows_nt_kernel;
+ if(!lpFileName || !lpFileName[0])
+ {
+ SetLastError(ERROR_PATH_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ }
+ if(hTemplateFile || !lstrcmpW(lpFileName, L"CONIN$") || !lstrcmpW(lpFileName, L"CONOUT$"))
+ {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return INVALID_HANDLE_VALUE;
+ }
+ switch(dwCreationDisposition)
+ {
+ case CREATE_NEW:
+ dwCreationDisposition = FILE_CREATE;
+ break;
+ case CREATE_ALWAYS:
+ dwCreationDisposition = FILE_OVERWRITE_IF;
+ break;
+ case OPEN_EXISTING:
+ dwCreationDisposition = FILE_OPEN;
+ break;
+ case OPEN_ALWAYS:
+ dwCreationDisposition = FILE_OPEN_IF;
+ break;
+ case TRUNCATE_EXISTING:
+ dwCreationDisposition = FILE_OVERWRITE;
+ break;
+ default:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ ULONG flags = 0;
+ if(!(dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
+ flags |= FILE_SYNCHRONOUS_IO_NONALERT;
+ if(dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
+ flags |= FILE_WRITE_THROUGH;
+ if(dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
+ flags |= FILE_NO_INTERMEDIATE_BUFFERING;
+ if(dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
+ flags |= FILE_RANDOM_ACCESS;
+ if(dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
+ flags |= FILE_SEQUENTIAL_ONLY;
+ if(dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
+ {
+ flags |= FILE_DELETE_ON_CLOSE;
+ dwDesiredAccess |= DELETE;
+ }
+ if(dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
+ {
+ if(dwDesiredAccess & GENERIC_ALL)
+ flags |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE;
+ else
+ {
+ if(dwDesiredAccess & GENERIC_READ)
+ flags |= FILE_OPEN_FOR_BACKUP_INTENT;
+ if(dwDesiredAccess & GENERIC_WRITE)
+ flags |= FILE_OPEN_REMOTE_INSTANCE;
+ }
+ }
+ else
+ flags |= FILE_NON_DIRECTORY_FILE;
+ if(dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
+ flags |= FILE_OPEN_REPARSE_POINT;
+ if(dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
+ flags |= FILE_OPEN_NO_RECALL;
+
+ UNICODE_STRING NtPath;
+ if(!RtlDosPathNameToNtPathName_U(lpFileName, &NtPath, NULL, NULL))
+ {
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return INVALID_HANDLE_VALUE;
+ }
+ auto unntpath = undoer([&NtPath] {
+ if(!HeapFree(GetProcessHeap(), 0, NtPath.Buffer))
+ abort();
+ });
+
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ InitializeObjectAttributes(&ObjectAttributes, &NtPath, 0, NULL, NULL);
+ if(lpSecurityAttributes)
+ {
+ if(lpSecurityAttributes->bInheritHandle)
+ ObjectAttributes.Attributes |= OBJ_INHERIT;
+ ObjectAttributes.SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
+ }
+ if(!(dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS))
+ ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
+
+ HANDLE ret = INVALID_HANDLE_VALUE;
+ IO_STATUS_BLOCK isb = make_iostatus();
+ dwFlagsAndAttributes &= ~0xfff80000;
+ NTSTATUS ntstat = NtCreateFile(&ret, dwDesiredAccess, &ObjectAttributes, &isb, NULL, dwFlagsAndAttributes, dwShareMode, dwCreationDisposition, flags, NULL, 0);
+ if(STATUS_SUCCESS == ntstat)
+ return ret;
+
+ win32_error_from_nt_status(ntstat);
+ if(STATUS_DELETE_PENDING == ntstat)
+ {
+ SetLastError(ERROR_DELETE_PENDING);
+ }
+ return INVALID_HANDLE_VALUE;
+}
+
+BOOST_AFIO_V2_NAMESPACE_END
+
+#endif