diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj index 490946b8..c5a18ad0 100644 --- a/OptiScaler/OptiScaler.vcxproj +++ b/OptiScaler/OptiScaler.vcxproj @@ -347,6 +347,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y + diff --git a/OptiScaler/OptiScaler.vcxproj.filters b/OptiScaler/OptiScaler.vcxproj.filters index e9b4f86c..fda4730c 100644 --- a/OptiScaler/OptiScaler.vcxproj.filters +++ b/OptiScaler/OptiScaler.vcxproj.filters @@ -563,6 +563,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/OptiScaler/OwnedMutex.h b/OptiScaler/OwnedMutex.h index fc35c303..15fdd927 100644 --- a/OptiScaler/OwnedMutex.h +++ b/OptiScaler/OwnedMutex.h @@ -9,7 +9,7 @@ class OwnedMutex { private: std::shared_mutex mtx; - std::atomic owner {}; // don't use 0 + std::atomic owner = 0; // don't use 0 public: void lock(uint32_t _owner) diff --git a/OptiScaler/State.h b/OptiScaler/State.h index 466ad9c2..b0a3dee6 100644 --- a/OptiScaler/State.h +++ b/OptiScaler/State.h @@ -6,6 +6,7 @@ #include #include "misc/Quirks.h" +#include #include #include #include @@ -194,6 +195,7 @@ class State std::string currentInputApiName; bool isShuttingDown = false; + std::set modulesToFree; // menu warnings bool fgSettingsChanged = false; diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp index 818d73d9..9dfcfcf7 100644 --- a/OptiScaler/dllmain.cpp +++ b/OptiScaler/dllmain.cpp @@ -17,6 +17,7 @@ #include #include "proxies/Kernel32_Proxy.h" #include "proxies/KernelBase_Proxy.h" +#include "proxies/Ntdll_Proxy.h" #include #include "inputs/FSR2_Dx12.h" @@ -32,7 +33,6 @@ #include #include #include - #include #include @@ -190,7 +190,7 @@ void LoadAsiPlugins() if (ext == L".asi") { - HMODULE hMod = KernelBaseProxy::LoadLibraryW_()(entry.path().c_str()); + HMODULE hMod = NtdllProxy::LoadLibraryExW_Ldr(entry.path().c_str(), NULL, 0); if (hMod != nullptr) { @@ -237,14 +237,6 @@ static void CheckWorkingMode() { LOG_FUNC(); - if (Config::Instance()->EarlyHooking.value_or_default()) - { - - NtdllHooks::Hook(); - KernelHooks::Hook(); - KernelHooks::HookBase(); - } - bool modeFound = false; std::string filename = Util::DllPath().filename().string(); std::string lCaseFilename(filename); @@ -272,13 +264,20 @@ static void CheckWorkingMode() break; } + if (Config::Instance()->EarlyHooking.value_or_default()) + { + NtdllHooks::Hook(); + KernelHooks::Hook(); + KernelHooks::HookBase(); + } + // version.dll if (lCaseFilename == "version.dll") { do { auto pluginFilePath = pluginPath / L"version.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -286,7 +285,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"version-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"version-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -295,7 +294,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"version.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as version.dll, system dll loaded"); @@ -328,7 +327,7 @@ static void CheckWorkingMode() do { auto pluginFilePath = pluginPath / L"winmm.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -336,7 +335,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"winmm-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"winmm-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -345,7 +344,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"winmm.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as winmm.dll, system dll loaded"); @@ -377,7 +376,7 @@ static void CheckWorkingMode() do { auto pluginFilePath = pluginPath / L"wininet.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -385,7 +384,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"wininet-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"wininet-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -394,7 +393,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"wininet.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as wininet.dll, system dll loaded"); @@ -426,7 +425,7 @@ static void CheckWorkingMode() do { auto pluginFilePath = pluginPath / L"dbghelp.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -434,7 +433,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"dbghelp-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"dbghelp-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -443,7 +442,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"dbghelp.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as dbghelp.dll, system dll loaded"); @@ -509,7 +508,7 @@ static void CheckWorkingMode() do { auto pluginFilePath = pluginPath / L"winhttp.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -517,7 +516,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"winhttp-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"winhttp-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -526,7 +525,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"winhttp.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as winhttp.dll, system dll loaded"); @@ -558,7 +557,7 @@ static void CheckWorkingMode() do { auto pluginFilePath = pluginPath / L"dxgi.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { @@ -566,7 +565,7 @@ static void CheckWorkingMode() break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"dxgi-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"dxgi-original.dll", NULL, 0); if (originalModule != nullptr) { @@ -575,7 +574,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"dxgi.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as dxgi.dll, system dll loaded"); @@ -609,17 +608,18 @@ static void CheckWorkingMode() do { // Moved here to cover agility sdk + NtdllHooks::Hook(); KernelHooks::HookBase(); auto pluginFilePath = pluginPath / L"d3d12.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(pluginFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(pluginFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) { LOG_INFO("OptiScaler working as d3d12.dll, original dll loaded from plugin folder"); break; } - originalModule = KernelBaseProxy::LoadLibraryExW_()(L"d3d12-original.dll", NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(L"d3d12-original.dll", NULL, 0); if (originalModule != nullptr) { LOG_INFO("OptiScaler working as d3d12.dll, d3d12-original.dll loaded"); @@ -627,7 +627,7 @@ static void CheckWorkingMode() } auto sysFilePath = sysPath / L"d3d12.dll"; - originalModule = KernelBaseProxy::LoadLibraryExW_()(sysFilePath.wstring().c_str(), NULL, 0); + originalModule = NtdllProxy::LoadLibraryExW_Ldr(sysFilePath.wstring().c_str(), NULL, 0); if (originalModule != nullptr) LOG_INFO("OptiScaler working as d3d12.dll, system dll loaded"); @@ -706,6 +706,7 @@ static void CheckWorkingMode() { // Moved here to cover agility sdk KernelHooks::HookBase(); + NtdllHooks::Hook(); LOG_DEBUG("Check for d3d12"); HMODULE d3d12Module = nullptr; @@ -740,7 +741,7 @@ static void CheckWorkingMode() // Vulkan vulkanModule = GetDllNameWModule(&vkNamesW); if ((State::Instance().isRunningOnDXVK || State::Instance().isRunningOnLinux) && vulkanModule == nullptr) - vulkanModule = KernelBaseProxy::LoadLibraryExW_()(vkNamesW[0].c_str(), NULL, 0); + vulkanModule = NtdllProxy::LoadLibraryExW_Ldr(vkNamesW[0].c_str(), NULL, 0); if (vulkanModule != nullptr) { @@ -879,7 +880,7 @@ static void CheckWorkingMode() SetEnvironmentVariableW(L"RESHADE_DISABLE_GRAPHICS_HOOK", L"1"); State::EnableServeOriginal(200); - skModule = LoadLibraryW(skFile.c_str()); + skModule = NtdllProxy::LoadLibraryExW_Ldr(skFile.c_str(), NULL, 0); State::DisableServeOriginal(200); LOG_INFO("Loading SpecialK64.dll, result: {0:X}", (UINT64) skModule); @@ -895,7 +896,7 @@ static void CheckWorkingMode() SetEnvironmentVariableW(L"RESHADE_DISABLE_GRAPHICS_HOOK", L"1"); State::EnableServeOriginal(201); - reshadeModule = LoadLibraryW(rsFile.c_str()); + reshadeModule = NtdllProxy::LoadLibraryExW_Ldr(rsFile.c_str(), NULL, 0); State::DisableServeOriginal(201); LOG_INFO("Loading ReShade64.dll, result: {0:X}", (size_t) reshadeModule); @@ -917,7 +918,7 @@ static void CheckWorkingMode() // Intel Extension Framework if (Config::Instance()->UESpoofIntelAtomics64.value_or_default()) { - HMODULE igdext = KernelBaseProxy::LoadLibraryW_()(L"igdext64.dll"); + HMODULE igdext = NtdllProxy::LoadLibraryExW_Ldr(L"igdext64.dll", NULL, 0); if (igdext == nullptr) { @@ -927,7 +928,7 @@ static void CheckWorkingMode() { auto dllPath = paths[i] / L"igdext64.dll"; LOG_DEBUG("Trying to load: {}", wstring_to_string(dllPath.c_str())); - igdext = KernelBaseProxy::LoadLibraryExW_()(dllPath.c_str(), NULL, 0); + igdext = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0); if (igdext != nullptr) { @@ -1048,7 +1049,7 @@ bool isNvidia() if (!nvapiModule) { - nvapiModule = KernelBaseProxy::LoadLibraryExW_()(L"nvapi64.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + nvapiModule = NtdllProxy::LoadLibraryExW_Ldr(L"nvapi64.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); loadedHere = true; } @@ -1105,7 +1106,7 @@ bool isNvidia() } if (loadedHere) - KernelBaseProxy::FreeLibrary_()(nvapiModule); + NtdllProxy::FreeLibrary_Ldr(nvapiModule); LOG_DEBUG("Detected: {}", nvidiaDetected); @@ -1157,9 +1158,14 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv spdlog::info(""); // Init Kernel proxies + NtdllProxy::Init(); KernelBaseProxy::Init(); Kernel32Proxy::Init(); + // Check for working mode and attach hooks + spdlog::info(""); + CheckWorkingMode(); + // Check if real DLSS available if (Config::Instance()->DLSSEnabled.value_or_default()) { @@ -1222,10 +1228,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv Config::Instance()->NvapiDllPath.set_volatile_value(L"fakenvapi.dll"); } - // Check for working mode and attach hooks - spdlog::info(""); - CheckWorkingMode(); - // Asi plugins if (!State::Instance().isWorkingAsNvngx && Config::Instance()->LoadAsiPlugins.value_or_default()) { @@ -1291,6 +1293,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv break; case DLL_PROCESS_DETACH: + State::Instance().isShuttingDown = true; + // Unhooking and cleaning stuff causing issues during shutdown. // Disabled for now to check if it cause any issues // UnhookApis(); @@ -1302,15 +1306,20 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv // DetachHooks(); if (skModule != nullptr) - KernelBaseProxy::FreeLibrary_()(skModule); + NtdllProxy::FreeLibrary_Ldr(skModule); if (reshadeModule != nullptr) - KernelBaseProxy::FreeLibrary_()(reshadeModule); + NtdllProxy::FreeLibrary_Ldr(reshadeModule); if (_asiHandles.size() > 0) { for (size_t i = 0; i < _asiHandles.size(); i++) - KernelBaseProxy::FreeLibrary_()(_asiHandles[i]); + NtdllProxy::FreeLibrary_Ldr(_asiHandles[i]); + } + + for (const PVOID& v : State::Instance().modulesToFree) + { + NtdllProxy::FreeLibrary_Ldr(v); } spdlog::info(""); diff --git a/OptiScaler/fsr4/FSR4Upgrade.h b/OptiScaler/fsr4/FSR4Upgrade.h index 4ca3e95a..be818cdf 100644 --- a/OptiScaler/fsr4/FSR4Upgrade.h +++ b/OptiScaler/fsr4/FSR4Upgrade.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include @@ -68,7 +68,7 @@ inline static std::vector GetDriverStore() if (hGdi32 == nullptr) { - hGdi32 = KernelBaseProxy::LoadLibraryExW_()(L"Gdi32.dll", NULL, 0); + hGdi32 = NtdllProxy::LoadLibraryExW_Ldr(L"Gdi32.dll", NULL, 0); libraryLoaded = hGdi32 != nullptr; } @@ -140,7 +140,7 @@ inline static std::vector GetDriverStore() } while (false); if (libraryLoaded) - KernelBaseProxy::FreeLibrary_()(hGdi32); + NtdllProxy::FreeLibrary_Ldr(hGdi32); return result; } @@ -315,7 +315,7 @@ struct AmdExtFfxApi : public IAmdExtFfxApi if (o_UpdateFfxApiProvider == nullptr) { - fsr4Module = KernelBaseProxy::LoadLibraryExW_()(L"amdxcffx64.dll", NULL, 0); + fsr4Module = NtdllProxy::LoadLibraryExW_Ldr(L"amdxcffx64.dll", NULL, 0); if (fsr4Module == nullptr) { @@ -327,7 +327,7 @@ struct AmdExtFfxApi : public IAmdExtFfxApi { auto dllPath = storePath[i] / L"amdxcffx64.dll"; LOG_DEBUG("Trying to load: {}", wstring_to_string(dllPath.c_str())); - fsr4Module = KernelBaseProxy::LoadLibraryExW_()(dllPath.c_str(), NULL, 0); + fsr4Module = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0); if (fsr4Module != nullptr) { @@ -507,7 +507,7 @@ inline void InitFSR4Update() // For FSR4 Upgrade moduleAmdxc64 = KernelBaseProxy::GetModuleHandleW_()(L"amdxc64.dll"); if (moduleAmdxc64 == nullptr) - moduleAmdxc64 = KernelBaseProxy::LoadLibraryExW_()(L"amdxc64.dll", NULL, 0); + moduleAmdxc64 = NtdllProxy::LoadLibraryExW_Ldr(L"amdxc64.dll", NULL, 0); if (moduleAmdxc64 != nullptr) { diff --git a/OptiScaler/hooks/HooksVk.cpp b/OptiScaler/hooks/HooksVk.cpp index 3e389e50..63628282 100644 --- a/OptiScaler/hooks/HooksVk.cpp +++ b/OptiScaler/hooks/HooksVk.cpp @@ -5,7 +5,7 @@ #include -#include +#include #include #include diff --git a/OptiScaler/hooks/Kernel_Hooks.h b/OptiScaler/hooks/Kernel_Hooks.h index f977c440..a583bc6c 100644 --- a/OptiScaler/hooks/Kernel_Hooks.h +++ b/OptiScaler/hooks/Kernel_Hooks.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -64,901 +65,13 @@ class KernelHooks inline static KernelBaseProxy::PFN_LoadLibraryExW o_KB_LoadLibraryExW = nullptr; inline static KernelBaseProxy::PFN_GetProcAddress o_KB_GetProcAddress = nullptr; - inline static bool _overlayMethodsCalled = false; - - inline static HMODULE LoadLibraryCheck(std::string lcaseLibName, LPCSTR lpLibFullPath) - { - LOG_TRACE("{}", lcaseLibName); - - // C:\\Path\\like\\this.dll - auto normalizedPath = std::filesystem::path(lcaseLibName).lexically_normal().string(); - - // If Opti is not loading as nvngx.dll - // if (!State::Instance().enablerAvailable && !State::Instance().isWorkingAsNvngx) - //{ - // // exe path - // auto exePath = Util::ExePath().parent_path().wstring(); - - // for (size_t i = 0; i < exePath.size(); i++) - // exePath[i] = std::tolower(exePath[i]); - - // auto pos = lcaseLibName.rfind(wstring_to_string(exePath)); - - // if (Config::Instance()->EnableDlssInputs.value_or_default() && CheckDllName(&lcaseLibName, &nvngxNames) && - // (!Config::Instance()->HookOriginalNvngxOnly.value_or_default() || pos == std::string::npos)) - // { - // // LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibName); - // // loadCount++; - - // return nullptr; - // // return dllModule; - // } - //} - - if (!State::Instance().isWorkingAsNvngx && - (!State::Instance().isDxgiMode || !State::Instance().skipDxgiLoadChecks) && - CheckDllName(&lcaseLibName, &dllNames)) - { - if (!State::Instance().ServeOriginal()) - { - LOG_INFO("{} call, returning this dll!", lcaseLibName); - return dllModule; - } - else - { - LOG_INFO("{} call, ServeOriginal active returning original dll!", lcaseLibName); - return originalModule; - } - } - - // NvApi64.dll - if (CheckDllName(&lcaseLibName, &nvapiNames)) - { - if (Config::Instance()->OverrideNvapiDll.value_or_default()) - { - LOG_INFO("{0} call!", lcaseLibName); - - auto nvapi = LoadNvApi(); - - // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded - if (nvapi != nullptr) - { - NvApiHooks::Hook(nvapi); - return nvapi; - } - } - else - { - auto nvapi = GetModuleHandleA(lcaseLibName.c_str()); - - // Try to load nvapi only from system32, like the original call would - if (nvapi == nullptr) - { - nvapi = - KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (nvapi != nullptr) - NvApiHooks::Hook(nvapi); - - // AMD without nvapi override should fall through - } - } - - // sl.interposer.dll - if (CheckDllName(&lcaseLibName, &slInterposerNames)) - { - auto streamlineModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (streamlineModule != nullptr) - { - StreamlineHooks::hookInterposer(streamlineModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return streamlineModule; - } - - // sl.dlss.dll - if (CheckDllName(&lcaseLibName, &slDlssNames)) - { - auto dlssModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (dlssModule != nullptr) - { - StreamlineHooks::hookDlss(dlssModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return dlssModule; - } - - // sl.dlss_g.dll - if (CheckDllName(&lcaseLibName, &slDlssgNames)) - { - auto dlssgModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (dlssgModule != nullptr) - { - StreamlineHooks::hookDlssg(dlssgModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return dlssgModule; - } - - // sl.reflex.dll - if (CheckDllName(&lcaseLibName, &slReflexNames)) - { - auto reflexModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (reflexModule != nullptr) - { - StreamlineHooks::hookReflex(reflexModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return reflexModule; - } - - // sl.pcl.dll - if (CheckDllName(&lcaseLibName, &slPclNames)) - { - auto pclModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (pclModule != nullptr) - { - StreamlineHooks::hookPcl(pclModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return pclModule; - } - - // sl.common.dll - if (CheckDllName(&lcaseLibName, &slCommonNames)) - { - auto commonModule = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (commonModule != nullptr) - { - StreamlineHooks::hookCommon(commonModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return commonModule; - } - - // nvngx_dlss - if (Config::Instance()->DLSSEnabled.value_or_default() && Config::Instance()->NVNGX_DLSS_Library.has_value() && - CheckDllName(&lcaseLibName, &nvngxDlssNames)) - { - auto nvngxDlss = LoadNvngxDlss(string_to_wstring(lcaseLibName)); - - if (nvngxDlss == nullptr) - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return nvngxDlss; - } - - // NGX OTA - // Try to catch something like this: - // c:\programdata/nvidia/ngx/models//dlss/versions/20316673/files/160_e658700.bin - if (lcaseLibName.ends_with(".bin")) - { - auto loadedBin = KernelBaseProxy::LoadLibraryExA_()(lpLibFullPath, NULL, 0); - - if (loadedBin && normalizedPath.contains("\\versions\\")) - { - if (normalizedPath.contains("\\dlss\\")) - { - State::Instance().NGX_OTA_Dlss = lpLibFullPath; - } - - if (normalizedPath.contains("\\dlssd\\")) - { - State::Instance().NGX_OTA_Dlssd = lpLibFullPath; - } - } - return loadedBin; - } - - // Overlay - if (Config::Instance()->DisableOverlays.value_or_default() && CheckDllName(&lcaseLibName, &blockOverlayNames)) - { - LOG_DEBUG("Blocking overlay dll: {}", lcaseLibName); - return (HMODULE) 1; - } - else if (CheckDllName(&lcaseLibName, &overlayNames)) - { - LOG_DEBUG("Overlay dll: {}", lcaseLibName); - - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - if (/*!_overlayMethodsCalled &&*/ DxgiProxy::Module() != nullptr) - { - CheckForGPU(); - - LOG_INFO("Calling CreateDxgiFactory methods for overlay!"); - IDXGIFactory* factory = nullptr; - IDXGIFactory1* factory1 = nullptr; - IDXGIFactory2* factory2 = nullptr; - - if (DxgiProxy::CreateDxgiFactory_()(__uuidof(factory), &factory) == S_OK && factory != nullptr) - { - LOG_DEBUG("CreateDxgiFactory ok"); - factory->Release(); - } - - if (DxgiProxy::CreateDxgiFactory1_()(__uuidof(factory1), &factory1) == S_OK && factory1 != nullptr) - { - LOG_DEBUG("CreateDxgiFactory1 ok"); - factory1->Release(); - } - - if (DxgiProxy::CreateDxgiFactory2_()(0, __uuidof(factory2), &factory2) == S_OK && - factory2 != nullptr) - { - LOG_DEBUG("CreateDxgiFactory2 ok"); - factory2->Release(); - } - - _overlayMethodsCalled = true; - } - - return module; - } - } - - // Hooks - if (CheckDllName(&lcaseLibName, &dx11Names) && Config::Instance()->OverlayMenu.value_or_default()) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HooksDx::HookDx11(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (CheckDllName(&lcaseLibName, &dx12Names) && Config::Instance()->OverlayMenu.value_or_default()) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - D3d12Proxy::Init(module); - HooksDx::HookDx12(); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return module; - } - - if (CheckDllName(&lcaseLibName, &vkNames)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - HookForVulkanSpoofing(module); - HookForVulkanExtensionSpoofing(module); - HookForVulkanVRAMSpoofing(module); - - HooksVk::HookVk(module); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return module; - } - - if (!State::Instance().skipDxgiLoadChecks && CheckDllName(&lcaseLibName, &dxgiNames)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - - if (module != nullptr) - { - DxgiProxy::Init(module); - - CheckForGPU(); - - if (Config::Instance()->DxgiSpoofing.value_or_default()) - HookDxgiForSpoofing(); - - if (Config::Instance()->OverlayMenu.value_or_default()) - HooksDx::HookDxgi(); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - } - - return module; - } - - if (Config::Instance()->EnableFsr2Inputs.value_or_default() && CheckDllName(&lcaseLibName, &fsr2Names)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR2Inputs(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (Config::Instance()->EnableFsr2Inputs.value_or_default() && CheckDllName(&lcaseLibName, &fsr2BENames)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR2Dx12Inputs(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (Config::Instance()->EnableFsr3Inputs.value_or_default() && CheckDllName(&lcaseLibName, &fsr3Names)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR3Inputs(module); - - return module; - } - - if (Config::Instance()->EnableFsr3Inputs.value_or_default() && CheckDllName(&lcaseLibName, &fsr3BENames)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR3Dx12Inputs(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (CheckDllName(&lcaseLibName, &xessNames)) - { - auto module = LoadLibxess(string_to_wstring(lcaseLibName)); - - if (module != nullptr) - XeSSProxy::HookXeSS(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (CheckDllName(&lcaseLibName, &xessDx11Names)) - { - auto module = LoadLibxessDx11( - string_to_wstring(lcaseLibName)); // KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - XeSSProxy::HookXeSSDx11(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (CheckDllName(&lcaseLibName, &ffxDx12Names)) - { - auto module = LoadFfxapiDx12( - string_to_wstring(lcaseLibName)); // KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - FfxApiProxy::InitFfxDx12(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - if (CheckDllName(&lcaseLibName, &ffxDx12UpscalerNames)) - { - auto module = KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - FSR4ModelSelection::Hook(module); - - return module; - } - - if (CheckDllName(&lcaseLibName, &ffxVkNames)) - { - auto module = LoadFfxapiVk( - string_to_wstring(lcaseLibName)); // KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - FfxApiProxy::InitFfxVk(module); - else - LOG_ERROR("Trying to load dll: {}", lcaseLibName); - - return module; - } - - return nullptr; - } - - inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName, LPCWSTR lpLibFullPath) - { - auto lcaseLibNameA = wstring_to_string(lcaseLibName); - LOG_TRACE("{}", lcaseLibNameA); - - // C:\\Path\\like\\this.dll - auto normalizedPath = std::filesystem::path(lcaseLibName).lexically_normal().string(); - - // If Opti is not loading as nvngx.dll - // if (!State::Instance().enablerAvailable && !State::Instance().isWorkingAsNvngx) - //{ - // // exe path - // auto exePath = Util::ExePath().parent_path().wstring(); - - // for (size_t i = 0; i < exePath.size(); i++) - // exePath[i] = std::tolower(exePath[i]); - - // auto pos = lcaseLibName.rfind(exePath); - - // if (Config::Instance()->EnableDlssInputs.value_or_default() && CheckDllNameW(&lcaseLibName, &nvngxNamesW) - // && - // (!Config::Instance()->HookOriginalNvngxOnly.value_or_default() || pos == std::string::npos)) - // { - // // LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibNameA); - - // // if (!dontCount) - // // loadCount++; - - // return nullptr; - // // return dllModule; - // } - //} - - if (!State::Instance().isWorkingAsNvngx && - (!State::Instance().isDxgiMode || !State::Instance().skipDxgiLoadChecks) && - CheckDllNameW(&lcaseLibName, &dllNamesW)) - { - if (!State::Instance().ServeOriginal()) - { - LOG_INFO("{} call, returning this dll!", lcaseLibNameA); - return dllModule; - } - else - { - LOG_INFO("{} call, ServeOriginal active returning original dll!", lcaseLibNameA); - return originalModule; - } - } - - // nvngx_dlss - if (Config::Instance()->DLSSEnabled.value_or_default() && Config::Instance()->NVNGX_DLSS_Library.has_value() && - CheckDllNameW(&lcaseLibName, &nvngxDlssNamesW)) - { - auto nvngxDlss = LoadNvngxDlss(lcaseLibName); - - if (nvngxDlss != nullptr) - return nvngxDlss; - else - LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); - } - - // NGX OTA - // Try to catch something like this: - // c:\programdata/nvidia/ngx/models//dlss/versions/20316673/files/160_e658700.bin - if (lcaseLibName.ends_with(L".bin")) - { - auto loadedBin = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (loadedBin && normalizedPath.contains("\\versions\\")) - { - if (normalizedPath.contains("\\dlss\\")) - { - State::Instance().NGX_OTA_Dlss = wstring_to_string(lpLibFullPath); - } - - if (normalizedPath.contains("\\dlssd\\")) - { - State::Instance().NGX_OTA_Dlssd = wstring_to_string(lpLibFullPath); - } - } - return loadedBin; - } - - // NvApi64.dll - if (CheckDllNameW(&lcaseLibName, &nvapiNamesW)) - { - if (Config::Instance()->OverrideNvapiDll.value_or_default()) - { - LOG_INFO("{0} call!", lcaseLibNameA); - - auto nvapi = LoadNvApi(); - - // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded - if (nvapi != nullptr) - { - NvApiHooks::Hook(nvapi); - return nvapi; - } - } - else - { - auto nvapi = GetModuleHandleW(lcaseLibName.c_str()); - - // Try to load nvapi only from system32, like the original call would - if (nvapi == nullptr) - { - nvapi = - KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (nvapi != nullptr) - NvApiHooks::Hook(nvapi); - - // AMD without nvapi override should fall through - } - } - - // sl.interposer.dll - if (CheckDllNameW(&lcaseLibName, &slInterposerNamesW)) - { - auto streamlineModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (streamlineModule != nullptr) - { - StreamlineHooks::hookInterposer(streamlineModule); - } - else - { - LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); - } - - return streamlineModule; - } - - // sl.dlss.dll - // Try to catch something like this: - // C:\ProgramData/NVIDIA/NGX/models/sl_dlss_0/versions/133120/files/190_E658703.dll - if (CheckDllNameW(&lcaseLibName, &slDlssNamesW) || - (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_dlss_0"))) - { - auto dlssModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (dlssModule != nullptr) - { - StreamlineHooks::hookDlss(dlssModule); - } - else - { - LOG_ERROR("Trying to load dll as sl.dlss: {}", lcaseLibNameA); - } - - return dlssModule; - } - - // sl.dlss_g.dll - if (CheckDllNameW(&lcaseLibName, &slDlssgNamesW) || - (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_dlss_g_"))) - { - auto dlssgModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (dlssgModule != nullptr) - { - StreamlineHooks::hookDlssg(dlssgModule); - } - else - { - LOG_ERROR("Trying to load dll as sl.dlss_g: {}", lcaseLibNameA); - } - - return dlssgModule; - } - - // sl.reflex.dll - if (CheckDllNameW(&lcaseLibName, &slReflexNamesW) || - (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_reflex_"))) - { - auto reflexModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (reflexModule != nullptr) - { - StreamlineHooks::hookReflex(reflexModule); - } - else - { - LOG_ERROR("Trying to load dll as sl.reflex: {}", lcaseLibNameA); - } - - return reflexModule; - } - - // sl.pcl.dll - if (CheckDllNameW(&lcaseLibName, &slPclNamesW) || - (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_pcl_"))) - { - auto pclModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (pclModule != nullptr) - { - StreamlineHooks::hookPcl(pclModule); - } - else - { - LOG_ERROR("Trying to load dll as sl.pcl: {}", lcaseLibNameA); - } - - return pclModule; - } - - // sl.common.dll - if (CheckDllNameW(&lcaseLibName, &slCommonNamesW) || - (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_common_"))) - { - auto commonModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); - - if (commonModule != nullptr) - { - StreamlineHooks::hookCommon(commonModule); - } - else - { - LOG_ERROR("Trying to load dll as sl.common: {}", lcaseLibNameA); - } - - return commonModule; - } - - if (Config::Instance()->DisableOverlays.value_or_default() && CheckDllNameW(&lcaseLibName, &blockOverlayNamesW)) - { - LOG_DEBUG("Blocking overlay dll: {}", wstring_to_string(lcaseLibName)); - return (HMODULE) 1; - } - else if (CheckDllNameW(&lcaseLibName, &overlayNamesW)) - { - LOG_DEBUG("Overlay dll: {}", wstring_to_string(lcaseLibName)); - - // If we hook CreateSwapChainForHwnd & CreateSwapChainForCoreWindow here - // Order of CreateSwapChain calls become - // Game -> Overlay -> Opti - // and Overlays really does not like Opti's wrapped swapchain - // If we skip hooking here first Steam hook CreateSwapChainForHwnd & CreateSwapChainForCoreWindow - // Then hopefully Opti hook and call order become - // Game -> Opti -> Overlay - // And Opti menu works with Overlay without issues - - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - if (/*!_overlayMethodsCalled && */ DxgiProxy::Module() != nullptr) - { - CheckForGPU(); - - LOG_INFO("Calling CreateDxgiFactory methods for overlay!"); - IDXGIFactory* factory = nullptr; - IDXGIFactory1* factory1 = nullptr; - IDXGIFactory2* factory2 = nullptr; - - if (DxgiProxy::CreateDxgiFactory_()(__uuidof(factory), &factory) == S_OK && factory != nullptr) - { - LOG_DEBUG("CreateDxgiFactory ok"); - factory->Release(); - } - - if (DxgiProxy::CreateDxgiFactory1_()(__uuidof(factory1), &factory1) == S_OK && factory1 != nullptr) - { - LOG_DEBUG("CreateDxgiFactory1 ok"); - factory1->Release(); - } - - if (DxgiProxy::CreateDxgiFactory2_()(0, __uuidof(factory2), &factory2) == S_OK && - factory2 != nullptr) - { - LOG_DEBUG("CreateDxgiFactory2 ok"); - factory2->Release(); - } - - _overlayMethodsCalled = true; - } - - return module; - } - } - - // Hooks - if (CheckDllNameW(&lcaseLibName, &dx11NamesW) && Config::Instance()->OverlayMenu.value_or_default()) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HooksDx::HookDx11(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &dx12NamesW) && Config::Instance()->OverlayMenu.value_or_default()) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - D3d12Proxy::Init(module); - HooksDx::HookDx12(); - } - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &vkNamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - { - HookForVulkanSpoofing(module); - HookForVulkanExtensionSpoofing(module); - HookForVulkanVRAMSpoofing(module); - - HooksVk::HookVk(module); - } - - return module; - } - - if (!State::Instance().skipDxgiLoadChecks && CheckDllNameW(&lcaseLibName, &dxgiNamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - - if (module != nullptr) - { - DxgiProxy::Init(module); - - CheckForGPU(); - - if (Config::Instance()->DxgiSpoofing.value_or_default()) - HookDxgiForSpoofing(); - - if (Config::Instance()->OverlayMenu.value_or_default()) - HooksDx::HookDxgi(); - } - } - - if (CheckDllNameW(&lcaseLibName, &fsr2NamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR2Inputs(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &fsr2BENamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR2Dx12Inputs(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &fsr3NamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR3Inputs(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &fsr3BENamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - HookFSR3Dx12Inputs(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &xessNamesW)) - { - auto module = - LoadLibxess(lcaseLibName); // KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - XeSSProxy::HookXeSS(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &xessDx11NamesW)) - { - auto module = - LoadLibxessDx11(lcaseLibName); // KernelBaseProxy::LoadLibraryExA_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - XeSSProxy::HookXeSSDx11(module); - else - LOG_ERROR("Trying to load dll: {}", wstring_to_string(lcaseLibName)); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &ffxDx12NamesW)) - { - auto module = - LoadFfxapiDx12(lcaseLibName); // KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - FfxApiProxy::InitFfxDx12(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &ffxDx12UpscalerNamesW)) - { - auto module = KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - FSR4ModelSelection::Hook(module); - - return module; - } - - if (CheckDllNameW(&lcaseLibName, &ffxVkNamesW)) - { - auto module = - LoadFfxapiVk(lcaseLibName); // KernelBaseProxy::LoadLibraryExW_()(lcaseLibName.c_str(), NULL, 0); - - if (module != nullptr) - FfxApiProxy::InitFfxVk(module); - - return module; - } - - return nullptr; - } - static HMODULE LoadNvApi() { HMODULE nvapi = nullptr; if (Config::Instance()->OverrideNvapiDll.value_or_default() && Config::Instance()->NvapiDllPath.has_value()) { - nvapi = KernelBaseProxy::LoadLibraryExW_()(Config::Instance()->NvapiDllPath->c_str(), NULL, 0); + nvapi = NtdllProxy::LoadLibraryExW_Ldr(Config::Instance()->NvapiDllPath->c_str(), NULL, 0); if (nvapi != nullptr) { @@ -970,7 +83,7 @@ class KernelHooks if (Config::Instance()->OverrideNvapiDll.value_or_default() && nvapi == nullptr) { auto localPath = Util::DllPath().parent_path() / L"nvapi64.dll"; - nvapi = KernelBaseProxy::LoadLibraryExW_()(localPath.wstring().c_str(), NULL, 0); + nvapi = NtdllProxy::LoadLibraryExW_Ldr(localPath.wstring().c_str(), NULL, 0); if (nvapi != nullptr) { @@ -981,7 +94,7 @@ class KernelHooks if (nvapi == nullptr) { - nvapi = KernelBaseProxy::LoadLibraryExW_()(L"nvapi64.dll", NULL, 0); + nvapi = NtdllProxy::LoadLibraryExW_Ldr(L"nvapi64.dll", NULL, 0); if (nvapi != nullptr) { @@ -993,742 +106,11 @@ class KernelHooks return nullptr; } - static HMODULE LoadNvngxDlss(std::wstring originalPath) - { - HMODULE nvngxDlss = nullptr; - - if (Config::Instance()->NVNGX_DLSS_Library.has_value()) - { - nvngxDlss = - KernelBaseProxy::LoadLibraryExW_()(Config::Instance()->NVNGX_DLSS_Library.value().c_str(), NULL, 0); - - if (nvngxDlss != nullptr) - { - LOG_INFO("nvngx_dlss.dll loaded from {0}", - wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); - return nvngxDlss; - } - else - { - LOG_WARN("nvngx_dlss.dll can't found at {0}", - wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); - } - } - - if (nvngxDlss == nullptr) - { - nvngxDlss = KernelBaseProxy::LoadLibraryExW_()(originalPath.c_str(), NULL, 0); - - if (nvngxDlss != nullptr) - { - LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(originalPath)); - return nvngxDlss; - } - } - - return nullptr; - } - - static HMODULE LoadLibxess(std::wstring originalPath) - { - if (XeSSProxy::Module() != nullptr) - return XeSSProxy::Module(); - - HMODULE libxess = nullptr; - - if (Config::Instance()->XeSSLibrary.has_value()) - { - std::filesystem::path libPath(Config::Instance()->XeSSLibrary.value().c_str()); - - if (libPath.has_filename()) - libxess = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); - else - libxess = KernelBaseProxy::LoadLibraryExW_()((libPath / L"libxess.dll").c_str(), NULL, 0); - - if (libxess != nullptr) - { - LOG_INFO("libxess.dll loaded from {0}", wstring_to_string(Config::Instance()->XeSSLibrary.value())); - return libxess; - } - else - { - LOG_WARN("libxess.dll can't found at {0}", wstring_to_string(Config::Instance()->XeSSLibrary.value())); - } - } - - if (libxess == nullptr) - { - libxess = KernelBaseProxy::LoadLibraryExW_()(originalPath.c_str(), NULL, 0); - - if (libxess != nullptr) - { - LOG_INFO("libxess.dll loaded from {0}", wstring_to_string(originalPath)); - return libxess; - } - } - - return nullptr; - } - - static HMODULE LoadLibxessDx11(std::wstring originalPath) - { - if (XeSSProxy::ModuleDx11() != nullptr) - return XeSSProxy::ModuleDx11(); - - HMODULE libxess = nullptr; - - if (Config::Instance()->XeSSDx11Library.has_value()) - { - std::filesystem::path libPath(Config::Instance()->XeSSDx11Library.value().c_str()); - - if (libPath.has_filename()) - libxess = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); - else - libxess = KernelBaseProxy::LoadLibraryExW_()((libPath / L"libxess_dx11.dll").c_str(), NULL, 0); - - if (libxess != nullptr) - { - LOG_INFO("libxess_dx11.dll loaded from {0}", - wstring_to_string(Config::Instance()->XeSSDx11Library.value())); - return libxess; - } - else - { - LOG_WARN("libxess_dx11.dll can't found at {0}", - wstring_to_string(Config::Instance()->XeSSDx11Library.value())); - } - } - - if (libxess == nullptr) - { - libxess = KernelBaseProxy::LoadLibraryExW_()(originalPath.c_str(), NULL, 0); - - if (libxess != nullptr) - { - LOG_INFO("libxess_dx11.dll loaded from {0}", wstring_to_string(originalPath)); - return libxess; - } - } - - return nullptr; - } - - static HMODULE LoadFfxapiDx12(std::wstring originalPath) - { - if (FfxApiProxy::Dx12Module() != nullptr) - return FfxApiProxy::Dx12Module(); - - HMODULE ffxDx12 = nullptr; - - if (Config::Instance()->FfxDx12Path.has_value()) - { - std::filesystem::path libPath(Config::Instance()->FfxDx12Path.value().c_str()); - - if (libPath.has_filename()) - ffxDx12 = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); - else - ffxDx12 = KernelBaseProxy::LoadLibraryExW_()((libPath / L"amd_fidelityfx_dx12.dll").c_str(), NULL, 0); - - if (ffxDx12 != nullptr) - { - LOG_INFO("amd_fidelityfx_dx12.dll loaded from {0}", - wstring_to_string(Config::Instance()->FfxDx12Path.value())); - return ffxDx12; - } - else - { - LOG_WARN("amd_fidelityfx_dx12.dll can't found at {0}", - wstring_to_string(Config::Instance()->FfxDx12Path.value())); - } - } - - if (ffxDx12 == nullptr) - { - ffxDx12 = KernelBaseProxy::LoadLibraryExW_()(originalPath.c_str(), NULL, 0); - - if (ffxDx12 != nullptr) - { - LOG_INFO("amd_fidelityfx_dx12.dll loaded from {0}", wstring_to_string(originalPath)); - return ffxDx12; - } - } - - return nullptr; - } - - static HMODULE LoadFfxapiVk(std::wstring originalPath) - { - if (FfxApiProxy::VkModule() != nullptr) - return FfxApiProxy::VkModule(); - - HMODULE ffxVk = nullptr; - - if (Config::Instance()->FfxVkPath.has_value()) - { - std::filesystem::path libPath(Config::Instance()->FfxVkPath.value().c_str()); - - if (libPath.has_filename()) - ffxVk = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); - else - ffxVk = KernelBaseProxy::LoadLibraryExW_()((libPath / L"amd_fidelityfx_vk.dll").c_str(), NULL, 0); - - if (ffxVk != nullptr) - { - LOG_INFO("amd_fidelityfx_vk.dll loaded from {0}", - wstring_to_string(Config::Instance()->FfxVkPath.value())); - return ffxVk; - } - else - { - LOG_WARN("amd_fidelityfx_vk.dll can't found at {0}", - wstring_to_string(Config::Instance()->FfxVkPath.value())); - } - } - - if (ffxVk == nullptr) - { - ffxVk = KernelBaseProxy::LoadLibraryExW_()(originalPath.c_str(), NULL, 0); - - if (ffxVk != nullptr) - { - LOG_INFO("amd_fidelityfx_vk.dll loaded from {0}", wstring_to_string(originalPath)); - return ffxVk; - } - } - - return nullptr; - } - - static BOOL hk_K32_FreeLibrary(HMODULE lpLibrary) - { - if (lpLibrary == nullptr) - return FALSE; - - if (!State::Instance().isShuttingDown) - { - if (lpLibrary == dllModule) - { - LOG_WARN("Call for OptiScaler, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == FfxApiProxy::Dx12Module()) - { - LOG_WARN("Call for FFX Dx12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == FfxApiProxy::VkModule()) - { - LOG_WARN("Call for FFX Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == XeSSProxy::Module()) - { - LOG_WARN("Call for XeSS, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == DxgiProxy::Module()) - { - LOG_WARN("Call for DXGI, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == D3d12Proxy::Module()) - { - LOG_WARN("Call for D3D12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == Kernel32Proxy::Module()) - { - LOG_WARN("Call for Kernel32, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == KernelBaseProxy::Module()) - { - LOG_WARN("Call for KernelBase, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == vulkanModule) - { - LOG_WARN("Call for Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == d3d11Module) - { - LOG_WARN("Call for D3D11, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - } - - return o_K32_FreeLibrary(lpLibrary); - } - - static BOOL hk_KB_FreeLibrary(HMODULE lpLibrary) - { - if (lpLibrary == nullptr) - return FALSE; - - if (!State::Instance().isShuttingDown) - { - if (lpLibrary == dllModule) - { - LOG_WARN("Call for OptiScaler, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == FfxApiProxy::Dx12Module()) - { - LOG_WARN("Call for FFX Dx12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == FfxApiProxy::VkModule()) - { - LOG_WARN("Call for FFX Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == XeSSProxy::Module()) - { - LOG_WARN("Call for XeSS, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == DxgiProxy::Module()) - { - LOG_WARN("Call for DXGI, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == D3d12Proxy::Module()) - { - LOG_WARN("Call for D3D12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == Kernel32Proxy::Module()) - { - LOG_WARN("Call for Kernel32, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == KernelBaseProxy::Module()) - { - LOG_WARN("Call for KernelBase, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == vulkanModule) - { - LOG_WARN("Call for Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - else if (lpLibrary == d3d11Module) - { - LOG_WARN("Call for D3D11, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); - return TRUE; - } - } - - return o_KB_FreeLibrary(lpLibrary); - } - - static HMODULE hk_KB_LoadLibraryA(LPCSTR lpLibFileName) - { - if (lpLibFileName == nullptr) - return NULL; - - std::string libName(lpLibFileName); - std::string lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::tolower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_KB_LoadLibraryA(lpLibFileName); - } - - auto dllName = State::SkipDllName(); - auto pos = lcaseLibName.rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_KB_LoadLibraryA(lpLibFileName); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", lcaseLibName, Util::WhoIsTheCaller(_ReturnAddress())); -#endif - auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - return o_KB_LoadLibraryA(lpLibFileName); - } - - static HMODULE hk_KB_LoadLibraryW(LPCWSTR lpLibFileName) - { - if (lpLibFileName == nullptr) - return NULL; - - std::wstring libName(lpLibFileName); - std::wstring lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::towlower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_KB_LoadLibraryW(lpLibFileName); - } - - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_KB_LoadLibraryW(lpLibFileName); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - return o_KB_LoadLibraryW(lpLibFileName); - } - - static HMODULE hk_KB_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) - { - if (lpLibFileName == nullptr) - return NULL; - - std::string libName(lpLibFileName); - std::string lcaseLibName(libName); - -#if _DEBUG - LOG_TRACE("{}, caller: {}", lcaseLibName, Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::tolower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_KB_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - } - - auto dllName = State::SkipDllName(); - auto pos = lcaseLibName.rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_KB_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - } - } - - auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - auto result = o_KB_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - return result; - } - - static HMODULE hk_KB_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) - { - if (lpLibFileName == nullptr) - return NULL; - - std::wstring libName(lpLibFileName); - std::wstring lcaseLibName(libName); - -#if _DEBUG - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::towlower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_KB_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - } - - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_KB_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - } - } - - auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - auto result = o_KB_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - return result; - } - - static HMODULE hk_K32_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) - { - if (lpLibFileName == nullptr) - return NULL; - - std::string libName(lpLibFileName); - std::string lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::tolower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_K32_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - } - - auto dllName = State::SkipDllName(); - auto pos = lcaseLibName.rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_K32_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", lcaseLibName, Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - auto result = o_K32_LoadLibraryExA(lpLibFileName, hFile, dwFlags); - return result; - } - - static HMODULE hk_K32_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) - { - if (lpLibFileName == nullptr) - return NULL; - - std::wstring libName(lpLibFileName); - std::wstring lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::tolower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_K32_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - } - - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_K32_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - auto result = o_K32_LoadLibraryExW(lpLibFileName, hFile, dwFlags); - return result; - } - - static HMODULE hk_K32_LoadLibraryA(LPCSTR lpLibFileName) - { - if (lpLibFileName == nullptr) - return NULL; - - std::string libName(lpLibFileName); - std::string lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::tolower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_K32_LoadLibraryA(lpLibFileName); - } - - auto dllName = State::SkipDllName(); - auto pos = lcaseLibName.rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", lcaseLibName); - return o_K32_LoadLibraryA(lpLibFileName); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", lcaseLibName, Util::WhoIsTheCaller(_ReturnAddress())); -#endif - auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - return o_K32_LoadLibraryA(lpLibFileName); - } - - static HMODULE hk_K32_LoadLibraryW(LPCWSTR lpLibFileName) - { - if (lpLibFileName == nullptr) - return NULL; - - std::wstring libName(lpLibFileName); - std::wstring lcaseLibName(libName); - - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::towlower(lcaseLibName[i]); - - if (State::SkipDllChecks()) - { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_K32_LoadLibraryW(lpLibFileName); - } - - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_K32_LoadLibraryW(lpLibFileName); - } - } - -#if _DEBUG - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); -#endif - - auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); - - // skip loading of dll - if (moduleHandle == (HMODULE) 1) - { - SetLastError(ERROR_ACCESS_DENIED); - return NULL; - } - - if (moduleHandle != nullptr) - return moduleHandle; - - return o_K32_LoadLibraryW(lpLibFileName); - } - static constexpr HMODULE amdxc64Mark = HMODULE(0xFFFFFFFF13372137); - static FARPROC hk_K32_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) + static FARPROC WINAPI hk_K32_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) { + if ((size_t) lpProcName < 0x000000000000F000) { if (hModule == dllModule) @@ -1743,6 +125,15 @@ class KernelHooks Util::WhoIsTheCaller(_ReturnAddress())); } + std::string pName(lpProcName); + + if (pName == "xessDestroyContext") + { + LOG_DEBUG("XeSSProxy: {:X}", (size_t) XeSSProxy::Module()); + LOG_DEBUG("Address: {:X}", (size_t) o_K32_GetModuleHandleA("libxess.dll")); + LOG_DEBUG("HERE!"); + } + // FSR 4 Init in case of missing amdxc64.dll // 2nd check is amdxcffx64.dll trying to queue amdxc64 but amdxc64 not being loaded if (lpProcName != nullptr && (hModule == amdxc64Mark || hModule == nullptr) && @@ -1761,7 +152,7 @@ class KernelHooks return o_K32_GetProcAddress(hModule, lpProcName); } - static HMODULE hk_K32_GetModuleHandleA(LPCSTR lpModuleName) + static HMODULE WINAPI hk_K32_GetModuleHandleA(LPCSTR lpModuleName) { if (lpModuleName != NULL) { @@ -1795,7 +186,7 @@ class KernelHooks return o_K32_GetModuleHandleA(lpModuleName); } - static BOOL hk_K32_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule) + static BOOL WINAPI hk_K32_GetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule) { if (lpModuleName && dwFlags == GET_MODULE_HANDLE_EX_FLAG_PIN && lstrcmpW(L"nvapi64.dll", lpModuleName) == 0 && phModule) @@ -1808,14 +199,14 @@ class KernelHooks return o_K32_GetModuleHandleExW(dwFlags, lpModuleName, phModule); } - static FARPROC hk_KB_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) + static FARPROC WINAPI hk_KB_GetProcAddress(HMODULE hModule, LPCSTR lpProcName) { if ((size_t) lpProcName < 0x000000000000F000) { if (hModule == dllModule) LOG_TRACE("Ordinal call: {:X}", (size_t) lpProcName); - return o_K32_GetProcAddress(hModule, lpProcName); + return o_KB_GetProcAddress(hModule, lpProcName); } if (hModule == dllModule && lpProcName != nullptr) @@ -1864,7 +255,7 @@ class KernelHooks return false; } - static DWORD hk_K32_GetFileAttributesW(LPCWSTR lpFileName) + static DWORD WINAPI hk_K32_GetFileAttributesW(LPCWSTR lpFileName) { if (!State::Instance().nvngxExists && State::Instance().nvngxReplacement.has_value() && (Config::Instance()->DxgiSpoofing.value_or_default() || @@ -1884,9 +275,9 @@ class KernelHooks return o_K32_GetFileAttributesW(lpFileName); } - static HANDLE hk_K32_CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) + static HANDLE WINAPI hk_K32_CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { if (!State::Instance().nvngxExists && State::Instance().nvngxReplacement.has_value() && (Config::Instance()->DxgiSpoofing.value_or_default() || @@ -1918,11 +309,6 @@ class KernelHooks LOG_DEBUG(""); - o_K32_FreeLibrary = Kernel32Proxy::Hook_FreeLibrary(hk_K32_FreeLibrary); - o_K32_LoadLibraryA = Kernel32Proxy::Hook_LoadLibraryA(hk_K32_LoadLibraryA); - o_K32_LoadLibraryW = Kernel32Proxy::Hook_LoadLibraryW(hk_K32_LoadLibraryW); - o_K32_LoadLibraryExA = Kernel32Proxy::Hook_LoadLibraryExA(hk_K32_LoadLibraryExA); - o_K32_LoadLibraryExW = Kernel32Proxy::Hook_LoadLibraryExW(hk_K32_LoadLibraryExW); o_K32_GetProcAddress = Kernel32Proxy::Hook_GetProcAddress(hk_K32_GetProcAddress); o_K32_GetModuleHandleA = Kernel32Proxy::Hook_GetModuleHandleA(hk_K32_GetModuleHandleA); o_K32_GetModuleHandleExW = Kernel32Proxy::Hook_GetModuleHandleExW(hk_K32_GetModuleHandleExW); @@ -1937,17 +323,6 @@ class KernelHooks LOG_DEBUG(""); - // These hooks cause stability regressions - // o_KB_FreeLibrary = KernelBaseProxy::Hook_FreeLibrary(hk_KB_FreeLibrary); - - if (State::Instance().gameQuirks & GameQuirk::KernelBaseHooks) - { - // o_KB_LoadLibraryA = KernelBaseProxy::Hook_LoadLibraryA(hk_KB_LoadLibraryA); - // o_KB_LoadLibraryW = KernelBaseProxy::Hook_LoadLibraryW(hk_KB_LoadLibraryW); - // o_KB_LoadLibraryExA = KernelBaseProxy::Hook_LoadLibraryExA(hk_KB_LoadLibraryExA); - o_KB_LoadLibraryExW = KernelBaseProxy::Hook_LoadLibraryExW(hk_KB_LoadLibraryExW); - } - o_KB_GetProcAddress = KernelBaseProxy::Hook_GetProcAddress(hk_KB_GetProcAddress); } }; diff --git a/OptiScaler/hooks/Ntdll_Hooks.h b/OptiScaler/hooks/Ntdll_Hooks.h index 43bc0553..14b542e0 100644 --- a/OptiScaler/hooks/Ntdll_Hooks.h +++ b/OptiScaler/hooks/Ntdll_Hooks.h @@ -7,37 +7,45 @@ #include #include -#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include #include -#include #pragma intrinsic(_ReturnAddress) class NtdllHooks { private: - typedef struct _UNICODE_STRING - { - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; - } UNICODE_STRING, *PUNICODE_STRING; - - typedef NTSTATUS(NTAPI* PFN_LdrLoadDll)(PWSTR PathToFile OPTIONAL, PULONG Flags OPTIONAL, - PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle); - - typedef NTSTATUS(NTAPI* PFN_NtLoadDll)(PUNICODE_STRING PathToFile OPTIONAL, PULONG Flags OPTIONAL, - PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle); - - inline static PFN_LdrLoadDll o_LdrLoadDll = nullptr; - inline static PFN_NtLoadDll o_NtLoadDll = nullptr; + inline static NtdllProxy::PFN_NtLoadDll o_NtLoadDll = nullptr; + inline static NtdllProxy::PFN_LdrLoadDll o_LdrLoadDll = nullptr; + inline static NtdllProxy::PFN_LdrUnloadDll o_LdrUnloadDll = nullptr; inline static bool _overlayMethodsCalled = false; - inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName) + static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName, LPCWSTR lpLibFullPath) { auto lcaseLibNameA = wstring_to_string(lcaseLibName); + LOG_TRACE("{}", lcaseLibNameA); + + // C:\\Path\\like\\this.dll + auto normalizedPath = std::filesystem::path(lcaseLibName).lexically_normal().string(); // If Opti is not loading as nvngx.dll if (!State::Instance().isWorkingAsNvngx) @@ -55,57 +63,725 @@ class NtdllHooks { LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibNameA); + // if (!dontCount) + // loadCount++; + return dllModule; } } + if (!State::Instance().isWorkingAsNvngx && + (!State::Instance().isDxgiMode || !State::Instance().skipDxgiLoadChecks) && + CheckDllNameW(&lcaseLibName, &dllNamesW)) + { + if (!State::Instance().ServeOriginal()) + { + LOG_INFO("{} call, returning this dll!", lcaseLibNameA); + return dllModule; + } + else + { + LOG_INFO("{} call, ServeOriginal active returning original dll!", lcaseLibNameA); + return originalModule; + } + } + + // nvngx_dlss + if (Config::Instance()->DLSSEnabled.value_or_default() && Config::Instance()->NVNGX_DLSS_Library.has_value() && + CheckDllNameW(&lcaseLibName, &nvngxDlssNamesW)) + { + auto nvngxDlss = LoadNvngxDlss(lcaseLibName); + + if (nvngxDlss != nullptr) + return nvngxDlss; + else + LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); + } + + // NGX OTA + // Try to catch something like this: + // c:\programdata/nvidia/ngx/models//dlss/versions/20316673/files/160_e658700.bin + if (lcaseLibName.ends_with(L".bin")) + { + auto loadedBin = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (loadedBin && normalizedPath.contains("\\versions\\")) + { + if (normalizedPath.contains("\\dlss\\")) + { + State::Instance().NGX_OTA_Dlss = wstring_to_string(lpLibFullPath); + } + + if (normalizedPath.contains("\\dlssd\\")) + { + State::Instance().NGX_OTA_Dlssd = wstring_to_string(lpLibFullPath); + } + } + return loadedBin; + } + + // NvApi64.dll + if (CheckDllNameW(&lcaseLibName, &nvapiNamesW)) + { + if (Config::Instance()->OverrideNvapiDll.value_or_default()) + { + LOG_INFO("{0} call!", lcaseLibNameA); + + auto nvapi = LoadNvApi(); + + // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded + if (nvapi != nullptr) + { + NvApiHooks::Hook(nvapi); + return nvapi; + } + } + else + { + auto nvapi = GetModuleHandleW(lcaseLibName.c_str()); + + // Try to load nvapi only from system32, like the original call would + if (nvapi == nullptr) + { + nvapi = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + + if (nvapi != nullptr) + NvApiHooks::Hook(nvapi); + + // AMD without nvapi override should fall through + } + } + + // sl.interposer.dll + if (CheckDllNameW(&lcaseLibName, &slInterposerNamesW)) + { + auto streamlineModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (streamlineModule != nullptr) + { + StreamlineHooks::hookInterposer(streamlineModule); + } + else + { + LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); + } + + return streamlineModule; + } + + // sl.dlss.dll + // Try to catch something like this: + // C:\ProgramData/NVIDIA/NGX/models/sl_dlss_0/versions/133120/files/190_E658703.dll + if (CheckDllNameW(&lcaseLibName, &slDlssNamesW) || + (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_dlss_0"))) + { + auto dlssModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (dlssModule != nullptr) + { + StreamlineHooks::hookDlss(dlssModule); + } + else + { + LOG_ERROR("Trying to load dll as sl.dlss: {}", lcaseLibNameA); + } + + return dlssModule; + } + + // sl.dlss_g.dll + if (CheckDllNameW(&lcaseLibName, &slDlssgNamesW) || + (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_dlss_g_"))) + { + auto dlssgModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (dlssgModule != nullptr) + { + StreamlineHooks::hookDlssg(dlssgModule); + } + else + { + LOG_ERROR("Trying to load dll as sl.dlss_g: {}", lcaseLibNameA); + } + + return dlssgModule; + } + + // sl.reflex.dll + if (CheckDllNameW(&lcaseLibName, &slReflexNamesW) || + (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_reflex_"))) + { + auto reflexModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (reflexModule != nullptr) + { + StreamlineHooks::hookReflex(reflexModule); + } + else + { + LOG_ERROR("Trying to load dll as sl.reflex: {}", lcaseLibNameA); + } + + return reflexModule; + } + + // sl.pcl.dll + if (CheckDllNameW(&lcaseLibName, &slPclNamesW) || + (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_pcl_"))) + { + auto pclModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (pclModule != nullptr) + { + StreamlineHooks::hookPcl(pclModule); + } + else + { + LOG_ERROR("Trying to load dll as sl.pcl: {}", lcaseLibNameA); + } + + return pclModule; + } + + // sl.common.dll + if (CheckDllNameW(&lcaseLibName, &slCommonNamesW) || + (normalizedPath.contains("\\versions\\") && normalizedPath.contains("\\sl_common_"))) + { + auto commonModule = NtdllProxy::LoadLibraryExW_Ldr(lpLibFullPath, NULL, 0); + + if (commonModule != nullptr) + { + StreamlineHooks::hookCommon(commonModule); + } + else + { + LOG_ERROR("Trying to load dll as sl.common: {}", lcaseLibNameA); + } + + return commonModule; + } + + if (Config::Instance()->DisableOverlays.value_or_default() && CheckDllNameW(&lcaseLibName, &blockOverlayNamesW)) + { + LOG_DEBUG("Blocking overlay dll: {}", wstring_to_string(lcaseLibName)); + return (HMODULE) 1337; + } + else if (CheckDllNameW(&lcaseLibName, &overlayNamesW)) + { + LOG_DEBUG("Overlay dll: {}", wstring_to_string(lcaseLibName)); + + // If we hook CreateSwapChainForHwnd & CreateSwapChainForCoreWindow here + // Order of CreateSwapChain calls become + // Game -> Overlay -> Opti + // and Overlays really does not like Opti's wrapped swapchain + // If we skip hooking here first Steam hook CreateSwapChainForHwnd & CreateSwapChainForCoreWindow + // Then hopefully Opti hook and call order become + // Game -> Opti -> Overlay + // And Opti menu works with Overlay without issues + + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + { + if (/*!_overlayMethodsCalled && */ DxgiProxy::Module() != nullptr) + { + LOG_INFO("Calling CreateDxgiFactory methods for overlay!"); + IDXGIFactory* factory = nullptr; + IDXGIFactory1* factory1 = nullptr; + IDXGIFactory2* factory2 = nullptr; + + if (DxgiProxy::CreateDxgiFactory_()(__uuidof(factory), &factory) == S_OK && factory != nullptr) + { + LOG_DEBUG("CreateDxgiFactory ok"); + factory->Release(); + } + + if (DxgiProxy::CreateDxgiFactory1_()(__uuidof(factory1), &factory1) == S_OK && factory1 != nullptr) + { + LOG_DEBUG("CreateDxgiFactory1 ok"); + factory1->Release(); + } + + if (DxgiProxy::CreateDxgiFactory2_()(0, __uuidof(factory2), &factory2) == S_OK && + factory2 != nullptr) + { + LOG_DEBUG("CreateDxgiFactory2 ok"); + factory2->Release(); + } + + _overlayMethodsCalled = true; + } + + return module; + } + } + + // Hooks + if (CheckDllNameW(&lcaseLibName, &dx11NamesW) && Config::Instance()->OverlayMenu.value_or_default()) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + HooksDx::HookDx11(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &dx12NamesW) && Config::Instance()->OverlayMenu.value_or_default()) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + { + D3d12Proxy::Init(module); + HooksDx::HookDx12(); + } + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &vkNamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + { + HookForVulkanSpoofing(module); + HookForVulkanExtensionSpoofing(module); + HookForVulkanVRAMSpoofing(module); + + HooksVk::HookVk(module); + } + + return module; + } + + if (!State::Instance().skipDxgiLoadChecks && CheckDllNameW(&lcaseLibName, &dxgiNamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + + if (module != nullptr) + { + DxgiProxy::Init(module); + + if (Config::Instance()->DxgiSpoofing.value_or_default()) + HookDxgiForSpoofing(); + + if (Config::Instance()->OverlayMenu.value_or_default()) + HooksDx::HookDxgi(); + } + } + + if (CheckDllNameW(&lcaseLibName, &fsr2NamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + HookFSR2Inputs(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &fsr2BENamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + HookFSR2Dx12Inputs(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &fsr3NamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + HookFSR3Inputs(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &fsr3BENamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + if (module != nullptr) + HookFSR3Dx12Inputs(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &xessNamesW)) + { + auto module = LoadLibxess(lcaseLibName); + + LOG_DEBUG("Libxess: {:X}", (size_t) module); + + if (module != nullptr) + XeSSProxy::HookXeSS(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &xessDx11NamesW)) + { + auto module = LoadLibxessDx11(lcaseLibName); + + if (module != nullptr) + XeSSProxy::HookXeSSDx11(module); + else + LOG_ERROR("Trying to load dll: {}", wstring_to_string(lcaseLibName)); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &ffxDx12NamesW)) + { + auto module = LoadFfxapiDx12(lcaseLibName); + + if (module != nullptr) + FfxApiProxy::InitFfxDx12(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &ffxDx12UpscalerNamesW)) + { + auto module = NtdllProxy::LoadLibraryExW_Ldr(lcaseLibName.c_str(), NULL, 0); + + FSR4ModelSelection::Hook(module); + + return module; + } + + if (CheckDllNameW(&lcaseLibName, &ffxVkNamesW)) + { + auto module = LoadFfxapiVk(lcaseLibName); + + if (module != nullptr) + FfxApiProxy::InitFfxVk(module); + + return module; + } + + return nullptr; + } + + static HMODULE LoadNvApi() + { + HMODULE nvapi = nullptr; + + if (Config::Instance()->NvapiDllPath.has_value()) + { + nvapi = NtdllProxy::LoadLibraryExW_Ldr(Config::Instance()->NvapiDllPath->c_str(), NULL, 0); + + if (nvapi != nullptr) + { + LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(Config::Instance()->NvapiDllPath.value())); + return nvapi; + } + } + + if (nvapi == nullptr) + { + auto localPath = Util::DllPath().parent_path() / L"nvapi64.dll"; + nvapi = NtdllProxy::LoadLibraryExW_Ldr(localPath.wstring().c_str(), NULL, 0); + + if (nvapi != nullptr) + { + LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(localPath.wstring())); + return nvapi; + } + } + + if (nvapi == nullptr) + { + nvapi = NtdllProxy::LoadLibraryExW_Ldr(L"nvapi64.dll", NULL, 0); + + if (nvapi != nullptr) + { + LOG_WARN("nvapi64.dll loaded from system!"); + return nvapi; + } + } + return nullptr; } - static std::wstring UnicodeStringToWString(const UNICODE_STRING& us) + static HMODULE LoadNvngxDlss(std::wstring originalPath) { - size_t charCount = us.Length / sizeof(wchar_t); - return std::wstring(us.Buffer, charCount); + HMODULE nvngxDlss = nullptr; + + if (Config::Instance()->NVNGX_DLSS_Library.has_value()) + { + nvngxDlss = NtdllProxy::LoadLibraryExW_Ldr(Config::Instance()->NVNGX_DLSS_Library.value().c_str(), NULL, 0); + + if (nvngxDlss != nullptr) + { + LOG_INFO("nvngx_dlss.dll loaded from {0}", + wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); + return nvngxDlss; + } + else + { + LOG_WARN("nvngx_dlss.dll can't found at {0}", + wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); + } + } + + if (nvngxDlss == nullptr) + { + nvngxDlss = NtdllProxy::LoadLibraryExW_Ldr(originalPath.c_str(), NULL, 0); + + if (nvngxDlss != nullptr) + { + LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(originalPath)); + return nvngxDlss; + } + } + + return nullptr; + } + + static HMODULE LoadLibxess(std::wstring originalPath) + { + if (XeSSProxy::Module() != nullptr) + return XeSSProxy::Module(); + + HMODULE libxess = nullptr; + + if (Config::Instance()->XeSSLibrary.has_value()) + { + std::filesystem::path libPath(Config::Instance()->XeSSLibrary.value().c_str()); + + if (libPath.has_filename()) + libxess = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); + else + libxess = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"libxess.dll").c_str(), NULL, 0); + + if (libxess != nullptr) + { + LOG_INFO("libxess.dll loaded from {0}", wstring_to_string(Config::Instance()->XeSSLibrary.value())); + return libxess; + } + else + { + LOG_WARN("libxess.dll can't found at {0}", wstring_to_string(Config::Instance()->XeSSLibrary.value())); + } + } + + if (libxess == nullptr) + { + libxess = NtdllProxy::LoadLibraryExW_Ldr(originalPath.c_str(), NULL, 0); + + if (libxess != nullptr) + { + LOG_INFO("libxess.dll loaded from {0}", wstring_to_string(originalPath)); + return libxess; + } + } + + return nullptr; + } + + static HMODULE LoadLibxessDx11(std::wstring originalPath) + { + if (XeSSProxy::ModuleDx11() != nullptr) + return XeSSProxy::ModuleDx11(); + + HMODULE libxess = nullptr; + + if (Config::Instance()->XeSSDx11Library.has_value()) + { + std::filesystem::path libPath(Config::Instance()->XeSSDx11Library.value().c_str()); + + if (libPath.has_filename()) + libxess = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); + else + libxess = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"libxess_dx11.dll").c_str(), NULL, 0); + + if (libxess != nullptr) + { + LOG_INFO("libxess_dx11.dll loaded from {0}", + wstring_to_string(Config::Instance()->XeSSDx11Library.value())); + return libxess; + } + else + { + LOG_WARN("libxess_dx11.dll can't found at {0}", + wstring_to_string(Config::Instance()->XeSSDx11Library.value())); + } + } + + if (libxess == nullptr) + { + libxess = NtdllProxy::LoadLibraryExW_Ldr(originalPath.c_str(), NULL, 0); + + if (libxess != nullptr) + { + LOG_INFO("libxess_dx11.dll loaded from {0}", wstring_to_string(originalPath)); + return libxess; + } + } + + return nullptr; + } + + static HMODULE LoadFfxapiDx12(std::wstring originalPath) + { + if (FfxApiProxy::Dx12Module() != nullptr) + return FfxApiProxy::Dx12Module(); + + HMODULE ffxDx12 = nullptr; + + if (Config::Instance()->FfxDx12Path.has_value()) + { + std::filesystem::path libPath(Config::Instance()->FfxDx12Path.value().c_str()); + + if (libPath.has_filename()) + ffxDx12 = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); + else + ffxDx12 = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"amd_fidelityfx_dx12.dll").c_str(), NULL, 0); + + if (ffxDx12 != nullptr) + { + LOG_INFO("amd_fidelityfx_dx12.dll loaded from {0}", + wstring_to_string(Config::Instance()->FfxDx12Path.value())); + return ffxDx12; + } + else + { + LOG_WARN("amd_fidelityfx_dx12.dll can't found at {0}", + wstring_to_string(Config::Instance()->FfxDx12Path.value())); + } + } + + if (ffxDx12 == nullptr) + { + ffxDx12 = NtdllProxy::LoadLibraryExW_Ldr(originalPath.c_str(), NULL, 0); + + if (ffxDx12 != nullptr) + { + LOG_INFO("amd_fidelityfx_dx12.dll loaded from {0}", wstring_to_string(originalPath)); + return ffxDx12; + } + } + + return nullptr; + } + + static HMODULE LoadFfxapiVk(std::wstring originalPath) + { + if (FfxApiProxy::VkModule() != nullptr) + return FfxApiProxy::VkModule(); + + HMODULE ffxVk = nullptr; + + if (Config::Instance()->FfxVkPath.has_value()) + { + std::filesystem::path libPath(Config::Instance()->FfxVkPath.value().c_str()); + + if (libPath.has_filename()) + ffxVk = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); + else + ffxVk = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"amd_fidelityfx_vk.dll").c_str(), NULL, 0); + + if (ffxVk != nullptr) + { + LOG_INFO("amd_fidelityfx_vk.dll loaded from {0}", + wstring_to_string(Config::Instance()->FfxVkPath.value())); + return ffxVk; + } + else + { + LOG_WARN("amd_fidelityfx_vk.dll can't found at {0}", + wstring_to_string(Config::Instance()->FfxVkPath.value())); + } + } + + if (ffxVk == nullptr) + { + ffxVk = NtdllProxy::LoadLibraryExW_Ldr(originalPath.c_str(), NULL, 0); + + if (ffxVk != nullptr) + { + LOG_INFO("amd_fidelityfx_vk.dll loaded from {0}", wstring_to_string(originalPath)); + return ffxVk; + } + } + + return nullptr; + } + + static inline bool EndsWithInsensitive(std::wstring_view text, std::wstring_view suffix) + { + if (suffix.size() > text.size()) + return false; + if (suffix.empty()) + return true; + + const wchar_t* tail = text.data() + (text.size() - suffix.size()); + const int res = + CompareStringOrdinal(tail, static_cast(suffix.size()), suffix.data(), static_cast(suffix.size()), + TRUE); // case-insensitive + return res == CSTR_EQUAL; + } + + static inline bool EndsWithInsensitive(const UNICODE_STRING& text, std::wstring_view suffix) + { + return EndsWithInsensitive( + std::wstring_view { text.Buffer, static_cast(text.Length) / sizeof(wchar_t) }, suffix); + } + + static inline bool IsApiSetName(const std::wstring_view& n) + { + return n.rfind(L"api-ms-win-", 0) == 0 || n.rfind(L"ext-ms-", 0) == 0 || n.rfind(L"api-ms-onecore-", 0) == 0; } static NTSTATUS NTAPI hkLdrLoadDll(PWSTR PathToFile, PULONG Flags, PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle) { - if (ModuleFileName == nullptr || ModuleFileName->Length == 0) + if (ModuleHandle == nullptr) + return STATUS_INVALID_PARAMETER; + + if (ModuleFileName == nullptr || ModuleFileName->Length == 0 || State::Instance().isShuttingDown) return o_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); - std::wstring libName = UnicodeStringToWString(*ModuleFileName); - std::wstring lcaseLibName(libName); + std::wstring_view name(ModuleFileName->Buffer, ModuleFileName->Length / sizeof(wchar_t)); - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::towlower(lcaseLibName[i]); + if (IsApiSetName(name)) + return o_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); if (State::SkipDllChecks()) { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); - } + const std::wstring skip = string_to_wstring(State::SkipDllName()); - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) + if (skip.empty() || EndsWithInsensitive(name, std::wstring_view(skip)) || + EndsWithInsensitive(name, std::wstring(skip + L".dll"))) { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); + LOG_TRACE("Skip checks for: {}", wstring_to_string(name.data())); return o_LdrLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); } } - auto moduleHandle = LoadLibraryCheckW(lcaseLibName); +#ifdef _DEBUG + LOG_TRACE("{}", wstring_to_string(name.data())); +#endif + + auto moduleHandle = LoadLibraryCheckW(name.data(), name.data()); + + // skip loading of dll + if (moduleHandle == (HMODULE) 1337) + { + return STATUS_DLL_NOT_FOUND; + } if (moduleHandle != nullptr) { - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); + LOG_TRACE("{}, caller: {}", wstring_to_string(name.data()), Util::WhoIsTheCaller(_ReturnAddress())); *ModuleHandle = (HANDLE) moduleHandle; return (NTSTATUS) 0x00000000L; } @@ -116,40 +792,50 @@ class NtdllHooks static NTSTATUS NTAPI hkNtLoadDll(PUNICODE_STRING PathToFile, PULONG Flags, PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle) { - if (ModuleFileName == nullptr || ModuleFileName->Length == 0) + if (ModuleHandle == nullptr) + return STATUS_INVALID_PARAMETER; + + if (ModuleFileName == nullptr || ModuleFileName->Length == 0 || State::Instance().isShuttingDown) return o_NtLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); - std::wstring libName = UnicodeStringToWString(*ModuleFileName); - std::wstring lcaseLibName(libName); + std::wstring_view name(ModuleFileName->Buffer, ModuleFileName->Length / sizeof(wchar_t)); - for (size_t i = 0; i < lcaseLibName.size(); i++) - lcaseLibName[i] = std::towlower(lcaseLibName[i]); + if (IsApiSetName(name)) + return o_NtLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); + + std::wstring_view path; + if (PathToFile == nullptr || PathToFile->Length == 0) + path = name; + else + path = std::wstring_view(PathToFile->Buffer, PathToFile->Length / sizeof(wchar_t)); if (State::SkipDllChecks()) { - if (State::SkipDllName() == "") - { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); - return o_NtLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); - } + const std::wstring skip = string_to_wstring(State::SkipDllName()); - auto dllName = State::SkipDllName(); - auto pos = wstring_to_string(lcaseLibName).rfind(dllName); - - // -4 for extension `.dll` - if (pos == (lcaseLibName.length() - dllName.length()) || - pos == (lcaseLibName.length() - dllName.length() - 4)) + if (skip.empty() || EndsWithInsensitive(name, std::wstring_view(skip)) || + EndsWithInsensitive(name, std::wstring(skip + L".dll"))) { - LOG_TRACE("Skip checks for: {}", wstring_to_string(lcaseLibName)); + LOG_TRACE("Skip checks for: {}", wstring_to_string(name.data())); return o_NtLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); } } - auto moduleHandle = LoadLibraryCheckW(lcaseLibName); +#ifdef _DEBUG + LOG_TRACE("{}", wstring_to_string(name.data())); +#endif + + auto moduleHandle = LoadLibraryCheckW(name.data(), path.data()); + + // skip loading of dll + if (moduleHandle == (HMODULE) 1337) + { + return STATUS_DLL_NOT_FOUND; + } if (moduleHandle != nullptr) { - LOG_TRACE("{}, caller: {}", wstring_to_string(lcaseLibName), Util::WhoIsTheCaller(_ReturnAddress())); + LOG_TRACE("{}, caller: {}", wstring_to_string(name.data()), Util::WhoIsTheCaller(_ReturnAddress())); *ModuleHandle = (HANDLE) moduleHandle; return (NTSTATUS) 0x00000000L; } @@ -157,41 +843,99 @@ class NtdllHooks return o_NtLoadDll(PathToFile, Flags, ModuleFileName, ModuleHandle); } + static NTSTATUS NTAPI hkLdrUnloadDll(PVOID lpLibrary) + { + if (lpLibrary == nullptr) + return STATUS_INVALID_PARAMETER; + +#ifdef _DEBUG + LOG_TRACE("{:X}", (size_t) lpLibrary); +#endif + + if (!State::Instance().isShuttingDown) + { + if (lpLibrary == dllModule) + { + LOG_WARN("Call for OptiScaler, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == FfxApiProxy::Dx12Module()) + { + LOG_WARN("Call for FFX Dx12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == FfxApiProxy::VkModule()) + { + LOG_WARN("Call for FFX Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == XeSSProxy::Module()) + { + LOG_WARN("Call for XeSS, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == DxgiProxy::Module()) + { + LOG_WARN("Call for DXGI, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == D3d12Proxy::Module()) + { + LOG_WARN("Call for D3D12, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == Kernel32Proxy::Module()) + { + LOG_WARN("Call for Kernel32, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == KernelBaseProxy::Module()) + { + LOG_WARN("Call for KernelBase, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == NtdllProxy::Module()) + { + LOG_WARN("Call for ntdll, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == vulkanModule) + { + LOG_WARN("Call for Vulkan, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + else if (lpLibrary == d3d11Module) + { + LOG_WARN("Call for D3D11, caller: {}", Util::WhoIsTheCaller(_ReturnAddress())); + State::Instance().modulesToFree.insert(lpLibrary); + return TRUE; + } + } + + return o_LdrUnloadDll(lpLibrary); + } + public: static void Hook() { if (o_LdrLoadDll != nullptr) return; - HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); - - if (ntdll == nullptr) + if (NtdllProxy::Module() == nullptr) return; - o_LdrLoadDll = (PFN_LdrLoadDll) GetProcAddress(ntdll, "LdrLoadDll"); - o_NtLoadDll = (PFN_NtLoadDll) GetProcAddress(ntdll, "NtLoadDll"); - - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - - if (o_LdrLoadDll != nullptr) - DetourAttach(&(PVOID&) o_LdrLoadDll, hkLdrLoadDll); - - if (o_NtLoadDll != nullptr) - DetourAttach(&(PVOID&) o_NtLoadDll, hkNtLoadDll); - - DetourTransactionCommit(); - } - - static void UnHook() - { - if (o_LdrLoadDll == nullptr) - return; - - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); - DetourDetach(&(PVOID&) o_LdrLoadDll, hkLdrLoadDll); - DetourDetach(&(PVOID&) o_NtLoadDll, hkNtLoadDll); - DetourTransactionCommit(); + o_NtLoadDll = NtdllProxy::Hook_NtLoadDll(hkNtLoadDll); + o_LdrLoadDll = NtdllProxy::Hook_LdrLoadDll(hkLdrLoadDll); + o_LdrUnloadDll = NtdllProxy::Hook_LdrUnloadDll(hkLdrUnloadDll); } }; diff --git a/OptiScaler/inputs/FG/DLSSG_Mod.h b/OptiScaler/inputs/FG/DLSSG_Mod.h index b272d9e2..6d455094 100644 --- a/OptiScaler/inputs/FG/DLSSG_Mod.h +++ b/OptiScaler/inputs/FG/DLSSG_Mod.h @@ -3,7 +3,7 @@ #include #include "proxies/NVNGX_Proxy.h" -#include "proxies/KernelBase_Proxy.h" +#include "proxies/Ntdll_Proxy.h" #define DLSSG_MOD_ID_OFFSET 2000000 @@ -69,7 +69,7 @@ class DLSSGMod if (_dll == nullptr) { auto dllPath = Util::DllPath().parent_path() / "dlssg_to_fsr3_amd_is_better.dll"; - _dll = KernelBaseProxy::LoadLibraryExW_()(dllPath.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0); } if (_dll != nullptr) @@ -113,7 +113,7 @@ class DLSSGMod if (_dll == nullptr) { auto dllPath = Util::DllPath().parent_path() / "dlssg_to_fsr3_amd_is_better.dll"; - _dll = KernelBaseProxy::LoadLibraryExW_()(dllPath.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(dllPath.c_str(), NULL, 0); } if (_dll != nullptr) diff --git a/OptiScaler/nvapi/fakenvapi.cpp b/OptiScaler/nvapi/fakenvapi.cpp index 9947c4a9..d8a9fbc4 100644 --- a/OptiScaler/nvapi/fakenvapi.cpp +++ b/OptiScaler/nvapi/fakenvapi.cpp @@ -144,7 +144,7 @@ bool fakenvapi::loadForNvidia() if (_dllForNvidia != nullptr) return true; - _dllForNvidia = KernelBaseProxy::LoadLibraryExW_()(L"fakenvapi.dll", NULL, 0); + _dllForNvidia = NtdllProxy::LoadLibraryExW_Ldr(L"fakenvapi.dll", NULL, 0); if (!_dllForNvidia) return false; diff --git a/OptiScaler/proxies/D3D12_Proxy.h b/OptiScaler/proxies/D3D12_Proxy.h index b47914e3..cc758812 100644 --- a/OptiScaler/proxies/D3D12_Proxy.h +++ b/OptiScaler/proxies/D3D12_Proxy.h @@ -4,6 +4,7 @@ #include +#include #include #include @@ -69,7 +70,7 @@ class D3d12Proxy _dll = KernelBaseProxy::GetModuleHandleW_()(L"d3d12.dll"); if (_dll == nullptr) - _dll = KernelBaseProxy::LoadLibraryExW_()(L"d3d12.dll", NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(L"d3d12.dll", NULL, 0); } else { diff --git a/OptiScaler/proxies/Dxgi_Proxy.h b/OptiScaler/proxies/Dxgi_Proxy.h index d5ad8aa7..a0fa5b96 100644 --- a/OptiScaler/proxies/Dxgi_Proxy.h +++ b/OptiScaler/proxies/Dxgi_Proxy.h @@ -4,7 +4,7 @@ #include -#include +#include #include @@ -29,7 +29,7 @@ class DxgiProxy _dll = GetModuleHandle(L"dxgi.dll"); if (_dll == nullptr) - _dll = KernelBaseProxy::LoadLibraryExW_()(L"dxgi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + _dll = NtdllProxy::LoadLibraryExW_Ldr(L"dxgi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); } else { diff --git a/OptiScaler/proxies/FfxApi_Proxy.h b/OptiScaler/proxies/FfxApi_Proxy.h index c98de53a..42dfc898 100644 --- a/OptiScaler/proxies/FfxApi_Proxy.h +++ b/OptiScaler/proxies/FfxApi_Proxy.h @@ -5,6 +5,7 @@ #include "Config.h" #include "Logger.h" +#include #include #include @@ -77,9 +78,9 @@ class FfxApiProxy std::filesystem::path libPath(Config::Instance()->FfxDx12Path.value().c_str()); if (libPath.has_filename()) - _dllDx12 = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); + _dllDx12 = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); else - _dllDx12 = KernelBaseProxy::LoadLibraryExW_()((libPath / dllNames[i]).c_str(), NULL, 0); + _dllDx12 = NtdllProxy::LoadLibraryExW_Ldr((libPath / dllNames[i]).c_str(), NULL, 0); if (_dllDx12 != nullptr) { @@ -91,7 +92,7 @@ class FfxApiProxy if (_dllDx12 == nullptr) { - _dllDx12 = KernelBaseProxy::LoadLibraryExW_()(dllNames[i].c_str(), NULL, 0); + _dllDx12 = NtdllProxy::LoadLibraryExW_Ldr(dllNames[i].c_str(), NULL, 0); if (_dllDx12 != nullptr) { @@ -222,9 +223,9 @@ class FfxApiProxy std::filesystem::path libPath(Config::Instance()->FfxVkPath.value().c_str()); if (libPath.has_filename()) - _dllVk = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); + _dllVk = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); else - _dllVk = KernelBaseProxy::LoadLibraryExW_()((libPath / L"amd_fidelityfx_vk.dll").c_str(), NULL, 0); + _dllVk = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"amd_fidelityfx_vk.dll").c_str(), NULL, 0); if (_dllVk != nullptr) { @@ -235,7 +236,7 @@ class FfxApiProxy if (_dllVk == nullptr) { - _dllVk = KernelBaseProxy::LoadLibraryExW_()(L"amd_fidelityfx_vk.dll", NULL, 0); + _dllVk = NtdllProxy::LoadLibraryExW_Ldr(L"amd_fidelityfx_vk.dll", NULL, 0); if (_dllVk != nullptr) LOG_INFO("amd_fidelityfx_vk.dll loaded from exe folder"); diff --git a/OptiScaler/proxies/Kernel32_Proxy.h b/OptiScaler/proxies/Kernel32_Proxy.h index f7932676..51998c3f 100644 --- a/OptiScaler/proxies/Kernel32_Proxy.h +++ b/OptiScaler/proxies/Kernel32_Proxy.h @@ -5,6 +5,7 @@ #include #include +#include "Ntdll_Proxy.h" #include "KernelBase_Proxy.h" #include @@ -12,20 +13,20 @@ class Kernel32Proxy { public: - typedef BOOL (*PFN_FreeLibrary)(HMODULE lpLibrary); - typedef HMODULE (*PFN_LoadLibraryA)(LPCSTR lpLibFileName); - typedef HMODULE (*PFN_LoadLibraryW)(LPCWSTR lpLibFileName); - typedef HMODULE (*PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); - typedef HMODULE (*PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); - typedef FARPROC (*PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName); - typedef HMODULE (*PFN_GetModuleHandleA)(LPCSTR lpModuleName); - typedef HMODULE (*PFN_GetModuleHandleW)(LPCWSTR lpModuleName); - typedef BOOL (*PFN_GetModuleHandleExA)(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); - typedef BOOL (*PFN_GetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule); - typedef DWORD (*PFN_GetFileAttributesW)(LPCWSTR lpFileName); - typedef HANDLE (*PFN_CreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + typedef BOOL(WINAPI* PFN_FreeLibrary)(HMODULE lpLibrary); + typedef HMODULE(WINAPI* PFN_LoadLibraryA)(LPCSTR lpLibFileName); + typedef HMODULE(WINAPI* PFN_LoadLibraryW)(LPCWSTR lpLibFileName); + typedef HMODULE(WINAPI* PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); + typedef HMODULE(WINAPI* PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); + typedef FARPROC(WINAPI* PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName); + typedef HMODULE(WINAPI* PFN_GetModuleHandleA)(LPCSTR lpModuleName); + typedef HMODULE(WINAPI* PFN_GetModuleHandleW)(LPCWSTR lpModuleName); + typedef BOOL(WINAPI* PFN_GetModuleHandleExA)(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); + typedef BOOL(WINAPI* PFN_GetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule); + typedef DWORD(WINAPI* PFN_GetFileAttributesW)(LPCWSTR lpFileName); + typedef HANDLE(WINAPI* PFN_CreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); static void Init() { @@ -35,7 +36,7 @@ class Kernel32Proxy _dll = KernelBaseProxy::GetModuleHandleW_()(L"kernel32.dll"); if (_dll == nullptr) - _dll = KernelBaseProxy::LoadLibraryExW_()(L"kernel32.dll", NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(L"kernel32.dll", NULL, 0); if (_dll == nullptr) return; diff --git a/OptiScaler/proxies/KernelBase_Proxy.h b/OptiScaler/proxies/KernelBase_Proxy.h index 2f3ff8b2..8849e283 100644 --- a/OptiScaler/proxies/KernelBase_Proxy.h +++ b/OptiScaler/proxies/KernelBase_Proxy.h @@ -7,16 +7,16 @@ class KernelBaseProxy { public: - typedef BOOL (*PFN_FreeLibrary)(HMODULE lpLibrary); - typedef HMODULE (*PFN_LoadLibraryA)(LPCSTR lpLibFileName); - typedef HMODULE (*PFN_LoadLibraryW)(LPCWSTR lpLibFileName); - typedef HMODULE (*PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); - typedef HMODULE (*PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); - typedef FARPROC (*PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName); - typedef HMODULE (*PFN_GetModuleHandleA)(LPCSTR lpModuleName); - typedef HMODULE (*PFN_GetModuleHandleW)(LPCWSTR lpModuleName); - typedef BOOL (*PFN_GetModuleHandleExA)(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); - typedef BOOL (*PFN_GetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule); + typedef BOOL(WINAPI* PFN_FreeLibrary)(HMODULE lpLibrary); + typedef HMODULE(WINAPI* PFN_LoadLibraryA)(LPCSTR lpLibFileName); + typedef HMODULE(WINAPI* PFN_LoadLibraryW)(LPCWSTR lpLibFileName); + typedef HMODULE(WINAPI* PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); + typedef HMODULE(WINAPI* PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); + typedef FARPROC(WINAPI* PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName); + typedef HMODULE(WINAPI* PFN_GetModuleHandleA)(LPCSTR lpModuleName); + typedef HMODULE(WINAPI* PFN_GetModuleHandleW)(LPCWSTR lpModuleName); + typedef BOOL(WINAPI* PFN_GetModuleHandleExA)(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); + typedef BOOL(WINAPI* PFN_GetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule); static void Init() { diff --git a/OptiScaler/proxies/NVNGX_Proxy.h b/OptiScaler/proxies/NVNGX_Proxy.h index e2d24c53..88c17f4f 100644 --- a/OptiScaler/proxies/NVNGX_Proxy.h +++ b/OptiScaler/proxies/NVNGX_Proxy.h @@ -5,6 +5,7 @@ #include "Config.h" #include "Logger.h" +#include #include #include "nvapi/NvApiHooks.h" @@ -427,8 +428,6 @@ class NVNGXProxy if (_dll == nullptr) { - State::DisableChecks(333); - do { std::wstring libraryName; @@ -454,7 +453,7 @@ class NVNGXProxy if (cfgPath.has_filename()) { - _dll = KernelBaseProxy::LoadLibraryExW_()(cfgPath.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(cfgPath.c_str(), NULL, 0); if (_dll) { @@ -468,7 +467,7 @@ class NVNGXProxy auto path = cfgPath / libraryNameUS; LOG_INFO("trying to load _nvngx.dll path: {0}", wstring_to_string(cfgPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(path.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(path.c_str(), NULL, 0); if (_dll) { @@ -479,7 +478,7 @@ class NVNGXProxy path = cfgPath / libraryName; LOG_INFO("trying to load nvngx.dll path: {0}", wstring_to_string(cfgPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(path.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(path.c_str(), NULL, 0); if (_dll) { @@ -497,7 +496,7 @@ class NVNGXProxy auto nvngxPath = regNGXCorePath.value() / libraryNameUS; LOG_INFO("trying to load _nvngx.dll path: {0}", wstring_to_string(nvngxPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(nvngxPath.wstring().c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(nvngxPath.wstring().c_str(), NULL, 0); if (_dll) { LOG_INFO("_nvngx.dll loaded from {0}, ptr: {1:X}", wstring_to_string(nvngxPath.wstring()), @@ -508,7 +507,7 @@ class NVNGXProxy nvngxPath = regNGXCorePath.value() / libraryName; LOG_INFO("trying to load nvngx.dll path: {0}", wstring_to_string(nvngxPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(nvngxPath.wstring().c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(nvngxPath.wstring().c_str(), NULL, 0); if (_dll) { LOG_INFO("nvngx.dll loaded from {0}, ptr: {1:X}", wstring_to_string(nvngxPath.wstring()), @@ -525,7 +524,7 @@ class NVNGXProxy auto nvngxPath = sysPath / libraryNameUS; LOG_INFO("trying to load _nvngx.dll path: {0}", wstring_to_string(nvngxPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(nvngxPath.wstring().c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(nvngxPath.wstring().c_str(), NULL, 0); if (_dll) { LOG_INFO("_nvngx.dll loaded from {0}, ptr: {1:X}", wstring_to_string(nvngxPath.wstring()), @@ -536,14 +535,12 @@ class NVNGXProxy nvngxPath = sysPath / libraryName; LOG_INFO("trying to load nvngx.dll path: {0}", wstring_to_string(nvngxPath.wstring())); - _dll = KernelBaseProxy::LoadLibraryExW_()(nvngxPath.wstring().c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(nvngxPath.wstring().c_str(), NULL, 0); if (_dll) LOG_INFO("nvngx.dll loaded from {0}, ptr: {1:X}", wstring_to_string(nvngxPath.wstring()), (ULONG64) _dll); } while (false); - - State::EnableChecks(333); } if (_dll != nullptr) diff --git a/OptiScaler/proxies/Ntdll_Proxy.h b/OptiScaler/proxies/Ntdll_Proxy.h new file mode 100644 index 00000000..ee29f580 --- /dev/null +++ b/OptiScaler/proxies/Ntdll_Proxy.h @@ -0,0 +1,120 @@ +#pragma once + +#include + +#include + +#include + +class NtdllProxy +{ + public: + typedef NTSTATUS(NTAPI* PFN_LdrLoadDll)(PWSTR PathToFile OPTIONAL, PULONG Flags OPTIONAL, + PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle); + + typedef NTSTATUS(NTAPI* PFN_NtLoadDll)(PUNICODE_STRING PathToFile OPTIONAL, PULONG Flags OPTIONAL, + PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle); + + typedef NTSTATUS(NTAPI* PFN_LdrUnloadDll)(PVOID ModuleHandle); + + static HMODULE LoadLibraryExW_Ldr(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) + { + UNICODE_STRING uName; + o_RtlInitUnicodeString(&uName, lpLibFileName); + + // LdrLoadDll wants a ULONG*, so stash flags here: + ULONG flags = dwFlags; + + // This will receive the module handle: + HANDLE hModule = nullptr; + + NTSTATUS status = o_LdrLoadDll(nullptr, // PathToFile – we rely on the default search order + &flags, // optional flags + &uName, // the name of the DLL + &hModule // out: module handle + ); + + if (NT_SUCCESS(status)) + { + return static_cast(hModule); + } + else + { + // translate NTSTATUS to a Win32 error code: + SetLastError(o_RtlNtStatusToDosError(status)); + return nullptr; + } + } + + static NTSTATUS FreeLibrary_Ldr(PVOID handle) { return o_LdrUnloadDll(handle); } + + static void Init() + { + if (o_RtlInitUnicodeString != nullptr) + return; + + _dll = GetModuleHandleW(L"ntdll.dll"); + + if (_dll == nullptr) + return; + + o_RtlInitUnicodeString = (PFN_RtlInitUnicodeString) GetProcAddress(_dll, "RtlInitUnicodeString"); + o_RtlNtStatusToDosError = (PFN_RtlNtStatusToDosError) GetProcAddress(_dll, "RtlNtStatusToDosError"); + o_LdrLoadDll = (PFN_LdrLoadDll) GetProcAddress(_dll, "LdrLoadDll"); + o_LdrUnloadDll = (PFN_LdrUnloadDll) GetProcAddress(_dll, "LdrUnloadDll"); + o_NtLoadDll = (PFN_NtLoadDll) GetProcAddress(_dll, "NtLoadDll"); + } + + static HMODULE Module() { return _dll; } + + static PFN_LdrLoadDll Hook_LdrLoadDll(PVOID method) + { + auto addr = o_LdrLoadDll; + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&) addr, method); + DetourTransactionCommit(); + + o_LdrLoadDll = addr; + return addr; + } + + static PFN_LdrUnloadDll Hook_LdrUnloadDll(PVOID method) + { + auto addr = o_LdrUnloadDll; + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&) addr, method); + DetourTransactionCommit(); + + o_LdrUnloadDll = addr; + return addr; + } + + static PFN_NtLoadDll Hook_NtLoadDll(PVOID method) + { + auto addr = o_NtLoadDll; + + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&) addr, method); + DetourTransactionCommit(); + + o_NtLoadDll = addr; + return addr; + } + + private: + typedef VOID(NTAPI* PFN_RtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString); + typedef ULONG(NTAPI* PFN_RtlNtStatusToDosError)(NTSTATUS Status); + + inline static HMODULE _dll = nullptr; + + inline static PFN_LdrLoadDll o_LdrLoadDll = nullptr; + inline static PFN_LdrUnloadDll o_LdrUnloadDll = nullptr; + inline static PFN_NtLoadDll o_NtLoadDll = nullptr; + inline static PFN_RtlInitUnicodeString o_RtlInitUnicodeString = nullptr; + inline static PFN_RtlNtStatusToDosError o_RtlNtStatusToDosError = nullptr; +}; diff --git a/OptiScaler/proxies/XeFG_Proxy.h b/OptiScaler/proxies/XeFG_Proxy.h index 4943c0b0..b1d79206 100644 --- a/OptiScaler/proxies/XeFG_Proxy.h +++ b/OptiScaler/proxies/XeFG_Proxy.h @@ -5,6 +5,7 @@ #include "Config.h" #include "Logger.h" +#include #include #include @@ -192,7 +193,7 @@ class XeFGProxy { std::filesystem::path libXeFGPath = dllPath.parent_path() / libraryName; LOG_INFO("Trying to load libxess_fg.dll from dll path: {}", libXeFGPath.string()); - mainModule = KernelBaseProxy::LoadLibraryExW_()(libXeFGPath.c_str(), NULL, 0); + mainModule = NtdllProxy::LoadLibraryExW_Ldr(libXeFGPath.c_str(), NULL, 0); } if (mainModule != nullptr) diff --git a/OptiScaler/proxies/XeLL_Proxy.h b/OptiScaler/proxies/XeLL_Proxy.h index 4f686d90..09f11446 100644 --- a/OptiScaler/proxies/XeLL_Proxy.h +++ b/OptiScaler/proxies/XeLL_Proxy.h @@ -5,6 +5,7 @@ #include "Config.h" #include "Logger.h" +#include #include #include @@ -170,7 +171,7 @@ class XeLLProxy { std::filesystem::path libXeLLPath = dllPath.parent_path() / libraryName; LOG_INFO("Trying to load libxell.dll from dll path: {}", libXeLLPath.string()); - mainModule = KernelBaseProxy::LoadLibraryExW_()(libXeLLPath.c_str(), NULL, 0); + mainModule = NtdllProxy::LoadLibraryExW_Ldr(libXeLLPath.c_str(), NULL, 0); } } while (false); diff --git a/OptiScaler/proxies/XeSS_Proxy.h b/OptiScaler/proxies/XeSS_Proxy.h index 629814dd..f700f094 100644 --- a/OptiScaler/proxies/XeSS_Proxy.h +++ b/OptiScaler/proxies/XeSS_Proxy.h @@ -5,6 +5,7 @@ #include "Config.h" #include "Logger.h" +#include #include #include @@ -255,14 +256,14 @@ class XeSSProxy LOG_INFO("Trying to load libxess.dll from ini path: {}", cfgPath.string()); cfgPath = cfgPath / libraryName; - mainModule = KernelBaseProxy::LoadLibraryExW_()(cfgPath.c_str(), NULL, 0); + mainModule = NtdllProxy::LoadLibraryExW_Ldr(cfgPath.c_str(), NULL, 0); } if (mainModule == nullptr) { std::filesystem::path libXessPath = dllPath.parent_path() / libraryName; LOG_INFO("Trying to load libxess.dll from dll path: {}", libXessPath.string()); - mainModule = KernelBaseProxy::LoadLibraryExW_()(libXessPath.c_str(), NULL, 0); + mainModule = NtdllProxy::LoadLibraryExW_Ldr(libXessPath.c_str(), NULL, 0); } if (mainModule != nullptr) @@ -298,14 +299,14 @@ class XeSSProxy LOG_INFO("Trying to load libxess.dll from ini path: {}", cfgPath.string()); auto dx11Path = cfgPath.parent_path() / libraryName; - dx11Module = KernelBaseProxy::LoadLibraryExW_()(dx11Path.c_str(), NULL, 0); + dx11Module = NtdllProxy::LoadLibraryExW_Ldr(dx11Path.c_str(), NULL, 0); } if (dx11Module == nullptr) { std::filesystem::path libXessDx11Path = dllPath.parent_path() / libraryName; LOG_INFO("Trying to load libxess.dll from dll path: {}", libXessDx11Path.string()); - dx11Module = KernelBaseProxy::LoadLibraryExW_()(libXessDx11Path.c_str(), NULL, 0); + dx11Module = NtdllProxy::LoadLibraryExW_Ldr(libXessDx11Path.c_str(), NULL, 0); } } while (false); @@ -324,7 +325,7 @@ class XeSSProxy if (_dll != nullptr && _xessD3D12CreateContext != nullptr) return true; - spdlog::info(""); + LOG_DEBUG("Loading XeSS methods from: {:X}", (size_t) libxessModule); if (libxessModule != nullptr) _dll = libxessModule; @@ -334,9 +335,9 @@ class XeSSProxy std::filesystem::path libPath(Config::Instance()->XeSSLibrary.value().c_str()); if (libPath.has_filename()) - _dll = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); else - _dll = KernelBaseProxy::LoadLibraryExW_()((libPath / L"libxess.dll").c_str(), NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"libxess.dll").c_str(), NULL, 0); if (_dll != nullptr) { @@ -346,7 +347,7 @@ class XeSSProxy if (_dll == nullptr) { - _dll = KernelBaseProxy::LoadLibraryExW_()(L"libxess.dll", NULL, 0); + _dll = NtdllProxy::LoadLibraryExW_Ldr(L"libxess.dll", NULL, 0); if (_dll != nullptr) LOG_INFO("libxess.dll loaded from exe folder"); @@ -622,9 +623,9 @@ class XeSSProxy std::filesystem::path libPath(Config::Instance()->XeSSDx11Library.value().c_str()); if (libPath.has_filename()) - _dlldx11 = KernelBaseProxy::LoadLibraryExW_()(libPath.c_str(), NULL, 0); + _dlldx11 = NtdllProxy::LoadLibraryExW_Ldr(libPath.c_str(), NULL, 0); else - _dlldx11 = KernelBaseProxy::LoadLibraryExW_()((libPath / L"libxess_dx11.dll").c_str(), NULL, 0); + _dlldx11 = NtdllProxy::LoadLibraryExW_Ldr((libPath / L"libxess_dx11.dll").c_str(), NULL, 0); if (_dlldx11 != nullptr) { @@ -635,7 +636,7 @@ class XeSSProxy if (_dlldx11 == nullptr) { - _dlldx11 = KernelBaseProxy::LoadLibraryExW_()(L"libxess_dx11.dll", NULL, 0); + _dlldx11 = NtdllProxy::LoadLibraryExW_Ldr(L"libxess_dx11.dll", NULL, 0); if (_dlldx11 != nullptr) LOG_INFO("libxess_dx11.dll loaded from exe folder");