[+] Broke out NT LoadLibrarys to a dedicated root AuProcAddesses.[NT.]hpp

This commit is contained in:
Reece Wilson 2023-02-16 16:01:21 +00:00
parent c4fae31057
commit 88b0270435
9 changed files with 244 additions and 151 deletions

View File

@ -0,0 +1,74 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcAddresses.NT.cpp
Date: 2023-2-16
Author: Reece
***/
#include <RuntimeInternal.hpp>
namespace Aurora
{
void InitNTAddresses()
{
#if defined(AURORA_PLATFORM_WIN32)
#define ADD_LOAD_LIB(name) \
auto h ## name = LoadLibraryW(k## name ## DllName);
ADD_LOAD_LIB(Kernel32);
ADD_LOAD_LIB(Nt);
ADD_LOAD_LIB(KernelBase);
ADD_LOAD_LIB(Sync);
#define ADD_GET_PROC(name, proc) \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(GetProcAddress(h ## name, #proc)); \
}
#define ADD_GET_PROC_BI(name, name2, proc) \
p ## proc = nullptr; \
if (h ## name) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(GetProcAddress(h ## name, #proc)); \
} \
if (!p ## proc) \
{ \
if (h ## name2) \
{ \
p ## proc = AuReinterpretCast<decltype(p ## proc)>(GetProcAddress(h ## name2, #proc)); \
} \
}
ADD_GET_PROC(Nt, RtlGetVersion)
ADD_GET_PROC(Nt, NtDelayExecution)
ADD_GET_PROC_BI(Kernel32, KernelBase, VirtualAlloc2)
ADD_GET_PROC_BI(Kernel32, KernelBase, MapViewOfFile3)
ADD_GET_PROC_BI(Kernel32, KernelBase, UnmapViewOfFile2)
ADD_GET_PROC(Sync, WaitOnAddress)
ADD_GET_PROC(Sync, WakeByAddressSingle)
ADD_GET_PROC(Sync, WakeByAddressAll)
#else
pWaitOnAddress = WaitOnAddress;
pWakeByAddressSingle = WakeByAddressSingle;
pWakeByAddressAll = WakeByAddressAll;
pVirtualAlloc2 = VirtualAlloc2FromApp;
pMapViewOfFile3 = MapViewOfFile3FromApp;
// 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) */;
#endif
}
}

View File

@ -0,0 +1,72 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcAddresses.NT.hpp
Date: 2023-2-16
Author: Reece
***/
#pragma once
namespace Aurora
{
void InitNTAddresses();
static const wchar_t *kSyncDllName { L"API-MS-Win-Core-Synch-l1-2-0.dll" };
static const wchar_t *kNtDllName { L"NTDLL.dll" };
static const wchar_t *kKernel32DllName { L"Kernel32.dll" };
static const wchar_t *kKernelBaseDllName { L"KernelBase.dll" };
inline BOOL(_stdcall *pWaitOnAddress)(
volatile VOID * Address,
PVOID CompareAddress,
SIZE_T AddressSize,
DWORD dwMilliseconds
);
inline void(_stdcall *pWakeByAddressSingle)(
PVOID Address
);
inline void(_stdcall *pWakeByAddressAll)(
PVOID Address
);
inline DWORD(_stdcall *pNtDelayExecution)(
BOOLEAN Alertable,
PLARGE_INTEGER DelayInterval
);
inline PVOID(__stdcall *pVirtualAlloc2)(
HANDLE Process,
PVOID BaseAddress,
SIZE_T Size,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
inline PVOID(__stdcall *pMapViewOfFile3)(
HANDLE FileMapping,
HANDLE Process,
PVOID BaseAddress,
ULONG64 Offset,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
inline PVOID(__stdcall *pUnmapViewOfFile2)(
HANDLE Process,
PVOID BaseAddress,
ULONG UnmapFlags
);
#if defined(AURORA_PLATFORM_WIN32)
inline NTSTATUS(_stdcall *pRtlGetVersion)(
PRTL_OSVERSIONINFOW lpVersionInformation
);
#endif
}

View File

@ -0,0 +1,22 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcAddresses.cpp
Date: 2023-2-16
Author: Reece
***/
#include <RuntimeInternal.hpp>
#if defined(AURORA_IS_MODERNNT_DERIVED)
#include "AuProcAddresses.NT.hpp"
#endif
namespace Aurora
{
void InitProcAddresses()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
InitNTAddresses();
#endif
}
}

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcAddresses.hpp
Date: 2023-2-16
Author: Reece
***/
#pragma once
#if defined(AURORA_IS_MODERNNT_DERIVED)
#include "AuProcAddresses.NT.hpp"
#endif
namespace Aurora
{
void InitProcAddresses();
}

View File

@ -16,33 +16,6 @@
namespace Aurora::Process
{
static PVOID (__stdcall *VirtualAlloc2_f)(
HANDLE Process,
PVOID BaseAddress,
SIZE_T Size,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
static PVOID (__stdcall *MapViewOfFile3_f)(
HANDLE FileMapping,
HANDLE Process,
PVOID BaseAddress,
ULONG64 Offset,
SIZE_T ViewSize,
ULONG AllocationType,
ULONG PageProtection,
MEM_EXTENDED_PARAMETER *ExtendedParameters,
ULONG ParameterCount
);
static PVOID(__stdcall *UnmapViewOfFile2_f)(
HANDLE Process,
PVOID BaseAddress,
ULONG UnmapFlags
);
AuUInt ProcessSectionViewReserved::GetStart()
{
@ -58,7 +31,7 @@ namespace Aurora::Process
{
this->uMaxLength = uLength;
this->pBaseAddress = AuReinterpretCast<decltype(this->pBaseAddress)>(VirtualAlloc2_f(
this->pBaseAddress = AuReinterpretCast<decltype(this->pBaseAddress)>(pVirtualAlloc2(
nullptr,
nullptr,
this->uMaxLength,
@ -153,9 +126,9 @@ namespace Aurora::Process
}
}
if (!UnmapViewOfFile2_f(INVALID_HANDLE_VALUE,
this->pBaseAddress + uOffset,
MEM_PRESERVE_PLACEHOLDER))
if (!pUnmapViewOfFile2(INVALID_HANDLE_VALUE,
this->pBaseAddress + uOffset,
MEM_PRESERVE_PLACEHOLDER))
{
SysPushErrorMemory("System refused to restore placeholder: {}", GetLastError());
break;
@ -294,15 +267,15 @@ namespace Aurora::Process
return {};
}
auto map = MapViewOfFile3_f(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
0,
uLength,
MEM_REPLACE_PLACEHOLDER,
uPageFlags,
nullptr,
0);
auto map = pMapViewOfFile3(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
0,
uLength,
MEM_REPLACE_PLACEHOLDER,
uPageFlags,
nullptr,
0);
if (!map)
{
SysPushErrorIO("Couldn't create allocation of section");
@ -430,15 +403,15 @@ namespace Aurora::Process
return {};
}
auto map = MapViewOfFile3_f(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
uOffset,
uLength,
MEM_REPLACE_PLACEHOLDER,
pageAttributes,
nullptr,
0);
auto map = pMapViewOfFile3(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
uOffset,
uLength,
MEM_REPLACE_PLACEHOLDER,
pageAttributes,
nullptr,
0);
if (!map)
{
SysPushErrorIO("Couldn't create map of section: {}", GetLastError());
@ -535,15 +508,15 @@ namespace Aurora::Process
return {};
}
auto map = MapViewOfFile3_f(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
uOffset,
uLength,
MEM_REPLACE_PLACEHOLDER,
pageAttributes,
nullptr,
0);
auto map = pMapViewOfFile3(hFileMap,
INVALID_HANDLE_VALUE,
this->pBaseAddress + uAddressOut,
uOffset,
uLength,
MEM_REPLACE_PLACEHOLDER,
pageAttributes,
nullptr,
0);
if (!map)
{
SysPushErrorIO("Couldn't create map of IPC section (handle: {})", handleString);
@ -577,12 +550,15 @@ namespace Aurora::Process
{
auto &platform = AuSwInfo::GetPlatformInfo();
#if 0
if (!AuSwInfo::IsWindows10OrGreater() || // < win10 or
((platform.uKernelMajor == 10) && (platform.uKernelPatch < 1803)) ||
!VirtualAlloc2_f ||
!MapViewOfFile3_f) // < RS4
#else
if (!pVirtualAlloc2) // allow modified windows runtimes
#endif
{
#define WIN_7_WARN "WARNING: ADDRESS SPACE CANNOT BE RESERVED ON OLDER NT KERNELS. \r\n" \
"AuProcess::ReserveAddressSpace(AuUInt uOffset) is about to lie about reserving the address space, yield the entire address space, and leave a note to terminate the application if an explicit fixed-offset request is made."
@ -611,24 +587,6 @@ namespace Aurora::Process
void LoadProcessSectionViewSymbol()
{
auto hKernelHandle = LoadLibraryA("Kernel32.dll");
auto hKernelHandle2 = LoadLibraryA("KernelBase.dll");
VirtualAlloc2_f = AuReinterpretCast<decltype(VirtualAlloc2_f)>(::GetProcAddress(hKernelHandle, "VirtualAlloc2"));
if (!VirtualAlloc2_f)
{
VirtualAlloc2_f = AuReinterpretCast<decltype(VirtualAlloc2_f)>(::GetProcAddress(hKernelHandle2, "VirtualAlloc2"));
}
MapViewOfFile3_f = AuReinterpretCast<decltype(MapViewOfFile3_f)>(::GetProcAddress(hKernelHandle, "MapViewOfFile3"));
if (!MapViewOfFile3_f)
{
MapViewOfFile3_f = AuReinterpretCast<decltype(MapViewOfFile3_f)>(::GetProcAddress(hKernelHandle2, "MapViewOfFile3"));
}
UnmapViewOfFile2_f = AuReinterpretCast<decltype(UnmapViewOfFile2_f)>(::GetProcAddress(hKernelHandle, "UnmapViewOfFile2"));
if (!UnmapViewOfFile2_f)
{
UnmapViewOfFile2_f = AuReinterpretCast<decltype(UnmapViewOfFile2_f)>(::GetProcAddress(hKernelHandle2, "UnmapViewOfFile2"));
}
}
}

View File

@ -19,16 +19,24 @@
#define WIN32_LEAN_AND_MEAN
#endif
// Do not change: Minimum target - Windows 7
#define _WIN32_WINNT 0x0601
#include <SDKDDKVer.h>
#include <winsock2.h>
// When I had ASIO in here for a few months (2020 experiments), it was a pain to include properly
#if defined(_AUHAS_ASIO)
#include <asio.hpp>
#endif
// High level Win32 APIs
#include <windows.h>
// Restricted public Nt-level APIs
#include <winternl.h>
// And of course, LoadLibrary and pattern scanning is going to be the best option for yoinking truely internal/undocumented functions.
#else
#if defined(_AUHAS_ASIO)
#include <asio.hpp>
@ -57,6 +65,8 @@
#endif
#include "AuProcAddresses.hpp"
#define GIMME_IOWAITABLEITEM
#include <AuroraRuntime.hpp>
@ -64,7 +74,6 @@
inline Aurora::RuntimeStartInfo gRuntimeConfig;
inline int gRuntimeRunLevel {0};
using namespace Aurora::Logging;
namespace Aurora

View File

@ -19,12 +19,6 @@
namespace Aurora::Threading
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
using NtDelayExecution_f = DWORD(NTAPI *)(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval);
static NtDelayExecution_f NtDelayExecution;
#endif
AUKN_SYM void Sleep(AuUInt64 qwTimeout)
{
#if defined(AURORA_IS_LINUX_DERIVED)
@ -63,7 +57,7 @@ namespace Aurora::Threading
#if defined(AURORA_IS_MODERNNT_DERIVED)
if (NtDelayExecution)
if (pNtDelayExecution)
{
auto endTimeSteady = AuTime::SteadyClockNS() + qwTimeout;
auto endTimeWall = AuTime::CurrentClockNS() + qwTimeout;
@ -73,7 +67,7 @@ namespace Aurora::Threading
{
LARGE_INTEGER word;
word.QuadPart = targetTimeNt;
NtDelayExecution(FALSE, &word);
pNtDelayExecution(FALSE, &word);
}
return;
@ -90,8 +84,6 @@ namespace Aurora::Threading
void InitSleep()
{
#if defined(AURORA_IS_MODERNNT_DERIVED)
NtDelayExecution = AuReinterpretCast<NtDelayExecution_f>(GetProcAddress(LoadLibraryA("ntdll.dll"), "NtDelayExecution"));
#endif
// ...
}
}

View File

@ -13,30 +13,9 @@
namespace Aurora::Threading::Primitives
{
static BOOL (_stdcall *WaitOnAddress_f)(
volatile VOID *Address,
PVOID CompareAddress,
SIZE_T AddressSize,
DWORD dwMilliseconds
) =
#if defined(AURORA_PLATFORM_WIN32)
decltype(WaitOnAddress_f)(GetProcAddress(LoadLibraryA("API-MS-Win-Core-Synch-l1-2-0.dll"), "WaitOnAddress"));
#else
WaitOnAddress;
#endif
static void(_stdcall *WakeByAddressSingle_f)(
PVOID Address
) =
#if defined(AURORA_PLATFORM_WIN32)
decltype(WakeByAddressSingle_f)(GetProcAddress(LoadLibraryA("API-MS-Win-Core-Synch-l1-2-0.dll"), "WakeByAddressSingle"));
#else
WakeByAddressSingle;
#endif
Mutex::Mutex()
{
if (!WaitOnAddress_f)
if (!pWaitOnAddress)
{
::InitializeSRWLock(&this->atomicHolder_);
::InitializeConditionVariable(&this->wakeup_);
@ -82,7 +61,7 @@ namespace Aurora::Threading::Primitives
AuInt64 uStartTime = Time::SteadyClockMS();
AuInt64 uEndTime = uStartTime + timeout;
if (WaitOnAddress_f)
if (pWaitOnAddress)
{
auto state = this->state_;
while (::_interlockedbittestandset(&this->state_, 0) != 0)
@ -100,7 +79,7 @@ namespace Aurora::Threading::Primitives
uTimeoutMS = uEndTime - uStartTime;
}
if (!WaitOnAddress_f(&this->state_, &state, sizeof(this->state_), uTimeoutMS))
if (!pWaitOnAddress(&this->state_, &state, sizeof(this->state_), uTimeoutMS))
{
SysAssertExp(GetLastError() == ERROR_TIMEOUT);
return false;
@ -149,7 +128,7 @@ namespace Aurora::Threading::Primitives
void Mutex::Unlock()
{
if (!WaitOnAddress_f)
if (!pWaitOnAddress)
{
::AcquireSRWLockExclusive(&this->atomicHolder_);
this->state_ = 0;
@ -159,7 +138,7 @@ namespace Aurora::Threading::Primitives
else
{
this->state_ = 0;
WakeByAddressSingle_f((void *)&this->state_);
pWakeByAddressSingle((void *)&this->state_);
}
}

View File

@ -12,40 +12,10 @@
#if !defined(_AURUNTIME_GENERIC_SEMAPHORE)
namespace Aurora::Threading::Primitives
{
static BOOL(_stdcall *WaitOnAddress_f)(
volatile VOID *Address,
PVOID CompareAddress,
SIZE_T AddressSize,
DWORD dwMilliseconds
) =
#if defined(AURORA_PLATFORM_WIN32)
decltype(WaitOnAddress_f)(GetProcAddress(LoadLibraryA("API-MS-Win-Core-Synch-l1-2-0.dll"), "WaitOnAddress"));
#else
WaitOnAddress;
#endif
static void(_stdcall *WakeByAddressSingle_f)(
PVOID Address
) =
#if defined(AURORA_PLATFORM_WIN32)
decltype(WakeByAddressSingle_f)(GetProcAddress(LoadLibraryA("API-MS-Win-Core-Synch-l1-2-0.dll"), "WakeByAddressSingle"));
#else
WakeByAddressSingle;
#endif
static void(_stdcall *WakeByAddressAll_f)(
PVOID Address
) =
#if defined(AURORA_PLATFORM_WIN32)
decltype(WakeByAddressAll_f)(GetProcAddress(LoadLibraryA("API-MS-Win-Core-Synch-l1-2-0.dll"), "WakeByAddressAll"));
#else
WakeByAddressAll;
#endif
Semaphore::Semaphore(long iIntialValue)
{
this->value_ = iIntialValue;
if (!WaitOnAddress_f)
if (!pWaitOnAddress)
{
::InitializeSRWLock(&this->lock_);
::InitializeConditionVariable(&this->winCond_);
@ -83,7 +53,7 @@ namespace Aurora::Threading::Primitives
AuUInt64 uStart = AuTime::SteadyClockMS();
AuUInt64 uEnd = uStart + uTimeout;
if (WaitOnAddress_f)
if (pWaitOnAddress)
{
auto old = this->value_;
//!tryLock (with old in a scope we can access)
@ -103,7 +73,7 @@ namespace Aurora::Threading::Primitives
timeoutMs = uEnd - uStart;
}
if (!WaitOnAddress_f(&this->value_, &old, sizeof(this->value_), timeoutMs))
if (!pWaitOnAddress(&this->value_, &old, sizeof(this->value_), timeoutMs))
{
SysAssertExp(GetLastError() == ERROR_TIMEOUT);
return false;
@ -153,7 +123,7 @@ namespace Aurora::Threading::Primitives
void Semaphore::Unlock(long count)
{
if (!WaitOnAddress_f)
if (!pWaitOnAddress)
{
::AcquireSRWLockShared(&this->lock_);
AuAtomicAdd<AuInt32>(&this->value_, count);
@ -165,11 +135,11 @@ namespace Aurora::Threading::Primitives
AuAtomicAdd<AuInt32>(&this->value_, count);
if (count == 1)
{
WakeByAddressSingle_f(&this->value_);
pWakeByAddressSingle(&this->value_);
}
else
{
WakeByAddressAll_f(&this->value_);
pWakeByAddressAll(&this->value_);
}
}
}