aboutsummaryrefslogtreecommitdiff
path: root/libs/usvfs/src/thooklib
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-12 02:40:16 -0500
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-04-12 02:40:16 -0500
commitbf7a57fc55493247a624ecfd65e4d73964e7d8d2 (patch)
tree0a4b2d6123672768187a5ab863e63cd3f21bb319 /libs/usvfs/src/thooklib
parente0fb66428a9b78b4c326df8d7e30429a5b271d74 (diff)
Remove vendored usvfs and Windows-only usvfs code paths
The Linux port uses its own in-process FUSE VFS (FuseConnector), so usvfs was dead weight: libs/usvfs/ was never built, usvfsconnector.cpp was explicitly REMOVE_ITEM'd from the source list, and every call site was already guarded by #ifdef _WIN32 with a working Linux branch (the Windows build is also broken on this branch, since FUSE3 is a hard find_package dependency). - Drop libs/usvfs/ and src/src/usvfsconnector.{cpp,h} - Collapse #ifdef _WIN32 / usvfs include branches in organizercore, mainwindow, settings, util, spawn - Remove getUsvfsVersionString() and the "usvfs: ..." log field - Remove vfs32/64DLLName APPPARAMs (nothing reads them) - Relabel About dialog "usvfs:" row to "VFS: FUSE 3"
Diffstat (limited to 'libs/usvfs/src/thooklib')
-rw-r--r--libs/usvfs/src/thooklib/CMakeLists.txt14
-rw-r--r--libs/usvfs/src/thooklib/asmjit_sane.h29
-rw-r--r--libs/usvfs/src/thooklib/hooklib.cpp740
-rw-r--r--libs/usvfs/src/thooklib/hooklib.h125
-rw-r--r--libs/usvfs/src/thooklib/pch.cpp1
-rw-r--r--libs/usvfs/src/thooklib/ttrampolinepool.cpp601
-rw-r--r--libs/usvfs/src/thooklib/ttrampolinepool.h222
-rw-r--r--libs/usvfs/src/thooklib/udis86wrapper.cpp102
-rw-r--r--libs/usvfs/src/thooklib/udis86wrapper.h62
-rw-r--r--libs/usvfs/src/thooklib/utility.cpp86
-rw-r--r--libs/usvfs/src/thooklib/utility.h35
11 files changed, 0 insertions, 2017 deletions
diff --git a/libs/usvfs/src/thooklib/CMakeLists.txt b/libs/usvfs/src/thooklib/CMakeLists.txt
deleted file mode 100644
index 48426db..0000000
--- a/libs/usvfs/src/thooklib/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-cmake_minimum_required(VERSION 3.16)
-
-find_package(asmjit CONFIG REQUIRED)
-find_library(LIBUDIS86_LIBRARY libudis86)
-find_package(spdlog CONFIG REQUIRED)
-
-file(GLOB sources CONFIGURE_DEPENDS "*.cpp" "*.h")
-source_group("" FILES ${sources})
-
-add_library(thooklib STATIC ${sources})
-target_link_libraries(thooklib PRIVATE shared asmjit::asmjit ${LIBUDIS86_LIBRARY} spdlog::spdlog_header_only)
-target_include_directories(thooklib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
-set_target_properties(thooklib PROPERTIES FOLDER injection)
-target_precompile_headers(shared PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../shared/pch.h)
diff --git a/libs/usvfs/src/thooklib/asmjit_sane.h b/libs/usvfs/src/thooklib/asmjit_sane.h
deleted file mode 100644
index 365622a..0000000
--- a/libs/usvfs/src/thooklib/asmjit_sane.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#pragma warning(push)
-#pragma warning(disable : 4201)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4245)
-#include <asmjit/asmjit.h>
-#include <asmjit/x86.h>
-#pragma warning(pop)
diff --git a/libs/usvfs/src/thooklib/hooklib.cpp b/libs/usvfs/src/thooklib/hooklib.cpp
deleted file mode 100644
index 9dbbafa..0000000
--- a/libs/usvfs/src/thooklib/hooklib.cpp
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "udis86wrapper.h"
-#include <boost/format.hpp>
-#include <boost/predef.h>
-#include <map>
-#pragma warning(push, 3)
-#include <asmjit/asmjit.h>
-#pragma warning(pop)
-#include "hooklib.h"
-#include "ttrampolinepool.h"
-#include "utility.h"
-#include <addrtools.h>
-#include <formatters.h>
-#include <shmlogger.h>
-#include <winapi.h>
-
-#if BOOST_ARCH_X86_64
-#pragma message("64bit build")
-#define JUMP_SIZE 13
-#elif BOOST_ARCH_X86_32
-#define JUMP_SIZE 5
-#else
-#error "unsupported architecture"
-#endif
-
-using namespace asmjit;
-// from here on out I'll only test for 64 or "other"
-
-using namespace HookLib;
-using namespace asmjit;
-
-using namespace usvfs;
-
-struct THookInfo
-{
- LPVOID originalFunction;
- LPVOID replacementFunction;
- LPVOID detour; // detour to call the original function after hook was installed.
- LPVOID trampoline; // code fragment that decides whether the replacement function or
- // detour is executed (preventing endless loops)
- std::vector<uint8_t>
- preamble; // part of the detour that needs to be re-inserted into the original
- // function to return it to vanilla state
- bool stub; // if this is true, the trampoline calls the "replacement"-function that
- // before the original function, not instead of it
- enum
- {
- TYPE_HOTPATCH, // official hot-patch variant as used on 32-bit windows
- TYPE_WIN64PATCH, // custom patch variant used on 64-bit windows
- TYPE_CHAINPATCH, // the hook is part of the hook chain (and not the first)
- TYPE_OVERWRITE, // full jump overwrite used if none of the above work
- TYPE_RIPINDIRECT // the function already started on a rip-relative jump so we only
- // modified that variable
- } type;
-};
-
-UDis86Wrapper& disasm()
-{
- static UDis86Wrapper instance;
- return instance;
-}
-
-void PauseOtherThreads()
-{
- // TODO: implement me!
-}
-
-void ResumePausedThreads()
-{
- // TODO: implement me! should resume only the threads paused by PauseOtherThreads
-}
-
-// not using the disassembler because this is simpler
-LPBYTE ShortJumpTarget(LPBYTE address)
-{
- int8_t off = *(address + 1);
- return address + 2 + off;
-}
-
-size_t GetJumpSize(LPBYTE, LPVOID)
-{
- // TODO: it would be neater to use asmjit to generate this jump and ask asmjit for
- // the size of this jump but with asmjit I can only generate absolute jumps, which
- // take too much space.
-
- // Since trampoline buffers is always allocated within 32-bit
- // address range of jump, we can say with confidence that a 5-byte jump is possible
- return 5;
-}
-
-void WriteLongJump(LPBYTE jumpAddr, LPVOID destination)
-{
- // TODO: not using asmjit here because I couldn't figure out how to generate
- // a working, space-optimized, relative jump to outside the generated code and
- // we do want to optimize this jump
-#if BOOST_ARCH_X86_64
- intptr_t dist = reinterpret_cast<intptr_t>(destination) -
- (reinterpret_cast<intptr_t>(jumpAddr) + 5);
- int32_t distShort = static_cast<int32_t>(dist);
-#else
- int32_t distShort = reinterpret_cast<intptr_t>(destination) -
- (reinterpret_cast<intptr_t>(jumpAddr) + 5);
-#endif
- *jumpAddr = 0xE9;
- *reinterpret_cast<int32_t*>(jumpAddr + 1) = distShort;
-}
-
-void WriteSingleJump(THookInfo& hookInfo, HookError* error)
-{
- DWORD oldprotect, ignore;
- // Set the target function to copy on write, so we don't modify code for other
- // processes
- if (!VirtualProtect(hookInfo.originalFunction, JUMP_SIZE, PAGE_EXECUTE_WRITECOPY,
- &oldprotect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- WriteLongJump(reinterpret_cast<LPBYTE>(hookInfo.originalFunction),
- hookInfo.trampoline);
-
- // restore old memory protection
- if (!VirtualProtect(hookInfo.originalFunction, JUMP_SIZE, oldprotect, &ignore)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- if (error != nullptr) {
- *error = ERR_NONE;
- }
-}
-
-void WriteShortJump(LPBYTE jumpAddr, const signed char offset)
-{
- *jumpAddr = 0xEB;
- *(jumpAddr + 1) = offset;
-}
-
-void WriteIndirectJump(THookInfo& hookInfo, size_t jumpSize, HookError* error)
-{
- DWORD oldProtect = 0;
- LPBYTE jumpAddr = reinterpret_cast<LPBYTE>(hookInfo.originalFunction) - jumpSize;
- // allow write to jump address + the short jump inside the function
- if (!VirtualProtect(jumpAddr, jumpSize + 2, PAGE_EXECUTE_WRITECOPY, &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- // insert the long jump first, then the short jump to the long jump, thus
- // activating the reroute
- WriteLongJump(jumpAddr, hookInfo.trampoline);
-
- PauseOtherThreads();
- WriteShortJump(jumpAddr + jumpSize, -(static_cast<int8_t>(jumpSize) + 2));
- ResumePausedThreads();
-
- // restore access protection
- if (!VirtualProtect(jumpAddr, jumpSize + 2, oldProtect, &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
- if (error != nullptr) {
- *error = ERR_NONE;
- }
-}
-
-/// implements function hooking using the mechanism intended for hot patching
-/// Explanation: the visual studio compiler offers an option to prepare functions
-/// for hot patching. In this case the compiler leaves room for one far jump before
-/// the actual function and a 2-byte nop inside the function.
-/// to hook such a function we write a jump to our replacement function to the
-/// space before the function and short jump to that jump to where the 2-byte nop
-/// was.
-/// On 32-bit windows, MS seems to have compiled all relevant functions in the
-/// windows API for hot patching starting with Windows XP SP3
-/// On 64-bit windows a lot of functions have the space for a jump before the function
-/// but they don't have the 2-byte nop so this function doesn't work
-/// \param hookInfo info about the hook to be installed
-/// \return true on success, false on error
-BOOL HookHotPatch(THookInfo& hookInfo, HookError* error)
-{
- LPVOID original = reinterpret_cast<LPVOID>(hookInfo.originalFunction);
-
- if (hookInfo.stub) {
- hookInfo.trampoline = TrampolinePool::instance().storeStub(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- shared::AddrAdd(original, 2));
- } else {
- hookInfo.trampoline = TrampolinePool::instance().storeTrampoline(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- shared::AddrAdd(original, 2));
- }
-
- WriteIndirectJump(hookInfo, JUMP_SIZE, error);
- hookInfo.type = THookInfo::TYPE_HOTPATCH;
- // in this case we don't need a separate detour, we simply jump past the 2-byte nop
- hookInfo.detour = reinterpret_cast<LPBYTE>(hookInfo.originalFunction) + 2;
-
- return TRUE;
-}
-
-uintptr_t followJumps(THookInfo& hookInfo)
-{
- LPBYTE original = reinterpret_cast<LPBYTE>(hookInfo.originalFunction);
- LPBYTE shortTarget = ShortJumpTarget(original);
-
- // disassemble the long jump
- disasm().setInputBuffer(shortTarget, JUMP_SIZE);
-
- ud_disassemble(disasm());
- if (ud_insn_mnemonic(disasm()) != UD_Ijmp) {
- // this shouldn't happen, we only call this if the jump was discovered before
- throw std::runtime_error("failed to find jump in patch");
- }
-
- uint64_t res = ud_insn_off(disasm()) + ud_insn_len(disasm());
- res += disasm().jumpOffset();
-
- return static_cast<uintptr_t>(res);
-}
-
-///
-/// \brief hook a call that is implemented as a short-jump to a long jump using a
-/// rip-relative address variable
-/// \param hookInfo info about the hook to be installed
-/// \param error if the return code is false and this is not null, the referred-to
-/// variable is set to an error code
-/// \return true on success, false on error
-///
-BOOL HookRIPIndirection(THookInfo& hookInfo, HookError* error)
-{
- uintptr_t res = followJumps(hookInfo);
-
- const ud_operand_t* op = ud_insn_opr(disasm(), 0);
-
- if (op->base != UD_R_RIP) {
- throw std::runtime_error("expected rip-relative addressing");
- }
-
- auto chainNext = disasm().jumpTarget();
- if (hookInfo.stub) {
- hookInfo.trampoline = TrampolinePool::instance().storeStub(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- reinterpret_cast<LPVOID>(chainNext));
- } else {
- hookInfo.trampoline = TrampolinePool::instance().storeTrampoline(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- reinterpret_cast<LPVOID>(chainNext));
- }
-
- DWORD oldProtect = 0;
- if (!VirtualProtect(reinterpret_cast<LPVOID>(res), 2, PAGE_EXECUTE_WRITECOPY,
- &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- *reinterpret_cast<uintptr_t*>(res) = reinterpret_cast<uintptr_t>(hookInfo.trampoline);
-
- if (!VirtualProtect(reinterpret_cast<LPVOID>(res), 2, oldProtect, &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- hookInfo.type = THookInfo::TYPE_RIPINDIRECT;
- hookInfo.detour = reinterpret_cast<LPVOID>(chainNext);
-
- if (error != nullptr) {
- *error = ERR_NONE;
- }
-
- return TRUE;
-}
-
-BOOL HookChainHook(THookInfo& hookInfo, LPBYTE jumpPos, HookError* error)
-{
- // disassemble the long jump
- disasm().setInputBuffer(jumpPos, JUMP_SIZE);
-
- ud_disassemble(disasm());
- if (ud_insn_mnemonic(disasm()) != UD_Ijmp) {
- // this shouldn't happen, we only call this if the jump was discovered before
- throw std::runtime_error("failed to find jump in patch");
- }
-
- auto chainTarget = disasm().jumpTarget();
-
- size_t size = ud_insn_len(disasm());
-
- // save the original code for the preamble so we can restore it later
- hookInfo.preamble.resize(size);
- memcpy(&hookInfo.preamble[0], jumpPos, size);
-
- spdlog::get("usvfs")->info("existing hook to {0:x} in {1}", chainTarget,
- shared::string_cast<std::string>(
- winapi::ex::wide::getSectionName((void*)chainTarget)));
-
- if (hookInfo.stub) {
- hookInfo.trampoline = TrampolinePool::instance().storeStub(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- reinterpret_cast<LPVOID>(chainTarget));
- } else {
- hookInfo.trampoline = TrampolinePool::instance().storeTrampoline(
- hookInfo.replacementFunction,
- reinterpret_cast<LPVOID>(hookInfo.originalFunction),
- reinterpret_cast<LPVOID>(chainTarget));
- }
-
- DWORD oldProtect = 0;
- if (!VirtualProtect(jumpPos, size, PAGE_EXECUTE_WRITECOPY, &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- WriteLongJump(jumpPos, hookInfo.trampoline);
-
- if (!VirtualProtect(jumpPos, size, oldProtect, &oldProtect)) {
- throw std::runtime_error("failed to change virtual protection");
- }
-
- hookInfo.type = THookInfo::TYPE_CHAINPATCH;
- hookInfo.detour = reinterpret_cast<LPVOID>(chainTarget);
-
- if (error != nullptr) {
- *error = ERR_NONE;
- }
-
- return TRUE;
-}
-
-///
-/// implements hooking by chaining to an existing hook
-/// \param hookInfo info about the hook to be installed
-/// \param error if the return code is false and this is not null,
-/// the referred-to variable is set to an error code
-/// \return true on success, false on error
-///
-BOOL HookChainHook(THookInfo& hookInfo, HookError* error)
-{
- return HookChainHook(hookInfo, reinterpret_cast<LPBYTE>(hookInfo.originalFunction),
- error);
-}
-
-///
-/// implements hooking by chaining to an existing hot patch
-/// \param hookInfo info about the hook to be installed
-/// \param error if the return code is false and this is not null,
-/// the referred-to variable is set to an error code
-/// \return true on success, false on error
-///
-BOOL HookChainPatch(THookInfo& hookInfo, HookError* error)
-{
- LPBYTE original = reinterpret_cast<LPBYTE>(hookInfo.originalFunction);
- LPBYTE shortTarget = ShortJumpTarget(original);
-
- return HookChainHook(hookInfo, shortTarget, error);
-}
-
-/// implements function hooking by overwriting the first n bytes of the function
-/// with a jump to the replacement function. Since this is destructive to the original
-/// function code the first n bytes of the function need to be copied somewhere else
-/// and that code needs to be called via a detour. This is a lot more complex than
-/// the hotpatch mechanism.
-/// \param hookInfo info about the hook to be installed
-/// \param error if the return code is false and this is not null, the referred-to
-/// variable is set to an error code
-/// \return true on success, false on error
-BOOL HookDisasm(THookInfo& hookInfo, HookError* error)
-{
- LPBYTE address = reinterpret_cast<LPBYTE>(hookInfo.originalFunction);
- ud_set_input_buffer(disasm(), address, 40);
-
- size_t jumpSize = GetJumpSize(
- static_cast<LPBYTE>(hookInfo.originalFunction),
- TrampolinePool::instance().currentBufferAddress(hookInfo.originalFunction));
-
- // test if we have room for a jump before the function
- bool jumpspace = true;
- for (size_t i = 0; i < jumpSize; ++i) {
- if (*(address - i - 1) != 0x90) {
- jumpspace = false;
- break;
- }
- }
-
- size_t minSize = jumpspace ? 2 : jumpSize;
-
- // iterate over all instructions that overlap with the jump instructions
- // we want to write.
- // TODO right now, this does not test if the function is smaller than the jump.
- size_t size = 0;
- while (size < minSize) {
- if (ud_disassemble(disasm()) == 0) {
- throw std::runtime_error("premature end of file in disassembly");
- }
-
- if ((size == 0) && (ud_insn_mnemonic(disasm()) == UD_Ijmp)) {
- if (error != nullptr) {
- *error = ERR_JUMP;
- }
- return FALSE;
- }
-
- size += ud_insn_len(disasm());
-
- // ret instruction or int3 smells like function end
- if ((ud_insn_mnemonic(disasm()) == UD_Iret) ||
- (ud_insn_mnemonic(disasm()) == UD_Iint3)) {
- if (error != nullptr) {
- *error = ERR_FUNCEND;
- }
- return FALSE;
- }
-
- // check the operands for relative addressing (not supported)
- for (int i = 0; i < 3; ++i) {
- const ud_operand* op = ud_insn_opr(disasm(), i);
- if (op) {
- if (
- // rip-relative are not handled, usually relative jumps
- op->base == UD_R_RIP
-
- // rsp-relative call are not handled (there are valid rsp-relative
- // instructions, e.g. sub)
- || (ud_insn_mnemonic(disasm()) == UD_Icall && op->base == UD_R_RSP)) {
- if (error != nullptr) {
- *error = ERR_RIP;
- }
- return FALSE;
- }
- }
- }
- }
-
- // save the original code for the preamble so we can restore it later
- hookInfo.preamble.resize(size);
- memcpy(&hookInfo.preamble[0], hookInfo.originalFunction, size);
-
- size_t rerouteOffset = 0;
- if (hookInfo.stub) {
- hookInfo.trampoline = TrampolinePool::instance().storeStub(
- hookInfo.replacementFunction, hookInfo.originalFunction, size, &rerouteOffset);
- } else {
- hookInfo.trampoline = TrampolinePool::instance().storeTrampoline(
- hookInfo.replacementFunction, hookInfo.originalFunction, size, &rerouteOffset);
- }
-
- if (jumpspace) {
- WriteIndirectJump(hookInfo, jumpSize, error);
- hookInfo.type = THookInfo::TYPE_WIN64PATCH;
- } else {
- WriteSingleJump(hookInfo, error);
- hookInfo.type = THookInfo::TYPE_OVERWRITE;
- }
- hookInfo.detour = reinterpret_cast<LPBYTE>(hookInfo.trampoline) + rerouteOffset;
-
- return TRUE;
-}
-
-enum EPreamble
-{
- PRE_PATCHFREE,
- PRE_PATCHUSED,
- PRE_RIPINDIRECT,
- PRE_FOREIGNHOOK,
- PRE_UNKNOWN
-};
-
-EPreamble DeterminePreamble(LPBYTE address)
-{
- ud_set_input_buffer(disasm(), address, JUMP_SIZE);
- ud_disassemble(disasm());
-
- if ((ud_insn_mnemonic(disasm()) == UD_Imov) &&
- (ud_insn_opr(disasm(), 0) == ud_insn_opr(disasm(), 1)) &&
- (ud_insn_opr(disasm(), 0)->type == UD_OP_REG)) {
- // mov edi, edi
- return PRE_PATCHFREE;
- } else if ((ud_insn_mnemonic(disasm()) == UD_Ijmp) && (ud_insn_len(disasm()) == 2)) {
- // determine target of the short jump
- LPBYTE shortTarget = ShortJumpTarget(address);
-
- // test if that short jump leads to a long jump
- ud_set_input_buffer(disasm(), shortTarget, JUMP_SIZE);
- ud_disassemble(disasm());
- if (ud_insn_mnemonic(disasm()) == UD_Ijmp) {
- const ud_operand* op = ud_insn_opr(disasm(), 0);
- if (op->base == UD_R_RIP) {
- return PRE_RIPINDIRECT;
- } else {
- return PRE_PATCHUSED;
- }
- } else {
- return PRE_UNKNOWN;
- }
- } else if (ud_insn_mnemonic(disasm()) == UD_Ijmp) {
- return PRE_FOREIGNHOOK;
- } else {
- return PRE_UNKNOWN;
- }
-}
-
-static std::map<HOOKHANDLE, THookInfo> s_Hooks;
-
-static HOOKHANDLE GenerateHandle()
-{
- static ULONG NextHandle = 1;
- return NextHandle++;
-}
-
-HOOKHANDLE applyHook(THookInfo info, HookError* error)
-{
- // apply the correct hook function depending on how the function start looks
- EPreamble preamble = DeterminePreamble((LPBYTE)info.originalFunction);
-
- BOOL success = FALSE;
- switch (preamble) {
- case PRE_PATCHUSED: {
- success = HookChainPatch(info, error);
- } break;
- case PRE_PATCHFREE: {
- success = HookHotPatch(info, error);
- } break;
- case PRE_RIPINDIRECT: {
- success = HookRIPIndirection(info, error);
- } break;
- case PRE_FOREIGNHOOK: {
- success = HookChainHook(info, error);
- } break;
- default: {
- success = HookDisasm(info, error);
- } break;
- }
-
- if (success == TRUE) {
- HOOKHANDLE handle = GenerateHandle();
- s_Hooks[handle] = info;
- return handle;
- } else {
- return INVALID_HOOK;
- }
-}
-
-HOOKHANDLE HookLib::InstallStub(LPVOID functionAddress, LPVOID stubAddress,
- HookError* error)
-{
- if (functionAddress == nullptr) {
- if (error != nullptr)
- *error = ERR_INVALIDPARAMETERS;
- return INVALID_HOOK;
- }
-
- THookInfo info;
- info.originalFunction = functionAddress;
- info.replacementFunction = stubAddress;
- info.stub = true;
- info.detour = nullptr;
- info.trampoline = nullptr;
- info.type = THookInfo::TYPE_OVERWRITE;
-
- return applyHook(info, error);
-}
-
-HOOKHANDLE HookLib::InstallStub(HMODULE module, LPCSTR functionName, LPVOID stubAddress,
- HookError* error)
-{
- LPVOID funcAddr = MyGetProcAddress(module, functionName);
- return InstallStub(funcAddr, stubAddress, error);
-}
-
-HOOKHANDLE HookLib::InstallHook(LPVOID functionAddress, LPVOID hookAddress,
- HookError* error)
-{
- if (functionAddress == nullptr) {
- if (error != nullptr)
- *error = ERR_INVALIDPARAMETERS;
- return INVALID_HOOK;
- }
- THookInfo info;
- info.originalFunction = functionAddress;
- info.replacementFunction = hookAddress;
- info.stub = false;
- info.detour = nullptr;
- info.trampoline = nullptr;
- info.type = THookInfo::TYPE_OVERWRITE;
-
- return applyHook(info, error);
-}
-
-HOOKHANDLE HookLib::InstallHook(HMODULE module, LPCSTR functionName, LPVOID hookAddress,
- HookError* error)
-{
- LPVOID funcAddr = MyGetProcAddress(module, functionName);
- return InstallHook(funcAddr, hookAddress, error);
-}
-
-void HookLib::RemoveHook(HOOKHANDLE handle)
-{
- auto iter = s_Hooks.find(handle);
- if (iter != s_Hooks.end()) {
- THookInfo info = iter->second;
- PauseOtherThreads();
- LPBYTE address = reinterpret_cast<LPBYTE>(info.originalFunction);
- if (info.type == THookInfo::TYPE_HOTPATCH) {
- // return the short jump to 2-byte nop
- // TODO: This doesn't take into account if we chain-loaded another hook
-
- DWORD oldProtect = 0;
- if (!VirtualProtect(address, 2, PAGE_EXECUTE_WRITECOPY, &oldProtect)) {
- throw shared::windows_error("failed to gain write access to remove hook");
- }
- *address = 0x8b;
- *(address + 1) = 0xff;
- VirtualProtect(address, 2, oldProtect, &oldProtect);
- } else if ((info.type == THookInfo::TYPE_OVERWRITE) ||
- (info.type == THookInfo::TYPE_WIN64PATCH)) {
- DWORD oldProtect = 0;
- if (!VirtualProtect(address, info.preamble.size(), PAGE_EXECUTE_WRITECOPY,
- &oldProtect)) {
- throw shared::windows_error("failed to gain write access to remove hook");
- }
- // TODO: remove hook by restoring the original function. This only works if we
- // have the exact code available somewhere
- memcpy(address, &info.preamble[0], info.preamble.size());
- VirtualProtect(address, info.preamble.size(), oldProtect, &oldProtect);
- } else if (info.type == THookInfo::TYPE_CHAINPATCH) {
- // we could attempt to restore the original function preamble but I'm not
- // sure we can reliably write the jump with same (or lower) size.
- // Instead overwrite our own trampoline
- disasm().setInputBuffer(static_cast<uint8_t*>(info.originalFunction), JUMP_SIZE);
- ud_disassemble(disasm());
- if (ud_insn_mnemonic(disasm()) != UD_Ijmp) {
- // this shouldn't happen, we only call this if the jump was discovered before
- throw std::runtime_error("failed to find jump in patch");
- }
-
- LPBYTE jumpPos = static_cast<LPBYTE>(info.originalFunction);
- if (ud_insn_len(disasm()) == 2) {
- jumpPos = reinterpret_cast<LPBYTE>(disasm().jumpTarget());
- }
-
- DWORD oldProtect = 0;
- if (!VirtualProtect(jumpPos, info.preamble.size(), PAGE_EXECUTE_WRITECOPY,
- &oldProtect)) {
- throw shared::windows_error("failed to gain write access to remove hook");
- }
- memcpy(jumpPos, info.preamble.data(), info.preamble.size());
- VirtualProtect(jumpPos, info.preamble.size(), oldProtect, &oldProtect);
- } else if (info.type == THookInfo::TYPE_RIPINDIRECT) {
- uintptr_t res = followJumps(info);
- DWORD oldProtect = 0;
- if (!VirtualProtect(reinterpret_cast<LPVOID>(res), JUMP_SIZE,
- PAGE_EXECUTE_WRITECOPY, &oldProtect)) {
- throw shared::windows_error("failed to gain write access to remove hook");
- }
- *reinterpret_cast<uintptr_t*>(res) =
- reinterpret_cast<uintptr_t>(info.originalFunction);
- VirtualProtect(reinterpret_cast<LPVOID>(res), JUMP_SIZE, oldProtect, &oldProtect);
- } else {
- spdlog::get("usvfs")->critical("can't remove hook, unknown hook type!");
- }
-
- s_Hooks.erase(iter);
- ResumePausedThreads();
- } else {
- spdlog::get("usvfs")->info("handle unknown: {0:x}", handle);
- }
-}
-
-const char* HookLib::GetErrorString(HookError err)
-{
- switch (err) {
- case ERR_NONE:
- return "No Error";
- case ERR_INVALIDPARAMETERS:
- return "Invalid parameters";
- case ERR_FUNCEND:
- return "Function too short";
- case ERR_JUMP:
- return "Function starts on a jump";
- case ERR_RIP:
- return "RIP-relative addressing can't be relocated.";
- case ERR_RELJUMP:
- return "Relative Jump can't be relocated.";
- default:
- return "Unkown error code";
- }
-}
-
-const char* HookLib::GetHookType(HOOKHANDLE handle)
-{
- auto iter = s_Hooks.find(handle);
- if (iter != s_Hooks.end()) {
- THookInfo info = iter->second;
- switch (info.type) {
- case THookInfo::TYPE_HOTPATCH:
- return "hot patch";
- case THookInfo::TYPE_WIN64PATCH:
- return "64-bit hot patch";
- case THookInfo::TYPE_CHAINPATCH:
- return "chained patch";
- case THookInfo::TYPE_OVERWRITE:
- return "overwrite";
- case THookInfo::TYPE_RIPINDIRECT:
- return "rip indirection modified";
- default: {
- spdlog::get("usvfs")->error("invalid hook type {0}", info.type);
- return "invalid hook type";
- }
- }
- }
- return "invalid handle";
-}
-
-LPVOID HookLib::GetDetour(HOOKHANDLE handle)
-{
- auto iter = s_Hooks.find(handle);
- if (iter != s_Hooks.end()) {
- THookInfo info = iter->second;
- return info.detour;
- }
- return nullptr;
-}
diff --git a/libs/usvfs/src/thooklib/hooklib.h b/libs/usvfs/src/thooklib/hooklib.h
deleted file mode 100644
index a549c03..0000000
--- a/libs/usvfs/src/thooklib/hooklib.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include <map>
-#include <windows_sane.h>
-
-namespace HookLib
-{
-
-enum HookError
-{
- ERR_NONE,
- ERR_INVALIDPARAMETERS, // parameters are invalid
- ERR_FUNCEND, // function is too short to be hooked
- ERR_JUMP, // function consists only of an unconditional jump. Maybe it has already
- // been hooked?
- ERR_RIP, // segment of the function to be overwritten contains a instruction-relative
- // operation
- ERR_RELJUMP // segment of the function to be overwritten contains a relative jump we
- // can't relocated
-};
-
-typedef ULONG HOOKHANDLE;
-static const HOOKHANDLE INVALID_HOOK = (HOOKHANDLE)-1;
-
-///
-/// \brief install a stub (function to be called before the target function)
-/// \param functionAddress address of the function to stub
-/// \param stubAddress address of the stub function. This function has to have the
-/// signature of void foobar(LPVOID address).
-/// address receives the address of the function.
-/// \param error (optional) if set, the referenced variable will receive an error code
-/// describing the problem (if any)
-/// \return a handle to reference the hook in later operations or INVALID_HOOK on error
-///
-HOOKHANDLE InstallStub(LPVOID functionAddress, LPVOID stubAddress,
- HookError* error = nullptr);
-
-///
-/// \brief install a stub (function to be called before the target function)
-/// \param module the module containing the function to hook
-/// \param functionName name of the function to stub (as exported by the library)
-/// \param stubAddress address of the stub function. This function has to have the
-/// signature of void foobar(LPVOID address).
-/// address receives the address of the function.
-/// \param error (optional) if set, the referenced variable will receive an error code
-/// describing the problem (if any)
-/// \return a handle to reference the hook in later operations or INVALID_HOOK on error
-///
-HOOKHANDLE InstallStub(HMODULE module, LPCSTR functionName, LPVOID stubAddress,
- HookError* error = nullptr);
-
-///
-/// \brief install a hook (function replacing the existing functionality of the
-/// function)
-/// \param functionAddress address of the function to hook
-/// \param hookAddress address of the replacement function. This function has to have
-/// the exact same signature as the replaced function
-/// \param error (optional) if set, the referenced variable will receive an error code
-/// describing the problem (if any)
-/// \return a handle to reference the hook in later operations or INVALID_HOOK on error
-///
-HOOKHANDLE InstallHook(LPVOID functionAddress, LPVOID hookAddress,
- HookError* error = nullptr);
-
-///
-/// \brief install a hook (function replacing the existing functionality of the
-/// function)
-/// \param functionName name of the function to hook (as exported by the library)
-/// \param hookAddress address of the replacement function. This function has to have
-/// the exact same signature as the replaced function
-/// \param error (optional) if set, the referenced variable will receive an error code
-/// describing the problem (if any)
-/// \return a handle to reference the hook in later operations or INVALID_HOOK on error
-///
-HOOKHANDLE InstallHook(HMODULE module, LPCSTR functionName, LPVOID hookAddress,
- HookError* error = nullptr);
-
-///
-/// \brief remove a hook
-/// \param handle handle returned in InstallStub or InstallHook
-///
-void RemoveHook(HOOKHANDLE handle);
-
-///
-/// \brief determine the type of a hook
-/// \param handle the handle to look up
-/// \return a string describing the used hooking mechanism
-///
-const char* GetHookType(HOOKHANDLE handle);
-
-///
-/// \brief retrieve the address that can be used to directly call a detour
-/// \param handle handle for the hook
-/// \return function address
-///
-LPVOID GetDetour(HOOKHANDLE handle);
-
-///
-/// \brief resolve an error code to a descriptive string
-/// \param err the error code to resolve
-/// \return the error string
-///
-const char* GetErrorString(HookError err);
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/pch.cpp b/libs/usvfs/src/thooklib/pch.cpp
deleted file mode 100644
index 1d9f38c..0000000
--- a/libs/usvfs/src/thooklib/pch.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "pch.h"
diff --git a/libs/usvfs/src/thooklib/ttrampolinepool.cpp b/libs/usvfs/src/thooklib/ttrampolinepool.cpp
deleted file mode 100644
index 3b6a51f..0000000
--- a/libs/usvfs/src/thooklib/ttrampolinepool.cpp
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "ttrampolinepool.h"
-#include <addrtools.h>
-#include <shmlogger.h>
-// #include <boost/thread/lock_guard.hpp>
-#include "udis86wrapper.h"
-
-using namespace asmjit;
-#if BOOST_ARCH_X86_64
-using namespace x86;
-#elif BOOST_ARCH_X86_32
-using namespace asmjit::x86;
-#endif
-
-using namespace usvfs::shared;
-
-namespace HookLib
-{
-
-TrampolinePool* TrampolinePool::s_Instance = nullptr;
-
-TrampolinePool::TrampolinePool() : m_MaxTrampolineSize(sizeof(LPVOID))
-{
- m_BarrierAddr = &TrampolinePool::barrier;
- m_ReleaseAddr = &TrampolinePool::release;
-
- SYSTEM_INFO sysInfo;
- ::ZeroMemory(&sysInfo, sizeof(SYSTEM_INFO));
- GetSystemInfo(&sysInfo);
- m_BufferSize = sysInfo.dwPageSize;
-
- // if search range = ffffff then addressmask = ffffffffff000000
- // => all jumps between xxxxxxxxxx000000 and xxxxxxxxxxffffff will use the same buffer
- // for trampolines which is guaranteed to be in that range
- // TODO it should be valid to use 2 ^ 32 as the search range to increase our chances
- // of finding a memory block we can reserve but then there is a problem with
- // converting negative jump distances to 32 bit I didn't understand. Everything
- // up to 2 ^ 31 seems to be fine though
- m_SearchRange = static_cast<size_t>(pow(2, 30)) - 1;
- m_AddressMask = std::numeric_limits<uint64_t>::max() - m_SearchRange;
-}
-
-// static
-void TrampolinePool::initialize()
-{
- if (!s_Instance)
- s_Instance = new TrampolinePool();
-}
-
-void TrampolinePool::setBlock(bool block)
-{
- m_FullBlock = block;
- if (m_ThreadGuards.get() == nullptr) {
- m_ThreadGuards.reset(new TThreadMap());
- }
-}
-
-#if BOOST_ARCH_X86_64
-// push all registers (except rax) and flags to the stack
-static void pushAll(X86Assembler& assembler)
-{
- assembler.pushf();
- assembler.push(rcx);
- assembler.push(rdx);
- assembler.push(rbx);
- assembler.push(rbp);
- assembler.push(rsi);
- assembler.push(rdi);
- assembler.push(r8);
- assembler.push(r9);
- assembler.push(r10);
- assembler.push(r11);
- assembler.push(r12);
- assembler.push(r13);
- assembler.push(r14);
- assembler.push(r15);
-}
-
-// pop all registers (except rax) and flags from stack
-static void popAll(X86Assembler& assembler)
-{
- assembler.pop(r15);
- assembler.pop(r14);
- assembler.pop(r13);
- assembler.pop(r12);
- assembler.pop(r11);
- assembler.pop(r10);
- assembler.pop(r9);
- assembler.pop(r8);
- assembler.pop(rdi);
- assembler.pop(rsi);
- assembler.pop(rbp);
- assembler.pop(rbx);
- assembler.pop(rdx);
- assembler.pop(rcx);
- assembler.popf();
-}
-#endif // BOOST_ARCH_X86_64
-
-void TrampolinePool::addBarrier(LPVOID rerouteAddr, LPVOID original,
- X86Assembler& assembler)
-{
- Label skipLabel = assembler.newLabel();
-
-#if BOOST_ARCH_X86_64
- pushAll(assembler);
- assembler.mov(rcx,
- imm(reinterpret_cast<int64_t>(
- original))); // set call parameter for call to barrier function
- assembler.mov(rax, imm((intptr_t)(void*)barrier));
- assembler.sub(rsp, 32);
- assembler.call(rax);
- assembler.add(rsp, 32);
- popAll(assembler);
- // test barrier
- assembler.cmp(rax, 0); // test if the barrier is locked
- assembler.jz(skipLabel); // skip if barrier was locked
-
- // call replacement function
- // for this call no registers are saved. the called function is a compiled function so
- // it should correctly save non-volatile registers, and the caller can't expect the
- // volatile ones to remain valid
- assembler.pop(r10);
- assembler.mov(dword_ptr(rax), r10); // store that return address to the variable
- // supplied by the barrier function
- assembler.mov(rax, imm((intptr_t)(LPVOID)rerouteAddr));
- assembler.call(rax);
- assembler.push(rax); // save away result
-
- // open the barrier again
- pushAll(assembler);
- assembler.mov(rcx, imm(reinterpret_cast<int64_t>(original)));
- assembler.mov(rax, imm((intptr_t)(void*)release));
- assembler.sub(rsp, 32);
- assembler.call(rax);
- assembler.add(rsp, 32);
- popAll(assembler);
- assembler.pop(r10); // get the result from the replacement function to a register
- assembler.push(rax); // push the original return address back on the stack
- assembler.mov(rax, r10); // move result of actual call to rax
- assembler.ret(); // return, using the original return address
-#else // BOOST_ARCH_X86_64
- assembler.push(imm(void_ptr_cast<int32_t>(
- original))); // push original function, as parameter to barrier
- assembler.mov(ecx, (Ptr) static_cast<void*>(TrampolinePool::barrier));
- assembler.call(ecx); // call barrier function
- assembler.cmp(eax, 0);
- assembler.jz(skipLabel); // if barrier is locked, jump to end of function
-
- // case a: we got through the barrier
- assembler.pop(ecx); // pop the return address into ecx
- assembler.mov(dword_ptr(eax), ecx); // store that return address in the variable
- // supplied by the barrier function
-
- assembler.mov(eax, (Ptr) static_cast<void*>(rerouteAddr));
- assembler.call(eax); // call replacement function (pointer was stored in front of the
- // trampoline) (this function gets the parameters that were on
- // the stack already and cleans
- // them up itself (stdcall convention))
- assembler.push(eax); // save away result
- assembler.push(imm(void_ptr_cast<int32_t>(original))); // open the barrier again
- assembler.mov(eax, (Ptr) static_cast<void*>(TrampolinePool::release));
- assembler.call(eax);
- assembler.pop(ecx); // pop the result from the actual call to ecx
- assembler.push(eax); // push the original return address (returned by
- // TTrampolinePool::release) back on the stack
- assembler.mov(eax, ecx); // move result of actual call to eax
- assembler.ret(); // return, using the original return address
-#endif // BOOST_ARCH_X86_64
-
- assembler.bind(skipLabel);
-}
-
-LPVOID TrampolinePool::roundAddress(LPVOID address) const
-{
- return reinterpret_cast<LPVOID>(reinterpret_cast<intptr_t>(address) & m_AddressMask);
-}
-
-TrampolinePool::BufferList& TrampolinePool::getBufferList(LPVOID address)
-{
- LPVOID rounded = roundAddress(address);
- auto iter = m_Buffers.find(rounded);
- if (iter == m_Buffers.end()) {
- BufferList newBufList = {0, std::vector<LPVOID>()};
- m_Buffers[rounded] = newBufList;
- iter = allocateBuffer(address);
- }
- return iter->second;
-}
-
-LPVOID TrampolinePool::storeStub(LPVOID reroute, LPVOID original, LPVOID returnAddress)
-{
- BufferList& bufferList = getBufferList(original);
- // first test to increase likelyhood we don't have to reallocate later
- if (bufferList.offset + m_MaxTrampolineSize > m_BufferSize) {
- allocateBuffer(original);
- }
-
- LPVOID spot = AddrAdd(*bufferList.buffers.rbegin(), bufferList.offset);
-
- // ??? write address of reroute to trampoline and move past the address
- *reinterpret_cast<LPVOID*>(spot) = reroute;
- // coverity[suspicious_sizeof]
- spot = AddrAdd(spot, sizeof(LPVOID));
- bufferList.offset += sizeof(LPVOID);
-
- JitRuntime runtime;
-#if BOOST_ARCH_X86_64
- X86Assembler assembler(&runtime);
-#else
- X86Assembler assembler(&runtime);
-#endif
- addCallToStub(assembler, original, reroute);
- addAbsoluteJump(assembler, reinterpret_cast<uint64_t>(returnAddress));
-
- size_t codeSize = assembler.getCodeSize();
-
- m_MaxTrampolineSize =
- std::max(m_MaxTrampolineSize, static_cast<int>(codeSize + sizeof(LPVOID)));
-
- // final test to see if we can store the trampoline in the buffer
- if ((bufferList.offset + codeSize) > m_BufferSize) {
- // can't place function in buffer, allocate another and try again
- allocateBuffer(original);
- // we could relocate the code and the data but this is simpler
- return storeStub(reroute, original, returnAddress);
- }
-
- // adjust relative jumps for move to buffer
- codeSize = assembler.relocCode(spot);
-
- uint8_t* code = assembler.getBuffer();
- memcpy(spot, code, codeSize);
-
- bufferList.offset += codeSize;
-
- return spot;
-}
-
-LPVOID TrampolinePool::storeTrampoline(LPVOID reroute, LPVOID original,
- LPVOID returnAddress)
-{
- BufferList& bufferList = getBufferList(original);
- // first test to increase likelyhood we don't have to reallocate later
- if (bufferList.offset + m_MaxTrampolineSize > m_BufferSize) {
- allocateBuffer(original);
- }
-
- LPVOID spot = AddrAdd(*bufferList.buffers.rbegin(), bufferList.offset);
-
- *reinterpret_cast<LPVOID*>(spot) = reroute;
- // coverity[suspicious_sizeof]
- spot = AddrAdd(spot, sizeof(LPVOID));
- bufferList.offset += sizeof(LPVOID);
-
- JitRuntime runtime;
- X86Assembler assembler(&runtime);
- addBarrier(reroute, original, assembler);
-#if BOOST_ARCH_X86_64
- assembler.mov(rax, imm((intptr_t)(void*)(returnAddress)));
- assembler.jmp(rax);
-#else
- assembler.mov(eax, imm((intptr_t)(void*)(returnAddress)));
- assembler.jmp(eax);
-#endif
- size_t codeSize = assembler.getCodeSize();
-
- m_MaxTrampolineSize =
- std::max(m_MaxTrampolineSize, static_cast<int>(codeSize + sizeof(LPVOID)));
-
- // final test to see if we can store the trampoline in the buffer
- if ((bufferList.offset + codeSize) > m_BufferSize) {
- // can't place function in buffer, allocate another and try again
- allocateBuffer(original);
- // we could relocate the code and the data but this is simpler
- return storeTrampoline(reroute, original, returnAddress);
- }
-
- // adjust relative jumps for move to buffer
- codeSize = assembler.relocCode(spot);
-
- // copy code to buffer
- uint8_t* code = assembler.getBuffer();
- memcpy(spot, code, codeSize);
-
- bufferList.offset += codeSize;
- return spot;
-}
-
-#if BOOST_ARCH_X86_64
-void TrampolinePool::copyCode(X86Assembler& assembler, LPVOID source, size_t numBytes)
-{
- static UDis86Wrapper disasm;
-
- disasm.setInputBuffer(static_cast<const uint8_t*>(source), numBytes);
-
- size_t offset = 0;
-
- while (ud_disassemble(disasm) != 0) {
- // rewrite relative jumps, blind copy everything else
-
- offset += ud_insn_len(disasm);
-
- // WARNING: doesn't support conditional jumps
- if ((ud_insn_mnemonic(disasm) == UD_Ijmp) &&
- (ud_insn_opr(disasm, 0)->type == UD_OP_JIMM)) {
- uintptr_t dest = disasm.jumpTarget();
- assembler.mov(rax, imm(static_cast<uint64_t>(dest)));
- assembler.jmp(rax);
- } else {
- assembler.embed(ud_insn_ptr(&disasm.obj()), ud_insn_len(&disasm.obj()));
- // assembler.data();
- }
- }
-}
-#endif
-
-void TrampolinePool::addCallToStub(X86Assembler& assembler, LPVOID original,
- LPVOID reroute)
-{
-#if BOOST_ARCH_X86_64
- pushAll(assembler);
- assembler.mov(rcx, imm(reinterpret_cast<int64_t>(original)));
- assembler.mov(rax, imm((intptr_t)(LPVOID)reroute));
- assembler.sub(rsp, 32);
- assembler.call(rax);
- assembler.add(rsp, 32);
- popAll(assembler);
-#else // BOOST_ARCH_X86_64
- assembler.push(reinterpret_cast<int64_t>(original));
- assembler.mov(ecx, imm((intptr_t)(LPVOID)reroute));
- assembler.call(ecx);
- assembler.pop(ecx); // remove argument from stack
-#endif // BOOST_ARCH_X86_64
-}
-
-void TrampolinePool::addAbsoluteJump(X86Assembler& assembler, uint64_t destination)
-{
-#if BOOST_ARCH_X86_64
- assembler.push(rax);
- assembler.push(rax);
- assembler.mov(rax, imm(destination));
- assembler.mov(ptr(rsp, 8), rax);
- assembler.pop(rax);
- assembler.ret();
-#else // BOOST_ARCH_X86_64
- assembler.push(imm(destination));
- assembler.ret();
-#endif // BOOST_ARCH_X86_64
-}
-
-LPVOID TrampolinePool::storeStub(LPVOID reroute, LPVOID original, size_t preambleSize,
- size_t* rerouteOffset)
-{
- BufferList& bufferList = getBufferList(original);
- // first test to increase likelyhood we don't have to reallocate later
- if (bufferList.offset + m_MaxTrampolineSize > m_BufferSize) {
- allocateBuffer(original);
- }
-
- LPVOID spot = AddrAdd(*bufferList.buffers.rbegin(), bufferList.offset);
-
- *reinterpret_cast<LPVOID*>(spot) = reroute;
- // coverity[suspicious_sizeof]
- spot = AddrAdd(spot, sizeof(LPVOID));
- bufferList.offset += sizeof(LPVOID);
-
- JitRuntime runtime;
- X86Assembler assembler(&runtime);
- addCallToStub(assembler, original, reroute);
-#if BOOST_ARCH_X86_64
- // insert backup code
- *rerouteOffset = assembler.getCodeSize();
- copyCode(assembler, original, preambleSize);
-#else // BOOST_ARCH_X86_64
- assembler.embed(original, preambleSize);
-#endif // BOOST_ARCH_X86_64
- addAbsoluteJump(assembler, reinterpret_cast<uint64_t>(original) + preambleSize);
-
- // adjust relative jumps for move to buffer
- size_t codeSize = assembler.getCodeSize();
-
- m_MaxTrampolineSize =
- std::max(m_MaxTrampolineSize, static_cast<int>(codeSize + sizeof(LPVOID)));
-
- // final test to see if we can store the trampoline in the buffer
- if ((bufferList.offset + codeSize) > m_BufferSize) {
- // can't place function in buffer, allocate another and try again
- allocateBuffer(original);
- // we could relocate the code and the data but this is simpler
- return storeStub(reroute, original, preambleSize, rerouteOffset);
- }
-
- // copy code to buffer
- codeSize = assembler.relocCode(spot);
-
- bufferList.offset += preambleSize + codeSize;
- return spot;
-}
-
-LPVOID TrampolinePool::storeTrampoline(LPVOID reroute, LPVOID original,
- size_t preambleSize, size_t* rerouteOffset)
-{
- BufferList& bufferList = getBufferList(original);
- // first test to increase likelyhood we don't have to reallocate later
- if (bufferList.offset + m_MaxTrampolineSize > m_BufferSize) {
- allocateBuffer(original);
- }
-
- LPVOID spot = AddrAdd(*bufferList.buffers.rbegin(), bufferList.offset);
-
- *reinterpret_cast<LPVOID*>(spot) = reroute;
- // coverity[suspicious_sizeof]
- spot = AddrAdd(spot, sizeof(LPVOID));
- bufferList.offset += sizeof(LPVOID);
-
- JitRuntime runtime;
- X86Assembler assembler(&runtime);
- addBarrier(reroute, original, assembler);
- // insert backup code
- *rerouteOffset = assembler.getCodeSize();
- assembler.embed(original, static_cast<uint32_t>(preambleSize));
- addAbsoluteJump(assembler, reinterpret_cast<uint64_t>(original) + preambleSize);
-
- // adjust relative jumps for move to buffer
- size_t codeSize = assembler.getCodeSize();
-
- m_MaxTrampolineSize =
- std::max(m_MaxTrampolineSize, static_cast<int>(codeSize + sizeof(LPVOID)));
-
- // TODO this does not take into account that the code size may technically change
- // after relocation in which case the following test may determine the code fits into
- // the buffer when it really doesnt't. asmjit doesn't seem to provide a way to adjust
- // jumps without actually moving the code though
-
- // final test to see if we can store the trampoline in the buffer
- if ((bufferList.offset + codeSize) > m_BufferSize) {
- // can't place function in buffer, allocate another and try again
- allocateBuffer(original);
- // we could relocate the code and the data but this is simpler
- return storeTrampoline(reroute, original, preambleSize, rerouteOffset);
- }
-
- // copy code to buffer
- codeSize = static_cast<size_t>(assembler.relocCode(spot));
-
- bufferList.offset += preambleSize + codeSize;
-
- return spot;
-}
-
-LPVOID TrampolinePool::currentBufferAddress(LPVOID addressNear)
-{
- LPVOID rounded = roundAddress(addressNear);
- auto lookupAddress = m_Buffers.find(rounded);
-
- if (lookupAddress == m_Buffers.end()) {
- lookupAddress = m_Buffers.insert(std::make_pair(rounded, BufferList())).first;
- }
- if (lookupAddress->second.buffers.size() == 0) {
- allocateBuffer(addressNear);
- }
-
- LPVOID res = *(lookupAddress->second.buffers.rbegin());
- return res;
-}
-
-void TrampolinePool::forceUnlockBarrier()
-{
- if (m_ThreadGuards.get() != nullptr) {
- for (auto funcId : *m_ThreadGuards) {
- (*m_ThreadGuards)[funcId.first] = nullptr;
- }
- } // else no barriers to unlock
-}
-
-TrampolinePool::BufferMap::iterator TrampolinePool::allocateBuffer(LPVOID addressNear)
-{
- // allocate a buffer that we can write to and that is executable
- SYSTEM_INFO sysInfo;
- ::ZeroMemory(&sysInfo, sizeof(SYSTEM_INFO));
- GetSystemInfo(&sysInfo);
-
- LPVOID rounded = roundAddress(addressNear);
- auto iter = m_Buffers.find(rounded);
- uintptr_t lowerEnd = reinterpret_cast<uintptr_t>(rounded);
- if (iter->second.buffers.size() > 0) {
- // start searching were we last found a buffer
- lowerEnd = reinterpret_cast<uintptr_t>(*iter->second.buffers.rbegin()) +
- sysInfo.dwPageSize;
- }
-
- uintptr_t start =
- std::max(std::max(lowerEnd, MIN_ALLOC_ADDR),
- reinterpret_cast<uintptr_t>(sysInfo.lpMinimumApplicationAddress));
- uintptr_t upperEnd = reinterpret_cast<uintptr_t>(rounded) + m_SearchRange;
- uintptr_t end = std::min(
- upperEnd, reinterpret_cast<uintptr_t>(sysInfo.lpMaximumApplicationAddress));
-
- LPVOID buffer = nullptr;
- for (uintptr_t cur = start; cur < end; cur += sysInfo.dwPageSize) {
- buffer = VirtualAlloc(reinterpret_cast<LPVOID>(cur), m_BufferSize,
- MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (buffer != nullptr) {
- break;
- }
- }
- if (buffer == nullptr) {
- throw std::runtime_error("failed to allocate buffer in range");
- }
-
- // the caller must have looked up the bufferlist in order to determine that a
- // buffer has to be allocated
- assert(iter != m_Buffers.end());
-
- iter->second.offset = 0;
- iter->second.buffers.push_back(buffer);
- spdlog::get("usvfs")->debug(
- "allocated trampoline buffer for jumps between {0:p} and {1:x} at {2:p}"
- "(size {3})",
- rounded, (reinterpret_cast<uintptr_t>(rounded) + m_SearchRange), buffer,
- m_BufferSize);
- return iter;
-}
-
-LPVOID TrampolinePool::barrier(LPVOID function)
-{
- DWORD err = GetLastError();
- LPVOID res = instance().barrierInt(function);
- SetLastError(err);
- return res;
-}
-
-LPVOID TrampolinePool::release(LPVOID function)
-{
- DWORD err = GetLastError();
- LPVOID res = instance().releaseInt(function);
- SetLastError(err);
- return res;
-}
-
-LPVOID TrampolinePool::barrierInt(LPVOID func)
-{
- if (m_FullBlock) {
- return nullptr;
- }
-
- if (m_ThreadGuards.get() == nullptr) {
- m_ThreadGuards.reset(new TThreadMap());
- }
-
- auto iter = m_ThreadGuards->find(func);
- if ((iter == m_ThreadGuards->end()) || (iter->second == nullptr)) {
- (*m_ThreadGuards)[func] = reinterpret_cast<LPVOID>(1);
- return &(*m_ThreadGuards)[func];
- } else {
- return nullptr;
- }
-}
-
-LPVOID TrampolinePool::releaseInt(LPVOID func)
-{
- DWORD lastError = GetLastError();
- if (m_ThreadGuards.get() == nullptr) {
- m_ThreadGuards.reset(new TThreadMap());
- }
-
- auto iter = m_ThreadGuards->find(func);
- if (iter == m_ThreadGuards->end()) {
- spdlog::get("hooks")->error("failed to release barrier for func {}", func);
- ::SetLastError(lastError);
- return nullptr;
- }
-
- LPVOID res = (*m_ThreadGuards)[func];
- (*m_ThreadGuards)[func] = nullptr;
-
- ::SetLastError(lastError);
- return res;
-}
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/ttrampolinepool.h b/libs/usvfs/src/thooklib/ttrampolinepool.h
deleted file mode 100644
index 5b44c51..0000000
--- a/libs/usvfs/src/thooklib/ttrampolinepool.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include "asmjit_sane.h"
-#include <logging.h>
-#include <map>
-#include <vector>
-#include <windows_sane.h>
-
-#ifdef _MSC_VER
-#pragma warning(disable : 4714)
-#include <boost/config/compiler/visualc.hpp>
-#else
-#include <boost/config/compiler/gcc.hpp>
-#endif
-#include <boost/predef.h>
-#include <boost/thread.hpp>
-#include <mutex>
-
-// #include <boost/thread/mutex.hpp>
-
-namespace HookLib
-{
-
-///
-/// trampolines are runtime-generated mini-functions that are used to call the
-/// original code of a function
-///
-class TrampolinePool
-{
-public:
- /// Call initialize before you use the TrampolinePool
- static void initialize();
-
- static TrampolinePool& instance()
- {
- // This is a very very sensitive place so we want to keep this function as simple as
- // possible and having it inlined probably cann't hurt
- return *s_Instance;
- }
-
- void setBlock(bool block);
-
- ///
- /// store a stub without moving code from the original function. This is used in cases
- /// where the hook can be placed without overwriting logic (i.e. hot-patchable
- /// functions and when chaining hooks)
- /// \param reroute the stub function to call before the regular function (on x86 this
- /// needs to be cdecl calling convention!)
- /// \param original the original function
- /// \param returnAddress address under which the original functionality can be
- /// reached.
- /// for the first hook this should be (original + 2), otherwise
- /// the address of the next hook in the chain
- /// \return address of the created trampoline function
- ///
- LPVOID storeStub(LPVOID reroute, LPVOID original, LPVOID returnAddress);
-
- ///
- /// store a stub, moving part of the original function to the trampoline
- /// \param reroute the stub function to call before the regular function (on x86 this
- /// needs to be cdecl calling convention!)
- /// \param original the original function
- /// \param preambleSize number of bytes from the original function to backup. Needs to
- /// correspond to complete instructions
- /// \param rerouteOffset offset in bytes from the created trampoline to the preamble
- /// that leads back to the original code
- /// \return address of the created trampoline function
- ///
- LPVOID storeStub(LPVOID reroute, LPVOID original, size_t preambleSize,
- size_t* rerouteOffset);
-
- ///
- /// store a trampoline for hot-patchable functions, where the original function
- /// is unharmed.
- /// \param reroute the reroute function
- /// \param original original function
- /// \param returnAddress address under which the original functionality can be
- /// reached.
- /// \return address of the trampoline function
- ///
- LPVOID storeTrampoline(LPVOID reroute, LPVOID original, LPVOID returnAddress);
-
- ///
- /// store a trampoline, copying a part of the original function to the trampoline.
- /// This is used for the case where the hooking mechanism needs to overwrite part of
- /// the function
- /// \param reroute the reroute function
- /// \param original original function
- /// \param preambleSize number of bytes from the original function to backup. Needs to
- /// correspond to complete instructions
- /// \param rerouteOffset offset in bytes from the created trampoline to the preamble
- /// that leads us back to the original code
- /// \return address of the trampoline function
- ///
- LPVOID storeTrampoline(LPVOID reroute, LPVOID original, size_t preambleSize,
- size_t* rerouteOffset);
-
- ///
- /// \param addressNear used to find a trampoline buffer near the jump instruction
- /// \return retrieve address of current trampoline buffer
- ///
- LPVOID currentBufferAddress(LPVOID addressNear);
-
- ///
- /// \brief forces the barrier(s) for the current thread to be released
- ///
- void forceUnlockBarrier();
-
-private:
- struct BufferList
- {
- size_t offset;
- std::vector<LPVOID> buffers;
- };
-
- typedef std::map<LPVOID, BufferList> BufferMap;
- static const intptr_t ADDRESS_MASK =
- 0xFFFFFFFFFF000000LL; // mask to "round" addresses to consolidate near
- // trampolines
-
-private:
- TrampolinePool();
-
- TrampolinePool& operator=(const TrampolinePool& reference); // not implemented
-
- /**
- * @brief allocates a buffer with read, write and execute rights near the
- * specified adress. The purpose is that we want to be able to jump from
- * adressNear to generated code with a 5-byte jump, even on x64 systems.
- * @param addressNear the reference adress
- * @note the resulting buffer is stored in the m_Buffers map
- */
- BufferMap::iterator allocateBuffer(LPVOID addressNear);
-
- void addBarrier(LPVOID rerouteAddr, LPVOID original, asmjit::X86Assembler& assembler);
-
-#if BOOST_ARCH_X86_64
- void copyCode(asmjit::X86Assembler& assembler, LPVOID source, size_t numBytes);
-#endif // BOOST_ARCH_X86_64
-
- BufferList& getBufferList(LPVOID address);
-
- LPVOID roundAddress(LPVOID address) const;
-
-public:
- static LPVOID __stdcall barrier(LPVOID function);
- static LPVOID __stdcall release(LPVOID function);
-
- LPVOID barrierInt(LPVOID function);
- LPVOID releaseInt(LPVOID function);
-
- void addCallToStub(asmjit::X86Assembler& assembler, LPVOID original, LPVOID reroute);
-
-private:
- ///
- /// \brief add a jump to an address outside the custom generated asm code (without
- /// modifying registers)
- /// \param assembler the assembler generator to write to
- /// \param destination destination address
- /// \note this currently generates a lot code on x64, may be overly complicated
- ///
- void addAbsoluteJump(asmjit::X86Assembler& assembler, uint64_t destination);
-
- DWORD determinePageSize();
-
-private:
-#if BOOST_ARCH_X86_64
- static const int SIZE_OF_JUMP = 13;
-#elif BOOST_ARCH_X86_32
- static const int SIZE_OF_JUMP = 5;
-#endif
-
- // the hook lib tries to allocate buffer close to the hooked functions,
- // for 32-bits application, this often falls on 0x40000000, which is the
- // address at which DLLs can be loaded on Windows
- //
- // some old-style DRM (e.g. Dragon Age 2) check that address and prevent
- // the game from running if it's not 0x40000000, so we give them a bit of
- // spaces before allocating our buffers
- //
- static constexpr uintptr_t MIN_ALLOC_ADDR = 0x40000000 + 0x200000;
-
- static TrampolinePool* s_Instance;
-
- bool m_FullBlock{false};
-
- BufferMap m_Buffers;
-
- typedef std::map<void*, void*> TThreadMap;
- boost::thread_specific_ptr<TThreadMap> m_ThreadGuards;
-
- LPVOID m_BarrierAddr;
- LPVOID m_ReleaseAddr;
-
- DWORD m_BufferSize = {1024};
- size_t m_SearchRange;
- uint64_t m_AddressMask;
-
- int m_MaxTrampolineSize;
-};
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/udis86wrapper.cpp b/libs/usvfs/src/thooklib/udis86wrapper.cpp
deleted file mode 100644
index 1ac7332..0000000
--- a/libs/usvfs/src/thooklib/udis86wrapper.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "udis86wrapper.h"
-#include "pch.h"
-#include <boost/predef.h>
-#include <shmlogger.h>
-#include <stdexcept>
-
-namespace HookLib
-{
-
-UDis86Wrapper::UDis86Wrapper()
-{
- ud_init(&m_Obj);
- ud_set_syntax(&m_Obj, UD_SYN_INTEL);
-#if BOOST_ARCH_X86_64
- ud_set_mode(&m_Obj, 64);
-#else
- ud_set_mode(&m_Obj, 32);
-#endif
-}
-
-void UDis86Wrapper::setInputBuffer(const uint8_t* buffer, size_t size)
-{
- m_Buffer = buffer;
- ud_set_input_buffer(&m_Obj, buffer, size);
- ud_set_pc(&m_Obj, reinterpret_cast<uint64_t>(m_Buffer));
-}
-
-ud_t& UDis86Wrapper::obj()
-{
- return m_Obj;
-}
-
-bool UDis86Wrapper::isRelativeJump()
-{
- ud_mnemonic_code code = ud_insn_mnemonic(&m_Obj);
- // all conditional jumps and loops are relative, as are unconditional jumps with an
- // offset operand
- return (code == UD_Ijo) || (code == UD_Ijno) || (code == UD_Ijb) ||
- (code == UD_Ijae) || (code == UD_Ijz) || (code == UD_Ijnz) ||
- (code == UD_Ijbe) || (code == UD_Ija) || (code == UD_Ijs) ||
- (code == UD_Ijns) || (code == UD_Ijp) || (code == UD_Ijnp) ||
- (code == UD_Ijl) || (code == UD_Ijge) || (code == UD_Ijle) ||
- (code == UD_Ijg) || (code == UD_Ijcxz) || (code == UD_Ijecxz) ||
- (code == UD_Ijrcxz) || (code == UD_Iloop) || (code == UD_Iloope) ||
- (code == UD_Iloopne) ||
- ((code == UD_Icall) && (ud_insn_opr(&m_Obj, 0)->type == UD_OP_JIMM)) ||
- ((code == UD_Ijmp) && (ud_insn_opr(&m_Obj, 0)->type == UD_OP_JIMM));
-}
-
-intptr_t UDis86Wrapper::jumpOffset()
-{
- const ud_operand_t* op = ud_insn_opr(&m_Obj, 0);
- switch (op->size) {
- case 8:
- return static_cast<intptr_t>(op->lval.sbyte);
- case 16:
- return static_cast<intptr_t>(op->lval.sword);
- case 32:
- return static_cast<intptr_t>(op->lval.sdword);
- case 64:
- return static_cast<intptr_t>(op->lval.sqword);
- default:
- throw std::runtime_error("unsupported jump size");
- }
-}
-
-uint64_t UDis86Wrapper::jumpTarget()
-{
- // TODO: assert we're actually on a jump
-
- uint64_t res = ud_insn_off(&m_Obj) + ud_insn_len(&m_Obj);
-
- res += jumpOffset();
-
- if (ud_insn_opr(&m_Obj, 0)->base == UD_R_RIP) {
- res = *reinterpret_cast<uintptr_t*>(res);
- }
-
- return res;
-}
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/udis86wrapper.h b/libs/usvfs/src/thooklib/udis86wrapper.h
deleted file mode 100644
index 48d8a42..0000000
--- a/libs/usvfs/src/thooklib/udis86wrapper.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include <udis86.h>
-#undef inline // libudis86/types.h defines inline to __inline which is no longer legal
- // since vs2012
-
-namespace HookLib
-{
-
-class UDis86Wrapper
-{
-
-public:
- UDis86Wrapper();
-
- void setInputBuffer(const uint8_t* buffer, size_t size);
-
- ud_t& obj();
-
- operator ud_t*() { return &m_Obj; }
-
- bool isRelativeJump();
-
- intptr_t jumpOffset();
-
- ///
- /// determines the absolute jump target at the current instruction, taking into
- /// account relative instructions of all sizes and RIP-relative addressing.
- /// \return absolute address of the jump at the current disassembler instruction
- /// \note this works correctly ONLY if the input buffer has been set with
- /// setInputBuffer or
- /// if ud_set_pc has been called
- ///
- uint64_t jumpTarget();
-
-private:
-private:
- ud_t m_Obj;
- const uint8_t* m_Buffer{nullptr};
-};
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/utility.cpp b/libs/usvfs/src/thooklib/utility.cpp
deleted file mode 100644
index 124141f..0000000
--- a/libs/usvfs/src/thooklib/utility.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "utility.h"
-#include "exceptionex.h"
-#include <cstdlib>
-
-namespace HookLib
-{
-
-FARPROC MyGetProcAddress(HMODULE module, LPCSTR functionName)
-{
- // determine position of the exports of the module
- PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)module;
- if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
- return nullptr;
- }
-
- PIMAGE_NT_HEADERS ntHeaders =
- (PIMAGE_NT_HEADERS)(((LPBYTE)dosHeader) + dosHeader->e_lfanew);
- if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
- return nullptr;
- }
-
- PIMAGE_OPTIONAL_HEADER optionalHeader = &ntHeaders->OptionalHeader;
- if (optionalHeader->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) {
- return nullptr;
- }
- PIMAGE_DATA_DIRECTORY dataDirectory =
- &optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
- PIMAGE_EXPORT_DIRECTORY exportDirectory =
- (PIMAGE_EXPORT_DIRECTORY)((LPBYTE)dosHeader + dataDirectory->VirtualAddress);
-
- ULONG* addressOfNames = (ULONG*)((LPBYTE)module + exportDirectory->AddressOfNames);
- ULONG* funcAddr = (ULONG*)((LPBYTE)module + exportDirectory->AddressOfFunctions);
-
- // search exports for the specified name
- for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i) {
- char* curFunctionName = (char*)((LPBYTE)module + addressOfNames[i]);
- USHORT* nameOrdinals =
- (USHORT*)((LPBYTE)module + exportDirectory->AddressOfNameOrdinals);
- if (strcmp(functionName, curFunctionName) == 0) {
- if (funcAddr[nameOrdinals[i]] >= dataDirectory->VirtualAddress &&
- funcAddr[nameOrdinals[i]] <
- dataDirectory->VirtualAddress + dataDirectory->Size) {
- char* forwardLibName = _strdup((LPSTR)module + funcAddr[nameOrdinals[i]]);
- ON_BLOCK_EXIT([forwardLibName]() {
- free(forwardLibName);
- });
- char* forwardFunctionName = strchr(forwardLibName, '.');
- *forwardFunctionName = 0;
- ++forwardFunctionName;
-
- HMODULE forwardLib = LoadLibraryA(forwardLibName);
- FARPROC forward = nullptr;
- if (forwardLib != nullptr) {
- forward = MyGetProcAddress(forwardLib, forwardFunctionName);
- FreeLibrary(forwardLib);
- }
-
- return forward;
- }
- return (FARPROC)((LPBYTE)module + funcAddr[nameOrdinals[i]]);
- }
- }
- return nullptr;
-}
-
-} // namespace HookLib
diff --git a/libs/usvfs/src/thooklib/utility.h b/libs/usvfs/src/thooklib/utility.h
deleted file mode 100644
index e0be9f7..0000000
--- a/libs/usvfs/src/thooklib/utility.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Userspace Virtual Filesystem
-
-Copyright (C) 2015 Sebastian Herbord. All rights reserved.
-
-This file is part of usvfs.
-
-usvfs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-usvfs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with usvfs. If not, see <http://www.gnu.org/licenses/>.
-*/
-#pragma once
-
-#include <windows_sane.h>
-
-namespace HookLib
-{
-
-/// \brief reimplementation of GetProcAddress to circumvent foreign hooks of
-/// GetProcAddress like AcLayer
-/// \param module handle to the module that contains the function or variable
-/// \param functionName function to retrieve the address of
-/// \return address of the exported function
-FARPROC MyGetProcAddress(HMODULE module, LPCSTR functionName);
-
-} // namespace HookLib