From bf7a57fc55493247a624ecfd65e4d73964e7d8d2 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Sun, 12 Apr 2026 02:40:16 -0500 Subject: 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" --- libs/usvfs/src/thooklib/hooklib.cpp | 740 ------------------------------------ 1 file changed, 740 deletions(-) delete mode 100644 libs/usvfs/src/thooklib/hooklib.cpp (limited to 'libs/usvfs/src/thooklib/hooklib.cpp') 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 . -*/ -#include "udis86wrapper.h" -#include -#include -#include -#pragma warning(push, 3) -#include -#pragma warning(pop) -#include "hooklib.h" -#include "ttrampolinepool.h" -#include "utility.h" -#include -#include -#include -#include - -#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 - 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(destination) - - (reinterpret_cast(jumpAddr) + 5); - int32_t distShort = static_cast(dist); -#else - int32_t distShort = reinterpret_cast(destination) - - (reinterpret_cast(jumpAddr) + 5); -#endif - *jumpAddr = 0xE9; - *reinterpret_cast(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(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(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(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(hookInfo.originalFunction); - - if (hookInfo.stub) { - hookInfo.trampoline = TrampolinePool::instance().storeStub( - hookInfo.replacementFunction, - reinterpret_cast(hookInfo.originalFunction), - shared::AddrAdd(original, 2)); - } else { - hookInfo.trampoline = TrampolinePool::instance().storeTrampoline( - hookInfo.replacementFunction, - reinterpret_cast(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(hookInfo.originalFunction) + 2; - - return TRUE; -} - -uintptr_t followJumps(THookInfo& hookInfo) -{ - LPBYTE original = reinterpret_cast(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(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(hookInfo.originalFunction), - reinterpret_cast(chainNext)); - } else { - hookInfo.trampoline = TrampolinePool::instance().storeTrampoline( - hookInfo.replacementFunction, - reinterpret_cast(hookInfo.originalFunction), - reinterpret_cast(chainNext)); - } - - DWORD oldProtect = 0; - if (!VirtualProtect(reinterpret_cast(res), 2, PAGE_EXECUTE_WRITECOPY, - &oldProtect)) { - throw std::runtime_error("failed to change virtual protection"); - } - - *reinterpret_cast(res) = reinterpret_cast(hookInfo.trampoline); - - if (!VirtualProtect(reinterpret_cast(res), 2, oldProtect, &oldProtect)) { - throw std::runtime_error("failed to change virtual protection"); - } - - hookInfo.type = THookInfo::TYPE_RIPINDIRECT; - hookInfo.detour = reinterpret_cast(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( - winapi::ex::wide::getSectionName((void*)chainTarget))); - - if (hookInfo.stub) { - hookInfo.trampoline = TrampolinePool::instance().storeStub( - hookInfo.replacementFunction, - reinterpret_cast(hookInfo.originalFunction), - reinterpret_cast(chainTarget)); - } else { - hookInfo.trampoline = TrampolinePool::instance().storeTrampoline( - hookInfo.replacementFunction, - reinterpret_cast(hookInfo.originalFunction), - reinterpret_cast(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(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(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(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(hookInfo.originalFunction); - ud_set_input_buffer(disasm(), address, 40); - - size_t jumpSize = GetJumpSize( - static_cast(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(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 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(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(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(info.originalFunction); - if (ud_insn_len(disasm()) == 2) { - jumpPos = reinterpret_cast(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(res), JUMP_SIZE, - PAGE_EXECUTE_WRITECOPY, &oldProtect)) { - throw shared::windows_error("failed to gain write access to remove hook"); - } - *reinterpret_cast(res) = - reinterpret_cast(info.originalFunction); - VirtualProtect(reinterpret_cast(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; -} -- cgit v1.3.1