diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6546470..5c98387 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,7 @@ jobs: - release compiler: - msvc + - clang steps: - name: Check out files uses: actions/checkout@main diff --git a/src/client/component/console.cpp b/src/client/component/console.cpp index 8a5dfaf..0eaf90e 100644 --- a/src/client/component/console.cpp +++ b/src/client/component/console.cpp @@ -2,7 +2,6 @@ #include "loader/component_loader.hpp" #include -#include #include #include @@ -37,8 +36,7 @@ public: void post_start() override { this->terminate_runner_ = false; - this->console_runner_ = utils::thread::create_named_thread( - "Console IO", [this] { this->runner(); }); + this->console_runner_ = std::thread([this] { this->runner(); }); } void post_unpack() override { @@ -77,31 +75,30 @@ private: int handles_[2]{}; void initialize() { - this->console_thread_ = - utils::thread::create_named_thread("Console", [this] { - if (!utils::flags::has_flag("noconsole")) { - game::Sys_ShowConsole(); + this->console_thread_ = std::thread([this] { + if (!utils::flags::has_flag("noconsole")) { + game::Sys_ShowConsole(); + } + + messages.access( + [&](message_queue&) { this->console_initialized_ = true; }); + + MSG msg; + while (!this->terminate_runner_) { + if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE)) { + if (msg.message == WM_QUIT) { + command::execute("quit", false); + break; } - messages.access( - [&](message_queue&) { this->console_initialized_ = true; }); - - MSG msg; - while (!this->terminate_runner_) { - if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE)) { - if (msg.message == WM_QUIT) { - command::execute("quit", false); - break; - } - - TranslateMessage(&msg); - DispatchMessageA(&msg); - } else { - this->log_messages(); - std::this_thread::sleep_for(1ms); - } - } - }); + TranslateMessage(&msg); + DispatchMessageA(&msg); + } else { + this->log_messages(); + std::this_thread::sleep_for(1ms); + } + } + }); } void log_messages() const { diff --git a/src/client/component/scheduler.cpp b/src/client/component/scheduler.cpp index 0e385e6..91fc527 100644 --- a/src/client/component/scheduler.cpp +++ b/src/client/component/scheduler.cpp @@ -3,7 +3,6 @@ #include #include -#include #include "scheduler.hpp" @@ -135,7 +134,7 @@ unsigned int thread_id; class component final : public component_interface { public: void post_unpack() override { - thread = utils::thread::create_named_thread("Async Scheduler", [] { + thread = std::thread([] { while (!kill) { execute(pipeline::async); std::this_thread::sleep_for(10ms); diff --git a/src/client/dllmain.cpp b/src/client/dllmain.cpp index 232ab3a..c398ed3 100644 --- a/src/client/dllmain.cpp +++ b/src/client/dllmain.cpp @@ -2,6 +2,19 @@ #include "loader/component_loader.hpp" namespace { +std::string get_current_date() { + auto now = std::chrono::system_clock::now(); + auto current_time = std::chrono::system_clock::to_time_t(now); + std::tm local_time{}; + + (void)localtime_s(&local_time, ¤t_time); + + std::stringstream ss; + ss << std::put_time(&local_time, "%Y%m%d_%H%M%S"); + + return ss.str(); +} + LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) { if (exception_info->ExceptionRecord->ExceptionCode == 0x406D1388) { return EXCEPTION_CONTINUE_EXECUTION; @@ -21,8 +34,8 @@ LONG WINAPI exception_handler(PEXCEPTION_POINTERS exception_info) { | MiniDumpWithFullMemoryInfo // | MiniDumpWithThreadInfo; - const auto file_name = std::format("minidumps\\mw3-server-freezer_{}.dmp", - game::Sys_Milliseconds()); + const auto file_name = + std::format("minidumps\\mw3-server-freezer_{}.dmp", get_current_date()); const auto file_handle = CreateFileA( file_name.data(), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index cd2cf42..0e98a00 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -10,13 +10,16 @@ #include -#include #include #include #include + +#include +#include +#include +#include #include #include -#include #include #include #include diff --git a/src/common/utils/hook.cpp b/src/common/utils/hook.cpp index 5f633bc..ad1314d 100644 --- a/src/common/utils/hook.cpp +++ b/src/common/utils/hook.cpp @@ -103,24 +103,6 @@ void hook::quick() { } } -bool hook::iat(const nt::library module, const std::string& target_module, - const std::string& process, void* stub) { - if (!module.is_valid()) - return false; - - auto ptr = module.get_iat_entry(target_module, process); - if (!ptr) - return false; - - DWORD protect; - VirtualProtect(ptr, sizeof(*ptr), PAGE_EXECUTE_READWRITE, &protect); - - *ptr = stub; - - VirtualProtect(ptr, sizeof(*ptr), protect, &protect); - return true; -} - hook* hook::uninstall(const bool unprotect) { std::lock_guard _(this->state_mutex_); diff --git a/src/common/utils/hook.hpp b/src/common/utils/hook.hpp index bc09916..61e3253 100644 --- a/src/common/utils/hook.hpp +++ b/src/common/utils/hook.hpp @@ -75,9 +75,6 @@ public: void* get_original() const; void quick(); - static bool iat(nt::library module, const std::string& target_module, - const std::string& process, void* stub); - static void nop(void* place, size_t length); static void nop(DWORD place, size_t length); diff --git a/src/common/utils/nt.cpp b/src/common/utils/nt.cpp index 43b8904..b8b67e1 100644 --- a/src/common/utils/nt.cpp +++ b/src/common/utils/nt.cpp @@ -135,62 +135,6 @@ void library::free() { HMODULE library::get_handle() const { return this->module_; } -void** library::get_iat_entry(const std::string& module_name, - const std::string& proc_name) const { - if (!this->is_valid()) - return nullptr; - - const library other_module(module_name); - if (!other_module.is_valid()) - return nullptr; - - auto* const target_function = other_module.get_proc(proc_name); - if (!target_function) - return nullptr; - - auto* header = this->get_optional_header(); - if (!header) - return nullptr; - - auto* import_descriptor = reinterpret_cast( - this->get_ptr() + - header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); - - while (import_descriptor->Name) { - if (!_stricmp( - reinterpret_cast(this->get_ptr() + import_descriptor->Name), - module_name.data())) { - auto* original_thunk_data = reinterpret_cast( - import_descriptor->OriginalFirstThunk + this->get_ptr()); - auto* thunk_data = reinterpret_cast( - import_descriptor->FirstThunk + this->get_ptr()); - - while (original_thunk_data->u1.AddressOfData) { - const size_t ordinal_number = - original_thunk_data->u1.AddressOfData & 0xFFFFFFF; - - if (ordinal_number > 0xFFFF) - continue; - - if (GetProcAddress(other_module.module_, - reinterpret_cast(ordinal_number)) == - target_function) { - return reinterpret_cast(&thunk_data->u1.Function); - } - - ++original_thunk_data; - ++thunk_data; - } - - // break; - } - - ++import_descriptor; - } - - return nullptr; -} - std::string load_resource(const int id) { auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA); if (!res) diff --git a/src/common/utils/nt.hpp b/src/common/utils/nt.hpp index f629a62..bb8ee31 100644 --- a/src/common/utils/nt.hpp +++ b/src/common/utils/nt.hpp @@ -48,27 +48,12 @@ public: HMODULE get_handle() const; - template T get_proc(const std::string& process) const { - if (!this->is_valid()) - return T{}; - return reinterpret_cast(GetProcAddress(this->module_, process.data())); - } - - template std::function get(const std::string& process) const { - if (!this->is_valid()) - return std::function(); - return reinterpret_cast(this->get_proc(process)); - } - std::vector get_section_headers() const; PIMAGE_NT_HEADERS get_nt_headers() const; PIMAGE_DOS_HEADER get_dos_header() const; PIMAGE_OPTIONAL_HEADER get_optional_header() const; - void** get_iat_entry(const std::string& module_name, - const std::string& proc_name) const; - private: HMODULE module_; }; diff --git a/src/common/utils/thread.cpp b/src/common/utils/thread.cpp deleted file mode 100644 index 7d778ed..0000000 --- a/src/common/utils/thread.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include -#include "nt.hpp" -#include "string.hpp" - -#include "thread.hpp" - -#include - -#include - -namespace utils::thread { -bool set_name(const HANDLE t, const std::string& name) { - const nt::library kernel32("kernel32.dll"); - if (!kernel32) { - return false; - } - - const auto set_description = - kernel32.get_proc( - "SetThreadDescription"); - if (!set_description) { - return false; - } - - return SUCCEEDED(set_description(t, string::convert(name).data())); -} - -bool set_name(const DWORD id, const std::string& name) { - auto* const t = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, id); - if (!t) - return false; - - const auto _ = gsl::finally([t]() { CloseHandle(t); }); - - return set_name(t, name); -} - -bool set_name(std::thread& t, const std::string& name) { - return set_name(t.native_handle(), name); -} - -bool set_name(const std::string& name) { - return set_name(GetCurrentThread(), name); -} - -std::vector get_thread_ids() { - auto* const h = - CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId()); - if (h == INVALID_HANDLE_VALUE) { - return {}; - } - - const auto _ = gsl::finally([h]() { CloseHandle(h); }); - - THREADENTRY32 entry{}; - entry.dwSize = sizeof(entry); - if (!Thread32First(h, &entry)) { - return {}; - } - - std::vector ids; - - do { - const auto check_size = - entry.dwSize < FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + - sizeof(entry.th32OwnerProcessID); - entry.dwSize = sizeof(entry); - - if (check_size && entry.th32OwnerProcessID == GetCurrentProcessId()) { - ids.emplace_back(entry.th32ThreadID); - } - } while (Thread32Next(h, &entry)); - - return ids; -} - -void for_each_thread(const std::function& callback) { - const auto ids = get_thread_ids(); - - for (const auto& id : ids) { - auto* const thread = OpenThread(THREAD_ALL_ACCESS, FALSE, id); - if (thread != nullptr) { - const auto _ = gsl::finally([thread]() { CloseHandle(thread); }); - - callback(thread); - } - } -} - -void suspend_other_threads() { - for_each_thread([](const HANDLE thread) { - if (GetThreadId(thread) != GetCurrentThreadId()) { - SuspendThread(thread); - } - }); -} - -void resume_other_threads() { - for_each_thread([](const HANDLE thread) { - if (GetThreadId(thread) != GetCurrentThreadId()) { - ResumeThread(thread); - } - }); -} -} // namespace utils::thread diff --git a/src/common/utils/thread.hpp b/src/common/utils/thread.hpp deleted file mode 100644 index b9ee875..0000000 --- a/src/common/utils/thread.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -namespace utils::thread { -bool set_name(HANDLE t, const std::string& name); -bool set_name(DWORD id, const std::string& name); -bool set_name(std::thread& t, const std::string& name); -bool set_name(const std::string& name); - -template -std::thread create_named_thread(const std::string& name, Args&&... args) { - auto t = std::thread(std::forward(args)...); - set_name(t, name); - return t; -} - -std::vector get_thread_ids(); -void for_each_thread(const std::function& callback); - -void suspend_other_threads(); -void resume_other_threads(); -} // namespace utils::thread