diff --git a/include/plib/pe/export_table.hpp b/include/plib/pe/export_table.hpp index c43dbbf..4b2079d 100644 --- a/include/plib/pe/export_table.hpp +++ b/include/plib/pe/export_table.hpp @@ -16,14 +16,19 @@ namespace plib::pe::export_table { class ExportDirectory; + /// @brief Represents an entry in the function table of an export directory. struct FunctionTableEntry { - const intptr_t va; - const DWORD ordinal; - const DWORD rva; - const std::string_view name; - const bool isForwarded; - + const intptr_t va; ///< Virtual address of the function. + const DWORD ordinal; ///< Ordinal number of the function. + const DWORD rva; ///< Relative virtual address of the function. + const std::string_view name; ///< Name of the function. + const bool isForwarded; ///< Indicates if the function is forwarded. + + /// @brief Retrieves the function address as a specific type. + /// @tparam T The type to cast the address to. + /// @return the function address cast to type T. + /// @throws std::runtime_error if the function is forwarded (in debug mode). template PLIB_FORCEINLINE T get() const { @@ -36,25 +41,36 @@ namespace plib::pe::export_table return reinterpret_cast(va); } + /// @brief Checks if the entry is valid. + /// @return true if the entry is valid, false otherwise. PLIB_FORCEINLINE constexpr operator bool() const noexcept { return rva != 0 && !name.empty(); } - + + /// @brief Constructs a function table entry. + /// @param va The virtual address of the function. + /// @param ord The ordinal number of the function. + /// @param rva The relative virtual address of the function. + /// @param name The name of the function. + /// @param isForwarded Indicates if the function is forwarded. constexpr FunctionTableEntry(intptr_t va, WORD ord, DWORD rva, std::string_view name, bool isForwarded) noexcept : va(va), ordinal(ord), rva(rva), name(name), isForwarded(isForwarded) {} + /// @brief Default constructor for an invalid function table entry. constexpr FunctionTableEntry() : va(0), ordinal(0), rva(0), name(""), isForwarded(false) {} constexpr ~FunctionTableEntry() = default; }; + /// @brief Iterator for traversing the function table of an export directory. class ExportDirectoryFunctionTableIterator { private: - const ExportDirectory* exportDir_; - DWORD ordinalIndex_; + const ExportDirectory* exportDir_; ///< Pointer to the export directory being iterated. + DWORD ordinalIndex_; ///< Current index in the function table. + friend class ExportDirectory; constexpr ExportDirectoryFunctionTableIterator(const ExportDirectory& exportDir) noexcept @@ -79,12 +95,13 @@ namespace plib::pe::export_table PLIB_FORCEINLINE FunctionTableEntry operator->() const; }; + /// @brief Represents the export directory of a PE file. class ExportDirectory { private: - const BYTE* _base; - const IMAGE_EXPORT_DIRECTORY* _ied; - const size_t _ied_size; + const BYTE* _base; ///< Base address of the PE image + const IMAGE_EXPORT_DIRECTORY* _ied; ///< Pointer to the IMAGE_EXPORT_DIRECTORY structure + const size_t _ied_size; ///< Size of the IMAGE_EXPORT_DIRECTORY structure friend class ExportDirectoryFunctionTableIterator; ExportDirectory(const BYTE* base, const IMAGE_EXPORT_DIRECTORY* exportDir, size_t ied_size) @@ -92,6 +109,10 @@ namespace plib::pe::export_table public: ~ExportDirectory() = default; + /// @brief Creates an ExportDirectory from a base address. + /// @tparam T The type of the base address. + /// @param base The base address of the PE image. + /// @return An ExportDirectory object. template requires types::HandleLike PLIB_FORCEINLINE static ExportDirectory FromBase(T base) @@ -186,6 +207,12 @@ namespace plib::pe::export_table } }; + /// @brief Get a module export entry by name. + /// @tparam _PredicateT + /// @tparam _BaseT + /// @param base Base address of the module. + /// @param predicate Predicate to match the function entry. + /// @return The matched FunctionTableEntry or std::nullopt if not found. template requires types::HandleLike<_BaseT> && std::is_invocable_r_v PLIB_FORCEINLINE std::optional GetModuleExportEntry(_BaseT base, _PredicateT&& predicate) noexcept @@ -200,34 +227,6 @@ namespace plib::pe::export_table } return std::nullopt; } - - template - requires types::HandleLike - PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const std::string_view& name) noexcept - { - return GetModuleExportEntry(base, ProcAddressNamePredicate {name}); - } - - template - requires types::HandleLike - PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const char* name) noexcept - { - return GetModuleExportEntry(base, ProcAddressNamePredicate {name}); - } - - template - requires types::HandleLike - PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const wchar_t* name) noexcept - { - // Convert wide string to narrow string - CHAR buffer[MAX_PATH] = {0}; - const size_t length = std::wcstombs(buffer, name, sizeof(buffer) - 1); - if (length == static_cast(-1)) { - return std::nullopt; // Conversion failed - } - buffer[length] = '\0'; // Ensure null termination - return GetModuleExportEntry(base, ProcAddressNamePredicate {buffer}); - } } namespace plib::pe::export_table @@ -266,7 +265,6 @@ namespace plib::pe::export_table return functionTable[ordinal]; } - PLIB_FORCEINLINE const WORD ExportDirectory::GetNameOrdinal(DWORD index) const noexcept { if (_ied == nullptr || index >= GetNumberOfNames()) { diff --git a/include/plib/pe/export_utils.hpp b/include/plib/pe/export_utils.hpp index 62bbb66..61c8b2f 100644 --- a/include/plib/pe/export_utils.hpp +++ b/include/plib/pe/export_utils.hpp @@ -22,6 +22,11 @@ static inline const void *to_address(T p) namespace plib::pe::export_utils { + /// @brief Retrieves the module handle of a function. + /// @tparam T The type of the function pointer. + /// @param funcPtr The function pointer to retrieve the module handle for. + /// @return The module handle if found, or std::nullopt if not found. + /// @note This function uses GetModuleHandleExA with the GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS flag. template inline std::optional GetModuleOfFunction(T funcPtr) noexcept { @@ -39,7 +44,11 @@ namespace plib::pe::export_utils return mod; } - // Obtém RVA a partir de um VA (endereço de função, thunk, etc.) + /// @brief Retrieves the RVA (Relative Virtual Address) of a function. + /// @tparam T The type of the function pointer. + /// @param funcPtr The function pointer to retrieve the RVA for. + /// @return The RVA if found, or std::nullopt if not found. + /// @note This function uses GetModuleHandleExA internally template inline std::optional GetRvaOfFunction(T funcPtr) noexcept { @@ -70,6 +79,11 @@ namespace plib::pe::export_utils return static_cast(rva); } + /// @brief Retrieves the ordinal of a function. + /// @tparam T The type of the function pointer. + /// @param funcPtr The function pointer to retrieve the ordinal for. + /// @return The ordinal if found, or std::nullopt if not found. + /// @note This function uses GetModuleHandleExA internally. template std::optional GetOrdinalOfFunction(T funcPtr) noexcept { @@ -109,4 +123,51 @@ namespace plib::pe::export_utils } return std::nullopt; } + + /// @brief Retrieves a module export entry by name. + /// @tparam T The type of the module base address. + /// @tparam Predicate The type of the predicate used for matching. + /// @param base The base address of the module. + /// @param name The name of the exported function. + /// @return The export entry if found, or std::nullopt if not found. + template + requires types::HandleLike + PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const std::string_view& name) noexcept + { + using namespace pe::export_table; + return GetModuleExportEntry(base, ProcAddressNamePredicate {name}); + } + + /// @brief Retrieves a module export entry by name. + /// @tparam T The type of the module base address. + /// @param base The base address of the module. + /// @param name The name of the exported function. + /// @return The export entry if found, or std::nullopt if not found. + template + requires types::HandleLike + PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const char* name) noexcept + { + using namespace pe::export_table; + return GetModuleExportEntry(base, ProcAddressNamePredicate {name}); + } + + /// @brief Retrieves a module export entry by name. + /// @tparam T The type of the module base address. + /// @param base The base address of the module. + /// @param name The name of the exported function. + /// @return The export entry if found, or std::nullopt if not found. + template + requires types::HandleLike + PLIB_FORCEINLINE std::optional GetModuleExportEntryByName(T base, const wchar_t* name) noexcept + { + using namespace pe::export_table; + // Convert wide string to narrow string + CHAR buffer[MAX_PATH] = {0}; + const size_t length = std::wcstombs(buffer, name, sizeof(buffer) - 1); + if (length == static_cast(-1)) { + return std::nullopt; // Conversion failed + } + buffer[length] = '\0'; // Ensure null termination + return GetModuleExportEntry(base, ProcAddressNamePredicate {buffer}); + } } diff --git a/include/plib/pe/import_utils.hpp b/include/plib/pe/import_utils.hpp index 8661893..02260b4 100644 --- a/include/plib/pe/import_utils.hpp +++ b/include/plib/pe/import_utils.hpp @@ -6,6 +6,13 @@ namespace plib::pe::import_utils { + /// @brief Hooks a function in the Import Address Table (IAT) of a PE module. + /// @tparam T The type of the module base address. + /// @param pModBase The base address of the module. + /// @param lpszImportProcName The name of the imported function to hook. + /// @param pfnNewProc The new function to replace the imported function. + /// @param ppfnOldProc A pointer to store the old function pointer. + /// @return True if the hook was successful, false otherwise. template bool PeHookIAT( T pModBase, diff --git a/include/plib/pe/pe_utils.hpp b/include/plib/pe/pe_utils.hpp index aa38cfb..3710b1e 100644 --- a/include/plib/pe/pe_utils.hpp +++ b/include/plib/pe/pe_utils.hpp @@ -8,9 +8,13 @@ namespace plib::pe::utils { + /// @brief Retrieves the NT headers from a given module base address. + /// @tparam T The type of the module base address. + /// @param baseRef The base address of the module. + /// @return A pointer to the NT headers, or nullptr if *baseRef* points to an invalid image. template requires types::HandleLike - inline const IMAGE_NT_HEADERS* GetNtHeaders(const T baseRef) + inline const IMAGE_NT_HEADERS* GetNtHeaders(const T baseRef) noexcept { auto base = reinterpret_cast(baseRef); auto dos = reinterpret_cast(base); @@ -22,6 +26,10 @@ namespace plib::pe::utils return nt; } + /// @brief Retrieves the NT headers from an optional module base address. + /// @tparam T The type of the module base address. + /// @param mod The optional module base address. + /// @return A pointer to the NT headers, or nullptr if not found. template inline const IMAGE_NT_HEADERS * GetNtHeaders(std::optional const &mod) noexcept @@ -29,6 +37,10 @@ namespace plib::pe::utils return mod ? GetNtHeaders(mod.value()) : nullptr; } + /// @brief Retrieves the NT headers from a module base address. + /// @tparam T The type of the module base address. + /// @param hModule The module base address. + /// @return A pointer to the NT headers, or nullptr if not found. template requires pe::types::HandleLike inline const IMAGE_DATA_DIRECTORY* GetExportDirectoryImage(const T hModule) diff --git a/include/plib/proxy_lib.hpp b/include/plib/proxy_lib.hpp index 9bb7e1b..69807a5 100644 --- a/include/plib/proxy_lib.hpp +++ b/include/plib/proxy_lib.hpp @@ -25,6 +25,9 @@ extern volatile LONG g_reflect_ready; extern "C" { #endif // __cplusplus +/// @brief Registers a callback function to be called when a new RL_IMAGE is available. +/// @param callback The callback function to register. If nullptr, unregisters any existing callback. +/// @note It is possible to register only one callback per process. DLL_EXPORT void RegisterProxyCallback(void(*callback)(const RL_IMAGE&)); #ifdef __cplusplus @@ -34,6 +37,8 @@ DLL_EXPORT void RegisterProxyCallback(void(*callback)(const RL_IMAGE&)); #include #include +/// @brief Registers a C++ callable (lambda, function object, etc.) as a proxy callback. +/// @note This is intended for internal use; Don't refer to this namespace directly. namespace proxycb_detail { struct IHandler { @@ -73,6 +78,9 @@ namespace proxycb_detail } } +/// @brief Registers a C++ callable (lambda, function object, etc.) as a proxy callback. +/// @tparam F The type of the callable to register. +/// @param f The callable to register. template inline void RegisterProxyCallbackCpp(F&& f) { using namespace proxycb_detail; @@ -81,6 +89,8 @@ inline void RegisterProxyCallbackCpp(F&& f) { RegisterProxyCallback(&Trampoline); } +/// @brief Unregisters the currently registered proxy callback. +/// @param uninstall_trampoline If true, uninstalls the trampoline function (defaults to true). inline void UnregisterProxyCallbackCpp(bool uninstall_trampoline = true) { using namespace proxycb_detail; g_handler.store(nullptr, std::memory_order_release); diff --git a/include/plib/rl/rl_tls.h b/include/plib/rl/rl_tls.h index 7337853..25d99db 100644 --- a/include/plib/rl/rl_tls.h +++ b/include/plib/rl/rl_tls.h @@ -1,4 +1,3 @@ -// rl/include/rl/rl_tls.h #pragma once #include #include "rl_loader.h"