mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Add option to use global import hook instead of MinHook for OpenProcess (#860)
This commit is contained in:
parent
d1e69ed6fd
commit
c5f84eb27d
13 changed files with 775 additions and 165 deletions
|
|
@ -10,14 +10,70 @@
|
|||
#include "unicode.h"
|
||||
|
||||
namespace utils {
|
||||
class loaded_module {
|
||||
HMODULE m_hModule;
|
||||
public:
|
||||
loaded_module() : m_hModule(nullptr) {}
|
||||
loaded_module(const void* hModule) : m_hModule(reinterpret_cast<HMODULE>(const_cast<void*>(hModule))) {}
|
||||
loaded_module(void* hModule) : m_hModule(reinterpret_cast<HMODULE>(hModule)) {}
|
||||
loaded_module(size_t hModule) : m_hModule(reinterpret_cast<HMODULE>(hModule)) {}
|
||||
|
||||
std::filesystem::path path() const;
|
||||
|
||||
bool is_current_process() const { return m_hModule == GetModuleHandleW(nullptr); }
|
||||
bool owns_address(const void* pAddress) const;
|
||||
|
||||
operator HMODULE() const {
|
||||
return m_hModule;
|
||||
}
|
||||
|
||||
size_t address_int() const { return reinterpret_cast<size_t>(m_hModule); }
|
||||
size_t image_size() const { return is_pe64() ? nt_header64().OptionalHeader.SizeOfImage : nt_header32().OptionalHeader.SizeOfImage; }
|
||||
char* address(size_t offset = 0) const { return reinterpret_cast<char*>(m_hModule) + offset; }
|
||||
template<typename T> T* address_as(size_t offset) const { return reinterpret_cast<T*>(address(offset)); }
|
||||
template<typename T> std::span<T> span_as(size_t offset, size_t count) const { return std::span<T>(reinterpret_cast<T*>(address(offset)), count); }
|
||||
template<typename T> T& ref_as(size_t offset) const { return *reinterpret_cast<T*>(address(offset)); }
|
||||
|
||||
IMAGE_DOS_HEADER& dos_header() const { return ref_as<IMAGE_DOS_HEADER>(0); }
|
||||
IMAGE_NT_HEADERS32& nt_header32() const { return ref_as<IMAGE_NT_HEADERS32>(dos_header().e_lfanew); }
|
||||
IMAGE_NT_HEADERS64& nt_header64() const { return ref_as<IMAGE_NT_HEADERS64>(dos_header().e_lfanew); }
|
||||
bool is_pe64() const { return nt_header32().OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC; }
|
||||
|
||||
std::span<IMAGE_DATA_DIRECTORY> data_directories() const { return is_pe64() ? nt_header64().OptionalHeader.DataDirectory : nt_header32().OptionalHeader.DataDirectory; }
|
||||
IMAGE_DATA_DIRECTORY& data_directory(size_t index) const { return data_directories()[index]; }
|
||||
|
||||
std::span<IMAGE_SECTION_HEADER> section_headers() const;
|
||||
IMAGE_SECTION_HEADER& section_header(const char* pcszSectionName) const;
|
||||
std::span<char> section(size_t index) const;
|
||||
std::span<char> section(const char* pcszSectionName) const;
|
||||
|
||||
template<typename TFn> TFn* get_exported_function(const char* pcszFunctionName) {
|
||||
const auto pAddress = GetProcAddress(m_hModule, pcszFunctionName);
|
||||
if (!pAddress)
|
||||
throw std::out_of_range(std::format("Exported function \"{}\" not found.", pcszFunctionName));
|
||||
return reinterpret_cast<TFn*>(pAddress);
|
||||
}
|
||||
|
||||
bool find_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal, void*& ppFunctionAddress) const;
|
||||
void* get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) const;
|
||||
template<typename TFn> TFn** get_imported_function_pointer(const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) { return reinterpret_cast<TFn**>(get_imported_function_pointer(pcszDllName, pcszFunctionName, hintOrOrdinal)); }
|
||||
|
||||
static loaded_module current_process();
|
||||
static std::vector<loaded_module> all_modules();
|
||||
};
|
||||
|
||||
class signature_finder {
|
||||
std::vector<std::span<const char>> m_ranges;
|
||||
std::vector<srell::regex> m_patterns;
|
||||
|
||||
public:
|
||||
signature_finder& look_in(const void* pFirst, size_t length);
|
||||
signature_finder& look_in(const void* pFirst, const void* pLast);
|
||||
signature_finder& look_in(HMODULE hModule, const char* sectionName);
|
||||
signature_finder& look_in(const loaded_module& m, const char* sectionName);
|
||||
|
||||
template<typename T>
|
||||
signature_finder& look_in(std::span<T> s) {
|
||||
return look_in(s.data(), s.size());
|
||||
}
|
||||
|
||||
signature_finder& look_for(std::string_view pattern, std::string_view mask, char cExactMatch = 'x', char cWildcard = '.');
|
||||
signature_finder& look_for(std::string_view pattern, char wildcardMask);
|
||||
|
|
@ -54,18 +110,12 @@ namespace utils {
|
|||
template<typename T>
|
||||
memory_tenderizer(std::span<const T> s, DWORD dwNewProtect) : memory_tenderizer(&s[0], s.size(), dwNewProtect) {}
|
||||
|
||||
template<typename T>
|
||||
memory_tenderizer(std::span<T> s, DWORD dwNewProtect) : memory_tenderizer(&s[0], s.size(), dwNewProtect) {}
|
||||
|
||||
~memory_tenderizer();
|
||||
};
|
||||
|
||||
bool find_imported_function_pointer(HMODULE hModule, const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal, void*& ppFunctionAddress);
|
||||
|
||||
void* get_imported_function_pointer(HMODULE hModule, const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal);
|
||||
|
||||
template<typename TFn>
|
||||
TFn** get_imported_function_pointer(HMODULE hModule, const char* pcszDllName, const char* pcszFunctionName, uint32_t hintOrOrdinal) {
|
||||
return reinterpret_cast<TFn**>(get_imported_function_pointer(hModule, pcszDllName, pcszFunctionName, hintOrOrdinal));
|
||||
}
|
||||
|
||||
std::shared_ptr<void> allocate_executable_heap(size_t len);
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -115,7 +165,7 @@ namespace utils {
|
|||
}
|
||||
};
|
||||
|
||||
template<class TElem, class TTraits>
|
||||
template<class TElem, class TTraits = std::char_traits<TElem>>
|
||||
std::basic_string_view<TElem, TTraits> trim(std::basic_string_view<TElem, TTraits> view, bool left = true, bool right = true) {
|
||||
if (left) {
|
||||
while (!view.empty() && (view.front() < 255 && std::isspace(view.front())))
|
||||
|
|
@ -128,6 +178,39 @@ namespace utils {
|
|||
return view;
|
||||
}
|
||||
|
||||
template<class TElem, class TTraits = std::char_traits<TElem>, class TAlloc = std::allocator<TElem>>
|
||||
std::basic_string<TElem, TTraits> trim(std::basic_string<TElem, TTraits> view, bool left = true, bool right = true) {
|
||||
return std::basic_string<TElem, TTraits, TAlloc>(trim(std::basic_string_view<TElem, TTraits>(view), left, right));
|
||||
}
|
||||
|
||||
template<class TElem, class TTraits = std::char_traits<TElem>, class TAlloc = std::allocator<TElem>>
|
||||
[[nodiscard]] std::vector<std::basic_string<TElem, TTraits, TAlloc>> split(const std::basic_string<TElem, TTraits, TAlloc>& str, const std::basic_string_view<TElem, TTraits>& delimiter, size_t maxSplit = SIZE_MAX) {
|
||||
std::vector<std::basic_string<TElem, TTraits, TAlloc>> result;
|
||||
if (delimiter.empty()) {
|
||||
for (size_t i = 0; i < str.size(); ++i)
|
||||
result.push_back(str.substr(i, 1));
|
||||
} else {
|
||||
size_t previousOffset = 0, offset;
|
||||
while (maxSplit && (offset = str.find(delimiter, previousOffset)) != std::string::npos) {
|
||||
result.push_back(str.substr(previousOffset, offset - previousOffset));
|
||||
previousOffset = offset + delimiter.length();
|
||||
--maxSplit;
|
||||
}
|
||||
result.push_back(str.substr(previousOffset));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class TElem, class TTraits = std::char_traits<TElem>, class TAlloc = std::allocator<TElem>>
|
||||
[[nodiscard]] std::vector<std::basic_string<TElem, TTraits, TAlloc>> split(const std::basic_string<TElem, TTraits, TAlloc>& str, const std::basic_string<TElem, TTraits, TAlloc>& delimiter, size_t maxSplit = SIZE_MAX) {
|
||||
return split(str, std::basic_string_view<TElem, TTraits>(delimiter), maxSplit);
|
||||
}
|
||||
|
||||
template<class TElem, class TTraits = std::char_traits<TElem>, class TAlloc = std::allocator<TElem>>
|
||||
[[nodiscard]] std::vector<std::basic_string<TElem, TTraits, TAlloc>> split(const std::basic_string<TElem, TTraits, TAlloc>& str, const TElem* pcszDelimiter, size_t maxSplit = SIZE_MAX) {
|
||||
return split(str, std::basic_string_view<TElem, TTraits>(pcszDelimiter), maxSplit);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get_env(const wchar_t* pcwzName) {
|
||||
static_assert(false);
|
||||
|
|
@ -139,6 +222,9 @@ namespace utils {
|
|||
template<>
|
||||
std::string get_env(const wchar_t* pcwzName);
|
||||
|
||||
template<>
|
||||
int get_env(const wchar_t* pcwzName);
|
||||
|
||||
template<>
|
||||
bool get_env(const wchar_t* pcwzName);
|
||||
|
||||
|
|
@ -147,6 +233,19 @@ namespace utils {
|
|||
return get_env<T>(unicode::convert<std::wstring>(pcszName).c_str());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> get_env_list(const wchar_t* pcwzName) {
|
||||
static_assert(false);
|
||||
}
|
||||
|
||||
template<>
|
||||
std::vector<std::wstring> get_env_list(const wchar_t* pcwzName);
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> get_env_list(const char* pcszName) {
|
||||
return get_env_list<T>(unicode::convert<std::wstring>(pcszName).c_str());
|
||||
}
|
||||
|
||||
bool is_running_on_linux();
|
||||
|
||||
std::filesystem::path get_module_path(HMODULE hModule);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue