From 4f4f517522927f74e5322b6dcc37935b438d2228 Mon Sep 17 00:00:00 2001 From: Patrick Mollohan <14967142+patrickmollohan@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:35:19 -0500 Subject: [PATCH] Update CPU/IO/Thread priority code, add version.ini, update exe check --- src/dll_main.cpp | 41 +++++++++++++-------------- src/settings.cpp | 7 ++++- src/settings.hpp | 6 ++++ src/utilities.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++---- src/utilities.hpp | 30 +++++++++++++++++--- version.ini | 12 ++++++++ 6 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 version.ini diff --git a/src/dll_main.cpp b/src/dll_main.cpp index 0afafe8..761d4ea 100644 --- a/src/dll_main.cpp +++ b/src/dll_main.cpp @@ -2,29 +2,28 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { VersionWrapper::Initialise(); - Utilities::SettingsParser::SetConfigFilePath(hModule); - Settings::LoadSettings(); - Utilities::Processes::SetHighPriority(); + if (Utilities::Processes::IsCompatibleExe()) { + Utilities::SettingsParser::SetConfigFilePath(hModule); + Settings::LoadSettings(); + Utilities::Processes::SetPriorityLevels(); - std::string exeName = Utilities::Processes::GetExeName(); - if (Utilities::String::EqualsIgnoreCase(exeName, "Outlaws.exe") || Utilities::String::EqualsIgnoreCase(exeName, "Outlaws_Plus.exe")) { switch (dwReason) { - case DLL_PROCESS_ATTACH: - MinHookHandler::Initialise(); - DiskCacheEnabler::Enable(); - ModLoader::Enable(); - MinHookHandler::EnableAllHooks(); - ScriptLoader::LoadScripts(); - break; - case DLL_PROCESS_DETACH: - DiskCacheEnabler::Disable(); - ModLoader::Disable(); - MinHookHandler::Shutdown(); - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - break; + case DLL_PROCESS_ATTACH: + MinHookHandler::Initialise(); + DiskCacheEnabler::Enable(); + ModLoader::Enable(); + MinHookHandler::EnableAllHooks(); + ScriptLoader::LoadScripts(); + break; + case DLL_PROCESS_DETACH: + DiskCacheEnabler::Disable(); + ModLoader::Disable(); + MinHookHandler::Shutdown(); + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; } return TRUE; } diff --git a/src/settings.cpp b/src/settings.cpp index 13e96ea..ae102bf 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,10 +1,12 @@ #include "settings.hpp" -#include "utilities.hpp" bool Settings::EnableMods = false; bool Settings::EnableScripts = false; bool Settings::CreateFileA = false; bool Settings::CreateFileW = false; +std::string Settings::CPUPriority = "normal"; +std::string Settings::IOPriority = "normal"; +std::string Settings::ThreadPriority = "normal"; void Settings::LoadSettings() { using SettingsParser = Utilities::SettingsParser; @@ -13,4 +15,7 @@ void Settings::LoadSettings() { EnableScripts = SettingsParser::GetBoolean("Settings", "EnableScripts", false); CreateFileA = SettingsParser::GetBoolean("DiskCacheEnabler", "CreateFileA", false); CreateFileW = SettingsParser::GetBoolean("DiskCacheEnabler", "CreateFileW", false); + CPUPriority = SettingsParser::GetString("Priorities", "CPUPriority", "normal"); + IOPriority = SettingsParser::GetString("Priorities", "IOPriority", "normal"); + ThreadPriority = SettingsParser::GetString("Priorities", "ThreadPriority", "normal"); } diff --git a/src/settings.hpp b/src/settings.hpp index 6aaefcd..02e0132 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -3,6 +3,9 @@ #define VC_EXTRALEAN #define WIN32_LEAN_AND_MEAN +#include +#include "utilities.hpp" + class Settings { public: static void LoadSettings(); @@ -11,4 +14,7 @@ class Settings { static bool EnableScripts; static bool CreateFileA; static bool CreateFileW; + static std::string CPUPriority; + static std::string IOPriority; + static std::string ThreadPriority; }; diff --git a/src/utilities.cpp b/src/utilities.cpp index ebb26bc..14bc7b2 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -1,5 +1,12 @@ #include "utilities.hpp" +const char* Utilities::Processes::allowedExes[] = { + "Outlaws.exe", + "Outlaws_Plus.exe", + "AFOP.exe", + "AFOP_Plus.exe" +}; + bool Utilities::Files::LocalFileExists(LPCSTR file_path) { DWORD dwAttrib = GetFileAttributesA(file_path); return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); @@ -93,12 +100,59 @@ std::string Utilities::Processes::GetExeName() { return exeName; } -void Utilities::Processes::SetHighPriority() { +bool Utilities::Processes::IsCompatibleExe() { + std::string exeName = Utilities::Processes::GetExeName(); + for (const char* allowedExe : allowedExes) { + if (Utilities::String::EqualsIgnoreCase(exeName, allowedExe)) { + return true; + } + } + return false; +} + +void Utilities::Processes::SetPriorityLevels() { HANDLE hProcess = GetCurrentProcess(); - SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS); - SetProcessPriorityBoost(hProcess, FALSE); HANDLE hThread = GetCurrentThread(); - SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + + // Set CPU Priority + SetProcessPriorityBoost(hProcess, FALSE); + if (Settings::CPUPriority == "normal") { + SetPriorityClass(hProcess, NORMAL_PRIORITY_CLASS); + } else if (Settings::CPUPriority == "medium") { + SetPriorityClass(hProcess, ABOVE_NORMAL_PRIORITY_CLASS); + } else if (Settings::CPUPriority == "high") { + SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS); + } + + // Set Thread Priority + if (Settings::ThreadPriority == "normal") { + SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL); + } else if (Settings::ThreadPriority == "medium") { + SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); + } else if (Settings::ThreadPriority == "high") { + SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); + } + + // Set IO Priority + HMODULE hNtDll = LoadLibrary(L"ntdll.dll"); + if (hNtDll) { + auto NtSetInformationThread = (NtSetInformationThread_t)GetProcAddress(hNtDll, "NtSetInformationThread"); + if (NtSetInformationThread) { + IO_PRIORITY_HINT ioPriorityHint = IoPriorityNormal; + + if (Settings::IOPriority == "high") { + ioPriorityHint = IoPriorityHigh; + } + + NTSTATUS status = NtSetInformationThread( + hThread, + ThreadIoPriority, + &ioPriorityHint, + sizeof(IO_PRIORITY_HINT) + ); + } + FreeLibrary(hNtDll); + } } std::string Utilities::SettingsParser::configFilePath = ""; @@ -126,7 +180,7 @@ bool Utilities::SettingsParser::GetBoolean(const std::string& section, const std DWORD length = GetPrivateProfileStringA( section.c_str(), key.c_str(), - defaultValue ? "true" : "false", // Default value + defaultValue ? "true" : "false", result, sizeof(result), configFilePath.c_str() @@ -145,7 +199,7 @@ bool Utilities::SettingsParser::GetBoolean(const std::string& section, const std value.erase(value.find_last_not_of(" \t") + 1); // Right trim // Convert to lowercase for case-insensitive comparison - std::transform(value.begin(), value.end(), value.begin(), ::tolower); + Utilities::String::ToLower(value); // Interpret the result as a boolean return value == "true" || value == "1" || value == "yes" || value == "on"; @@ -212,3 +266,9 @@ std::string Utilities::SettingsParser::GetString(const std::string& section, con bool Utilities::String::EqualsIgnoreCase(const std::string& str1, const std::string& str2) { return str1.size() == str2.size() && std::equal(str1.begin(), str1.end(), str2.begin(), [](char a, char b) { return std::tolower(a) == std::tolower(b); }); } + +void Utilities::String::ToLower(std::string& str) { + for (size_t i = 0; i < str.size(); ++i) { + str[i] = std::tolower(static_cast(str[i])); + } +} \ No newline at end of file diff --git a/src/utilities.hpp b/src/utilities.hpp index fe79bda..dc589b4 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -4,10 +4,27 @@ #define WIN32_LEAN_AND_MEAN #include -#include #include +#include +#include "settings.hpp" #define PATTERN_WILDCARD 0x00 +#define ThreadIoPriority (THREADINFOCLASS)21 + +typedef enum _IO_PRIORITY_HINT { + IoPriorityVeryLow = 0, + IoPriorityLow, + IoPriorityNormal, + IoPriorityHigh, + IoPriorityCritical +} IO_PRIORITY_HINT; + +typedef NTSTATUS(NTAPI* NtSetInformationThread_t)( + HANDLE ThreadHandle, + THREADINFOCLASS ThreadInformationClass, + PVOID ThreadInformation, + ULONG ThreadInformationLength +); class Utilities { public: @@ -26,8 +43,8 @@ class Utilities { MainModule(); ~MainModule(); - uintptr_t GetBaseAddress() const; // Gets the module base address - uintptr_t GetCodeSize() const; // Gets the size of code reported by the PE header + uintptr_t GetBaseAddress() const; + uintptr_t GetCodeSize() const; size_t Begin() const; size_t End() const; std::string GetModulePath() const; @@ -38,7 +55,11 @@ class Utilities { static uintptr_t FindPatternAddress(const unsigned char* pattern, size_t patternLength); static uintptr_t FindPatternAddressMask(const unsigned char* pattern, const unsigned char* mask, size_t patternLength); static std::string GetExeName(); - static void SetHighPriority(); + static bool IsCompatibleExe(); + static void SetPriorityLevels(); + + private: + static const char* allowedExes[]; }; class SettingsParser { @@ -55,5 +76,6 @@ class Utilities { class String { public: static bool EqualsIgnoreCase(const std::string& str1, const std::string& str2); + static void ToLower(std::string& str); }; }; \ No newline at end of file diff --git a/version.ini b/version.ini new file mode 100644 index 0000000..a0e05fc --- /dev/null +++ b/version.ini @@ -0,0 +1,12 @@ +[Settings] +EnableMods=true # Enables mod support (true/false, default: true) +EnableScripts=true # Enables loading DLL/ASI scripts (true/false, default: true) + +[DiskCacheEnabler] +CreateFileA=true # Enables disk caching during calls to CreateFileA (true/false, default: true) +CreateFileW=true # Enables disk caching during calls to CreateFileW (true/false, default: true) + +[Priorities] +CPUPriority=high # Sets the priority level of the CPU (normal/medium/high, default: high) +IOPriority=high # Sets the priority level of the IO (normal/high, default: high) +ThreadPriority=high # Sets the priority level of threads (normal/medium/high, default: high)