From a375a40422479603499a01cdbee6a0e5b95bd4d8 Mon Sep 17 00:00:00 2001 From: ApfelTeeSaft <91074565+ApfelTeeSaft@users.noreply.github.com> Date: Sun, 1 Feb 2026 18:52:47 +0100 Subject: [PATCH] Replace std::mutex with safer FCriticalSection --- Core/Common.h | 67 ++++++++++++++++++++++++++++++++++-------- Core/Hooks/HookTypes.h | 26 ++++++---------- Core/Logging/Log.cpp | 10 +++---- Core/Logging/Log.h | 4 +-- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/Core/Common.h b/Core/Common.h index 67d7943..88521da 100644 --- a/Core/Common.h +++ b/Core/Common.h @@ -22,6 +22,47 @@ namespace USS { + // ======================================================================== + // CRITICAL_SECTION RAII Wrapper + // ======================================================================== + + /** + * RAII wrapper for Windows CRITICAL_SECTION + * Safer than std::mutex when injected into processes - doesn't depend on CRT initialization + */ + class FCriticalSection + { + public: + FCriticalSection() { InitializeCriticalSection(&m_CS); } + ~FCriticalSection() { DeleteCriticalSection(&m_CS); } + + FCriticalSection(const FCriticalSection&) = delete; + FCriticalSection& operator=(const FCriticalSection&) = delete; + + void Lock() { EnterCriticalSection(&m_CS); } + void Unlock() { LeaveCriticalSection(&m_CS); } + bool TryLock() { return TryEnterCriticalSection(&m_CS) != 0; } + + private: + CRITICAL_SECTION m_CS; + }; + + /** + * RAII lock guard for FCriticalSection + */ + class FScopedLock + { + public: + explicit FScopedLock(FCriticalSection& CS) : m_CS(CS) { m_CS.Lock(); } + ~FScopedLock() { m_CS.Unlock(); } + + FScopedLock(const FScopedLock&) = delete; + FScopedLock& operator=(const FScopedLock&) = delete; + + private: + FCriticalSection& m_CS; + }; + using int8 = int8_t; using int16 = int16_t; using int32 = int32_t; @@ -86,26 +127,26 @@ namespace USS } } - #define USS_INTERFACE class +#define USS_INTERFACE class - #define USS_NON_COPYABLE(ClassName) \ +#define USS_NON_COPYABLE(ClassName) \ ClassName(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; - #define USS_NON_MOVABLE(ClassName) \ +#define USS_NON_MOVABLE(ClassName) \ ClassName(ClassName&&) = delete; \ ClassName& operator=(ClassName&&) = delete; - #ifdef USS_DEBUG - #define USS_LOG(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Info, fmt, ##__VA_ARGS__) - #define USS_WARN(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Warning, fmt, ##__VA_ARGS__) - #define USS_ERROR(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Error, fmt, ##__VA_ARGS__) - #else - #define USS_LOG(fmt, ...) ((void)0) - #define USS_WARN(fmt, ...) ((void)0) - #define USS_ERROR(fmt, ...) ((void)0) - #endif +#ifdef USS_DEBUG +#define USS_LOG(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Info, fmt, ##__VA_ARGS__) +#define USS_WARN(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Warning, fmt, ##__VA_ARGS__) +#define USS_ERROR(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Error, fmt, ##__VA_ARGS__) +#else +#define USS_LOG(fmt, ...) ((void)0) +#define USS_WARN(fmt, ...) ((void)0) +#define USS_ERROR(fmt, ...) ((void)0) +#endif - #define USS_FATAL(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Fatal, fmt, ##__VA_ARGS__) +#define USS_FATAL(fmt, ...) ::USS::Log::Write(::USS::ELogLevel::Fatal, fmt, ##__VA_ARGS__) } \ No newline at end of file diff --git a/Core/Hooks/HookTypes.h b/Core/Hooks/HookTypes.h index 617e8f0..cb713f2 100644 --- a/Core/Hooks/HookTypes.h +++ b/Core/Hooks/HookTypes.h @@ -12,7 +12,6 @@ #include #include #include -#include namespace USS { @@ -20,11 +19,10 @@ namespace USS namespace Hook { - // Internal state namespace Detail { inline bool g_bInitialized = false; - inline std::mutex g_Mutex; + inline FCriticalSection g_CriticalSection; } /** @@ -33,7 +31,7 @@ namespace USS */ inline EResult Initialize() { - std::lock_guard Lock(Detail::g_Mutex); + FScopedLock Lock(Detail::g_CriticalSection); if (Detail::g_bInitialized) return EResult::AlreadyInitialized; @@ -56,7 +54,7 @@ namespace USS */ inline void Shutdown() { - std::lock_guard Lock(Detail::g_Mutex); + FScopedLock Lock(Detail::g_CriticalSection); if (!Detail::g_bInitialized) return; @@ -299,29 +297,25 @@ namespace USS return Instance; } - // Register a pre-ProcessEvent callback - // Return false from callback to block the original function void RegisterPre(PreCallback Callback) { - std::lock_guard Lock(m_Mutex); + FScopedLock Lock(m_CriticalSection); m_PreCallbacks.push_back(std::move(Callback)); } - // Register a post-ProcessEvent callback void RegisterPost(PostCallback Callback) { - std::lock_guard Lock(m_Mutex); + FScopedLock Lock(m_CriticalSection); m_PostCallbacks.push_back(std::move(Callback)); } - // Called from the hook detour - dispatch to pre-callbacks bool DispatchPre(void* Object, void* Function, void* Params) { bool bCallOriginal = true; std::vector Callbacks; { - std::lock_guard Lock(m_Mutex); + FScopedLock Lock(m_CriticalSection); Callbacks = m_PreCallbacks; } @@ -333,12 +327,11 @@ namespace USS return bCallOriginal; } - // Called from the hook detour - dispatch to post-callbacks void DispatchPost(void* Object, void* Function, void* Params) { std::vector Callbacks; { - std::lock_guard Lock(m_Mutex); + FScopedLock Lock(m_CriticalSection); Callbacks = m_PostCallbacks; } @@ -348,13 +341,12 @@ namespace USS } } - // Set/get original function pointer void SetOriginal(ProcessEventFn Original) { m_pOriginal = Original; } ProcessEventFn GetOriginal() const { return m_pOriginal; } void ClearCallbacks() { - std::lock_guard Lock(m_Mutex); + FScopedLock Lock(m_CriticalSection); m_PreCallbacks.clear(); m_PostCallbacks.clear(); } @@ -362,7 +354,7 @@ namespace USS private: FSimpleProcessEventDispatcher() : m_pOriginal(nullptr) {} - std::mutex m_Mutex; + FCriticalSection m_CriticalSection; std::vector m_PreCallbacks; std::vector m_PostCallbacks; ProcessEventFn m_pOriginal; diff --git a/Core/Logging/Log.cpp b/Core/Logging/Log.cpp index 5bf9c25..f1fe96c 100644 --- a/Core/Logging/Log.cpp +++ b/Core/Logging/Log.cpp @@ -8,7 +8,7 @@ namespace USS { - std::mutex Log::s_Mutex; + FCriticalSection Log::s_CriticalSection; std::ofstream Log::s_FileStream; ELogLevel Log::s_MinLevel = ELogLevel::Info; bool Log::s_bConsoleEnabled = false; @@ -17,7 +17,7 @@ namespace USS EResult Log::Initialize(bool bEnableConsole, const char* LogFilePath) { - std::lock_guard Lock(s_Mutex); + FScopedLock Lock(s_CriticalSection); if (s_bInitialized) return EResult::AlreadyInitialized; @@ -48,7 +48,7 @@ namespace USS void Log::Shutdown() { - std::lock_guard Lock(s_Mutex); + FScopedLock Lock(s_CriticalSection); if (!s_bInitialized) return; @@ -90,7 +90,7 @@ namespace USS void Log::SetMinLevel(ELogLevel Level) { - std::lock_guard Lock(s_Mutex); + FScopedLock Lock(s_CriticalSection); s_MinLevel = Level; } @@ -110,7 +110,7 @@ namespace USS void Log::WriteInternal(ELogLevel Level, const char* Message) { - std::lock_guard Lock(s_Mutex); + FScopedLock Lock(s_CriticalSection); if (!s_bInitialized) return; diff --git a/Core/Logging/Log.h b/Core/Logging/Log.h index 8786add..1a4e09f 100644 --- a/Core/Logging/Log.h +++ b/Core/Logging/Log.h @@ -8,7 +8,6 @@ #pragma once #include "../Common.h" -#include #include #include @@ -31,6 +30,7 @@ namespace USS USS_NON_MOVABLE(Log) static EResult Initialize(bool bEnableConsole = true, const char* LogFilePath = nullptr); + static void Shutdown(); static void Write(ELogLevel Level, const char* Format, ...); @@ -47,7 +47,7 @@ namespace USS static void WriteInternal(ELogLevel Level, const char* Message); - static std::mutex s_Mutex; + static FCriticalSection s_CriticalSection; static std::ofstream s_FileStream; static ELogLevel s_MinLevel; static bool s_bConsoleEnabled;