https://github.com/z3lx/mminhook
A modern C++23 interface for MinHook, with C++20 module support.
https://github.com/z3lx/mminhook
cpp cpp20-modules cpp23 detour detours hooking
Last synced: 2 months ago
JSON representation
A modern C++23 interface for MinHook, with C++20 module support.
- Host: GitHub
- URL: https://github.com/z3lx/mminhook
- Owner: z3lx
- License: mit
- Created: 2025-08-05T18:31:57.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2025-09-19T23:17:37.000Z (6 months ago)
- Last Synced: 2025-09-20T01:31:10.007Z (6 months ago)
- Topics: cpp, cpp20-modules, cpp23, detour, detours, hooking
- Language: C++
- Homepage:
- Size: 48.8 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mminhook
A modern C++23 interface for [MinHook](https://github.com/TsudaKageyu/minhook), with C++20 module support. Provides a lightweight, type-safe, and expressive API with flexible error handling strategies. See the [example](#example) for usage.
## Installation
MMinHook can be installed via CMake's `FetchContent` module.
- `BUILD_SHARED_LIBS` is `OFF` by default to build a static library; set to `ON` for a shared library.
- `MMH_BUILD_MODULES` is `ON` by default to enable module support; set to `OFF` to disable.
- Requires CMake 3.28.2+ and a C++23 compiler with C++20 modules support for module builds.
```cmake
include(FetchContent)
FetchContent_Declare(
mminhook
GIT_REPOSITORY https://github.com/z3lx/mminhook.git
GIT_TAG main
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(mminhook)
add_executable(app)
target_link_libraries(app PRIVATE mmh::mmh)
```
## Usage
Check the [header files](include/mmh) containing the public interface for exact function signatures and template parameters, as they are self-documenting, and developers already familiar with MinHook will find them intuitive.
### Consuming the library
- If using C++20 modules, import the `mmh` module with `import mmh;`.
- If not using modules, include the main header with `#include `.
### Hooking functions
- Use the `mmh::Hook` class template to instantiate an empty (default constructed) hook for a function with return type `Ret` and argument types `Args...`. Any method that manipulates the state of an empty hook will fail.
- Use the `mmh::Hook::Create` static method to create a hook; its input parameters match those of `MH_CreateHook` and `MH_CreateHookApi`, with an additional boolean parameter to specify whether to enable the hook immediately after creation.
- Use the `mmh::Hook::Enable` method to enable or disable the hook.
- Use the `mmh::Hook::CallOriginal` method to call the trampoline to the original function.
- MinHook is initialized automatically when the first hook is created, and uninitialized when the last hook is destroyed.
- Excluding the creation of the hook, all methods are not thread-safe. Without proper synchronization, undefined behavior may occur.
### Error handling
- Methods that may fail provide both throwing and non-throwing variants; non-throwing methods use the `Try*` suffix in their names.
- Throwing methods throw `mmh::Exception` on failure; `mmh::Exception::what` returns a non-owning string describing the error, and `mmh::Exception::GetError` returns an `mmh::Error` representing the error code.
- Non-throwing methods return a `mmh::Result`, which is an alias for `std::expected`; `T` is the type of the return value on success, and `E` is of type `mmh::Error` representing the error code on failure.
- If compiling without exceptions enabled, throwing methods will instead terminate the program.
### Example
Using the library to hook the `GetAsyncKeyState` function from the Windows API:
```cpp
import mmh;
import std;
import ;
mmh::Hook hook {};
SHORT GetAsyncKeyStateHk(const int vKey) noexcept try {
const SHORT state = hook.CallOriginal(vKey);
std::println(
std::cout,
"GetAsyncKeyState called with vKey = 0x{0:02X}, "
"returned with state = 0x{1:04X}",
static_cast(vKey),
static_cast(state)
);
return state;
} catch (...) {
return 0;
}
int main() noexcept try {
hook = mmh::Hook::Create(
GetAsyncKeyState,
GetAsyncKeyStateHk,
true
);
GetAsyncKeyState(VK_RBUTTON);
return 0;
} catch (const mmh::Exception& e) {
std::println(
std::cerr,
"Caught mmh::Exception with error: {}",
e.what()
);
return 1;
}
```
Possible output:
```
GetAsyncKeyState called with vKey = 0x02, returned with state = 0x0000
```
## Attribution
This project uses [`minhook`](https://github.com/TsudaKageyu/minhook), licensed under the BSD-2-Clause License.
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.