Last active
April 4, 2023 15:48
-
-
Save DavinciPG/68975a87b31ebadf5929992cffe8ae22 to your computer and use it in GitHub Desktop.
Simple caching system for CModule
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CModule { | |
public: | |
CModule(CModule&&) = delete; | |
CModule(const CModule&) = delete; | |
explicit CModule(const char* name, bool shouldLoad) { | |
this->m_name = name; | |
if (shouldLoad) Load(); | |
} | |
void Load() { | |
InitializeHandle(); | |
InitializeBounds(); | |
} | |
template <typename T = void*> | |
auto GetProcAddress(const char* procName) const { | |
T rv = nullptr; | |
if (this->IsLoaded()) { | |
rv = reinterpret_cast<T>(::GetProcAddress( | |
static_cast<HMODULE>(this->m_handle), procName)); | |
} | |
return rv; | |
} | |
template <typename T = void*> | |
T FindInterface(const char* version) const { | |
void* rv = nullptr; | |
if (this->IsLoaded()) { | |
UTILPtr pCreateInterface = this->GetProcAddress("CreateInterface"); | |
InterfaceReg* s_pInterfaceRegs = pCreateInterface.ToAbsolute(3, 0) | |
.Dereference(1) | |
.Get<InterfaceReg*>(); | |
for (; s_pInterfaceRegs; | |
s_pInterfaceRegs = s_pInterfaceRegs->m_pNext) { | |
if (strcmp(version, s_pInterfaceRegs->m_pName) == 0) { | |
rv = s_pInterfaceRegs->m_CreateFn(); | |
break; | |
} | |
} | |
} | |
return reinterpret_cast<T>(rv); | |
} | |
template <size_t N> | |
UTILPtr FindPattern(const std::array<int, N>& signature) const { | |
UTILPtr rv = 0; | |
if (this->IsLoaded()) { | |
const int* pSigData = signature.data(); | |
uint8_t* pBytes = reinterpret_cast<uint8_t*>(this->m_start); | |
for (size_t i = 0; i < this->m_end - N; ++i) { | |
bool found = true; | |
for (size_t j = 0; j < N; ++j) { | |
if (pBytes[i + j] != pSigData[j] && pSigData[j] != -1) { | |
found = false; | |
break; | |
} | |
} | |
if (found) { | |
rv = reinterpret_cast<uintptr_t>(&pBytes[i]); | |
break; | |
} | |
} | |
} | |
return rv; | |
} | |
const char* GetName() const { return this->m_name.c_str(); } | |
bool IsLoaded() const { return this->m_handle != 0; } | |
private: | |
void InitializeHandle() { | |
if (m_isCached) { | |
this->m_handle = m_cachedHandle; | |
} | |
else { | |
this->m_handle = static_cast<void*>(GetModuleHandle(this->GetName())); | |
this->m_cachedHandle = this->m_handle; | |
} | |
} | |
void InitializeBounds() { | |
if (!this->IsLoaded()) return; | |
if (m_isCached) { | |
this->m_start = this->m_cachedStart; | |
this->m_end = this->m_cachedEnd; | |
} | |
else { | |
MODULEINFO mi; | |
BOOL status = GetModuleInformation(GetCurrentProcess(), | |
static_cast<HMODULE>(this->m_handle), | |
&mi, sizeof(mi)); | |
if (status != 0) { | |
this->m_start = reinterpret_cast<uintptr_t>(this->m_handle); | |
this->m_end = static_cast<uintptr_t>(mi.SizeOfImage); | |
this->m_cachedStart = this->m_start; | |
this->m_cachedEnd = this->m_end; | |
this->m_isCached = true; | |
} | |
} | |
} | |
void* m_handle = nullptr; | |
uintptr_t m_start = 0, m_end = 0; | |
std::string m_name = ""; | |
/// Caching | |
bool m_isCached = false; | |
void* m_cachedHandle = nullptr; | |
uintptr_t m_cachedStart = 0, m_cachedEnd = 0; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment