diff --git a/recipes/minhook/all/conandata.yml b/recipes/minhook/all/conandata.yml new file mode 100644 index 0000000000000..9fbac6aa78698 --- /dev/null +++ b/recipes/minhook/all/conandata.yml @@ -0,0 +1,4 @@ +sources: + "1.3.3.cci.20240629": + url: "https://github.com/TsudaKageyu/minhook/archive/91cc9466e383d13a43d7cf33c7c8fdccb27095d3.tar.gz" + sha256: "b84b2ff19afe5fb9430948680146bee2e198392ee6333a71f81e339c36a819f1" diff --git a/recipes/minhook/all/conanfile.py b/recipes/minhook/all/conanfile.py new file mode 100644 index 0000000000000..73c08a93a80d6 --- /dev/null +++ b/recipes/minhook/all/conanfile.py @@ -0,0 +1,69 @@ +import os + +from conan import ConanFile +from conan.errors import ConanInvalidConfiguration +from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout +from conan.tools.files import copy, get, rmdir + +required_conan_version = ">=1.53.0" + + +class PackageConan(ConanFile): + name = "minhook" + description = "The Minimalistic x86/x64 API Hooking Library for Windows" + license = "BSD-2-Clause" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/TsudaKageyu/minhook" + topics = ("hook", "windows") + package_type = "library" + settings = "os", "arch", "compiler", "build_type" + options = { + "shared": [True, False], + } + default_options = { + "shared": False, + } + + def configure(self): + # minhook is a plain C projects + self.settings.rm_safe("compiler.cppstd") + self.settings.rm_safe("compiler.libcxx") + + def layout(self): + cmake_layout(self, src_folder="src") + + def validate(self): + if self.settings.os != "Windows": + raise ConanInvalidConfiguration(f"{self.ref} can only be built on Windows.") + + if self.settings.arch not in ["x86", "x86_64"]: + raise ConanInvalidConfiguration(f"{self.ref} can only be built on x86 or x86_64 architectures.") + + def source(self): + get(self, **self.conan_data["sources"][self.version], strip_root=True) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy(self, "LICENSE.txt", self.source_folder, os.path.join(self.package_folder, "licenses")) + cmake = CMake(self) + cmake.install() + + rmdir(self, os.path.join(self.package_folder, "lib", "minhook")) + + def package_info(self): + if self.settings.arch == "x86_64": + postfix = ".x64d" if self.settings.build_type == "Debug" else ".x64" + else: + postfix = ".x32d" if self.settings.build_type == "Debug" else ".x32" + + self.cpp_info.libs = [f"minhook{postfix}"] diff --git a/recipes/minhook/all/test_package/CMakeLists.txt b/recipes/minhook/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..a090c65f0323b --- /dev/null +++ b/recipes/minhook/all/test_package/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) + +project(test_package LANGUAGES CXX) + +find_package(minhook REQUIRED CONFIG) + +add_executable(${PROJECT_NAME} test_package.cpp) +target_link_libraries(${PROJECT_NAME} PRIVATE minhook::minhook) diff --git a/recipes/minhook/all/test_package/conanfile.py b/recipes/minhook/all/test_package/conanfile.py new file mode 100644 index 0000000000000..d7de1f914ce42 --- /dev/null +++ b/recipes/minhook/all/test_package/conanfile.py @@ -0,0 +1,27 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import cmake_layout, CMake + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindir, "test_package") + self.run(bin_path, env="conanrun") diff --git a/recipes/minhook/all/test_package/test_package.cpp b/recipes/minhook/all/test_package/test_package.cpp new file mode 100644 index 0000000000000..95ccf7f207da6 --- /dev/null +++ b/recipes/minhook/all/test_package/test_package.cpp @@ -0,0 +1,75 @@ +#include + +#include + +#include "MinHook.h" + +typedef int(WINAPI *MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT); + +// Pointer for calling original MessageBoxW. +MESSAGEBOXW fpMessageBoxW = NULL; + +// Dummy MessageBox function for testing. +int WINAPI DummyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) +{ + const int box_width = 40; + std::wstring text(lpText); + std::wstring caption(lpCaption); + + // Top border + std::wcout << "+" << std::wstring(box_width - 2, '-') << "+\n"; + + // Caption + std::wcout << "| " << caption << std::wstring(box_width - 3 - caption.size(), ' ') << "|\n"; + std::wcout << "| " << std::wstring(box_width - 4, '=') << " |\n"; + + // Text + std::wcout << "| " << text << std::wstring(box_width - 3 - text.size(), ' ') << "|\n"; + + // Bottom border + std::wcout << "+" << std::wstring(box_width - 2, '-') << "+\n"; + + return IDOK; // The OK button was selected. +} + +// Detour function which overrides MessageBoxW. +int WINAPI DetourMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) +{ + return fpMessageBoxW(hWnd, L"Hooked!", lpCaption, uType); +} + +int main() +{ + // Initialize MinHook. + if (MH_Initialize() != MH_OK) { + return 1; + } + + // Create a hook for MessageBoxW, in disabled state. + if (MH_CreateHook(&DummyMessageBoxW, &DetourMessageBoxW, reinterpret_cast(&fpMessageBoxW)) != MH_OK) { + return 1; + } + + // Enable the hook for MessageBoxW. + if (MH_EnableHook(&DummyMessageBoxW) != MH_OK) { + return 1; + } + + // Expected to tell "Hooked!". + DummyMessageBoxW(NULL, L"Not hooked...", L"MinHook Sample", MB_OK); + + // Disable the hook for MessageBoxW. + if (MH_DisableHook(&DummyMessageBoxW) != MH_OK) { + return 1; + } + + // Expected to tell "Not hooked...". + DummyMessageBoxW(NULL, L"Not hooked...", L"MinHook Sample", MB_OK); + + // Uninitialize MinHook. + if (MH_Uninitialize() != MH_OK) { + return 1; + } + + return 0; +} diff --git a/recipes/minhook/config.yml b/recipes/minhook/config.yml new file mode 100644 index 0000000000000..36b74a86356a1 --- /dev/null +++ b/recipes/minhook/config.yml @@ -0,0 +1,3 @@ +versions: + "1.3.3.cci.20240629": + folder: all