AuroraRuntime/Source/AuProcAddresses.NT.cpp

1037 lines
40 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcAddresses.NT.cpp
Date: 2023-2-16
Author: Reece
***/
#include <AuroraEnvironment.h>
#if defined(AURORA_PLATFORM_WIN32)
#define _WIN32_WINNT 0x0602
#endif
#include <RuntimeInternal.hpp>
#include "Source/Threading/Primitives/AuConditionMutex.NT.hpp"
#define AURORA_HAS_LOAD_PGKD
#define AURORA_HAS_GET_PROC_NONWIN32
#if !defined(AURORA_RUNITIME_NO_PROFILE_SYMBOL)
extern "C"
{
// As much as I despise third-party drivers matching module names and pattern matching,
// we may as well provide some hint for:
// * Windows emulators
// * Future first party win32 compatibility layers
// * Drivers checking for the vintage
// * Non-standard PE linkers (Aurora::AddBlockedDLL(...) is valid)
AUKN_SYM int NT_APPLICATION_COMPAT_AURORA_RUNTIME_ALPHA;
AUKN_SYM int NT_APPLICATION_COMPAT_AURORA_RUNTIME;
}
#endif
namespace Aurora::Memory
{
AuUInt32 RoundPageUp(AuUInt32 value);
}
namespace Aurora
{
static bool gShouldResPathDoNothing {};
#if !defined(AURORA_PLATFORM_WIN32)
HMODULE UWPLibraryW(LPCWSTR lpLibFileName);
FARPROC UWPProcAddress(HMODULE hModule,
LPCSTR lpProcName);
HANDLE __stdcall UWPCreateFileMappingA(HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCSTR lpName);
HANDLE __stdcall UWPOpenFileMappingA(DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCSTR lpName);
LPVOID __stdcall UWPMapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap);
#endif
#if !defined(AURORA_DLL_BLACKLIST)
static AuUInt32 gBlockedDLLTable[128] {};
#else
static AuUInt32 gBlockedDLLTable[128] { AURORA_DLL_BLACKLIST };
#endif
AUKN_SYM bool AddBlockedDLL(const char *pString)
{
if (!pString)
{
return false;
}
auto uHash = AuFnv1a32Runtime(pString, strlen(pString));
for (AU_ITERATE_N(i, AuArraySize(gBlockedDLLTable)))
{
if (gBlockedDLLTable[i])
{
continue;
}
gBlockedDLLTable[i] = uHash;
return true;
}
return false;
}
static bool IsBlocked(const char *pString)
{
auto uHash = AuFnv1a32Runtime(pString, strlen(pString));
for (AU_ITERATE_N(i, AuArraySize(gBlockedDLLTable)))
{
auto uCurrent = gBlockedDLLTable[i];
if (uCurrent == uHash)
{
return true;
}
else if (uCurrent == 0)
{
return false;
}
}
return false;
}
void InitNTAddressesForClock()
{
#if defined(AURORA_PLATFORM_WIN32)
// We just need a partial AuSwInfo pass to work in order to setup the clocks at TLS callback-time
// Why? rng isnt ready either. We need the fallback clock to work.
pLoadLibraryW = LoadLibraryW;
pGetProcAddress = GetProcAddress;
#define ADD_LOAD_LIB(name) \
HMODULE h ## name {}; \
h ## name = GetModuleHandleW(k## name ## DllName); \
if (!h ## name) \
{ \
h ## name = pLoadLibraryW(k## name ## DllName); \
} \
#define ADD_GET_PROC(name, proc) \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(pGetProcAddress(h ## name, #proc)); \
} \
ADD_LOAD_LIB(Kernel32);
#if 0
ADD_LOAD_LIB(AdvancedApi);
#endif
ADD_GET_PROC(Kernel32, VerifyVersionInfoW)
ADD_GET_PROC(Kernel32, VerSetConditionMask)
ADD_GET_PROC(Kernel32, QueryPerformanceCounter)
ADD_GET_PROC(Kernel32, QueryPerformanceFrequency)
#if 0
ADD_GET_PROC(AdvancedApi, RegSetValueExW)
ADD_GET_PROC(AdvancedApi, RegCloseKey)
ADD_GET_PROC(AdvancedApi, RegOpenKeyExW)
ADD_GET_PROC(AdvancedApi, RegQueryValueExW)
#endif
#undef ADD_GET_PROC
#undef ADD_LOAD_LIB
#else
InitNTAddresses();
#endif
}
void InitNTAddresses()
{
#if defined(AURORA_PLATFORM_WIN32)
pLoadLibraryW = LoadLibraryW;
pGetProcAddress = GetProcAddress;
#define ADD_LOAD_LIB(name) \
\
HMODULE h ## name {}; \
if (!IsBlocked(#name)) \
{ \
h ## name = GetModuleHandleW(k## name ## DllName); \
if (!h ## name) \
{ \
h ## name = pLoadLibraryW(k## name ## DllName); \
} \
}
ADD_LOAD_LIB(Kernel32);
ADD_LOAD_LIB(Nt);
ADD_LOAD_LIB(KernelBase);
ADD_LOAD_LIB(Sync);
ADD_LOAD_LIB(WS2);
ADD_LOAD_LIB(AdvancedApi);
ADD_LOAD_LIB(BCrypt);
ADD_LOAD_LIB(Theme);
ADD_LOAD_LIB(Shell);
ADD_LOAD_LIB(PSAPILegacy);
ADD_LOAD_LIB(DbgHelper);
ADD_LOAD_LIB(WinTrust);
ADD_LOAD_LIB(IPHelper);
ADD_LOAD_LIB(COM);
ADD_LOAD_LIB(User32);
ADD_LOAD_LIB(SetupAPI);
ADD_LOAD_LIB(Router);
ADD_LOAD_LIB(CredUI);
#define ADD_GET_PROC(name, proc) \
if (!IsBlocked(#proc)) \
{ \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(pGetProcAddress(h ## name, #proc)); \
} \
}
#define ADD_GET_PROC_BI(name, name2, proc) \
if (!IsBlocked(#proc)) \
{ \
p ## proc = nullptr; \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(pGetProcAddress(h ## name, #proc)); \
} \
if (!p ## proc) \
{ \
if (h ## name2) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(pGetProcAddress(h ## name2, #proc));\
} \
} \
}
#define ADD_GET_PROC_BI2(name, name2, proc, proc2) \
if (!IsBlocked(#proc)) \
{ \
p ## proc2 = nullptr; \
if (h ## name) \
{ \
p ## proc2 = AuReinterpretCast<decltype(p ## proc2)>(pGetProcAddress(h ## name, #proc)); \
} \
if (!p ## proc2) \
{ \
if (h ## name2) \
{ \
p ## proc2 = AuReinterpretCast<decltype(p ## proc2)>(pGetProcAddress(h ## name2, #proc2)); \
} \
} \
}
#define ADD_GET_PROC_INTERNAL_MAP(name, proc, symbol) \
if (!IsBlocked(#proc)) \
{ \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(pGetProcAddress(h ## name, #symbol)); \
} \
}
if (pRtlGetVersion)
{
return;
}
ADD_GET_PROC(Nt, RtlGetVersion)
ADD_GET_PROC(Nt, NtDelayExecution)
ADD_GET_PROC(Nt, NtWaitForKeyedEvent)
ADD_GET_PROC(Nt, NtReleaseKeyedEvent)
ADD_GET_PROC(Nt, NtOpenKeyedEvent)
ADD_GET_PROC(Nt, NtCreateKeyedEvent)
ADD_GET_PROC(Nt, RtlWaitOnAddress)
ADD_GET_PROC(Nt, RtlWakeByAddressAll)
ADD_GET_PROC(Nt, RtlWakeAddressSingle)
ADD_GET_PROC(Nt, ZwSetTimerResolution)
ADD_GET_PROC(Nt, NtQueryInformationProcess)
ADD_GET_PROC(Nt, NtNotifyChangeDirectoryFile)
ADD_GET_PROC(Nt, NtTerminateProcess)
ADD_GET_PROC(Nt, NtQuerySymbolicLinkObject)
ADD_GET_PROC(Nt, NtOpenSymbolicLinkObject)
ADD_GET_PROC(Nt, NtWaitForMultipleObjects)
ADD_GET_PROC(Nt, NtQuerySystemInformation)
ADD_GET_PROC_BI(Kernel32, KernelBase, VirtualAlloc2)
ADD_GET_PROC_BI(Kernel32, KernelBase, MapViewOfFile)
ADD_GET_PROC_BI(Kernel32, KernelBase, MapViewOfFile3)
ADD_GET_PROC_BI(Kernel32, KernelBase, UnmapViewOfFile2)
ADD_GET_PROC_BI(Kernel32, KernelBase, CreateFileW)
ADD_GET_PROC_BI(Kernel32, KernelBase, CreateFile2W)
ADD_GET_PROC_BI(Kernel32, KernelBase, GetTempPathW)
ADD_GET_PROC_BI(Kernel32, KernelBase, CreateFileMappingA)
ADD_GET_PROC_BI(Kernel32, KernelBase, OpenFileMappingA)
ADD_GET_PROC(Kernel32, GetSystemCpuSetInformation)
ADD_GET_PROC(Kernel32, GetLogicalProcessorInformation)
ADD_GET_PROC(Kernel32, SetThreadDescription)
ADD_GET_PROC(Kernel32, SetThreadInformation)
ADD_GET_PROC(Kernel32, SetThreadSelectedCpuSets)
ADD_GET_PROC(Kernel32, PrefetchVirtualMemory)
ADD_GET_PROC(Kernel32, SetThreadGroupAffinity)
ADD_GET_PROC(Kernel32, FindFirstStreamW)
ADD_GET_PROC(Kernel32, FindNextStreamW)
ADD_GET_PROC(Kernel32, FindClose)
ADD_GET_PROC(Kernel32, CancelIoEx)
ADD_GET_PROC(Kernel32, CancelSynchronousIo)
ADD_GET_PROC(Kernel32, SetFileInformationByHandle)
ADD_GET_PROC(Kernel32, GetLocaleInfoEx)
ADD_GET_PROC(Kernel32, LCIDToLocaleName)
ADD_GET_PROC(Kernel32, GetLocaleInfoW)
ADD_GET_PROC(Kernel32, GetThreadId)
ADD_GET_PROC(Kernel32, VerifyVersionInfoW)
ADD_GET_PROC(Kernel32, VerSetConditionMask)
ADD_GET_PROC(Kernel32, QueryPerformanceCounter)
ADD_GET_PROC(Kernel32, QueryPerformanceFrequency)
ADD_GET_PROC(Kernel32, RemoveDllDirectory)
ADD_GET_PROC(Kernel32, AddDllDirectory)
ADD_GET_PROC(Kernel32, SetProcessInformation)
ADD_GET_PROC(Kernel32, GetNamedPipeClientProcessId)
ADD_GET_PROC(Kernel32, Module32FirstW)
ADD_GET_PROC(Kernel32, Module32NextW)
ADD_GET_PROC(Kernel32, CreateJobObjectW)
ADD_GET_PROC(Kernel32, GetConsoleScreenBufferInfo)
ADD_GET_PROC(Kernel32, SetConsoleScreenBufferSize)
ADD_GET_PROC(Kernel32, SetConsoleWindowInfo)
ADD_GET_PROC(Kernel32, CreateConsoleScreenBuffer)
ADD_GET_PROC(Kernel32, SetConsoleCursorPosition)
ADD_GET_PROC(Kernel32, FillConsoleOutputCharacterW)
ADD_GET_PROC(Kernel32, FillConsoleOutputAttribute)
ADD_GET_PROC(Kernel32, SetConsoleTextAttribute)
ADD_GET_PROC(Kernel32, SetConsoleActiveScreenBuffer)
ADD_GET_PROC(Kernel32, ScrollConsoleScreenBufferW)
ADD_GET_PROC(Kernel32, WriteConsoleInputW)
ADD_GET_PROC(Kernel32, WriteConsoleW)
ADD_GET_PROC(Kernel32, ReadConsoleInputW)
ADD_GET_PROC(Kernel32, GetNumberOfConsoleInputEvents)
ADD_GET_PROC_BI2(Kernel32, PSAPILegacy, K32GetProcessMemoryInfo, GetProcessMemoryInfo)
ADD_GET_PROC(Sync, WaitOnAddress)
ADD_GET_PROC(Sync, WakeByAddressSingle)
ADD_GET_PROC(Sync, WakeByAddressAll)
ADD_GET_PROC(DbgHelper, UnDecorateSymbolName)
ADD_GET_PROC(DbgHelper, MiniDumpWriteDump)
ADD_GET_PROC(DbgHelper, SymInitialize)
ADD_GET_PROC(DbgHelper, SymGetModuleBase64)
ADD_GET_PROC(DbgHelper, SymGetLineFromAddr64)
ADD_GET_PROC(DbgHelper, SymFunctionTableAccess64)
ADD_GET_PROC(DbgHelper, StackWalk64)
ADD_GET_PROC(WS2, GetAddrInfoExW)
ADD_GET_PROC(WS2, GetAddrInfoExCancel)
ADD_GET_PROC(WS2, FreeAddrInfoExW)
ADD_GET_PROC(WS2, getaddrinfo)
ADD_GET_PROC(WS2, freeaddrinfo)
ADD_GET_PROC(WS2, listen)
ADD_GET_PROC(WS2, bind)
ADD_GET_PROC(WS2, closesocket)
ADD_GET_PROC(WS2, shutdown)
ADD_GET_PROC(WS2, getpeername)
ADD_GET_PROC(WS2, getsockname)
ADD_GET_PROC(WS2, ioctlsocket)
ADD_GET_PROC(WS2, setsockopt)
ADD_GET_PROC(WS2, WSAStartup)
ADD_GET_PROC(WS2, WSAIoctl)
ADD_GET_PROC(WS2, WSAGetLastError)
ADD_GET_PROC(WS2, WSASocketW)
ADD_GET_PROC(WS2, WSARecvFrom)
ADD_GET_PROC(WS2, WSARecv)
ADD_GET_PROC(WS2, WSASendTo)
ADD_GET_PROC(WS2, WSASend)
ADD_GET_PROC(WS2, WSAStringToAddressA)
ADD_GET_PROC(WinTrust, WinVerifyTrust)
ADD_GET_PROC(IPHelper, GetAdaptersAddresses)
ADD_GET_PROC(IPHelper, GetAdaptersInfo)
ADD_GET_PROC(AdvancedApi, CryptAcquireContextW)
ADD_GET_PROC(AdvancedApi, CryptReleaseContext)
ADD_GET_PROC(AdvancedApi, CryptGenRandom)
ADD_GET_PROC(AdvancedApi, RegSetValueExW)
ADD_GET_PROC(AdvancedApi, RegCloseKey)
ADD_GET_PROC(AdvancedApi, RegOpenKeyExW)
ADD_GET_PROC(AdvancedApi, RegQueryValueExW)
ADD_GET_PROC(AdvancedApi, DeregisterEventSource)
ADD_GET_PROC(AdvancedApi, RegisterEventSourceW)
ADD_GET_PROC(AdvancedApi, ReportEventW)
ADD_GET_PROC(AdvancedApi, SetEntriesInAclA)
ADD_GET_PROC(AdvancedApi, AllocateAndInitializeSid)
ADD_GET_PROC(AdvancedApi, SetNamedSecurityInfoW)
ADD_GET_PROC(AdvancedApi, FreeSid)
// privilege escalation
ADD_GET_PROC(AdvancedApi, CreateProcessWithLogonW);
ADD_GET_PROC(AdvancedApi, CreateProcessAsUserW);
ADD_GET_PROC(AdvancedApi, AdjustTokenPrivileges);
ADD_GET_PROC(AdvancedApi, RevertToSelf);
ADD_GET_PROC(AdvancedApi, SetTokenInformation);
ADD_GET_PROC(AdvancedApi, GetSidSubAuthorityCount);
ADD_GET_PROC(AdvancedApi, GetSidSubAuthority);
ADD_GET_PROC(AdvancedApi, LogonUserW);
ADD_GET_PROC(AdvancedApi, OpenProcessToken);
ADD_GET_PROC(AdvancedApi, SetThreadToken);
ADD_GET_PROC(AdvancedApi, SetSecurityInfo);
ADD_GET_PROC(AdvancedApi, GetUserNameW);
ADD_GET_PROC(AdvancedApi, DuplicateTokenEx);
ADD_GET_PROC(AdvancedApi, LookupAccountSidW);
ADD_GET_PROC(AdvancedApi, GetTokenInformation);
ADD_GET_PROC(AdvancedApi, SetSecurityDescriptorDacl);
ADD_GET_PROC(AdvancedApi, InitializeSecurityDescriptor);
ADD_GET_PROC(AdvancedApi, LookupAccountNameW);
ADD_GET_PROC(AdvancedApi, LookupPrivilegeValueA);
ADD_GET_PROC(AdvancedApi, LsaOpenPolicy);
ADD_GET_PROC(AdvancedApi, LsaClose);
ADD_GET_PROC(AdvancedApi, LsaAddAccountRights);
ADD_GET_PROC_INTERNAL_MAP(AdvancedApi, RtlGenRandom, SystemFunction036)
ADD_GET_PROC(BCrypt, BCryptGenRandom)
ADD_GET_PROC(Theme, SetWindowTheme)
ADD_GET_PROC(COM, CoInitializeEx)
ADD_GET_PROC(COM, CoUninitialize)
ADD_GET_PROC(COM, CoTaskMemFree)
ADD_GET_PROC(Shell, SHGetKnownFolderPath)
ADD_GET_PROC(Shell, SHGetFolderPathA)
ADD_GET_PROC(Shell, CommandLineToArgvW)
ADD_GET_PROC(Shell, ShellExecuteW)
ADD_GET_PROC(User32, GetClipboardData);
ADD_GET_PROC(User32, MapVirtualKeyA);
ADD_GET_PROC(User32, CloseClipboard);
ADD_GET_PROC(User32, GetWindowThreadProcessId);
ADD_GET_PROC(User32, SendMessageA);
ADD_GET_PROC(User32, EnumThreadWindows);
ADD_GET_PROC(User32, DispatchMessageW);
ADD_GET_PROC(User32, TranslateMessage);
ADD_GET_PROC(User32, MsgWaitForMultipleObjectsEx);
ADD_GET_PROC(User32, MsgWaitForMultipleObjects);
ADD_GET_PROC(User32, PeekMessageW);
ADD_GET_PROC(User32, SetPropW);
ADD_GET_PROC(User32, OpenClipboard);
ADD_GET_PROC(SetupAPI, SetupDiEnumDeviceInterfaces);
ADD_GET_PROC(SetupAPI, SetupDiDestroyDeviceInfoList);
ADD_GET_PROC(SetupAPI, SetupDiGetClassDevsW);
ADD_GET_PROC(SetupAPI, SetupDiGetDeviceRegistryPropertyA);
ADD_GET_PROC(SetupAPI, SetupDiGetDeviceInterfaceDetailW);
ADD_GET_PROC(Router, WNetCloseEnum);
ADD_GET_PROC(Router, WNetEnumResourceW);
ADD_GET_PROC(Router, WNetOpenEnumW);
ADD_GET_PROC(Router, WNetGetUniversalNameW);
ADD_GET_PROC(CredUI, CredUIPromptForWindowsCredentialsW);
ADD_GET_PROC(CredUI, CredUnPackAuthenticationBufferW);
if (pNtCreateKeyedEvent &&
Threading::Primitives::gKeyedEventHandle == INVALID_HANDLE_VALUE)
{
if (!gUseNativeWaitCondvar)
{
SysAssert(pNtCreateKeyedEvent);
pNtCreateKeyedEvent(&Threading::Primitives::gKeyedEventHandle, -1, NULL, 0);
}
}
#else
pLoadLibraryW = UWPLibraryW;
pGetProcAddress = UWPProcAddress;
pCreateFile2W = CreateFile2FromAppW;
pCreateFileMappingFromApp = CreateFileMappingFromApp;
pOpenFileMappingFromApp = OpenFileMappingFromApp;
pMapViewOfFileFromApp = MapViewOfFileFromApp;
pCreateFileMappingA = UWPCreateFileMappingA;
pOpenFileMappingA = UWPOpenFileMappingA;
pMapViewOfFile = UWPMapViewOfFile;
pWaitOnAddress = WaitOnAddress;
pWakeByAddressSingle = WakeByAddressSingle;
pWakeByAddressAll = WakeByAddressAll;
pVirtualAlloc2 = VirtualAlloc2FromApp;
pMapViewOfFile3 = MapViewOfFile3FromApp;
pCancelIoEx = CancelIoEx;
pCancelSynchronousIo = CancelSynchronousIo;
pGetLocaleInfoEx = GetLocaleInfoEx;
pLCIDToLocaleName = LCIDToLocaleName;
pSetFileInformationByHandle = SetFileInformationByHandle;
pFindClose = FindClose;
pGetTempPathW = GetTempPath2W;
pGetSystemCpuSetInformation = GetSystemCpuSetInformation;
pGetLogicalProcessorInformation = GetLogicalProcessorInformation;
pSetThreadInformation = SetThreadInformation;
pSetThreadDescription = SetThreadDescription;
pSetThreadSelectedCpuSets = SetThreadSelectedCpuSets;
pGetAddrInfoExCancel = GetAddrInfoExCancel;
pPrefetchVirtualMemory = PrefetchVirtualMemory;
pQueryPerformanceCounter = decltype(pQueryPerformanceCounter)(QueryPerformanceCounter);
pQueryPerformanceFrequency = decltype(pQueryPerformanceFrequency)(QueryPerformanceFrequency);
// https://github.com/LWJGL/lwjgl3/blob/master/modules/lwjgl/remotery/src/main/c/Remotery.c#L1188
// Xbox main SDK has a better API we should use
// So...
// TODO: Xbox One and later: https://github.com/microsoft/Xbox-ATG-Samples/blob/main/XDKSamples/Graphics/AdvancedESRAM12/PageAllocator.cpp#L193-L206
// Require AuProcess for that given target
pUnmapViewOfFile2 = UnmapViewOfFile2; // < isn't portable but
// "This topic lists the Win32 APIs that are part of the Universal Windows Platform (UWP) and that are implemented by all Windows 10 devices."
// UnmapViewOfFile2 -> Introduced into api-ms-win-core-memory-l1-1-5.dll in 10.0.17134.
pNtDelayExecution = nullptr /* ... (you dont need it, but it'll help a ton for SleepNs) */;
pGetAddrInfoExW = GetAddrInfoExW;
pGetAddrInfoExCancel = GetAddrInfoExCancel;
pFreeAddrInfoExW = FreeAddrInfoExW;
pgetaddrinfo = getaddrinfo;
pfreeaddrinfo = freeaddrinfo;
plisten = listen;
pbind = bind;
pclosesocket = closesocket;
pshutdown = shutdown;
pgetpeername = getpeername;
pgetsockname = getsockname;
pioctlsocket = ioctlsocket;
psetsockopt = setsockopt;
pWSAStartup = WSAStartup;
pWSAIoctl = WSAIoctl;
pWSAGetLastError = WSAGetLastError;
pWSASocketW = WSASocketW;
pWSARecvFrom = WSARecvFrom;
pWSARecv = WSARecv;
pWSASendTo = WSASendTo;
pWSASend = WSASend;
pWSAStringToAddressA = WSAStringToAddressA;
#endif
gUseNativeWaitMutex = (pWaitOnAddress &&
!gRuntimeConfig.threadingConfig.bPreferNt51XpMutexesOver8 &&
(pRtlWaitOnAddress || AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32)) ||
!pNtWaitForKeyedEvent;
gUseNativeWaitCondvar = (pWaitOnAddress &&
!gRuntimeConfig.threadingConfig.bPreferNt51XpCondvarsOver8 &&
(pRtlWaitOnAddress || AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32)) ||
!pNtWaitForKeyedEvent;
gUseNativeWaitSemapahore = bool(pWaitOnAddress);
}
static bool IsNetbookXpOrWin7Laptop()
{
return bool(GetEnvironmentVariableW(L"AURORA_IS_NETBOOK", nullptr, 0));
}
void Win32DropInit()
{
gShouldResPathDoNothing =
(AuBuild::kCurrentPlatform != AuBuild::EPlatform::ePlatformWin32) ||
(!gRuntimeConfig.threadingConfig.bEnableAggressiveScheduling &&
AuSwInfo::IsWindows10OrGreater()) ||
IsNetbookXpOrWin7Laptop();
gUseFastFail = AuSwInfo::IsWindows8Point1OrGreater()
#if defined(PF_FASTFAIL_AVAILABLE)
&& ::IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)
#endif
;
if (gShouldResPathDoNothing)
{
return;
}
#if defined(PROCESS_POWER_THROTTLING_CURRENT_VERSION)
if (pSetProcessInformation &&
AuSwInfo::IsWindows10OrGreater())
{
static AuInitOnceSmall gInitOnce;
if (AuThreading::InitOnceLocker::TryLock(&gInitOnce))
{
PROCESS_POWER_THROTTLING_STATE powerThrottling {};
powerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
powerThrottling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
powerThrottling.StateMask = 0;
gShouldResPathDoNothing = bool(pSetProcessInformation(GetCurrentProcess(),
ProcessPowerThrottling,
&powerThrottling,
sizeof(powerThrottling)));
powerThrottling.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
powerThrottling.StateMask = 0;
gShouldResPathDoNothing &= bool(pSetProcessInformation(GetCurrentProcess(),
ProcessPowerThrottling,
&powerThrottling,
sizeof(powerThrottling)));
AuThreading::InitOnceLocker::Finish(&gInitOnce);
} /* else no-wait. intentionally nop*/
}
#endif
}
void Win32DropSchedulerResolution()
{
ULONG ullActualResolution {};
if (gShouldResPathDoNothing)
{
return;
}
if (gRuntimeConfig.threadingConfig.bEnableAgrSchedulingRatelimit)
{
static Aurora::Utility::RateLimiter limiter;
if (!limiter.nsTimeStep)
{
limiter.SetNextStep(AuMSToNS<AuUInt64>(gRuntimeConfig.threadingConfig.bWinXpThrough7BlazeOptimizerPower));
}
else if (!limiter.CheckExchangePass())
{
return;
}
}
if (pZwSetTimerResolution)
{
auto uRet = pZwSetTimerResolution(1, true, &ullActualResolution);
if (uRet == 0)
{
return;
}
else if (uRet == 0xC0000245)
{
if ((uRet = pZwSetTimerResolution(5'000, true, &ullActualResolution)) == 0)
{
return;
}
}
}
}
HANDLE UWPCreateFileMappingA(HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCSTR lpName)
{
auto uSize = AuUInt64(AuUInt64(dwMaximumSizeHigh) << 32ull) |
AuUInt64(dwMaximumSizeLow);
if (!uSize && SysHandleIsNonZero(AuUInt(hFile)))
{
uSize = SysGetFileLength(AuUInt(hFile));
}
if (!pCreateFileMappingFromApp)
{
return NULL;
}
return pCreateFileMappingFromApp(hFile,
lpFileMappingAttributes,
flProtect,
uSize,
lpName ? AuLocale::ConvertFromUTF8(lpName).c_str() : nullptr);
}
HANDLE UWPOpenFileMappingA(DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCSTR lpName)
{
if (!pOpenFileMappingFromApp)
{
return NULL;
}
return pOpenFileMappingFromApp(dwDesiredAccess,
bInheritHandle,
lpName ? AuLocale::ConvertFromUTF8(lpName).c_str() : nullptr);
}
LPVOID UWPMapViewOfFile(HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
SIZE_T dwNumberOfBytesToMap)
{
if (!pMapViewOfFileFromApp)
{
return NULL;
}
return pMapViewOfFileFromApp(hFileMappingObject,
dwDesiredAccess,
AuUInt64(AuUInt64(dwFileOffsetHigh) << 32ull) | AuUInt64(dwFileOffsetLow),
dwNumberOfBytesToMap);
}
void Win32Terminate()
{
if (gUseFastFail)
{
__fastfail('fokd');
}
else
{
if (pNtTerminateProcess)
{
pNtTerminateProcess((HANDLE)-1, 0x0);
}
::TerminateProcess(::GetCurrentProcess(), 0);
}
}
HANDLE Win32Open(LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
bool bInherit,
DWORD dwCreationDisposition,
DWORD dwFlags,
DWORD dwAttributes
)
{
SECURITY_ATTRIBUTES attrs {};
attrs.nLength = sizeof(attrs);
attrs.bInheritHandle = bInherit ? TRUE : FALSE;
bool bSpecialFlags = (dwFlags & 0x4ffff7);
bool bSpecialAttrs = (dwAttributes & 0xFFB00008);
if (!pCreateFile2W)
{
if (bSpecialFlags)
{
SysPushErrorFeatureMissing("Do not use Windows8+ attributes/flags under Win32Open");
return INVALID_HANDLE_VALUE;
}
if (bSpecialAttrs)
{
SysPushErrorFeatureMissing("Do not use Windows8+ attributes/flags under Win32Open");
return INVALID_HANDLE_VALUE;
}
}
if (!dwAttributes)
{
dwAttributes = FILE_ATTRIBUTE_NORMAL;
}
if (pCreateFileW &&
!bSpecialFlags &&
!bSpecialAttrs)
{
return pCreateFileW(lpFileName,
dwDesiredAccess,
dwShareMode,
&attrs,
dwCreationDisposition,
dwFlags | dwAttributes,
NULL);
}
if (pCreateFile2W)
{
_CREATEFILE2_EXTENDED_PARAMETERS params {};
bool bRead {};
HANDLE hHandle {};
params.dwSize = sizeof(_CREATEFILE2_EXTENDED_PARAMETERS);
params.dwFileFlags = dwFlags;
params.dwFileAttributes = dwAttributes;
params.lpSecurityAttributes = &attrs;
if ((bRead = (::wcscmp(lpFileName, L"CONIN$") == 0)) ||
(::wcscmp(lpFileName, L"CONOUT$") == 0) ||
(::wcscmp(lpFileName, L"CONERR$") == 0))
{
if (!bRead)
{
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
}
else
{
dwDesiredAccess = GENERIC_READ;
}
if ((hHandle = pCreateFile2W(lpFileName,
dwDesiredAccess,
dwShareMode,
dwCreationDisposition,
&params)) != INVALID_HANDLE_VALUE)
{
return hHandle;
}
lpFileName = L"CON";
}
return pCreateFile2W(lpFileName,
dwDesiredAccess,
dwShareMode,
dwCreationDisposition,
&params);
}
return INVALID_HANDLE_VALUE;
}
HANDLE Win32Open2(LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlags,
DWORD dwAttributes)
{
bool bSpecialFlags = (dwFlags & 0x4ffff7);
bool bSpecialAttrs = (dwAttributes & 0xFFB00008);
if (!pCreateFile2W)
{
if (bSpecialFlags)
{
SysPushErrorFeatureMissing("Do not use Windows8+ attributes/flags under Win32Open");
return INVALID_HANDLE_VALUE;
}
if (bSpecialAttrs)
{
SysPushErrorFeatureMissing("Do not use Windows8+ attributes/flags under Win32Open");
return INVALID_HANDLE_VALUE;
}
}
if (!dwAttributes)
{
dwAttributes = FILE_ATTRIBUTE_NORMAL;
}
if (pCreateFileW &&
!bSpecialFlags &&
!bSpecialAttrs)
{
return pCreateFileW(lpFileName,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlags | dwAttributes,
NULL);
}
if (pCreateFile2W)
{
_CREATEFILE2_EXTENDED_PARAMETERS params {};
bool bRead {};
HANDLE hHandle {};
params.dwSize = sizeof(_CREATEFILE2_EXTENDED_PARAMETERS);
params.dwFileFlags = dwFlags;
params.dwFileAttributes = dwAttributes;
params.lpSecurityAttributes = lpSecurityAttributes;
if ((bRead = (::wcscmp(lpFileName, L"CONIN$") == 0)) ||
(::wcscmp(lpFileName, L"CONOUT$") == 0) ||
(::wcscmp(lpFileName, L"CONERR$") == 0))
{
if (!bRead)
{
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
}
else
{
dwDesiredAccess = GENERIC_READ;
}
if ((hHandle = pCreateFile2W(lpFileName,
dwDesiredAccess,
dwShareMode,
dwCreationDisposition,
&params)) != INVALID_HANDLE_VALUE)
{
return hHandle;
}
lpFileName = L"CON";
}
return pCreateFile2W(lpFileName,
dwDesiredAccess,
dwShareMode,
dwCreationDisposition,
&params);
}
return INVALID_HANDLE_VALUE;
}
#if !defined(AURORA_PLATFORM_WIN32)
HMODULE UWPLibraryW(LPCWSTR lpLibFileName)
{
auto pos = std::basic_string_view<wchar_t>(lpLibFileName).find_last_of('/');
if (pos == std::basic_string_view<wchar_t>::npos)
{
pos = std::basic_string_view<wchar_t>(lpLibFileName).find_last_of('\\');
}
if (pos == std::basic_string_view<wchar_t>::npos)
{
#if defined(AURORA_HAS_LOAD_PGKD)
return (HMODULE)::LoadPackagedLibrary(lpLibFileName, 0);
#else
return (HMODULE)lpLibFileName;
#endif
}
else
{
auto pString = &lpLibFileName[pos + 1];
#if defined(AURORA_HAS_LOAD_PGKD)
return (HMODULE)::LoadPackagedLibrary(pString, 0);
#else
return (HMODULE)pString;
#endif
}
}
FARPROC UWPProcAddress(HMODULE hModule,
LPCSTR lpProcName)
{
if (!hModule)
{
return nullptr;
}
#if defined(AURORA_HAS_GET_PROC_NONWIN32)
return GetProcAddress(hModule, lpProcName);
#endif
return nullptr;
}
#endif
bool SysNativeWaitOnAddressFutexSupported()
{
return bool(pWaitOnAddress) || bool(pRtlWaitOnAddress);
}
bool SysWaitOnAddressTimed(const void *pTargetAddress,
const void *pCompareAddress,
AuUInt8 uWordSize,
AuUInt64 uAbsTimeSteadyClock,
AuUInt64 uRelativeNanoseconds,
AuOptional<AuUInt64> uAbsTimeAltClock,
bool bSpun)
{
// Wont move out of AuWakeOnAddress.cpp because it's so long and bloated in order to force nanosecond-scale yields on UWP.
SysUnreachable();
}
void NTWriteEoS(HANDLE hHandle)
{
SetEndOfFile(hHandle);
}
void SysWriteEoS(AuUInt uOSHandle)
{
NTWriteEoS((HANDLE)uOSHandle);
}
void SysCloseHandle(AuUInt uOSHandle)
{
auto pHandle = (void *)uOSHandle;
AuWin32CloseHandle(pHandle);
}
bool SysHandleIsNonZero(AuUInt uOSHandle)
{
return uOSHandle && (void *)uOSHandle != INVALID_HANDLE_VALUE;
}
void SysFlushHandle(AuUInt uOSHandle)
{
auto pHandle = (void *)uOSHandle;
FlushFileBuffers(pHandle);
}
AuUInt64 SysGetFileLength(AuUInt uOSHandle)
{
LARGE_INTEGER length;
if (!::GetFileSizeEx((HANDLE)uOSHandle, &length))
{
SysPushErrorIO();
return 0;
}
return length.QuadPart;
}
void *SysAllocateLarge(AuUInt uLength)
{
uLength = AuMemory::RoundPageUp(uLength);
return VirtualAlloc(nullptr, uLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
}
void SysAllocateFree(void *pBuffer, AuUInt uLength)
{
VirtualFree(pBuffer, 0, MEM_RELEASE);
}
bool SysMemoryLockPages(const void *pVoid, AuUInt uLength)
{
return VirtualLock((void *)pVoid, uLength);
}
bool SysMemoryUnlockPages(const void *pVoid, AuUInt uLength)
{
return VirtualUnlock((void *)pVoid, uLength);
}
}