diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e1618173f..7d95f82f9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: DEPENDENCIES_FOLDER: dependencies DEPENDENCIES_ROOT: ${{ github.workspace }}/dependencies MYSQL_VERSION: '5.7' - MMSOURCE_VERSION: '1.12' + MMSOURCE_VERSION: '2.0' steps: - uses: actions/checkout@v6 with: diff --git a/.github/workflows/mocktest.yml b/.github/workflows/mocktest.yml index f5e85241c2..2a116fad8e 100644 --- a/.github/workflows/mocktest.yml +++ b/.github/workflows/mocktest.yml @@ -22,6 +22,7 @@ jobs: name: Clone metamod-source with: repository: alliedmodders/metamod-source + ref: k/sourcehook_alternative submodules: recursive path: metamod-source diff --git a/.gitmodules b/.gitmodules index dce1debb8a..7012fa8486 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,6 +9,6 @@ [submodule "hl2sdk-manifests"] path = hl2sdk-manifests url = https://github.com/alliedmodders/hl2sdk-manifests.git -[submodule "public/safetyhook"] - path = public/safetyhook - url = https://github.com/alliedmodders/safetyhook +[submodule "core/logic/libaddrz"] + path = core/logic/libaddrz + url = https://github.com/dvander/libaddrz.git diff --git a/AMBuildScript b/AMBuildScript index 56faedafb4..a0e377cea8 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -55,7 +55,6 @@ class SMConfig(object): self.target_archs = set() self.enable_asan = getattr(builder.options, 'enable_asan', False) self.asan_libs = {} - self.libsafetyhook = {} if builder.options.targets: target_archs = builder.options.targets.split(',') @@ -128,7 +127,7 @@ class SMConfig(object): if builder.options.mms_path: self.mms_root = builder.options.mms_path else: - self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') + self.mms_root = ResolveEnvPath('MMSOURCE200', 'mmsource-2.0') if not self.mms_root: self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') if not self.mms_root: @@ -499,6 +498,11 @@ class SMConfig(object): os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'), os.path.join(builder.sourcePath, 'public', 'amtl'), ] + + compiler.cxxincludes += [ + os.path.join(self.mms_root, 'core'), + os.path.join(self.mms_root, 'third_party', 'khook', 'include'), + ] return compiler def ExtLibrary(self, context, compiler, name): @@ -517,11 +521,6 @@ class SMConfig(object): compiler = binary.compiler SetArchFlags(compiler) - compiler.cxxincludes += [ - os.path.join(self.mms_root, 'core'), - os.path.join(self.mms_root, 'core', 'sourcehook'), - ] - for other_sdk in self.sdk_manifests: compiler.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])] @@ -529,17 +528,6 @@ class SMConfig(object): return binary - def AddCDetour(self, binary): - public_path = os.path.join(builder.sourcePath, 'public') - binary.sources += [ os.path.join(public_path, 'CDetour', 'detours.cpp') ] - binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook', 'include') ] - - for task in self.libsafetyhook: - if task.target.arch == binary.compiler.target.arch: - binary.compiler.linkflags += [task.binary] - return - raise Exception('No suitable build of safetyhook was found.') - def HL2Library(self, context, compiler, name, sdk): binary = self.Library(context, compiler, name) self.ConfigureForExtension(context, binary.compiler) @@ -588,16 +576,6 @@ if SM.use_auto_versioning(): { 'SM': SM } ) -class SafetyHookShim(object): - def __init__(self): - self.all_targets = {} - self.libsafetyhook = {} - -SafetyHook = SafetyHookShim() -SafetyHook.all_targets = SM.all_targets -builder.Build('public/safetyhook/AMBuilder', {'SafetyHook': SafetyHook }) -SM.libsafetyhook = SafetyHook.libsafetyhook - class SPRoot(object): def __init__(self): self.generated_headers = SM.generated_headers @@ -666,10 +644,10 @@ else: 'extensions/bintools/AMBuilder', 'extensions/clientprefs/AMBuilder', 'extensions/curl/AMBuilder', - 'extensions/cstrike/AMBuilder', + #'extensions/cstrike/AMBuilder', 'extensions/dhooks/AMBuilder', 'extensions/geoip/AMBuilder', - 'extensions/mysql/AMBuilder', + #'extensions/mysql/AMBuilder', 'extensions/pgsql/AMBuilder', 'extensions/regex/AMBuilder', 'extensions/sdkhooks/AMBuilder', diff --git a/bridge/include/IExtensionBridge.h b/bridge/include/IExtensionBridge.h index 4b41795f6c..3a2c661ad6 100644 --- a/bridge/include/IExtensionBridge.h +++ b/bridge/include/IExtensionBridge.h @@ -29,13 +29,12 @@ #include #include -#include +#include struct edict_t; namespace SourceMod { -using namespace SourceHook; using namespace SourcePawn; class SMPlugin; @@ -51,8 +50,8 @@ class IExtensionSys : public IExtensionManager virtual IExtension *GetExtensionFromIdent(IdentityToken_t *token) = 0; virtual void BindChildPlugin(IExtension *ext, SMPlugin *plugin) = 0; virtual void AddRawDependency(IExtension *myself, IdentityToken_t *token, void *iface) = 0; - virtual const CVector *ListExtensions() = 0; - virtual void FreeExtensionList(const CVector *list) = 0; + virtual const std::vector *ListExtensions() = 0; + virtual void FreeExtensionList(const std::vector *list) = 0; virtual void CallOnCoreMapEnd() = 0; }; @@ -67,13 +66,13 @@ class AutoExtensionList { extensions_->FreeExtensionList(list_); } - const CVector *operator ->() + const std::vector *operator ->() { return list_; } private: IExtensionSys *extensions_; - const CVector *list_; + const std::vector *list_; }; } // namespace SourceMod diff --git a/bridge/include/IScriptManager.h b/bridge/include/IScriptManager.h index 2af3905566..d530a3a8cb 100644 --- a/bridge/include/IScriptManager.h +++ b/bridge/include/IScriptManager.h @@ -29,12 +29,11 @@ #include #include -#include -#include +#include +#include namespace SourceMod { -using namespace SourceHook; using namespace SourcePawn; class IChangeableForward; @@ -47,8 +46,8 @@ enum LibraryAction struct AutoConfig { - SourceHook::String autocfg; - SourceHook::String folder; + std::string autocfg; + std::string folder; bool create; }; @@ -82,8 +81,8 @@ class IScriptManager virtual SMPlugin *FindPluginByConsoleArg(const char *text) = 0; virtual SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) = 0; virtual bool UnloadPlugin(IPlugin *plugin) = 0; - virtual const CVector *ListPlugins() = 0; - virtual void FreePluginList(const CVector *list) = 0; + virtual const std::vector *ListPlugins() = 0; + virtual void FreePluginList(const std::vector *list) = 0; virtual void AddFunctionsToForward(const char *name, IChangeableForward *fwd) = 0; }; @@ -98,13 +97,13 @@ class AutoPluginList { scripts_->FreePluginList(list_); } - const CVector *operator ->() + const std::vector *operator ->() { return list_; } private: IScriptManager *scripts_; - const CVector *list_; + const std::vector *list_; }; } // namespace SourceMod diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index 1777cfbeea..5d485dde46 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -415,7 +415,7 @@ void RegisterInPlugin(CmdHook *hook) void ConCmdManager::AddToCmdList(ConCmdInfo *info) { - List::iterator iter = m_CmdList.begin(); + auto iter = m_CmdList.begin(); ConCmdInfo *pInfo; bool inserted = false; const char *orig = NULL; diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index f3b882e299..20ce26082a 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -43,16 +43,14 @@ #include "sm_globals.h" #include "sourcemm_api.h" #include -#include -#include +#include +#include #include #include #include "concmd_cleaner.h" #include "GameHooks.h" #include -using namespace SourceHook; - struct CmdHook; struct ConCmdInfo; @@ -137,7 +135,7 @@ struct ConCmdInfo }; }; -typedef List ConCmdList; +typedef std::list ConCmdList; class ConCmdManager : public SMGlobalClass, @@ -180,7 +178,7 @@ class ConCmdManager : bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); ConCmdInfo *FindInTrie(const char *name); public: - inline const List & GetCommandList() + inline const std::list & GetCommandList() { return m_CmdList; } diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index dcd5d8ed0a..c422771ec4 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -30,7 +30,7 @@ #include "ConVarManager.h" #include "HalfLife2.h" #include "sm_stringutil.h" -#include +#include #include #include "logic_bridge.h" #include "sourcemod.h" @@ -40,7 +40,7 @@ ConVarManager g_ConVarManager; const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}; -typedef List ConVarList; +typedef std::list ConVarList; NameHashSet convar_cache; enum { @@ -114,7 +114,7 @@ void ConVarManager::OnSourceModAllInitialized() void ConVarManager::OnSourceModShutdown() { - List::iterator iter = m_ConVars.begin(); + auto iter = m_ConVars.begin(); HandleSecurity sec(NULL, g_pCoreIdent); /* Iterate list of ConVarInfo structures, remove every one of them */ @@ -217,7 +217,7 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin) } /* Clear any references to this plugin as the convar creator */ - for (List::iterator iter = m_ConVars.begin(); iter != m_ConVars.end(); ++iter) + for (auto iter = m_ConVars.begin(); iter != m_ConVars.end(); ++iter) { ConVarInfo *pInfo = (*iter); @@ -230,7 +230,7 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin) const IPluginRuntime * pRuntime = plugin->GetRuntime(); /* Remove convar queries for this plugin that haven't returned results yet */ - for (List::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();) + for (auto iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();) { ConVarQuery &query = (*iter); if (query.pCallback->GetParentRuntime() == pRuntime) @@ -246,7 +246,7 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin) void ConVarManager::OnClientDisconnected(int client) { /* Remove convar queries for this client that haven't returned results yet */ - for (List::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();) + for (auto iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();) { ConVarQuery &query = (*iter); if (query.client == client) @@ -311,7 +311,6 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename(); ConVarList *pConVarList; - ConVarList::iterator iter; /* If no convar list... */ if (!plugin->GetProperty("ConVarList", (void **)&pConVarList)) @@ -327,7 +326,7 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const ICommandArgs } /* Iterate convar list and display/reset each one */ - for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) + for (auto iter = pConVarList->begin(); iter != pConVarList->end(); iter++) { /*const */ConVar *pConVar = const_cast(*iter); if (!wantReset) @@ -599,10 +598,18 @@ void ConVarManager::AddConVarToPluginList(IPlugin *plugin, const ConVar *pConVar pConVarList = new ConVarList(); plugin->SetProperty("ConVarList", pConVarList); } - else if (pConVarList->find(pConVar) != pConVarList->end()) + else { /* If convar is already in list, then don't add it */ - return; + auto iterS = pConVarList->begin(); + while (iterS != pConVarList->end() && (*iterS) != pConVar) + { + iterS++; + } + if (iterS != pConVarList->end()) + { + return; + } } /* Insert convar into list which is sorted alphabetically */ @@ -672,9 +679,9 @@ void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie, { IPluginFunction *pCallback = NULL; cell_t value = 0; - List::iterator iter; - for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++) + auto iter = m_ConVarQueries.begin(); + for (; iter != m_ConVarQueries.end(); iter++) { ConVarQuery &query = (*iter); if (query.cookie == cookie) @@ -706,7 +713,8 @@ void ConVarManager::OnClientQueryFinished(QueryCvarCookie_t cookie, pCallback->PushCell(value); pCallback->Execute(&ret); - m_ConVarQueries.erase(iter); + if (iter != m_ConVarQueries.end()) + m_ConVarQueries.erase(iter); } } #endif diff --git a/core/ConVarManager.h b/core/ConVarManager.h index a613aa4331..21c2b26ae5 100644 --- a/core/ConVarManager.h +++ b/core/ConVarManager.h @@ -34,7 +34,7 @@ #include "sm_globals.h" #include "sourcemm_api.h" -#include +#include #include #include #include @@ -45,8 +45,6 @@ #include "PlayerManager.h" #include -using namespace SourceHook; - class IConVarChangeListener { public: @@ -63,7 +61,7 @@ struct ConVarInfo IChangeableForward *pChangeForward; /**< Forward associated with convar */ ConVar *pVar; /**< The actual convar */ IPlugin *pPlugin; /**< Originally owning plugin */ - List changeListeners; + std::list changeListeners; struct ConVarPolicy { @@ -175,8 +173,8 @@ class ConVarManager : static void AddConVarToPluginList(IPlugin *plugin, const ConVar *pConVar); private: HandleType_t m_ConVarType; - List m_ConVars; - List m_ConVarQueries; + std::list m_ConVars; + std::list m_ConVarQueries; }; extern ConVarManager g_ConVarManager; diff --git a/core/ConsoleDetours.cpp b/core/ConsoleDetours.cpp index 69badc43c7..879789443f 100644 --- a/core/ConsoleDetours.cpp +++ b/core/ConsoleDetours.cpp @@ -62,30 +62,34 @@ # include #endif +class GenericCommandHooker : public IConCommandLinkListener +{ #if SOURCE_ENGINE >= SE_ORANGEBOX - SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); + using CmdHook = KHook::Member; + KHook::Return Dispatch(ConCommand* this_ptr, const CCommand& args) #else - SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); + using CmdHook = KHook::Member; + KHook::Return Dispatch(ConCommand* this_ptr) #endif + { + cell_t res = ConsoleDetours::Dispatch(this_ptr +#if SOURCE_ENGINE >= SE_ORANGEBOX + , args +#endif + ); + if (res >= Pl_Handled) + return { KHook::Action::Supersede }; + return { KHook::Action::Ignore }; + } -class GenericCommandHooker : public IConCommandLinkListener -{ struct HackInfo { void **vtable; - int hook; + CmdHook* hook; unsigned int refcount; }; - CVector vtables; + std::vector vtables; bool enabled; - SourceHook::MemFuncInfo dispatch; - - inline void **GetVirtualTable(ConCommandBase *pBase) - { - return *reinterpret_cast(reinterpret_cast(pBase) + - dispatch.thisptroffs + - dispatch.vtbloffs); - } inline bool FindVtable(void **ptr, size_t& index) { @@ -105,15 +109,14 @@ class GenericCommandHooker : public IConCommandLinkListener if (!pBase->IsCommand()) return; - ConCommand *cmd = (ConCommand*)pBase; - void **vtable = GetVirtualTable(cmd); - + ConCommand *cmd = reinterpret_cast(pBase); + void **vtable = *(void***)cmd; size_t index; if (!FindVtable(vtable, index)) { HackInfo hack; hack.vtable = vtable; - hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false); + hack.hook = new CmdHook(KHook::GetVtableFunction(cmd, &ConCommand::Dispatch), this, &GenericCommandHooker::Dispatch, nullptr); hack.refcount = 1; vtables.push_back(hack); } @@ -123,28 +126,13 @@ class GenericCommandHooker : public IConCommandLinkListener } } -#if SOURCE_ENGINE >= SE_ORANGEBOX - void Dispatch(const CCommand& args) -#else - void Dispatch() -#endif - { - cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand) -#if SOURCE_ENGINE >= SE_ORANGEBOX - , args -#endif - ); - if (res >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); - } - void ReparseCommandList() { for (size_t i = 0; i < vtables.size(); i++) vtables[i].refcount = 0; for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next()) MakeHookable(iter.Get()); - CVector::iterator iter = vtables.begin(); + auto iter = vtables.begin(); while (iter != vtables.end()) { if ((*iter).refcount) @@ -167,6 +155,7 @@ class GenericCommandHooker : public IConCommandLinkListener * * See bug 4018. */ + delete (*iter).hook; iter = vtables.erase(iter); } } @@ -177,7 +166,7 @@ class GenericCommandHooker : public IConCommandLinkListener return; ConCommand *cmd = (ConCommand*)pBase; - void **vtable = GetVirtualTable(cmd); + void **vtable = *(void***)(cmd); size_t index; if (!FindVtable(vtable, index)) @@ -190,8 +179,8 @@ class GenericCommandHooker : public IConCommandLinkListener vtables[index].refcount--; if (vtables[index].refcount == 0) { - SH_REMOVE_HOOK_ID(vtables[index].hook); - vtables.erase(vtables.iterAt(index)); + delete vtables[index].hook; + vtables.erase(vtables.begin() + index); } } @@ -202,9 +191,7 @@ class GenericCommandHooker : public IConCommandLinkListener bool Enable() { - SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch); - - if (dispatch.thisptroffs < 0) + if (KHook::GetVtableIndex(&ConCommand::Dispatch) == -1) { logger->LogError("Command filter could not determine ConCommand layout"); return false; @@ -227,7 +214,7 @@ class GenericCommandHooker : public IConCommandLinkListener void Disable() { for (size_t i = 0; i < vtables.size(); i++) - SH_REMOVE_HOOK_ID(vtables[i].hook); + delete vtables[i].hook; vtables.clear(); } diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index f2b32f72b9..5af5117c8d 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -41,13 +41,11 @@ #include #include #include -#include +#include #include #include #include -using namespace SourceHook; - #ifdef PLATFORM_WINDOWS ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file"); #elif defined PLATFORM_LINUX || defined PLATFORM_APPLE @@ -68,11 +66,9 @@ ConVar *g_ServerCfgFile = NULL; void CheckAndFinalizeConfigs(); #if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); -void Hook_ExecDispatchPre(const CCommand &cmd) +KHook::Return Hook_ExecDispatchPre(ConCommand*, const CCommand &cmd) #else -SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); -void Hook_ExecDispatchPre() +KHook::Return Hook_ExecDispatchPre(ConCommand*) #endif { #if SOURCE_ENGINE <= SE_DARKMESSIAH @@ -85,12 +81,14 @@ void Hook_ExecDispatchPre() { g_bGotTrigger = true; } + + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE >= SE_ORANGEBOX -void Hook_ExecDispatchPost(const CCommand &cmd) +KHook::Return Hook_ExecDispatchPost(ConCommand*, const CCommand &cmd) #else -void Hook_ExecDispatchPost() +KHook::Return Hook_ExecDispatchPost(ConCommand*) #endif { if (g_bGotTrigger) @@ -99,8 +97,12 @@ void Hook_ExecDispatchPost() g_bServerExecd = true; CheckAndFinalizeConfigs(); } + + return { KHook::Action::Ignore }; } +KHook::Virtual gExecCommandHook(&ConCommand::Dispatch, &Hook_ExecDispatchPre, &Hook_ExecDispatchPost); + void CheckAndFinalizeConfigs() { if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart) @@ -134,8 +136,7 @@ void CoreConfig::OnSourceModShutdown() if (g_pExecPtr != NULL) { - SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); - SH_REMOVE_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); + gExecCommandHook.Remove(g_pExecPtr); g_pExecPtr = NULL; } } @@ -160,8 +161,7 @@ void CoreConfig::OnSourceModLevelChange(const char *mapName) g_pExecPtr = FindCommand("exec"); if (g_pExecPtr != NULL) { - SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPre), false); - SH_ADD_HOOK(ConCommand, Dispatch, g_pExecPtr, SH_STATIC(Hook_ExecDispatchPost), true); + gExecCommandHook.Add(g_pExecPtr); } else { @@ -396,7 +396,7 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) bool file_exists = ke::file::IsFile(file); if (!file_exists && will_create) { - List *convars = NULL; + std::list *convars = NULL; if (pl->GetProperty("ConVarList", (void **)&convars, false) && convars) { /* Attempt to create it */ @@ -407,9 +407,8 @@ bool SM_ExecuteConfig(IPlugin *pl, AutoConfig *cfg, bool can_create) fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename()); fprintf(fp, "\n\n"); - List::iterator iter; float x; - for (iter = convars->begin(); iter != convars->end(); iter++) + for (auto iter = convars->begin(); iter != convars->end(); iter++) { const ConVar *cvar = (*iter); #if SOURCE_ENGINE >= SE_ORANGEBOX diff --git a/core/EventManager.cpp b/core/EventManager.cpp index dc67d81c05..1da72a0900 100644 --- a/core/EventManager.cpp +++ b/core/EventManager.cpp @@ -38,10 +38,8 @@ EventManager g_EventManager; -SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); - const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; -typedef List EventHookList; +typedef std::list EventHookList; class EventForwardFilter : public IForwardFilter { @@ -57,27 +55,25 @@ class EventForwardFilter : public IForwardFilter } }; -EventManager::EventManager() : m_EventType(0) +EventManager::EventManager() : m_EventType(0), + m_FireEvent(&IGameEventManager2::FireEvent, this, &EventManager::OnFireEvent, &EventManager::OnFireEvent_Post) { } EventManager::~EventManager() { /* Free memory used by EventInfo structs if any */ - CStack::iterator iter; - for (iter = m_FreeEvents.begin(); iter != m_FreeEvents.end(); iter++) + while (!m_FreeEvents.empty()) { - delete (*iter); + delete (m_FreeEvents.top()); + m_FreeEvents.pop(); } - - m_FreeEvents.popall(); } void EventManager::OnSourceModAllInitialized() { /* Add a hook for IGameEventManager2::FireEvent() */ - SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); - SH_ADD_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); + m_FireEvent.Add(gameevents); HandleAccess sec; @@ -93,8 +89,7 @@ void EventManager::OnSourceModAllInitialized() void EventManager::OnSourceModShutdown() { /* Remove hook for IGameEventManager2::FireEvent() */ - SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent), false); - SH_REMOVE_HOOK(IGameEventManager2, FireEvent, gameevents, SH_MEMBER(this, &EventManager::OnFireEvent_Post), true); + m_FireEvent.Remove(gameevents); /* Remove the 'GameEvent' handle type */ handlesys->RemoveType(m_EventType, g_pCoreIdent); @@ -306,7 +301,11 @@ EventHookError EventManager::UnhookEvent(const char *name, IPluginFunction *pFun } /* Make sure the event was actually being hooked */ - if (pHookList->find(pHook) == pHookList->end()) + auto iter = pHookList->begin(); + while (iter != pHookList->end() && *iter == pHook) { + iter++; + } + if (iter == pHookList->end()) { return EventHookErr_NotActive; } @@ -335,7 +334,7 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name, { pInfo = new EventInfo(); } else { - pInfo = m_FreeEvents.front(); + pInfo = m_FreeEvents.top(); m_FreeEvents.pop(); } @@ -382,7 +381,7 @@ void EventManager::CancelCreatedEvent(EventInfo *pInfo) } /* IGameEventManager2::FireEvent hook */ -bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) +KHook::Return EventManager::OnFireEvent(IGameEventManager2* this_ptr, IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; IChangeableForward *pForward; @@ -393,7 +392,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore, false }; } name = pEvent->GetName(); @@ -436,7 +435,7 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) if (res >= Pl_Handled) { gameevents->FreeEvent(pEvent); - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; } } else @@ -445,13 +444,13 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast) } if (broadcast != bDontBroadcast) - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast)); + return KHook::Recall(&IGameEventManager2::FireEvent, KHook::Return{ KHook::Action::Ignore, true }, this_ptr, pEvent, broadcast); - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } /* IGameEventManager2::FireEvent post hook */ -bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) +KHook::Return EventManager::OnFireEvent_Post(IGameEventManager2*, IGameEvent *pEvent, bool bDontBroadcast) { EventHook *pHook; EventInfo info; @@ -461,10 +460,10 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ if (!pEvent) { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore, false }; } - pHook = m_EventStack.front(); + pHook = m_EventStack.top(); if (pHook != NULL) { @@ -475,7 +474,7 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) if (pHook->postCopy) { info.bDontBroadcast = bDontBroadcast; - info.pEvent = m_EventCopies.front(); + info.pEvent = m_EventCopies.top(); info.pOwner = NULL; hndl = handlesys->CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); @@ -512,5 +511,5 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) m_EventStack.pop(); - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } diff --git a/core/EventManager.h b/core/EventManager.h index b149231491..fe9113dec8 100644 --- a/core/EventManager.h +++ b/core/EventManager.h @@ -35,16 +35,14 @@ #include "sm_globals.h" #include "sourcemm_api.h" #include -#include -#include +#include +#include #include #include #include class IClient; -using namespace SourceHook; - struct EventInfo { EventInfo() @@ -135,14 +133,15 @@ class EventManager : void FireEventToClient(EventInfo *pInfo, IClient *pClient); void CancelCreatedEvent(EventInfo *pInfo); private: // IGameEventManager2 hooks - bool OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast); - bool OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast); + KHook::Return OnFireEvent(IGameEventManager2*, IGameEvent *pEvent, bool bDontBroadcast); + KHook::Return OnFireEvent_Post(IGameEventManager2*, IGameEvent *pEvent, bool bDontBroadcast); private: HandleType_t m_EventType; NameHashSet m_EventHooks; - CStack m_FreeEvents; - CStack m_EventStack; - CStack m_EventCopies; + std::stack m_FreeEvents; + std::stack m_EventStack; + std::stack m_EventCopies; + KHook::Virtual m_FireEvent; }; extern EventManager g_EventManager; diff --git a/core/GameHooks.cpp b/core/GameHooks.cpp index 356e764eb7..86bd4c41c5 100644 --- a/core/GameHooks.cpp +++ b/core/GameHooks.cpp @@ -31,48 +31,36 @@ #include "provider.h" #if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); +KHook::Virtual CallGlobalChangeCallback_Hook(&ICvar::CallGlobalChangeCallbacks, &GameHooks::OnConVarChanged, nullptr); #else -SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *); +KHook::Virtual CallGlobalChangeCallback_Hook(&ICvar::CallGlobalChangeCallback, &GameHooks::OnConVarChanged, nullptr); #endif +GameHooks::GameHooks() + : #if SOURCE_ENGINE != SE_DARKMESSIAH -SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); -SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *); + m_GameDLLOnQueryCvarValueFinishedHook(&IServerGameDLL::OnQueryCvarValueFinished, this, &GameHooks::GameDLLOnQueryCvarValueFinished, nullptr), + m_VSPOnQueryCvarValueFinishedHook(&IServerPluginCallbacks::OnQueryCvarValueFinished, this, &GameHooks::VSPOnQueryCvarValueFinished, nullptr), #endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); -#else -SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false); -#endif - -SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int); - -GameHooks::GameHooks() - : client_cvar_query_mode_(ClientCvarQueryMode::Unavailable), - last_command_client_(-1) + m_SetCommandClient(&IServerGameClients::SetCommandClient, this, &GameHooks::SetCommandClient, nullptr) + ,client_cvar_query_mode_(ClientCvarQueryMode::Unavailable) + ,last_command_client_(-1) { } void GameHooks::Start() { // Hook ICvar::CallGlobalChangeCallbacks. -#if SOURCE_ENGINE >= SE_ORANGEBOX - hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false); -#else - hooks_ += SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false); -#endif + CallGlobalChangeCallback_Hook.Add(icvar); // Episode 2 has this function by default, but the older versions do not. #if SOURCE_ENGINE == SE_EPISODEONE if (g_SMAPI->GetGameDLLVersion() >= 6) { - hooks_ += SH_ADD_HOOK(IServerGameDLL, OnQueryCvarValueFinished, gamedll, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false); + m_GameDLLOnQueryCvarValueFinishedHook.Add(gamedll); client_cvar_query_mode_ = ClientCvarQueryMode::DLL; } #endif - - hooks_ += SH_ADD_HOOK(IServerGameClients, SetCommandClient, serverClients, SH_MEMBER(this, &GameHooks::SetCommandClient), false); + m_SetCommandClient.Add(serverClients); } void GameHooks::OnVSPReceived() @@ -84,30 +72,33 @@ void GameHooks::OnVSPReceived() return; #if SOURCE_ENGINE != SE_DARKMESSIAH - hooks_ += SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false); + m_VSPOnQueryCvarValueFinishedHook.Add(vsp_interface); client_cvar_query_mode_ = ClientCvarQueryMode::VSP; #endif } void GameHooks::Shutdown() { - for (size_t i = 0; i < hooks_.size(); i++) - SH_REMOVE_HOOK_ID(hooks_[i]); - hooks_.clear(); + CallGlobalChangeCallback_Hook.Remove(icvar); + m_GameDLLOnQueryCvarValueFinishedHook.Remove(gamedll); + m_SetCommandClient.Remove(serverClients); + m_VSPOnQueryCvarValueFinishedHook.Remove(vsp_interface); client_cvar_query_mode_ = ClientCvarQueryMode::Unavailable; } #if SOURCE_ENGINE >= SE_ORANGEBOX -void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) +KHook::Return GameHooks::OnConVarChanged(ICvar*, ConVar *pConVar, const char *oldValue, float flOldValue) #else -void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue) +KHook::Return GameHooks::OnConVarChanged(ICvar*, ConVar *pConVar, const char *oldValue) #endif { #if SOURCE_ENGINE < SE_ORANGEBOX float flOldValue = atof(oldValue); #endif g_ConVarManager.OnConVarChanged(pConVar, oldValue, flOldValue); + + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE != SE_DARKMESSIAH @@ -123,6 +114,17 @@ void GameHooks::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPla } #endif +KHook::Return GameHooks::GameDLLOnQueryCvarValueFinished(IServerGameDLL*, QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, + const char *cvarName, const char *cvarValue) { + OnQueryCvarValueFinished(cookie, pPlayer, result, cvarName, cvarValue); + return { KHook::Action::Ignore }; +} +KHook::Return GameHooks::VSPOnQueryCvarValueFinished(IServerPluginCallbacks*, QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, + const char *cvarName, const char *cvarValue) { + OnQueryCvarValueFinished(cookie, pPlayer, result, cvarName, cvarValue); + return { KHook::Action::Ignore }; +} + ke::RefPtr GameHooks::AddCommandHook(ConCommand *cmd, const CommandHook::Callback &callback) { @@ -135,25 +137,29 @@ GameHooks::AddPostCommandHook(ConCommand *cmd, const CommandHook::Callback &call return new CommandHook(cmd, callback, true); } -void GameHooks::SetCommandClient(int client) +KHook::Return GameHooks::SetCommandClient(IServerGameClients*, int client) { last_command_client_ = client + 1; + + return { KHook::Action::Ignore }; } CommandHook::CommandHook(ConCommand *cmd, const Callback &callback, bool post) - : hook_id_(0), - callback_(callback) + : callback_(callback), + m_DispatchHook(&ConCommand::Dispatch, this, (post) ? nullptr : &CommandHook::Dispatch, (post) ? &CommandHook::Dispatch : nullptr) { - hook_id_ = SH_ADD_HOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &CommandHook::Dispatch), post); + m_DispatchHook.Add(cmd); } CommandHook::~CommandHook() { - if (hook_id_) - SH_REMOVE_HOOK_ID(hook_id_); } -void CommandHook::Dispatch(DISPATCH_ARGS) +#if SOURCE_ENGINE >= SE_ORANGEBOX +KHook::Return CommandHook::Dispatch(ConCommand*, const CCommand& command) +#else +KHook::Return CommandHook::Dispatch(ConCommand*) +#endif { DISPATCH_PROLOGUE; EngineArgs args(command); @@ -162,10 +168,8 @@ void CommandHook::Dispatch(DISPATCH_ARGS) bool rval = callback_(sCoreProviderImpl.CommandClient(), &args); Release(); if (rval) - RETURN_META(MRES_SUPERCEDE); -} - -void CommandHook::Zap() -{ - hook_id_ = 0; -} + { + return { KHook::Action::Supersede }; + } + return { KHook::Action::Ignore }; +} \ No newline at end of file diff --git a/core/GameHooks.h b/core/GameHooks.h index 83c8ad7004..4a6b92e012 100644 --- a/core/GameHooks.h +++ b/core/GameHooks.h @@ -35,6 +35,7 @@ #include #include #include +#include class ConVar; class CCommand; @@ -68,12 +69,19 @@ class CommandHook : public ke::Refcounted public: CommandHook(ConCommand *cmd, const Callback &callback, bool post); ~CommandHook(); - void Dispatch(DISPATCH_ARGS); - void Zap(); +#if SOURCE_ENGINE >= SE_ORANGEBOX + KHook::Return Dispatch(ConCommand*, const CCommand&); +#else + KHook::Return Dispatch(ConCommand*); +#endif private: - int hook_id_; Callback callback_; +#if SOURCE_ENGINE >= SE_ORANGEBOX + KHook::Virtual m_DispatchHook; +#else + KHook::Virtual m_DispatchHook; +#endif }; class GameHooks @@ -97,21 +105,29 @@ class GameHooks return last_command_client_; } -private: +public: // Static callback that Valve's ConVar object executes when the convar's value changes. #if SOURCE_ENGINE >= SE_ORANGEBOX - static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue); + static KHook::Return OnConVarChanged(ICvar*, ConVar *pConVar, const char *oldValue, float flOldValue); #else - static void OnConVarChanged(ConVar *pConVar, const char *oldValue); + static KHook::Return OnConVarChanged(ICvar*, ConVar *pConVar, const char *oldValue); #endif +private: // Callback for when StartQueryCvarValue() has finished. #if SOURCE_ENGINE != SE_DARKMESSIAH void OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue); + KHook::Return GameDLLOnQueryCvarValueFinished(IServerGameDLL*, QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, + const char *cvarName, const char *cvarValue); + KHook::Virtual m_GameDLLOnQueryCvarValueFinishedHook; + KHook::Return VSPOnQueryCvarValueFinished(IServerPluginCallbacks*, QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, + const char *cvarName, const char *cvarValue); + KHook::Virtual m_VSPOnQueryCvarValueFinishedHook; #endif - void SetCommandClient(int client); + KHook::Return SetCommandClient(IServerGameClients*, int client); + KHook::Virtual m_SetCommandClient; private: class HookList : public std::vector diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index 91a1e0aef4..082412e94d 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -756,7 +756,7 @@ void CHalfLife2::AddToFakeCliCmdQueue(int client, int userid, const char *cmd) { pFake = new DelayedFakeCliCmd; } else { - pFake = m_FreeCmds.front(); + pFake = m_FreeCmds.top(); m_FreeCmds.pop(); } @@ -852,7 +852,7 @@ const ICommandArgs *CHalfLife2::PeekCommandStack() return NULL; } - return m_CommandStack.front().args; + return m_CommandStack.top().args; } void CHalfLife2::PopCommandStack() @@ -863,9 +863,9 @@ void CHalfLife2::PopCommandStack() const char *CHalfLife2::CurrentCommandName() { #if SOURCE_ENGINE >= SE_ORANGEBOX - return m_CommandStack.front().args->Arg(0); + return m_CommandStack.top().args->Arg(0); #else - return m_CommandStack.front().cmd; + return m_CommandStack.top().cmd; #endif } diff --git a/core/HalfLife2.h b/core/HalfLife2.h index 5496a337b9..bf24f12cd9 100644 --- a/core/HalfLife2.h +++ b/core/HalfLife2.h @@ -32,9 +32,8 @@ #ifndef _INCLUDE_SOURCEMOD_CHALFLIFE2_H_ #define _INCLUDE_SOURCEMOD_CHALFLIFE2_H_ -#include -#include -#include +#include +#include #include #include #include @@ -54,7 +53,6 @@ namespace SourceMod { class ICommandArgs; } // namespace SourceMod -using namespace SourceHook; using namespace SourceMod; static const int ENTREF_MASK = (1 << 31); @@ -153,7 +151,7 @@ typedef NameHashSet DataMapCache; struct DelayedFakeCliCmd { - String cmd; + std::string cmd; int client; int userid; }; @@ -288,8 +286,8 @@ class CHalfLife2 : int m_SayTextMsg; int m_VGUIMenu; Queue m_CmdQueue; - CStack m_FreeCmds; - CStack m_CommandStack; + std::stack m_FreeCmds; + std::stack m_CommandStack; Queue m_DelayedKicks; void *m_pGetCommandLine; #if SOURCE_ENGINE == SE_CSGO diff --git a/core/Logger.cpp b/core/Logger.cpp index 2312e3b0d3..aced8c00cc 100644 --- a/core/Logger.cpp +++ b/core/Logger.cpp @@ -43,33 +43,36 @@ bool g_in_game_log_hook = false; static LoggerCore g_LoggerCore; -SH_DECL_HOOK1_void(IVEngineServer, LogPrint, SH_NOATTRIB, false, const char *); - -static void HookLogPrint(const char *message) +static KHook::Return HookLogPrint(IVEngineServer*, const char *message) { g_in_game_log_hook = true; bool stopped = logicore.callbacks->OnLogPrint(message); g_in_game_log_hook = false; if (stopped) - RETURN_META(MRES_SUPERCEDE); + { + return { KHook::Action::Supersede }; + } + return { KHook::Action::Ignore }; } +KHook::Virtual LogPrintHook(&IVEngineServer::LogPrint, &HookLogPrint, nullptr); + void LoggerCore::OnSourceModStartup(bool late) { - SH_ADD_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); + LogPrintHook.Add(engine); } void LoggerCore::OnSourceModAllShutdown() { - SH_REMOVE_HOOK(IVEngineServer, LogPrint, engine, SH_STATIC(HookLogPrint), false); + LogPrintHook.Remove(engine); } void Engine_LogPrintWrapper(const char *msg) { if (g_in_game_log_hook) { - ENGINE_CALL(LogPrint)(msg); + LogPrintHook.CallOriginal(engine, msg); } else { diff --git a/core/Logger.h b/core/Logger.h index a12dc9ef65..5699e19a85 100644 --- a/core/Logger.h +++ b/core/Logger.h @@ -33,11 +33,9 @@ #define _INCLUDE_SOURCEMOD_CLOGGER_H_ #include -#include +#include #include "sm_globals.h" -using namespace SourceHook; - class LoggerCore : public SMGlobalClass { public: //SMGlobalClass diff --git a/core/MenuManager.h b/core/MenuManager.h index 3c75347ef7..2d9bfe44b0 100644 --- a/core/MenuManager.h +++ b/core/MenuManager.h @@ -33,14 +33,11 @@ #define _INCLUDE_SOURCEMOD_MENUMANAGER_H_ #include -#include -#include -#include +#include #include "sm_globals.h" #include using namespace SourceMod; -using namespace SourceHook; class MenuManager : public IMenuManager, @@ -102,7 +99,7 @@ class MenuManager : private: int m_ShowMenu; IMenuStyle *m_pDefaultStyle; - CVector m_Styles; + std::vector m_Styles; HandleType_t m_StyleType; HandleType_t m_MenuType; std::string m_SelectSound = ""; diff --git a/core/MenuStyle_Radio.cpp b/core/MenuStyle_Radio.cpp index 035219e322..0ca5ebf9a9 100644 --- a/core/MenuStyle_Radio.cpp +++ b/core/MenuStyle_Radio.cpp @@ -144,7 +144,7 @@ void CRadioStyle::OnSourceModShutdown() while (!m_FreeDisplays.empty()) { - delete m_FreeDisplays.front(); + delete m_FreeDisplays.top(); m_FreeDisplays.pop(); } } @@ -261,7 +261,7 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu) } else { - display = m_FreeDisplays.front(); + display = m_FreeDisplays.top(); m_FreeDisplays.pop(); display->Reset(); } diff --git a/core/MenuStyle_Radio.h b/core/MenuStyle_Radio.h index afb356ef01..0febb8311c 100644 --- a/core/MenuStyle_Radio.h +++ b/core/MenuStyle_Radio.h @@ -39,8 +39,8 @@ #include #include "UserMessages.h" #include "sm_fastlink.h" -#include -#include +#include +#include #include #include "logic/common_logic.h" #include "AutoHandleRooter.h" @@ -106,7 +106,7 @@ class CRadioStyle : CRadioMenuPlayer *GetRadioMenuPlayer(int client); private: CRadioMenuPlayer *m_players; - CStack m_FreeDisplays; + std::stack m_FreeDisplays; }; class CRadioDisplay : public IMenuPanel @@ -133,8 +133,8 @@ class CRadioDisplay : public IMenuPanel unsigned int GetApproxMemUsage(); bool DirectSet(const char *str); private: - String m_BufferText; - String m_Title; + std::string m_BufferText; + std::string m_Title; unsigned int m_NextPos; int keys; }; diff --git a/core/MenuStyle_Valve.cpp b/core/MenuStyle_Valve.cpp index 892720984c..88f7bfea4b 100644 --- a/core/MenuStyle_Valve.cpp +++ b/core/MenuStyle_Valve.cpp @@ -34,15 +34,15 @@ #include "MenuStyle_Valve.h" #include "PlayerManager.h" #include "ConCmdManager.h" - -SH_DECL_HOOK4_void(IServerPluginHelpers, CreateMessage, SH_NOATTRIB, false, edict_t *, DIALOG_TYPE, KeyValues *, IServerPluginCallbacks *); +#include "engine/iserverplugin.h" ValveMenuStyle g_ValveMenuStyle; extern const char *g_OptionNumTable[]; extern const char *g_OptionCmdTable[]; -CallClass *g_pSPHCC = NULL; -ValveMenuStyle::ValveMenuStyle() : m_players(new CValveMenuPlayer[256+1]) +ValveMenuStyle::ValveMenuStyle() : + m_HookCreateMessage(&IServerPluginHelpers::CreateMessage, this, &ValveMenuStyle::HookCreateMessage, nullptr), + m_players(new CValveMenuPlayer[256+1]) { } @@ -66,31 +66,30 @@ bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCom void ValveMenuStyle::OnSourceModAllInitialized() { g_Players.AddClientListener(this); - SH_ADD_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); - g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers); + m_HookCreateMessage.Add(serverpluginhelpers); } void ValveMenuStyle::OnSourceModShutdown() { - SH_RELEASE_CALLCLASS(g_pSPHCC); - SH_REMOVE_HOOK(IServerPluginHelpers, CreateMessage, serverpluginhelpers, SH_MEMBER(this, &ValveMenuStyle::HookCreateMessage), false); + m_HookCreateMessage.Remove(serverpluginhelpers); g_Players.RemoveClientListener(this); } -void ValveMenuStyle::HookCreateMessage(edict_t *pEdict, +KHook::Return ValveMenuStyle::HookCreateMessage(IServerPluginHelpers*, + edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin) { if (type != DIALOG_MENU) { - return; + return { KHook::Action::Ignore }; } int client = IndexOfEdict(pEdict); if (client < 1 || client > 256) { - return; + return { KHook::Action::Ignore }; } CValveMenuPlayer *player = &m_players[client]; @@ -110,6 +109,7 @@ void ValveMenuStyle::HookCreateMessage(edict_t *pEdict, */ _CancelClientMenu(client, MenuCancel_Interrupted, true); } + return { KHook::Action::Ignore }; } IMenuPanel *ValveMenuStyle::CreatePanel() @@ -323,7 +323,8 @@ void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int ti m_pKv->SetInt("level", priority); m_pKv->SetInt("time", time ? time : 200); - SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)( + KHook::CallOriginal(&IServerPluginHelpers::CreateMessage, + serverpluginhelpers, PEntityOfEntIndex(client), DIALOG_MENU, m_pKv, diff --git a/core/MenuStyle_Valve.h b/core/MenuStyle_Valve.h index 03fa1226fd..55402df797 100644 --- a/core/MenuStyle_Valve.h +++ b/core/MenuStyle_Valve.h @@ -79,7 +79,8 @@ class ValveMenuStyle : unsigned int GetApproxMemUsage(); bool IsSupported() { return true; } private: - void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin); + KHook::Return HookCreateMessage(IServerPluginHelpers*, edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin); + KHook::Virtual m_HookCreateMessage; private: CValveMenuPlayer *m_players; }; diff --git a/core/MenuVoting.h b/core/MenuVoting.h index 7660b29430..11f299310d 100644 --- a/core/MenuVoting.h +++ b/core/MenuVoting.h @@ -34,11 +34,10 @@ #include #include -#include +#include #include "sm_globals.h" #include -using namespace SourceHook; using namespace SourceMod; class VoteMenuHandler : @@ -97,7 +96,7 @@ class VoteMenuHandler : unsigned int m_Clients; unsigned int m_TotalClients; unsigned int m_Items; - CVector m_Votes; + std::vector m_Votes; IBaseMenu *m_pCurMenu; bool m_bStarted; bool m_bCancelled; diff --git a/core/NextMap.cpp b/core/NextMap.cpp index 16b6b25a3d..c0c5656518 100644 --- a/core/NextMap.cpp +++ b/core/NextMap.cpp @@ -34,7 +34,6 @@ #include "HalfLife2.h" #include "sourcemm_api.h" #include "sm_stringutil.h" -#include "sourcehook.h" #include "logic_bridge.h" #include "compat_wrappers.h" #include @@ -42,17 +41,7 @@ NextMapManager g_NextMap; -#if SOURCE_ENGINE != SE_DARKMESSIAH -SH_DECL_HOOK2_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *); -#else -SH_DECL_HOOK4_void(IVEngineServer, ChangeLevel, SH_NOATTRIB, 0, const char *, const char *, const char *, bool); -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); -#else -SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); -#endif +KHook::Virtual gCommandDispatch(&ConCommand::Dispatch, CmdChangeLevelCallback, nullptr); ConCommand *changeLevelCmd = NULL; @@ -63,27 +52,25 @@ bool g_forcedChange = false; void NextMapManager::OnSourceModAllInitialized_Post() { - SH_ADD_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false); - + m_HookChangeLevel.Add(engine); ConCommand *pCmd = FindCommand("changelevel"); if (pCmd != NULL) { - SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdChangeLevelCallback), false); + gCommandDispatch.Add(pCmd); changeLevelCmd = pCmd; } } void NextMapManager::OnSourceModShutdown() { - SH_REMOVE_HOOK(IVEngineServer, ChangeLevel, engine, SH_MEMBER(this, &NextMapManager::HookChangeLevel), false); + m_HookChangeLevel.Remove(engine); if (changeLevelCmd != NULL) { - SH_REMOVE_HOOK(ConCommand, Dispatch, changeLevelCmd, SH_STATIC(CmdChangeLevelCallback), false); + gCommandDispatch.Remove(changeLevelCmd); } - SourceHook::List::iterator iter; - iter = m_mapHistory.begin(); + auto iter = m_mapHistory.begin(); while (iter != m_mapHistory.end()) { @@ -112,15 +99,15 @@ bool NextMapManager::SetNextMap(const char *map) static char g_nextMap[PLATFORM_MAX_PATH]; #if SOURCE_ENGINE != SE_DARKMESSIAH -void NextMapManager::HookChangeLevel(const char *map, const char *unknown) +KHook::Return NextMapManager::HookChangeLevel(IVEngineServer* this_ptr, const char *map, const char *unknown) #else -void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading) +KHook::Return NextMapManager::HookChangeLevel(IVEngineServer* this_ptr, const char *map, const char *unknown, const char *video, bool bLongLoading) #endif { if (g_forcedChange) { logger->LogMessage("[SM] Changed map to \"%s\"", map); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } const char *newmap = sm_nextmap.GetString(); @@ -135,7 +122,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const if (newmap[0] == '\0' || !g_HL2.IsMapValid(newmap)) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } logger->LogMessage("[SM] Changed map to \"%s\"", newmap); @@ -144,9 +131,9 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const ke::SafeStrcpy(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "Normal level change"); #if SOURCE_ENGINE != SE_DARKMESSIAH - RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown)); + return KHook::Recall(&IVEngineServer::ChangeLevel, KHook::Return{ KHook::Action::Ignore }, this_ptr, newmap, unknown); #else - RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::ChangeLevel, (newmap, unknown, video, bLongLoading)); + return KHook::Recall(&IVEngineServer::ChangeLevel, KHook::Return{ KHook::Action::Ignore }, this_ptr, newmap, unknown, video, bLongLoading); #endif } @@ -186,7 +173,7 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName ) historydiff = (m_mapHistory.size() * -1); } - for (SourceHook::List::iterator iter = m_mapHistory.begin(); historydiff++ < 0; iter = m_mapHistory.erase(iter)) + for (auto iter = m_mapHistory.begin(); historydiff++ < 0; iter = m_mapHistory.erase(iter)) { delete (MapChangeData *)*iter; } @@ -210,24 +197,24 @@ void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeRe g_forcedChange = false; } -NextMapManager::NextMapManager() +NextMapManager::NextMapManager() : + m_HookChangeLevel(&IVEngineServer::ChangeLevel, this, &NextMapManager::HookChangeLevel, nullptr) { m_tempChangeInfo = MapChangeData(); - m_mapHistory = SourceHook::List(); } #if SOURCE_ENGINE >= SE_ORANGEBOX -void CmdChangeLevelCallback(const CCommand &command) +KHook::Return CmdChangeLevelCallback(ConCommand*, const CCommand &command) { #else -void CmdChangeLevelCallback() +KHook::Return CmdChangeLevelCallback(ConCommand*) { CCommand command; #endif if (command.ArgC() < 2) { - return; + return { KHook::Action::Ignore }; } if (g_NextMap.m_tempChangeInfo.m_mapName[0] == '\0') @@ -235,4 +222,6 @@ void CmdChangeLevelCallback() ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_mapName, sizeof(g_NextMap.m_tempChangeInfo.m_mapName), command.Arg(1)); ke::SafeStrcpy(g_NextMap.m_tempChangeInfo.m_changeReason, sizeof(g_NextMap.m_tempChangeInfo.m_changeReason), "changelevel Command"); } + + return { KHook::Action::Ignore }; } diff --git a/core/NextMap.h b/core/NextMap.h index 2f6c0523ec..e11b0cf1ca 100644 --- a/core/NextMap.h +++ b/core/NextMap.h @@ -34,9 +34,10 @@ #include "sm_globals.h" #include -#include "sh_list.h" +#include #include "sm_stringutil.h" #include +#include struct MapChangeData { @@ -60,9 +61,9 @@ struct MapChangeData }; #if SOURCE_ENGINE >= SE_ORANGEBOX -void CmdChangeLevelCallback(const CCommand &command); +KHook::Return CmdChangeLevelCallback(ConCommand*, const CCommand &command); #else -void CmdChangeLevelCallback(); +KHook::Return CmdChangeLevelCallback(ConCommand*); #endif class NextMapManager : public SMGlobalClass @@ -71,9 +72,9 @@ class NextMapManager : public SMGlobalClass NextMapManager(); #if SOURCE_ENGINE >= SE_ORANGEBOX - friend void CmdChangeLevelCallback(const CCommand &command); + friend KHook::Return CmdChangeLevelCallback(ConCommand*, const CCommand &command); #else - friend void CmdChangeLevelCallback(); + friend KHook::Return CmdChangeLevelCallback(ConCommand*); #endif void OnSourceModAllInitialized_Post(); @@ -86,13 +87,15 @@ class NextMapManager : public SMGlobalClass void ForceChangeLevel(const char *mapName, const char* changeReason); #if SOURCE_ENGINE != SE_DARKMESSIAH - void HookChangeLevel(const char *map, const char *unknown); + KHook::Virtual m_HookChangeLevel; + KHook::Return HookChangeLevel(IVEngineServer*, const char *map, const char *unknown); #else - void HookChangeLevel(const char *map, const char *unknown, const char *video, bool bLongLoading); + KHook::Virtual m_HookChangeLevel; + KHook::Return HookChangeLevel(IVEngineServer*, const char *map, const char *unknown, const char *video, bool bLongLoading); #endif public: - SourceHook::List m_mapHistory; + std::list m_mapHistory; private: MapChangeData m_tempChangeInfo; diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 1d541daa36..c94f10f5a6 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -64,38 +64,11 @@ IForward *ServerExitHibernation = NULL; const unsigned int *g_NumPlayersToAuth = NULL; int lifestate_offset = -1; -List target_processors; +std::list target_processors; ConVar sm_debug_connect("sm_debug_connect", "1", 0, "Log Debug information about potential connection issues."); -SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int); -SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *); -SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *); -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); -#else -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -#endif -SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *); - -#if SOURCE_ENGINE >= SE_EYE -SH_DECL_HOOK2_void(IServerGameClients, ClientCommandKeyValues, SH_NOATTRIB, 0, edict_t *, KeyValues *); -#endif - -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); - -#if SOURCE_ENGINE >= SE_LEFT4DEAD -SH_DECL_HOOK1_void(IServerGameDLL, ServerHibernationUpdate, SH_NOATTRIB, 0, bool); -#elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox. -SH_DECL_HOOK1_void(IServerGameDLL, SetServerHibernation, SH_NOATTRIB, 0, bool); -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); -#else -SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); -#endif -SH_DECL_HOOK2_void(IVEngineServer, ClientPrintf, SH_NOATTRIB, 0, edict_t *, const char *); +KHook::Virtual gHookCommandDispatch(&ConCommand::Dispatch, nullptr, &CmdMaxplayersCallback); static void PrintfBuffer_FrameAction(void *data) { @@ -125,7 +98,22 @@ class KickPlayerTimer : public ITimedEvent } } s_KickPlayerTimer; -PlayerManager::PlayerManager() +PlayerManager::PlayerManager() : + m_HookClientConnect(&IServerGameClients::ClientConnect, this, &PlayerManager::OnClientConnect, &PlayerManager::OnClientConnect_Post), + m_HookClientPutInServer(&IServerGameClients::ClientPutInServer, this, nullptr, &PlayerManager::OnClientPutInServer), + m_HookClientDisconnect(&IServerGameClients::ClientDisconnect, this, &PlayerManager::OnClientDisconnect, &PlayerManager::OnClientDisconnect_Post), + m_HookClientCommand(&IServerGameClients::ClientCommand, this, &PlayerManager::OnClientCommand, nullptr), +#if SOURCE_ENGINE >= SE_EYE + m_HookClientCommandKeyValues(&IServerGameClients::ClientCommandKeyValues, this, &PlayerManager::OnClientCommandKeyValues, &PlayerManager::OnClientCommandKeyValues_Post), +#endif + m_HookClientSettingsChanged(&IServerGameClients::ClientSettingsChanged, this, nullptr, &PlayerManager::OnClientSettingsChanged), + m_HookServerActivate(&IServerGameDLL::ServerActivate, this, nullptr, &PlayerManager::OnServerActivate), +#if SOURCE_ENGINE >= SE_LEFT4DEAD + m_HookOnServerHibernationUpdate(&IServerGameDLL::ServerHibernationUpdate, this, nullptr, &PlayerManager::OnServerHibernationUpdate), +#elif SOURCE_ENGINE > SE_EYE + m_HookSetServerHibernation(&IServerGameDLL::SetServerHibernation, this, nullptr, &PlayerManager::OnServerHibernationUpdate), +#endif + m_HookClientPrintf(&IVEngineServer::ClientPrintf, this, &PlayerManager::OnClientPrintf, nullptr) { m_AuthQueue = NULL; m_bServerActivated = false; @@ -164,24 +152,21 @@ void PlayerManager::OnSourceModStartup(bool late) void PlayerManager::OnSourceModAllInitialized() { - SH_ADD_HOOK(IServerGameClients, ClientConnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientConnect), false); - SH_ADD_HOOK(IServerGameClients, ClientConnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientConnect_Post), true); - SH_ADD_HOOK(IServerGameClients, ClientPutInServer, serverClients, SH_MEMBER(this, &PlayerManager::OnClientPutInServer), true); - SH_ADD_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect), false); - SH_ADD_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true); - SH_ADD_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommand), false); + m_HookClientConnect.Add(serverClients); + m_HookClientPutInServer.Add(serverClients); + m_HookClientDisconnect.Add(serverClients); + m_HookClientCommand.Add(serverClients); #if SOURCE_ENGINE >= SE_EYE - SH_ADD_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues), false); - SH_ADD_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues_Post), true); + m_HookClientCommandKeyValues.Add(serverClients); #endif - SH_ADD_HOOK(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true); - SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true); + m_HookClientSettingsChanged.Add(serverClients); + m_HookServerActivate.Add(gamedll); #if SOURCE_ENGINE >= SE_LEFT4DEAD - SH_ADD_HOOK(IServerGameDLL, ServerHibernationUpdate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true); + m_HookOnServerHibernationUpdate.Add(gamedll); #elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox. - SH_ADD_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true); + m_HookSetServerHibernation.Add(gamedll); #endif - SH_ADD_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false); + m_HookClientPrintf.Add(engine); sharesys->AddInterface(NULL, this); @@ -214,31 +199,28 @@ void PlayerManager::OnSourceModAllInitialized() ConCommand *pCmd = FindCommand("maxplayers"); if (pCmd != NULL) { - SH_ADD_HOOK(ConCommand, Dispatch, pCmd, SH_STATIC(CmdMaxplayersCallback), true); + gHookCommandDispatch.Add(pCmd); maxplayersCmd = pCmd; } } void PlayerManager::OnSourceModShutdown() { - SH_REMOVE_HOOK(IServerGameClients, ClientConnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientConnect), false); - SH_REMOVE_HOOK(IServerGameClients, ClientConnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientConnect_Post), true); - SH_REMOVE_HOOK(IServerGameClients, ClientPutInServer, serverClients, SH_MEMBER(this, &PlayerManager::OnClientPutInServer), true); - SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect), false); - SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true); - SH_REMOVE_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommand), false); + m_HookClientConnect.Remove(serverClients); + m_HookClientPutInServer.Remove(serverClients); + m_HookClientDisconnect.Remove(serverClients); + m_HookClientCommand.Remove(serverClients); #if SOURCE_ENGINE >= SE_EYE - SH_REMOVE_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues), false); - SH_REMOVE_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues_Post), true); + m_HookClientCommandKeyValues.Remove(serverClients); #endif - SH_REMOVE_HOOK(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true); - SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true); + m_HookClientSettingsChanged.Remove(serverClients); + m_HookServerActivate.Remove(gamedll); #if SOURCE_ENGINE >= SE_LEFT4DEAD - SH_REMOVE_HOOK(IServerGameDLL, ServerHibernationUpdate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true); + m_HookOnServerHibernationUpdate.Remove(gamedll); #elif SOURCE_ENGINE > SE_EYE // 2013/orangebox, but not original orangebox. - SH_REMOVE_HOOK(IServerGameDLL, SetServerHibernation, gamedll, SH_MEMBER(this, &PlayerManager::OnServerHibernationUpdate), true); + m_HookSetServerHibernation.Remove(gamedll); #endif - SH_REMOVE_HOOK(IVEngineServer, ClientPrintf, engine, SH_MEMBER(this, &PlayerManager::OnClientPrintf), false); + m_HookClientPrintf.Remove(engine); /* Release forwards */ forwardsys->ReleaseForward(m_clconnect); @@ -265,7 +247,7 @@ void PlayerManager::OnSourceModShutdown() if (maxplayersCmd != NULL) { - SH_REMOVE_HOOK(ConCommand, Dispatch, maxplayersCmd, SH_STATIC(CmdMaxplayersCallback), true); + gHookCommandDispatch.Remove(maxplayersCmd); } } @@ -308,7 +290,7 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key, return ConfigResult_Ignore; } -void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax) +KHook::Return PlayerManager::OnServerActivate(IServerGameDLL*, edict_t *pEdictList, int edictCount, int clientMax) { static ConVar *tv_enable = icvar->FindVar("tv_enable"); #if SOURCE_ENGINE == SE_TF2 @@ -331,8 +313,7 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl m_onActivate->Execute(NULL); m_onActivate2->Execute(NULL); - List::iterator iter; - for (iter = m_hooks.begin(); iter != m_hooks.end(); iter++) + for (auto iter = m_hooks.begin(); iter != m_hooks.end(); iter++) { if ((*iter)->GetClientListenerVersion() >= 5) { @@ -348,6 +329,8 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl } SM_ExecuteAllConfigs(); + + return { KHook::Action::Ignore }; } bool PlayerManager::IsServerActivated() @@ -434,9 +417,8 @@ void PlayerManager::RunAuthChecks() const char *steamId = pPlayer->GetSteam2Id(); /* Send to extensions */ - List::iterator iter; IClientListener *pListener; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientAuthorized(client, steamId ? steamId : authstr); @@ -492,7 +474,7 @@ void PlayerManager::RunAuthChecks() } } -bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) +KHook::Return PlayerManager::OnClientConnect(IServerGameClients* clients, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { int client = IndexOfEdict(pEntity); CPlayer *pPlayer = &m_Players[client]; @@ -511,8 +493,8 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const logger->LogMessage("\"%s<%d><%s><>\" was already connected to the server.", pPlayer->GetName(), pPlayer->GetUserId(), pAuth); } - OnClientDisconnect(pPlayer->GetEdict()); - OnClientDisconnect_Post(pPlayer->GetEdict()); + OnClientDisconnect(clients, pPlayer->GetEdict()); + OnClientDisconnect_Post(clients, pPlayer->GetEdict()); } pPlayer->Initialize(pszName, pszAddress, pEntity); @@ -537,14 +519,13 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const pPlayer->m_OriginalLangId = pPlayer->m_LangId; } - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); if (!pListener->InterceptClientConnect(client, reject, maxrejectlen)) { - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; } } @@ -568,30 +549,29 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const { if (!pPlayer->IsFakeClient()) { - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; } } - return true; + return { KHook::Action::Ignore, true }; } -bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) +KHook::Return PlayerManager::OnClientConnect_Post(IServerGameClients*, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { int client = IndexOfEdict(pEntity); - bool orig_value = META_RESULT_ORIG_RET(bool); + bool orig_value = *(bool*)KHook::GetOriginalValuePtr(); CPlayer *pPlayer = &m_Players[client]; if (orig_value) { - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientConnected(client); if (!pPlayer->IsConnected()) { - return true; + return { KHook::Action::Ignore }; } } @@ -611,10 +591,10 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, InvalidatePlayer(pPlayer); } - return true; + return { KHook::Action::Ignore }; } -void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername) +KHook::Return PlayerManager::OnClientPutInServer(IServerGameClients* clients, edict_t *pEntity, const char *playername) { cell_t res; int client = IndexOfEdict(pEntity); @@ -693,21 +673,21 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername m_SourceTVUserId = userId; } - if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error))) + if (!OnClientConnect(clients, pEntity, playername, "127.0.0.1", error, sizeof(error)).ret) { /* :TODO: kick the bot if it's rejected */ - return; + return { KHook::Action::Ignore }; } - List::iterator iter; + IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientConnected(client); /* See if bot was kicked */ if (!pPlayer->IsConnected()) { - return; + return { KHook::Action::Ignore }; } } @@ -720,7 +700,7 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername const char *steamId = pPlayer->GetSteam2Id(); /* Now do authorization */ - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientAuthorized(client, steamId ? steamId : pPlayer->m_AuthID.c_str()); @@ -751,9 +731,8 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername pPlayer->Connect(); m_PlayerCount++; - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientPutInServer(client); @@ -766,6 +745,8 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername { pPlayer->DoPostConnectAuthorization(); } + + return { KHook::Action::Ignore }; } void PlayerManager::OnSourceModLevelEnd() @@ -775,14 +756,14 @@ void PlayerManager::OnSourceModLevelEnd() { if (m_Players[i].IsConnected()) { - OnClientDisconnect(m_Players[i].GetEdict()); - OnClientDisconnect_Post(m_Players[i].GetEdict()); + OnClientDisconnect(serverClients, m_Players[i].GetEdict()); + OnClientDisconnect_Post(serverClients, m_Players[i].GetEdict()); } } m_PlayerCount = 0; } -void PlayerManager::OnServerHibernationUpdate(bool bHibernating) +KHook::Return PlayerManager::OnServerHibernationUpdate(IServerGameDLL*, bool bHibernating) { cell_t res; if (bHibernating) @@ -805,14 +786,16 @@ void PlayerManager::OnServerHibernationUpdate(bool bHibernating) if (pPlayer->IsSourceTV() || pPlayer->IsReplay()) continue; #endif - OnClientDisconnect(m_Players[i].GetEdict()); - OnClientDisconnect_Post(m_Players[i].GetEdict()); + OnClientDisconnect(serverClients, m_Players[i].GetEdict()); + OnClientDisconnect_Post(serverClients, m_Players[i].GetEdict()); } } } + + return { KHook::Action::Ignore }; } -void PlayerManager::OnClientDisconnect(edict_t *pEntity) +KHook::Return PlayerManager::OnClientDisconnect(IServerGameClients*, edict_t *pEntity) { cell_t res; int client = IndexOfEdict(pEntity); @@ -826,7 +809,7 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity) else { /* We don't care, prevent a double call */ - return; + return { KHook::Action::Ignore }; } if (pPlayer->WasCountedAsInGame()) @@ -834,23 +817,23 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity) m_PlayerCount--; } - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientDisconnecting(client); } + return { KHook::Action::Ignore }; } -void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity) +KHook::Return PlayerManager::OnClientDisconnect_Post(IServerGameClients*, edict_t *pEntity) { int client = IndexOfEdict(pEntity); CPlayer *pPlayer = &m_Players[client]; if (!pPlayer->IsConnected()) { /* We don't care, prevent a double call */ - return; + return { KHook::Action::Ignore }; } InvalidatePlayer(pPlayer); @@ -865,26 +848,26 @@ void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity) m_cldisconnect_post->PushCell(client); m_cldisconnect_post->Execute(&res, NULL); - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnClientDisconnected(client); } + return { KHook::Action::Ignore }; } -void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg) +KHook::Return PlayerManager::OnClientPrintf(IVEngineServer*, edict_t *pEdict, const char *szMsg) { int client = IndexOfEdict(pEdict); CPlayer &player = m_Players[client]; if (!player.IsConnected()) - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; INetChannel *pNetChan = static_cast(engine->GetPlayerNetInfo(client)); if (pNetChan == NULL) - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; size_t nMsgLen = strlen(szMsg); #if SOURCE_ENGINE == SE_EPISODEONE || SOURCE_ENGINE == SE_DARKMESSIAH @@ -895,7 +878,7 @@ void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg) // if the msg is bigger than allowed then just let it fail if (nMsgLen + 1 >= SVC_Print_BufferSize) // +1 for NETMSG_TYPE_BITS - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; // enqueue msgs if we'd overflow the SVC_Print buffer (+7 as ceil) if (!player.m_PrintfBuffer.empty() || (nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + nMsgLen >= SVC_Print_BufferSize) @@ -907,10 +890,10 @@ void PlayerManager::OnClientPrintf(edict_t *pEdict, const char *szMsg) player.m_PrintfBuffer.push_back(szMsg); - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } void PlayerManager::OnPrintfFrameAction(unsigned int serial) @@ -944,7 +927,7 @@ void PlayerManager::OnPrintfFrameAction(unsigned int serial) if ((nNumBitsWritten + NETMSG_TYPE_BITS + 7) / 8 + string.length() >= SVC_Print_BufferSize) break; - SH_CALL(engine, &IVEngineServer::ClientPrintf)(player.m_pEdict, string.c_str()); + KHook::CallOriginal(&IVEngineServer::ClientPrintf, engine, player.m_pEdict, string.c_str()); player.m_PrintfBuffer.pop_front(); } @@ -1045,7 +1028,7 @@ void ListPluginsToClient(CPlayer *player, const CCommand &args) return; } - SourceHook::List m_FailList; + std::list m_FailList; size_t i = 0; for (; i < plugins->size(); i++) @@ -1077,10 +1060,10 @@ void ListPluginsToClient(CPlayer *player, const CCommand &args) } #if SOURCE_ENGINE >= SE_ORANGEBOX -void PlayerManager::OnClientCommand(edict_t *pEntity, const CCommand &args) +KHook::Return PlayerManager::OnClientCommand(IServerGameClients*, edict_t *pEntity, const CCommand &args) { #else -void PlayerManager::OnClientCommand(edict_t *pEntity) +KHook::Return PlayerManager::OnClientCommand(IServerGameClients*, edict_t *pEntity) { CCommand args; #endif @@ -1091,7 +1074,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) if (!pPlayer->IsConnected()) { - return; + return { KHook::Action::Ignore }; } if (strcmp(args.Arg(0), "sm") == 0) @@ -1099,12 +1082,12 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) if (args.ArgC() > 1 && strcmp(args.Arg(1), "plugins") == 0) { ListPluginsToClient(pPlayer, args); - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } else if (args.ArgC() > 1 && strcmp(args.Arg(1), "exts") == 0) { ListExtensionsToClient(pPlayer, args); - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0) { @@ -1124,7 +1107,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) " Borja \"faluco\" Ferrer, Pavol \"PM OnoTo\" Marko"); ClientConsolePrint(pEntity, "SourceMod is open source under the GNU General Public License."); - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } ClientConsolePrint(pEntity, @@ -1135,7 +1118,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) "To see credits, type \"sm credits\""); ClientConsolePrint(pEntity, "Visit https://www.sourcemod.net/"); - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } EngineArgs cargs(args); @@ -1161,7 +1144,7 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) cell_t res2 = g_ConsoleDetours.InternalDispatch(client, &cargs); if (res2 >= Pl_Handled) { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } else if (res2 > res) { @@ -1184,21 +1167,22 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) if (res >= Pl_Stop) { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res); if (res >= Pl_Handled) { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE >= SE_EYE static bool s_LastCCKVAllowed = true; -void PlayerManager::OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand) +KHook::Return PlayerManager::OnClientCommandKeyValues(IServerGameClients*, edict_t *pEntity, KeyValues *pCommand) { int client = IndexOfEdict(pEntity); @@ -1207,12 +1191,12 @@ void PlayerManager::OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pComma if (!pPlayer->IsInGame()) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } KeyValueStack *pStk = new KeyValueStack; pStk->pBase = pCommand; - pStk->pCurRoot.push(pStk->pBase); + pStk->pCurRoot.push_front(pStk->pBase); pStk->m_bDeleteOnDestroy = false; Handle_t hndl = handlesys->CreateHandle(g_KeyValueType, pStk, g_pCoreIdent, g_pCoreIdent, NULL); @@ -1231,19 +1215,19 @@ void PlayerManager::OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pComma if (res >= Pl_Handled) { s_LastCCKVAllowed = false; - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } s_LastCCKVAllowed = true; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void PlayerManager::OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand) +KHook::Return PlayerManager::OnClientCommandKeyValues_Post(IServerGameClients*, edict_t *pEntity, KeyValues *pCommand) { if (!s_LastCCKVAllowed) { - return; + return { KHook::Action::Ignore }; } int client = IndexOfEdict(pEntity); @@ -1252,12 +1236,12 @@ void PlayerManager::OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *p if (!pPlayer->IsInGame()) { - return; + return { KHook::Action::Ignore }; } KeyValueStack *pStk = new KeyValueStack; pStk->pBase = pCommand; - pStk->pCurRoot.push(pStk->pBase); + pStk->pCurRoot.push_front(pStk->pBase); pStk->m_bDeleteOnDestroy = false; Handle_t hndl = handlesys->CreateHandle(g_KeyValueType, pStk, g_pCoreIdent, g_pCoreIdent, NULL); @@ -1272,10 +1256,12 @@ void PlayerManager::OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *p // Deletes pStk handlesys->FreeHandle(hndl, &sec); + + return { KHook::Action::Ignore }; } #endif -void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) +KHook::Return PlayerManager::OnClientSettingsChanged(IServerGameClients*, edict_t *pEntity) { cell_t res; int client = IndexOfEdict(pEntity); @@ -1283,7 +1269,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) if (!pPlayer->IsConnected()) { - return; + return { KHook::Action::Ignore }; } m_clinfochanged->PushCell(client); @@ -1305,7 +1291,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) char kickMsg[128]; logicore.CoreTranslate(kickMsg, sizeof(kickMsg), "%T", 2, NULL, "Name Reserved", &client); pPlayer->Kick(kickMsg); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } } else if ((id = adminsys->FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) { @@ -1347,15 +1333,14 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress()); pPlayer->Kick("NetworkID spoofing detected."); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } #endif } /* Notify Extensions */ - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); if (pListener->GetClientListenerVersion() >= 13) @@ -1363,6 +1348,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) pListener->OnClientSettingsChanged(client); } } + return { KHook::Action::Ignore }; } void PlayerManager::OnClientLanguageChanged(int client, unsigned int language) @@ -1842,8 +1828,7 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info) } } - List::iterator iter; - for (iter = target_processors.begin(); iter != target_processors.end(); iter++) + for (auto iter = target_processors.begin(); iter != target_processors.end(); iter++) { ICommandTargetProcessor *pProcessor = (*iter); if (pProcessor->ProcessCommandTarget(info)) @@ -1926,9 +1911,8 @@ void PlayerManager::MaxPlayersChanged( int newvalue /*= -1*/ ) } /* Notify Extensions */ - List::iterator iter; IClientListener *pListener = NULL; - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); if (pListener->GetClientListenerVersion() >= 8) @@ -1961,14 +1945,16 @@ int PlayerManager::GetClientFromSerial(unsigned int serial) } #if SOURCE_ENGINE >= SE_ORANGEBOX -void CmdMaxplayersCallback(const CCommand &command) +KHook::Return CmdMaxplayersCallback(ConCommand*, const CCommand &command) { #else -void CmdMaxplayersCallback() +KHook::Return CmdMaxplayersCallback(ConCommand*) { #endif g_Players.MaxPlayersChanged(); + + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV @@ -2451,8 +2437,7 @@ void CPlayer::DoPostConnectAuthorization() { bool delay = false; - List::iterator iter; - for (iter = g_Players.m_hooks.begin(); + for (auto iter = g_Players.m_hooks.begin(); iter != g_Players.m_hooks.end(); iter++) { @@ -2511,8 +2496,7 @@ void CPlayer::NotifyPostAdminChecks() /* Block beforehand so they can't double-call */ m_bAdminCheckSignalled = true; - List::iterator iter; - for (iter = g_Players.m_hooks.begin(); + for (auto iter = g_Players.m_hooks.begin(); iter != g_Players.m_hooks.end(); iter++) { diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 799ce56254..e6181305f1 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -39,17 +39,15 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include "ConVarManager.h" #include -using namespace SourceHook; - class IClient; #define PLAYER_LIFE_UNKNOWN 0 @@ -131,9 +129,9 @@ class CPlayer : public IGamePlayer bool m_IsInGame = false; bool m_IsAuthorized = false; bool m_bIsInKickQueue = false; - String m_Name; - String m_Ip; - String m_IpNoPort; + std::string m_Name; + std::string m_Ip; + std::string m_IpNoPort; std::string m_AuthID; std::string m_Steam2Id; std::string m_Steam3Id; @@ -142,7 +140,7 @@ class CPlayer : public IGamePlayer edict_t *m_pEdict = nullptr; IPlayerInfo *m_Info = nullptr; IClient *m_pIClient = nullptr; - String m_LastPassword; + std::string m_LastPassword; bool m_bAdminCheckSignalled = false; int m_iIndex; unsigned int m_LangId = SOURCEMOD_LANGUAGE_ENGLISH; @@ -178,25 +176,40 @@ class PlayerManager : CPlayer *GetPlayerByIndex(int client) const; void RunAuthChecks(); public: - bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); - bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); - void OnClientPutInServer(edict_t *pEntity, char const *playername); - void OnClientDisconnect(edict_t *pEntity); - void OnClientDisconnect_Post(edict_t *pEntity); + KHook::Virtual m_HookClientConnect; + KHook::Return OnClientConnect(IServerGameClients*, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); + KHook::Return OnClientConnect_Post(IServerGameClients*, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); + KHook::Virtual m_HookClientPutInServer; + KHook::Return OnClientPutInServer(IServerGameClients*, edict_t *pEntity, char const *playername); + KHook::Virtual m_HookClientDisconnect; + KHook::Return OnClientDisconnect(IServerGameClients*, edict_t *pEntity); + KHook::Return OnClientDisconnect_Post(IServerGameClients*, edict_t *pEntity); #if SOURCE_ENGINE >= SE_ORANGEBOX - void OnClientCommand(edict_t *pEntity, const CCommand &args); + KHook::Virtual m_HookClientCommand; + KHook::Return OnClientCommand(IServerGameClients*, edict_t *pEntity, const CCommand &args); #if SOURCE_ENGINE >= SE_EYE - void OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand); - void OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand); + KHook::Virtual m_HookClientCommandKeyValues; + KHook::Return OnClientCommandKeyValues(IServerGameClients*, edict_t *pEntity, KeyValues *pCommand); + KHook::Return OnClientCommandKeyValues_Post(IServerGameClients*, edict_t *pEntity, KeyValues *pCommand); #endif #else - void OnClientCommand(edict_t *pEntity); + KHook::Virtual m_HookClientCommand; + KHook::Return OnClientCommand(IServerGameClients*, edict_t *pEntity); #endif - void OnClientSettingsChanged(edict_t *pEntity); + KHook::Virtual m_HookClientSettingsChanged; + KHook::Return OnClientSettingsChanged(IServerGameClients*, edict_t *pEntity); //void OnClientSettingsChanged_Pre(edict_t *pEntity); void OnClientLanguageChanged(int client, unsigned int language); - void OnServerHibernationUpdate(bool bHibernating); - void OnClientPrintf(edict_t *pEdict, const char *szMsg); + KHook::Virtual m_HookServerActivate; + KHook::Return OnServerActivate(IServerGameDLL*, edict_t *pEdictList, int edictCount, int clientMax); +#if SOURCE_ENGINE >= SE_LEFT4DEAD + KHook::Virtual m_HookOnServerHibernationUpdate; +#elif SOURCE_ENGINE > SE_EYE + KHook::Virtual m_HookSetServerHibernation; +#endif + KHook::Return OnServerHibernationUpdate(IServerGameDLL*, bool bHibernating); + KHook::Virtual m_HookClientPrintf; + KHook::Return OnClientPrintf(IVEngineServer*, edict_t *pEdict, const char *szMsg); void OnPrintfFrameAction(unsigned int serial); public: //IPlayerManager void AddClientListener(IClientListener *listener); @@ -242,10 +255,9 @@ class PlayerManager : bool HandleConVarQuery(QueryCvarCookie_t cookie, int client, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue); #endif private: - void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); void InvalidatePlayer(CPlayer *pPlayer); private: - List m_hooks; + std::list m_hooks; IForward *m_clconnect; IForward *m_clconnect_post; IForward *m_cldisconnect; @@ -266,7 +278,7 @@ class PlayerManager : int m_PlayersSinceActive; bool m_bServerActivated; unsigned int *m_AuthQueue; - String m_PassInfoVar; + std::string m_PassInfoVar; bool m_QueryLang; bool m_bAuthstringValidation; // are we validating admins with steam before authorizing? bool m_bIsListenServer; @@ -282,9 +294,9 @@ class PlayerManager : }; #if SOURCE_ENGINE >= SE_ORANGEBOX -void CmdMaxplayersCallback(const CCommand &command); +KHook::Return CmdMaxplayersCallback(ConCommand*, const CCommand &command); #else -void CmdMaxplayersCallback(); +KHook::Return CmdMaxplayersCallback(ConCommand*); #endif extern void ClientConsolePrint(edict_t *e, const char *fmt, ...); diff --git a/core/TimerSys.cpp b/core/TimerSys.cpp index 2084b153e1..f346953d59 100644 --- a/core/TimerSys.cpp +++ b/core/TimerSys.cpp @@ -177,12 +177,11 @@ TimerSystem::TimerSystem() TimerSystem::~TimerSystem() { - CStack::iterator iter; - for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++) + while (!m_FreeTimers.empty()) { - delete (*iter); + delete m_FreeTimers.top(); + m_FreeTimers.pop(); } - m_FreeTimers.popall(); } void TimerSystem::OnSourceModAllInitialized() @@ -304,7 +303,7 @@ ITimer *TimerSystem::CreateTimer(ITimedEvent *pCallbacks, float fInterval, void { pTimer = new ITimer; } else { - pTimer = m_FreeTimers.front(); + pTimer = m_FreeTimers.top(); m_FreeTimers.pop(); } @@ -402,7 +401,7 @@ void TimerSystem::KillTimer(ITimer *pTimer) m_FreeTimers.push(pTimer); } -CStack s_tokill; +std::stack s_tokill; void TimerSystem::RemoveMapChangeTimers() { ITimer *pTimer; @@ -428,7 +427,7 @@ void TimerSystem::RemoveMapChangeTimers() while (!s_tokill.empty()) { - KillTimer(s_tokill.front()); + KillTimer(s_tokill.top()); s_tokill.pop(); } } diff --git a/core/TimerSys.h b/core/TimerSys.h index c5a9b75889..dd56107327 100644 --- a/core/TimerSys.h +++ b/core/TimerSys.h @@ -33,16 +33,15 @@ #define _INCLUDE_SOURCEMOD_CTIMERSYS_H_ #include -#include -#include +#include +#include #include "sourcemm_api.h" #include "sm_globals.h" -using namespace SourceHook; using namespace SourceMod; -typedef List TimerList; -typedef List::iterator TimerIter; +typedef std::list TimerList; +typedef TimerList::iterator TimerIter; class SourceMod::ITimer { @@ -84,9 +83,9 @@ class TimerSystem : void RemoveMapChangeTimers(); void GameFrame(bool simulating); private: - List m_SingleTimers; - List m_LoopTimers; - CStack m_FreeTimers; + std::list m_SingleTimers; + std::list m_LoopTimers; + std::stack m_FreeTimers; IMapTimer *m_pMapTimer; /* This is stuff for our manual ticking escapades. */ diff --git a/core/UserMessagePBHelpers.h b/core/UserMessagePBHelpers.h index 2a12cd3c96..0e627b3036 100644 --- a/core/UserMessagePBHelpers.h +++ b/core/UserMessagePBHelpers.h @@ -32,7 +32,7 @@ #ifndef _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_ #define _INCLUDE_SOURCEMOD_SMPBMESSAGE_H_ -#include +#include #include #include @@ -85,7 +85,7 @@ return false; \ } -typedef List PBHandleList; +typedef std::list PBHandleList; class SMProtobufMessage { @@ -97,7 +97,7 @@ class SMProtobufMessage ~SMProtobufMessage() { - PBHandleList::iterator iter = childHandles.begin(); + auto iter = childHandles.begin(); while (iter != childHandles.end()) { Handle_t &hndl = (*iter); diff --git a/core/UserMessages.cpp b/core/UserMessages.cpp index 413ae7853b..98fefbbddf 100644 --- a/core/UserMessages.cpp +++ b/core/UserMessages.cpp @@ -44,25 +44,19 @@ UserMessages g_UserMsgs; -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &); -#else -#if SOURCE_ENGINE >= SE_LEFT4DEAD -SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *); -#else -SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int); -#endif -SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0); -#endif // ==SE_CSGO || ==SE_BLADE || ==SE_MCV - UserMessages::UserMessages() #ifndef USE_PROTOBUF_USERMESSAGES - : m_InterceptBuffer(m_pBase, 2500) -{ + : m_InterceptBuffer(m_pBase, 2500), #else - : m_InterceptBuffer(NULL) -{ + : m_InterceptBuffer(NULL), #endif +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV + m_SendUserMessage(&IVEngineServer::SendUserMessage, this, &UserMessages::OnSendUserMessage_Pre, &UserMessages::OnSendUserMessage_Post) +#else + m_UserMessageBegin(&IVEngineServer::UserMessageBegin, this, &UserMessages::OnStartMessage_Pre, &UserMessages::OnStartMessage_Post), + m_MessageEnd(&IVEngineServer::MessageEnd, this, &UserMessages::OnMessageEnd_Pre, &UserMessages::OnMessageEnd_Post) +#endif +{ m_HookCount = 0; m_InExec = false; m_InHook = false; @@ -72,12 +66,11 @@ UserMessages::UserMessages() UserMessages::~UserMessages() { - CStack::iterator iter; - for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) + while (!m_FreeListeners.empty()) { - delete (*iter); + delete m_FreeListeners.top(); + m_FreeListeners.pop(); } - m_FreeListeners.popall(); } void UserMessages::OnSourceModStartup(bool late) @@ -98,13 +91,10 @@ void UserMessages::OnSourceModAllShutdown() if (m_HookCount) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); + m_SendUserMessage.Remove(engine); #else - SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); - SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); + m_UserMessageBegin.Remove(engine); + m_MessageEnd.Remove(engine); #endif } m_HookCount = 0; @@ -218,9 +208,9 @@ bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], u if (m_CurFlags & USERMSG_BLOCKHOOKS) { #if SOURCE_ENGINE >= SE_LEFT4DEAD - buffer = ENGINE_CALL(UserMessageBegin)(static_cast(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); + buffer = m_UserMessageBegin.CallOriginal(engine, static_cast(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); #else - buffer = ENGINE_CALL(UserMessageBegin)(static_cast(&m_CellRecFilter), msg_id); + buffer = m_UserMessageBegin.CallOriginal(engine, static_cast(&m_CellRecFilter), msg_id); #endif } else { #if SOURCE_ENGINE >= SE_LEFT4DEAD @@ -278,24 +268,23 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const return NULL; } - protobuf::Message *msg = OnStartMessage_Pre(static_cast(&m_CellRecFilter), msg_id, messageName); + protobuf::Message *msg = OnStartMessage_Pre(engine, static_cast(&m_CellRecFilter), msg_id, messageName).ret; switch (m_FakeMetaRes) { - case MRES_IGNORED: - case MRES_HANDLED: + case KHook::Action::Ignore: m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); buffer = m_FakeEngineBuffer; break; - case MRES_OVERRIDE: + case KHook::Action::Override: m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New(); // fallthrough - case MRES_SUPERCEDE: + case KHook::Action::Supersede: buffer = msg; break; } - OnStartMessage_Post(static_cast(&m_CellRecFilter), msg_id, messageName); + OnStartMessage_Post(engine, static_cast(&m_CellRecFilter), msg_id, messageName); } return buffer; @@ -312,30 +301,29 @@ bool UserMessages::EndMessage() #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV if (m_CurFlags & USERMSG_BLOCKHOOKS) { - ENGINE_CALL(SendUserMessage)(static_cast(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); + KHook::CallOriginal(&IVEngineServer::SendUserMessage, engine, static_cast(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); delete m_FakeEngineBuffer; m_FakeEngineBuffer = NULL; } else { - OnMessageEnd_Pre(); + OnMessageEnd_Pre(engine); switch (m_FakeMetaRes) { - case MRES_IGNORED: - case MRES_HANDLED: - case MRES_OVERRIDE: + case KHook::Action::Ignore: + case KHook::Action::Override: engine->SendUserMessage(static_cast(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer); delete m_FakeEngineBuffer; m_FakeEngineBuffer = NULL; break; - //case MRES_SUPERCEDE: + //case KHook::Action::Supersede: } - OnMessageEnd_Post(); + OnMessageEnd_Post(engine); } #else if (m_CurFlags & USERMSG_BLOCKHOOKS) { - ENGINE_CALL(MessageEnd)(); + m_MessageEnd.CallOriginal(engine); } else { engine->MessageEnd(); } @@ -413,7 +401,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene { pInfo = new ListenerInfo; } else { - pInfo = m_FreeListeners.front(); + pInfo = m_FreeListeners.top(); m_FreeListeners.pop(); } @@ -425,13 +413,10 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene if (!m_HookCount++) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); - SH_ADD_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); + m_SendUserMessage.Add(engine); #else - SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); - SH_ADD_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); - SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); - SH_ADD_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); + m_UserMessageBegin.Add(engine); + m_MessageEnd.Add(engine); #endif } @@ -504,19 +489,16 @@ void UserMessages::_DecRefCounter() if (--m_HookCount == 0) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, SendUserMessage, engine, SH_MEMBER(this, &UserMessages::OnSendUserMessage_Post), true); + m_SendUserMessage.Add(engine); #else - SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, UserMessageBegin, engine, SH_MEMBER(this, &UserMessages::OnStartMessage_Post), true); - SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Pre), false); - SH_REMOVE_HOOK(IVEngineServer, MessageEnd, engine, SH_MEMBER(this, &UserMessages::OnMessageEnd_Post), true); + m_UserMessageBegin.Remove(engine); + m_MessageEnd.Remove(engine); #endif } } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg) +KHook::Return UserMessages::OnSendUserMessage_Pre(IVEngineServer* enginesrv, IRecipientFilter &filter, int msg_type, const protobuf::Message &msg) { #if SOURCE_ENGINE == SE_CSGO const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msg_type); @@ -526,9 +508,9 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const char *pszName = g_VietnamUsermessageHelpers.GetName(msg_type); #endif - OnStartMessage_Pre(&filter, msg_type, pszName); + OnStartMessage_Pre(enginesrv, &filter, msg_type, pszName); - if (m_FakeMetaRes == MRES_SUPERCEDE) + if (m_FakeMetaRes == KHook::Action::Supersede) { int size = msg.ByteSize(); uint8 *data = (uint8 *)stackalloc(size); @@ -540,44 +522,44 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, m_FakeEngineBuffer = &const_cast(msg); } - OnStartMessage_Post(&filter, msg_type, pszName); + OnStartMessage_Post(enginesrv, &filter, msg_type, pszName); - OnMessageEnd_Pre(); - if (m_FakeMetaRes == MRES_SUPERCEDE) - RETURN_META(MRES_SUPERCEDE); + OnMessageEnd_Pre(enginesrv); + if (m_FakeMetaRes == KHook::Action::Supersede) + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg) +KHook::Return UserMessages::OnSendUserMessage_Post(IVEngineServer* enginesrv, IRecipientFilter &filter, int msg_type, const protobuf::Message &msg) { - OnMessageEnd_Post(); - RETURN_META(MRES_IGNORED); + OnMessageEnd_Post(enginesrv); + return { KHook::Action::Ignore }; } #endif #ifdef USE_PROTOBUF_USERMESSAGES #define UM_RETURN_META_VALUE(res, val) \ m_FakeMetaRes = res; \ - return val; + return { res, val }; #define UM_RETURN_META(res) \ m_FakeMetaRes = res; \ - return; + return { res }; #else #define UM_RETURN_META_VALUE(res, val) \ - RETURN_META_VALUE(res, val) + return { res, val }; #define UM_RETURN_META(res) \ - RETURN_META(res) + return { res }; #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) +KHook::Return UserMessages::OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name) #elif SOURCE_ENGINE >= SE_LEFT4DEAD -bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) +KHook::Return UserMessages::OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name) #else -bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type) +KHook::Return UserMessages::OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type) #endif { bool is_intercept_empty = m_msgIntercepts[msg_type].empty(); @@ -587,7 +569,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS))) { m_InHook = false; - UM_RETURN_META_VALUE(MRES_IGNORED, NULL); + UM_RETURN_META_VALUE(KHook::Action::Ignore, NULL) } m_CurId = msg_type; @@ -602,46 +584,47 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ delete m_InterceptBuffer; m_InterceptBuffer = GetMessagePrototype(msg_type)->New(); - UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer); + UM_RETURN_META_VALUE(KHook::Action::Supersede, m_InterceptBuffer) #else m_InterceptBuffer.Reset(); - UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer); + + UM_RETURN_META_VALUE(KHook::Action::Supersede, &m_InterceptBuffer) #endif } - UM_RETURN_META_VALUE(MRES_IGNORED, NULL); + UM_RETURN_META_VALUE(KHook::Action::Ignore, NULL) } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) +KHook::Return UserMessages::OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name) #elif SOURCE_ENGINE >= SE_LEFT4DEAD -bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) +KHook::Return UserMessages::OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name) #else -bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type) +KHook::Return UserMessages::OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type) #endif { if (!m_InHook) { - UM_RETURN_META_VALUE(MRES_IGNORED, NULL); + UM_RETURN_META_VALUE(KHook::Action::Ignore, NULL) } #ifdef USE_PROTOBUF_USERMESSAGES - if (m_FakeMetaRes == MRES_SUPERCEDE) + if (m_FakeMetaRes == KHook::Action::Supersede) m_OrigBuffer = m_InterceptBuffer; else m_OrigBuffer = m_FakeEngineBuffer; #else - m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *); + m_OrigBuffer = *(bf_write**)KHook::GetOriginalValuePtr(); #endif - UM_RETURN_META_VALUE(MRES_IGNORED, NULL); + UM_RETURN_META_VALUE(KHook::Action::Ignore, NULL) } -void UserMessages::OnMessageEnd_Post() +KHook::Return UserMessages::OnMessageEnd_Post(IVEngineServer*) { if (!m_InHook) { - UM_RETURN_META(MRES_IGNORED); + UM_RETURN_META(KHook::Action::Ignore) } MsgList *pList; @@ -703,13 +686,15 @@ void UserMessages::OnMessageEnd_Post() pInfo->IsHooked = false; iter++; } + + UM_RETURN_META(KHook::Action::Ignore) } -void UserMessages::OnMessageEnd_Pre() +KHook::Return UserMessages::OnMessageEnd_Pre(IVEngineServer*) { if (!m_InHook) { - UM_RETURN_META(MRES_IGNORED); + UM_RETURN_META(KHook::Action::Ignore); } MsgList *pList; @@ -778,17 +763,17 @@ void UserMessages::OnMessageEnd_Pre() if (!handled && intercepted) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - ENGINE_CALL(SendUserMessage)(static_cast(*m_CurRecFilter), m_CurId, *m_InterceptBuffer); + m_SendUserMessage.CallOriginal(engine, static_cast(*m_CurRecFilter), m_CurId, *m_InterceptBuffer); #else bf_write *engine_bfw; #if SOURCE_ENGINE >= SE_LEFT4DEAD - engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId)); + engine_bfw = m_UserMessageBegin.CallOriginal(engine, m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId)); #else - engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId); + engine_bfw = m_UserMessageBegin.CallOriginal(engine, m_CurRecFilter, m_CurId); #endif m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten()); engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten()); - ENGINE_CALL(MessageEnd)(); + m_MessageEnd.CallOriginal(engine); #endif // SE_CSGO || SE_BLADE || SE_MCV } @@ -828,8 +813,8 @@ void UserMessages::OnMessageEnd_Pre() #endif } - UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED); + UM_RETURN_META((intercepted) ? KHook::Action::Supersede : KHook::Action::Ignore); supercede: m_BlockEndPost = true; - UM_RETURN_META(MRES_SUPERCEDE); + UM_RETURN_META(KHook::Action::Supersede) } diff --git a/core/UserMessages.h b/core/UserMessages.h index 77cc201ba9..2b511765f2 100644 --- a/core/UserMessages.h +++ b/core/UserMessages.h @@ -38,10 +38,9 @@ #include "sm_stringutil.h" #include "CellRecipientFilter.h" #include "sm_globals.h" -#include -#include +#include +#include -using namespace SourceHook; using namespace SourceMod; #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV @@ -72,8 +71,8 @@ struct ListenerInfo bool IsNew; }; -typedef List MsgList; -typedef List::iterator MsgIter; +typedef std::list MsgList; +typedef MsgList::iterator MsgIter; class UserMessages : public IUserMessages, @@ -103,22 +102,22 @@ class UserMessages : UserMessageType GetUserMessageType() const; public: #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg); - void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg); + KHook::Return OnSendUserMessage_Pre(IVEngineServer*, IRecipientFilter &filter, int msg_type, const protobuf::Message &msg); + KHook::Return OnSendUserMessage_Post(IVEngineServer*, IRecipientFilter &filter, int msg_type, const protobuf::Message &msg); #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name); - protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name); + KHook::Return OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name); + KHook::Return OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name); #elif SOURCE_ENGINE >= SE_LEFT4DEAD - bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name); - bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name); + KHook::Return OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name); + KHook::Return OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type, const char *msg_name); #else - bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type); - bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type); + KHook::Return OnStartMessage_Pre(IVEngineServer*, IRecipientFilter *filter, int msg_type); + KHook::Return OnStartMessage_Post(IVEngineServer*, IRecipientFilter *filter, int msg_type); #endif - void OnMessageEnd_Pre(); - void OnMessageEnd_Post(); + KHook::Return OnMessageEnd_Pre(IVEngineServer*); + KHook::Return OnMessageEnd_Post(IVEngineServer*); private: #ifdef USE_PROTOBUF_USERMESSAGES const protobuf::Message *GetMessagePrototype(int msg_type); @@ -130,9 +129,9 @@ class UserMessages : #endif void _DecRefCounter(); private: - List m_msgHooks[255]; - List m_msgIntercepts[255]; - CStack m_FreeListeners; + std::list m_msgHooks[255]; + std::list m_msgIntercepts[255]; + std::stack m_FreeListeners; IRecipientFilter *m_CurRecFilter; #ifndef USE_PROTOBUF_USERMESSAGES unsigned char m_pBase[2500]; @@ -143,7 +142,7 @@ class UserMessages : // The engine used to provide this. Now we track it. protobuf::Message *m_OrigBuffer; protobuf::Message *m_FakeEngineBuffer; - META_RES m_FakeMetaRes; + KHook::Action m_FakeMetaRes; protobuf::Message *m_InterceptBuffer; #endif @@ -159,6 +158,17 @@ class UserMessages : bool m_InExec; int m_CurFlags; int m_CurId; +protected: +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV + KHook::Virtual m_SendUserMessage; +#else +#if SOURCE_ENGINE >= SE_LEFT4DEAD + KHook::Virtual m_UserMessageBegin; +#else + KHook::Virtual m_UserMessageBegin; +#endif + KHook::Virtual m_MessageEnd; +#endif // ==SE_CSGO || ==SE_BLADE || ==SE_MCV }; extern UserMessages g_UserMsgs; diff --git a/core/concmd_cleaner.cpp b/core/concmd_cleaner.cpp index 3488495bcd..cc13c2bd19 100644 --- a/core/concmd_cleaner.cpp +++ b/core/concmd_cleaner.cpp @@ -26,7 +26,7 @@ // or . #include "sm_globals.h" -#include +#include #include #include "concmd_cleaner.h" #include "sm_stringutil.h" @@ -34,19 +34,6 @@ #include "compat_wrappers.h" #include -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *); -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -SH_DECL_HOOK2_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *, bool); -#else -SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *); -#endif -#else -SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *); -#endif - -using namespace SourceHook; - struct ConCommandInfo { ConCommandBase *pBase; @@ -54,7 +41,7 @@ struct ConCommandInfo char name[64]; }; -List tracked_bases; +std::list tracked_bases; IConCommandLinkListener *IConCommandLinkListener::head = NULL; ConCommandBase *FindConCommandBase(const char *name); @@ -62,30 +49,12 @@ ConCommandBase *FindConCommandBase(const char *name); class ConCommandCleaner : public SMGlobalClass { public: - void OnSourceModAllInitialized() - { -#if SOURCE_ENGINE >= SE_ORANGEBOX - SH_ADD_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false); - SH_ADD_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); -#else - SH_ADD_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); -#endif - } - - void OnSourceModShutdown() - { -#if SOURCE_ENGINE >= SE_ORANGEBOX - SH_REMOVE_HOOK(ICvar, UnregisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false); - SH_REMOVE_HOOK(ICvar, RegisterConCommand, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); -#else - SH_REMOVE_HOOK(ICvar, RegisterConCommandBase, icvar, SH_MEMBER(this, &ConCommandCleaner::LinkConCommandBase), false); -#endif - } - #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - void LinkConCommandBase(ConCommandBase *pBase, bool unknown) + KHook::Virtual m_HookLinkConCommandBase; + KHook::Return LinkConCommandBase(ICvar*, ConCommandBase *pBase, bool unknown) #else - void LinkConCommandBase(ConCommandBase *pBase) + KHook::Virtual m_HookLinkConCommandBase; + KHook::Return LinkConCommandBase(ICvar*, ConCommandBase *pBase) #endif { IConCommandLinkListener *listener = IConCommandLinkListener::head; @@ -94,12 +63,15 @@ class ConCommandCleaner : public SMGlobalClass listener->OnLinkConCommand(pBase); listener = listener->next; } + + return { KHook::Action::Ignore }; } - void UnlinkConCommandBase(ConCommandBase *pBase) + KHook::Virtual m_HookUnlinkConCommandBase; + KHook::Return UnlinkConCommandBase(ICvar*, ConCommandBase *pBase) { ConCommandInfo *pInfo; - List::iterator iter = tracked_bases.begin(); + auto iter = tracked_bases.begin(); IConCommandLinkListener *listener = IConCommandLinkListener::head; while (listener) @@ -112,16 +84,17 @@ class ConCommandCleaner : public SMGlobalClass { if ((*iter)->pBase == pBase) { - pInfo = (*iter); - iter = tracked_bases.erase(iter); - pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName()); - delete pInfo; + pInfo = (*iter); + iter = tracked_bases.erase(iter); + pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName()); + delete pInfo; } else { - iter++; + iter++; } } + return { KHook::Action::Ignore }; } void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls) @@ -137,10 +110,9 @@ class ConCommandCleaner : public SMGlobalClass void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls) { - List::iterator iter; ConCommandInfo *pInfo; - iter = tracked_bases.begin(); + auto iter = tracked_bases.begin(); while (iter != tracked_bases.end()) { pInfo = (*iter); @@ -155,6 +127,35 @@ class ConCommandCleaner : public SMGlobalClass } } } + + virtual void OnSourceModAllInitialized() override + { +#if SOURCE_ENGINE >= SE_ORANGEBOX + m_HookUnlinkConCommandBase.Add(icvar); + m_HookLinkConCommandBase.Add(icvar); +#else + m_HookLinkConCommandBase.Add(icvar); +#endif + } + + virtual void OnSourceModShutdown() override + { +#if SOURCE_ENGINE >= SE_ORANGEBOX + m_HookUnlinkConCommandBase.Remove(icvar); + m_HookLinkConCommandBase.Remove(icvar); +#else + m_HookLinkConCommandBase.Remove(icvar); +#endif + } + + ConCommandCleaner() : +#if SOURCE_ENGINE >= SE_ORANGEBOX + m_HookLinkConCommandBase(&ICvar::RegisterConCommand, this, &ConCommandCleaner::LinkConCommandBase, nullptr), + m_HookUnlinkConCommandBase(&ICvar::UnregisterConCommand, this, &ConCommandCleaner::UnlinkConCommandBase, nullptr) +#else + m_HookLinkConCommandBase(&ICvar::RegisterConCommandBase, this, &ConCommandCleaner::LinkConCommandBase, nullptr) +#endif + {} } s_ConCmdTracker; void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me) @@ -169,5 +170,5 @@ void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me) void Global_OnUnlinkConCommandBase(ConCommandBase *pBase) { - s_ConCmdTracker.UnlinkConCommandBase(pBase); + s_ConCmdTracker.UnlinkConCommandBase(icvar, pBase); } diff --git a/core/logic/AMBuilder b/core/logic/AMBuilder index a858f18524..6852ed0f98 100644 --- a/core/logic/AMBuilder +++ b/core/logic/AMBuilder @@ -10,7 +10,7 @@ for cxx in builder.targets: os.path.join(builder.sourcePath, 'sourcepawn', 'include'), os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'), os.path.join(builder.sourcePath, 'public', 'amtl'), - os.path.join(SM.mms_root, 'core', 'sourcehook') + os.path.join(SM.mms_root, 'third_party', 'khook', 'include') ] binary.compiler.defines += [ 'SM_DEFAULT_THREADER', diff --git a/core/logic/AdminCache.cpp b/core/logic/AdminCache.cpp index 6cf9ac38bb..d9f4d81251 100644 --- a/core/logic/AdminCache.cpp +++ b/core/logic/AdminCache.cpp @@ -233,8 +233,7 @@ AdminCache::~AdminCache() DumpAdminCache(AdminCache_Overrides, false); DumpAdminCache(AdminCache_Groups, false); - List::iterator iter; - for (iter=m_AuthMethods.begin(); + for (auto iter=m_AuthMethods.begin(); iter!=m_AuthMethods.end(); iter++) { @@ -759,8 +758,7 @@ bool AdminCache::GetGroupCommandOverride(GroupId id, const char *name, OverrideT AuthMethod *AdminCache::GetMethodByIndex(unsigned int index) { - List::iterator iter; - for (iter=m_AuthMethods.begin(); + for (auto iter=m_AuthMethods.begin(); iter!=m_AuthMethods.end(); iter++) { @@ -974,8 +972,7 @@ void AdminCache::InvalidateAdminCache(bool unlink_admins) } } /* Wipe the identity cache first */ - List::iterator iter; - for (iter=m_AuthMethods.begin(); + for (auto iter=m_AuthMethods.begin(); iter!=m_AuthMethods.end(); iter++) { @@ -998,7 +995,6 @@ void AdminCache::InvalidateAdminCache(bool unlink_admins) void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) { - List::iterator iter; IAdminListener *pListener; if (part == AdminCache_Overrides) @@ -1007,7 +1003,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) DumpCommandOverrideCache(Override_CommandGroup); if (rebuild && !m_destroying) { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnRebuildOverrideCache(); @@ -1021,7 +1017,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) InvalidateGroupCache(); if (rebuild && !m_destroying) { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnRebuildGroupCache(); @@ -1033,7 +1029,7 @@ void AdminCache::DumpAdminCache(AdminCachePart part, bool rebuild) InvalidateAdminCache(true); if (rebuild && !m_destroying) { - for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + for (auto iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) { pListener = (*iter); pListener->OnRebuildAdminCache((part == AdminCache_Groups)); @@ -1058,9 +1054,8 @@ const char *AdminCache::GetAdminName(AdminId id) bool AdminCache::GetMethodIndex(const char *name, unsigned int *_index) { - List::iterator iter; unsigned int index = 0; - for (iter=m_AuthMethods.begin(); + for (auto iter=m_AuthMethods.begin(); iter!=m_AuthMethods.end(); iter++,index++) { @@ -1962,8 +1957,7 @@ AdminUser *AdminCache::GetUser(AdminId aid) const char *AdminCache::GetMethodName(unsigned int index) { - List::iterator iter; - for (iter=m_AuthMethods.begin(); + for (auto iter=m_AuthMethods.begin(); iter!=m_AuthMethods.end(); iter++) { diff --git a/core/logic/AdminCache.h b/core/logic/AdminCache.h index daecd9510f..09e03f241a 100644 --- a/core/logic/AdminCache.h +++ b/core/logic/AdminCache.h @@ -33,16 +33,12 @@ #define _INCLUDE_SOURCEMOD_ADMINCACHE_H_ #include "common_logic.h" -#include +#include "sm_hashmap.h" #include "sm_memtable.h" -#include -#include -#include +#include "sm_namehashset.h" +#include #include -#include -#include - -using namespace SourceHook; +#include #define GRP_MAGIC_SET 0xDEADFADE #define GRP_MAGIC_UNSET 0xFACEFACE @@ -70,7 +66,7 @@ struct AdminGroup struct AuthMethod { - String name; + std::string name; StringHashMap identities; AuthMethod(const char *name) @@ -214,8 +210,8 @@ class AdminCache : int m_LastGroup; int m_FreeGroupList; StringHashMap m_Groups; - List m_hooks; - List m_AuthMethods; + std::list m_hooks; + std::list m_AuthMethods; NameHashSet m_AuthTables; IForward *m_pCacheFwd; int m_FirstUser; diff --git a/core/logic/BaseWorker.cpp b/core/logic/BaseWorker.cpp index 342d4cc3e9..db1be47824 100644 --- a/core/logic/BaseWorker.cpp +++ b/core/logic/BaseWorker.cpp @@ -109,10 +109,9 @@ SWThreadHandle *BaseWorker::PopThreadFromQueue() if (!m_ThreadQueue.size()) return NULL; - SourceHook::List::iterator begin; SWThreadHandle *swt; - begin = m_ThreadQueue.begin(); + auto begin = m_ThreadQueue.begin(); swt = (*begin); m_ThreadQueue.erase(begin); diff --git a/core/logic/BaseWorker.h b/core/logic/BaseWorker.h index 5e87ed63d2..f729934850 100644 --- a/core/logic/BaseWorker.h +++ b/core/logic/BaseWorker.h @@ -32,7 +32,7 @@ #ifndef _INCLUDE_SOURCEMOD_BASEWORKER_H #define _INCLUDE_SOURCEMOD_BASEWORKER_H -#include "sh_list.h" +#include #include "ThreadSupport.h" #define SM_DEFAULT_THREADS_PER_FRAME 1 @@ -96,7 +96,7 @@ class BaseWorker : public IThreadWorker virtual void AddThreadToQueue(SWThreadHandle *pHandle); virtual SWThreadHandle *PopThreadFromQueue(); protected: - SourceHook::List m_ThreadQueue; + std::list m_ThreadQueue; unsigned int m_perFrame; volatile WorkerState m_state; IThreadWorkerCallbacks *m_pHooks; diff --git a/core/logic/Database.cpp b/core/logic/Database.cpp index e9a520495a..1628ab2b19 100644 --- a/core/logic/Database.cpp +++ b/core/logic/Database.cpp @@ -204,7 +204,7 @@ void DBManager::RemoveDriver(IDBDriver *pDriver) { if (m_drivers[i] == pDriver) { - m_drivers.erase(m_drivers.iterAt(i)); + m_drivers.erase(m_drivers.begin() + i); break; } } diff --git a/core/logic/Database.h b/core/logic/Database.h index cdd06fe0e2..e279d4e68e 100644 --- a/core/logic/Database.h +++ b/core/logic/Database.h @@ -33,9 +33,9 @@ #define _INCLUDE_DATABASE_MANAGER_H_ #include "common_logic.h" -#include +#include #include -#include +#include #include #include #include @@ -46,8 +46,6 @@ #include #include "DatabaseConfBuilder.h" -using namespace SourceHook; - class DBManager : public IDBManager, @@ -98,12 +96,12 @@ class DBManager : void ClearConfigs(); void KillWorkerThread(); private: - CVector m_drivers; + std::vector m_drivers; /* Threading stuff */ PrioQueue m_OpQueue; Queue m_ThinkQueue; - CVector m_drSafety; /* which drivers are safe? */ + std::vector m_drSafety; /* which drivers are safe? */ std::unique_ptr m_Worker; std::condition_variable m_QueueEvent; std::mutex m_ThinkLock; diff --git a/core/logic/ExtensionSys.cpp b/core/logic/ExtensionSys.cpp index 4406a7943a..a3a5bd149f 100644 --- a/core/logic/ExtensionSys.cpp +++ b/core/logic/ExtensionSys.cpp @@ -346,7 +346,15 @@ void CExtension::MarkAllLoaded() void CExtension::AddPlugin(CPlugin *pPlugin) { /* Unfortunately we have to do this :( */ - if (m_Dependents.find(pPlugin) == m_Dependents.end()) + auto iter = m_Dependents.begin(); + while (iter != m_Dependents.end()) { + if ((*iter) == pPlugin) { + break; + } else { + iter++; + } + } + if (iter == m_Dependents.end()) { m_Dependents.push_back(pPlugin); } @@ -389,7 +397,12 @@ bool CLocalExtension::IsLoaded() void CExtension::AddDependency(const IfaceInfo *pInfo) { - if (m_Deps.find(*pInfo) == m_Deps.end()) + auto iter = m_Deps.begin(); + while (iter != m_Deps.end() && !((*iter) == (*pInfo))) + { + iter++; + } + if (iter == m_Deps.end()) { m_Deps.push_back(*pInfo); } @@ -401,8 +414,7 @@ void CExtension::AddChildDependent(CExtension *pOther, SMInterface *iface) info.iface = iface; info.owner = pOther; - List::iterator iter; - for (iter = m_ChildDeps.begin(); + for (auto iter = m_ChildDeps.begin(); iter != m_ChildDeps.end(); iter++) { @@ -482,7 +494,7 @@ void CExtensionManager::OnSourceModShutdown() void CExtensionManager::Shutdown() { - List::iterator iter; + auto iter = m_Libs.begin(); while ((iter = m_Libs.begin()) != m_Libs.end()) { @@ -575,14 +587,13 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn IExtension *CExtensionManager::FindExtensionByFile(const char *file) { - List::iterator iter; CExtension *pExt; /* Chomp off the path */ char lookup[PLATFORM_MAX_PATH]; libsys->GetFileFromPath(lookup, sizeof(lookup), file); - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { pExt = (*iter); if (pExt->IsSameFile(lookup)) @@ -596,12 +607,11 @@ IExtension *CExtensionManager::FindExtensionByFile(const char *file) IExtension *CExtensionManager::FindExtensionByName(const char *ext) { - List::iterator iter; CExtension *pExt; IExtensionInterface *pAPI; const char *name; - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { pExt = (*iter); if (!pExt->IsLoaded()) @@ -710,9 +720,7 @@ void CExtensionManager::BindChildPlugin(IExtension *pParent, SMPlugin *pPlugin) void CExtensionManager::OnPluginDestroyed(IPlugin *plugin) { - List::iterator iter; - - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { (*iter)->DropRefsTo(static_cast(plugin)); } @@ -725,7 +733,7 @@ CExtension *CExtensionManager::FindByOrder(unsigned int num) return NULL; } - List::iterator iter = m_Libs.begin(); + auto iter = m_Libs.begin(); while (iter != m_Libs.end()) { @@ -745,8 +753,12 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) return false; CExtension *pExt = (CExtension *)_pExt; - - if (m_Libs.find(pExt) == m_Libs.end()) + auto iter = m_Libs.begin(); + while (iter != m_Libs.end() && (*iter) != pExt) + { + iter++; + } + if (iter == m_Libs.end()) return false; /* Tell it to unload */ @@ -760,13 +772,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) g_ShareSys.RemoveInterfaces(_pExt); m_Libs.remove(pExt); - List UnloadQueue; + std::list UnloadQueue; /* Handle dependencies */ if (pExt->IsLoaded()) { /* Unload any dependent plugins */ - List::iterator p_iter = pExt->m_Dependents.begin(); + auto p_iter = pExt->m_Dependents.begin(); while (p_iter != pExt->m_Dependents.end()) { /* We have to manually unlink ourselves here, since we're no longer being managed */ @@ -774,8 +786,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) p_iter = pExt->m_Dependents.erase(p_iter); } - List::iterator s_iter; - for (s_iter = pExt->m_Libraries.begin(); + for (auto s_iter = pExt->m_Libraries.begin(); s_iter != pExt->m_Libraries.end(); s_iter++) { @@ -783,10 +794,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) } /* Notify and/or unload all dependencies */ - List::iterator c_iter; CExtension *pDep; IExtensionInterface *pAPI; - for (c_iter = m_Libs.begin(); c_iter != m_Libs.end(); c_iter++) + for (auto c_iter = m_Libs.begin(); c_iter != m_Libs.end(); c_iter++) { pDep = (*c_iter); if ((pAPI=pDep->GetAPI()) == NULL) @@ -795,7 +805,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) continue; /* Now, get its dependency list */ bool dropped = false; - List::iterator i_iter = pDep->m_Deps.begin(); + auto i_iter = pDep->m_Deps.begin(); while (i_iter != pDep->m_Deps.end()) { if ((*i_iter).owner == _pExt) @@ -850,8 +860,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) pExt->Unload(); delete pExt; - List::iterator iter; - for (iter=UnloadQueue.begin(); iter!=UnloadQueue.end(); iter++) + for (auto iter=UnloadQueue.begin(); iter!=UnloadQueue.end(); iter++) { /* NOTE: This is safe because the unload function backs out of anything not present */ UnloadExtension((*iter)); @@ -862,10 +871,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) void CExtensionManager::MarkAllLoaded() { - List::iterator iter; CExtension *pExt; - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { pExt = (*iter); if (!pExt->IsLoaded()) @@ -900,7 +908,6 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand const char *cmd = command->Arg(2); if (strcmp(cmd, "list") == 0) { - List::iterator iter; CExtension *pExt; unsigned int num = 1; @@ -922,7 +929,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand break; } } - for (iter = m_Libs.begin(); iter != m_Libs.end(); iter++,num++) + for (auto iter = m_Libs.begin(); iter != m_Libs.end(); iter++,num++) { pExt = (*iter); if (pExt->IsLoaded()) @@ -1011,7 +1018,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand return; } - List::iterator iter = m_Libs.begin(); + auto iter = m_Libs.begin(); CExtension *pExt = NULL; while (iter != m_Libs.end()) { @@ -1114,23 +1121,21 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand } else { - List plugins; + std::list plugins; if (pExt->m_ChildDeps.size()) { rootmenu->ConsolePrint("[SM] Unloading %s will unload the following extensions: ", pExt->GetFilename()); - List::iterator iter; CExtension *pOther; /* Get list of all extensions */ - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { - List::iterator i_iter; pOther = (*iter); if (!pOther->IsLoaded() || pOther == pExt) { continue; } /* Get their dependencies */ - for (i_iter=pOther->m_Deps.begin(); + for (auto i_iter=pOther->m_Deps.begin(); i_iter!=pOther->m_Deps.end(); i_iter++) { @@ -1144,12 +1149,16 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand { rootmenu->ConsolePrint(" -> %s", pOther->GetFilename()); /* Add to plugin unload list */ - List::iterator p_iter; - for (p_iter=pOther->m_Dependents.begin(); + for (auto p_iter=pOther->m_Dependents.begin(); p_iter!=pOther->m_Dependents.end(); p_iter++) { - if (plugins.find((*p_iter)) == plugins.end()) + auto iterS = plugins.begin(); + while (iterS != plugins.end() && (*iterS) != (*p_iter)) + { + iterS++; + } + if (iterS == plugins.end()) { plugins.push_back((*p_iter)); } @@ -1161,17 +1170,21 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const ICommand if (pExt->m_Dependents.size()) { rootmenu->ConsolePrint("[SM] Unloading %s will unload the following plugins: ", pExt->GetFilename()); - List::iterator iter; CPlugin *pPlugin; - for (iter = pExt->m_Dependents.begin(); iter != pExt->m_Dependents.end(); iter++) + for (auto iter = pExt->m_Dependents.begin(); iter != pExt->m_Dependents.end(); iter++) { pPlugin = (*iter); - if (plugins.find(pPlugin) == plugins.end()) + auto iterS = plugins.begin(); + while (iterS != plugins.end() && (*iterS) != (pPlugin)) + { + iterS++; + } + if (iterS == plugins.end()) { plugins.push_back(pPlugin); } } - for (iter = plugins.begin(); iter != plugins.end(); iter++) + for (auto iter = plugins.begin(); iter != plugins.end(); iter++) { pPlugin = (*iter); rootmenu->ConsolePrint(" -> %s", pPlugin->GetFilename()); @@ -1267,12 +1280,12 @@ bool CExtensionManager::LibraryExists(const char *library) { CExtension *pExt; - for (List::iterator iter = m_Libs.begin(); + for (auto iter = m_Libs.begin(); iter != m_Libs.end(); iter++) { pExt = (*iter); - for (List::iterator s_iter = pExt->m_Libraries.begin(); + for (auto s_iter = pExt->m_Libraries.begin(); s_iter != pExt->m_Libraries.end(); s_iter++) { @@ -1315,9 +1328,8 @@ IExtension *CExtensionManager::LoadExternal(IExtensionInterface *pInterface, void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) { IExtensionInterface *pAPI; - List::iterator iter; - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { if ((pAPI = (*iter)->GetAPI()) == NULL) { @@ -1333,9 +1345,8 @@ void CExtensionManager::CallOnCoreMapStart(edict_t *pEdictList, int edictCount, void CExtensionManager::CallOnCoreMapEnd() { IExtensionInterface *pAPI; - List::iterator iter; - for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) + for (auto iter=m_Libs.begin(); iter!=m_Libs.end(); iter++) { if ((pAPI = (*iter)->GetAPI()) == NULL) { @@ -1348,17 +1359,17 @@ void CExtensionManager::CallOnCoreMapEnd() } } -const CVector *CExtensionManager::ListExtensions() +const std::vector *CExtensionManager::ListExtensions() { - CVector *list = new CVector(); - for (List::iterator iter = m_Libs.begin(); iter != m_Libs.end(); iter++) + std::vector *list = new std::vector(); + for (auto iter = m_Libs.begin(); iter != m_Libs.end(); iter++) list->push_back(*iter); return list; } -void CExtensionManager::FreeExtensionList(const CVector *list) +void CExtensionManager::FreeExtensionList(const std::vector *list) { - delete const_cast *>(list); + delete const_cast *>(list); } bool CLocalExtension::IsSameFile(const char *file) diff --git a/core/logic/ExtensionSys.h b/core/logic/ExtensionSys.h index 6687057cc0..64d978a290 100644 --- a/core/logic/ExtensionSys.h +++ b/core/logic/ExtensionSys.h @@ -34,8 +34,8 @@ #include #include -#include -#include +#include +#include #include "common_logic.h" #include #include @@ -46,7 +46,6 @@ class CPlayer; using namespace SourceMod; -using namespace SourceHook; class CExtension; @@ -95,14 +94,14 @@ class CExtension : protected: IdentityToken_t *m_pIdentToken; IExtensionInterface *m_pAPI; - String m_File; - String m_RealFile; - String m_Path; - String m_Error; - List m_Deps; /** Dependencies */ - List m_ChildDeps; /** Children who might depend on us */ - List m_Interfaces; - List m_Libraries; + std::string m_File; + std::string m_RealFile; + std::string m_Path; + std::string m_Error; + std::list m_Deps; /** Dependencies */ + std::list m_ChildDeps; /** Children who might depend on us */ + std::list m_Interfaces; + std::list m_Libraries; unsigned int unload_code; bool m_bFullyLoaded; bool m_bRequired; @@ -178,8 +177,8 @@ class CExtensionManager : void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax); void CallOnCoreMapEnd(); void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface); - const CVector *ListExtensions(); - void FreeExtensionList(const CVector *list); + const std::vector *ListExtensions(); + void FreeExtensionList(const std::vector *list); public: CExtension *GetExtensionFromIdent(IdentityToken_t *ptr); void Shutdown(); @@ -191,7 +190,7 @@ class CExtensionManager : private: CExtension *FindByOrder(unsigned int num); private: - List m_Libs; + std::list m_Libs; }; extern CExtensionManager g_Extensions; diff --git a/core/logic/GameConfigs.cpp b/core/logic/GameConfigs.cpp index b141335c14..9320714d8d 100644 --- a/core/logic/GameConfigs.cpp +++ b/core/logic/GameConfigs.cpp @@ -31,8 +31,8 @@ #include #include #include -#include -#include +#include +#include #include "GameConfigs.h" #include "stringutil.h" #include @@ -53,8 +53,6 @@ #include #endif -using namespace SourceHook; - GameConfigManager g_GameConfigs; IGameConfig *g_pGameConf = NULL; static char g_Game[256]; @@ -791,7 +789,11 @@ class MasterReader : public ITextListener_SMC (!had_game && matched_engine) || (matched_engine && matched_game)) { - if (fileList->find(cur_file) == fileList->end()) + auto iterS = fileList->begin(); + while (iterS != fileList->end() && (*iterS) != cur_file) { + iterS++; + } + if (iterS == fileList->end()) { fileList->push_back(cur_file); } @@ -806,7 +808,7 @@ class MasterReader : public ITextListener_SMC return SMCResult_Continue; } public: - List *fileList; + std::list *fileList; unsigned int state; unsigned int ignoreLevel; char cur_file[PLATFORM_MAX_PATH]; @@ -857,7 +859,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) /* Otherwise, it's time to parse the master. */ SMCError err; SMCStates state = {0, 0}; - List fileList; + std::list fileList; master_reader.fileList = &fileList; const char *pEngine[2] = { m_pBaseEngine, m_pEngine }; @@ -885,8 +887,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength) } /* Go through each file we found and parse it. */ - List::iterator iter; - for (iter = fileList.begin(); iter != fileList.end(); iter++) + for (auto iter = fileList.begin(); iter != fileList.end(); iter++) { ke::SafeSprintf(path, sizeof(path), "%s/%s", m_File, (*iter).c_str()); if (!EnterFile(path, error, maxlength)) diff --git a/core/logic/MemoryUtils.h b/core/logic/MemoryUtils.h index f7eeaafd2e..97d2727bbf 100644 --- a/core/logic/MemoryUtils.h +++ b/core/logic/MemoryUtils.h @@ -35,10 +35,8 @@ #include #include #if defined PLATFORM_LINUX || defined PLATFORM_APPLE -#include +#include #include "sm_symtable.h" - -using namespace SourceHook; #endif using namespace SourceMod; @@ -79,7 +77,7 @@ class MemoryUtils : const DynLibInfo *GetLibraryInfo(const void *libPtr); #if defined PLATFORM_LINUX || defined PLATFORM_APPLE private: - CVector m_SymTables; + std::vector m_SymTables; #ifdef PLATFORM_APPLE struct dyld_all_image_infos *m_ImageList; SInt32 m_OSXMajor; diff --git a/core/logic/NativeOwner.cpp b/core/logic/NativeOwner.cpp index bdb415f80e..cfc164abf5 100644 --- a/core/logic/NativeOwner.cpp +++ b/core/logic/NativeOwner.cpp @@ -48,8 +48,17 @@ unsigned int CNativeOwner::GetMarkSerial() void CNativeOwner::AddDependent(CPlugin *pPlugin) { - if (m_Dependents.find(pPlugin) == m_Dependents.end()) + auto iter = m_Dependents.begin(); + while (iter != m_Dependents.end()) { + if ((*iter) == pPlugin) { + break; + } else { + iter++; + } + } + if (iter == m_Dependents.end()) { m_Dependents.push_back(pPlugin); + } } void CNativeOwner::AddWeakRef(const WeakNative & ref) @@ -79,10 +88,8 @@ void CNativeOwner::UnbindWeakRef(const WeakNative &ref) void CNativeOwner::DropEverything() { - List::iterator iter; - /* Unbind and remove all weak references to us */ - iter = m_WeakRefs.begin(); + auto iter = m_WeakRefs.begin(); while (iter != m_WeakRefs.end()) { UnbindWeakRef((*iter)); @@ -104,9 +111,7 @@ void CNativeOwner::DropEverything() void CNativeOwner::DropWeakRefsTo(CPlugin *pPlugin) { - List::iterator iter; - - iter = m_WeakRefs.begin(); + auto iter = m_WeakRefs.begin(); while (iter != m_WeakRefs.end()) { WeakNative & ref = (*iter); diff --git a/core/logic/NativeOwner.h b/core/logic/NativeOwner.h index bc25d4b01a..139a49e2fc 100644 --- a/core/logic/NativeOwner.h +++ b/core/logic/NativeOwner.h @@ -32,7 +32,7 @@ #define _INCLUDE_SOURCEMOD_NATIVE_OWNER_H_ #include -#include +#include #include #include "common_logic.h" #include "Native.h" @@ -55,8 +55,6 @@ struct WeakNative uint32_t idx; }; -using namespace SourceHook; - class CNativeOwner { public: @@ -76,9 +74,9 @@ class CNativeOwner void DropWeakRefsTo(CPlugin *pPlugin); void UnbindWeakRef(const WeakNative & ref); protected: - List m_Dependents; + std::list m_Dependents; unsigned int m_nMarkSerial; - List m_WeakRefs; + std::list m_WeakRefs; std::vector m_natives; std::vector > m_fakes; }; diff --git a/core/logic/PhraseCollection.h b/core/logic/PhraseCollection.h index bf14e190fa..22be38b200 100644 --- a/core/logic/PhraseCollection.h +++ b/core/logic/PhraseCollection.h @@ -32,11 +32,9 @@ #ifndef _INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_ #define _INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_ -#include -#include +#include #include -using namespace SourceHook; using namespace SourceMod; class CPhraseCollection : public IPhraseCollection @@ -60,7 +58,7 @@ class CPhraseCollection : public IPhraseCollection size_t *pOutLength, const char **pFailPhrase); private: - CVector m_Files; + std::vector m_Files; }; #endif //_INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_ diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 74d4161dc3..1067360110 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -675,7 +675,11 @@ void CPlugin::DependencyDropped(CPlugin *pOwner) return; for (auto lib_iter=pOwner->m_Libraries.begin(); lib_iter!=pOwner->m_Libraries.end(); lib_iter++) { - if (m_RequiredLibs.find(*lib_iter) != m_RequiredLibs.end()) { + auto iterS = m_RequiredLibs.begin(); + while (iterS != m_RequiredLibs.end() && (*iterS) != *lib_iter) { + iterS++; + } + if (iterS != m_RequiredLibs.end()) { m_LibraryMissing = true; break; } @@ -746,10 +750,9 @@ void CPlugin::AddConfig(bool autoCreate, const char *cfg, const char *folder) void CPlugin::DropEverything() { CPlugin *pOther; - List::iterator wk_iter; /* Tell everyone that depends on us that we're about to drop */ - for (List::iterator iter = m_Dependents.begin(); + for (auto iter = m_Dependents.begin(); iter != m_Dependents.end(); iter++) { @@ -1191,7 +1194,11 @@ void CPlugin::ForEachLibrary(ke::Function callback) void CPlugin::AddRequiredLib(const char *name) { - if (m_RequiredLibs.find(name) == m_RequiredLibs.end()) + auto iterS = m_RequiredLibs.begin(); + while (iterS != m_RequiredLibs.end() && (*iterS) != name) { + iterS++; + } + if (iterS == m_RequiredLibs.end()) m_RequiredLibs.push_back(name); } @@ -2281,9 +2288,9 @@ void CPluginManager::SyncMaxClients(int max_clients) (*iter)->SyncMaxClients(max_clients); } -const CVector *CPluginManager::ListPlugins() +const std::vector *CPluginManager::ListPlugins() { - CVector *list = new CVector(); + std::vector *list = new std::vector(); for (PluginIter iter(m_plugins); !iter.done(); iter.next()) list->push_back((*iter)); @@ -2291,9 +2298,9 @@ const CVector *CPluginManager::ListPlugins() return list; } -void CPluginManager::FreePluginList(const CVector *list) +void CPluginManager::FreePluginList(const std::vector *list) { - delete const_cast *>(list); + delete const_cast *>(list); } void CPluginManager::ForEachPlugin(ke::Function callback) diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index 1afbf52170..50a5e2acdb 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -41,10 +41,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include "common_logic.h" #include #include @@ -61,8 +61,6 @@ class CPlayer; -using namespace SourceHook; - enum LoadRes { LoadRes_Successful, @@ -196,7 +194,15 @@ class CPlugin : m_Libraries.push_back(name); } inline bool HasLibrary(const char *name) { - return m_Libraries.find(name) != m_Libraries.end(); + auto iter = m_Libraries.begin(); + while (iter != m_Libraries.end()) { + if (strcmp((*iter).c_str(), name) == 0) { + break; + } else { + iter++; + } + } + return iter != m_Libraries.end(); } void LibraryActions(LibraryAction action); void SyncMaxClients(int max_clients); @@ -275,13 +281,13 @@ class CPlugin : IPluginContext *m_pContext; sp_pubvar_t *m_MaxClientsVar; StringHashMap m_Props; - CVector m_configs; - List m_Libraries; + std::vector m_configs; + std::list m_Libraries; bool m_bGotAllLoaded; int m_FileVersion; // Information that survives past eviction. - List m_RequiredLibs; + std::list m_RequiredLibs; IdentityToken_t *m_ident; time_t m_LastFileModTime; Handle_t m_handle; @@ -355,8 +361,8 @@ class CPluginManager : SMPlugin *FindPluginByHandle(Handle_t hndl, HandleError *errp) { return static_cast(PluginFromHandle(hndl, errp)); } - const CVector *ListPlugins(); - void FreePluginList(const CVector *plugins); + const std::vector *ListPlugins(); + void FreePluginList(const std::vector *plugins); public: //SMGlobalClass void OnSourceModAllInitialized(); @@ -513,7 +519,7 @@ class CPluginManager : IdentityToken_t *m_MyIdent; /* Dynamic native stuff */ - List m_Natives; + std::list m_Natives; bool m_LoadingLocked; diff --git a/core/logic/RootConsoleMenu.cpp b/core/logic/RootConsoleMenu.cpp index fb6857bf2a..331d0bb39e 100644 --- a/core/logic/RootConsoleMenu.cpp +++ b/core/logic/RootConsoleMenu.cpp @@ -42,8 +42,7 @@ RootConsoleMenu::RootConsoleMenu() RootConsoleMenu::~RootConsoleMenu() { - List::iterator iter; - for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) + for (auto iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { delete (*iter); } @@ -100,7 +99,7 @@ bool RootConsoleMenu::AddRootConsoleCommand3(const char *cmd, return false; /* Sort this into the menu */ - List::iterator iter = m_Menu.begin(); + auto iter = m_Menu.begin(); ConsoleEntry *pEntry; bool inserted = false; while (iter != m_Menu.end()) @@ -137,9 +136,8 @@ bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleComm { m_Commands.remove(cmd); - List::iterator iter; ConsoleEntry *pEntry; - for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) + for (auto iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { pEntry = (*iter); if (pEntry->command.compare(cmd) == 0) @@ -200,9 +198,8 @@ void RootConsoleMenu::GotRootCmd(const ICommandArgs *cmd) ConsolePrint("SourceMod Menu:"); ConsolePrint("Usage: sm [arguments]"); - List::iterator iter; ConsoleEntry *pEntry; - for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) + for (auto iter=m_Menu.begin(); iter!=m_Menu.end(); iter++) { pEntry = (*iter); DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str()); diff --git a/core/logic/RootConsoleMenu.h b/core/logic/RootConsoleMenu.h index c240a488f0..c02e7093b5 100644 --- a/core/logic/RootConsoleMenu.h +++ b/core/logic/RootConsoleMenu.h @@ -28,18 +28,17 @@ #define _INCLUDE_SOURCEMOD_ROOT_CONSOLE_MENU_IMPL_H_ #include "common_logic.h" +#include "sm_namehashset.h" #include -#include -#include -#include +#include +#include using namespace SourceMod; -using namespace SourceHook; struct ConsoleEntry { - String command; - String description; + std::string command; + std::string description; IRootConsoleCommand *cmd; static inline bool matches(const char *name, const ConsoleEntry *entry) @@ -84,7 +83,7 @@ class RootConsoleMenu : void GotRootCmd(const ICommandArgs *cmd); private: NameHashSet m_Commands; - List m_Menu; + std::list m_Menu; }; extern RootConsoleMenu g_RootMenu; diff --git a/core/logic/ShareSys.cpp b/core/logic/ShareSys.cpp index fd998b39e2..259d591952 100644 --- a/core/logic/ShareSys.cpp +++ b/core/logic/ShareSys.cpp @@ -232,7 +232,7 @@ void ShareSystem::DestroyIdentType(IdentityType_t type) void ShareSystem::RemoveInterfaces(IExtension *pExtension) { - List::iterator iter = m_Interfaces.begin(); + auto iter = m_Interfaces.begin(); while (iter != m_Interfaces.end()) { diff --git a/core/logic/ShareSys.h b/core/logic/ShareSys.h index cc431cb779..78f132d348 100644 --- a/core/logic/ShareSys.h +++ b/core/logic/ShareSys.h @@ -37,14 +37,12 @@ #include #include #include -#include +#include #include #include #include "common_logic.h" #include "Native.h" -using namespace SourceHook; - namespace SourceMod { struct IdentityToken_t @@ -133,7 +131,7 @@ class ShareSystem : private: typedef NameHashSet, Native> NativeCache; - List m_Interfaces; + std::list m_Interfaces; HandleType_t m_TypeRoot; IdentityToken_t m_IdentRoot; HandleType_t m_IfaceType; diff --git a/core/logic/Translator.h b/core/logic/Translator.h index 5cd57dfbbf..8070b21b66 100644 --- a/core/logic/Translator.h +++ b/core/logic/Translator.h @@ -34,17 +34,16 @@ #include "common_logic.h" #include -#include -#include #include "sm_memtable.h" #include "ITextParsers.h" #include #include "PhraseCollection.h" +#include +#include /* :TODO: write a templatized version of tries? */ using namespace SourceMod; -using namespace SourceHook; class Translator; enum PhraseParseState @@ -83,15 +82,15 @@ class CPhraseFile : void ParseWarning(const char *message, ...); private: StringHashMap m_PhraseLookup; - String m_File; + std::string m_File; Translator *m_pTranslator; PhraseParseState m_ParseState; int m_CurPhrase; BaseMemTable *m_pMemory; BaseStringTable *m_pStringTab; unsigned int m_LangCount; - String m_ParseError; - String m_LastPhraseString; + std::string m_ParseError; + std::string m_LastPhraseString; bool m_FileLogged; }; @@ -152,13 +151,13 @@ class Translator : private: bool AddLanguage(const char *langcode, const char *description); private: - CVector m_Languages; - CVector m_Files; + std::vector m_Languages; + std::vector m_Files; BaseStringTable *m_pStringTab; StringHashMap m_LCodeLookup; StringHashMap m_LAliases; bool m_InLanguageSection; - String m_CustomError; + std::string m_CustomError; unsigned int m_ServerLang; char m_InitialLang[4]; }; diff --git a/core/logic/smn_core.cpp b/core/logic/smn_core.cpp index 6db6e766dc..8ddd7de850 100644 --- a/core/logic/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "common_logic.h" #include "Logger.h" @@ -43,9 +44,6 @@ #include #include -#include -#include - #if defined PLATFORM_WINDOWS #include #include "sm_invalidparamhandler.h" @@ -54,12 +52,12 @@ #include #include #endif +#include #include #include #include #include #include -#include using namespace SourceMod; using namespace SourcePawn; @@ -128,7 +126,7 @@ class CMMPluginIterator public IPluginsListener { public: - CMMPluginIterator(const CVector *list) + CMMPluginIterator(const std::vector *list) : m_hasStarted(false) { for(auto iter = list->begin(); iter != list->end(); ++iter) { @@ -932,21 +930,21 @@ static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params) case NumberType_Int8: if (updateMemAccess) { - SourceHook::SetMemAccess(addr, sizeof(uint8_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); + KHook::Memory::SetAccess(addr, sizeof(uint8_t), KHook::Memory::Flags::READ | KHook::Memory::Flags::EXECUTE | KHook::Memory::Flags::WRITE); } *reinterpret_cast(addr) = data; break; case NumberType_Int16: if (updateMemAccess) { - SourceHook::SetMemAccess(addr, sizeof(uint16_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); + KHook::Memory::SetAccess(addr, sizeof(uint16_t), KHook::Memory::Flags::READ | KHook::Memory::Flags::EXECUTE | KHook::Memory::Flags::WRITE); } *reinterpret_cast(addr) = data; break; case NumberType_Int32: if (updateMemAccess) { - SourceHook::SetMemAccess(addr, sizeof(uint32_t), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); + KHook::Memory::SetAccess(addr, sizeof(uint32_t), KHook::Memory::Flags::READ | KHook::Memory::Flags::EXECUTE | KHook::Memory::Flags::WRITE); } *reinterpret_cast(addr) = data; break; @@ -1028,7 +1026,7 @@ static cell_t StoreAddressToAddress(IPluginContext *pContext, const cell_t *para bool updateMemAccess = params[3]; if (updateMemAccess) { - SourceHook::SetMemAccess(addr, sizeof(void*), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); + KHook::Memory::SetAccess(addr, sizeof(void*), KHook::Memory::Flags::READ|KHook::Memory::Flags::WRITE|KHook::Memory::Flags::EXECUTE); } *reinterpret_cast(addr) = data; diff --git a/core/logic/smn_database.cpp b/core/logic/smn_database.cpp index 505cb6d695..8a97ea9a1d 100644 --- a/core/logic/smn_database.cpp +++ b/core/logic/smn_database.cpp @@ -290,7 +290,7 @@ class TQueryOp : public IDBThreadOperation private: IDatabase *m_pDatabase; IPluginFunction *m_pFunction; - String m_Query; + std::string m_Query; cell_t m_Data; IPlugin *me; IQuery *m_pQuery; diff --git a/core/logic/smn_fakenatives.cpp b/core/logic/smn_fakenatives.cpp index e68e527a6d..25a3f055e4 100644 --- a/core/logic/smn_fakenatives.cpp +++ b/core/logic/smn_fakenatives.cpp @@ -29,16 +29,12 @@ * Version: $Id$ */ -#include -#include #include #include "common_logic.h" #include "ShareSys.h" #include "PluginSys.h" #include "sprintf.h" -using namespace SourceHook; - static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1]; static FakeNative *s_curnative = NULL; static IPluginContext *s_curcaller = NULL; diff --git a/core/logic/smn_maplists.cpp b/core/logic/smn_maplists.cpp index 2a1e1f179d..071e870032 100644 --- a/core/logic/smn_maplists.cpp +++ b/core/logic/smn_maplists.cpp @@ -29,7 +29,7 @@ * Version: $Id$ */ -#include +#include #include #include "common_logic.h" #include "CellArray.h" @@ -42,8 +42,6 @@ #include #include -using namespace SourceHook; - struct maplist_info_t { bool bIsCompat; @@ -168,7 +166,7 @@ class MapLists : public SMGlobalClass, public ITextListener_SMC m_pMapCycleFile = bridge->FindConVar("mapcyclefile"); /* Dump everything we know about. */ - List compat; + std::list compat; DumpCache(&compat); /* All this is to add the default entry back in. */ @@ -206,7 +204,7 @@ class MapLists : public SMGlobalClass, public ITextListener_SMC } /* Now, re-add compat stuff back in if we can. */ - List::iterator iter = compat.begin(); + auto iter = compat.begin(); while (iter != compat.end()) { if (m_ListLookup.contains((*iter)->name)) @@ -666,11 +664,11 @@ class MapLists : public SMGlobalClass, public ITextListener_SMC return true; } - void DumpCache(List *compat_list) + void DumpCache(std::list *compat_list) { m_ListLookup.clear(); - List::iterator iter = m_MapLists.begin(); + auto iter = m_MapLists.begin(); while (iter != m_MapLists.end()) { if (compat_list != NULL && (*iter)->bIsCompat) @@ -690,7 +688,7 @@ class MapLists : public SMGlobalClass, public ITextListener_SMC time_t m_ConfigLastChanged; ConVar *m_pMapCycleFile; NameHashSet m_ListLookup; - List m_MapLists; + std::list m_MapLists; MapListState m_CurState; unsigned int m_IgnoreLevel; maplist_info_t *m_pCurMapList; diff --git a/core/logic/smn_menus.cpp b/core/logic/smn_menus.cpp index 152215ebeb..5ad5bf9de4 100644 --- a/core/logic/smn_menus.cpp +++ b/core/logic/smn_menus.cpp @@ -30,7 +30,6 @@ */ #include "common_logic.h" -#include #include #include #include "DebugReporter.h" @@ -40,6 +39,8 @@ #include #include #include +#include +#include #if defined CreateMenu #undef CreateMenu @@ -175,13 +176,13 @@ class MenuNativeHelpers : while (!m_FreePanelHandlers.empty()) { - delete m_FreePanelHandlers.front(); + delete m_FreePanelHandlers.top(); m_FreePanelHandlers.pop(); } while (!m_FreeMenuHandlers.empty()) { - delete m_FreeMenuHandlers.front(); + delete m_FreeMenuHandlers.top(); m_FreeMenuHandlers.pop(); } } @@ -213,12 +214,12 @@ class MenuNativeHelpers : */ virtual void OnPluginUnloaded(IPlugin *plugin) { - for (size_t i = 0; i < m_PanelHandlers.size(); i++) + for (auto e : m_PanelHandlers) { - if (m_PanelHandlers[i]->m_pPlugin == plugin) + if (e->m_pPlugin == plugin) { - m_PanelHandlers[i]->m_pPlugin = NULL; - m_PanelHandlers[i]->m_pFunc = NULL; + e->m_pPlugin = nullptr; + e->m_pFunc = nullptr; } } } @@ -241,7 +242,7 @@ class MenuNativeHelpers : handler = new CPanelHandler; m_PanelHandlers.push_back(handler); } else { - handler = m_FreePanelHandlers.front(); + handler = m_FreePanelHandlers.top(); m_FreePanelHandlers.pop(); } handler->m_pFunc = pFunction; @@ -263,7 +264,7 @@ class MenuNativeHelpers : { handler = new CMenuHandler(pFunction, flags); } else { - handler = m_FreeMenuHandlers.front(); + handler = m_FreeMenuHandlers.top(); m_FreeMenuHandlers.pop(); handler->m_pBasic = pFunction; handler->m_Flags = flags; @@ -280,9 +281,9 @@ class MenuNativeHelpers : private: HandleType_t m_PanelType; HandleType_t m_TempPanelType; - CStack m_FreePanelHandlers; - CStack m_FreeMenuHandlers; - CVector m_PanelHandlers; + std::stack m_FreePanelHandlers; + std::stack m_FreeMenuHandlers; + std::list m_PanelHandlers; } g_MenuHelpers; /** diff --git a/core/logic/smn_players.cpp b/core/logic/smn_players.cpp index 4fdb5304f3..abd705fd22 100644 --- a/core/logic/smn_players.cpp +++ b/core/logic/smn_players.cpp @@ -35,8 +35,8 @@ #include #include #include -#include -#include +#include +#include #include "GameConfigs.h" #include "CellArray.h" #include "AutoHandleRooter.h" @@ -46,7 +46,6 @@ #include #include -using namespace SourceHook; using namespace SourceMod; #ifndef PRIu64 @@ -75,9 +74,9 @@ class PlayerLogicHelpers : struct SimpleMultiTargetFilter { IPlugin *plugin; - SourceHook::String pattern; + std::string pattern; IPluginFunction *fun; - SourceHook::String phrase; + std::string phrase; bool phraseIsML; SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun, @@ -87,7 +86,7 @@ class PlayerLogicHelpers : } }; - List simpleMultis; + std::list simpleMultis; bool filterEnabled; public: @@ -107,7 +106,7 @@ class PlayerLogicHelpers : void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun) { - List::iterator iter = simpleMultis.begin(); + auto iter = simpleMultis.begin(); while (iter != simpleMultis.end()) { if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) { @@ -127,9 +126,7 @@ class PlayerLogicHelpers : public: //ICommandTargetProcessor bool ProcessCommandTarget(cmd_target_info_t *info) { - List::iterator iter; - - for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) { + for (auto iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) { SimpleMultiTargetFilter *smtf = (*iter); if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) { CellArray *array = new CellArray(1); @@ -206,7 +203,7 @@ class PlayerLogicHelpers : void OnPluginDestroyed(IPlugin *plugin) { - List::iterator iter = simpleMultis.begin(); + auto iter = simpleMultis.begin(); while (iter != simpleMultis.end()) { if ((*iter)->plugin != plugin) { diff --git a/core/logic/smn_timers.cpp b/core/logic/smn_timers.cpp index 631d4d41f8..855f87a6c3 100644 --- a/core/logic/smn_timers.cpp +++ b/core/logic/smn_timers.cpp @@ -34,12 +34,10 @@ #include #include #include -#include +#include #include "DebugReporter.h" #include -using namespace SourceHook; - #define TIMER_DATA_HNDL_CLOSE (1<<9) #define TIMER_HNDL_CLOSE (1<<9) @@ -74,17 +72,16 @@ class TimerNatives : TimerInfo *CreateTimerInfo(); void DeleteTimerInfo(TimerInfo *pInfo); private: - CStack m_FreeTimers; + std::stack m_FreeTimers; }; TimerNatives::~TimerNatives() { - CStack::iterator iter; - for (iter=m_FreeTimers.begin(); iter!=m_FreeTimers.end(); iter++) + while (!m_FreeTimers.empty()) { - delete (*iter); + delete m_FreeTimers.top(); + m_FreeTimers.pop(); } - m_FreeTimers.popall(); } void TimerNatives::OnSourceModAllInitialized() @@ -118,7 +115,7 @@ TimerInfo *TimerNatives::CreateTimerInfo() { pInfo = new TimerInfo; } else { - pInfo = m_FreeTimers.front(); + pInfo = m_FreeTimers.top(); m_FreeTimers.pop(); } diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index fe1f3377fd..0525dda8e2 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -473,7 +473,7 @@ bool CoreProviderImpl::GetGameName(char *buffer, size_t maxlength) const char *CoreProviderImpl::GetGameDescription() { - return SERVER_CALL(GetGameDescription)(); + return KHook::CallOriginal(&IServerGameDLL::GetGameDescription, gamedll); } const char *CoreProviderImpl::GetSourceEngineName() diff --git a/core/smn_console.cpp b/core/smn_console.cpp index 29b830a865..e97056ae42 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -79,7 +79,7 @@ HandleType_t htConCmdIter = 0; struct GlobCmdIter { bool started; - List::iterator iter; + std::list::iterator iter; }; class ConsoleHelpers : @@ -1056,7 +1056,7 @@ static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params return pContext->ThrowNativeError("Invalid GlobCmdIter Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + std::list& cmds = const_cast(g_ConCmds.GetCommandList()); if (!iter->started) { @@ -1356,7 +1356,7 @@ static cell_t FakeClientCommandKeyValues(IPluginContext *pContext, const cell_t if (g_Players.InClientCommandKeyValuesHook()) { - SH_CALL(serverClients, &IServerGameClients::ClientCommandKeyValues)(pPlayer->GetEdict(), pStk->pBase); + KHook::CallOriginal(&IServerGameClients::ClientCommandKeyValues, serverClients, pPlayer->GetEdict(), pStk->pBase); } else { @@ -1395,7 +1395,7 @@ static cell_t sm_CommandIteratorNext(IPluginContext *pContext, const cell_t *par return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + std::list& cmds = const_cast(g_ConCmds.GetCommandList()); if (!iter->started) { @@ -1427,7 +1427,7 @@ static cell_t sm_CommandIteratorAdminFlags(IPluginContext *pContext, const cell_ { return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + const std::list &cmds = g_ConCmds.GetCommandList(); if (!iter->started || iter->iter == cmds.end()) { return pContext->ThrowNativeError("Invalid CommandIterator position"); @@ -1448,7 +1448,7 @@ static cell_t sm_CommandIteratorConVarFlags(IPluginContext *pContext, const cell { return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + const std::list &cmds = g_ConCmds.GetCommandList(); if (!iter->started || iter->iter == cmds.end()) { return pContext->ThrowNativeError("Invalid CommandIterator position"); @@ -1469,7 +1469,7 @@ static cell_t sm_CommandIteratorGetDesc(IPluginContext *pContext, const cell_t * { return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + const std::list &cmds = g_ConCmds.GetCommandList(); if (!iter->started || iter->iter == cmds.end()) { return pContext->ThrowNativeError("Invalid CommandIterator position"); @@ -1492,7 +1492,7 @@ static cell_t sm_CommandIteratorGetName(IPluginContext *pContext, const cell_t * { return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + const std::list &cmds = g_ConCmds.GetCommandList(); if (!iter->started || iter->iter == cmds.end()) { return pContext->ThrowNativeError("Invalid CommandIterator position"); @@ -1515,7 +1515,7 @@ static cell_t sm_CommandIteratorPlugin(IPluginContext *pContext, const cell_t *p { return pContext->ThrowNativeError("Invalid CommandIterator Handle %x", params[1]); } - const List &cmds = g_ConCmds.GetCommandList(); + const std::list &cmds = g_ConCmds.GetCommandList(); if (!iter->started || iter->iter == cmds.end()) { return pContext->ThrowNativeError("Invalid CommandIterator position"); diff --git a/core/smn_halflife.cpp b/core/smn_halflife.cpp index f72b719608..21fdcc2100 100644 --- a/core/smn_halflife.cpp +++ b/core/smn_halflife.cpp @@ -181,7 +181,7 @@ static cell_t GetGameDescription(IPluginContext *pContext, const cell_t *params) { description = gamedll->GetGameDescription(); } else { - description = SERVER_CALL(GetGameDescription)(); + description = KHook::CallOriginal(&IServerGameDLL::GetGameDescription, gamedll); } size_t numBytes; diff --git a/core/smn_keyvalues.cpp b/core/smn_keyvalues.cpp index 985e78057c..9bda86e163 100644 --- a/core/smn_keyvalues.cpp +++ b/core/smn_keyvalues.cpp @@ -499,7 +499,7 @@ static cell_t smn_CreateKeyValues(IPluginContext *pCtx, const cell_t *params) is_empty = (firstkey[0] == '\0'); pStk = new KeyValueStack; pStk->pBase = new KeyValues(name, is_empty ? NULL : firstkey, (is_empty||(firstvalue[0]=='\0')) ? NULL : firstvalue); - pStk->pCurRoot.push(pStk->pBase); + pStk->pCurRoot.push_front(pStk->pBase); return handlesys->CreateHandle(g_KeyValueType, pStk, pCtx->GetIdentity(), g_pCoreIdent, NULL); } @@ -529,7 +529,7 @@ static cell_t smn_KvJumpToKey(IPluginContext *pCtx, const cell_t *params) { return 0; } - pStk->pCurRoot.push(pSubKey); + pStk->pCurRoot.push_front(pSubKey); return 1; } @@ -556,7 +556,7 @@ static cell_t smn_KvJumpToKeySymbol(IPluginContext *pCtx, const cell_t *params) { return 0; } - pStk->pCurRoot.push(pSubKey); + pStk->pCurRoot.push_front(pSubKey); return 1; } @@ -590,7 +590,7 @@ static cell_t smn_KvGotoFirstSubKey(IPluginContext *pCtx, const cell_t *params) { return 0; } - pStk->pCurRoot.push(pFirstSubKey); + pStk->pCurRoot.push_front(pFirstSubKey); return 1; } @@ -622,8 +622,8 @@ static cell_t smn_KvGotoNextKey(IPluginContext *pCtx, const cell_t *params) { return 0; } - pStk->pCurRoot.pop(); - pStk->pCurRoot.push(pSubKey); + pStk->pCurRoot.pop_front(); + pStk->pCurRoot.push_front(pSubKey); return 1; } @@ -648,7 +648,7 @@ static cell_t smn_KvGoBack(IPluginContext *pCtx, const cell_t *params) { return 0; } - pStk->pCurRoot.pop(); + pStk->pCurRoot.pop_front(); return 1; } @@ -674,7 +674,7 @@ static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params) { while (pStk->pCurRoot.size() > 1) { - pStk->pCurRoot.pop(); + pStk->pCurRoot.pop_front(); } } else @@ -682,7 +682,7 @@ static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params) auto root = pStk->pCurRoot.begin(); if (root != pStk->pCurRoot.end()) { - pStk->pCurRoot.push(*root); + pStk->pCurRoot.push_front(*root); } } @@ -897,7 +897,7 @@ static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params) } KeyValues *pValues = pStk->pCurRoot.front(); - pStk->pCurRoot.pop(); + pStk->pCurRoot.pop_front(); KeyValues *pRoot = pStk->pCurRoot.front(); /* We have to manually verify this since Valve sucks @@ -914,7 +914,7 @@ static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params) pValues->deleteThis(); if (pNext) { - pStk->pCurRoot.push(pNext); + pStk->pCurRoot.push_front(pNext); return 1; } else { return -1; @@ -924,7 +924,7 @@ static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params) } /* Push this back on :( */ - pStk->pCurRoot.push(pValues); + pStk->pCurRoot.push_front(pValues); return 0; } @@ -988,7 +988,7 @@ static cell_t smn_KvSavePosition(IPluginContext *pContext, const cell_t *params) } KeyValues *pValues = pStk->pCurRoot.front(); - pStk->pCurRoot.push(pValues); + pStk->pCurRoot.push_front(pValues); return 1; } diff --git a/core/smn_keyvalues.h b/core/smn_keyvalues.h index 61e83f3ab8..d799d7cc34 100644 --- a/core/smn_keyvalues.h +++ b/core/smn_keyvalues.h @@ -33,7 +33,7 @@ #define _INCLUDE_SOURCEMOD_KVWRAPPER_H_ #include -#include +#include using namespace SourceMod; @@ -42,7 +42,7 @@ class KeyValues; struct KeyValueStack { KeyValues *pBase; - SourceHook::CStack pCurRoot; + std::deque pCurRoot; bool m_bDeleteOnDestroy = true; }; diff --git a/core/smn_nextmap.cpp b/core/smn_nextmap.cpp index ef6f4ab28c..c9a6405521 100644 --- a/core/smn_nextmap.cpp +++ b/core/smn_nextmap.cpp @@ -79,8 +79,7 @@ static cell_t sm_GetMapHistory(IPluginContext *pCtx, const cell_t *params) return pCtx->ThrowNativeError("Invalid Map History Index"); } - SourceHook::List::iterator iter; - iter = g_NextMap.m_mapHistory.end(); + auto iter = g_NextMap.m_mapHistory.end(); iter--; for (int i=0; i MsgWrapperList; -typedef List::iterator MsgWrapperIter; +typedef std::list MsgWrapperList; +typedef MsgWrapperList::iterator MsgWrapperIter; class UsrMessageNatives : public SMGlobalClass, @@ -72,17 +72,15 @@ class UsrMessageNatives : bool FindListener(int msgid, IPluginContext *pCtx, IPluginFunction *pHook, bool intercept, MsgWrapperIter *iter); bool DeleteListener(IPluginContext *pCtx, MsgWrapperIter iter); private: - CStack m_FreeListeners; + std::stack m_FreeListeners; }; UsrMessageNatives::~UsrMessageNatives() { - CStack::iterator iter; - for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) - { - delete (*iter); + while (!m_FreeListeners.empty()) { + delete m_FreeListeners.top(); + m_FreeListeners.pop(); } - m_FreeListeners.popall(); } void UsrMessageNatives::OnSourceModAllInitialized() @@ -175,13 +173,13 @@ MsgListenerWrapper *UsrMessageNatives::CreateListener(IPluginContext *pCtx) { pListener = new MsgListenerWrapper; } else { - pListener = m_FreeListeners.front(); + pListener = m_FreeListeners.top(); m_FreeListeners.pop(); } if (!pl->GetProperty("MsgListeners", reinterpret_cast(&pList))) { - pList = new List; + pList = new std::list; pl->SetProperty("MsgListeners", pList); } diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index a801079998..6fcb8de642 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -48,8 +48,6 @@ ISmmPluginManager *g_pMMPlugins = NULL; CGlobalVars *gpGlobals = NULL; ICvar *icvar = NULL; IGameEventManager2 *gameevents = NULL; -CallClass *enginePatch = NULL; -CallClass *gamedllPatch = NULL; IPlayerInfoManager *playerinfo = NULL; IBaseFileSystem *basefilesystem = NULL; IFileSystem *filesystem = NULL; diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index 68372a10c7..ee8b349744 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -40,6 +40,7 @@ #include #include #include +#include /** * @file Contains wrappers around required Metamod:Source API exports @@ -78,8 +79,6 @@ extern ICvar *icvar; extern ISmmPluginManager *g_pMMPlugins; extern CGlobalVars *gpGlobals; extern IGameEventManager2 *gameevents; -extern SourceHook::CallClass *enginePatch; -extern SourceHook::CallClass *gamedllPatch; extern IPlayerInfoManager *playerinfo; extern IBaseFileSystem *basefilesystem; extern IFileSystem *filesystem; @@ -91,9 +90,6 @@ extern IServerPluginHelpers *serverpluginhelpers; extern IServerPluginCallbacks *vsp_interface; extern int vsp_version; -#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func) -#define SERVER_CALL(func) SH_CALL(gamedllPatch, &IServerGameDLL::func) - PLUGIN_GLOBALVARS(); #endif //_INCLUDE_SOURCEMOD_MM_API_H_ diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 5f2dde5f97..dea336df77 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -32,7 +32,7 @@ #include #include "sourcemod.h" #include "sourcemm_api.h" -#include +#include #include "CoreConfig.h" #include "Logger.h" #include "sm_stringutil.h" @@ -49,17 +49,12 @@ #include #include -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); -SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, false, bool); -SH_DECL_HOOK1_void(IServerGameDLL, Think, SH_NOATTRIB, false, bool); -SH_DECL_HOOK1_void(IVEngineServer, ServerCommand, SH_NOATTRIB, false, const char *); -SH_DECL_HOOK0(IVEngineServer, GetMapEntitiesString, SH_NOATTRIB, 0, const char *); +/**/ SourceModBase g_SourceMod; ke::RefPtr g_JIT; -SourceHook::String g_BaseDir; +std::string g_BaseDir; ISourcePawnEngine *g_pSourcePawn = NULL; ISourcePawnEngine2 *g_pSourcePawn2 = NULL; ISourcePawnEnvironment *g_pPawnEnv = NULL; @@ -93,13 +88,32 @@ void ShutdownJIT() g_JIT = nullptr; } -SourceModBase::SourceModBase() +SourceModBase::SourceModBase() : + m_HookLevelInit(&IServerGameDLL::LevelInit, this, &SourceModBase::Hook_LevelInit, nullptr), + m_HookLevelShutdown(&IServerGameDLL::LevelShutdown, this, &SourceModBase::Hook_LevelShutdown, nullptr), + m_HookGameFrame(&IServerGameDLL::GameFrame, this, &SourceModBase::Hook_GameFrame, nullptr), + m_HookThink(&IServerGameDLL::Think, this, &SourceModBase::Hook_Think, nullptr), + m_HookGetMapEntitiesString(&IVEngineServer::GetMapEntitiesString, this, &SourceModBase::Hook_GetMapEntitiesString, nullptr) { m_IsMapLoading = false; m_ExecPluginReload = false; m_GotBasePath = false; } +KHook::Return SourceModBase::Hook_GameFrame(IServerGameDLL*, bool simulating) +{ + g_Timers.GameFrame(simulating); + + return { KHook::Action::Ignore }; +} + +KHook::Return SourceModBase::Hook_Think(IServerGameDLL*, bool simulating) +{ + logicore.callbacks->OnThink(simulating); + + return { KHook::Action::Ignore }; +} + ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, @@ -278,8 +292,8 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late sSourceModInitialized = true; /* Hook this now so we can detect startup without calling StartSourceMod() */ - SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false); - SH_ADD_HOOK(IVEngineServer, GetMapEntitiesString, engine, SH_MEMBER(this, &SourceModBase::GetMapEntitiesString), false); + m_HookLevelInit.Add(gamedll); + m_HookGetMapEntitiesString.Add(engine); /* Only load if we're not late */ if (!late) @@ -292,11 +306,8 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late void SourceModBase::StartSourceMod(bool late) { - SH_ADD_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false); - SH_ADD_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false); - - enginePatch = SH_GET_CALLCLASS(engine); - gamedllPatch = SH_GET_CALLCLASS(gamedll); + m_HookLevelShutdown.Add(gamedll); + m_HookGameFrame.Add(gamedll); sCoreProviderImpl.InitializeBridge(); @@ -370,12 +381,11 @@ void SourceModBase::StartSourceMod(bool late) { g_pPawnEnv->EnableDebugBreak(); } - - SH_ADD_HOOK(IServerGameDLL, Think, gamedll, SH_MEMBER(logicore.callbacks, &IProviderCallbacks::OnThink), false); + m_HookThink.Add(gamedll); } static bool g_LevelEndBarrier = false; -bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) +KHook::Return SourceModBase::Hook_LevelInit(IServerGameDLL* this_ptr, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { /* Seed rand() globally per map */ srand(time(NULL)); @@ -436,23 +446,23 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch if (!success) { logger->LogError("Map entity lump parsing for %s failed with error code %d on position %d", pMapName, parseError, position); - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore }; } - RETURN_META_VALUE_NEWPARAMS(MRES_HANDLED, true, &IServerGameDLL::LevelInit, (pMapName, logicore.GetEntityLumpString(), pOldLevel, pLandmarkName, loadGame, background)); + return KHook::Recall(&IServerGameDLL::LevelInit, KHook::Return{KHook::Action::Override, true}, this_ptr, pMapName, logicore.GetEntityLumpString(), pOldLevel, pLandmarkName, loadGame, background); } -const char *SourceModBase::GetMapEntitiesString() +KHook::Return SourceModBase::Hook_GetMapEntitiesString(IVEngineServer*) { const char *pNewMapEntities = logicore.GetEntityLumpString(); if (pNewMapEntities != nullptr) { - RETURN_META_VALUE(MRES_SUPERCEDE, pNewMapEntities); + return { KHook::Action::Supersede, pNewMapEntities }; } - RETURN_META_VALUE(MRES_IGNORED, NULL); + return { KHook::Action::Ignore }; } -void SourceModBase::LevelShutdown() +KHook::Return SourceModBase::Hook_LevelShutdown(IServerGameDLL*) { if (g_LevelEndBarrier) { @@ -479,6 +489,8 @@ void SourceModBase::LevelShutdown() scripts->RefreshAll(); m_ExecPluginReload = false; } + + return { KHook::Action::Ignore }; } bool SourceModBase::IsMapLoading() const @@ -563,13 +575,13 @@ void SourceModBase::CloseSourceMod() if (!sSourceModInitialized) return; - SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false); - SH_REMOVE_HOOK(IVEngineServer, GetMapEntitiesString, engine, SH_MEMBER(this, &SourceModBase::GetMapEntitiesString), false); + m_HookLevelInit.Remove(gamedll); + m_HookGetMapEntitiesString.Remove(engine); if (g_Loaded) { /* Force a level end */ - LevelShutdown(); + Hook_LevelShutdown(gamedll); ShutdownServices(); } @@ -616,21 +628,9 @@ void SourceModBase::ShutdownServices() pBase = pBase->m_pGlobalClassNext; } - if (enginePatch) - { - SH_RELEASE_CALLCLASS(enginePatch); - enginePatch = NULL; - } - - if (gamedllPatch) - { - SH_RELEASE_CALLCLASS(gamedllPatch); - gamedllPatch = NULL; - } - - SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false); - SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false); - SH_REMOVE_HOOK(IServerGameDLL, Think, gamedll, SH_MEMBER(logicore.callbacks, &IProviderCallbacks::OnThink), false); + m_HookLevelShutdown.Remove(gamedll); + m_HookGameFrame.Remove(gamedll); + m_HookThink.Remove(gamedll); } void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...) @@ -765,7 +765,7 @@ void SourceModBase::RemoveGameFrameHook(GAME_FRAME_HOOK hook) { if (m_frame_hooks[i] == hook) { - m_frame_hooks.erase(m_frame_hooks.iterAt(i)); + m_frame_hooks.erase(m_frame_hooks.begin() + i); return; } } @@ -821,9 +821,7 @@ int SourceModBase::GetPluginId() int SourceModBase::GetShApiVersion() { - int api, impl; - g_SMAPI->GetShVersions(api, impl); - + int api = 999, impl = 999; return api; } diff --git a/core/sourcemod.h b/core/sourcemod.h index 3667f2275d..5dd2a7ae63 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -34,10 +34,9 @@ #include "sm_globals.h" #include -#include -#include - -using namespace SourceHook; +#include +#include +#include #if defined _DEBUG # define IF_DEBUG_SPEW @@ -76,16 +75,6 @@ class SourceModBase : */ void CloseSourceMod(); - /** - * @brief Map change hook - */ - bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); - - /** - * @brief Level shutdown hook - */ - void LevelShutdown(); - /** * @brief Returns whether or not a map load is in progress */ @@ -138,7 +127,6 @@ class SourceModBase : private: void ShutdownServices(); private: - const char* GetMapEntitiesString(); char m_SMBaseDir[PLATFORM_MAX_PATH]; char m_SMRelDir[PLATFORM_MAX_PATH]; char m_ModDir[32]; @@ -147,7 +135,18 @@ class SourceModBase : bool m_ExecOnMapEnd; unsigned int m_target; bool m_GotBasePath; - CVector m_frame_hooks; + std::vector m_frame_hooks; +protected: + KHook::Virtual m_HookLevelInit; + KHook::Return Hook_LevelInit(class IServerGameDLL*, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); + KHook::Virtual m_HookLevelShutdown; + KHook::Return Hook_LevelShutdown(class IServerGameDLL*); + KHook::Virtual m_HookGameFrame; + KHook::Return Hook_GameFrame(class IServerGameDLL*, bool); + KHook::Virtual m_HookThink; + KHook::Return Hook_Think(class IServerGameDLL*, bool); + KHook::Virtual m_HookGetMapEntitiesString; + KHook::Return Hook_GetMapEntitiesString(class IVEngineServer*); }; void UTIL_ConsolePrintVa(const char *fmt, va_list ap); diff --git a/extensions/bintools/CallMaker.cpp b/extensions/bintools/CallMaker.cpp index f5c4c56d50..745baba15c 100644 --- a/extensions/bintools/CallMaker.cpp +++ b/extensions/bintools/CallMaker.cpp @@ -30,53 +30,82 @@ */ #include +#include #include "CallMaker.h" #include "jit_compile.h" #include "extension.h" -/* SourceMod <==> SourceHook type conversion functions */ - -SourceHook::ProtoInfo::CallConvention GetSHCallConvention(SourceMod::CallConvention cv) +class CProtoInfoBuilder { - if (cv < SourceMod::CallConv_ThisCall || cv > SourceMod::CallConv_Cdecl) + ProtoInfo m_PI; + std::vector m_Params; +public: + CProtoInfoBuilder(int cc) { - return SourceHook::ProtoInfo::CallConv_Unknown; - } + memset(reinterpret_cast(&m_PI), 0, sizeof(ProtoInfo)); + m_PI.convention = cc; - return (SourceHook::ProtoInfo::CallConvention)(cv + 1); -} + // dummy 0 params + PassInfo dummy; + memset(reinterpret_cast(&dummy), 0, sizeof(PassInfo)); -SourceMod::CallConvention GetSMCallConvention(SourceHook::ProtoInfo::CallConvention cv) -{ - assert(cv >= SourceHook::ProtoInfo::CallConv_ThisCall || cv <= SourceHook::ProtoInfo::CallConv_Cdecl); + dummy.size = 1; // Version1 - return (SourceMod::CallConvention)(cv - 1); -} + m_Params.push_back(dummy); + } -SourceHook::PassInfo::PassType GetSHPassType(SourceMod::PassType type) -{ - if (type < SourceMod::PassType_Basic || type > SourceMod::PassType_Object) + void SetReturnType(size_t size, PassType type, int flags, + void *pNormalCtor, void *pCopyCtor, void *pDtor, void *pAssignOperator) { - return SourceHook::PassInfo::PassType_Unknown; + if (pNormalCtor) + flags |= PASSFLAG_OCTOR; + + //if (pCopyCtor) + // flags |= PassInfo::PassFlag_CCtor; + + if (pDtor) + flags |= PASSFLAG_ODTOR; + + if (pAssignOperator) + flags |= PASSFLAG_OASSIGNOP; + + m_PI.retPassInfo.size = size; + m_PI.retPassInfo.type = type; + m_PI.retPassInfo.flags = flags; } - return (SourceHook::PassInfo::PassType)(type + 1); -} + void AddParam(size_t size, PassType type, int flags, + void *pNormalCtor, void *pCopyCtor, void *pDtor, void *pAssignOperator) + { + PassInfo pi; -SourceMod::PassType GetSMPassType(int type) -{ - /* SourceMod doesn't provide an Unknown type so we it must be an error */ - assert(type >= SourceHook::PassInfo::PassType_Basic && type <= SourceHook::PassInfo::PassType_Object); + if (pNormalCtor) + flags |= PASSFLAG_OCTOR; - return (SourceMod::PassType)(type - 1); -} + //if (pCopyCtor) + // flags |= PassInfo::PassFlag_CCtor; -void GetSMPassInfo(SourceMod::PassInfo *out, const SourceHook::PassInfo *in) -{ - out->size = in->size; - out->flags = in->flags; - out->type = GetSMPassType(in->type); -} + if (pDtor) + flags |= PASSFLAG_ODTOR; + + if (pAssignOperator) + flags |= PASSFLAG_OASSIGNOP; + + + pi.size = size; + pi.type = type; + pi.flags = flags; + + m_Params.push_back(pi); + ++m_PI.numOfParams; + } + + operator ProtoInfo*() + { + m_PI.paramsPassInfo = &(m_Params[0]); + return &m_PI; + } +}; ICallWrapper *CallMaker::CreateCall(void *address, CallConvention cv, @@ -85,22 +114,22 @@ ICallWrapper *CallMaker::CreateCall(void *address, unsigned int numParams, unsigned int fnFlags) { - SourceHook::CProtoInfoBuilder protoInfo(GetSHCallConvention(cv)); + CProtoInfoBuilder protoInfo(cv); for (unsigned int i=0; isize, GetSHPassType(retInfo->type), retInfo->flags, + protoInfo.SetReturnType(retInfo->size, retInfo->type, retInfo->flags, NULL, NULL, NULL, NULL); } else { - protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, + protoInfo.SetReturnType(0, PassType_Basic, 0, NULL, NULL, NULL, NULL); } @@ -119,39 +148,34 @@ ICallWrapper *CallMaker::CreateVCall(unsigned int vtblIdx, unsigned int numParams, unsigned int fnFlags) { - SourceHook::MemFuncInfo info; - info.isVirtual = true; - info.vtblindex = vtblIdx; - info.vtbloffs = vtblOffs; - info.thisptroffs = thisOffs; - SourceHook::CProtoInfoBuilder protoInfo(SourceHook::ProtoInfo::CallConv_ThisCall); + CProtoInfoBuilder protoInfo(CallConv_ThisCall); for (unsigned int i=0; isize, GetSHPassType(retInfo->type), retInfo->flags, + protoInfo.SetReturnType(retInfo->size, retInfo->type, retInfo->flags, NULL, NULL, NULL, NULL); } else { - protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, + protoInfo.SetReturnType(0, PassType::PassType_Basic, 0, NULL, NULL, NULL, NULL); } #if defined KE_ARCH_X64 - return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info, retInfo, paramInfo, fnFlags); + return g_CallMaker2.CreateVirtualCall(&(*protoInfo), vtblIdx, retInfo, paramInfo, fnFlags); #else - return g_CallMaker2.CreateVirtualCall(&(*protoInfo), &info); + return g_CallMaker2.CreateVirtualCall(&(*protoInfo), vtblIdx); #endif } -ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo) +ICallWrapper *CallMaker2::CreateCall(void *address, const ProtoInfo *protoInfo) { #ifdef KE_ARCH_X86 CallWrapper *pWrapper = new CallWrapper(protoInfo); @@ -166,12 +190,11 @@ ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo #endif } -ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info) +ICallWrapper *CallMaker2::CreateVirtualCall(const ProtoInfo* protoInfo, uint32_t vtable_index) { #ifdef KE_ARCH_X86 CallWrapper *pWrapper = new CallWrapper(protoInfo); - pWrapper->SetMemFuncInfo(info); + pWrapper->SetVtableIndex(vtable_index); void *addr = JIT_CallCompile(pWrapper, FuncAddr_VTable); pWrapper->SetCodeBaseAddr(addr); @@ -182,7 +205,7 @@ ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoIn #endif } -ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo, +ICallWrapper *CallMaker2::CreateCall(void *address, const ProtoInfo *protoInfo, const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags) { @@ -199,15 +222,15 @@ ICallWrapper *CallMaker2::CreateCall(void *address, const SourceHook::ProtoInfo #endif } -ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info, +ICallWrapper *CallMaker2::CreateVirtualCall(const ProtoInfo *protoInfo, + uint32_t vtable_index, const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags) { #ifdef KE_ARCH_X64 CallWrapper *pWrapper = new CallWrapper(protoInfo, retInfo, paramInfo, fnFlags); - pWrapper->SetMemFuncInfo(info); + pWrapper->SetVtableIndex(vtable_index); void *addr = JIT_CallCompile(pWrapper, FuncAddr_VTable); pWrapper->SetCodeBaseAddr(addr); @@ -216,23 +239,4 @@ ICallWrapper *CallMaker2::CreateVirtualCall(const SourceHook::ProtoInfo *protoIn #else return nullptr; #endif -} - -#if 0 -IHookWrapper *CallMaker2::CreateVirtualHook(SourceHook::ISourceHook *pSH, - const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info, - VIRTUAL_HOOK_PROTO f) -{ - HookWrapper *pWrapper = new HookWrapper(pSH, protoInfo, const_cast(info), (void *)f); - - void *addr = JIT_HookCompile(pWrapper); - pWrapper->SetHookWrpAddr(addr); - - ICallWrapper *callWrap = CreateVirtualCall(protoInfo, info); - pWrapper->SetCallWrapperAddr(callWrap); - - return pWrapper; -} -#endif - +} \ No newline at end of file diff --git a/extensions/bintools/CallMaker.h b/extensions/bintools/CallMaker.h index d97b10699b..51fdde2a2f 100644 --- a/extensions/bintools/CallMaker.h +++ b/extensions/bintools/CallMaker.h @@ -34,6 +34,7 @@ #include "CallWrapper.h" +#include "stdint.h" using namespace SourceMod; @@ -59,30 +60,18 @@ class CallMaker2 { public: //IBinTools2 virtual ICallWrapper *CreateCall(void *address, - const SourceHook::ProtoInfo *protoInfo); - virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info); - ICallWrapper *CreateCall(void *address, const SourceHook::ProtoInfo *protoInfo, + const ProtoInfo *protoInfo); + virtual ICallWrapper *CreateVirtualCall(const ProtoInfo *protoInfo, + uint32_t vtable_index); + ICallWrapper *CreateCall(void *address, const ProtoInfo *protoInfo, const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags); - ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info, const PassInfo *retInfo, + ICallWrapper *CreateVirtualCall(const ProtoInfo *protoInfo, + uint32_t vtable_index, const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags); -#if 0 - virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH, - const SourceHook::ProtoInfo *protoInfo, - const SourceHook::MemFuncInfo *info, - VIRTUAL_HOOK_PROTO f); -#endif }; extern CallMaker2 g_CallMaker2; -SourceHook::ProtoInfo::CallConvention GetSHCallConvention(SourceMod::CallConvention cv); -SourceMod::CallConvention GetSMCallConvention(SourceHook::ProtoInfo::CallConvention cv); -SourceHook::PassInfo::PassType GetSHPassType(SourceMod::PassType type); -SourceMod::PassType GetSMPassType(int type); -void GetSMPassInfo(SourceMod::PassInfo *out, const SourceHook::PassInfo *in); - #endif //_INCLUDE_SOURCEMOD_CALLMAKER_H_ diff --git a/extensions/bintools/CallWrapper.cpp b/extensions/bintools/CallWrapper.cpp index 513b540ea9..6e21b2c580 100644 --- a/extensions/bintools/CallWrapper.cpp +++ b/extensions/bintools/CallWrapper.cpp @@ -33,7 +33,7 @@ #include "CallWrapper.h" #include "CallMaker.h" -CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo) : m_FnFlags(0) +CallWrapper::CallWrapper(const ProtoInfo *protoInfo) : m_FnFlags(0) { m_AddrCodeBase = NULL; m_AddrCallee = NULL; @@ -41,15 +41,15 @@ CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo) : m_FnFlags(0) unsigned int argnum = protoInfo->numOfParams; m_Info = *protoInfo; - m_Info.paramsPassInfo = new SourceHook::PassInfo[argnum + 1]; - memcpy((void *)m_Info.paramsPassInfo, protoInfo->paramsPassInfo, sizeof(SourceHook::PassInfo) * (argnum+1)); + m_Info.paramsPassInfo = new PassInfo[argnum + 1]; + memcpy((void *)m_Info.paramsPassInfo, protoInfo->paramsPassInfo, sizeof(PassInfo) * (argnum+1)); if (argnum) { m_Params = new PassEncode[argnum]; for (size_t i=0; i GetParamCount()) - { - return NULL; - } - - return &(m_Info.paramsPassInfo[num+1]); -} - unsigned int CallWrapper::GetParamOffset(unsigned int num) { assert(num < GetParamCount() && num >= 0); @@ -212,3 +181,13 @@ unsigned int CallWrapper::GetFunctionFlags() { return m_FnFlags; } + +void CallWrapper::SetVtableIndex(unsigned int index) +{ + m_VTableIndex = index; +} + +unsigned int CallWrapper::GetVtableIndex() +{ + return m_VTableIndex; +} \ No newline at end of file diff --git a/extensions/bintools/CallWrapper.h b/extensions/bintools/CallWrapper.h index 38c65a21e3..2fa39f15d8 100644 --- a/extensions/bintools/CallWrapper.h +++ b/extensions/bintools/CallWrapper.h @@ -33,7 +33,6 @@ #define _INCLUDE_SOURCEMOD_CALLWRAPPER_H_ #include -#include using namespace SourceMod; @@ -43,11 +42,24 @@ enum FuncAddrMethod FuncAddr_VTable }; +struct ProtoInfo +{ + int numOfParams; //!< number of parameters + PassInfo retPassInfo; //!< PassInfo for the return value. size=0 -> no retval + const PassInfo *paramsPassInfo; //!< PassInfos for the parameters + + // paramsPassInfo[0] is basically a dummy parameter. + // However, paramsPassInfo[0].size stores the version of the ProtoInfo structure. + + // Extra info: + int convention; +}; + class CallWrapper : public ICallWrapper { public: - CallWrapper(const SourceHook::ProtoInfo *protoInfo); - CallWrapper(const SourceHook::ProtoInfo *protoInfo, const PassInfo *retInfo, + CallWrapper(const ProtoInfo *protoInfo); + CallWrapper(const ProtoInfo *protoInfo, const PassInfo *retInfo, const PassInfo paramInfo[], unsigned int fnFlags); ~CallWrapper(); public: //ICallWrapper @@ -57,27 +69,23 @@ class CallWrapper : public ICallWrapper unsigned int GetParamCount(); void Execute(void *vParamStack, void *retBuffer); void Destroy(); - const SourceHook::PassInfo *GetSHReturnInfo(); - SourceHook::ProtoInfo::CallConvention GetSHCallConvention(); - const SourceHook::PassInfo *GetSHParamInfo(unsigned int num); unsigned int GetParamOffset(unsigned int num); unsigned int GetFunctionFlags(); + void SetVtableIndex(unsigned int); + unsigned int GetVtableIndex(); public: void SetCalleeAddr(void *addr); void SetCodeBaseAddr(void *addr); void *GetCalleeAddr(); void *GetCodeBaseAddr(); - - void SetMemFuncInfo(const SourceHook::MemFuncInfo *funcInfo); - SourceHook::MemFuncInfo *GetMemFuncInfo(); private: PassEncode *m_Params; - SourceHook::ProtoInfo m_Info; + ProtoInfo m_Info; PassInfo *m_RetParam; void *m_AddrCallee; void *m_AddrCodeBase; - SourceHook::MemFuncInfo m_FuncInfo; unsigned int m_FnFlags; + unsigned int m_VTableIndex; }; #endif //_INCLUDE_SOURCEMOD_CALLWRAPPER_H_ diff --git a/extensions/bintools/jit_call.cpp b/extensions/bintools/jit_call.cpp index 165c06e67f..8230b8d3cc 100644 --- a/extensions/bintools/jit_call.cpp +++ b/extensions/bintools/jit_call.cpp @@ -111,13 +111,13 @@ inline void Write_Function_Epilogue(JitWriter *jit, bool is_void, bool has_param IA32_Return(jit); } -inline void Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset) +inline void Write_PushPOD(JitWriter *jit, const PassInfo& info, unsigned int offset) { jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++); - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { - switch (info->size) + switch (info.size) { case 1: { @@ -200,7 +200,7 @@ inline void Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *info, unsi break; } } - } else if (info->flags & PASSFLAG_BYREF) { + } else if (info.flags & PASSFLAG_BYREF) { //lea reg, [ebx+] //push reg if (!offset) @@ -221,11 +221,11 @@ inline void Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *info, unsi } } -inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset) +inline void Write_PushFloat(JitWriter *jit, const PassInfo& info, unsigned int offset) { - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { - switch (info->size) + switch (info.size) { case 4: { @@ -264,7 +264,7 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un break; } } - } else if (info->flags & PASSFLAG_BYREF) { + } else if (info.flags & PASSFLAG_BYREF) { //lea reg, [ebx+] //push reg if (!offset) @@ -287,18 +287,18 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un } } -inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset) +inline void Write_PushObject(JitWriter *jit, const PassInfo& info, unsigned int offset) { - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { #ifdef PLATFORM_POSIX - if (info->flags & PASSFLAG_ODTOR) + if (info.flags & PASSFLAG_ODTOR) { goto push_byref; } #endif - jit_uint32_t dwords = info->size >> 2; - jit_uint32_t bytes = info->size & 0x3; + jit_uint32_t dwords = info.size >> 2; + jit_uint32_t bytes = info.size & 0x3; //sub esp, //cld @@ -314,11 +314,11 @@ inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, u // rep movsb //pop esi //pop edi - if (info->size < SCHAR_MAX) + if (info.size < SCHAR_MAX) { - IA32_Sub_Rm_Imm8(jit, kREG_ESP, (jit_int8_t)info->size, MOD_REG); + IA32_Sub_Rm_Imm8(jit, kREG_ESP, (jit_int8_t)info.size, MOD_REG); } else { - IA32_Sub_Rm_Imm32(jit, kREG_ESP, info->size, MOD_REG); + IA32_Sub_Rm_Imm32(jit, kREG_ESP, info.size, MOD_REG); } IA32_Cld(jit); IA32_Push_Reg(jit, kREG_EDI); @@ -347,8 +347,8 @@ inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, u IA32_Pop_Reg(jit, kREG_ESI); IA32_Pop_Reg(jit, kREG_EDI); - g_StackUsage += info->size; - } else if (info->flags & PASSFLAG_BYREF) { + g_StackUsage += info.size; + } else if (info.flags & PASSFLAG_BYREF) { #ifdef PLATFORM_POSIX push_byref: #endif @@ -410,9 +410,9 @@ inline void Write_CallFunction(JitWriter *jit, FuncAddrMethod method, CallWrappe //mov eax, [edx++] //mov edx, [eax+*4] //call edx - SourceHook::MemFuncInfo *funcInfo = pWrapper->GetMemFuncInfo(); - jit_uint32_t total_offs = funcInfo->thisptroffs + funcInfo->vtbloffs; - jit_uint32_t vfunc_pos = funcInfo->vtblindex * 4; + //SourceHook::MemFuncInfo *funcInfo = pWrapper->GetMemFuncInfo(); + jit_uint32_t total_offs = 0; /*funcInfo->thisptroffs + funcInfo->vtbloffs;*/ + jit_uint32_t vfunc_pos = pWrapper->GetVtableIndex() * sizeof(void*); /*funcInfo->vtblindex * 4;*/ IA32_Mov_Reg_Rm(jit, kREG_EDX, kREG_EBX, MOD_MEM_REG); if (total_offs < SCHAR_MAX) @@ -529,24 +529,24 @@ void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method) for (jit_int32_t i=ParamCount-1; i>=0; i--) { unsigned int offset = pWrapper->GetParamOffset(i); - const SourceHook::PassInfo *info = pWrapper->GetSHParamInfo(i); + auto info = pWrapper->GetParamInfo(i); assert(info != NULL); - switch (info->type) + switch (info->info.type) { - case SourceHook::PassInfo::PassType_Basic: + case PassType::PassType_Basic: { - Write_PushPOD(jit, info, offset); + Write_PushPOD(jit, info->info, offset); break; } - case SourceHook::PassInfo::PassType_Float: + case PassType::PassType_Float: { - Write_PushFloat(jit, info, offset); + Write_PushFloat(jit, info->info, offset); break; } - case SourceHook::PassInfo::PassType_Object: + case PassType::PassType_Object: { - Write_PushObject(jit, info, offset); + Write_PushObject(jit, info->info, offset); break; } } diff --git a/extensions/bintools/jit_call_x64.cpp b/extensions/bintools/jit_call_x64.cpp index d404498015..691c7084ee 100644 --- a/extensions/bintools/jit_call_x64.cpp +++ b/extensions/bintools/jit_call_x64.cpp @@ -273,10 +273,10 @@ inline void Write_Function_Epilogue(JitWriter *jit, bool is_void, bool has_param X64_Return(jit); } -inline jit_uint8_t Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset) +inline jit_uint8_t Write_PushPOD(JitWriter *jit, const PassInfo& info, unsigned int offset) { bool needStack = false; - jit_uint8_t reg = NextPODReg(info->size); + jit_uint8_t reg = NextPODReg(info.size); jit_uint8_t reg2; if (reg == STACK_PARAM) @@ -285,9 +285,9 @@ inline jit_uint8_t Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *inf needStack = true; } - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { - switch (info->size) + switch (info.size) { case 1: { @@ -358,7 +358,7 @@ inline jit_uint8_t Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *inf break; } } - } else if (info->flags & PASSFLAG_BYREF) { + } else if (info.flags & PASSFLAG_BYREF) { //lea reg, [ebx+] if (!offset) X64_Mov_Reg_Rm(jit, reg, kREG_RBX, MOD_REG); @@ -384,7 +384,7 @@ inline jit_uint8_t Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *inf else X64_Mov_RmRSP_Disp32_Reg(jit, reg, g_StackUsage); - if (info->size == 16) + if (info.size == 16) { if (g_StackUsage + 8 < SCHAR_MAX) X64_Mov_RmRSP_Disp8_Reg(jit, reg2, (jit_int8_t)g_StackUsage + 8); @@ -399,10 +399,10 @@ inline jit_uint8_t Write_PushPOD(JitWriter *jit, const SourceHook::PassInfo *inf return reg; } -inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset, uint8_t *floatRegs) +inline void Write_PushFloat(JitWriter *jit, const PassInfo& info, unsigned int offset, uint8_t *floatRegs) { bool needStack = false; - jit_uint8_t floatReg = NextFloatReg(info->size); + jit_uint8_t floatReg = NextFloatReg(info.size); jit_uint8_t floatReg2; if (floatReg == STACK_PARAM) @@ -411,9 +411,9 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un needStack = true; } - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { - switch (info->size) + switch (info.size) { case 4: { @@ -491,7 +491,7 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un X64_Movups_Rm_Disp32(jit, floatReg2, kREG_EBX, offset+8); } } - } else if (info->flags & PASSFLAG_BYREF) { + } else if (info.flags & PASSFLAG_BYREF) { //lea reg, [ebx+] Write_PushPOD(jit, info, offset); return; @@ -520,7 +520,7 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un X64_Movups_Rm_Disp32_Reg(jit, kREG_RSP, floatReg, g_StackUsage); } - if (info->size == 16) + if (info.size == 16) { if (g_StackUsage + 8 < SCHAR_MAX) { if ((g_StackUsage + 8) % 16 == 0) @@ -542,7 +542,7 @@ inline void Write_PushFloat(JitWriter *jit, const SourceHook::PassInfo *info, un if (floatRegs) { floatRegs[0] = floatReg; - floatRegs[1] = info->size == 16 ? floatReg2 : INVALID_REG; + floatRegs[1] = info.size == 16 ? floatReg2 : INVALID_REG; } } @@ -716,10 +716,10 @@ inline int ClassifyObject(const PassInfo *info, ObjectClass *classes) return numWords; } -inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, unsigned int offset, +inline void Write_PushObject(JitWriter *jit, const PassInfo& info, unsigned int offset, const PassInfo *smInfo) { - if (info->flags & PASSFLAG_BYVAL) + if (info.flags & PASSFLAG_BYVAL) { #ifdef PLATFORM_POSIX ObjectClass classes[MAX_CLASSES]; @@ -752,27 +752,27 @@ inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, u if (classes[0] != ObjectClass::Memory) { - size_t sizeLeft = info->size; + size_t sizeLeft = info.size; for (int i = 0; i < numWords; i++) { switch (classes[i]) { case ObjectClass::Integer: { - SourceHook::PassInfo podInfo; + PassInfo podInfo; podInfo.size = (sizeLeft > 8) ? 8 : sizeLeft; - podInfo.type = SourceHook::PassInfo::PassType_Basic; - podInfo.flags = SourceHook::PassInfo::PassFlag_ByVal; - Write_PushPOD(jit, &podInfo, offset + (i * 8)); + podInfo.type = PassType_Basic; + podInfo.flags = PASSFLAG_BYVAL; + Write_PushPOD(jit, podInfo, offset + (i * 8)); break; } case ObjectClass::SSE: { - SourceHook::PassInfo floatInfo; + PassInfo floatInfo; floatInfo.size = (sizeLeft > 8) ? 8 : sizeLeft; - floatInfo.type = SourceHook::PassInfo::PassType_Float; - floatInfo.flags = SourceHook::PassInfo::PassFlag_ByVal; - Write_PushFloat(jit, &floatInfo, offset + (i * 8), nullptr); + floatInfo.type = PassType_Float; + floatInfo.flags = PASSFLAG_BYVAL; + Write_PushFloat(jit, floatInfo, offset + (i * 8), nullptr); break; } default: @@ -800,8 +800,8 @@ inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, u return; #endif - jit_uint32_t qwords = info->size >> 3; - jit_uint32_t bytes = info->size & 0x7; + jit_uint32_t qwords = info.size >> 3; + jit_uint32_t bytes = info.size & 0x7; //sub rsp, //cld @@ -854,25 +854,25 @@ inline void Write_PushObject(JitWriter *jit, const SourceHook::PassInfo *info, u X64_Pop_Reg(jit, kREG_RSI); X64_Pop_Reg(jit, kREG_RDI); - g_StackUsage += info->size; - } else if (info->flags & PASSFLAG_BYREF) { + g_StackUsage += info.size; + } else if (info.flags & PASSFLAG_BYREF) { push_byref: //lea reg, [ebx+] - SourceHook::PassInfo podInfo; + PassInfo podInfo; podInfo.size = sizeof(void *); - podInfo.type = SourceHook::PassInfo::PassType_Basic; - podInfo.flags = SourceHook::PassInfo::PassFlag_ByRef; - Write_PushPOD(jit, &podInfo, offset); + podInfo.type = PassType_Basic; + podInfo.flags = PASSFLAG_BYREF; + Write_PushPOD(jit, podInfo, offset); } } inline void Write_PushThisPtr(JitWriter *jit) { - SourceHook::PassInfo podInfo; + PassInfo podInfo; podInfo.size = 8; - podInfo.type = SourceHook::PassInfo::PassType_Basic; - podInfo.flags = SourceHook::PassInfo::PassFlag_ByVal; - g_ThisPtrReg = Write_PushPOD(jit, &podInfo, 0); + podInfo.type = PassType_Basic; + podInfo.flags = PASSFLAG_BYVAL; + g_ThisPtrReg = Write_PushPOD(jit, podInfo, 0); } inline void Write_PushRetBuffer(JitWriter *jit) @@ -904,9 +904,9 @@ inline void Write_CallFunction(JitWriter *jit, FuncAddrMethod method, CallWrappe // mov r10, [g_ThisPtrReg++] // mov r11, [r10+*8] // call r11 - SourceHook::MemFuncInfo *funcInfo = pWrapper->GetMemFuncInfo(); - jit_uint32_t total_offs = funcInfo->thisptroffs + funcInfo->vtbloffs; - jit_uint32_t vfunc_pos = funcInfo->vtblindex * 8; + //SourceHook::MemFuncInfo *funcInfo = pWrapper->GetMemFuncInfo(); + jit_uint32_t total_offs = 0;/*funcInfo->thisptroffs + funcInfo->vtbloffs;*/ + jit_uint32_t vfunc_pos = pWrapper->GetVtableIndex() * sizeof(void*);/*funcInfo->vtblindex * 8;*/ //X64_Mov_Reg_Rm(jit, kREG_RAX, kREG_RBX, MOD_MEM_REG); if (total_offs < SCHAR_MAX) @@ -1115,17 +1115,17 @@ void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method) for (jit_uint32_t i = 0; i < ParamCount; i++) { unsigned int offset = pWrapper->GetParamOffset(i); - const SourceHook::PassInfo *info = pWrapper->GetSHParamInfo(i); + auto info = pWrapper->GetParamInfo(i); assert(info != NULL); - switch (info->type) + switch (info->info.type) { - case SourceHook::PassInfo::PassType_Basic: + case PassType::PassType_Basic: { - Write_PushPOD(jit, info, offset); + Write_PushPOD(jit, info->info, offset); break; } - case SourceHook::PassInfo::PassType_Float: + case PassType::PassType_Float: { #ifdef PLATFORM_WINDOWS if ((info->flags & PASSFLAG_BYVAL) && (pWrapper->GetFunctionFlags() & FNFLAG_VARARGS)) @@ -1137,14 +1137,14 @@ void *JIT_CallCompile(CallWrapper *pWrapper, FuncAddrMethod method) else #endif { - Write_PushFloat(jit, info, offset, nullptr); + Write_PushFloat(jit, info->info, offset, nullptr); } break; } - case SourceHook::PassInfo::PassType_Object: + case PassType::PassType_Object: { const PassEncode *paramInfo = pWrapper->GetParamInfo(i); - Write_PushObject(jit, info, offset, ¶mInfo->info); + Write_PushObject(jit, info->info, offset, ¶mInfo->info); break; } } diff --git a/extensions/clientprefs/query.h b/extensions/clientprefs/query.h index 31cdf55d01..2580bde024 100644 --- a/extensions/clientprefs/query.h +++ b/extensions/clientprefs/query.h @@ -34,7 +34,6 @@ #include "extension.h" #include "cookie.h" -#include "sh_string.h" enum querytype { diff --git a/extensions/dhooks/AMBuilder b/extensions/dhooks/AMBuilder index 3ea7987166..10644dfac2 100644 --- a/extensions/dhooks/AMBuilder +++ b/extensions/dhooks/AMBuilder @@ -1,87 +1,38 @@ # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: import os -for cxx in builder.targets: - binary = SM.ExtLibrary(builder, cxx, 'dhooks.ext') +sources = [ + 'src/capsule.cpp', + 'src/globals.cpp', + 'src/handle.cpp', + 'src/main.cpp', + 'src/register.cpp', + 'src/signatures.cpp', + 'src/sp_inc.cpp', + 'src/natives.cpp', + 'src/natives/dhookparam.cpp', + 'src/natives/dhookreturn.cpp', + 'src/natives/dhooksetup.cpp', + 'src/natives/dynamicdetour.cpp', + 'src/natives/dynamichook.cpp', + '../../public/smsdk_ext.cpp' +] - # mac isn't supported - if binary.compiler.target.platform == 'mac': - continue - # Presently only x86_64 on Windows is supported - if binary.compiler.target.arch == 'x86_64' and binary.compiler.target.platform != 'windows': +for cxx in builder.targets: + if cxx.target.platform != 'linux' or cxx.target.arch != 'x86_64': continue - binary.compiler.defines += [ - 'META_NO_HL2SDK', - 'HAVE_STRING_H', - ] - - if binary.compiler.like('gcc'): - binary.compiler.cflags += ['-Wno-invalid-offsetof'] - - binary.compiler.cxxincludes += [ - os.path.join(SM.mms_root, 'core'), - os.path.join(SM.mms_root, 'core', 'sourcehook'), - os.path.join(builder.sourcePath, 'extensions', 'dhooks'), - os.path.join(builder.sourcePath, 'public', 'jit'), - os.path.join(builder.sourcePath, 'sourcepawn', 'include'), - os.path.join(builder.sourcePath, 'sourcepawn', 'vm'), - os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'DynamicHooks'), - ] - - binary.compiler.includes += [ - os.path.join(builder.sourcePath, 'extensions', 'dhooks') - ] - - binary.sources += [ - 'extension.cpp', - 'listeners.cpp', - 'natives.cpp', - 'signatures.cpp', - 'vhook.cpp', - 'util.cpp', - 'dynhooks_sourcepawn.cpp', - '../../public/smsdk_ext.cpp', - # Dynamic Hooks - os.path.join('DynamicHooks', 'registers.cpp'), - os.path.join('DynamicHooks', 'hook.cpp'), - os.path.join('DynamicHooks', 'manager.cpp') - ] - SM.AddCDetour(binary) - - if binary.compiler.target.arch == 'x86': - #binary.sources += ['../../sourcepawn/vm/x86/assembler-x86.cpp'] - - binary.compiler.cxxincludes += [ - os.path.join(builder.sourcePath, 'public', 'jit', 'x86'), - os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86') - ] - # DynamicHooks - binary.sources += [ - os.path.join('DynamicHooks', 'conventions', 'x86MsCdecl.cpp'), - os.path.join('DynamicHooks', 'conventions', 'x86MsStdcall.cpp'), - os.path.join('DynamicHooks', 'conventions', 'x86MsFastcall.cpp'), - ] + binary = SM.ExtLibrary(builder, cxx, 'dhooks.ext') + binary.compiler.includes += [os.path.join(builder.sourcePath, 'extensions', 'dhooks', 'src')] + binary.sources += sources - if binary.compiler.target.platform == 'windows': - binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86MsThiscall.cpp')] - else: - binary.sources += [os.path.join('DynamicHooks', 'conventions', 'x86GccThiscall.cpp')] - - # Dynamic detour is only supported on x86 - binary.compiler.defines += ['DHOOKS_DYNAMIC_DETOUR'] + if cxx.target.platform == 'linux': + if cxx.target.arch == 'x86_64': + binary.sources += ['src/abi/system_v_amd64.cpp'] - elif binary.compiler.target.arch == 'x86_64': - binary.compiler.defines += ['DYNAMICHOOKS_x86_64', 'DHOOKS_DYNAMIC_DETOUR'] + if binary.compiler.target.arch == "x86": + binary.compiler.defines += ['DHOOKS_X86'] + elif binary.compiler.target.arch == "x86_64": + binary.compiler.defines += ['DHOOKS_X86_64'] - if binary.compiler.target.platform == 'windows': - binary.sources += [ - os.path.join('DynamicHooks', 'conventions', 'x86_64MicrosoftDefault.cpp') - ] - # Linux follows System V definition - elif binary.compiler.target.platform == 'linux': - binary.sources += [ - os.path.join('DynamicHooks', 'conventions', 'x86_64SystemVDefault.cpp') - ] - SM.extensions += [builder.Add(binary)] diff --git a/extensions/dhooks/DynamicHooks/convention.h b/extensions/dhooks/DynamicHooks/convention.h deleted file mode 100644 index e9a63ed479..0000000000 --- a/extensions/dhooks/DynamicHooks/convention.h +++ /dev/null @@ -1,290 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _CONVENTION_H -#define _CONVENTION_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "registers.h" -#include -#include -#include -#include -#include - -// ============================================================================ -// >> DataType_t -// ============================================================================ -enum DataType_t -{ - DATA_TYPE_VOID, - DATA_TYPE_BOOL, - DATA_TYPE_CHAR, - DATA_TYPE_UCHAR, - DATA_TYPE_SHORT, - DATA_TYPE_USHORT, - DATA_TYPE_INT, - DATA_TYPE_UINT, - DATA_TYPE_LONG, - DATA_TYPE_ULONG, - DATA_TYPE_LONG_LONG, - DATA_TYPE_ULONG_LONG, - DATA_TYPE_FLOAT, - DATA_TYPE_DOUBLE, - DATA_TYPE_POINTER, - DATA_TYPE_STRING, - DATA_TYPE_OBJECT -}; - -typedef struct DataTypeSized_s { - DataTypeSized_s() - { - type = DATA_TYPE_POINTER; - size = 0; - custom_register = None; - } - DataType_t type; - size_t size; - Register_t custom_register; -} DataTypeSized_t; - - -// ============================================================================ -// >> FUNCTIONS -// ============================================================================ -/* -Returns the size after applying alignment. - -@param : -The size that should be aligned. - -@param : -The alignment that should be used. -*/ -inline int Align(int size, int alignment) -{ - int unaligned = size % alignment; - if (unaligned == 0) - return size; - - return size + (alignment - unaligned); -} - -/* -Returns the size of a data type after applying alignment. - -@param : -The data type you would like to get the size of. - -@param : -The alignment that should be used. -*/ -inline size_t GetDataTypeSize(DataTypeSized_t type, int iAlignment=4) -{ - switch(type.type) - { - case DATA_TYPE_VOID: return 0; - case DATA_TYPE_BOOL: return Align(sizeof(bool), iAlignment); - case DATA_TYPE_CHAR: return Align(sizeof(char), iAlignment); - case DATA_TYPE_UCHAR: return Align(sizeof(unsigned char), iAlignment); - case DATA_TYPE_SHORT: return Align(sizeof(short), iAlignment); - case DATA_TYPE_USHORT: return Align(sizeof(unsigned short), iAlignment); - case DATA_TYPE_INT: return Align(sizeof(int), iAlignment); - case DATA_TYPE_UINT: return Align(sizeof(unsigned int), iAlignment); - case DATA_TYPE_LONG: return Align(sizeof(long), iAlignment); - case DATA_TYPE_ULONG: return Align(sizeof(unsigned long), iAlignment); - case DATA_TYPE_LONG_LONG: return Align(sizeof(long long), iAlignment); - case DATA_TYPE_ULONG_LONG: return Align(sizeof(unsigned long long), iAlignment); - case DATA_TYPE_FLOAT: return Align(sizeof(float), iAlignment); - case DATA_TYPE_DOUBLE: return Align(sizeof(double), iAlignment); - case DATA_TYPE_POINTER: return Align(sizeof(void *), iAlignment); - case DATA_TYPE_STRING: return Align(sizeof(char *), iAlignment); - case DATA_TYPE_OBJECT: return type.size; - default: puts("Unknown data type."); - } - return 0; -} - -// ============================================================================ -// >> CLASSES -// ============================================================================ -/* -This is the base class for every calling convention. Inherit from this class -to create your own calling convention. -*/ -class ICallingConvention -{ -public: - /* - Initializes the calling convention. - - @param : - A list of DataType_t objects, which define the arguments of the function. - - @param : - The return type of the function. - */ - ICallingConvention(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4) - { - m_vecArgTypes = std::move(vecArgTypes); - - for (size_t i=0; i < m_vecArgTypes.size(); i++) - { - DataTypeSized_t &type = m_vecArgTypes[i]; - if (!type.size) - type.size = GetDataTypeSize(type, iAlignment); - } - m_returnType = returnType; - if (!m_returnType.size) - m_returnType.size = GetDataTypeSize(m_returnType, iAlignment); - m_iAlignment = iAlignment; - } - - virtual ~ICallingConvention() - { - } - - /* - This should return a list of Register_t values. These registers will be - saved for later access. - */ - virtual std::vector GetRegisters() = 0; - - /* - Returns the number of bytes that should be added to the stack to clean up. - */ - virtual int GetPopSize() = 0; - - virtual int GetArgStackSize() = 0; - virtual void** GetStackArgumentPtr(CRegisters* pRegisters) = 0; - - /* - Returns the number of bytes for the buffer to store all the arguments that are passed in a register in. - */ - virtual int GetArgRegisterSize() = 0; - - /* - Returns a pointer to the argument at the given index. - - @param : - The index of the argument. - - @param : - A snapshot of all saved registers. - */ - virtual void* GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters) = 0; - - /* - */ - virtual void ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr) = 0; - - /* - Returns a pointer to the return value. - - @param : - A snapshot of all saved registers. - */ - virtual void* GetReturnPtr(CRegisters* pRegisters) = 0; - - /* - */ - virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr) = 0; - - /* - Save the return value in a seperate buffer, so we can restore it after calling the original function. - - @param : - A snapshot of all saved registers. - */ - virtual void SaveReturnValue(CRegisters* pRegisters) - { - std::unique_ptr pSavedReturnValue = std::make_unique(m_returnType.size); - memcpy(pSavedReturnValue.get(), GetReturnPtr(pRegisters), m_returnType.size); - m_pSavedReturnBuffers.push_back(std::move(pSavedReturnValue)); - } - - virtual void RestoreReturnValue(CRegisters* pRegisters) - { - uint8_t* pSavedReturnValue = m_pSavedReturnBuffers.back().get(); - memcpy(GetReturnPtr(pRegisters), pSavedReturnValue, m_returnType.size); - ReturnPtrChanged(pRegisters, pSavedReturnValue); - m_pSavedReturnBuffers.pop_back(); - } - - /* - Save the value of arguments in a seperate buffer for the post callback. - Compiler optimizations might cause the registers or stack space to be reused - and overwritten during function execution if the value isn't needed anymore - at some point. This leads to different values in the post hook. - - @param : - A snapshot of all saved registers. - */ - virtual void SaveCallArguments(CRegisters* pRegisters) - { - int size = GetArgStackSize() + GetArgRegisterSize(); - std::unique_ptr pSavedCallArguments = std::make_unique(size); - size_t offset = 0; - for (unsigned int i = 0; i < m_vecArgTypes.size(); i++) { - DataTypeSized_t &type = m_vecArgTypes[i]; - memcpy((void *)((uintptr_t)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size); - offset += type.size; - } - m_pSavedCallArguments.push_back(std::move(pSavedCallArguments)); - } - - virtual void RestoreCallArguments(CRegisters* pRegisters) - { - uint8_t *pSavedCallArguments = m_pSavedCallArguments.back().get(); - size_t offset = 0; - for (size_t i = 0; i < m_vecArgTypes.size(); i++) { - DataTypeSized_t &type = m_vecArgTypes[i]; - memcpy(GetArgumentPtr((unsigned int)i, pRegisters), (void *)((uintptr_t)pSavedCallArguments + offset), type.size); - offset += type.size; - } - m_pSavedCallArguments.pop_back(); - } - -public: - std::vector m_vecArgTypes; - DataTypeSized_t m_returnType; - int m_iAlignment; - // Save the return in case we call the original function and want to override the return again. - std::vector> m_pSavedReturnBuffers; - // Save call arguments in case the function reuses the space and overwrites the values for the post hook. - std::vector> m_pSavedCallArguments; -}; - -#endif // _CONVENTION_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86GccCdecl.h b/extensions/dhooks/DynamicHooks/conventions/x86GccCdecl.h deleted file mode 100644 index 94c5b124f6..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86GccCdecl.h +++ /dev/null @@ -1,48 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_GCC_CDECL_H -#define _X86_GCC_CDECL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsCdecl.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -typedef x86MsCdecl x86GccCdecl; - - -#endif // _X86_GCC_CDECL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.cpp b/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.cpp deleted file mode 100644 index 10f12503a5..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86GccThiscall.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ - -x86GccThiscall::x86GccThiscall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - x86GccCdecl(vecArgTypes, returnType, iAlignment) -{ - // Always add the |this| pointer. - DataTypeSized_t type; - type.type = DATA_TYPE_POINTER; - type.size = GetDataTypeSize(type, iAlignment); - type.custom_register = None; - m_vecArgTypes.insert(m_vecArgTypes.begin(), type); -} - -x86GccThiscall::~x86GccThiscall() -{ -} - -int x86GccThiscall::GetArgStackSize() -{ - // Remove the this pointer from the arguments size. - DataTypeSized_t type; - type.type = DATA_TYPE_POINTER; - return x86GccCdecl::GetArgStackSize() - GetDataTypeSize(type, m_iAlignment); -} - -void** x86GccThiscall::GetStackArgumentPtr(CRegisters* pRegisters) -{ - // Skip return address and this pointer. - DataTypeSized_t type; - type.type = DATA_TYPE_POINTER; - return (void **)(pRegisters->m_esp->GetValue() + 4 + GetDataTypeSize(type, m_iAlignment)); -} - -void x86GccThiscall::SaveCallArguments(CRegisters* pRegisters) -{ - // Count the this pointer. - int size = x86GccCdecl::GetArgStackSize() + GetArgRegisterSize(); - std::unique_ptr pSavedCallArguments = std::make_unique(size); - size_t offset = 0; - for (size_t i = 0; i < m_vecArgTypes.size(); i++) { - DataTypeSized_t &type = m_vecArgTypes[i]; - memcpy((void *)((unsigned long)pSavedCallArguments.get() + offset), GetArgumentPtr(i, pRegisters), type.size); - offset += type.size; - } - m_pSavedCallArguments.push_back(std::move(pSavedCallArguments)); -} diff --git a/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.h b/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.h deleted file mode 100644 index c123796ff7..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86GccThiscall.h +++ /dev/null @@ -1,59 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_GCC_THISCALL_H -#define _X86_GCC_THISCALL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86GccCdecl.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -// |this| pointer is always passed as implicit first argument on the stack. -class x86GccThiscall: public x86GccCdecl -{ -public: - x86GccThiscall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment = 4); - virtual ~x86GccThiscall(); - - virtual int GetArgStackSize(); - virtual void** GetStackArgumentPtr(CRegisters* pRegisters); - - virtual void SaveCallArguments(CRegisters* pRegisters); -}; - -#endif // _X86_GCC_THISCALL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.cpp b/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.cpp deleted file mode 100644 index 58e1dbfd9f..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsCdecl.h" -#include - - -// ============================================================================ -// >> x86MsCdecl -// ============================================================================ -x86MsCdecl::x86MsCdecl(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - ICallingConvention(vecArgTypes, returnType, iAlignment) -{ - if (m_returnType.size > 4) - { - m_pReturnBuffer = malloc(m_returnType.size); - } - else - { - m_pReturnBuffer = NULL; - } -} - -x86MsCdecl::~x86MsCdecl() -{ - if (m_pReturnBuffer) - { - free(m_pReturnBuffer); - } -} - -std::vector x86MsCdecl::GetRegisters() -{ - std::vector registers; - - registers.push_back(ESP); - - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - { - registers.push_back(ST0); - } - else - { - registers.push_back(EAX); - if (m_pReturnBuffer) - { - registers.push_back(EDX); - } - } - - // Save all the custom calling convention registers as well. - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - continue; - - // TODO: Make sure the list is unique? Set? - registers.push_back(m_vecArgTypes[i].custom_register); - } - - return registers; -} - -int x86MsCdecl::GetPopSize() -{ - return 0; -} - -int x86MsCdecl::GetArgStackSize() -{ - int iArgStackSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - iArgStackSize += m_vecArgTypes[i].size; - } - - return iArgStackSize; -} - -void** x86MsCdecl::GetStackArgumentPtr(CRegisters* pRegisters) -{ - return (void **)(pRegisters->m_esp->GetValue() + 4); -} - -int x86MsCdecl::GetArgRegisterSize() -{ - int iArgRegisterSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register != None) - iArgRegisterSize += m_vecArgTypes[i].size; - } - - return iArgRegisterSize; -} - -void* x86MsCdecl::GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters) -{ - if (iIndex >= m_vecArgTypes.size()) - return NULL; - - // Check if this argument was passed in a register. - if (m_vecArgTypes[iIndex].custom_register != None) - { - CRegister *pRegister = pRegisters->GetRegister(m_vecArgTypes[iIndex].custom_register); - if (!pRegister) - return NULL; - - return pRegister->m_pAddress; - } - - // Skip return address. - size_t iOffset = 4; - for(unsigned int i=0; i < iIndex; i++) - { - if (m_vecArgTypes[i].custom_register == None) - iOffset += m_vecArgTypes[i].size; - } - - return (void *) (pRegisters->m_esp->GetValue() + iOffset); -} - -void x86MsCdecl::ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr) -{ -} - -void* x86MsCdecl::GetReturnPtr(CRegisters* pRegisters) -{ - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - return pRegisters->m_st0->m_pAddress; - - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(m_pReturnBuffer, pRegisters->m_eax, 4); - memcpy((void *) ((unsigned long) m_pReturnBuffer + 4), pRegisters->m_edx, 4); - return m_pReturnBuffer; - } - - return pRegisters->m_eax->m_pAddress; -} - -void x86MsCdecl::ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr) -{ - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(pRegisters->m_eax, m_pReturnBuffer, 4); - memcpy(pRegisters->m_edx, (void *) ((unsigned long) m_pReturnBuffer + 4), 4); - } -} \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.h b/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.h deleted file mode 100644 index 37b8aba5f8..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsCdecl.h +++ /dev/null @@ -1,88 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_MS_CDECL_H -#define _X86_MS_CDECL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "../convention.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -/* -Source: DynCall manual and Windows docs - -Registers: - - eax = return value - - edx = return value - - esp = stack pointer - - st0 = floating point return value - -Parameter passing: - - stack parameter order: right-to-left - - caller cleans up the stack - - all arguments are pushed onto the stack - - alignment: 4 bytes - -Return values: - - return values of pointer or intergral type (<= 32 bits) are returned via the eax register - - integers > 32 bits are returned via the eax and edx registers - - floating pointer types are returned via the st0 register -*/ -class x86MsCdecl: public ICallingConvention -{ -public: - x86MsCdecl(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4); - virtual ~x86MsCdecl(); - - virtual std::vector GetRegisters(); - virtual int GetPopSize(); - virtual int GetArgStackSize(); - virtual void** GetStackArgumentPtr(CRegisters* pRegisters); - virtual int GetArgRegisterSize(); - - virtual void* GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters); - virtual void ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr); - - virtual void* GetReturnPtr(CRegisters* pRegisters); - virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr); - -private: - void* m_pReturnBuffer; -}; - -#endif // _X86_MS_CDECL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.cpp b/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.cpp deleted file mode 100644 index ccb30392fa..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsFastcall.h" - - -// ============================================================================ -// >> x86MsFastcall -// ============================================================================ -x86MsFastcall::x86MsFastcall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - x86MsStdcall(vecArgTypes, returnType, iAlignment) -{ - // First argument is passed in ecx. - if (m_vecArgTypes.size() > 0) { - DataTypeSized_t &type = m_vecArgTypes[0]; - // Don't force the register on the user. - // Why choose Fastcall if you set your own argument registers though.. - if (type.custom_register == None) - type.custom_register = ECX; - } - - // Second argument is passed in edx. - if (m_vecArgTypes.size() > 1) { - DataTypeSized_t &type = m_vecArgTypes[1]; - if (type.custom_register == None) - type.custom_register = EDX; - } -} diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.h b/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.h deleted file mode 100644 index 4b07449456..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsFastcall.h +++ /dev/null @@ -1,72 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_MS_FASTCALL_H -#define _X86_MS_FASTCALL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsStdcall.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -/* -Source: DynCall manual and Windows docs - -Registers: - - eax = return value - - edx = return value - - esp = stack pointer - - st0 = floating point return value - -Parameter passing: - - first parameter in ecx, second parameter in edx, rest on the stack - - stack parameter order: right-to-left - - callee cleans up the stack - - alignment: 4 bytes - -Return values: - - return values of pointer or intergral type (<= 32 bits) are returned via the eax register - - integers > 32 bits are returned via the eax and edx registers - - floating pointer types are returned via the st0 register -*/ -class x86MsFastcall: public x86MsStdcall -{ -public: - x86MsFastcall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4); -}; - -#endif // _X86_MS_FASTCALL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.cpp b/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.cpp deleted file mode 100644 index e61cf83de8..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsStdcall.h" -#include - - -// ============================================================================ -// >> x86MsStdcall -// ============================================================================ -x86MsStdcall::x86MsStdcall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - ICallingConvention(vecArgTypes, returnType, iAlignment) -{ - if (m_returnType.size > 4) - { - m_pReturnBuffer = malloc(m_returnType.size); - } - else - { - m_pReturnBuffer = NULL; - } -} - -x86MsStdcall::~x86MsStdcall() -{ - if (m_pReturnBuffer) - { - free(m_pReturnBuffer); - } -} - -std::vector x86MsStdcall::GetRegisters() -{ - std::vector registers; - - registers.push_back(ESP); - - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - { - registers.push_back(ST0); - } - else - { - registers.push_back(EAX); - if (m_pReturnBuffer) - { - registers.push_back(EDX); - } - } - - // Save all the custom calling convention registers as well. - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - continue; - - // TODO: Make sure the list is unique? Set? - registers.push_back(m_vecArgTypes[i].custom_register); - } - - return registers; -} - -int x86MsStdcall::GetPopSize() -{ - int iPopSize = 0; - - for(size_t i=0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - iPopSize += m_vecArgTypes[i].size; - } - - return iPopSize; -} - -int x86MsStdcall::GetArgStackSize() -{ - int iArgStackSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - iArgStackSize += m_vecArgTypes[i].size; - } - - return iArgStackSize; -} - -void** x86MsStdcall::GetStackArgumentPtr(CRegisters* pRegisters) -{ - return (void **)(pRegisters->m_esp->GetValue() + 4); -} - -int x86MsStdcall::GetArgRegisterSize() -{ - int iArgRegisterSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register != None) - iArgRegisterSize += m_vecArgTypes[i].size; - } - - return iArgRegisterSize; -} - -void* x86MsStdcall::GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters) -{ - if (iIndex >= m_vecArgTypes.size()) - return NULL; - - // Check if this argument was passed in a register. - if (m_vecArgTypes[iIndex].custom_register != None) - { - CRegister *pRegister = pRegisters->GetRegister(m_vecArgTypes[iIndex].custom_register); - if (!pRegister) - return NULL; - - return pRegister->m_pAddress; - } - - size_t iOffset = 4; - for (unsigned int i = 0; i < iIndex; i++) - { - if (m_vecArgTypes[i].custom_register == None) - iOffset += m_vecArgTypes[i].size; - } - - return (void *)(pRegisters->m_esp->GetValue() + iOffset); -} - -void x86MsStdcall::ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr) -{ -} - -void* x86MsStdcall::GetReturnPtr(CRegisters* pRegisters) -{ - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - return pRegisters->m_st0->m_pAddress; - - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(m_pReturnBuffer, pRegisters->m_eax, 4); - memcpy((void *) ((unsigned long) m_pReturnBuffer + 4), pRegisters->m_edx, 4); - return m_pReturnBuffer; - } - - return pRegisters->m_eax->m_pAddress; -} - -void x86MsStdcall::ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr) -{ - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(pRegisters->m_eax, m_pReturnBuffer, 4); - memcpy(pRegisters->m_edx, (void *) ((unsigned long) m_pReturnBuffer + 4), 4); - } -} \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.h b/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.h deleted file mode 100644 index ed25b32736..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsStdcall.h +++ /dev/null @@ -1,88 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_MS_STDCALL_H -#define _X86_MS_STDCALL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "../convention.h" - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -/* -Source: DynCall manual and Windows docs - -Registers: - - eax = return value - - edx = return value - - esp = stack pointer - - st0 = floating point return value - -Parameter passing: - - stack parameter order: right-to-left - - callee cleans up the stack - - all arguments are pushed onto the stack - - alignment: 4 bytes - -Return values: - - return values of pointer or intergral type (<= 32 bits) are returned via the eax register - - integers > 32 bits are returned via the eax and edx registers - - floating pointer types are returned via the st0 register -*/ -class x86MsStdcall: public ICallingConvention -{ -public: - x86MsStdcall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4); - virtual ~x86MsStdcall(); - - virtual std::vector GetRegisters(); - virtual int GetPopSize(); - virtual int GetArgStackSize(); - virtual void** GetStackArgumentPtr(CRegisters* pRegisters); - virtual int GetArgRegisterSize(); - - virtual void* GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters); - virtual void ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr); - - virtual void* GetReturnPtr(CRegisters* pRegisters); - virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr); - -private: - void* m_pReturnBuffer; -}; - -#endif // _X86_MS_STDCALL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.cpp b/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.cpp deleted file mode 100644 index 9c01b66094..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86MsThiscall.h" -#include - - -// ============================================================================ -// >> x86MsThiscall -// ============================================================================ -x86MsThiscall::x86MsThiscall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - ICallingConvention(vecArgTypes, returnType, iAlignment) -{ - if (m_returnType.size > 4) - { - m_pReturnBuffer = malloc(m_returnType.size); - } - else - { - m_pReturnBuffer = NULL; - } -} - -x86MsThiscall::~x86MsThiscall() -{ - if (m_pReturnBuffer) - { - free(m_pReturnBuffer); - } -} - -std::vector x86MsThiscall::GetRegisters() -{ - std::vector registers; - - registers.push_back(ESP); - // TODO: Allow custom this register. - registers.push_back(ECX); - - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - { - registers.push_back(ST0); - } - else - { - registers.push_back(EAX); - if (m_pReturnBuffer) - { - registers.push_back(EDX); - } - } - - // Save all the custom calling convention registers as well. - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - continue; - - // TODO: Make sure the list is unique? Set? - registers.push_back(m_vecArgTypes[i].custom_register); - } - - return registers; -} - -int x86MsThiscall::GetPopSize() -{ - // This pointer. - // FIXME LINUX - //int iPopSize = GetDataTypeSize(DATA_TYPE_POINTER, m_iAlignment); - int iPopSize = 0; - - for(size_t i=0; i < m_vecArgTypes.size(); i++) - { - // Only pop arguments that are actually on the stack. - if (m_vecArgTypes[i].custom_register == None) - iPopSize += m_vecArgTypes[i].size; - } - - return iPopSize; -} - -int x86MsThiscall::GetArgStackSize() -{ - int iArgStackSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register == None) - iArgStackSize += m_vecArgTypes[i].size; - } - - return iArgStackSize; -} - -void** x86MsThiscall::GetStackArgumentPtr(CRegisters* pRegisters) -{ - return (void **)(pRegisters->m_esp->GetValue() + 4); -} - -int x86MsThiscall::GetArgRegisterSize() -{ - int iArgRegisterSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register != None) - iArgRegisterSize += m_vecArgTypes[i].size; - } - - return iArgRegisterSize; -} - -void* x86MsThiscall::GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters) -{ - if (iIndex == 0) - { - // TODO: Allow custom this register. - return pRegisters->m_ecx->m_pAddress; - } - - // The this pointer isn't explicitly defined as an argument. - iIndex--; - - if (iIndex >= m_vecArgTypes.size()) - return NULL; - - // Check if this argument was passed in a register. - if (m_vecArgTypes[iIndex].custom_register != None) - { - CRegister *pRegister = pRegisters->GetRegister(m_vecArgTypes[iIndex].custom_register); - if (!pRegister) - return NULL; - - return pRegister->m_pAddress; - } - - size_t iOffset = 4; - for(unsigned int i=0; i < iIndex; i++) - { - if (m_vecArgTypes[i].custom_register == None) - iOffset += m_vecArgTypes[i].size; - } - - return (void *) (pRegisters->m_esp->GetValue() + iOffset); -} - -void x86MsThiscall::ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr) -{ -} - -void* x86MsThiscall::GetReturnPtr(CRegisters* pRegisters) -{ - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - return pRegisters->m_st0->m_pAddress; - - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(m_pReturnBuffer, pRegisters->m_eax, 4); - memcpy((void *) ((unsigned long) m_pReturnBuffer + 4), pRegisters->m_edx, 4); - return m_pReturnBuffer; - } - - return pRegisters->m_eax->m_pAddress; -} - -void x86MsThiscall::ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr) -{ - if (m_pReturnBuffer) - { - // First half in eax, second half in edx - memcpy(pRegisters->m_eax, m_pReturnBuffer, 4); - memcpy(pRegisters->m_edx, (void *) ((unsigned long) m_pReturnBuffer + 4), 4); - } -} - -void x86MsThiscall::SaveCallArguments(CRegisters* pRegisters) -{ - // Account for implicit this-pointer in ecx. - int size = GetArgStackSize() + GetArgRegisterSize() + sizeof(void *); - std::unique_ptr pSavedCallArguments = std::make_unique(size); - memcpy(pSavedCallArguments.get(), GetArgumentPtr(0, pRegisters), sizeof(void *)); - - size_t offset = sizeof(void *); - for (size_t i = 0; i < m_vecArgTypes.size(); i++) { - DataTypeSized_t &type = m_vecArgTypes[i]; - memcpy((void *)((unsigned long)pSavedCallArguments.get() + offset), GetArgumentPtr(i + 1, pRegisters), type.size); - offset += type.size; - } - m_pSavedCallArguments.push_back(std::move(pSavedCallArguments)); -} - -void x86MsThiscall::RestoreCallArguments(CRegisters* pRegisters) -{ - uint8_t* pSavedCallArguments = m_pSavedCallArguments.back().get(); - memcpy(GetArgumentPtr(0, pRegisters), pSavedCallArguments, sizeof(void *)); - - size_t offset = sizeof(void *); - for (size_t i = 0; i < m_vecArgTypes.size(); i++) { - DataTypeSized_t &type = m_vecArgTypes[i]; - memcpy(GetArgumentPtr(i + 1, pRegisters), (void *)((unsigned long)pSavedCallArguments + offset), type.size); - offset += type.size; - } - m_pSavedCallArguments.pop_back(); -} diff --git a/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.h b/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.h deleted file mode 100644 index b28e061daf..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86MsThiscall.h +++ /dev/null @@ -1,93 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _X86_MS_THISCALL_H -#define _X86_MS_THISCALL_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "../convention.h" -#include - - -// ============================================================================ -// >> CLASSES -// ============================================================================ -/* -Source: DynCall manual and Windows docs - -Registers: - - eax = return value - - ecx = this pointer - - edx = return value - - esp = stack pointer - - st0 = floating point return value - -Parameter passing: - - stack parameter order: right-to-left - - callee cleans up the stack - - all other arguments are pushed onto the stack - - alignment: 4 bytes - -Return values: - - return values of pointer or intergral type (<= 32 bits) are returned via the eax register - - integers > 32 bits are returned via the eax and edx registers - - floating pointer types are returned via the st0 register -*/ -class x86MsThiscall: public ICallingConvention -{ -public: - x86MsThiscall(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment=4); - virtual ~x86MsThiscall(); - - virtual std::vector GetRegisters(); - virtual int GetPopSize(); - virtual int GetArgStackSize(); - virtual void** GetStackArgumentPtr(CRegisters* pRegisters); - virtual int GetArgRegisterSize(); - - virtual void* GetArgumentPtr(unsigned int iIndex, CRegisters* pRegisters); - virtual void ArgumentPtrChanged(unsigned int iIndex, CRegisters* pRegisters, void* pArgumentPtr); - - virtual void* GetReturnPtr(CRegisters* pRegisters); - virtual void ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr); - - virtual void SaveCallArguments(CRegisters* pRegisters); - virtual void RestoreCallArguments(CRegisters* pRegisters); - -private: - void* m_pReturnBuffer; -}; - -#endif // _X86_MS_THISCALL_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.cpp b/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.cpp deleted file mode 100644 index d371d16cc8..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks-x86_64 -* Copyright (C) 2024 Benoist "Kenzzer" André. All rights reserved. -* Copyright (C) 2024 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "x86_64MicrosoftDefault.h" -#include - -// ============================================================================ -// >> CLASSES -// ============================================================================ -x86_64MicrosoftDefault::x86_64MicrosoftDefault(std::vector &vecArgTypes, DataTypeSized_t returnType, int iAlignment) : - ICallingConvention(vecArgTypes, returnType, iAlignment), - m_stackArgs(0) -{ - const Register_t params_reg[] = { RCX, RDX, R8, R9 }; - const Register_t params_floatreg[] = { XMM0, XMM1, XMM2, XMM3 }; - //const char* regNames[] = { "RCX or XMM0", "RDX or XMM1", "R8 or XMM2", "R9 or XMM3"}; - const std::uint8_t num_reg = sizeof(params_reg) / sizeof(Register_t); - - bool used_reg[] = { false, false, false, false }; - - // Figure out if any register has been used - auto retreg = m_returnType.custom_register; - used_reg[0] = (retreg == RCX || retreg == XMM0); - used_reg[1] = (retreg == RDX || retreg == XMM1); - used_reg[2] = (retreg == R8 || retreg == XMM2); - used_reg[3] = (retreg == R9 || retreg == XMM3); - - for (const auto& arg : m_vecArgTypes) { - int reg_index = -1; - if (arg.custom_register == RCX || arg.custom_register == XMM0) { - reg_index = 0; - } else if (arg.custom_register == RDX || arg.custom_register == XMM1) { - reg_index = 1; - } else if (arg.custom_register == R8 || arg.custom_register == XMM2) { - reg_index = 2; - } else if (arg.custom_register == R9 || arg.custom_register == XMM3) { - reg_index = 3; - } - - if (reg_index != -1) { - if (used_reg[reg_index]) { - puts("Argument register is used twice, or shared with return"); - return; - } - used_reg[reg_index] = true; - } - } - - // Special return type - if (m_returnType.custom_register == None && m_returnType.type == DATA_TYPE_OBJECT && - // If size unknown, or doesn't fit on 1, 2, 4 or 8 bytes - // special place must have been allocated for it - (m_returnType.size == 0 - || m_returnType.size == 3 - || m_returnType.size == 5 - || m_returnType.size == 6 - || m_returnType.size == 7 - || m_returnType.size > 8)) { - for (std::uint8_t i = 0; i < num_reg && m_returnType.custom_register == None; i++) { - if (!used_reg[i]) { - m_returnType.custom_register = params_reg[i]; - used_reg[i] = true; - } - // Couldn't find a free register, this is a big problem - if (m_returnType.custom_register == None) { - puts("Missing free register for return pointer"); - return; - } - } - } - - for (auto& arg : m_vecArgTypes) { - if (arg.custom_register == None) { - for (std::uint8_t i = 0; i < num_reg && arg.custom_register == None; i++) { - // Register is unused assign it - if (!used_reg[i]) { - arg.custom_register = (arg.type == DATA_TYPE_FLOAT || arg.type == DATA_TYPE_DOUBLE) ? params_floatreg[i] : params_reg[i]; - used_reg[i] = true; - } - } - // Couldn't find a free register, it's therefore a stack parameter - if (arg.custom_register == None) { - m_stackArgs++; - } - } - } -} - -std::vector x86_64MicrosoftDefault::GetRegisters() -{ - std::vector registers; - - registers.push_back(RSP); - - if (m_returnType.custom_register != None) - { - registers.push_back(m_returnType.custom_register); - } - else if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - { - registers.push_back(XMM0); - } - else - { - registers.push_back(RAX); - } - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - auto reg = m_vecArgTypes[i].custom_register; - if (reg == None) - { - continue; - } - registers.push_back(m_vecArgTypes[i].custom_register); - } - - return registers; -} - -int x86_64MicrosoftDefault::GetPopSize() -{ - // Clean-up is caller handled - return 0; -} - -int x86_64MicrosoftDefault::GetArgStackSize() -{ - // Shadow space (32 bytes) + 8 bytes * amount of stack arguments - return 32 + 8 * m_stackArgs; -} - -void** x86_64MicrosoftDefault::GetStackArgumentPtr(CRegisters* registers) -{ - // Skip shadow space + return address - return (void **)(registers->m_rsp->GetValue() + 8 + 32); -} - -int x86_64MicrosoftDefault::GetArgRegisterSize() -{ - int argRegisterSize = 0; - - for (size_t i = 0; i < m_vecArgTypes.size(); i++) - { - if (m_vecArgTypes[i].custom_register != None) - { - // It doesn't matter, it's always 8 bytes or less - argRegisterSize += 8; - } - } - - return argRegisterSize; -} - -void* x86_64MicrosoftDefault::GetArgumentPtr(unsigned int index, CRegisters* registers) -{ - //g_pSM->LogMessage(myself, "Retrieving argument %d (max args %d) registers %p", index, m_vecArgTypes.size(), registers); - if (index >= m_vecArgTypes.size()) - { - //g_pSM->LogMessage(myself, "Not enough arguments"); - return nullptr; - } - - // Check if this argument was passed in a register. - if (m_vecArgTypes[index].custom_register != None) - { - CRegister* reg = registers->GetRegister(m_vecArgTypes[index].custom_register); - if (!reg) - { - //g_pSM->LogMessage(myself, "Register does not exit"); - return nullptr; - } - //g_pSM->LogMessage(myself, "Register arg %d", m_vecArgTypes[index].custom_register); - return reg->m_pAddress; - } - - // Return address + shadow space - size_t offset = 8 + 32; - for (unsigned int i = 0; i < index; i++) - { - if (m_vecArgTypes[i].custom_register == None) - { - // No matter what, the stack is allocated in slices of 8 bytes - offset += 8; - } - } - return (void *) (registers->m_rsp->GetValue() + offset); -} - -void x86_64MicrosoftDefault::ArgumentPtrChanged(unsigned int index, CRegisters* registers, void* argumentPtr) -{ -} - -void* x86_64MicrosoftDefault::GetReturnPtr(CRegisters* registers) -{ - // Custom return value register - if (m_returnType.custom_register != None) - { - return registers->GetRegister(m_returnType.custom_register)->m_pAddress; - } - - if (m_returnType.type == DATA_TYPE_FLOAT || m_returnType.type == DATA_TYPE_DOUBLE) - { - // Floating point register - return registers->m_xmm0->m_pAddress; - } - return registers->m_rax->m_pAddress; -} - -void x86_64MicrosoftDefault::ReturnPtrChanged(CRegisters* pRegisters, void* pReturnPtr) -{ -} - -void x86_64MicrosoftDefault::SaveReturnValue(CRegisters* registers) -{ - // It doesn't matter what the return value is, it will always be fitting on 8 bytes (or less) - std::unique_ptr savedReturn = std::make_unique(8); - memcpy(savedReturn.get(), GetReturnPtr(registers), 8); - m_pSavedReturnBuffers.push_back(std::move(savedReturn)); -} - -void x86_64MicrosoftDefault::RestoreReturnValue(CRegisters* registers) -{ - // Like stated in SaveReturnValue, it will always fit within 8 bytes - // the actual underlining type does not matter - uint8_t* savedReturn = m_pSavedReturnBuffers.back().get(); - memcpy(GetReturnPtr(registers), savedReturn, 8); - ReturnPtrChanged(registers, savedReturn); - m_pSavedReturnBuffers.pop_back(); -} - -void x86_64MicrosoftDefault::SaveCallArguments(CRegisters* registers) -{ - int size = GetArgStackSize() + GetArgRegisterSize(); - std::unique_ptr savedCallArguments = std::make_unique(size); - size_t offset = 0; - for (unsigned int i = 0; i < m_vecArgTypes.size(); i++) { - // Doesn't matter the type, it will always be within 8 bytes - memcpy((void *)((uintptr_t)savedCallArguments.get() + offset), GetArgumentPtr(i, registers), 8); - offset += 8; - } - m_pSavedCallArguments.push_back(std::move(savedCallArguments)); -} - -void x86_64MicrosoftDefault::RestoreCallArguments(CRegisters* registers) -{ - uint8_t *savedCallArguments = m_pSavedCallArguments.back().get(); - size_t offset = 0; - for (size_t i = 0; i < m_vecArgTypes.size(); i++) { - // Doesn't matter the type, it will always be within 8 bytes - memcpy(GetArgumentPtr((unsigned int)i, registers), (void *)((uintptr_t)savedCallArguments + offset), 8); - offset += 8; - } - m_pSavedCallArguments.pop_back(); -} \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.h b/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.h deleted file mode 100644 index ade067503d..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86_64MicrosoftDefault.h +++ /dev/null @@ -1,68 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks-x86_64 -* Copyright (C) 2024 Benoist "Kenzzer" André. All rights reserved. -* Copyright (C) 2024 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef _X86_64_MICROSOFT_DEFAULT_H -#define _X86_64_MICROSOFT_DEFAULT_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "../convention.h" - -// ============================================================================ -// >> CLASSES -// ============================================================================ -class x86_64MicrosoftDefault : public ICallingConvention -{ -public: - x86_64MicrosoftDefault(std::vector& vecArgTypes, DataTypeSized_t returnType, int iAlignment = 8); - virtual ~x86_64MicrosoftDefault() = default; - - virtual std::vector GetRegisters() override; - virtual int GetPopSize() override; - - virtual int GetArgStackSize() override; - virtual void** GetStackArgumentPtr(CRegisters* registers) override; - - virtual int GetArgRegisterSize() override; - - virtual void* GetArgumentPtr(unsigned int index, CRegisters* registers) override; - virtual void ArgumentPtrChanged(unsigned int index, CRegisters* registers, void* argumentPtr) override; - - virtual void* GetReturnPtr(CRegisters* registers) override; - virtual void ReturnPtrChanged(CRegisters* registers, void* returnPtr) override; - - virtual void SaveReturnValue(CRegisters* registers) override; - virtual void RestoreReturnValue(CRegisters* registers) override; - - virtual void SaveCallArguments(CRegisters* pRegisters) override; - virtual void RestoreCallArguments(CRegisters* pRegisters) override; - -protected: - std::uint32_t m_stackArgs; -}; - -#endif // _X86_64_MICROSOFT_DEFAULT_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.cpp b/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.cpp deleted file mode 100644 index 10b909f814..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks-x86_64 -* Copyright (C) 2024 Benoist "Kenzzer" André. All rights reserved. -* Copyright (C) 2024 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -*/ \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.h b/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.h deleted file mode 100644 index 10b909f814..0000000000 --- a/extensions/dhooks/DynamicHooks/conventions/x86_64SystemVDefault.h +++ /dev/null @@ -1,25 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks-x86_64 -* Copyright (C) 2024 Benoist "Kenzzer" André. All rights reserved. -* Copyright (C) 2024 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -*/ \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/hook.cpp b/extensions/dhooks/DynamicHooks/hook.cpp deleted file mode 100644 index 4454ea37f3..0000000000 --- a/extensions/dhooks/DynamicHooks/hook.cpp +++ /dev/null @@ -1,891 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "hook.h" -#include "extension.h" - -#ifdef DYNAMICHOOKS_x86_64 - -#else -#include -#include -#include -using namespace sp; -#endif - -// ============================================================================ -// >> DEFINITIONS -// ============================================================================ -#define JMP_SIZE 6 - - -// ============================================================================ -// >> CHook -// ============================================================================ -CHook::CHook(void* pFunc, ICallingConvention* pConvention) -{ - m_pFunc = pFunc; - m_pRegisters = new CRegisters(pConvention->GetRegisters()); - m_pCallingConvention = pConvention; - - if (!m_hookHandler.init()) - return; - - if (!m_RetAddr.init()) - return; - - CreateBridge(); - if (!m_pBridge) - return; - - auto result = safetyhook::InlineHook::create(pFunc, m_pBridge, safetyhook::InlineHook::Flags::StartDisabled); - if (!result) { - return; - } - - m_Hook = std::move(result.value()); - m_pTrampoline = m_Hook.original(); - - m_Hook.enable(); -} - -CHook::~CHook() -{ - if (m_Hook.enabled()) { - m_Hook.disable(); - } - - // x64 will free these in the m_bridge/m_postCallback destructors. -#ifndef DYNAMICHOOKS_x86_64 - if (m_pBridge) { - smutils->GetScriptingEngine()->FreePageMemory(m_pBridge); - smutils->GetScriptingEngine()->FreePageMemory(m_pNewRetAddr); - } -#endif - - delete m_pRegisters; - delete m_pCallingConvention; -} - -void CHook::AddCallback(HookType_t eHookType, HookHandlerFn* pCallback) -{ - if (!pCallback) - return; - - HookTypeMap::Insert i = m_hookHandler.findForAdd(eHookType); - if (!i.found()) { - HookHandlerSet set; - set.init(); - m_hookHandler.add(i, eHookType, std::move(set)); - } - - i->value.add(pCallback); -} - -void CHook::RemoveCallback(HookType_t eHookType, HookHandlerFn* pCallback) -{ - HookTypeMap::Result r = m_hookHandler.find(eHookType); - if (!r.found()) - return; - - r->value.removeIfExists(pCallback); -} - -bool CHook::IsCallbackRegistered(HookType_t eHookType, HookHandlerFn* pCallback) -{ - HookTypeMap::Result r = m_hookHandler.find(eHookType); - if (!r.found()) - return false; - - return r->value.has(pCallback); -} - -bool CHook::AreCallbacksRegistered() -{ - HookTypeMap::Result r = m_hookHandler.find(HOOKTYPE_PRE); - if (r.found() && r->value.elements() > 0) - return true; - - r = m_hookHandler.find(HOOKTYPE_POST); - if (r.found() && r->value.elements() > 0) - return true; - - return false; -} - -ReturnAction_t CHook::HookHandler(HookType_t eHookType) -{ - if (eHookType == HOOKTYPE_POST) - { - ReturnAction_t lastPreReturnAction = m_LastPreReturnAction.back(); - m_LastPreReturnAction.pop_back(); - if (lastPreReturnAction >= ReturnAction_Override) - m_pCallingConvention->RestoreReturnValue(m_pRegisters); - if (lastPreReturnAction < ReturnAction_Supercede) - m_pCallingConvention->RestoreCallArguments(m_pRegisters); - } - - ReturnAction_t returnAction = ReturnAction_Ignored; - HookTypeMap::Result r = m_hookHandler.find(eHookType); - if (!r.found()) - { - // Still save the arguments for the post hook even if there - // is no pre-handler registered. - if (eHookType == HOOKTYPE_PRE) - { - m_LastPreReturnAction.push_back(returnAction); - m_pCallingConvention->SaveCallArguments(m_pRegisters); - } - return returnAction; - } - - HookHandlerSet &callbacks = r->value; - for(HookHandlerSet::iterator it=callbacks.iter(); !it.empty(); it.next()) - { - ReturnAction_t result = ((HookHandlerFn) *it)(eHookType, this); - if (result > returnAction) - returnAction = result; - } - - if (eHookType == HOOKTYPE_PRE) - { - m_LastPreReturnAction.push_back(returnAction); - if (returnAction >= ReturnAction_Override) - m_pCallingConvention->SaveReturnValue(m_pRegisters); - if (returnAction < ReturnAction_Supercede) - m_pCallingConvention->SaveCallArguments(m_pRegisters); - } - - return returnAction; -} - -void* __cdecl CHook::GetReturnAddress(void* pESP) -{ - ReturnAddressMap::Result r = m_RetAddr.find(pESP); - assert(r.found()); - if (!r.found()) - { - smutils->LogError(myself, "FATAL: Failed to find return address of original function. Check the arguments and return type of your detour setup."); - return NULL; - } - - void *pRetAddr = r->value.back(); - r->value.pop_back(); - - // Clear the stack address from the cache now that we ran the last post hook. - if (r->value.empty()) - m_RetAddr.remove(r); - - return pRetAddr; -} - -void __cdecl CHook::SetReturnAddress(void* pRetAddr, void* pESP) -{ - ReturnAddressMap::Insert i = m_RetAddr.findForAdd(pESP); - if (!i.found()) - m_RetAddr.add(i, pESP, std::vector()); - - i->value.push_back(pRetAddr); -} - -#ifdef DYNAMICHOOKS_x86_64 -using namespace SourceHook::Asm; -SourceHook::CPageAlloc SourceHook::Asm::GenBuffer::ms_Allocator(16); - -void PrintFunc(const char* message) { - g_pSM->LogMessage(myself, message); -} - -void PrintDebug(x64JitWriter& jit, const char* message) { - // LogMessage has variadic parameters, this shouldn't be problem on x86_64 - // but paranoia calls for safety - /* - union { - void (*PrintFunc)(const char* message); - std::uint64_t address; - } func; - - func.PrintFunc = &PrintFunc; - - // Shadow space - MSVC_ONLY(jit.sub(rsp, 40)); - - MSVC_ONLY(jit.mov(rcx, reinterpret_cast(message))); - GCC_ONLY(jit.mov(rdi, reinterpret_cast(message))); - - jit.mov(rax, func.address); - jit.call(rax); - - // Free shadow space - MSVC_ONLY(jit.add(rsp, 40));*/ -} - -void _PrintRegs(std::uint64_t* rsp, int numregs) { - g_pSM->LogMessage(myself, "RSP - %p", rsp); - - for (int i = 0; i < numregs; i++) { - g_pSM->LogMessage(myself, "RSP[%d] - %llu", i, rsp[i]); - } -} - -void PrintRegisters(x64JitWriter& jit) { - /* - union { - void (*PrintRegs)(std::uint64_t* rsp, int numregs); - std::uint64_t address; - } func; - func.PrintRegs = &_PrintRegs; - // Rax is pushed twice to keep the stack aligned - jit.push(rax); - jit.push(rax); - jit.push(rcx); - jit.push(rdx); - jit.push(r8); - jit.push(r9); - - jit.mov(rcx, rsp); - jit.mov(rdx, 5); - jit.sub(rsp, 40); - jit.mov(rax, func.address); - jit.call(rax); - jit.add(rsp, 40); - - jit.pop(r9); - jit.pop(r8); - jit.pop(rdx); - jit.pop(rcx); - jit.pop(rax); - jit.pop(rax);*/ -} - -void CHook::CreateBridge() -{ - auto& jit = m_bridge; - - //jit.breakpoint(); - PrintRegisters(jit); - - // Save registers right away - Write_SaveRegisters(jit, HOOKTYPE_PRE); - - PrintDebug(jit, "Hook Called"); - - Write_ModifyReturnAddress(jit); - - // Call the pre-hook handler and jump to label_supercede if ReturnAction_Supercede was returned - Write_CallHandler(jit, HOOKTYPE_PRE); - - jit.cmp(rax, ReturnAction_Supercede); - - // Restore the previously saved registers, so any changes will be applied - Write_RestoreRegisters(jit, HOOKTYPE_PRE); - - jit.je(0x0); - std::int32_t jumpOff = jit.get_outputpos(); - - // Dump regs - PrintRegisters(jit); - - // Jump to the trampoline - jit.sub(rsp, 8); - jit.push(rax); - jit.mov(rax, reinterpret_cast(&m_pTrampoline)); - jit.mov(rax, rax()); - jit.mov(rsp(8), rax); - jit.pop(rax); - jit.retn(); - - // This code will be executed if a pre-hook returns ReturnAction_Supercede - jit.rewrite(jumpOff - sizeof(std::int32_t), jit.get_outputpos() - jumpOff); - - PrintDebug(jit, "Hook leave"); - - // Finally, return to the caller - // This will still call post hooks, but will skip the original function. - jit.retn(); - - // It's very important to only finalise the jit code creation here - // setting the memory to ReadExecute too early can create crashes - // as it changes the permissions of the whole memory page - m_pBridge = m_bridge.GetData(); - m_pNewRetAddr = m_postCallback.GetData(); - - m_bridge.SetRE(); - m_postCallback.SetRE(); -} - -void CHook::Write_ModifyReturnAddress(x64JitWriter& jit) -{ - // Store the return address in rax - jit.mov(rax, rsp()); - - // Save the original return address by using the current esp as the key. - // This should be unique until we have returned to the original caller. - union - { - void (__cdecl CHook::*SetReturnAddress)(void*, void*); - std::uint64_t address; - } func; - func.SetReturnAddress = &CHook::SetReturnAddress; - - // Shadow space 32 bytes + 8 bytes to keep it aligned on 16 bytes - MSVC_ONLY(jit.sub(rsp, 40)); - - // 1st param (this) - GCC_ONLY(jit.mov(rdi, reinterpret_cast(this))); - MSVC_ONLY(jit.mov(rcx, reinterpret_cast(this))); - - // 2nd parameter (return address) - GCC_ONLY(jit.mov(rsi, rax)); - MSVC_ONLY(jit.mov(rdx, rax)); - - // 3rd parameter (rsp) - GCC_ONLY(jit.lea(rdx, rsp())); - MSVC_ONLY(jit.lea(r8, rsp(40))); - - // Call SetReturnAddress - jit.mov(rax, func.address); - jit.call(rax); - - // Free shadow space - MSVC_ONLY(jit.add(rsp, 40)); - - // Override the return address. This is a redirect to our post-hook code - CreatePostCallback(); - jit.mov(rax, reinterpret_cast(&m_pNewRetAddr)); - jit.mov(rax, rax()); - jit.mov(rsp(), rax); -} - -void CHook::CreatePostCallback() -{ - auto& jit = m_postCallback; - - jit.sub(rsp, 8); - PrintRegisters(jit); - - // Save registers right away - Write_SaveRegisters(jit, HOOKTYPE_POST); - - PrintDebug(jit, "Hook post"); - PrintRegisters(jit); - - // Call the post-hook handler - Write_CallHandler(jit, HOOKTYPE_POST); - - // Restore the previously saved registers, so any changes will be applied - Write_RestoreRegisters(jit, HOOKTYPE_POST); - - // Get return address - union - { - void* (__cdecl CHook::*GetReturnAddress)(void*); - std::uint64_t address; - } func; - func.GetReturnAddress = &CHook::GetReturnAddress; - - // Shadow space 32 bytes + 8 bytes to keep it aligned on 16 bytes - MSVC_ONLY(jit.sub(rsp, 40)); - - // 1st param (this) - GCC_ONLY(jit.mov(rdi, reinterpret_cast(this))); - MSVC_ONLY(jit.mov(rcx, reinterpret_cast(this))); - - // 2n parameter (rsp) - GCC_ONLY(jit.lea(rsi, rsp())); - MSVC_ONLY(jit.lea(rdx, rsp(40))); - - // Call GetReturnAddress - jit.mov(rax, func.address); - jit.call(rax); - - // Free shadow space - MSVC_ONLY(jit.add(rsp, 40)); - - // Jump to the original return address - jit.add(rsp, 8); - jit.jump(rax); -} - -void CHook::Write_CallHandler(x64JitWriter& jit, HookType_t type) -{ - union - { - ReturnAction_t (__cdecl CHook::*HookHandler)(HookType_t); - std::uint64_t address; - } func; - - func.HookHandler = &CHook::HookHandler; - - // Shadow space 32 bytes + 8 bytes to keep it aligned on 16 bytes - MSVC_ONLY(jit.sub(rsp, 40)); - - // Call the global hook handler - - // 1st param (this) - GCC_ONLY(jit.mov(rdi, reinterpret_cast(this))); - MSVC_ONLY(jit.mov(rcx, reinterpret_cast(this))); - - // 2nd parameter (type) - GCC_ONLY(jit.mov(rsi, type)); - MSVC_ONLY(jit.mov(rdx, type)); - - jit.mov(rax, func.address); - jit.call(rax); - - // Free shadow space - MSVC_ONLY(jit.add(rsp, 40)); -} - -void CHook::Write_SaveRegisters(x64JitWriter& jit, HookType_t type) -{ - // Save RAX - jit.push(rax); - bool saveRAX = false; - - std::vector vecRegistersToSave = m_pCallingConvention->GetRegisters(); - for(size_t i = 0; i < vecRegistersToSave.size(); i++) - { - switch(vecRegistersToSave[i]) - { - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== - // RAX is saved by default (see above) - case Register_t::RAX: saveRAX = true; break; - case Register_t::RCX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rcx->m_pAddress)); jit.mov(rax(), rcx); break; - case Register_t::RDX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rdx->m_pAddress)); jit.mov(rax(), rdx); break; - case Register_t::RBX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rbx->m_pAddress)); jit.mov(rax(), rbx); break; - // BEWARE BECAUSE WE PUSHED TO STACK ABOVE, RSP NEEDS TO BE HANDLED DIFFERENTLY - case Register_t::RSP: - jit.push(r8); - // Add +push(rax) & +push(r8) - jit.lea(r8, rsp(16)); - jit.mov(rax, reinterpret_cast(m_pRegisters->m_rsp->m_pAddress)); jit.mov(rax(), r8); - jit.pop(r8); - break; - case Register_t::RBP: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rbp->m_pAddress)); jit.mov(rax(), rbp); break; - case Register_t::RSI: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rsi->m_pAddress)); jit.mov(rax(), rsi); break; - case Register_t::RDI: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rdi->m_pAddress)); jit.mov(rax(), rdi); break; - - case Register_t::R8: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r8->m_pAddress)); jit.mov(rax(), r8); break; - case Register_t::R9: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r9->m_pAddress)); jit.mov(rax(), r9); break; - case Register_t::R10: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r10->m_pAddress)); jit.mov(rax(), r10); break; - case Register_t::R11: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r11->m_pAddress)); jit.mov(rax(), r11); break; - case Register_t::R12: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r12->m_pAddress)); jit.mov(rax(), r12); break; - case Register_t::R13: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r13->m_pAddress)); jit.mov(rax(), r13); break; - case Register_t::R14: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r14->m_pAddress)); jit.mov(rax(), r14); break; - case Register_t::R15: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r15->m_pAddress)); jit.mov(rax(), r15); break; - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - case Register_t::XMM0: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm0->m_pAddress)); jit.movsd(rax(), xmm0); break; - case Register_t::XMM1: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm1->m_pAddress)); jit.movsd(rax(), xmm1); break; - case Register_t::XMM2: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm2->m_pAddress)); jit.movsd(rax(), xmm2); break; - case Register_t::XMM3: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm3->m_pAddress)); jit.movsd(rax(), xmm3); break; - case Register_t::XMM4: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm4->m_pAddress)); jit.movsd(rax(), xmm4); break; - case Register_t::XMM5: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm5->m_pAddress)); jit.movsd(rax(), xmm5); break; - case Register_t::XMM6: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm6->m_pAddress)); jit.movsd(rax(), xmm6); break; - case Register_t::XMM7: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm7->m_pAddress)); jit.movsd(rax(), xmm7); break; - - case Register_t::XMM8: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm8->m_pAddress)); jit.movsd(rax(), xmm8); break; - case Register_t::XMM9: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm9->m_pAddress)); jit.movsd(rax(), xmm9); break; - case Register_t::XMM10: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm10->m_pAddress)); jit.movsd(rax(), xmm10); break; - case Register_t::XMM11: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm11->m_pAddress)); jit.movsd(rax(), xmm11); break; - case Register_t::XMM12: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm12->m_pAddress)); jit.movsd(rax(), xmm12); break; - case Register_t::XMM13: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm13->m_pAddress)); jit.movsd(rax(), xmm13); break; - case Register_t::XMM14: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm14->m_pAddress)); jit.movsd(rax(), xmm14); break; - case Register_t::XMM15: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm15->m_pAddress)); jit.movsd(rax(), xmm15); break; - - default: puts("Unsupported register."); - } - } - - jit.pop(rax); - if (saveRAX) { - jit.push(r8); - jit.mov(r8, reinterpret_cast(m_pRegisters->m_rax->m_pAddress)); jit.mov(r8(), rax); - jit.pop(r8); - } -} - -void CHook::Write_RestoreRegisters(x64JitWriter& jit, HookType_t type) -{ - // RAX & RSP will be restored last - bool restoreRAX = false, restoreRSP = false; - - const auto& vecRegistersToRestore = m_pCallingConvention->GetRegisters(); - for(size_t i = 0; i < vecRegistersToRestore.size(); i++) - { - switch(vecRegistersToRestore[i]) - { - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== - // RAX is handled differently (see below) - case Register_t::RAX: restoreRAX = true; break; - case Register_t::RCX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rcx->m_pAddress)); jit.mov(rcx, rax()); break; - case Register_t::RDX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rdx->m_pAddress)); jit.mov(rdx, rax()); break; - case Register_t::RBX: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rbx->m_pAddress)); jit.mov(rbx, rax()); break; - // This could be very troublesome, but oh well... - case Register_t::RSP: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rsp->m_pAddress)); jit.mov(rsp, rax()); break; - case Register_t::RBP: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rbp->m_pAddress)); jit.mov(rbp, rax()); break; - case Register_t::RSI: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rsi->m_pAddress)); jit.mov(rsi, rax()); break; - case Register_t::RDI: jit.mov(rax, reinterpret_cast(m_pRegisters->m_rdi->m_pAddress)); jit.mov(rdi, rax()); break; - - case Register_t::R8: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r8->m_pAddress)); jit.mov(r8, rax()); break; - case Register_t::R9: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r9->m_pAddress)); jit.mov(r9, rax()); break; - case Register_t::R10: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r10->m_pAddress)); jit.mov(r10, rax()); break; - case Register_t::R11: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r11->m_pAddress)); jit.mov(r11, rax()); break; - case Register_t::R12: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r12->m_pAddress)); jit.mov(r12, rax()); break; - case Register_t::R13: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r13->m_pAddress)); jit.mov(r13, rax()); break; - case Register_t::R14: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r14->m_pAddress)); jit.mov(r14, rax()); break; - case Register_t::R15: jit.mov(rax, reinterpret_cast(m_pRegisters->m_r15->m_pAddress)); jit.mov(r15, rax()); break; - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - case Register_t::XMM0: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm0->m_pAddress)); jit.movsd(xmm0, rax()); break; - case Register_t::XMM1: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm1->m_pAddress)); jit.movsd(xmm1, rax()); break; - case Register_t::XMM2: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm2->m_pAddress)); jit.movsd(xmm2, rax()); break; - case Register_t::XMM3: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm3->m_pAddress)); jit.movsd(xmm3, rax()); break; - case Register_t::XMM4: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm4->m_pAddress)); jit.movsd(xmm4, rax()); break; - case Register_t::XMM5: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm5->m_pAddress)); jit.movsd(xmm5, rax()); break; - case Register_t::XMM6: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm6->m_pAddress)); jit.movsd(xmm6, rax()); break; - case Register_t::XMM7: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm7->m_pAddress)); jit.movsd(xmm7, rax()); break; - - case Register_t::XMM8: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm8->m_pAddress)); jit.movsd(xmm8, rax()); break; - case Register_t::XMM9: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm9->m_pAddress)); jit.movsd(xmm9, rax()); break; - case Register_t::XMM10: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm10->m_pAddress)); jit.movsd(xmm10, rax()); break; - case Register_t::XMM11: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm11->m_pAddress)); jit.movsd(xmm11, rax()); break; - case Register_t::XMM12: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm12->m_pAddress)); jit.movsd(xmm12, rax()); break; - case Register_t::XMM13: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm13->m_pAddress)); jit.movsd(xmm13, rax()); break; - case Register_t::XMM14: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm14->m_pAddress)); jit.movsd(xmm14, rax()); break; - case Register_t::XMM15: jit.mov(rax, reinterpret_cast(m_pRegisters->m_xmm15->m_pAddress)); jit.movsd(xmm15, rax()); break; - - default: puts("Unsupported register."); - } - } - - if (restoreRAX) { - jit.push(r8); - jit.mov(r8, reinterpret_cast(m_pRegisters->m_rax->m_pAddress)); - jit.mov(rax, r8()); - jit.pop(r8); - } -} - -#else -void CHook::CreateBridge() -{ - sp::MacroAssembler masm; - Label label_supercede; - - // Write a redirect to the post-hook code - Write_ModifyReturnAddress(masm); - - // Call the pre-hook handler and jump to label_supercede if ReturnAction_Supercede was returned - Write_CallHandler(masm, HOOKTYPE_PRE); - masm.cmpb(r8_al, ReturnAction_Supercede); - - // Restore the previously saved registers, so any changes will be applied - Write_RestoreRegisters(masm, HOOKTYPE_PRE); - - masm.j(equal, &label_supercede); - - // Jump to the trampoline - masm.subl(esp, 4); - masm.push(eax); - masm.movl(eax, Operand(ExternalAddress(&m_pTrampoline))); - masm.movl(Operand(esp, 4), eax); - masm.pop(eax); - masm.ret(); - - // This code will be executed if a pre-hook returns ReturnAction_Supercede - masm.bind(&label_supercede); - - // Finally, return to the caller - // This will still call post hooks, but will skip the original function. - masm.ret(m_pCallingConvention->GetPopSize()); - - void* base = smutils->GetScriptingEngine()->AllocatePageMemory(masm.length()); - masm.emitToExecutableMemory(base); - m_pBridge = base; -} - -void CHook::Write_ModifyReturnAddress(sp::MacroAssembler& masm) -{ - // Save scratch registers that are used by SetReturnAddress - static void* pEAX = NULL; - static void* pECX = NULL; - static void* pEDX = NULL; - - masm.movl(Operand(ExternalAddress(&pEAX)), eax); - masm.movl(Operand(ExternalAddress(&pECX)), ecx); - masm.movl(Operand(ExternalAddress(&pEDX)), edx); - - // Store the return address in eax - masm.movl(eax, Operand(esp, 0)); - - // Save the original return address by using the current esp as the key. - // This should be unique until we have returned to the original caller. - void (__cdecl CHook::*SetReturnAddress)(void*, void*) = &CHook::SetReturnAddress; - masm.push(esp); - masm.push(eax); - masm.push(intptr_t(this)); - masm.call(ExternalAddress((void *&)SetReturnAddress)); - masm.addl(esp, 12); - - // Restore scratch registers - masm.movl(eax, Operand(ExternalAddress(&pEAX))); - masm.movl(ecx, Operand(ExternalAddress(&pECX))); - masm.movl(edx, Operand(ExternalAddress(&pEDX))); - - // Override the return address. This is a redirect to our post-hook code - CreatePostCallback(); - masm.movl(Operand(esp, 0), intptr_t(m_pNewRetAddr)); -} - -void CHook::CreatePostCallback() -{ - sp::MacroAssembler masm; - - int iPopSize = m_pCallingConvention->GetPopSize(); - - // Subtract the previously added bytes (stack size + return address), so - // that we can access the arguments again - masm.subl(esp, iPopSize+4); - - // Call the post-hook handler - Write_CallHandler(masm, HOOKTYPE_POST); - - // Restore the previously saved registers, so any changes will be applied - Write_RestoreRegisters(masm, HOOKTYPE_POST); - - // Save scratch registers that are used by GetReturnAddress - static void* pEAX = NULL; - static void* pECX = NULL; - static void* pEDX = NULL; - masm.movl(Operand(ExternalAddress(&pEAX)), eax); - masm.movl(Operand(ExternalAddress(&pECX)), ecx); - masm.movl(Operand(ExternalAddress(&pEDX)), edx); - - // Get the original return address - void* (__cdecl CHook::*GetReturnAddress)(void*) = &CHook::GetReturnAddress; - masm.push(esp); - masm.push(intptr_t(this)); - masm.call(ExternalAddress((void *&)GetReturnAddress)); - masm.addl(esp, 8); - - // Save the original return address - static void* pRetAddr = NULL; - masm.movl(Operand(ExternalAddress(&pRetAddr)), eax); - - // Restore scratch registers - masm.movl(eax, Operand(ExternalAddress(&pEAX))); - masm.movl(ecx, Operand(ExternalAddress(&pECX))); - masm.movl(edx, Operand(ExternalAddress(&pEDX))); - - // Add the bytes again to the stack (stack size + return address), so we - // don't corrupt the stack. - masm.addl(esp, iPopSize+4); - - // Jump to the original return address - masm.jmp(Operand(ExternalAddress(&pRetAddr))); - - // Generate the code - void* base = smutils->GetScriptingEngine()->AllocatePageMemory(masm.length()); - masm.emitToExecutableMemory(base); - m_pNewRetAddr = base; -} - -void CHook::Write_CallHandler(sp::MacroAssembler& masm, HookType_t type) -{ - ReturnAction_t (__cdecl CHook::*HookHandler)(HookType_t) = &CHook::HookHandler; - - // Save the registers so that we can access them in our handlers - Write_SaveRegisters(masm, type); - - // Align the stack to 16 bytes. - masm.subl(esp, 4); - - // Call the global hook handler - masm.push(type); - masm.push(intptr_t(this)); - masm.call(ExternalAddress((void *&)HookHandler)); - masm.addl(esp, 12); -} - -void CHook::Write_SaveRegisters(sp::MacroAssembler& masm, HookType_t type) -{ - std::vector vecRegistersToSave = m_pCallingConvention->GetRegisters(); - for(size_t i = 0; i < vecRegistersToSave.size(); i++) - { - switch(vecRegistersToSave[i]) - { - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - case AL: masm.movl(Operand(ExternalAddress(m_pRegisters->m_al->m_pAddress)), r8_al); break; - case CL: masm.movl(Operand(ExternalAddress(m_pRegisters->m_cl->m_pAddress)), r8_cl); break; - case DL: masm.movl(Operand(ExternalAddress(m_pRegisters->m_dl->m_pAddress)), r8_dl); break; - case BL: masm.movl(Operand(ExternalAddress(m_pRegisters->m_bl->m_pAddress)), r8_bl); break; - case AH: masm.movl(Operand(ExternalAddress(m_pRegisters->m_ah->m_pAddress)), r8_ah); break; - case CH: masm.movl(Operand(ExternalAddress(m_pRegisters->m_ch->m_pAddress)), r8_ch); break; - case DH: masm.movl(Operand(ExternalAddress(m_pRegisters->m_dh->m_pAddress)), r8_dh); break; - case BH: masm.movl(Operand(ExternalAddress(m_pRegisters->m_bh->m_pAddress)), r8_bh); break; - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - case EAX: masm.movl(Operand(ExternalAddress(m_pRegisters->m_eax->m_pAddress)), eax); break; - case ECX: masm.movl(Operand(ExternalAddress(m_pRegisters->m_ecx->m_pAddress)), ecx); break; - case EDX: masm.movl(Operand(ExternalAddress(m_pRegisters->m_edx->m_pAddress)), edx); break; - case EBX: masm.movl(Operand(ExternalAddress(m_pRegisters->m_ebx->m_pAddress)), ebx); break; - case ESP: masm.movl(Operand(ExternalAddress(m_pRegisters->m_esp->m_pAddress)), esp); break; - case EBP: masm.movl(Operand(ExternalAddress(m_pRegisters->m_ebp->m_pAddress)), ebp); break; - case ESI: masm.movl(Operand(ExternalAddress(m_pRegisters->m_esi->m_pAddress)), esi); break; - case EDI: masm.movl(Operand(ExternalAddress(m_pRegisters->m_edi->m_pAddress)), edi); break; - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - // TODO: Also provide movups? - case XMM0: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm0->m_pAddress)), xmm0); break; - case XMM1: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm1->m_pAddress)), xmm1); break; - case XMM2: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm2->m_pAddress)), xmm2); break; - case XMM3: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm3->m_pAddress)), xmm3); break; - case XMM4: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm4->m_pAddress)), xmm4); break; - case XMM5: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm5->m_pAddress)), xmm5); break; - case XMM6: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm6->m_pAddress)), xmm6); break; - case XMM7: masm.movaps(Operand(ExternalAddress(m_pRegisters->m_xmm7->m_pAddress)), xmm7); break; - - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - case ST0: - // Don't mess with the FPU stack in a pre-hook. The float return is returned in st0, - // so only load it in a post hook to avoid writing back NaN. - if (type == HOOKTYPE_POST) - masm.fst32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress))); - break; - //case ST1: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress)), st1); break; - //case ST2: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress)), st2); break; - //case ST3: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress)), st3); break; - //case ST4: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st4->m_pAddress)), st4); break; - //case ST5: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st5->m_pAddress)), st5); break; - //case ST6: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st6->m_pAddress)), st6); break; - //case ST7: masm.movl(tword_ptr_abs(Ptr(m_pRegisters->m_st7->m_pAddress)), st7); break; - - default: puts("Unsupported register."); - } - } -} - -void CHook::Write_RestoreRegisters(sp::MacroAssembler& masm, HookType_t type) -{ - std::vector vecRegistersToSave = m_pCallingConvention->GetRegisters(); - for (size_t i = 0; i < vecRegistersToSave.size(); i++) - { - switch (vecRegistersToSave[i]) - { - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - case AL: masm.movl(r8_al, Operand(ExternalAddress(m_pRegisters->m_al->m_pAddress))); break; - case CL: masm.movl(r8_cl, Operand(ExternalAddress(m_pRegisters->m_cl->m_pAddress))); break; - case DL: masm.movl(r8_dl, Operand(ExternalAddress(m_pRegisters->m_dl->m_pAddress))); break; - case BL: masm.movl(r8_bl, Operand(ExternalAddress(m_pRegisters->m_bl->m_pAddress))); break; - case AH: masm.movl(r8_ah, Operand(ExternalAddress(m_pRegisters->m_ah->m_pAddress))); break; - case CH: masm.movl(r8_ch, Operand(ExternalAddress(m_pRegisters->m_ch->m_pAddress))); break; - case DH: masm.movl(r8_dh, Operand(ExternalAddress(m_pRegisters->m_dh->m_pAddress))); break; - case BH: masm.movl(r8_bh, Operand(ExternalAddress(m_pRegisters->m_bh->m_pAddress))); break; - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - case EAX: masm.movl(eax, Operand(ExternalAddress(m_pRegisters->m_eax->m_pAddress))); break; - case ECX: masm.movl(ecx, Operand(ExternalAddress(m_pRegisters->m_ecx->m_pAddress))); break; - case EDX: masm.movl(edx, Operand(ExternalAddress(m_pRegisters->m_edx->m_pAddress))); break; - case EBX: masm.movl(ebx, Operand(ExternalAddress(m_pRegisters->m_ebx->m_pAddress))); break; - case ESP: masm.movl(esp, Operand(ExternalAddress(m_pRegisters->m_esp->m_pAddress))); break; - case EBP: masm.movl(ebp, Operand(ExternalAddress(m_pRegisters->m_ebp->m_pAddress))); break; - case ESI: masm.movl(esi, Operand(ExternalAddress(m_pRegisters->m_esi->m_pAddress))); break; - case EDI: masm.movl(edi, Operand(ExternalAddress(m_pRegisters->m_edi->m_pAddress))); break; - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - // TODO: Also provide movups? - case XMM0: masm.movaps(xmm0, Operand(ExternalAddress(m_pRegisters->m_xmm0->m_pAddress))); break; - case XMM1: masm.movaps(xmm1, Operand(ExternalAddress(m_pRegisters->m_xmm1->m_pAddress))); break; - case XMM2: masm.movaps(xmm2, Operand(ExternalAddress(m_pRegisters->m_xmm2->m_pAddress))); break; - case XMM3: masm.movaps(xmm3, Operand(ExternalAddress(m_pRegisters->m_xmm3->m_pAddress))); break; - case XMM4: masm.movaps(xmm4, Operand(ExternalAddress(m_pRegisters->m_xmm4->m_pAddress))); break; - case XMM5: masm.movaps(xmm5, Operand(ExternalAddress(m_pRegisters->m_xmm5->m_pAddress))); break; - case XMM6: masm.movaps(xmm6, Operand(ExternalAddress(m_pRegisters->m_xmm6->m_pAddress))); break; - case XMM7: masm.movaps(xmm7, Operand(ExternalAddress(m_pRegisters->m_xmm7->m_pAddress))); break; - - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - case ST0: - if (type == HOOKTYPE_POST) { - // Replace the top of the FPU stack. - // Copy st0 to st0 and pop -> just pop the FPU stack. - masm.fstp(st0); - // Push a value to the FPU stack. - // TODO: Only write back when changed? Save full 80bits for that case. - // Avoid truncation of the data if it's unchanged. - masm.fld32(Operand(ExternalAddress(m_pRegisters->m_st0->m_pAddress))); - } - break; - //case ST1: masm.movl(st1, tword_ptr_abs(Ptr(m_pRegisters->m_st1->m_pAddress))); break; - //case ST2: masm.movl(st2, tword_ptr_abs(Ptr(m_pRegisters->m_st2->m_pAddress))); break; - //case ST3: masm.movl(st3, tword_ptr_abs(Ptr(m_pRegisters->m_st3->m_pAddress))); break; - //case ST4: masm.movl(st4, tword_ptr_abs(Ptr(m_pRegisters->m_st4->m_pAddress))); break; - //case ST5: masm.movl(st5, tword_ptr_abs(Ptr(m_pRegisters->m_st5->m_pAddress))); break; - //case ST6: masm.movl(st6, tword_ptr_abs(Ptr(m_pRegisters->m_st6->m_pAddress))); break; - //case ST7: masm.movl(st7, tword_ptr_abs(Ptr(m_pRegisters->m_st7->m_pAddress))); break; - - default: puts("Unsupported register."); - } - } -} -#endif \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/hook.h b/extensions/dhooks/DynamicHooks/hook.h deleted file mode 100644 index e9136087ee..0000000000 --- a/extensions/dhooks/DynamicHooks/hook.h +++ /dev/null @@ -1,245 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _HOOK_H -#define _HOOK_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "registers.h" -#include "convention.h" -#include -#include -#include - -#ifdef DYNAMICHOOKS_x86_64 -#include -#include -#include "sh_asm_x86_64.h" - -#if SH_COMP == SH_COMP_MSVC -# define GCC_ONLY(x) -# define MSVC_ONLY(x) x -#elif SH_COMP == SH_COMP_GCC -# define GCC_ONLY(x) x -# define MSVC_ONLY(x) -#endif - -#endif - -// ============================================================================ -// >> HookType_t -// ============================================================================ -enum HookType_t -{ - // Callback will be executed before the original function. - HOOKTYPE_PRE, - - // Callback will be executed after the original function. - HOOKTYPE_POST -}; - -enum ReturnAction_t -{ - ReturnAction_Ignored, // handler didn't take any action - ReturnAction_Handled, // plugin did something, but real function should still be called - ReturnAction_Override, // call real function, but use my return value - ReturnAction_Supercede // skip real function; use my return value -}; - - -// ============================================================================ -// >> TYPEDEFS -// ============================================================================ -class CHook; -typedef ReturnAction_t (*HookHandlerFn)(HookType_t, CHook*); - -#ifdef __linux__ -#define __cdecl -#endif - -struct IntegerPolicy -{ - static inline uint32_t hash(size_t i) { - return ke::HashInteger(i); - } - static inline bool matches(size_t i1, size_t i2) { - return i1 == i2; - } -}; - -typedef ke::HashSet> HookHandlerSet; -typedef ke::HashMap HookTypeMap; -typedef ke::HashMap, ke::PointerPolicy> ReturnAddressMap; - -namespace sp -{ - class MacroAssembler; -} - - -// ============================================================================ -// >> CLASSES -// ============================================================================ - -class CHook -{ -private: - friend class CHookManager; - - /* - Creates a new function hook. - - @param : - The address of the function to hook - - @param : - The calling convention of . - */ - CHook(void* pFunc, ICallingConvention* pConvention); - ~CHook(); - -public: - /* - Adds a hook handler to the hook. - - @param type The hook type. - @param pFunc The hook handler that should be added. - */ - void AddCallback(HookType_t type, HookHandlerFn* pFunc); - - /* - Removes a hook handler to the hook. - - @param type The hook type. - @param pFunc The hook handler that should be removed. - */ - void RemoveCallback(HookType_t type, HookHandlerFn* pFunc); - - /* - Checks if a hook handler is already added. - - @param type The hook type. - @param pFunc The hook handler that should be checked. - */ - bool IsCallbackRegistered(HookType_t type, HookHandlerFn* pFunc); - - /* - Checks if there are any hook handlers added to this hook. - */ - bool AreCallbacksRegistered(); - - template - T GetArgument(int iIndex) - { - return *(T *) m_pCallingConvention->GetArgumentPtr(iIndex, m_pRegisters); - } - - template - void SetArgument(int iIndex, T value) - { - void* pPtr = m_pCallingConvention->GetArgumentPtr(iIndex, m_pRegisters); - *(T *) pPtr = value; - m_pCallingConvention->ArgumentPtrChanged(iIndex, m_pRegisters, pPtr); - } - - template - T GetReturnValue() - { - return *(T *) m_pCallingConvention->GetReturnPtr(m_pRegisters); - } - - template - void SetReturnValue(T value) - { - void* pPtr = m_pCallingConvention->GetReturnPtr(m_pRegisters); - *(T *) pPtr = value; - m_pCallingConvention->ReturnPtrChanged(m_pRegisters, pPtr); - } - -private: - void CreateBridge(); - void CreatePostCallback(); - -#ifdef DYNAMICHOOKS_x86_64 - void Write_ModifyReturnAddress(SourceHook::Asm::x64JitWriter& jit); - void Write_CallHandler(SourceHook::Asm::x64JitWriter& jit, HookType_t type); - void Write_SaveRegisters(SourceHook::Asm::x64JitWriter& jit, HookType_t type); - void Write_RestoreRegisters(SourceHook::Asm::x64JitWriter& jit, HookType_t type); - - SourceHook::Asm::x64JitWriter m_bridge; - SourceHook::Asm::x64JitWriter m_postCallback; -#else - void Write_ModifyReturnAddress(sp::MacroAssembler& masm); - void Write_CallHandler(sp::MacroAssembler& masm, HookType_t type); - void Write_SaveRegisters(sp::MacroAssembler& masm, HookType_t type); - void Write_RestoreRegisters(sp::MacroAssembler& masm, HookType_t type); -#endif - - ReturnAction_t __cdecl HookHandler(HookType_t type); - - void* __cdecl GetReturnAddress(void* pESP); - void __cdecl SetReturnAddress(void* pRetAddr, void* pESP); - -public: - - HookTypeMap m_hookHandler; - - // Address of the original function - void* m_pFunc; - - ICallingConvention* m_pCallingConvention; - - // SafetyHook - SafetyHookInline m_Hook{}; - - // Address of the bridge - void* m_pBridge; - - // Address of the trampoline - void* m_pTrampoline; - - // Register storage - CRegisters* m_pRegisters; - - // New return address - void* m_pNewRetAddr; - - ReturnAddressMap m_RetAddr; - - // Save the last return action of the pre HookHandler for use in the post handler. - std::vector m_LastPreReturnAction; -}; - -#endif // _HOOK_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/manager.cpp b/extensions/dhooks/DynamicHooks/manager.cpp deleted file mode 100644 index d282a88572..0000000000 --- a/extensions/dhooks/DynamicHooks/manager.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "manager.h" - - -// ============================================================================ -// >> CHookManager -// ============================================================================ -CHook* CHookManager::HookFunction(void* pFunc, ICallingConvention* pConvention) -{ - if (!pFunc) - return NULL; - - CHook* pHook = FindHook(pFunc); - if (pHook) - { - delete pConvention; - return pHook; - } - - pHook = new CHook(pFunc, pConvention); - m_Hooks.push_back(pHook); - return pHook; -} - -void CHookManager::UnhookFunction(void* pFunc) -{ - if (!pFunc) - return; - - for (size_t i = 0; i < m_Hooks.size(); i++) - { - CHook* pHook = m_Hooks[i]; - if (pHook->m_pFunc == pFunc) - { - m_Hooks.erase(m_Hooks.begin() + i); - delete pHook; - return; - } - } -} - -CHook* CHookManager::FindHook(void* pFunc) -{ - if (!pFunc) - return NULL; - - for(size_t i = 0; i < m_Hooks.size(); i++) - { - CHook* pHook = m_Hooks[i]; - if (pHook->m_pFunc == pFunc) - return pHook; - } - return NULL; -} - -void CHookManager::UnhookAllFunctions() -{ - for(size_t i = 0; i < m_Hooks.size(); i++) - delete m_Hooks[i]; - - m_Hooks.clear(); -} - - -// ============================================================================ -// >> GetHookManager -// ============================================================================ -CHookManager* GetHookManager() -{ - static CHookManager* s_pManager = new CHookManager; - return s_pManager; -} \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/manager.h b/extensions/dhooks/DynamicHooks/manager.h deleted file mode 100644 index 4c1d8ff54b..0000000000 --- a/extensions/dhooks/DynamicHooks/manager.h +++ /dev/null @@ -1,86 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _MANAGER_H -#define _MANAGER_H - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include "hook.h" -#include "convention.h" -#include - - -// ============================================================================ -// >> CHookManager -// ============================================================================ -class CHookManager -{ -public: - /* - Hooks the given function and returns a new CHook instance. If the - function was already hooked, the existing CHook instance will be - returned. - */ - CHook* HookFunction(void* pFunc, ICallingConvention* pConvention); - - /* - Removes all callbacks and restores the original function. - */ - void UnhookFunction(void* pFunc); - - /* - Returns either NULL or the found CHook instance. - */ - CHook* FindHook(void* pFunc); - - /* - Removes all callbacks and restores all functions. - */ - void UnhookAllFunctions(); - -public: - std::vector m_Hooks; -}; - - -// ============================================================================ -// >> GetHookManager -// ============================================================================ -/* -Returns a pointer to a static CHookManager object. -*/ -CHookManager* GetHookManager(); - -#endif // _MANAGER_H \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/registers.cpp b/extensions/dhooks/DynamicHooks/registers.cpp deleted file mode 100644 index 0984926f5e..0000000000 --- a/extensions/dhooks/DynamicHooks/registers.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#include "registers.h" - -CRegisters::CRegisters(std::vector registers) -{ - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - m_al = CreateRegister(registers, AL, 1); - m_cl = CreateRegister(registers, CL, 1); - m_dl = CreateRegister(registers, DL, 1); - m_bl = CreateRegister(registers, BL, 1); - - // 64-bit mode only - /* - m_spl = CreateRegister(registers, SPL, 1); - m_bpl = CreateRegister(registers, BPL, 1); - m_sil = CreateRegister(registers, SIL, 1); - m_dil = CreateRegister(registers, DIL, 1); - m_r8b = CreateRegister(registers, R8B, 1); - m_r9b = CreateRegister(registers, R9B, 1); - m_r10b = CreateRegister(registers, R10B, 1); - m_r11b = CreateRegister(registers, R11B, 1); - m_r12b = CreateRegister(registers, R12B, 1); - m_r13b = CreateRegister(registers, R13B, 1); - m_r14b = CreateRegister(registers, R14B, 1); - m_r15b = CreateRegister(registers, R15B, 1); - */ - - m_ah = CreateRegister(registers, AH, 1); - m_ch = CreateRegister(registers, CH, 1); - m_dh = CreateRegister(registers, DH, 1); - m_bh = CreateRegister(registers, BH, 1); - - // ======================================================================== - // >> 16-bit General purpose registers - // ======================================================================== - m_ax = CreateRegister(registers, AX, 2); - m_cx = CreateRegister(registers, CX, 2); - m_dx = CreateRegister(registers, DX, 2); - m_bx = CreateRegister(registers, BX, 2); - m_sp = CreateRegister(registers, SP, 2); - m_bp = CreateRegister(registers, BP, 2); - m_si = CreateRegister(registers, SI, 2); - m_di = CreateRegister(registers, DI, 2); - - // 64-bit mode only - /* - m_r8w = CreateRegister(registers, R8W, 2); - m_r9w = CreateRegister(registers, R9W, 2); - m_r10w = CreateRegister(registers, R10W, 2); - m_r11w = CreateRegister(registers, R11W, 2); - m_r12w = CreateRegister(registers, R12W, 2); - m_r13w = CreateRegister(registers, R13W, 2); - m_r14w = CreateRegister(registers, R14W, 2); - m_r15w = CreateRegister(registers, R14W, 2); - */ - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - m_eax = CreateRegister(registers, EAX, 4); - m_ecx = CreateRegister(registers, ECX, 4); - m_edx = CreateRegister(registers, EDX, 4); - m_ebx = CreateRegister(registers, EBX, 4); - m_esp = CreateRegister(registers, ESP, 4); - m_ebp = CreateRegister(registers, EBP, 4); - m_esi = CreateRegister(registers, ESI, 4); - m_edi = CreateRegister(registers, EDI, 4); - - // 64-bit mode only - /* - m_r8d = CreateRegister(registers, R8D, 4); - m_r9d = CreateRegister(registers, R9D, 4); - m_r10d = CreateRegister(registers, R10D, 4); - m_r11d = CreateRegister(registers, R11D, 4); - m_r12d = CreateRegister(registers, R12D, 4); - m_r13d = CreateRegister(registers, R13D, 4); - m_r14d = CreateRegister(registers, R14D, 4); - m_r15d = CreateRegister(registers, R15D, 4); - */ - - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - m_rax = CreateRegister(registers, RAX, 8); - m_rcx = CreateRegister(registers, RCX, 8); - m_rdx = CreateRegister(registers, RDX, 8); - m_rbx = CreateRegister(registers, RBX, 8); - m_rsp = CreateRegister(registers, RSP, 8); - m_rbp = CreateRegister(registers, RBP, 8); - m_rsi = CreateRegister(registers, RSI, 8); - m_rdi = CreateRegister(registers, RDI, 8); - - m_r8 = CreateRegister(registers, R8, 8); - m_r9 = CreateRegister(registers, R9, 8); - m_r10 = CreateRegister(registers, R10, 8); - m_r11 = CreateRegister(registers, R11, 8); - m_r12 = CreateRegister(registers, R12, 8); - m_r13 = CreateRegister(registers, R13, 8); - m_r14 = CreateRegister(registers, R14, 8); - m_r15 = CreateRegister(registers, R15, 8); -#endif - - // ======================================================================== - // >> 64-bit MM (MMX) registers - // ======================================================================== - m_mm0 = CreateRegister(registers, MM0, 8); - m_mm1 = CreateRegister(registers, MM1, 8); - m_mm2 = CreateRegister(registers, MM2, 8); - m_mm3 = CreateRegister(registers, MM3, 8); - m_mm4 = CreateRegister(registers, MM4, 8); - m_mm5 = CreateRegister(registers, MM5, 8); - m_mm6 = CreateRegister(registers, MM6, 8); - m_mm7 = CreateRegister(registers, MM7, 8); - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - // Copying data from xmm0-7 requires the memory address to be 16-byte aligned. - m_xmm0 = CreateRegister(registers, XMM0, 16, 16); - m_xmm1 = CreateRegister(registers, XMM1, 16, 16); - m_xmm2 = CreateRegister(registers, XMM2, 16, 16); - m_xmm3 = CreateRegister(registers, XMM3, 16, 16); - m_xmm4 = CreateRegister(registers, XMM4, 16, 16); - m_xmm5 = CreateRegister(registers, XMM5, 16, 16); - m_xmm6 = CreateRegister(registers, XMM6, 16, 16); - m_xmm7 = CreateRegister(registers, XMM7, 16, 16); - - // 64-bit mode only -#ifdef KE_ARCH_X64 - m_xmm8 = CreateRegister(registers, XMM8, 16); - m_xmm9 = CreateRegister(registers, XMM9, 16); - m_xmm10 = CreateRegister(registers, XMM10, 16); - m_xmm11 = CreateRegister(registers, XMM11, 16); - m_xmm12 = CreateRegister(registers, XMM12, 16); - m_xmm13 = CreateRegister(registers, XMM13, 16); - m_xmm14 = CreateRegister(registers, XMM14, 16); - m_xmm15 = CreateRegister(registers, XMM15, 16); -#endif - - // ======================================================================== - // >> 16-bit Segment registers - // ======================================================================== - m_cs = CreateRegister(registers, CS, 2); - m_ss = CreateRegister(registers, SS, 2); - m_ds = CreateRegister(registers, DS, 2); - m_es = CreateRegister(registers, ES, 2); - m_fs = CreateRegister(registers, FS, 2); - m_gs = CreateRegister(registers, GS, 2); - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - m_st0 = CreateRegister(registers, ST0, 10); - m_st1 = CreateRegister(registers, ST1, 10); - m_st2 = CreateRegister(registers, ST2, 10); - m_st3 = CreateRegister(registers, ST3, 10); - m_st4 = CreateRegister(registers, ST4, 10); - m_st5 = CreateRegister(registers, ST5, 10); - m_st6 = CreateRegister(registers, ST6, 10); - m_st7 = CreateRegister(registers, ST7, 10); -} - -CRegisters::~CRegisters() -{ - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - DeleteRegister(m_al); - DeleteRegister(m_cl); - DeleteRegister(m_dl); - DeleteRegister(m_bl); - - // 64-bit mode only - /* - DeleteRegister(m_spl); - DeleteRegister(m_bpl); - DeleteRegister(m_sil); - DeleteRegister(m_dil); - DeleteRegister(m_r8b); - DeleteRegister(m_r9b); - DeleteRegister(m_r10b); - DeleteRegister(m_r11b); - DeleteRegister(m_r12b); - DeleteRegister(m_r13b); - DeleteRegister(m_r14b); - DeleteRegister(m_r15b); - */ - - DeleteRegister(m_ah); - DeleteRegister(m_ch); - DeleteRegister(m_dh); - DeleteRegister(m_bh); - - // ======================================================================== - // >> 16-bit General purpose registers - // ======================================================================== - DeleteRegister(m_ax); - DeleteRegister(m_cx); - DeleteRegister(m_dx); - DeleteRegister(m_bx); - DeleteRegister(m_sp); - DeleteRegister(m_bp); - DeleteRegister(m_si); - DeleteRegister(m_di); - - // 64-bit mode only - /* - DeleteRegister(m_r8w); - DeleteRegister(m_r9w); - DeleteRegister(m_r10w); - DeleteRegister(m_r11w); - DeleteRegister(m_r12w); - DeleteRegister(m_r13w); - DeleteRegister(m_r14w); - DeleteRegister(m_r15w); - */ - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - DeleteRegister(m_eax); - DeleteRegister(m_ecx); - DeleteRegister(m_edx); - DeleteRegister(m_ebx); - DeleteRegister(m_esp); - DeleteRegister(m_ebp); - DeleteRegister(m_esi); - DeleteRegister(m_edi); - - // 64-bit mode only - /* - DeleteRegister(m_r8d); - DeleteRegister(m_r9d); - DeleteRegister(m_r10d); - DeleteRegister(m_r11d); - DeleteRegister(m_r12d); - DeleteRegister(m_r13d); - DeleteRegister(m_r14d); - DeleteRegister(m_r15d); - */ - - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - DeleteRegister(m_rax); - DeleteRegister(m_rcx); - DeleteRegister(m_rdx); - DeleteRegister(m_rbx); - DeleteRegister(m_rsp); - DeleteRegister(m_rbp); - DeleteRegister(m_rsi); - DeleteRegister(m_rdi); - - // 64-bit mode only - DeleteRegister(m_r8); - DeleteRegister(m_r9); - DeleteRegister(m_r10); - DeleteRegister(m_r11); - DeleteRegister(m_r12); - DeleteRegister(m_r13); - DeleteRegister(m_r14); - DeleteRegister(m_r15); -#endif - - // ======================================================================== - // >> 64-bit MM (MMX) registers - // ======================================================================== - DeleteRegister(m_mm0); - DeleteRegister(m_mm1); - DeleteRegister(m_mm2); - DeleteRegister(m_mm3); - DeleteRegister(m_mm4); - DeleteRegister(m_mm5); - DeleteRegister(m_mm6); - DeleteRegister(m_mm7); - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - DeleteRegister(m_xmm0); - DeleteRegister(m_xmm1); - DeleteRegister(m_xmm2); - DeleteRegister(m_xmm3); - DeleteRegister(m_xmm4); - DeleteRegister(m_xmm5); - DeleteRegister(m_xmm6); - DeleteRegister(m_xmm7); - - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - DeleteRegister(m_xmm8); - DeleteRegister(m_xmm9); - DeleteRegister(m_xmm10); - DeleteRegister(m_xmm11); - DeleteRegister(m_xmm12); - DeleteRegister(m_xmm13); - DeleteRegister(m_xmm14); - DeleteRegister(m_xmm15); -#endif - - // ======================================================================== - // >> 2-bit Segment registers - // ======================================================================== - DeleteRegister(m_cs); - DeleteRegister(m_ss); - DeleteRegister(m_ds); - DeleteRegister(m_es); - DeleteRegister(m_fs); - DeleteRegister(m_gs); - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - DeleteRegister(m_st0); - DeleteRegister(m_st1); - DeleteRegister(m_st2); - DeleteRegister(m_st3); - DeleteRegister(m_st4); - DeleteRegister(m_st5); - DeleteRegister(m_st6); - DeleteRegister(m_st7); -} - -CRegister* CRegisters::CreateRegister(std::vector& registers, Register_t reg, uint16_t iSize, uint16_t iAlignment) -{ - for(size_t i = 0; i < registers.size(); i++) - { - if (registers[i] == reg) - { - return new CRegister(iSize, iAlignment); - } - } - return NULL; -} - -void CRegisters::DeleteRegister(CRegister* pRegister) -{ - if (pRegister) - { - delete pRegister; - } -} - -CRegister* CRegisters::GetRegister(Register_t reg) -{ - switch (reg) - { - case AL: - return m_al; - case CL: - return m_cl; - case DL: - return m_dl; - case BL: - return m_bl; - case AH: - return m_ah; - case CH: - return m_ch; - case DH: - return m_dh; - case BH: - return m_bh; - - case AX: - return m_ax; - case CX: - return m_cx; - case DX: - return m_dx; - case BX: - return m_bx; - case SP: - return m_sp; - case BP: - return m_bp; - case SI: - return m_si; - case DI: - return m_di; - - case EAX: - return m_eax; - case ECX: - return m_ecx; - case EDX: - return m_edx; - case EBX: - return m_ebx; - case ESP: - return m_esp; - case EBP: - return m_ebp; - case ESI: - return m_esi; - case EDI: - return m_edi; - -#ifdef DYNAMICHOOKS_x86_64 - case RAX: - return m_rax; - case RCX: - return m_rcx; - case RDX: - return m_rdx; - case RBX: - return m_rbx; - case RSP: - return m_rsp; - case RBP: - return m_rbp; - case RSI: - return m_rsi; - case RDI: - return m_rdi; - - case R8: - return m_r8; - case R9: - return m_r9; - case R10: - return m_r10; - case R11: - return m_r11; - case R12: - return m_r12; - case R13: - return m_r13; - case R14: - return m_r14; - case R15: - return m_r15; -#endif - - case MM0: - return m_mm0; - case MM1: - return m_mm1; - case MM2: - return m_mm2; - case MM3: - return m_mm3; - case MM4: - return m_mm4; - case MM5: - return m_mm5; - case MM6: - return m_mm6; - case MM7: - return m_mm7; - - case XMM0: - return m_xmm0; - case XMM1: - return m_xmm1; - case XMM2: - return m_xmm2; - case XMM3: - return m_xmm3; - case XMM4: - return m_xmm4; - case XMM5: - return m_xmm5; - case XMM6: - return m_xmm6; - case XMM7: - return m_xmm7; - -#ifdef DYNAMICHOOKS_x86_64 - case XMM8: - return m_xmm8; - case XMM9: - return m_xmm9; - case XMM10: - return m_xmm10; - case XMM11: - return m_xmm11; - case XMM12: - return m_xmm12; - case XMM13: - return m_xmm13; - case XMM14: - return m_xmm14; - case XMM15: - return m_xmm15; -#endif - - case CS: - return m_cs; - case SS: - return m_ss; - case DS: - return m_ds; - case ES: - return m_es; - case FS: - return m_fs; - case GS: - return m_gs; - - case ST0: - return m_st0; - case ST1: - return m_st1; - case ST2: - return m_st2; - case ST3: - return m_st3; - case ST4: - return m_st4; - case ST5: - return m_st5; - case ST6: - return m_st6; - case ST7: - return m_st7; - - default: - return nullptr; - } -} \ No newline at end of file diff --git a/extensions/dhooks/DynamicHooks/registers.h b/extensions/dhooks/DynamicHooks/registers.h deleted file mode 100644 index d0c394c898..0000000000 --- a/extensions/dhooks/DynamicHooks/registers.h +++ /dev/null @@ -1,455 +0,0 @@ -/** -* ============================================================================= -* DynamicHooks -* Copyright (C) 2015 Robin Gohmert. All rights reserved. -* Copyright (C) 2018-2021 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This software is provided 'as-is', without any express or implied warranty. -* In no event will the authors be held liable for any damages arising from -* the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be -* appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -* asm.h/cpp from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -* -fPIC thunks correctly -* -* Idea and trampoline code taken from DynDetours (thanks your-name-here). -* -* Adopted to provide similar features to SourceHook by AlliedModders LLC. -*/ - -#ifndef _REGISTERS_H -#define _REGISTERS_H - - -// ============================================================================ -// >> INCLUDES -// ============================================================================ -#include -#include -#include -#include - - -// ============================================================================ -// >> Register_t -// ============================================================================ -enum Register_t -{ - // No register at all. - None, - - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - AL, - CL, - DL, - BL, - - // 64-bit mode only - /* - SPL, - BPL, - SIL, - DIL, - R8B, - R9B, - R10B, - R11B, - R12B, - R13B, - R14B, - R15B, - */ - - AH, - CH, - DH, - BH, - - // ======================================================================== - // >> 16-bit General purpose registers - // ======================================================================== - AX, - CX, - DX, - BX, - SP, - BP, - SI, - DI, - - // 64-bit mode only - /* - R8W, - R9W, - R10W, - R11W, - R12W, - R13W, - R14W, - R15W, - */ - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - EAX, - ECX, - EDX, - EBX, - ESP, - EBP, - ESI, - EDI, - - // 64-bit mode only - /* - R8D, - R9D, - R10D, - R11D, - R12D, - R13D, - R14D, - R15D, - */ - - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== -#ifdef DYNAMICHOOKS_x86_64 - RAX, - RCX, - RDX, - RBX, - RSP, - RBP, - RSI, - RDI, - - R8, - R9, - R10, - R11, - R12, - R13, - R14, - R15, -#endif - - // ======================================================================== - // >> 64-bit MM (MMX) registers - // ======================================================================== - MM0, - MM1, - MM2, - MM3, - MM4, - MM5, - MM6, - MM7, - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - XMM0, - XMM1, - XMM2, - XMM3, - XMM4, - XMM5, - XMM6, - XMM7, - - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - XMM8, - XMM9, - XMM10, - XMM11, - XMM12, - XMM13, - XMM14, - XMM15, -#endif - - // ======================================================================== - // >> 16-bit Segment registers - // ======================================================================== - CS, - SS, - DS, - ES, - FS, - GS, - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - ST0, - ST1, - ST2, - ST3, - ST4, - ST5, - ST6, - ST7, -}; - - -// ============================================================================ -// >> CRegister -// ============================================================================ -class CRegister -{ -public: - CRegister(uint16_t iSize, uint16_t iAlignment = 0) - { - m_iSize = iSize; - m_iAlignment = iAlignment; - if (iAlignment > 0) -#ifdef KE_WINDOWS - m_pAddress = _aligned_malloc(iSize, iAlignment); -#else - m_pAddress = aligned_alloc(iAlignment, iSize); -#endif - else - m_pAddress = malloc(iSize); - } - - ~CRegister() - { - -#ifdef KE_WINDOWS - if (m_iAlignment > 0) - _aligned_free(m_pAddress); - else - free(m_pAddress); -#else - free(m_pAddress); -#endif - } - - template - T GetValue() - { - return *(T *) m_pAddress; - } - - template - T GetPointerValue(int iOffset=0) - { - return *(T *) (GetValue() + iOffset); - } - - template - void SetValue(T value) - { - *(T *) m_pAddress = value; - } - - template - void SetPointerValue(T value, int iOffset=0) - { - *(T *) (GetValue() + iOffset) = value; - } - -public: - uint16_t m_iSize; - uint16_t m_iAlignment; - void* m_pAddress; -}; - - -// ============================================================================ -// >> CRegisters -// ============================================================================ -class CRegisters -{ -public: - CRegisters(std::vector registers); - ~CRegisters(); - - CRegister* GetRegister(Register_t reg); - -private: - CRegister* CreateRegister(std::vector& registers, Register_t reg, uint16_t iSize, uint16_t iAlignment = 0); - void DeleteRegister(CRegister* pRegister); - -public: - // ======================================================================== - // >> 8-bit General purpose registers - // ======================================================================== - CRegister* m_al; - CRegister* m_cl; - CRegister* m_dl; - CRegister* m_bl; - - // 64-bit mode only - /* - CRegister* m_spl; - CRegister* m_bpl; - CRegister* m_sil; - CRegister* m_dil; - CRegister* m_r8b; - CRegister* m_r9b; - CRegister* m_r10b; - CRegister* m_r11b; - CRegister* m_r12b; - CRegister* m_r13b; - CRegister* m_r14b; - CRegister* m_r15b; - */ - - CRegister* m_ah; - CRegister* m_ch; - CRegister* m_dh; - CRegister* m_bh; - - // ======================================================================== - // >> 16-bit General purpose registers - // ======================================================================== - CRegister* m_ax; - CRegister* m_cx; - CRegister* m_dx; - CRegister* m_bx; - CRegister* m_sp; - CRegister* m_bp; - CRegister* m_si; - CRegister* m_di; - - // 64-bit mode only - /* - CRegister* m_r8w; - CRegister* m_r9w; - CRegister* m_r10w; - CRegister* m_r11w; - CRegister* m_r12w; - CRegister* m_r13w; - CRegister* m_r14w; - CRegister* m_r15w; - */ - - // ======================================================================== - // >> 32-bit General purpose registers - // ======================================================================== - CRegister* m_eax; - CRegister* m_ecx; - CRegister* m_edx; - CRegister* m_ebx; - CRegister* m_esp; - CRegister* m_ebp; - CRegister* m_esi; - CRegister* m_edi; - - // 64-bit mode only - /* - CRegister* m_r8d; - CRegister* m_r9d; - CRegister* m_r10d; - CRegister* m_r11d; - CRegister* m_r12d; - CRegister* m_r13d; - CRegister* m_r14d; - CRegister* m_r15d; - */ - - // ======================================================================== - // >> 64-bit General purpose registers - // ======================================================================== - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - CRegister* m_rax; - CRegister* m_rcx; - CRegister* m_rdx; - CRegister* m_rbx; - CRegister* m_rsp; - CRegister* m_rbp; - CRegister* m_rsi; - CRegister* m_rdi; - - CRegister* m_r8; - CRegister* m_r9; - CRegister* m_r10; - CRegister* m_r11; - CRegister* m_r12; - CRegister* m_r13; - CRegister* m_r14; - CRegister* m_r15; -#endif - - // ======================================================================== - // >> 64-bit MM (MMX) registers - // ======================================================================== - CRegister* m_mm0; - CRegister* m_mm1; - CRegister* m_mm2; - CRegister* m_mm3; - CRegister* m_mm4; - CRegister* m_mm5; - CRegister* m_mm6; - CRegister* m_mm7; - - // ======================================================================== - // >> 128-bit XMM registers - // ======================================================================== - CRegister* m_xmm0; - CRegister* m_xmm1; - CRegister* m_xmm2; - CRegister* m_xmm3; - CRegister* m_xmm4; - CRegister* m_xmm5; - CRegister* m_xmm6; - CRegister* m_xmm7; - - // 64-bit mode only -#ifdef DYNAMICHOOKS_x86_64 - CRegister* m_xmm8; - CRegister* m_xmm9; - CRegister* m_xmm10; - CRegister* m_xmm11; - CRegister* m_xmm12; - CRegister* m_xmm13; - CRegister* m_xmm14; - CRegister* m_xmm15; -#endif - - // ======================================================================== - // >> 16-bit Segment registers - // ======================================================================== - CRegister* m_cs; - CRegister* m_ss; - CRegister* m_ds; - CRegister* m_es; - CRegister* m_fs; - CRegister* m_gs; - - // ======================================================================== - // >> 80-bit FPU registers - // ======================================================================== - CRegister* m_st0; - CRegister* m_st1; - CRegister* m_st2; - CRegister* m_st3; - CRegister* m_st4; - CRegister* m_st5; - CRegister* m_st6; - CRegister* m_st7; -}; - -#endif // _REGISTERS_H \ No newline at end of file diff --git a/extensions/dhooks/dynhooks_sourcepawn.cpp b/extensions/dhooks/dynhooks_sourcepawn.cpp deleted file mode 100644 index 9f7057c3e5..0000000000 --- a/extensions/dhooks/dynhooks_sourcepawn.cpp +++ /dev/null @@ -1,732 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "dynhooks_sourcepawn.h" -#include "util.h" -#include - -#ifdef KE_WINDOWS -#ifdef DYNAMICHOOKS_x86_64 -#include "conventions/x86_64MicrosoftDefault.h" -typedef x86_64MicrosoftDefault x86_64DetourCall; -#else -#include "conventions/x86MsCdecl.h" -#include "conventions/x86MsThiscall.h" -#include "conventions/x86MsStdcall.h" -#include "conventions/x86MsFastcall.h" -typedef x86MsCdecl x86DetourCdecl; -typedef x86MsThiscall x86DetourThisCall; -typedef x86MsStdcall x86DetourStdCall; -typedef x86MsFastcall x86DetourFastCall; -#endif -#elif defined KE_LINUX -#ifdef DYNAMICHOOKS_x86_64 -#else -#include "conventions/x86GccCdecl.h" -#include "conventions/x86GccThiscall.h" -#include "conventions/x86MsStdcall.h" -#include "conventions/x86MsFastcall.h" -typedef x86GccCdecl x86DetourCdecl; -typedef x86GccThiscall x86DetourThisCall; -// Uhm, stdcall on linux? -typedef x86MsStdcall x86DetourStdCall; -// Uhumm, fastcall on linux? -typedef x86MsFastcall x86DetourFastCall; -#endif -#else -#error "Unsupported platform." -#endif - -// Keep a map of detours and their registered plugin callbacks. -DetourMap g_pPreDetours; -DetourMap g_pPostDetours; - -void UnhookFunction(HookType_t hookType, CHook *pDetour) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - CHookManager *pDetourManager = GetHookManager(); - pDetour->RemoveCallback(hookType, (HookHandlerFn *)(void *)&HandleDetour); - // Only disable the detour if there are no more listeners. - if (!pDetour->AreCallbacksRegistered()) - pDetourManager->UnhookFunction(pDetour->m_pFunc); -#endif -} - -bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup, IPluginFunction *pCallback) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - DetourMap *map; - if (hookType == HOOKTYPE_PRE) - map = &g_pPreDetours; - else - map = &g_pPostDetours; - - // See if we already have this detour in our list. - PluginCallbackList *wrappers; - DetourMap::Insert f = map->findForAdd(pDetour); - if (f.found()) - { - wrappers = f->value; - } - else - { - // Create a vector to store all the plugin callbacks in. - wrappers = new PluginCallbackList; - if (!map->add(f, pDetour, wrappers)) - { - delete wrappers; - UnhookFunction(hookType, pDetour); - return false; - } - } - - // Add the plugin callback to the detour list. - CDynamicHooksSourcePawn *pWrapper = new CDynamicHooksSourcePawn(setup, pDetour, pCallback, pCallback->GetParentRuntime()->FindPubvarByName("__Int64_Address__", nullptr) == SP_ERROR_NONE, hookType == HOOKTYPE_POST); - wrappers->push_back(pWrapper); - - return true; -#else - return false; -#endif -} - -bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction *pCallback) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - DetourMap *map; - if (hookType == HOOKTYPE_PRE) - map = &g_pPreDetours; - else - map = &g_pPostDetours; - - DetourMap::Result res = map->find(pDetour); - if (!res.found()) - return false; - - // Remove the plugin's callback - bool bRemoved = false; - PluginCallbackList *wrappers = res->value; - for (int i = wrappers->size()-1; i >= 0 ; i--) - { - CDynamicHooksSourcePawn *pWrapper = wrappers->at(i); - if (pWrapper->plugin_callback == pCallback) - { - bRemoved = true; - delete pWrapper; - wrappers->erase(wrappers->begin() + i); - } - } - - // No more plugin hooks on this callback. Free our structures. - if (wrappers->empty()) - { - delete wrappers; - UnhookFunction(hookType, pDetour); - map->remove(res); - } - - return bRemoved; -#else - return false; -#endif -} - -void RemoveAllCallbacksForContext(HookType_t hookType, DetourMap *map, IPluginContext *pContext) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - PluginCallbackList *wrappers; - CDynamicHooksSourcePawn *pWrapper; - DetourMap::iterator it = map->iter(); - // Run through all active detours we added. - for (; !it.empty(); it.next()) - { - wrappers = it->value; - // See if there are callbacks of this plugin context registered - // and remove them. - for (int i = wrappers->size() - 1; i >= 0; i--) - { - pWrapper = wrappers->at(i); - if (pWrapper->plugin_callback->GetParentRuntime()->GetDefaultContext() != pContext) - continue; - - delete pWrapper; - wrappers->erase(wrappers->begin() + i); - } - - // No plugin interested in this hook anymore. unhook. - if (wrappers->empty()) - { - delete wrappers; - UnhookFunction(hookType, it->key); - it.erase(); - } - } -#endif -} - -void RemoveAllCallbacksForContext(IPluginContext *pContext) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - RemoveAllCallbacksForContext(HOOKTYPE_PRE, &g_pPreDetours, pContext); - RemoveAllCallbacksForContext(HOOKTYPE_POST, &g_pPostDetours, pContext); -#endif -} - -void CleanupDetours(HookType_t hookType, DetourMap *map) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - PluginCallbackList *wrappers; - CDynamicHooksSourcePawn *pWrapper; - DetourMap::iterator it = map->iter(); - // Run through all active detours we added. - for (; !it.empty(); it.next()) - { - wrappers = it->value; - // Remove all callbacks - for (int i = wrappers->size() - 1; i >= 0; i--) - { - pWrapper = wrappers->at(i); - delete pWrapper; - } - - // Unhook the function - delete wrappers; - UnhookFunction(hookType, it->key); - } - map->clear(); -#endif -} - -void CleanupDetours() -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - CleanupDetours(HOOKTYPE_PRE, &g_pPreDetours); - CleanupDetours(HOOKTYPE_POST, &g_pPostDetours); -#endif -} - -#if defined( DHOOKS_DYNAMIC_DETOUR ) -ICallingConvention *ConstructCallingConvention(HookSetup *setup) -{ - // Convert function parameter types into DynamicHooks structures. - std::vector vecArgTypes; - for (size_t i = 0; i < setup->params.size(); i++) - { - ParamInfo &info = setup->params[i]; - DataTypeSized_t type; - type.type = DynamicHooks_ConvertParamTypeFrom(info.type); - type.size = info.size; - type.custom_register = info.custom_register; - vecArgTypes.push_back(type); - } - - DataTypeSized_t returnType; - returnType.type = DynamicHooks_ConvertReturnTypeFrom(setup->returnType); - returnType.size = 0; - // TODO: Add support for a custom return register. - returnType.custom_register = None; - -#ifdef DYNAMICHOOKS_x86_64 -#ifdef WIN32 - if (setup->callConv == CallConv_THISCALL) { - DataTypeSized_t type; - type.type = DATA_TYPE_POINTER; - type.size = GetDataTypeSize(type, sizeof(void*)); - type.custom_register = RCX; - vecArgTypes.insert(vecArgTypes.begin(), type); - } -#endif -#endif - - ICallingConvention *pCallConv = nullptr; - switch (setup->callConv) - { -#ifdef DYNAMICHOOKS_x86_64 - case CallConv_THISCALL: - case CallConv_CDECL: - case CallConv_STDCALL: - case CallConv_FASTCALL: - pCallConv = new x86_64DetourCall(vecArgTypes, returnType); - break; -#else - case CallConv_CDECL: - pCallConv = new x86DetourCdecl(vecArgTypes, returnType); - break; - case CallConv_THISCALL: - pCallConv = new x86DetourThisCall(vecArgTypes, returnType); - break; - case CallConv_STDCALL: - pCallConv = new x86DetourStdCall(vecArgTypes, returnType); - break; - case CallConv_FASTCALL: - pCallConv = new x86DetourFastCall(vecArgTypes, returnType); - break; -#endif - default: - smutils->LogError(myself, "Unknown calling convention %d.", setup->callConv); - break; - } - - return pCallConv; -} -#endif - -// Some arguments might be optimized to be passed in registers instead of the stack. -bool UpdateRegisterArgumentSizes(CHook* pDetour, HookSetup *setup) -{ - // The registers the arguments are passed in might not be the same size as the actual parameter type. - // Update the type info to the size of the register that's now holding that argument, - // so we can copy the whole value. - ICallingConvention* callingConvention = pDetour->m_pCallingConvention; - std::vector &argTypes = callingConvention->m_vecArgTypes; - int numArgs = argTypes.size(); - - for (int i = 0; i < numArgs; i++) - { - // Ignore regular arguments on the stack. - if (argTypes[i].custom_register == None) - continue; - - CRegister *reg = pDetour->m_pRegisters->GetRegister(argTypes[i].custom_register); - // That register can't be handled yet. - if (!reg) - return false; - - argTypes[i].size = reg->m_iSize; - setup->params[i].size = reg->m_iSize; - } - - return true; -} - -// Central handler for all detours. Heart of the detour support. -ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour) -{ - // Can't call into SourcePawn offthread. - if (g_MainThreadId != std::this_thread::get_id()) - return ReturnAction_Ignored; - - DetourMap *map; - if (hookType == HOOKTYPE_PRE) - map = &g_pPreDetours; - else - map = &g_pPostDetours; - - // Find the callback list for this detour. - DetourMap::Result r = map->find(pDetour); - if (!r.found()) - return ReturnAction_Ignored; - - // List of all callbacks. - PluginCallbackList *wrappers = r->value; - - HookReturnStruct *returnStruct = NULL; - Handle_t rHndl = BAD_HANDLE; - - HookParamsStruct *paramStruct = NULL; - Handle_t pHndl = BAD_HANDLE; - - int argNum = pDetour->m_pCallingConvention->m_vecArgTypes.size(); - // Keep a copy of the last return value if some plugin wants to override or supercede the function. - ReturnAction_t finalRet = ReturnAction_Ignored; - std::unique_ptr finalRetBuf = std::make_unique(pDetour->m_pCallingConvention->m_returnType.size); - - // Call all the plugin functions.. - for (size_t i = 0; i < wrappers->size(); i++) - { - CDynamicHooksSourcePawn *pWrapper = wrappers->at(i); - IPluginFunction *pCallback = pWrapper->plugin_callback; - - // Create a seperate buffer for changed return values for this plugin. - // We update the finalRet above if the tempRet is higher than the previous ones in the callback list. - ReturnAction_t tempRet = ReturnAction_Ignored; - uint8_t *tempRetBuf = nullptr; - - // Find the this pointer for thiscalls. - // Don't even try to load it if the plugin doesn't care and set it to be ignored. - if (pWrapper->callConv == CallConv_THISCALL && pWrapper->thisType != ThisPointer_Ignore) - { - // The this pointer is implicitly always the first argument. - auto thisAddr = pDetour->GetArgument(0); - if (pWrapper->thisType == ThisPointer_CBaseEntity) { - if (thisAddr == nullptr) { - pWrapper->plugin_callback->PushCell(-1); - } else { - pWrapper->plugin_callback->PushCell(gamehelpers->EntityToBCompatRef((CBaseEntity *)thisAddr)); - } - } else { - if (pWrapper->int64_address) { - std::int64_t addr = reinterpret_cast(thisAddr); - pWrapper->plugin_callback->PushArray(reinterpret_cast(&addr), 2); - } else { - pWrapper->plugin_callback->PushCell((cell_t)thisAddr); - } - } - } - - // Create the structure for plugins to change/get the return value if the function returns something. - if (pWrapper->returnType != ReturnType_Void) - { - // Create a handle for the return value to pass to the plugin callback. - returnStruct = pWrapper->GetReturnStruct(); - HandleError err; - rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, pCallback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), &err); - if (!rHndl) - { - pCallback->Cancel(); - pCallback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(pCallback, "Error creating ReturnHandle in preparation to call hook callback. (error %d)", err); - - if (returnStruct) - delete returnStruct; - - // Don't call more callbacks. They will probably fail too. - break; - } - pCallback->PushCell(rHndl); - } - - // Create the structure for plugins to access the function arguments if it has some. - if (argNum > 0) - { - paramStruct = pWrapper->GetParamStruct(); - HandleError err; - pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, pCallback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), &err); - if (!pHndl) - { - pCallback->Cancel(); - pCallback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(pCallback, "Error creating ThisHandle in preparation to call hook callback. (error %d)", err); - - // Don't leak our own handles here! Free the return struct if we fail during the argument marshalling. - if (rHndl) - { - HandleSecurity sec(pCallback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - handlesys->FreeHandle(rHndl, &sec); - rHndl = BAD_HANDLE; - } - - if (paramStruct) - delete paramStruct; - - // Don't call more callbacks. They will probably fail too. - break; - } - pCallback->PushCell(pHndl); - } - - // Run the plugin callback. - cell_t result = (cell_t)MRES_Ignored; - pCallback->Execute(&result); - - switch ((MRESReturn)result) - { - case MRES_Handled: - tempRet = ReturnAction_Handled; - break; - case MRES_ChangedHandled: - tempRet = ReturnAction_Handled; - // Copy the changed parameter values from the plugin's parameter structure back into the actual detour arguments. - pWrapper->UpdateParamsFromStruct(paramStruct); - break; - case MRES_ChangedOverride: - case MRES_Override: - case MRES_Supercede: - // See if this function returns something we should override. - if (pWrapper->returnType != ReturnType_Void) - { - // Make sure the plugin provided a new return value. Could be an oversight if MRES_ChangedOverride - // is called without the return value actually being changed. - if (!returnStruct->isChanged) - { - //Throw an error if no override was set - tempRet = ReturnAction_Ignored; - pCallback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(pCallback, "Tried to override return value without return value being set"); - break; - } - - if (pWrapper->returnType == ReturnType_String || pWrapper->returnType == ReturnType_Int || pWrapper->returnType == ReturnType_Bool) - { - tempRetBuf = *(uint8_t **)returnStruct->newResult; - } - else if (pWrapper->returnType == ReturnType_Float) - { - *(float *)&tempRetBuf = *(float *)returnStruct->newResult; - } - else - { - tempRetBuf = (uint8_t *)returnStruct->newResult; - } - } - - // Store if the plugin wants the original function to be called. - if (result == MRES_Supercede) - tempRet = ReturnAction_Supercede; - else - tempRet = ReturnAction_Override; - - // Copy the changed parameter values from the plugin's parameter structure back into the actual detour arguments. - if (result == MRES_ChangedOverride) - pWrapper->UpdateParamsFromStruct(paramStruct); - break; - default: - tempRet = ReturnAction_Ignored; - break; - } - - // Prioritize the actions. - if (finalRet <= tempRet) - { - // Copy the action and return value. - finalRet = tempRet; - memcpy(finalRetBuf.get(), &tempRetBuf, pDetour->m_pCallingConvention->m_returnType.size); - } - - // Free the handles again. - HandleSecurity sec(pCallback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - if (returnStruct) - { - handlesys->FreeHandle(rHndl, &sec); - } - if (paramStruct) - { - handlesys->FreeHandle(pHndl, &sec); - } - } - - // If we want to use our own return value, write it back. - if (finalRet >= ReturnAction_Override) - { - void* pPtr = pDetour->m_pCallingConvention->GetReturnPtr(pDetour->m_pRegisters); - memcpy(pPtr, finalRetBuf.get(), pDetour->m_pCallingConvention->m_returnType.size); - pDetour->m_pCallingConvention->ReturnPtrChanged(pDetour->m_pRegisters, pPtr); - } - - return finalRet; -} - -CDynamicHooksSourcePawn::CDynamicHooksSourcePawn(HookSetup *setup, CHook *pDetour, IPluginFunction *pCallback, bool int64_addr, bool post) -{ - this->params = setup->params; - this->offset = -1; - this->returnFlag = setup->returnFlag; - this->returnType = setup->returnType; - this->post = post; - this->plugin_callback = pCallback; - this->entity = -1; - this->thisType = setup->thisType; - this->hookType = setup->hookType; - this->m_pDetour = pDetour; - this->callConv = setup->callConv; - this->int64_address = int64_addr; - this->thisFuncCallConv = setup->callConv; -} - -HookReturnStruct *CDynamicHooksSourcePawn::GetReturnStruct() -{ - // Create buffers to store the return value of the function. - HookReturnStruct *res = new HookReturnStruct(); - res->isChanged = false; - res->type = this->returnType; - res->orgResult = NULL; - res->newResult = NULL; - - // Copy the actual function's return value too for post hooks. - if (this->post) - { - switch (this->returnType) - { - case ReturnType_String: - res->orgResult = malloc(sizeof(string_t)); - res->newResult = malloc(sizeof(string_t)); - *(string_t *)res->orgResult = m_pDetour->GetReturnValue(); - break; - case ReturnType_Int: - res->orgResult = malloc(sizeof(int)); - res->newResult = malloc(sizeof(int)); - *(int *)res->orgResult = m_pDetour->GetReturnValue(); - break; - case ReturnType_Bool: - res->orgResult = malloc(sizeof(bool)); - res->newResult = malloc(sizeof(bool)); - *(bool *)res->orgResult = m_pDetour->GetReturnValue(); - break; - case ReturnType_Float: - res->orgResult = malloc(sizeof(float)); - res->newResult = malloc(sizeof(float)); - *(float *)res->orgResult = m_pDetour->GetReturnValue(); - break; - case ReturnType_Vector: - { - res->orgResult = malloc(sizeof(SDKVector)); - res->newResult = malloc(sizeof(SDKVector)); - SDKVector vec = m_pDetour->GetReturnValue(); - *(SDKVector *)res->orgResult = vec; - break; - } - default: - res->orgResult = m_pDetour->GetReturnValue(); - break; - } - } - // Pre hooks don't have access to the return value yet - duh. - // Just create the buffers for overridden values. - // TODO: Strip orgResult malloc. - else - { - switch (this->returnType) - { - case ReturnType_String: - res->orgResult = malloc(sizeof(string_t)); - res->newResult = malloc(sizeof(string_t)); - *(string_t *)res->orgResult = NULL_STRING; - break; - case ReturnType_Vector: - res->orgResult = malloc(sizeof(SDKVector)); - res->newResult = malloc(sizeof(SDKVector)); - *(SDKVector *)res->orgResult = SDKVector(); - break; - case ReturnType_Int: - res->orgResult = malloc(sizeof(int)); - res->newResult = malloc(sizeof(int)); - *(int *)res->orgResult = 0; - break; - case ReturnType_Bool: - res->orgResult = malloc(sizeof(bool)); - res->newResult = malloc(sizeof(bool)); - *(bool *)res->orgResult = false; - break; - case ReturnType_Float: - res->orgResult = malloc(sizeof(float)); - res->newResult = malloc(sizeof(float)); - *(float *)res->orgResult = 0.0; - break; - } - } - - return res; -} - -HookParamsStruct *CDynamicHooksSourcePawn::GetParamStruct() -{ - // Save argument values of detoured function. - HookParamsStruct *params = new HookParamsStruct(); - params->dg = this; - - ICallingConvention* callingConvention = m_pDetour->m_pCallingConvention; - size_t stackSize = callingConvention->GetArgStackSize(); - size_t paramsSize = stackSize + callingConvention->GetArgRegisterSize(); - std::vector &argTypes = callingConvention->m_vecArgTypes; - size_t numArgs = argTypes.size(); - - // Create space for original parameters and changes plugins might do. - params->orgParams = (void **)malloc(paramsSize); - params->newParams = (void **)malloc(paramsSize); - params->isChanged = (bool *)malloc(numArgs * sizeof(bool)); - - // Save old stack parameters. - if (stackSize > 0) - { - void *pArgPtr = m_pDetour->m_pCallingConvention->GetStackArgumentPtr(m_pDetour->m_pRegisters); - memcpy(params->orgParams, pArgPtr, stackSize); - } - - memset(params->newParams, 0, paramsSize); - memset(params->isChanged, false, numArgs * sizeof(bool)); - - size_t firstArg = 0; - // TODO: Support custom register for this ptr. - if (callConv == CallConv_THISCALL) - firstArg = 1; - - // Save the old parameters passed in a register. - size_t offset = stackSize; - for (size_t i = firstArg; i < numArgs; i++) - { - // We already saved the stack arguments. - if (argTypes[i].custom_register == None) - continue; - - size_t size = argTypes[i].size; - // Register argument values are saved after all stack arguments in this buffer. - void *paramAddr = (void *)((intptr_t)params->orgParams + offset); - void *regAddr = callingConvention->GetArgumentPtr(i, m_pDetour->m_pRegisters); - memcpy(paramAddr, regAddr, size); - offset += size; - } - - return params; -} - -void CDynamicHooksSourcePawn::UpdateParamsFromStruct(HookParamsStruct *params) -{ - // Function had no params to update now. - if (!params) - return; - - ICallingConvention* callingConvention = m_pDetour->m_pCallingConvention; - size_t stackSize = callingConvention->GetArgStackSize(); - std::vector &argTypes = callingConvention->m_vecArgTypes; - size_t numArgs = argTypes.size(); - - size_t firstArg = 0; - // TODO: Support custom register for this ptr. - if (callConv == CallConv_THISCALL) - firstArg = 1; - size_t stackOffset = 0; - // Values of arguments stored in registers are saved after the stack arguments. - size_t registerOffset = stackSize; - size_t offset; - for (size_t i = 0; i < numArgs; i++) - { - size_t size = argTypes[i].size; - // Only have to copy something if the plugin changed this parameter. - if (params->isChanged[i]) - { - // Get the offset of this argument in the linear buffer. Register argument values are placed after all stack arguments. - offset = argTypes[i].custom_register == None ? stackOffset : registerOffset; - - void *paramAddr = (void *)((intptr_t)params->newParams + offset); - void *stackAddr = callingConvention->GetArgumentPtr(i + firstArg, m_pDetour->m_pRegisters); - memcpy(stackAddr, paramAddr, size); - } - - // Keep track of the seperate stack and register arguments. - if (argTypes[i].custom_register == None) { -#ifdef DYNAMICHOOKS_x86_64 - stackOffset += 8; -#else - stackOffset += size; -#endif - } - else { - registerOffset += size; - } - } -} diff --git a/extensions/dhooks/dynhooks_sourcepawn.h b/extensions/dhooks/dynhooks_sourcepawn.h deleted file mode 100644 index bc69862a0e..0000000000 --- a/extensions/dhooks/dynhooks_sourcepawn.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_DYNHOOKS_SP_H_ -#define _INCLUDE_DYNHOOKS_SP_H_ - -#include "manager.h" -#include "vhook.h" -#include - -class CDynamicHooksSourcePawn; -typedef ke::HashMap> CallbackMap; -typedef std::vector PluginCallbackList; -typedef ke::HashMap> DetourMap; - -//extern ke::Vector g_pDetours; -// Keep a list of plugin callback -> Hook wrapper for easily removing plugin hooks -//extern CallbackMap g_pPluginPreDetours; -//extern CallbackMap g_pPluginPostDetours; -// Keep a list of hook -> callbacks for calling in the detour handler -extern DetourMap g_pPreDetours; -extern DetourMap g_pPostDetours; - -class CDynamicHooksSourcePawn : public DHooksInfo { -public: - CDynamicHooksSourcePawn(HookSetup *setup, CHook *pDetour, IPluginFunction *pCallback, bool int64_address, bool post); - - HookReturnStruct *GetReturnStruct(); - HookParamsStruct *GetParamStruct(); - void UpdateParamsFromStruct(HookParamsStruct *params); - -public: - CHook *m_pDetour; - CallingConvention callConv; -}; - -#if defined( DHOOKS_DYNAMIC_DETOUR ) -ICallingConvention *ConstructCallingConvention(HookSetup *setup); -#endif -bool UpdateRegisterArgumentSizes(CHook* pDetour, HookSetup *setup); -ReturnAction_t HandleDetour(HookType_t hookType, CHook* pDetour); -bool AddDetourPluginHook(HookType_t hookType, CHook *pDetour, HookSetup *setup, IPluginFunction *pCallback); -bool RemoveDetourPluginHook(HookType_t hookType, CHook *pDetour, IPluginFunction *pCallback); -void RemoveAllCallbacksForContext(IPluginContext *pContext); -void CleanupDetours(); - -#endif \ No newline at end of file diff --git a/extensions/dhooks/extension.cpp b/extensions/dhooks/extension.cpp deleted file mode 100644 index dbd11055d4..0000000000 --- a/extensions/dhooks/extension.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "extension.h" -#include "listeners.h" -#include "dynhooks_sourcepawn.h" -#include "signatures.h" - -DHooks g_DHooksIface; /**< Global singleton for extension's main interface */ -SMEXT_LINK(&g_DHooksIface); - -IBinTools *g_pBinTools; -ISDKHooks *g_pSDKHooks; -ISDKTools *g_pSDKTools; -DHooksEntityListener *g_pEntityListener = NULL; - -HandleType_t g_HookSetupHandle = 0; -HandleType_t g_HookParamsHandle = 0; -HandleType_t g_HookReturnHandle = 0; - -std::thread::id g_MainThreadId; - -bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late) -{ - HandleError err; - g_HookSetupHandle = handlesys->CreateType("HookSetup", this, 0, NULL, NULL, myself->GetIdentity(), &err); - if(g_HookSetupHandle == 0) - { - snprintf(error, maxlength, "Could not create hook setup handle type (err: %d)", err); - return false; - } - g_HookParamsHandle = handlesys->CreateType("HookParams", this, 0, NULL, NULL, myself->GetIdentity(), &err); - if(g_HookParamsHandle == 0) - { - snprintf(error, maxlength, "Could not create hook params handle type (err: %d)", err); - return false; - } - g_HookReturnHandle = handlesys->CreateType("HookReturn", this, 0, NULL, NULL, myself->GetIdentity(), &err); - if(g_HookReturnHandle == 0) - { - snprintf(error, maxlength, "Could not create hook return handle type (err: %d)", err); - return false; - } - - if (!g_pPreDetours.init()) - { - snprintf(error, maxlength, "Could not initialize pre hook detours hashmap."); - return false; - } - - if (!g_pPostDetours.init()) - { - snprintf(error, maxlength, "Could not initialize post hook detours hashmap."); - return false; - } - - sharesys->AddDependency(myself, "bintools.ext", true, true); - sharesys->AddDependency(myself, "sdktools.ext", true, true); - sharesys->AddDependency(myself, "sdkhooks.ext", true, true); - - sharesys->RegisterLibrary(myself, "dhooks"); - plsys->AddPluginsListener(this); - sharesys->AddNatives(myself, g_Natives); - - g_pEntityListener = new DHooksEntityListener(); - g_pSignatures = new SignatureGameConfig(); - g_MainThreadId = std::this_thread::get_id(); - - return true; -} - -void DHooks::OnHandleDestroy(HandleType_t type, void *object) -{ - if(type == g_HookSetupHandle) - { - delete (HookSetup *)object; - } - else if(type == g_HookParamsHandle) - { - delete (HookParamsStruct *)object; - } - else if(type == g_HookReturnHandle) - { - delete (HookReturnStruct *)object; - } -} - -void DHooks::SDK_OnAllLoaded() -{ - SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools); - SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools); - SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks); - - if (g_pSDKHooks) - { - g_pSDKHooks->AddEntityListener(g_pEntityListener); - } - gameconfs->AddUserConfigHook("Functions", g_pSignatures); -} - -void DHooks::SDK_OnUnload() -{ - CleanupHooks(); - CleanupDetours(); - if(g_pEntityListener) - { - g_pEntityListener->CleanupListeners(); - g_pEntityListener->CleanupRemoveList(); - if (g_pSDKHooks) - { - g_pSDKHooks->RemoveEntityListener(g_pEntityListener); - } - delete g_pEntityListener; - } - plsys->RemovePluginsListener(this); - - handlesys->RemoveType(g_HookSetupHandle, myself->GetIdentity()); - handlesys->RemoveType(g_HookParamsHandle, myself->GetIdentity()); - handlesys->RemoveType(g_HookReturnHandle, myself->GetIdentity()); - - gameconfs->RemoveUserConfigHook("Functions", g_pSignatures); -} - -bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late) -{ - if(!SetupHookManager(ismm)) - { - snprintf(error, maxlength, "Failed to get IHookManagerAutoGen iface"); - return false; - } - return true; -} - -void DHooks::OnPluginUnloaded(IPlugin *plugin) -{ - CleanupHooks(plugin->GetBaseContext()); - RemoveAllCallbacksForContext(plugin->GetBaseContext()); - if(g_pEntityListener) - { - g_pEntityListener->CleanupListeners(plugin->GetBaseContext()); - } -} -// The next 3 functions handle cleanup if our interfaces are going to be unloaded -bool DHooks::QueryRunning(char *error, size_t maxlength) -{ - SM_CHECK_IFACE(SDKTOOLS, g_pSDKTools); - SM_CHECK_IFACE(BINTOOLS, g_pBinTools); - SM_CHECK_IFACE(SDKHOOKS, g_pSDKHooks); - return true; -} -void DHooks::NotifyInterfaceDrop(SMInterface *pInterface) -{ - if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_SDKHOOKS_NAME) == 0) - { - if(g_pEntityListener) - { - // If this fails, remove this line and just delete the ent listener instead - g_pSDKHooks->RemoveEntityListener(g_pEntityListener); - - g_pEntityListener->CleanupListeners(); - delete g_pEntityListener; - g_pEntityListener = NULL; - } - g_pSDKHooks = NULL; - } - else if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_BINTOOLS_NAME) == 0) - { - g_pBinTools = NULL; - } - else if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_SDKTOOLS_NAME) == 0) - { - g_pSDKTools = NULL; - } -} diff --git a/extensions/dhooks/extension.h b/extensions/dhooks/extension.h deleted file mode 100644 index 2d3f390708..0000000000 --- a/extensions/dhooks/extension.h +++ /dev/null @@ -1,134 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ - -/** - * @file extension.h - * @brief Sample extension code header. - */ - -#include "smsdk_ext.h" - -#include -#include -#include -#include "sdk-hacks.h" -#include - -/** - * @brief Sample implementation of the SDK Extension. - * Note: Uncomment one of the pre-defined virtual functions in order to use it. - */ - -class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch -{ -public: - virtual void OnHandleDestroy(HandleType_t type, void *object); -public: //IPluginsListener - virtual void OnPluginUnloaded(IPlugin *plugin); -public: - /** - * @brief This is called after the initial loading sequence has been processed. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @param late Whether or not the module was loaded after map load. - * @return True to succeed loading, false to fail. - */ - virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); - - /** - * @brief This is called right before the extension is unloaded. - */ - virtual void SDK_OnUnload(); - - /** - * @brief This is called once all known extensions have been loaded. - * Note: It is is a good idea to add natives here, if any are provided. - */ - virtual void SDK_OnAllLoaded(); - - /** - * @brief Called when the pause state is changed. - */ - //virtual void SDK_OnPauseChange(bool paused); - - /** - * @brief this is called when Core wants to know if your extension is working. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @return True if working, false otherwise. - */ - virtual bool QueryRunning(char *error, size_t maxlength); - //virtual bool QueryInterfaceDrop(SMInterface *pInterface); - virtual void NotifyInterfaceDrop(SMInterface *pInterface); - virtual void OnCoreMapEnd(); -public: -#if defined SMEXT_CONF_METAMOD - /** - * @brief Called when Metamod is attached, before the extension version is called. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @param late Whether or not Metamod considers this a late load. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); - - /** - * @brief Called when Metamod is detaching, after the extension version is called. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); - - /** - * @brief Called when Metamod's pause state is changing. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param paused Pause state being set. - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); -#endif -}; -extern SourceHook::IHookManagerAutoGen *g_pHookManager; -extern sp_nativeinfo_t g_Natives[]; -extern std::thread::id g_MainThreadId; -#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/dhooks/listeners.cpp b/extensions/dhooks/listeners.cpp deleted file mode 100644 index 41a8ef101a..0000000000 --- a/extensions/dhooks/listeners.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "listeners.h" -#include "vhook.h" - -using namespace SourceHook; - -std::vector g_EntityListeners; -std::vectorg_pRemoveList; - -void FrameCleanupHooks(void *data) -{ - for (int i = g_pRemoveList.size() - 1; i >= 0; i--) - { - DHooksManager *manager = g_pRemoveList.at(i); - delete manager; - g_pRemoveList.erase(g_pRemoveList.begin() + i); - } -} - -void DHooks::OnCoreMapEnd() -{ - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->callback->hookType == HookType_GameRules) - { - delete manager; - g_pHooks.erase(g_pHooks.begin() + i); - } - } -} - -void DHooksEntityListener::CleanupListeners(IPluginContext *pContext) -{ - for(int i = g_EntityListeners.size() -1; i >= 0; i--) - { - if(pContext == NULL || pContext == g_EntityListeners.at(i).callback->GetParentRuntime()->GetDefaultContext()) - { - g_EntityListeners.erase(g_EntityListeners.begin() + i); - } - } - for (int i = g_pRemoveList.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pRemoveList.at(i); - IPluginFunction *cb = manager->callback->plugin_callback; - if (pContext == NULL || (cb && pContext == cb->GetParentRuntime()->GetDefaultContext())) - { - manager->callback->plugin_callback = nullptr; - manager->remove_callback = nullptr; - } - } -} - -void DHooksEntityListener::CleanupRemoveList() -{ - for (int i = g_pRemoveList.size() - 1; i >= 0; i--) - { - DHooksManager *manager = g_pRemoveList.at(i); - delete manager; - } - g_pRemoveList.clear(); -} - -void DHooksEntityListener::OnEntityCreated(CBaseEntity *pEntity, const char *classname) -{ - int entity = gamehelpers->EntityToBCompatRef(pEntity); - - for(int i = g_EntityListeners.size() -1; i >= 0; i--) - { - EntityListener listerner = g_EntityListeners.at(i); - if(listerner.type == ListenType_Created) - { - IPluginFunction *callback = listerner.callback; - callback->PushCell(entity); - callback->PushString(classname); - callback->Execute(NULL); - } - } -} - -void DHooksEntityListener::OnEntityDestroyed(CBaseEntity *pEntity) -{ - int entity = gamehelpers->EntityToBCompatRef(pEntity); - - for(int i = g_EntityListeners.size() -1; i >= 0; i--) - { - EntityListener listerner = g_EntityListeners.at(i); - if(listerner.type == ListenType_Deleted) - { - IPluginFunction *callback = listerner.callback; - callback->PushCell(gamehelpers->EntityToBCompatRef(pEntity)); - callback->Execute(NULL); - } - } - - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->callback->hookType == HookType_Entity && manager->callback->entity == entity) - { - if(g_pRemoveList.size() == 0) - { - smutils->AddFrameAction(&FrameCleanupHooks, NULL); - } - - g_pRemoveList.push_back(manager); - g_pHooks.erase(g_pHooks.begin() + i); - } - } -} -bool DHooksEntityListener::AddPluginEntityListener(ListenType type, IPluginFunction *callback) -{ - for(int i = g_EntityListeners.size() -1; i >= 0; i--) - { - EntityListener listerner = g_EntityListeners.at(i); - if(listerner.callback == callback && listerner.type == type) - { - return true; - } - } - EntityListener listener; - listener.callback = callback; - listener.type = type; - g_EntityListeners.push_back(listener); - return true; -} -bool DHooksEntityListener::RemovePluginEntityListener(ListenType type, IPluginFunction *callback) -{ - for(int i = g_EntityListeners.size() -1; i >= 0; i--) - { - EntityListener listerner = g_EntityListeners.at(i); - if(listerner.callback == callback && listerner.type == type) - { - g_EntityListeners.erase(g_EntityListeners.begin() + i); - return true; - } - } - return false; -} diff --git a/extensions/dhooks/listeners.h b/extensions/dhooks/listeners.h deleted file mode 100644 index 2a624fb924..0000000000 --- a/extensions/dhooks/listeners.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_LISTENERS_H_ -#define _INCLUDE_LISTENERS_H_ - -#include "extension.h" -#include "vhook.h" - -enum ListenType -{ - ListenType_Created, - ListenType_Deleted -}; - -class DHooksEntityListener : public ISMEntityListener -{ -public: - virtual void OnEntityCreated(CBaseEntity *pEntity, const char *classname); - virtual void OnEntityDestroyed(CBaseEntity *pEntity); - void CleanupListeners(IPluginContext *func = NULL); - void CleanupRemoveList(); - bool AddPluginEntityListener(ListenType type, IPluginFunction *callback); - bool RemovePluginEntityListener(ListenType type, IPluginFunction *callback); -}; - - -struct EntityListener -{ - ListenType type; - IPluginFunction *callback; -}; - -extern std::vector g_pHooks; -#endif diff --git a/extensions/dhooks/natives.cpp b/extensions/dhooks/natives.cpp deleted file mode 100644 index 8127ae3e4b..0000000000 --- a/extensions/dhooks/natives.cpp +++ /dev/null @@ -1,1593 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "natives.h" -#include "util.h" -#include "dynhooks_sourcepawn.h" -#include "signatures.h" - -// Must match same enum in sdktools.inc -enum SDKFuncConfSource -{ - SDKConf_Virtual, - SDKConf_Signature, - SDKConf_Address -}; - -using ParamVector = SourceHook::CVector; - -bool GetHandleIfValidOrError(HandleType_t type, void **object, IPluginContext *pContext, cell_t param) -{ - if(param == BAD_HANDLE) - { - return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE) != 0; - } - - HandleError err; - HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); - - if((err = handlesys->ReadHandle(param, type, &sec, object)) != HandleError_None) - { - return pContext->ThrowNativeError("Invalid Handle %x (error %d)", param, err) != 0; - } - return true; -} - -bool GetCallbackArgHandleIfValidOrError(HandleType_t type, HandleType_t otherType, void **object, IPluginContext *pContext, cell_t param) -{ - if (param == BAD_HANDLE) - { - return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE) != 0; - } - - HandleError err; - HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); - - if ((err = handlesys->ReadHandle(param, type, &sec, object)) != HandleError_None) - { - // Check if the user mixed up the callback signature and tried to call - // e.g. DHookGetParam on a hReturn handle. Print a nicer error message in that case. - void *dummy; - if (handlesys->ReadHandle(param, otherType, &sec, &dummy) == HandleError_None) - return pContext->ThrowNativeError("Invalid Handle %x (error %d). It looks like you've chosen the wrong hook callback signature for your setup and you're trying to access the wrong handle.", param, err) != 0; - return pContext->ThrowNativeError("Invalid Handle %x (error %d)", param, err) != 0; - } - return true; -} - -bool GetObjectAddrOrThis(IPluginContext *pContext, const cell_t *params, void *&retAddr) -{ - HookParamsStruct *paramStruct = NULL; - retAddr = NULL; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return false; - } - - if(params[2] != 0) - { - const ParamVector ¶msVec = paramStruct->dg->params; - - if(params[2] < 0 || params[2] > static_cast(paramsVec.size())) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramsVec.size()); - } - - int index = params[2] - 1; - const ParamInfo ¶m = paramsVec.at(index); - - if(param.type != HookParamType_ObjectPtr && param.type != HookParamType_Object) - { - return pContext->ThrowNativeError("Invalid object value type %i", param.type); - } - - size_t offset = GetParamOffset(paramStruct, index); - retAddr = GetObjectAddr(param.type, param.flags, paramStruct->orgParams, offset); - return true; - } - - const DHooksInfo* dgInfo = paramStruct->dg; - - if(dgInfo->thisFuncCallConv != CallConv_THISCALL) - { - return pContext->ThrowNativeError("Parameter 'this' is only available in member functions"); - } - - if(dgInfo->thisType != ThisPointer_Address - && dgInfo->thisType != ThisPointer_CBaseEntity - && dgInfo->hookType != HookType_GameRules) - { - return pContext->ThrowNativeError("Parameter 'this' is not specified as an address, it is not available"); - } - - retAddr = g_SHPtr->GetIfacePtr(); - return true; -} - -IPluginFunction *GetCallback(IPluginContext *pContext, HookSetup * setup, const cell_t *params, cell_t callback_index) -{ - IPluginFunction *ret = NULL; - - if (params[0] >= callback_index) - { - ret = pContext->GetFunctionById(params[callback_index]); - } - - if (!ret && setup->callback) - { - ret = setup->callback; - } - - return ret; -} - -//native Handle:DHookCreate(offset, HookType:hooktype, ReturnType:returntype, ThisPointerType:thistype, DHookCallback:callback = INVALID_FUNCTION); // Callback is now optional here. -cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params) -{ - IPluginFunction *callback = nullptr; - // The methodmap constructor doesn't have the callback parameter anymore. - if (params[0] >= 5) - callback = pContext->GetFunctionById(params[5]); - - HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (HookType)params[2], (ThisPointerType)params[4], params[1], callback); - - Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL); - - if(!hndl) - { - delete setup; - return pContext->ThrowNativeError("Failed to create hook"); - } - - return hndl; -} - -//native Handle:DHookCreateDetour(Address:funcaddr, CallingConvention:callConv, ReturnType:returntype, ThisPointerType:thistype); -cell_t Native_CreateDetour(IPluginContext *pContext, const cell_t *params) -{ - void *addr = reinterpret_cast(params[1]); - if (pContext->GetRuntime()->FindPubvarByName("__Int64_Address__", nullptr) == SP_ERROR_NONE) { - cell_t* sp_addr; - if (int err = pContext->LocalToPhysAddr(params[1], &sp_addr); err != SP_ERROR_NONE) { - return pContext->ThrowNativeErrorEx(err, "Could not read argument"); - } - auto value = *reinterpret_cast(sp_addr); - addr = (void*)value; - } - - HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL, (CallingConvention)params[2], (ThisPointerType)params[4], addr); - - Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL); - - if (!hndl) - { - delete setup; - return pContext->ThrowNativeError("Failed to create hook"); - } - - return hndl; -} - -// native Handle:DHookCreateFromConf(Handle:gameconf, const String:function[]); -cell_t Native_DHookCreateFromConf(IPluginContext *pContext, const cell_t *params) -{ - IGameConfig *conf; - HandleError err; - if ((conf = gameconfs->ReadHandle(params[1], pContext->GetIdentity(), &err)) == nullptr) - { - return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err); - } - - char *function; - pContext->LocalToString(params[2], &function); - - SignatureWrapper *sig = g_pSignatures->GetFunctionSignature(function); - if (!sig) - { - return pContext->ThrowNativeError("Function signature \"%s\" was not found.", function); - } - - HookSetup *setup = nullptr; - // This is a virtual hook. - if (sig->offset.length() > 0) - { - int offset; - if (!conf->GetOffset(sig->offset.c_str(), &offset)) - { - return BAD_HANDLE; - } - - setup = new HookSetup(sig->retType, PASSFLAG_BYVAL, sig->hookType, sig->thisType, offset, nullptr); - } - // This is a detour. - else - { - void *addr = nullptr;; - if (sig->signature.length() > 0) - { - if (!conf->GetMemSig(sig->signature.c_str(), &addr) || !addr) - { - return BAD_HANDLE; - } - } - else - { - if (!conf->GetAddress(sig->address.c_str(), &addr) || !addr) - { - return BAD_HANDLE; - } - } - - setup = new HookSetup(sig->retType, PASSFLAG_BYVAL, sig->callConv, sig->thisType, addr); - } - - // Push all the arguments. - for (ArgumentInfo &arg : sig->args) - { - ParamInfo info = arg.info; - setup->params.push_back(info); - } - - // Create the handle to hold this setup. - Handle_t hndl = handlesys->CreateHandle(g_HookSetupHandle, setup, pContext->GetIdentity(), myself->GetIdentity(), NULL); - if (!hndl) - { - delete setup; - return pContext->ThrowNativeError("Failed to create hook"); - } - - return hndl; -} - -//native bool:DHookSetFromConf(Handle:setup, Handle:gameconf, SDKFuncConfSource:source, const String:name[]); -cell_t Native_SetFromConf(IPluginContext *pContext, const cell_t *params) -{ - HookSetup *setup; - if (!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - IGameConfig *conf; - HandleError err; - if ((conf = gameconfs->ReadHandle(params[2], pContext->GetIdentity(), &err)) == nullptr) - { - return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err); - } - - char *key; - pContext->LocalToString(params[4], &key); - - int offset = -1; - void *addr = nullptr;; - switch (params[3]) - { - case SDKConf_Virtual: - if (!conf->GetOffset(key, &offset)) - { - return 0; - } - break; - case SDKConf_Signature: - if (!conf->GetMemSig(key, &addr) || !addr) - { - return 0; - } - break; - case SDKConf_Address: - if (!conf->GetAddress(key, &addr) || !addr) - { - return 0; - } - break; - default: - return pContext->ThrowNativeError("Unknown SDKFuncConfSource: %d", params[3]); - } - - // Save the new info. This always invalidates the other option. - // Detour or vhook. - setup->funcAddr = addr; - setup->offset = offset; - - if (addr == nullptr) - { - setup->hookMethod = Virtual; - } - else - { - setup->hookMethod = Detour; - } - - return 1; -} - -//native bool:DHookAddParam(Handle:setup, HookParamType:type, size=-1, DHookPassFlag:flag=DHookPass_ByVal, DHookRegister custom_register=DHookRegister_Default); -cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params) -{ - HookSetup *setup; - - if(!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - ParamInfo info; - - info.type = (HookParamType)params[2]; - - if(params[0] >= 4) - { - info.flags = params[4]; - } - else - { - info.flags = PASSFLAG_BYVAL; - } - - // DynamicDetours doesn't expose the passflags concept like SourceHook. - // See if we're trying to set some invalid flags on detour arguments. - if(setup->hookMethod == Detour && (info.flags & ~PASSFLAG_BYVAL) > 0) - { - return pContext->ThrowNativeError("Pass flags are only supported for virtual hooks."); - } - - if (params[0] >= 5) - { - PluginRegister custom_register = (PluginRegister)params[5]; - info.custom_register = DynamicHooks_ConvertRegisterFrom(custom_register); - - // Stay future proof. - if (info.custom_register == None && custom_register != DHookRegister_Default) - return pContext->ThrowNativeError("Unhandled DHookRegister %d", params[5]); - - if (info.custom_register != None && info.type == HookParamType_Object) - return pContext->ThrowNativeError("Can't pass an object in a register."); - } - else - { - info.custom_register = None; - } - - if(params[0] >= 3 && params[3] != -1) - { - info.size = params[3]; - } - else if(info.type == HookParamType_Object) - { - return pContext->ThrowNativeError("Object param being set with no size"); - } - else - { - info.size = GetParamTypeSize(info.type); - } - - info.pass_type = GetParamTypePassType(info.type); - setup->params.push_back(info); - - return 1; -} - - -// native bool:DHookEnableDetour(Handle:setup, bool:post, DHookCallback:callback); -cell_t Native_EnableDetour(IPluginContext *pContext, const cell_t *params) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - HookSetup *setup; - - if (!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - if (setup->funcAddr == nullptr) - { - return pContext->ThrowNativeError("Hook not setup for a detour."); - } - - IPluginFunction *callback = pContext->GetFunctionById(params[3]); - if (!callback) - { - return pContext->ThrowNativeError("Failed to retrieve function by id"); - } - - bool post = params[2] != 0; - HookType_t hookType = post ? HOOKTYPE_POST : HOOKTYPE_PRE; - - // Check if we already detoured that function. - CHookManager *pDetourManager = GetHookManager(); - CHook* pDetour = pDetourManager->FindHook(setup->funcAddr); - - // If there is no detour on this function yet, create it. - if (!pDetour) - { - ICallingConvention *pCallConv = ConstructCallingConvention(setup); - pDetour = pDetourManager->HookFunction(setup->funcAddr, pCallConv); - if (!UpdateRegisterArgumentSizes(pDetour, setup)) - return pContext->ThrowNativeError("A custom register for a parameter isn't supported."); - } - - // Register our pre/post handler. - pDetour->AddCallback(hookType, (HookHandlerFn *)&HandleDetour); - - // Add the plugin callback to the map. - return AddDetourPluginHook(hookType, pDetour, setup, callback); -#else - return pContext->ThrowNativeError("Dynamic detours are not enabled for this mod!"); -#endif -} - -// native bool:DHookDisableDetour(Handle:setup, bool:post, DHookCallback:callback); -cell_t Native_DisableDetour(IPluginContext *pContext, const cell_t *params) -{ -#if defined( DHOOKS_DYNAMIC_DETOUR ) - HookSetup *setup; - - if (!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - if (setup->funcAddr == nullptr) - { - return pContext->ThrowNativeError("Hook not setup for a detour."); - } - - IPluginFunction *callback = pContext->GetFunctionById(params[3]); - if (!callback) - { - return pContext->ThrowNativeError("Failed to retrieve function by id"); - } - - bool post = params[2] != 0; - HookType_t hookType = post ? HOOKTYPE_POST : HOOKTYPE_PRE; - - // Check if we already detoured that function. - CHookManager *pDetourManager = GetHookManager(); - CHook* pDetour = pDetourManager->FindHook(setup->funcAddr); - - if (!pDetour || !pDetour->IsCallbackRegistered(hookType, (HookHandlerFn *)&HandleDetour)) - { - return pContext->ThrowNativeError("Function not detoured."); - } - - // Remove the callback from the hook. - return RemoveDetourPluginHook(hookType, pDetour, callback); -#else - return pContext->ThrowNativeError("Dynamic detours are not enabled for this mod!"); -#endif -} - -cell_t HookEntityImpl(IPluginContext *pContext, const cell_t *params, uint32_t callbackIndex, uint32_t removalcbIndex) -{ - HookSetup *setup; - - if(!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - if (setup->offset == -1) - { - return pContext->ThrowNativeError("Hook not setup for a virtual hook."); - } - - if(setup->hookType != HookType_Entity) - { - return pContext->ThrowNativeError("Hook is not an entity hook"); - } - - IPluginFunction *cb = GetCallback(pContext, setup, params, callbackIndex); - if (!cb) - { - return pContext->ThrowNativeError("Failed to hook entity %i, no callback provided", params[3]); - } - - bool post = params[2] != 0; - IPluginFunction *removalcb = pContext->GetFunctionById(params[removalcbIndex]); - - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->callback->hookType == HookType_Entity && manager->callback->entity == gamehelpers->ReferenceToBCompatRef(params[3]) && manager->callback->offset == setup->offset && manager->callback->post == post && manager->remove_callback == removalcb && manager->callback->plugin_callback == cb) - { - return manager->hookid; - } - } - CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[3]); - - if(!pEnt) - { - return pContext->ThrowNativeError("Invalid entity passed %i", params[3]); - } - - DHooksManager *manager = new DHooksManager(setup, pEnt, removalcb, cb, post); - - if(!manager->hookid) - { - delete manager; - return 0; - } - - g_pHooks.push_back(manager); - - return manager->hookid; -} - -// native DHookEntity(Handle:setup, bool:post, entity, DHookRemovalCB:removalcb, DHookCallback:callback = INVALID_FUNCTION); // Both callbacks are optional -cell_t Native_HookEntity(IPluginContext *pContext, const cell_t *params) -{ - return HookEntityImpl(pContext, params, 5, 4); -} -// public native int DynamicHook.HookEntity(HookMode mode, int entity, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); -cell_t Native_HookEntity_Methodmap(IPluginContext *pContext, const cell_t *params) -{ - return HookEntityImpl(pContext, params, 4, 5); -} - -cell_t HookGamerulesImpl(IPluginContext *pContext, const cell_t *params, uint32_t callbackIndex, uint32_t removalcbIndex) -{ - HookSetup *setup; - - if(!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - if (setup->offset == -1) - { - return pContext->ThrowNativeError("Hook not setup for a virtual hook."); - } - - if(setup->hookType != HookType_GameRules) - { - return pContext->ThrowNativeError("Hook is not a gamerules hook"); - } - - IPluginFunction *cb = GetCallback(pContext, setup, params, callbackIndex); - if (!cb) - { - return pContext->ThrowNativeError("Failed to hook gamerules, no callback provided"); - } - - bool post = params[2] != 0; - IPluginFunction *removalcb = pContext->GetFunctionById(params[removalcbIndex]); - - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->callback->hookType == HookType_GameRules && manager->callback->offset == setup->offset && manager->callback->post == post && manager->remove_callback == removalcb && manager->callback->plugin_callback == cb) - { - return manager->hookid; - } - } - - void *rules = g_pSDKTools->GetGameRules(); - if(!rules) - { - return pContext->ThrowNativeError("Could not get gamerules pointer"); - } - - DHooksManager *manager = new DHooksManager(setup, rules, removalcb, cb, post); - - if(!manager->hookid) - { - delete manager; - return 0; - } - - g_pHooks.push_back(manager); - - return manager->hookid; -} - -// native DHookGamerules(Handle:setup, bool:post, DHookRemovalCB:removalcb, DHookCallback:callback = INVALID_FUNCTION); // Both callbacks are optional -cell_t Native_HookGamerules(IPluginContext *pContext, const cell_t *params) -{ - return HookGamerulesImpl(pContext, params, 4, 3); -} - -// public native int DynamicHook.HookGamerules(HookMode mode, DHookCallback callback, DHookRemovalCB removalcb=INVALID_FUNCTION); -cell_t Native_HookGamerules_Methodmap(IPluginContext *pContext, const cell_t *params) -{ - return HookGamerulesImpl(pContext, params, 3, 4); -} - -cell_t HookRawImpl(IPluginContext *pContext, const cell_t *params, int callbackIndex, int removalcbIndex) -{ - HookSetup *setup; - - if(!GetHandleIfValidOrError(g_HookSetupHandle, (void **)&setup, pContext, params[1])) - { - return 0; - } - - if (setup->offset == -1) - { - return pContext->ThrowNativeError("Hook not setup for a virtual hook."); - } - - if(setup->hookType != HookType_Raw) - { - return pContext->ThrowNativeError("Hook is not a raw hook"); - } - - IPluginFunction *cb = GetCallback(pContext, setup, params, callbackIndex); - if (!cb) - { - return pContext->ThrowNativeError("Failed to hook address, no callback provided"); - } - - bool post = params[2] != 0; - IPluginFunction *removalcb = nullptr; - if (removalcbIndex > 0) - removalcb = pContext->GetFunctionById(params[removalcbIndex]); - - void *iface = reinterpret_cast(params[3]); - if (pContext->GetRuntime()->FindPubvarByName("__Int64_Address__", nullptr) == SP_ERROR_NONE) { - cell_t* sp_addr; - if (int err = pContext->LocalToPhysAddr(params[3], &sp_addr); err != SP_ERROR_NONE) { - return pContext->ThrowNativeErrorEx(err, "Could not read argument"); - } - auto value = *reinterpret_cast(sp_addr); - iface = (void*)value; - } - - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->callback->hookType == HookType_Raw && manager->addr == (intptr_t)iface && manager->callback->offset == setup->offset && manager->callback->post == post && manager->remove_callback == removalcb && manager->callback->plugin_callback == cb) - { - return manager->hookid; - } - } - - if(!iface) - { - return pContext->ThrowNativeError("Invalid address passed"); - } - - DHooksManager *manager = new DHooksManager(setup, iface, removalcb, cb, post); - - if(!manager->hookid) - { - delete manager; - return 0; - } - - g_pHooks.push_back(manager); - - return manager->hookid; -} - -// DHookRaw(Handle:setup, bool:post, Address:addr, DHookRemovalCB:removalcb, DHookCallback:callback = INVALID_FUNCTION); // Both callbacks are optional -cell_t Native_HookRaw(IPluginContext *pContext, const cell_t *params) -{ - return HookRawImpl(pContext, params, 5, 4); -} - -// public native int DynamicHook.HookRaw(HookMode mode, Address addr, DHookCallback callback); -cell_t Native_HookRaw_Methodmap(IPluginContext *pContext, const cell_t *params) -{ - return HookRawImpl(pContext, params, 4, 0); -} - -// native bool:DHookRemoveHookID(hookid); -cell_t Native_RemoveHookID(IPluginContext *pContext, const cell_t *params) -{ - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - if(manager->hookid == params[1] && manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext() == pContext) - { - delete manager; - g_pHooks.erase(g_pHooks.begin() + i); - return 1; - } - } - return 0; -} -// native any:DHookGetParam(Handle:hParams, num); -cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] < 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - if(params[2] == 0) - { - return paramStruct->dg->params.size(); - } - - int index = params[2] - 1; - - size_t offset = GetParamOffset(paramStruct, index); - - void *addr = (void **)((intptr_t)paramStruct->orgParams + offset); - - if(*(void **)addr == NULL && (paramStruct->dg->params.at(index).type == HookParamType_CBaseEntity || paramStruct->dg->params.at(index).type == HookParamType_Edict)) - { - return pContext->ThrowNativeError("Trying to get value for null pointer."); - } - - switch(paramStruct->dg->params.at(index).type) - { - case HookParamType_Int: - return *(int *)addr; - case HookParamType_Bool: - return *(cell_t *)addr != 0; - case HookParamType_CBaseEntity: - return gamehelpers->EntityToBCompatRef(*(CBaseEntity **)addr); - case HookParamType_Edict: - return gamehelpers->IndexOfEdict(*(edict_t **)addr); - case HookParamType_Float: - return sp_ftoc(*(float *)addr); - default: - return pContext->ThrowNativeError("Invalid param type (%i) to get", paramStruct->dg->params.at(index).type); - } - - return 1; -} - -// native DHookSetParam(Handle:hParams, param, any:value) -cell_t Native_SetParam(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - - size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->newParams + offset); - - switch(paramStruct->dg->params.at(index).type) - { - case HookParamType_Int: - *(int *)addr = params[3]; - break; - case HookParamType_Bool: - *(bool *)addr = (params[3] ? true : false); - break; - case HookParamType_CBaseEntity: - { - if(params[2] == -1) - { - *(CBaseEntity **)addr = nullptr; - } - else - { - CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[2]); - - if(!pEnt) - { - return pContext->ThrowNativeError("Invalid entity index passed for param value"); - } - - *(CBaseEntity **)addr = pEnt; - } - break; - } - case HookParamType_Edict: - { - edict_t *pEdict = gamehelpers->EdictOfIndex(params[2]); - - if(!pEdict || pEdict->IsFree()) - { - pContext->ThrowNativeError("Invalid entity index passed for param value"); - } - - *(edict_t **)addr = pEdict; - break; - } - case HookParamType_Float: - *(float *)addr = sp_ctof(params[3]); - break; - default: - return pContext->ThrowNativeError("Invalid param type (%i) to set", paramStruct->dg->params.at(index).type); - } - - paramStruct->isChanged[index] = true; - return 1; -} - -// native any:DHookGetReturn(Handle:hReturn); -cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - switch(returnStruct->type) - { - case ReturnType_Int: - return *(int *)returnStruct->orgResult; - case ReturnType_Bool: - return *(bool *)returnStruct->orgResult? 1 : 0; - case ReturnType_CBaseEntity: - return gamehelpers->EntityToBCompatRef((CBaseEntity *)returnStruct->orgResult); - case ReturnType_Edict: - return gamehelpers->IndexOfEdict((edict_t *)returnStruct->orgResult); - case ReturnType_Float: - return sp_ftoc(*(float *)returnStruct->orgResult); - default: - return pContext->ThrowNativeError("Invalid param type (%i) to get", returnStruct->type); - } - return 1; -} -// native DHookSetReturn(Handle:hReturn, any:value) -cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - switch(returnStruct->type) - { - case ReturnType_Int: - *(int *)returnStruct->newResult = params[2]; - break; - case ReturnType_Bool: - *(bool *)returnStruct->newResult = params[2] != 0; - break; - case ReturnType_CBaseEntity: - { - if(params[2] == -1) { - returnStruct->newResult = nullptr; - } else { - CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[2]); - if(!pEnt) - { - return pContext->ThrowNativeError("Invalid entity index passed for return value"); - } - returnStruct->newResult = pEnt; - } - break; - } - case ReturnType_Edict: - { - edict_t *pEdict = gamehelpers->EdictOfIndex(params[2]); - if(!pEdict || pEdict->IsFree()) - { - pContext->ThrowNativeError("Invalid entity index passed for return value"); - } - returnStruct->newResult = pEdict; - break; - } - case ReturnType_Float: - *(float *)returnStruct->newResult = sp_ctof(params[2]); - break; - default: - return pContext->ThrowNativeError("Invalid param type (%i) to get",returnStruct->type); - } - returnStruct->isChanged = true; - return 1; -} -// native DHookGetParamVector(Handle:hParams, num, Float:vec[3]) -cell_t Native_GetParamVector(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - - size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->orgParams + offset); - - if (*(void **)addr == NULL) - { - return pContext->ThrowNativeError("Trying to get value for null pointer."); - } - - switch(paramStruct->dg->params.at(index).type) - { - case HookParamType_VectorPtr: - { - cell_t *buffer; - pContext->LocalToPhysAddr(params[3], &buffer); - SDKVector *vec = *(SDKVector **)addr; - - buffer[0] = sp_ftoc(vec->x); - buffer[1] = sp_ftoc(vec->y); - buffer[2] = sp_ftoc(vec->z); - return 1; - } - } - - return pContext->ThrowNativeError("Invalid param type to get. Param is not a vector."); -} - -static void FreeChangedVector(void *pData) -{ - delete (SDKVector *)pData; -} - -// native DHookSetParamVector(Handle:hParams, num, Float:vec[3]) -cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - - size_t offset = GetParamOffset(paramStruct, index); - void **origAddr = (void **)((intptr_t)paramStruct->orgParams + offset); - void **newAddr = (void **)((intptr_t)paramStruct->newParams + offset); - - switch(paramStruct->dg->params.at(index).type) - { - case HookParamType_VectorPtr: - { - cell_t *buffer; - pContext->LocalToPhysAddr(params[3], &buffer); - SDKVector *origVec = *(SDKVector **)origAddr; - SDKVector **newVec = (SDKVector **)newAddr; - - if(origVec == nullptr) - { - *newVec = new SDKVector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); - // Free it later (cheaply) after the function returned. - smutils->AddFrameAction(FreeChangedVector, *newVec); - } - else - { - origVec->x = sp_ctof(buffer[0]); - origVec->y = sp_ctof(buffer[1]); - origVec->z = sp_ctof(buffer[2]); - *newVec = origVec; - } - paramStruct->isChanged[index] = true; - return 1; - } - } - return pContext->ThrowNativeError("Invalid param type to set. Param is not a vector."); -} - -// native DHookGetParamString(Handle:hParams, num, String:buffer[], size) -cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - - size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->orgParams + offset); - - if(*(void **)addr == NULL) - { - return pContext->ThrowNativeError("Trying to get value for null pointer."); - } - - if(paramStruct->dg->params.at(index).type == HookParamType_CharPtr) - { - pContext->StringToLocal(params[3], params[4], *(const char **)addr); - } - - return 1; -} - -// native DHookGetReturnString(Handle:hReturn, String:buffer[], size) -cell_t Native_GetReturnString(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - switch(returnStruct->type) - { - case ReturnType_String: - pContext->StringToLocal(params[2], params[3], (*(string_t *)returnStruct->orgResult == NULL_STRING) ? "" : STRING(*(string_t *)returnStruct->orgResult)); - return 1; - case ReturnType_StringPtr: - pContext->StringToLocal(params[2], params[3], ((string_t *)returnStruct->orgResult == NULL) ? "" : ((string_t *)returnStruct->orgResult)->ToCStr()); - return 1; - case ReturnType_CharPtr: - pContext->StringToLocal(params[2], params[3], ((char *)returnStruct->orgResult == NULL) ? "" : (const char *)returnStruct->orgResult); - return 1; - default: - return pContext->ThrowNativeError("Invalid param type to get. Param is not a string."); - } -} - -static void FreeChangedCharPtr(void *pData) -{ - delete[](char *)pData; -} - -//native DHookSetReturnString(Handle:hReturn, String:value[]) -cell_t Native_SetReturnString(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - char *value; - pContext->LocalToString(params[2], &value); - - switch(returnStruct->type) - { - case ReturnType_CharPtr: - { - returnStruct->newResult = new char[strlen(value) + 1]; - strcpy((char *)returnStruct->newResult, value); - returnStruct->isChanged = true; - // Free it later (cheaply) after the function returned. - smutils->AddFrameAction(FreeChangedCharPtr, returnStruct->newResult); - return 1; - } - default: - return pContext->ThrowNativeError("Invalid param type to get. Param is not a char pointer."); - } -} - -//native DHookSetParamString(Handle:hParams, num, String:value[]) -cell_t Native_SetParamString(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->newParams + offset); - - char *value; - pContext->LocalToString(params[3], &value); - - if(paramStruct->dg->params.at(index).type == HookParamType_CharPtr) - { - *(char **)addr = new char[strlen(value)+1]; - strcpy(*(char **)addr, value); - paramStruct->isChanged[index] = true; - // Free it later (cheaply) after the function returned. - smutils->AddFrameAction(FreeChangedCharPtr, *(char **)addr); - } - return 1; -} - -//native DHookAddEntityListener(ListenType:type, ListenCB:callback); -cell_t Native_AddEntityListener(IPluginContext *pContext, const cell_t *params) -{ - if(g_pEntityListener) - { - return g_pEntityListener->AddPluginEntityListener((ListenType)params[1], pContext->GetFunctionById(params[2]));; - } - return pContext->ThrowNativeError("Failed to get g_pEntityListener"); -} - -//native bool:DHookRemoveEntityListener(ListenType:type, ListenCB:callback); -cell_t Native_RemoveEntityListener(IPluginContext *pContext, const cell_t *params) -{ - if(g_pEntityListener) - { - return g_pEntityListener->RemovePluginEntityListener((ListenType)params[1], pContext->GetFunctionById(params[2]));; - } - return pContext->ThrowNativeError("Failed to get g_pEntityListener"); -} - -//native any:DHookGetParamObjectPtrVar(Handle:hParams, num, offset, ObjectValueType:type); -cell_t Native_GetParamObjectPtrVar(IPluginContext *pContext, const cell_t *params) -{ - void *addr = NULL; - if(!GetObjectAddrOrThis(pContext, params, addr)) - { - return 0; - } - - switch((ObjectValueType)params[4]) - { - case ObjectValueType_Int: - { - return *(int *)((intptr_t)addr + params[3]); - } - case ObjectValueType_Bool: - return (*(bool *)((intptr_t)addr + params[3])) ? 1 : 0; - case ObjectValueType_Ehandle: - case ObjectValueType_EhandlePtr: - { - edict_t *pEdict = gamehelpers->GetHandleEntity(*(CBaseHandle *)((intptr_t)addr +params[3])); - - if(!pEdict) - { - return -1; - } - - return gamehelpers->IndexOfEdict(pEdict); - } - case ObjectValueType_Float: - { - return sp_ftoc(*(float *)((intptr_t)addr + params[3])); - } - case ObjectValueType_CBaseEntityPtr: - return gamehelpers->EntityToBCompatRef(*(CBaseEntity **)((intptr_t)addr + params[3])); - case ObjectValueType_IntPtr: - { - int *ptr = *(int **)((intptr_t)addr + params[3]); - return *ptr; - } - case ObjectValueType_BoolPtr: - { - bool *ptr = *(bool **)((intptr_t)addr + params[3]); - return *ptr ? 1 : 0; - } - case ObjectValueType_FloatPtr: - { - float *ptr = *(float **)((intptr_t)addr + params[3]); - return sp_ftoc(*ptr); - } - default: - return pContext->ThrowNativeError("Invalid Object value type"); - } -} - -//native DHookSetParamObjectPtrVar(Handle:hParams, num, offset, ObjectValueType:type, value) -cell_t Native_SetParamObjectPtrVar(IPluginContext *pContext, const cell_t *params) -{ - void *addr = NULL; - if(!GetObjectAddrOrThis(pContext, params, addr)) - { - return 0; - } - - switch((ObjectValueType)params[4]) - { - case ObjectValueType_Int: - *(int *)((intptr_t)addr + params[3]) = params[5]; - break; - case ObjectValueType_Bool: - *(bool *)((intptr_t)addr + params[3]) = params[5] != 0; - break; - case ObjectValueType_Ehandle: - case ObjectValueType_EhandlePtr: - { - edict_t *pEdict = gamehelpers->EdictOfIndex(params[5]); - - if(!pEdict || pEdict->IsFree()) - { - return pContext->ThrowNativeError("Invalid edict passed"); - } - gamehelpers->SetHandleEntity(*(CBaseHandle *)((intptr_t)addr + params[3]), pEdict); - - break; - } - case ObjectValueType_Float: - *(float *)((intptr_t)addr + params[3]) = sp_ctof(params[5]); - break; - case ObjectValueType_CBaseEntityPtr: - { - CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[5]); - - if(!pEnt) - { - return pContext->ThrowNativeError("Invalid entity passed"); - } - - *(CBaseEntity **)((intptr_t)addr + params[3]) = pEnt; - break; - } - case ObjectValueType_IntPtr: - { - int *ptr = *(int **)((intptr_t)addr + params[3]); - *ptr = params[5]; - break; - } - case ObjectValueType_BoolPtr: - { - bool *ptr = *(bool **)((intptr_t)addr + params[3]); - *ptr = params[5] != 0; - break; - } - case ObjectValueType_FloatPtr: - { - float *ptr = *(float **)((intptr_t)addr + params[3]); - *ptr = sp_ctof(params[5]); - break; - } - default: - return pContext->ThrowNativeError("Invalid Object value type"); - } - return 1; -} - -//native DHookGetParamObjectPtrVarVector(Handle:hParams, num, offset, ObjectValueType:type, Float:buffer[3]); -cell_t Native_GetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t *params) -{ - void *addr = NULL; - if(!GetObjectAddrOrThis(pContext, params, addr)) - { - return 0; - } - - cell_t *buffer; - pContext->LocalToPhysAddr(params[5], &buffer); - - if((ObjectValueType)params[4] == ObjectValueType_VectorPtr || (ObjectValueType)params[4] == ObjectValueType_Vector) - { - SDKVector *vec; - - if((ObjectValueType)params[4] == ObjectValueType_VectorPtr) - { - vec = *(SDKVector **)((intptr_t)addr + params[3]); - if(vec == NULL) - { - return pContext->ThrowNativeError("Trying to get value for null pointer."); - } - } - else - { - vec = (SDKVector *)((intptr_t)addr + params[3]); - } - - buffer[0] = sp_ftoc(vec->x); - buffer[1] = sp_ftoc(vec->y); - buffer[2] = sp_ftoc(vec->z); - return 1; - } - - return pContext->ThrowNativeError("Invalid Object value type (not a type of vector)"); -} - -//native DHookSetParamObjectPtrVarVector(Handle:hParams, num, offset, ObjectValueType:type, Float:value[3]); -cell_t Native_SetParamObjectPtrVarVector(IPluginContext *pContext, const cell_t *params) -{ - void *addr = NULL; - if(!GetObjectAddrOrThis(pContext, params, addr)) - { - return 0; - } - - cell_t *buffer; - pContext->LocalToPhysAddr(params[5], &buffer); - - if((ObjectValueType)params[4] == ObjectValueType_VectorPtr || (ObjectValueType)params[4] == ObjectValueType_Vector) - { - SDKVector *vec; - - if((ObjectValueType)params[4] == ObjectValueType_VectorPtr) - { - vec = *(SDKVector **)((intptr_t)addr + params[3]); - if(vec == NULL) - { - return pContext->ThrowNativeError("Trying to set value for null pointer."); - } - } - else - { - vec = (SDKVector *)((intptr_t)addr + params[3]); - } - - vec->x = sp_ctof(buffer[0]); - vec->y = sp_ctof(buffer[1]); - vec->z = sp_ctof(buffer[2]); - return 1; - } - return pContext->ThrowNativeError("Invalid Object value type (not a type of vector)"); -} - -//native DHookGetParamObjectPtrString(Handle:hParams, num, offset, ObjectValueType:type, String:buffer[], size) -cell_t Native_GetParamObjectPtrString(IPluginContext *pContext, const cell_t *params) -{ - void *addr = NULL; - if (!GetObjectAddrOrThis(pContext, params, addr)) - { - return 0; - } - - switch((ObjectValueType)params[4]) - { - case ObjectValueType_CharPtr: - { - char *ptr = *(char **)((intptr_t)addr + params[3]); - pContext->StringToLocal(params[5], params[6], ptr == NULL ? "" : (const char *)ptr); - break; - } - case ObjectValueType_String: - { - string_t string = *(string_t *)((intptr_t)addr + params[3]); - pContext->StringToLocal(params[5], params[6], string == NULL_STRING ? "" : STRING(string)); - break; - } - default: - return pContext->ThrowNativeError("Invalid Object value type (not a type of string)"); - } - return 1; -} - -// DHookGetReturnVector(Handle:hReturn, Float:vec[3]) -cell_t Native_GetReturnVector(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - cell_t *buffer; - pContext->LocalToPhysAddr(params[2], &buffer); - - if(returnStruct->type == ReturnType_Vector) - { - buffer[0] = sp_ftoc((*(SDKVector *)returnStruct->orgResult).x); - buffer[1] = sp_ftoc((*(SDKVector *)returnStruct->orgResult).y); - buffer[2] = sp_ftoc((*(SDKVector *)returnStruct->orgResult).z); - - return 1; - } - else if(returnStruct->type == ReturnType_VectorPtr) - { - buffer[0] = sp_ftoc(((SDKVector *)returnStruct->orgResult)->x); - buffer[1] = sp_ftoc(((SDKVector *)returnStruct->orgResult)->y); - buffer[2] = sp_ftoc(((SDKVector *)returnStruct->orgResult)->z); - - return 1; - } - return pContext->ThrowNativeError("Return type is not a vector type"); -} - -//DHookSetReturnVector(Handle:hReturn, Float:vec[3]) -cell_t Native_SetReturnVector(IPluginContext *pContext, const cell_t *params) -{ - HookReturnStruct *returnStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookReturnHandle, g_HookParamsHandle, (void **)&returnStruct, pContext, params[1])) - { - return 0; - } - - cell_t *buffer; - pContext->LocalToPhysAddr(params[2], &buffer); - - if(returnStruct->type == ReturnType_Vector) - { - *(SDKVector *)returnStruct->newResult = SDKVector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); - returnStruct->isChanged = true; - - return 1; - } - else if(returnStruct->type == ReturnType_VectorPtr) - { - returnStruct->newResult = new SDKVector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); - returnStruct->isChanged = true; - // Free it later (cheaply) after the function returned. - smutils->AddFrameAction(FreeChangedVector, returnStruct->newResult); - - return 1; - } - return pContext->ThrowNativeError("Return type is not a vector type"); -} - -//native bool:DHookIsNullParam(Handle:hParams, num); -cell_t Native_IsNullParam(IPluginContext *pContext, const cell_t *params) -{ - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[1])) - { - return 0; - } - - if(params[2] <= 0 || params[2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.size()); - } - - int index = params[2] - 1; - size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->orgParams + offset); - - HookParamType type = paramStruct->dg->params.at(index).type; - - //Check that the type is ptr - if(type == HookParamType_StringPtr || type == HookParamType_CharPtr || type == HookParamType_VectorPtr || type == HookParamType_CBaseEntity || type == HookParamType_ObjectPtr || type == HookParamType_Edict || type == HookParamType_Unknown) - return *(void **)addr == NULL; - else - return pContext->ThrowNativeError("Param is not a pointer!"); -} - -//native Address:DHookGetParamAddress(Handle:hParams, num); -cell_t Native_GetParamAddress(IPluginContext *pContext, const cell_t *params) -{ - cell_t shift_param = 0; - if (pContext->GetRuntime()->FindPubvarByName("__Int64_Address__", nullptr) == SP_ERROR_NONE) { - shift_param = 1; - } - - HookParamsStruct *paramStruct; - - if(!GetCallbackArgHandleIfValidOrError(g_HookParamsHandle, g_HookReturnHandle, (void **)¶mStruct, pContext, params[shift_param + 1])) - { - return 0; - } - - if(params[shift_param + 2] <= 0 || params[shift_param + 2] > (int)paramStruct->dg->params.size()) - { - return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[shift_param + 2], paramStruct->dg->params.size()); - } - - int index = params[shift_param + 2] - 1; - - HookParamType type = paramStruct->dg->params.at(index).type; - if(type != HookParamType_StringPtr && type != HookParamType_CharPtr && type != HookParamType_VectorPtr && type != HookParamType_CBaseEntity && type != HookParamType_ObjectPtr && type != HookParamType_Edict && type != HookParamType_Unknown) - { - return pContext->ThrowNativeError("Param is not a pointer!"); - } - - size_t offset = GetParamOffset(paramStruct, index); - - auto return_ptr = *(void**)((intptr_t)paramStruct->orgParams + offset); - - if (shift_param != 0) { - cell_t* sp_addr; - if (int err = pContext->LocalToPhysAddr(params[1], &sp_addr); err != SP_ERROR_NONE) { - return pContext->ThrowNativeErrorEx(err, "Could not read argument"); - } - *reinterpret_cast(sp_addr) = reinterpret_cast(return_ptr); - } - return reinterpret_cast(return_ptr); -} - -sp_nativeinfo_t g_Natives[] = -{ - {"DHookCreate", Native_CreateHook}, - {"DHookCreateDetour", Native_CreateDetour}, - {"DHookCreateFromConf", Native_DHookCreateFromConf}, - {"DHookSetFromConf", Native_SetFromConf}, - {"DHookAddParam", Native_AddParam}, - {"DHookEnableDetour", Native_EnableDetour}, - {"DHookDisableDetour", Native_DisableDetour}, - {"DHookEntity", Native_HookEntity}, - {"DHookGamerules", Native_HookGamerules}, - {"DHookRaw", Native_HookRaw}, - {"DHookRemoveHookID", Native_RemoveHookID}, - {"DHookGetParam", Native_GetParam}, - {"DHookGetReturn", Native_GetReturn}, - {"DHookSetReturn", Native_SetReturn}, - {"DHookSetParam", Native_SetParam}, - {"DHookGetParamVector", Native_GetParamVector}, - {"DHookGetReturnVector", Native_GetReturnVector}, - {"DHookSetReturnVector", Native_SetReturnVector}, - {"DHookSetParamVector", Native_SetParamVector}, - {"DHookGetParamString", Native_GetParamString}, - {"DHookGetReturnString", Native_GetReturnString}, - {"DHookSetReturnString", Native_SetReturnString}, - {"DHookSetParamString", Native_SetParamString}, - {"DHookAddEntityListener", Native_AddEntityListener}, - {"DHookRemoveEntityListener", Native_RemoveEntityListener}, - {"DHookGetParamObjectPtrVar", Native_GetParamObjectPtrVar}, - {"DHookSetParamObjectPtrVar", Native_SetParamObjectPtrVar}, - {"DHookGetParamObjectPtrVarVector", Native_GetParamObjectPtrVarVector}, - {"DHookSetParamObjectPtrVarVector", Native_SetParamObjectPtrVarVector}, - {"DHookGetParamObjectPtrString", Native_GetParamObjectPtrString}, - {"DHookIsNullParam", Native_IsNullParam}, - {"DHookGetParamAddress", Native_GetParamAddress}, - - // Methodmap API - {"DHookSetup.AddParam", Native_AddParam}, - {"DHookSetup.SetFromConf", Native_SetFromConf}, - - {"DynamicHook.DynamicHook", Native_CreateHook}, - {"DynamicHook.FromConf", Native_DHookCreateFromConf}, - {"DynamicHook.HookEntity", Native_HookEntity_Methodmap}, - {"DynamicHook.HookGamerules", Native_HookGamerules_Methodmap}, - {"DynamicHook.HookRaw", Native_HookRaw_Methodmap}, - {"DynamicHook.RemoveHook", Native_RemoveHookID}, - - {"DynamicDetour.DynamicDetour", Native_CreateDetour}, - {"DynamicDetour.FromConf", Native_DHookCreateFromConf}, - {"DynamicDetour.Enable", Native_EnableDetour}, - {"DynamicDetour.Disable", Native_DisableDetour}, - - {"DHookParam.Get", Native_GetParam}, - {"DHookParam.GetVector", Native_GetParamVector}, - {"DHookParam.GetString", Native_GetParamString}, - {"DHookParam.Set", Native_SetParam}, - {"DHookParam.SetVector", Native_SetParamVector}, - {"DHookParam.SetString", Native_SetParamString}, - {"DHookParam.GetObjectVar", Native_GetParamObjectPtrVar}, - {"DHookParam.GetObjectVarVector", Native_GetParamObjectPtrVarVector}, - {"DHookParam.GetObjectVarString", Native_GetParamObjectPtrString}, - {"DHookParam.SetObjectVar", Native_SetParamObjectPtrVar}, - {"DHookParam.SetObjectVarVector", Native_SetParamObjectPtrVarVector}, - {"DHookParam.IsNull", Native_IsNullParam}, - {"DHookParam.GetAddress", Native_GetParamAddress}, - - {"DHookReturn.Value.get", Native_GetReturn}, - {"DHookReturn.Value.set", Native_SetReturn}, - {"DHookReturn.GetVector", Native_GetReturnVector}, - {"DHookReturn.SetVector", Native_SetReturnVector}, - {"DHookReturn.GetString", Native_GetReturnString}, - {"DHookReturn.SetString", Native_SetReturnString}, - {NULL, NULL} -}; diff --git a/extensions/dhooks/natives.h b/extensions/dhooks/natives.h deleted file mode 100644 index 6b90064c77..0000000000 --- a/extensions/dhooks/natives.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_NATIVES_H_ -#define _INCLUDE_NATIVES_H_ - -#include "extension.h" -#include "vhook.h" -#include "listeners.h" - -extern DHooksEntityListener *g_pEntityListener; -extern ISDKTools *g_pSDKTools; -extern HandleType_t g_HookSetupHandle; -extern HandleType_t g_HookParamsHandle; -extern HandleType_t g_HookReturnHandle; -extern std::vector g_pHooks; -#endif diff --git a/extensions/dhooks/sdk-hacks.h b/extensions/dhooks/sdk-hacks.h deleted file mode 100644 index e2ddb6ee70..0000000000 --- a/extensions/dhooks/sdk-hacks.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SDK_HACKS_H_ -#define _INCLUDE_SDK_HACKS_H_ - -class SDKVector -{ -public: - SDKVector(float x1, float y1, float z1) - { - this->x = x1; - this->y = y1; - this->z = z1; - } - SDKVector(void) - { - this->x = 0.0; - this->y = 0.0; - this->z = 0.0; - } - float x; - float y; - float z; -}; - -struct string_t -{ -public: - bool operator!() const { return ( pszValue == NULL ); } - bool operator==( const string_t &rhs ) const { return ( pszValue == rhs.pszValue ); } - bool operator!=( const string_t &rhs ) const { return ( pszValue != rhs.pszValue ); } - bool operator<( const string_t &rhs ) const { return ((void *)pszValue < (void *)rhs.pszValue ); } - - const char *ToCStr() const { return ( pszValue ) ? pszValue : ""; } - -protected: - const char *pszValue; -}; - -struct castable_string_t : public string_t // string_t is used in unions, hence, no constructor allowed -{ - castable_string_t() { pszValue = NULL; } - castable_string_t( const char *pszFrom ) { pszValue = (pszFrom && *pszFrom) ? pszFrom : 0; } -}; - -#define NULL_STRING castable_string_t() -#define STRING( string_t_obj ) (string_t_obj).ToCStr() -#define MAKE_STRING( c_str ) castable_string_t( c_str ) - -#define FL_EDICT_FREE (1<<1) - -struct edict_t -{ -public: - bool IsFree() - { - return (m_fStateFlags & FL_EDICT_FREE) != 0; - } -private: - int m_fStateFlags; -}; - -class CBaseHandle -{ -/*public: - bool IsValid() const {return m_Index != INVALID_EHANDLE_INDEX;} - int GetEntryIndex() const - { - if ( !IsValid() ) - return NUM_ENT_ENTRIES-1; - return m_Index & ENT_ENTRY_MASK; - }*/ -private: - unsigned long m_Index; -}; - -#endif \ No newline at end of file diff --git a/extensions/dhooks/signatures.cpp b/extensions/dhooks/signatures.cpp deleted file mode 100644 index e816e6580a..0000000000 --- a/extensions/dhooks/signatures.cpp +++ /dev/null @@ -1,679 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include - -SignatureGameConfig *g_pSignatures; - -enum ParseState -{ - PState_None, - PState_Root, - PState_Function, - PState_Arguments, - PState_Argument -}; - -ParseState g_ParseState; -unsigned int g_IgnoreLevel; -// The parent section type of a platform specific "windows" or "linux" section. -ParseState g_PlatformOnlyState; - -SignatureWrapper *g_CurrentSignature; -std::string g_CurrentFunctionName; -ArgumentInfo g_CurrentArgumentInfo; - -SignatureWrapper *SignatureGameConfig::GetFunctionSignature(const char *function) -{ - auto sig = signatures_.find(function); - if (!sig.found()) - return nullptr; - - return sig->value; -} - -/** - * Game config "Functions" section parsing. - */ -SMCResult SignatureGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name) -{ - // We're ignoring the parent section. Ignore all child sections as well. - if (g_IgnoreLevel > 0) - { - g_IgnoreLevel++; - return SMCResult_Continue; - } - - // Handle platform specific sections first. -#ifdef DYNAMICHOOKS_x86_64 -#if defined WIN32 - if (!strcmp(name, "windows64")) -#elif defined _LINUX - if (!strcmp(name, "linux64")) -#elif defined _OSX - if (!strcmp(name, "mac64")) -#endif -#else -#if defined WIN32 - if (!strcmp(name, "windows")) -#elif defined _LINUX - if (!strcmp(name, "linux")) -#elif defined _OSX - if (!strcmp(name, "mac")) -#endif -#endif - { - // We're already in a section for a different OS that we're ignoring. Can't have a section for our OS in here. - if (g_IgnoreLevel > 0) - { - smutils->LogError(myself, "Unreachable platform specific section in \"%s\" Function: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - - // We don't support nested (useless) sections of the same OS like "windows" { "windows" { "foo" "bar" } } - if (g_PlatformOnlyState != PState_None) - { - smutils->LogError(myself, "Duplicate platform specific section for \"%s\". Already parsing only for that OS: line: %i col: %i", name, states->line, states->col); - return SMCResult_HaltFail; - } - - // This is a specific block for us. - g_PlatformOnlyState = g_ParseState; - return SMCResult_Continue; - } - else if (!strcmp(name, "windows") || !strcmp(name, "linux") || !strcmp(name, "mac") - || !strcmp(name, "windows64") || !strcmp(name, "linux64") || !strcmp(name, "mac64")) - { - if (g_PlatformOnlyState != PState_None) - { - smutils->LogError(myself, "Unreachable platform specific section in \"%s\" Function: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - - // A specific block for a different platform. - g_IgnoreLevel++; - return SMCResult_Continue; - } - - switch (g_ParseState) - { - case PState_Root: - { - auto sig = signatures_.find(name); - if (sig.found()) - g_CurrentSignature = sig->value; - else - g_CurrentSignature = new SignatureWrapper(); - g_CurrentFunctionName = name; - g_ParseState = PState_Function; - break; - } - - case PState_Function: - { - if (!strcmp(name, "arguments")) - { - g_ParseState = PState_Arguments; - } - else - { - smutils->LogError(myself, "Unknown subsection \"%s\" (expected \"arguments\"): line: %i col: %i", name, states->line, states->col); - return SMCResult_HaltFail; - } - break; - } - case PState_Arguments: - { - g_ParseState = PState_Argument; - g_CurrentArgumentInfo.name = name; - - // Reset the parameter info. - ParamInfo info; - memset(&info, 0, sizeof(info)); - info.flags = PASSFLAG_BYVAL; - g_CurrentArgumentInfo.info = info; - - // See if we already have info about this argument. - for (auto &arg : g_CurrentSignature->args) { - if (!arg.name.compare(name)) { - // Continue changing that argument now. - g_CurrentArgumentInfo.info = arg.info; - break; - } - } - break; - } - default: - smutils->LogError(myself, "Unknown subsection \"%s\": line: %i col: %i", name, states->line, states->col); - return SMCResult_HaltFail; - } - - return SMCResult_Continue; -} - -SMCResult SignatureGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) -{ - // We don't care for anything in this section or subsections. - if (g_IgnoreLevel > 0) - return SMCResult_Continue; - - switch (g_ParseState) - { - case PState_Function: - - if (!strcmp(key, "signature")) - { - if (g_CurrentSignature->address.length() > 0 || g_CurrentSignature->offset.length() > 0) - { - smutils->LogError(myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); - return SMCResult_HaltFail; - } - g_CurrentSignature->signature = value; - } - else if (!strcmp(key, "address")) - { - if (g_CurrentSignature->signature.length() > 0 || g_CurrentSignature->offset.length() > 0) - { - smutils->LogError(myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); - return SMCResult_HaltFail; - } - g_CurrentSignature->address = value; - } - else if (!strcmp(key, "offset")) - { - if (g_CurrentSignature->address.length() > 0 || g_CurrentSignature->signature.length() > 0) - { - smutils->LogError(myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); - return SMCResult_HaltFail; - } - g_CurrentSignature->offset = value; - } - else if (!strcmp(key, "callconv")) - { - CallingConvention callConv; - - if (!strcmp(value, "cdecl")) - callConv = CallConv_CDECL; - else if (!strcmp(value, "thiscall")) - callConv = CallConv_THISCALL; - else if (!strcmp(value, "stdcall")) - callConv = CallConv_STDCALL; - else if (!strcmp(value, "fastcall")) - callConv = CallConv_FASTCALL; - else - { - smutils->LogError(myself, "Invalid calling convention \"%s\": line: %i col: %i", value, states->line, states->col); - return SMCResult_HaltFail; - } - - g_CurrentSignature->callConv = callConv; - } - else if (!strcmp(key, "hooktype")) - { - HookType hookType; - - if (!strcmp(value, "entity")) - hookType = HookType_Entity; - else if (!strcmp(value, "gamerules")) - hookType = HookType_GameRules; - else if (!strcmp(value, "raw")) - hookType = HookType_Raw; - else - { - smutils->LogError(myself, "Invalid hook type \"%s\": line: %i col: %i", value, states->line, states->col); - return SMCResult_HaltFail; - } - - g_CurrentSignature->hookType = hookType; - } - else if (!strcmp(key, "return")) - { - g_CurrentSignature->retType = GetReturnTypeFromString(value); - - if (g_CurrentSignature->retType == ReturnType_Unknown) - { - smutils->LogError(myself, "Invalid return type \"%s\": line: %i col: %i", value, states->line, states->col); - return SMCResult_HaltFail; - } - } - else if (!strcmp(key, "this")) - { - if (!strcmp(value, "ignore")) - g_CurrentSignature->thisType = ThisPointer_Ignore; - else if (!strcmp(value, "entity")) - g_CurrentSignature->thisType = ThisPointer_CBaseEntity; - else if (!strcmp(value, "address")) - g_CurrentSignature->thisType = ThisPointer_Address; - else - { - smutils->LogError(myself, "Invalid this type \"%s\": line: %i col: %i", value, states->line, states->col); - return SMCResult_HaltFail; - } - } - else - { - smutils->LogError(myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); - return SMCResult_HaltFail; - } - break; - - case PState_Argument: - - if (!strcmp(key, "type")) - { - g_CurrentArgumentInfo.info.type = GetHookParamTypeFromString(value); - if (g_CurrentArgumentInfo.info.type == HookParamType_Unknown) - { - smutils->LogError(myself, "Invalid argument type \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - } - else if (!strcmp(key, "size")) - { - g_CurrentArgumentInfo.info.size = static_cast(strtol(value, NULL, 0)); - - if (g_CurrentArgumentInfo.info.size < 1) - { - smutils->LogError(myself, "Invalid argument size \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - } - else if (!strcmp(key, "flags")) - { - size_t flags = 0; - if (strstr(value, "byval")) - flags |= PASSFLAG_BYVAL; - if (strstr(value, "byref")) - flags |= PASSFLAG_BYREF; - if (strstr(value, "odtor")) - flags |= PASSFLAG_ODTOR; - if (strstr(value, "octor")) - flags |= PASSFLAG_OCTOR; - if (strstr(value, "oassignop")) - flags |= PASSFLAG_OASSIGNOP; -#ifdef PASSFLAG_OCOPYCTOR - if (strstr(value, "ocopyctor")) - flags |= PASSFLAG_OCOPYCTOR; -#endif -#ifdef PASSFLAG_OUNALIGN - if (strstr(value, "ounalign")) - flags |= PASSFLAG_OUNALIGN; -#endif - - g_CurrentArgumentInfo.info.flags = flags; - } - else if (!strcmp(key, "register")) - { - g_CurrentArgumentInfo.info.custom_register = GetCustomRegisterFromString(value); - - if (g_CurrentArgumentInfo.info.custom_register == Register_t::None) - { - smutils->LogError(myself, "Invalid register \"%s\": line: %i col: %i", value, states->line, states->col); - return SMCResult_HaltFail; - } - } - else - { - smutils->LogError(myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); - return SMCResult_HaltFail; - } - break; - - default: - smutils->LogError(myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); - return SMCResult_HaltFail; - } - return SMCResult_Continue; -} - -SMCResult SignatureGameConfig::ReadSMC_LeavingSection(const SMCStates *states) -{ - // We were ignoring this section. - if (g_IgnoreLevel > 0) - { - g_IgnoreLevel--; - return SMCResult_Continue; - } - - // We were in a section only for our OS. - if (g_PlatformOnlyState == g_ParseState) - { - g_PlatformOnlyState = PState_None; - return SMCResult_Continue; - } - - switch (g_ParseState) - { - case PState_Function: - g_ParseState = PState_Root; - - if (!g_CurrentSignature->address.length() && !g_CurrentSignature->signature.length() && !g_CurrentSignature->offset.length()) - { - smutils->LogError(myself, "Function \"%s\" doesn't have a \"signature\", \"offset\" nor \"address\" set: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - - if (!g_CurrentSignature->offset.length()) - { - // DynamicDetours doesn't expose the passflags concept like SourceHook. - // See if we're trying to set some invalid flags on detour arguments. - for (auto &arg : g_CurrentSignature->args) - { - if ((arg.info.flags & ~PASSFLAG_BYVAL) > 0) - { - smutils->LogError(myself, "Function \"%s\" uses unsupported pass flags in argument \"%s\". Flags are only supported for virtual hooks: line: %i col: %i", g_CurrentFunctionName.c_str(), arg.name.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - } - } - - // Save this function signature in our cache. - signatures_.insert(g_CurrentFunctionName.c_str(), g_CurrentSignature); - g_CurrentFunctionName = ""; - g_CurrentSignature = nullptr; - break; - case PState_Arguments: - g_ParseState = PState_Function; - break; - case PState_Argument: - g_ParseState = PState_Arguments; - - if (g_CurrentArgumentInfo.info.type == HookParamType_Unknown) - { - smutils->LogError(myself, "Missing argument type for argument \"%s\": line: %i col: %i", g_CurrentArgumentInfo.name.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - - // The size wasn't set in the config. See if that's fine and we can guess it from the type. - if (!g_CurrentArgumentInfo.info.size) - { - if (g_CurrentArgumentInfo.info.type == HookParamType_Object) - { - smutils->LogError(myself, "Object param \"%s\" being set with no size: line: %i col: %i", g_CurrentArgumentInfo.name.c_str(), states->line, states->col); - return SMCResult_HaltFail; - } - else - { - g_CurrentArgumentInfo.info.size = GetParamTypeSize(g_CurrentArgumentInfo.info.type); - } - } - - if (g_CurrentArgumentInfo.info.pass_type == SourceHook::PassInfo::PassType::PassType_Unknown) - g_CurrentArgumentInfo.info.pass_type = GetParamTypePassType(g_CurrentArgumentInfo.info.type); - - // See if we were changing an existing argument. - bool changed = false; - for (auto &arg : g_CurrentSignature->args) - { - if (!arg.name.compare(g_CurrentArgumentInfo.name)) - { - arg.info = g_CurrentArgumentInfo.info; - changed = true; - break; - } - } - // This was a new argument. Add it to the end of the list. - if (!changed) - g_CurrentSignature->args.push_back(g_CurrentArgumentInfo); - - g_CurrentArgumentInfo.name = ""; - break; - } - - return SMCResult_Continue; -} - -void SignatureGameConfig::ReadSMC_ParseStart() -{ - g_ParseState = PState_Root; - g_IgnoreLevel = 0; - g_PlatformOnlyState = PState_None; - g_CurrentSignature = nullptr; - g_CurrentFunctionName = ""; - g_CurrentArgumentInfo.name = ""; -} - -ReturnType SignatureGameConfig::GetReturnTypeFromString(const char *str) -{ - if (!strcmp(str, "void")) - return ReturnType_Void; - else if (!strcmp(str, "int")) - return ReturnType_Int; - else if (!strcmp(str, "bool")) - return ReturnType_Bool; - else if (!strcmp(str, "float")) - return ReturnType_Float; - else if (!strcmp(str, "string")) - return ReturnType_String; - else if (!strcmp(str, "stringptr")) - return ReturnType_StringPtr; - else if (!strcmp(str, "charptr")) - return ReturnType_CharPtr; - else if (!strcmp(str, "vector")) - return ReturnType_Vector; - else if (!strcmp(str, "vectorptr")) - return ReturnType_VectorPtr; - else if (!strcmp(str, "cbaseentity")) - return ReturnType_CBaseEntity; - else if (!strcmp(str, "edict")) - return ReturnType_Edict; - - return ReturnType_Unknown; -} - -HookParamType SignatureGameConfig::GetHookParamTypeFromString(const char *str) -{ - if (!strcmp(str, "int")) - return HookParamType_Int; - else if (!strcmp(str, "bool")) - return HookParamType_Bool; - else if (!strcmp(str, "float")) - return HookParamType_Float; - else if (!strcmp(str, "string")) - return HookParamType_String; - else if (!strcmp(str, "stringptr")) - return HookParamType_StringPtr; - else if (!strcmp(str, "charptr")) - return HookParamType_CharPtr; - else if (!strcmp(str, "vectorptr")) - return HookParamType_VectorPtr; - else if (!strcmp(str, "cbaseentity")) - return HookParamType_CBaseEntity; - else if (!strcmp(str, "objectptr")) - return HookParamType_ObjectPtr; - else if (!strcmp(str, "edict")) - return HookParamType_Edict; - else if (!strcmp(str, "object")) - return HookParamType_Object; - - return HookParamType_Unknown; -} - -Register_t SignatureGameConfig::GetCustomRegisterFromString(const char *str) -{ - if (!strcmp(str, "al")) - return AL; - else if (!strcmp(str, "cl")) - return CL; - else if (!strcmp(str, "dl")) - return DL; - else if (!strcmp(str, "bl")) - return BL; - else if (!strcmp(str, "ah")) - return AH; - else if (!strcmp(str, "ch")) - return CH; - else if (!strcmp(str, "dh")) - return DH; - else if (!strcmp(str, "bh")) - return BH; - - else if (!strcmp(str, "ax")) - return AX; - else if (!strcmp(str, "cx")) - return CX; - else if (!strcmp(str, "dx")) - return DX; - else if (!strcmp(str, "bx")) - return BX; - else if (!strcmp(str, "sp")) - return SP; - else if (!strcmp(str, "bp")) - return BP; - else if (!strcmp(str, "si")) - return SI; - else if (!strcmp(str, "di")) - return DI; - - else if (!strcmp(str, "eax")) - return EAX; - else if (!strcmp(str, "ecx")) - return ECX; - else if (!strcmp(str, "edx")) - return EDX; - else if (!strcmp(str, "ebx")) - return EBX; - else if (!strcmp(str, "esp")) - return ESP; - else if (!strcmp(str, "ebp")) - return EBP; - else if (!strcmp(str, "esi")) - return ESI; - else if (!strcmp(str, "edi")) - return EDI; - -#ifdef DYNAMICHOOKS_x86_64 - else if (!strcmp(str, "rax")) - return RAX; - else if (!strcmp(str, "rcx")) - return RCX; - else if (!strcmp(str, "rdx")) - return RDX; - else if (!strcmp(str, "rbx")) - return RBX; - else if (!strcmp(str, "rsp")) - return RSP; - else if (!strcmp(str, "rbp")) - return RBP; - else if (!strcmp(str, "rsi")) - return RSI; - else if (!strcmp(str, "rdi")) - return RDI; - - else if (!strcmp(str, "r8")) - return R8; - else if (!strcmp(str, "r9")) - return R9; - else if (!strcmp(str, "r10")) - return R10; - else if (!strcmp(str, "r11")) - return R11; - else if (!strcmp(str, "r12")) - return R12; - else if (!strcmp(str, "r13")) - return R13; - else if (!strcmp(str, "r14")) - return R14; - else if (!strcmp(str, "r15")) - return R15; -#endif - - else if (!strcmp(str, "mm0")) - return MM0; - else if (!strcmp(str, "mm1")) - return MM1; - else if (!strcmp(str, "mm2")) - return MM2; - else if (!strcmp(str, "mm3")) - return MM3; - else if (!strcmp(str, "mm4")) - return MM4; - else if (!strcmp(str, "mm5")) - return MM5; - else if (!strcmp(str, "mm6")) - return MM6; - else if (!strcmp(str, "mm7")) - return MM7; - - else if (!strcmp(str, "xmm0")) - return XMM0; - else if (!strcmp(str, "xmm1")) - return XMM1; - else if (!strcmp(str, "xmm2")) - return XMM2; - else if (!strcmp(str, "xmm3")) - return XMM3; - else if (!strcmp(str, "xmm4")) - return XMM4; - else if (!strcmp(str, "xmm5")) - return XMM5; - else if (!strcmp(str, "xmm6")) - return XMM6; - else if (!strcmp(str, "xmm7")) - return XMM7; - -#ifdef DYNAMICHOOKS_x86_64 - else if (!strcmp(str, "xmm8")) - return XMM8; - else if (!strcmp(str, "xmm9")) - return XMM9; - else if (!strcmp(str, "xmm10")) - return XMM10; - else if (!strcmp(str, "xmm11")) - return XMM11; - else if (!strcmp(str, "xmm12")) - return XMM12; - else if (!strcmp(str, "xmm13")) - return XMM13; - else if (!strcmp(str, "xmm14")) - return XMM14; - else if (!strcmp(str, "xmm15")) - return XMM15; -#endif - - else if (!strcmp(str, "cs")) - return CS; - else if (!strcmp(str, "ss")) - return SS; - else if (!strcmp(str, "ds")) - return DS; - else if (!strcmp(str, "es")) - return ES; - else if (!strcmp(str, "fs")) - return FS; - else if (!strcmp(str, "gs")) - return GS; - - else if (!strcmp(str, "st0")) - return ST0; - - return Register_t::None; -} \ No newline at end of file diff --git a/extensions/dhooks/src/abi.hpp b/extensions/dhooks/src/abi.hpp new file mode 100644 index 0000000000..9547802f38 --- /dev/null +++ b/extensions/dhooks/src/abi.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "capsule.hpp" + +namespace dhooks::abi { + +void JIT_Align(AsmJit& jit) { + auto realign = (16 - (jit.get_outputpos() % 16)) % 16; + for (;realign; realign--) { + jit.breakpoint(); + } +} + +bool AreParamsEquivalent(const std::vector& params_lh, const std::vector& params_rh, const ReturnVariable& return_lh, const ReturnVariable& return_rh) { + return true; +} + +bool Proccess(sp::CallingConvention conv, std::vector& params, ReturnVariable& ret, size_t& stack_size); +void JIT_CallMemberFunction(AsmJit& jit, bool save_general_register[MAX_GENERAL_REGISTERS], bool save_float_register[MAX_FLOAT_REGISTERS], void* this_ptr, const void* mfp, bool post); +void JIT_MakeReturn(AsmJit& jit, ReturnVariable& ret); +void JIT_CallOriginal(AsmJit& jit, ReturnVariable& ret, std::uintptr_t* original_function, size_t stack_size, std::uintptr_t* jit_start); +void JIT_Recall(AsmJit& jit, bool save_general_register[MAX_GENERAL_REGISTERS], bool save_float_register[MAX_FLOAT_REGISTERS], size_t stack_size, std::uintptr_t* call_function); + +} \ No newline at end of file diff --git a/extensions/dhooks/src/abi/system_v_amd64.cpp b/extensions/dhooks/src/abi/system_v_amd64.cpp new file mode 100644 index 0000000000..0fe0813835 --- /dev/null +++ b/extensions/dhooks/src/abi/system_v_amd64.cpp @@ -0,0 +1,496 @@ +#include "../sp_inc.hpp" +#include "../capsule.hpp" +#include "../sdk_types.hpp" + +#include +#include +#include + +// Reference: https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf + +namespace dhooks::abi { + +using namespace KHook::Asm; + +enum class TypeClass { + VOID, + INTEGER, + SSE, + SSEUP, + X87, + X87UP, + COMPLEX_X87, + NO_CLASS, + MEMORY +}; + +const char* TypeToString(TypeClass type) { + switch (type) { + case TypeClass::VOID: + return "VOID"; + case TypeClass::INTEGER: + return "INTEGER"; + case TypeClass::SSE: + return "SSE"; + case TypeClass::SSEUP: + return "SSEUP"; + case TypeClass::X87: + return "X87"; + case TypeClass::X87UP: + return "X87UP"; + case TypeClass::COMPLEX_X87: + return "X87UP"; + case TypeClass::NO_CLASS: + return "NO_CLASS"; + case TypeClass::MEMORY: + return "MEMORY"; + default: + return "UNKNOWN"; + } +} + +// Chapter 3.2.3 Parameter Passing +std::optional Classify_ParamType(sp::HookParamType type) { + switch (type) { + case sp::HookParamType_StringPtr: + case sp::HookParamType_CharPtr: + case sp::HookParamType_VectorPtr: + case sp::HookParamType_Bool: + case sp::HookParamType_Int: + case sp::HookParamType_CBaseEntity: + case sp::HookParamType_ObjectPtr: + case sp::HookParamType_Edict: + return TypeClass::INTEGER; + case sp::HookParamType_Float: + return TypeClass::SSE; + default: + break; + } + return {}; +} + +std::optional Classify_ReturnType(const ReturnVariable& info) { + if (info.dhook_size > (4 * 8)) { + return TypeClass::MEMORY; + } + + switch (info.dhook_type) { + case sp::ReturnType_Int: + case sp::ReturnType_Bool: + case sp::ReturnType_String: + case sp::ReturnType_StringPtr: + case sp::ReturnType_CharPtr: + case sp::ReturnType_VectorPtr: + case sp::ReturnType_CBaseEntity: + case sp::ReturnType_Edict: + return TypeClass::INTEGER; + case sp::ReturnType_Float: + case sp::ReturnType_Vector: // Not true but it's fine... Must be reworked if dhook ever introduces complex types + return TypeClass::SSE; + case sp::ReturnType_Void: + return TypeClass::VOID; + default: + break; + } + return {}; +} + +bool Proccess(sp::CallingConvention conv, std::vector& params, ReturnVariable& ret, size_t& stack_size) { + // 3.2.3 Parameter Passing + static const AsmReg available_general_registers[] = { rdi, rsi, rdx, rcx, r8, r9 }; + static const AsmFloatReg available_float_registers[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 }; + size_t general_register_available = 0; + static constexpr size_t general_register_count = sizeof(available_general_registers) / sizeof(AsmReg); + size_t float_register_available = 0; + static constexpr size_t float_register_count = sizeof(available_float_registers) / sizeof(AsmFloatReg); + + if (ret.dhook_custom_register == sp::DHookRegister_Default) { + auto cls = Classify_ReturnType(ret); + if (!cls.has_value()) { + globals::sourcemod->LogError(globals::myself, "Couldn't classify return type!"); + return false; + } + /*if (cls.value() == TypeClass::MEMORY) { + // RDI is used by the Return + // Unsupported for now + ret.reg_index = available_general_registers[general_register_available++]; + ret.reg_offset = {}; + globals::sourcemod->LogError(globals::myself, "!"); + return false; + } + // We don't know how to handle it + else*/ if (cls.value() != TypeClass::INTEGER + && cls.value() != TypeClass::SSE + && cls.value() != TypeClass::VOID) { + globals::sourcemod->LogError(globals::myself, "ABI classified return type as \"%s\", we don't know how to handle it!", TypeToString(cls.value())); + return false; + } + } else { + ret.reg_index = Translate_DHookRegister(ret.dhook_custom_register); + ret.float_reg_index = Translate_DHookRegister_Float(ret.dhook_custom_register); + ret.reg_offset = {}; + // Need better support + globals::sourcemod->LogError(globals::myself, "Custom register for return isn't supported!"); + return false; + } + + // Calling conventions don't really exist in this ABI, however for easier user experience + // We still use CallConv_THISCALL to figure whether or not we're dealing with a member func + if (conv == sp::CallConv_THISCALL) { + Variable this_ptr; + this_ptr.dhook_type = sp::HookParamType_Int; + this_ptr.dhook_custom_register = sp::DHookRegister_Default; + this_ptr.dhook_pass_flags = sp::DHookPass_ByVal; + this_ptr.dhook_size = sizeof(void*); + params.insert(params.begin(), this_ptr); + } + + /* Skip the return address */ + size_t stack_offset = sizeof(void*); + {auto len = params.size(); for (unsigned int i = 0; i < len; i++) { + auto& param = params[i]; + if (param.dhook_custom_register == sp::DHookRegister_Default) { + auto cls = Classify_ParamType(param.dhook_type); + if (!cls.has_value()) { + if (param.dhook_pass_flags & sp::DHookPass_ByRef) { + // Its a pointer + cls = TypeClass::INTEGER; + } else { + // Otherwise not supported, end + // TO-DO: Update and support objects passed on the stack + globals::sourcemod->LogError(globals::myself, "ABI could not classify parameter (%d)!", i); + return false; + } + } + switch (cls.value()) { + case TypeClass::INTEGER: + if (general_register_count == general_register_available) { + // No regs left, its on the stack + param.reg_index = RSP; + param.reg_offset = stack_offset; + stack_offset += sizeof(void*); + } else { + param.reg_index = available_general_registers[general_register_available++]; + param.reg_offset = {}; + } + break; + case TypeClass::SSE: + if (float_register_count == float_register_available) { + // No regs left, its on the stack + param.reg_index = RSP; + param.reg_offset = stack_offset; + stack_offset += sizeof(void*); + } else { + param.float_reg_index = available_float_registers[float_register_available++]; + param.reg_offset = {}; + float_register_available++; + } + break; + default: + globals::sourcemod->LogError(globals::myself, "ABI classified parameter (%d) as %s, we don't know how to handle it!", i, TypeToString(cls.value())); + return false; + } + } else { + param.reg_index = Translate_DHookRegister(param.dhook_custom_register); + param.float_reg_index = Translate_DHookRegister_Float(param.dhook_custom_register); + ret.reg_offset = {}; + } + }} + /* Stack size here only means the size the parameters occupy, so remove the space occupied by return address */ + stack_size = stack_offset - sizeof(void*); + return true; +} + +void JIT_CallMemberFunction(AsmJit& jit, bool save_general_register[MAX_GENERAL_REGISTERS], bool save_float_register[MAX_FLOAT_REGISTERS], void* this_ptr, const void* mfp, bool post) { + jit.push(rbp); + jit.mov(rbp, rsp); + + static constexpr size_t stack_size = (MAX_GENERAL_REGISTERS * 0x8) + (MAX_FLOAT_REGISTERS * 0x10); + static_assert(stack_size % 16 == 0); // System-V requires the stack to be aligned for any call operation + jit.sub(rsp, stack_size); + + // Independently of anything else, RAX gets saved always + jit.mov(rsp(), rax); + for (size_t i = 1; i < MAX_GENERAL_REGISTERS; i++) { + auto reg = AsmReg((AsmRegCode)i); + if (!save_general_register[i]) { + continue; + } + if (reg == STACK_REG) { + // We modified the stack, so RSP no longer holds the correct value + jit.lea(rax, rsp(stack_size)); + jit.mov(rsp(i * 0x8), rax); + } else { + jit.mov(rsp(i * 0x8), reg); + } + } + + for (size_t i = 1; i < MAX_FLOAT_REGISTERS; i++) { + auto reg = AsmFloatReg((AsmFloatRegCode)i); + if (!save_float_register[i]) { + continue; + } + jit.movsd(rsp(i * 0x10 + (MAX_GENERAL_REGISTERS * 0x8)), reg); + } + // void Capsule::PrePostHookLoop(std::uint8_t* saved_register, bool post) + jit.mov(rdx, post); + jit.mov(rsi, rsp); + jit.mov(rdi, reinterpret_cast(this_ptr)); + jit.mov(rax, reinterpret_cast(mfp)); + jit.call(rax); + + jit.add(rsp, stack_size); + jit.pop(rbp); +} + +void JIT_MakeReturn(AsmJit& jit, ReturnVariable& ret) { + jit.push(rbp); // Re-align stack + jit.sub(rsp, 0x10); // Make space to save data + jit.mov(rbp, rsp); + + jit.mov(rax, reinterpret_cast(::KHook::GetCurrentValuePtr)); + jit.mov(rdi, true); // Pop + jit.call(rax); + // RAX now contains the return value ptr + switch (Classify_ReturnType(ret).value()) { + case TypeClass::VOID: + // Do nothing + break; + case TypeClass::MEMORY: + // Currently unsupported + std::abort(); + break; + case TypeClass::INTEGER: + // At the present time, dhook has trivial INTEGER types + // However this will have to be revised to MOV on RDI too + // if there's an INTEGER return type that exceeds 8 bytes + jit.mov(rax, rax()); + // Save RAX, we're gonna call a function which could modify rax + jit.mov(rsp(), rax); + break; + case TypeClass::SSE: + // TO-DO: handle this better... + if (ret.dhook_type == sp::ReturnType_Vector) { + jit.movsd(xmm0, rax()); + jit.movsd(rsp(), xmm0); + jit.movsd(xmm1, rax(0x8)); + jit.movsd(rsp(0x8), xmm1); + } else { + jit.movsd(xmm0, rax()); + jit.movsd(rsp(), xmm0); + } + break; + default: + std::abort(); + return; + } + + jit.mov(rax, reinterpret_cast(::KHook::DestroyReturnValue)); + jit.call(rax); + + switch (Classify_ReturnType(ret).value()) { + case TypeClass::VOID: + break; + case TypeClass::INTEGER: + // Restore RAX + jit.mov(rax, rsp()); + break; + case TypeClass::SSE: + // TO-DO: handle this better... + if (ret.dhook_type == sp::ReturnType_Vector) { + jit.movsd(xmm0, rsp()); + jit.movsd(xmm1, rsp(0x8)); + } else { + jit.movsd(xmm0, rsp()); + } + break; + default: + std::abort(); + return; + } + + jit.add(rsp, 0x10); + jit.pop(rbp); + jit.retn(); +} + +void JIT_Recall(AsmJit& jit, bool save_general_register[MAX_GENERAL_REGISTERS], bool save_float_register[MAX_FLOAT_REGISTERS], size_t stack_size, std::uintptr_t* jit_start) { + jit.push(rbp); + jit.mov(rbp, rsp); + + // 1st - rdi - is ptr to function to call + // 2nd - rsi - is ptr to registers + + if (stack_size != 0) { + if (save_general_register[STACK_REG] == false) { + // What the hell + std::abort(); + } + // Have RAX act as the previous stack + jit.mov(rax, rsi(sizeof(GeneralRegister) * STACK_REG)); + + // Prepare the stack + jit.sub(rsp, stack_size + (16 - (stack_size % 16)) % 16); + + // Save the 2 parameters + jit.push(rdi); + jit.push(rsi); + + // Skip the two parameters we just saved + jit.lea(rdi, rsp(0x8 * 2)); + // Skip return value contained in the stack + jit.lea(rsi, rax(0x8)); + jit.mov(rdx, stack_size); + + jit.mov(rax, reinterpret_cast(memcpy)); + jit.call(rax); + + jit.pop(rsi); + jit.pop(rdi); + } + + // Prepare function to call + jit.push(rdi); + jit.push(rdi); + + // Figure out the return address + jit.mov(rdi, reinterpret_cast(jit_start)); + jit.mov(rdi, rdi()); + jit.add(rdi, INT32_MAX); + auto add = jit.get_outputpos(); + jit.mov(rsp(0x8), rdi); + + // Restore the registers + for (size_t i = 1; i < MAX_FLOAT_REGISTERS; i++) { + auto reg = AsmFloatReg((AsmFloatRegCode)i); + if (!save_float_register[i]) { + continue; + } + jit.movsd(reg, rsi(i * 0x10 + (MAX_GENERAL_REGISTERS * 0x8))); + } + + for (size_t i = 1; i < MAX_GENERAL_REGISTERS; i++) { + auto reg = AsmReg((AsmRegCode)i); + if (!save_general_register[i]) { + continue; + } + // Stack isn't a register to restore + if (reg != STACK_REG && reg != rsi) { + jit.mov(reg, rsi(sizeof(GeneralRegister) * i)); + } + } + // RSI is restored last + if (save_general_register[RSI]) { + jit.mov(rsi, rsi(sizeof(GeneralRegister) * RSI)); + } + + // Call the recall + jit.retn(); + // Rewrite the add value + jit.rewrite(add - sizeof(std::int32_t), jit.get_outputpos()); + + jit.mov(rsp, rbp); + jit.pop(rbp); + jit.retn(); +} + +void JIT_CallOriginal(AsmJit& jit, ReturnVariable& ret, std::uintptr_t* original_function, size_t stack_size, std::uintptr_t* jit_start) { + auto start = jit.get_outputpos(); + + // save rax (and re-align stack) + jit.push(rax); + + // Ensure stack size is aligned on 16 bytes + stack_size = (stack_size + 15) & ~15; + jit.sub(rsp, stack_size); + + // Now copy stack over + for (int i = 0; i < stack_size; i += sizeof(void*)) { + // Skip saved RAX, skip return value + jit.mov(rax, rsp(stack_size + 0x8 + 0x8 + i)); + jit.mov(rsp(i), rax); + } + + // Setup the return address to later in this function + jit.mov(rax, reinterpret_cast(jit_start)); + jit.mov(rax, rax()); + jit.add(rax, INT32_MAX); + auto add = jit.get_outputpos(); + + // Place the return address + jit.push(rax); + + jit.mov(rax, reinterpret_cast(original_function)); + jit.mov(rax, rax()); + + // Place the call address + jit.push(rax); + // Restore rax (call addr, return addr) + stack_size + jit.mov(rax, rsp(0x8 + 0x8 + stack_size)); + jit.retn(); + + jit.rewrite(add - sizeof(std::int32_t), jit.get_outputpos()); + + // Free up the stack + jit.add(rsp, stack_size); + jit.sub(rsp, 0x10); // Make some space for local save data + + // Stack is currently aligned + // Store the return value in a local variable + std::uintptr_t init_op = 0; + std::uintptr_t deinit_op = 0; + switch (Classify_ReturnType(ret).value()) { + case TypeClass::VOID: + break; + case TypeClass::INTEGER: + // Store RAX + jit.mov(rsp(), rax); + + init_op = reinterpret_cast(KHook::init_operator); + deinit_op = reinterpret_cast(KHook::deinit_operator); + break; + case TypeClass::SSE: + // TO-DO: handle this better... + if (ret.dhook_type == sp::ReturnType_Vector) { + jit.movsd(rsp(), xmm0); + jit.movsd(rsp(0x8), xmm1); + + init_op = reinterpret_cast(KHook::init_operator); + deinit_op = reinterpret_cast(KHook::deinit_operator); + } else { + jit.movsd(rsp(), xmm0); + + init_op = reinterpret_cast(KHook::init_operator); + deinit_op = reinterpret_cast(KHook::deinit_operator); + } + break; + default: + std::abort(); + return; + } + + // KHook::SaveReturnValue(KHook::Action action, void* ptr_to_return, std::size_t return_size, void* init_op, void* delete_op, bool original) + jit.mov(rdi, (std::uint8_t)KHook::Action::Ignore); // action + if (Classify_ReturnType(ret).value() == TypeClass::VOID) { + jit.mov(rsi, 0x0); // ptr_to_return + jit.mov(rdx, 0x0); // return_size + jit.mov(rcx, 0x0); // init_op + jit.mov(r8, 0x0); // deinit_op + } else { + jit.mov(rsi, rsp); // ptr_to_return + jit.mov(rdx, ret.dhook_size); // return_size + jit.mov(rcx, init_op); // init_op + jit.mov(r8, deinit_op); // deinit_op + } + jit.mov(r9, true); // original + + jit.mov(rax, reinterpret_cast(::KHook::SaveReturnValue)); + jit.call(rax); + + // Free local save data + RAX + jit.add(rsp, 0x10 + 0x8); + + jit.retn(); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/capsule.cpp b/extensions/dhooks/src/capsule.cpp new file mode 100644 index 0000000000..2b785bf6df --- /dev/null +++ b/extensions/dhooks/src/capsule.cpp @@ -0,0 +1,367 @@ +#include "capsule.hpp" +#include "handle.hpp" +#include "abi.hpp" +#include "sdk_types.hpp" + +namespace dhooks { + +using namespace KHook::Asm; + +namespace locals { +std::uint32_t last_hook_id = 1; +std::unordered_map> address_detours; +std::unordered_map> virtual_detours; +std::unordered_map hook_callbacks; +std::unordered_map> plugin_hook_ids; + +static std::unique_ptr nullptr_capsule(nullptr); +} + +const std::unique_ptr& Capsule::FindOrCreate(const handle::HookSetup* setup, void** vtable) { + auto dyndetour = dynamic_cast(setup); + if (dyndetour) { + // Let's see if a hook already exists + auto it = locals::address_detours.find(dyndetour->GetAddress()); + if (it == locals::address_detours.end()) { + // It does not, so let's create it + auto hook = new Capsule(dyndetour->GetAddress(), nullptr, 0, setup->GetCallConv(), setup->GetParameters(), setup->GetReturn()); + if (!hook->IsActive()) { + delete hook; + return locals::nullptr_capsule; + } + auto insert = locals::address_detours.try_emplace(dyndetour->GetAddress(), hook); + if (!insert.second) { + delete hook; + return locals::nullptr_capsule; + } + it = insert.first; + } + return it->second; + } + auto dynhook = dynamic_cast(setup); + if (dynhook) { + auto key = reinterpret_cast(reinterpret_cast(vtable) + dynhook->GetOffset()); + // Let's see if a hook already exists + auto it = locals::virtual_detours.find(key); + if (it == locals::virtual_detours.end()) { + // It does not, so let's create it + auto hook = new Capsule(nullptr, vtable, dynhook->GetOffset(), setup->GetCallConv(), setup->GetParameters(), setup->GetReturn()); + if (!hook->IsActive()) { + delete hook; + return locals::nullptr_capsule; + } + auto insert = locals::virtual_detours.try_emplace(key, hook); + if (!insert.second) { + delete hook; + return locals::nullptr_capsule; + } + it = insert.first; + } + return it->second; + } + return locals::nullptr_capsule; +} + +class EmptyClass { +public: + bool AllowedToHealTarget_MakeReturn( CBaseEntity* pTarget ) { + printf("MAKE RETURN\n"); + + bool ret = *(bool*)::KHook::GetCurrentValuePtr(true); + ::KHook::DestroyReturnValue(); + return ret; + } + + bool AllowedToHealTarget_CallOriginal( CBaseEntity* pTarget ) { + printf("CALLED ORIGINAL 0x%lX\n", (uintptr_t)this); + + auto ptr = KHook::BuildMFP(::KHook::GetOriginalFunction()); + bool ret = (((EmptyClass*)this)->*ptr)(pTarget); + ::KHook::__internal__savereturnvalue(KHook::Return{ KHook::Action::Ignore, ret }, true); + return ret; + } +}; + +std::uint32_t Capsule::AddCallback(SourcePawn::IPluginFunction* callback, SourcePawn::IPluginFunction* remove_callback, sp::HookMode mode, sp::ThisPointerType this_ptr, void* associated_this) { + auto id = ++locals::last_hook_id; + + HookCallback cb; + cb.this_pointer_type = this_ptr; + cb.associated_this = associated_this; + cb.associated_capsule = this; + cb.callback = callback; + cb.remove_callback = remove_callback; + cb.using_int64_address = (callback->GetParentRuntime()->FindPubvarByName("__Int64_Address__", nullptr) == SP_ERROR_NONE); + + auto plugin_it = locals::plugin_hook_ids.find(callback->GetParentRuntime()->GetDefaultContext()); + if (plugin_it == locals::plugin_hook_ids.end()) { + auto plugin_insert = locals::plugin_hook_ids.try_emplace(callback->GetParentRuntime()->GetDefaultContext()); + if (!plugin_insert.second) { + return 0; + } + plugin_it = plugin_insert.first; + } + if (plugin_it->second.find(id) != plugin_it->second.end()) { + return 0; + } + if (plugin_it->second.insert(id).second == false) { + return 0; + } + + auto it = locals::hook_callbacks.find(id); + if (it == locals::hook_callbacks.end()) { + auto it_insert = locals::hook_callbacks.try_emplace(id, cb); + if (!it_insert.second) { + plugin_it->second.erase(id); + return 0; + } + it = it_insert.first; + } else { + plugin_it->second.erase(id); + return 0; + } + + auto& callbacks = (mode == sp::HookMode::Hook_Post) ? this->_post_hooks : this->_pre_hooks; + auto capsule_it = callbacks.find(id); + if (capsule_it == callbacks.end()) { + auto capsule_emplace = callbacks.try_emplace(id, cb); + if (!capsule_emplace.second) { + locals::hook_callbacks.erase(id); + plugin_it->second.erase(id); + return 0; + } + capsule_it = capsule_emplace.first; + } else { + locals::hook_callbacks.erase(id); + plugin_it->second.erase(id); + return 0; + } + return id; +} + +void Capsule::RemoveCallbackById(std::uint32_t id) { + auto it = locals::hook_callbacks.find(id); + if (locals::hook_callbacks.end() == it) { + return; + } + const auto& cb = it->second; + auto rm_callback = cb.remove_callback; + + if (cb.associated_capsule != nullptr) { + cb.associated_capsule->_pre_hooks.erase(id); + cb.associated_capsule->_post_hooks.erase(id); + } + auto plugin_hooks_it = locals::plugin_hook_ids.find(cb.callback->GetParentRuntime()->GetDefaultContext()); + if (locals::plugin_hook_ids.end() != plugin_hooks_it) { + plugin_hooks_it->second.erase(id); + } + locals::hook_callbacks.erase(id); + + if (rm_callback != nullptr && rm_callback->IsRunnable()) { + rm_callback->PushCell((cell_t)id); + cell_t result; + rm_callback->Execute(&result); + } +} + +void Capsule::RemoveCallbackByPlugin(SourcePawn::IPluginContext* default_context) { + auto plugin_hooks_it = locals::plugin_hook_ids.find(default_context); + if (locals::plugin_hook_ids.end() == plugin_hooks_it) { + return; + } + for (auto id : plugin_hooks_it->second) { + auto it = locals::hook_callbacks.find(id); + if (locals::hook_callbacks.end() == it) { + continue; + } + const auto& cb = it->second; + auto rm_callback = cb.remove_callback; + + if (cb.associated_capsule != nullptr) { + cb.associated_capsule->_pre_hooks.erase(id); + cb.associated_capsule->_post_hooks.erase(id); + } + locals::hook_callbacks.erase(id); + + if (rm_callback != nullptr && rm_callback->IsRunnable()) { + rm_callback->PushCell((cell_t)id); + cell_t result; + rm_callback->Execute(&result); + } + } + locals::plugin_hook_ids.erase(default_context); +} + +Capsule::Capsule(void* address, void** vtable, std::uint32_t vtable_index, sp::CallingConvention conv, const std::vector& params, const ReturnVariable& ret) : + _parameters(params), + _return(ret), + _linked_hook(KHook::INVALID_HOOK), + _call_conv(conv) { + if (!abi::Proccess(conv, _parameters, _return, _stack_size)) { + globals::sourcemod->LogError(globals::myself, "Failed to create Capsule based on provided parameters"); + return; + } + + // Well we need to know what we're detouring here + if (address == nullptr && vtable == nullptr) { + globals::sourcemod->LogError(globals::myself, "Failed to create Capsule, neither a vtable or address was given"); + return; + } + + // For every parameter found, and return value, save the associated registers + for (auto& param : _parameters) { + if (param.float_reg_index) { + _save_float_register[param.float_reg_index.value()] = true; + } + if (param.reg_index) { + _save_general_register[param.reg_index.value()] = true; + } + + if (!param.float_reg_index && !param.reg_index) { + // A parameter must be associated with a register + // If a parameter is on the stack, then it must be + // associated with the stack and the offset into it + globals::sourcemod->LogError(globals::myself, "Param isn't associated with register. Kill server"); + std::abort(); + } + } + if (_return.float_reg_index) { + _save_float_register[_return.float_reg_index.value()] = true; + } + if (_return.reg_index) { + _save_general_register[_return.reg_index.value()] = true; + } + + const void* mfp = nullptr; + switch (ret.dhook_type) { + case sp::ReturnType_Void: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_Int: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_Bool: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_Float: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_String: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_StringPtr: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_CharPtr: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_Vector: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_VectorPtr: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_CBaseEntity: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + case sp::ReturnType_Edict: + mfp = KHook::ExtractMFP(&Capsule::PrePostHookLoop); + break; + default: + globals::sourcemod->LogError(globals::myself, "Invalid return type. Kill server"); + std::abort(); + break; + } + + abi::JIT_Align(_jit); + auto offset_to_pre_callback = _jit.get_outputpos(); + // PRE Callback + { + abi::JIT_CallMemberFunction(_jit, _save_general_register, _save_float_register, this, mfp, false); + // KHook doesn't care whether or not we've set the return registers/cleaned the stack + _jit.retn(); + } + + abi::JIT_Align(_jit); + auto offset_to_post_callback = _jit.get_outputpos(); + // POST Callback + { + abi::JIT_CallMemberFunction(_jit, _save_general_register, _save_float_register, this, mfp, true); + // KHook doesn't care whether or not we've set the return registers/cleaned the stack + _jit.retn(); + } + + abi::JIT_Align(_jit); + auto offset_to_make_return = _jit.get_outputpos(); + abi::JIT_MakeReturn(_jit, _return); + + abi::JIT_Align(_jit); + auto offset_to_call_original = _jit.get_outputpos(); + abi::JIT_CallOriginal(_jit, _return, &_original_function, _stack_size, &_jit_start); + + abi::JIT_Align(_jit); + auto offset_to_recall = _jit.get_outputpos(); + abi::JIT_Recall(_jit, _save_general_register, _save_float_register, _stack_size, &_jit_start); + + _jit.SetRE(); + _jit_start = reinterpret_cast(_jit.GetData()); + + _linked_hook = (address != nullptr) ? + KHook::SetupHook( + address, + this, + KHook::ExtractMFP(&Capsule::_KHook_RemovedHook), + reinterpret_cast(_jit_start + offset_to_pre_callback), + reinterpret_cast(_jit_start + offset_to_post_callback), + reinterpret_cast(_jit_start + offset_to_make_return), // KHook::ExtractMFP(&EmptyClass::AllowedToHealTarget_MakeReturn), //reinterpret_cast(_jit_start + offset_to_make_return), + reinterpret_cast(_jit_start + offset_to_call_original), // KHook::ExtractMFP(&EmptyClass::AllowedToHealTarget_CallOriginal), //reinterpret_cast(_jit_start + offset_to_call_original), + true + ) + : + KHook::SetupVirtualHook( + vtable, + vtable_index, + this, + KHook::ExtractMFP(&Capsule::_KHook_RemovedHook), + reinterpret_cast(_jit_start + offset_to_pre_callback), + reinterpret_cast(_jit_start + offset_to_post_callback), + reinterpret_cast(_jit_start + offset_to_make_return), + reinterpret_cast(_jit_start + offset_to_call_original), + true + ); + + if (_linked_hook != KHook::INVALID_HOOK) { + _original_function = (address != nullptr) ? + reinterpret_cast(KHook::FindOriginal(address)) + : + reinterpret_cast(KHook::FindOriginalVirtual(vtable, vtable_index)); + _recall_function = reinterpret_cast(_jit_start + offset_to_recall); + } +} + +void Capsule::_KHook_RemovedHook(unsigned int) { +} + +Capsule::~Capsule() { + if (_linked_hook != KHook::INVALID_HOOK) { + KHook::RemoveHook(_linked_hook, false); + } + for (const auto& it : _pre_hooks) { + locals::hook_callbacks.erase(it.first); + auto default_ctx = it.second.callback->GetParentRuntime()->GetDefaultContext(); + auto plugin_it = locals::plugin_hook_ids.find(default_ctx); + if (plugin_it != locals::plugin_hook_ids.end()) { + plugin_it->second.erase(it.first); + } + } + for (const auto& it : _post_hooks) { + locals::hook_callbacks.erase(it.first); + auto default_ctx = it.second.callback->GetParentRuntime()->GetDefaultContext(); + auto plugin_it = locals::plugin_hook_ids.find(default_ctx); + if (plugin_it != locals::plugin_hook_ids.end()) { + plugin_it->second.erase(it.first); + } + } +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/capsule.hpp b/extensions/dhooks/src/capsule.hpp new file mode 100644 index 0000000000..fc7344774a --- /dev/null +++ b/extensions/dhooks/src/capsule.hpp @@ -0,0 +1,186 @@ +#pragma once + +#include "register.hpp" +#include "sp_inc.hpp" +#include "globals.hpp" +#include "handle.hpp" +#include "hook.hpp" +#include "variable.hpp" + +#if defined(DHOOKS_X86_64) +#include +#elif defined(DHOOKS_X86) +#include +#endif +#include + +#include +#include +#include +#include +#include + +namespace dhooks { + +#if defined(DHOOKS_X86_64) +using AsmJit = KHook::Asm::x86_64_Jit; +#elif defined(DHOOKS_X86) +using AsmJit = KHook::Asm::x86_Jit; +#endif + +struct HookCallback; +class Capsule { +protected: + Capsule(void* address, void** vtable, std::uint32_t vtable_index, sp::CallingConvention conv, const std::vector& params, const ReturnVariable& ret); +public: + ~Capsule(); + + static const std::unique_ptr& FindOrCreate(const class handle::HookSetup* setup, void** vtable = nullptr); + std::uint32_t AddCallback(SourcePawn::IPluginFunction* callback, SourcePawn::IPluginFunction* remove_callback, sp::HookMode mode, sp::ThisPointerType this_ptr, void* associated_this); + static void RemoveCallbackById(std::uint32_t id); + static void RemoveCallbackByPlugin(SourcePawn::IPluginContext* default_context); + + const std::vector& GetParameters() const { return _parameters; }; + const ReturnVariable& GetReturn() const { return _return; }; + const sp::CallingConvention GetCallConv() const { return _call_conv; }; + + bool IsActive() const { return _linked_hook != KHook::INVALID_HOOK; } +protected: + //void JIT_SaveRegisters(AsmJit& jit); + void JIT_RestoreRegisters(AsmJit& jit); + + template + void PrePostHookLoop(std::uint8_t* saved_register, bool post) const; +protected: + static void _KHook_RemovedHook(KHook::HookID_t id); + + // Parameters for the Capsule + std::vector _parameters; + ReturnVariable _return; + +#if defined(DHOOKS_X86_64) + static_assert(KHook::Asm::R15 == (MAX_GENERAL_REGISTERS - 1), "Mismatch in register index"); + static_assert(KHook::Asm::XMM15 == (MAX_FLOAT_REGISTERS - 1), "Mismatch in register index"); +#elif defined(DHOOKS_X86) + static_assert(KHook::Asm::RSP == (MAX_GENERAL_REGISTERS - 1), "Mismatch in register index"); + static_assert(KHook::Asm::XMM7 == (MAX_FLOAT_REGISTERS - 1), "Mismatch in register index"); +#endif + + // Registers we should save upon function entry + bool _save_general_register[MAX_GENERAL_REGISTERS]; + // Registers we should save upon function entry + bool _save_float_register[MAX_FLOAT_REGISTERS]; + + // First is general registers, second is float registers + std::stack, std::unique_ptr>> _saved_registers; + + AsmJit _jit; + size_t _stack_size; + KHook::HookID_t _linked_hook; + std::uintptr_t _original_function; + std::uintptr_t _jit_start; + void (*_recall_function)(void* recall_func, std::uint8_t* saved_register); + + std::unordered_map _pre_hooks; + std::unordered_map _post_hooks; + + // Only for dhook natives + sp::CallingConvention _call_conv; +}; + +template +void Capsule::PrePostHookLoop(std::uint8_t* saved_register, bool post) const { + RETURN* return_ptr = nullptr; + RETURN* temp_ptr = nullptr; + void* init_op = nullptr; + void* delete_op = nullptr; + size_t return_size = 0; + + if constexpr(!std::is_same::value) { + return_ptr = new RETURN; + temp_ptr = new RETURN; + init_op = reinterpret_cast(::KHook::init_operator); + delete_op = reinterpret_cast(::KHook::deinit_operator); + return_size = sizeof(RETURN); + } + + KHook::Action final_action = KHook::Action::Ignore; + // Only detours executing on the main thread can fire dhooks' callback + // Most notably because the SP VM isn't thread safe + if (std::this_thread::get_id() == globals::main_thread) { + handle::ParamReturn paramret( + this, + reinterpret_cast(saved_register), + reinterpret_cast(saved_register + sizeof(GeneralRegister) * MAX_GENERAL_REGISTERS), + return_ptr + ); + + // If this is a post hook, fill in the return ptr with the current value (original or override) + if constexpr(!std::is_same::value) { + if (post) { + *return_ptr = *reinterpret_cast(KHook::GetCurrentValuePtr()); + } + } + + // Save some time and pre-save a this pointer (if it even exists) + void* this_ptr = nullptr; + std::optional entity_index; + if (_parameters.size() != 0) { + this_ptr = *(paramret.Get(0)); + //printf("this_ptr 0x%lX\n", (uintptr_t)this_ptr); + } + + // Make deep-copy to allow deletion of hooks under callbacks + auto hooks = (post) ? _post_hooks : _pre_hooks; + for (const auto& it : hooks) { + const auto& hook = it.second; + if (hook.callback->IsRunnable()) { + if (hook.associated_this != nullptr && hook.associated_this != this_ptr) { + continue; + } + + if (hook.this_pointer_type != sp::ThisPointer_Ignore) { + // Push the associated this pointer + if (hook.this_pointer_type == sp::ThisPointer_CBaseEntity) { + if (!entity_index) { + entity_index = globals::gamehelpers->EntityToBCompatRef(reinterpret_cast(this_ptr)); + } + hook.callback->PushCell(entity_index.value_or(-1)); + } else if (hook.this_pointer_type == sp::ThisPointer_Address) { + if (hook.using_int64_address) { + std::int64_t sm_address = reinterpret_cast(this_ptr); + hook.callback->PushArray((cell_t*)&sm_address, 2); + } else { + hook.callback->PushCell(reinterpret_cast(this_ptr)); + } + } + } + + if (_return.dhook_type != sp::ReturnType_Void) { + hook.callback->PushCell(paramret); + } + + if (_parameters.size() != 0) { + hook.callback->PushCell(paramret); + } + + cell_t result = (cell_t)sp::MRES_Ignored; + hook.callback->Execute(&result); + + if (result == (cell_t)sp::MRES_Supercede) { + final_action = KHook::Action::Supersede; + } else if (result != (cell_t)sp::MRES_Ignored) { + final_action = KHook::Action::Override; + } + // Params change, perform recall + if (result == (cell_t)sp::MRES_ChangedHandled || result == (cell_t)sp::MRES_ChangedOverride) { + void* recall_func = KHook::DoRecall(final_action, return_ptr, return_size, init_op, delete_op); + (*_recall_function)(recall_func, saved_register); + } + } + } + } + KHook::SaveReturnValue(final_action, return_ptr, return_size, init_op, delete_op, false); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/globals.cpp b/extensions/dhooks/src/globals.cpp new file mode 100644 index 0000000000..498dd3b85a --- /dev/null +++ b/extensions/dhooks/src/globals.cpp @@ -0,0 +1,76 @@ +#include "globals.hpp" +#include "signatures.hpp" + +namespace dhooks::globals { + +std::thread::id main_thread; +SourceMod::IExtension* myself; +SourceMod::IShareSys* sharedsys; +SourceMod::IHandleSys* handlesys; +SourceMod::IGameHelpers* gamehelpers; +SourceMod::ISourceMod* sourcemod; +SourceMod::IGameConfigManager* gameconfs; +SourceMod::ISDKTools* sdktools; +dhooks::SignatureGameConfig dhooks_config; + +template +static inline Interface* RequestSourcemodInterface( + const char* name, + unsigned int version, + char *error, + size_t maxlength) { + SourceMod::SMInterface* interface = nullptr; + if (globals::sharedsys->RequestInterface(name, version, globals::myself, &interface) && interface != nullptr) { + return (Interface*)interface; + } + + size_t len = ke::SafeSprintf(error, maxlength, "Could not find interface: %s", name); + if (len >= maxlength) { + error[maxlength - 1] = '\0'; + } + return nullptr; +} + +bool init(SourceMM::ISmmAPI* smmapi, SourceMod::IExtension* me, SourceMod::IShareSys* sys, char *error, size_t maxlength, bool late) { + globals::main_thread = std::this_thread::get_id(); + globals::myself = me; + globals::sharedsys = sys; + + if ((globals::handlesys = RequestSourcemodInterface( + SMINTERFACE_HANDLESYSTEM_NAME, + SMINTERFACE_HANDLESYSTEM_VERSION, + error, + maxlength)) == nullptr) { + return false; + } + + if ((globals::gamehelpers = RequestSourcemodInterface( + SMINTERFACE_GAMEHELPERS_NAME, + SMINTERFACE_GAMEHELPERS_VERSION, + error, + maxlength)) == nullptr) { + return false; + } + + if ((globals::sourcemod = RequestSourcemodInterface( + SMINTERFACE_SOURCEMOD_NAME, + SMINTERFACE_SOURCEMOD_VERSION, + error, + maxlength)) == nullptr) { + return false; + } + + if ((globals::gameconfs = RequestSourcemodInterface( + SMINTERFACE_GAMECONFIG_NAME, + SMINTERFACE_GAMECONFIG_VERSION, + error, + maxlength)) == nullptr) { + return false; + } + + globals::sdktools = nullptr; + + return true; +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/globals.hpp b/extensions/dhooks/src/globals.hpp new file mode 100644 index 0000000000..62cabd8524 --- /dev/null +++ b/extensions/dhooks/src/globals.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#define META_NO_HL2SDK +#include +#include + +#include +#include +#include +#include + +namespace dhooks { +class SignatureGameConfig; +}; + +namespace dhooks::globals { + +extern std::thread::id main_thread; +extern SourceMod::IHandleSys* handlesys; +extern SourceMod::IGameHelpers* gamehelpers; +extern SourceMod::IExtension* myself; +extern SourceMod::ISourceMod* sourcemod; +extern SourceMod::IGameConfigManager* gameconfs; +extern SourceMod::ISDKTools* sdktools; +extern std::vector natives; +extern dhooks::SignatureGameConfig dhooks_config; + +bool init(SourceMM::ISmmAPI* smmapi, SourceMod::IExtension* me, SourceMod::IShareSys* sys, char *error, size_t maxlength, bool late); + +inline const char *HandleErrorToString(SourceMod::HandleError err) { + switch(err) { + case SourceMod::HandleError_None: { return "No error"; } + case SourceMod::HandleError_Changed: { return "The handle has been freed and reassigned"; } + case SourceMod::HandleError_Type: { return "The handle has a different type registered"; } + case SourceMod::HandleError_Freed: { return "The handle has been freed"; } + case SourceMod::HandleError_Index: { return "generic internal indexing error"; } + case SourceMod::HandleError_Access: { return "No access permitted to free this handle"; } + case SourceMod::HandleError_Limit: { return "The limited number of handles has been reached"; } + case SourceMod::HandleError_Identity: { return "The identity token was not usable"; } + case SourceMod::HandleError_Owner: { return "Owners do not match for this operation"; } + case SourceMod::HandleError_Version: { return "Unrecognized security structure version"; } + case SourceMod::HandleError_Parameter: { return "An invalid parameter was passed"; } + case SourceMod::HandleError_NoInherit: { return "This type cannot be inherited"; } + } + return ""; +} + +inline void* cell_to_ptr(SourcePawn::IPluginContext* ctx, const cell_t addr) { + if (ctx->GetRuntime()->FindPubvarByName("__Virtual_Address__", nullptr) != SP_ERROR_NONE) { + return sourcemod->FromPseudoAddress(addr); + } + return reinterpret_cast(addr); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/handle.cpp b/extensions/dhooks/src/handle.cpp new file mode 100644 index 0000000000..8c4e2532bd --- /dev/null +++ b/extensions/dhooks/src/handle.cpp @@ -0,0 +1,337 @@ +#include "handle.hpp" +#include "globals.hpp" +#include "capsule.hpp" + +#include +#include +#include +#include +#include + +namespace dhooks::handle { + +SourceMod::HandleType_t ParamReturn::HANDLE_TYPE = 0; +SourceMod::HandleType_t HookSetup::HANDLE_TYPE = 0; +SourceMod::HandleType_t DynamicHook::HANDLE_TYPE = 0; +SourceMod::HandleType_t DynamicDetour::HANDLE_TYPE = 0; + +class CGenericClass; +namespace locals { +std::unordered_map associated_handle; +std::unordered_map> class_dynamichooks; +std::unordered_set class_vtables; +} + +ParamReturn::ParamReturn(const Capsule* capsule, GeneralRegister* generalregs, FloatRegister* floatregs, void* return_ptr) : + _handle(globals::handlesys->CreateHandle(handle::ParamReturn::HANDLE_TYPE, this, globals::myself->GetIdentity(), globals::myself->GetIdentity(), nullptr)), + _capsule(capsule), + _general_registers(generalregs), + _float_registers(floatregs), + _return(return_ptr) { +} + +ParamReturn::~ParamReturn() { + if (_handle != BAD_HANDLE) { + globals::handlesys->FreeHandle(_handle, nullptr); + } +} + +// This is a helper function for very trivial types (that are held by only one register) +// If dhooks becomes more complex this logic must be entirely re-written +void* ParamReturn::_Get(size_t index) const { + const auto& params = _capsule->GetParameters(); + if (params.size() <= index) { + // What the hell + std::abort(); + } + + const auto& variable = params[index]; + if (variable.reg_index) { + //printf("Reg code: %d Offset: %lu (%d)\n", variable.reg_index.value(), variable.reg_offset.value_or(0), variable.reg_offset.has_value()); + AsmRegCode code = variable.reg_index.value(); + + if (variable.reg_offset) { + // The register already acts as a pointer + return reinterpret_cast(static_cast(_general_registers[code]) + variable.reg_offset.value()); + } else { + // The register holds the value, return a pointer to it + return reinterpret_cast(&_general_registers[code]); + } + } else if (variable.float_reg_index) { + AsmFloatRegCode code = variable.float_reg_index.value(); + + if (variable.reg_offset) { + // Floating registers can't be pointers + std::abort(); + } else { + // The register holds the value, return a pointer to it + return reinterpret_cast(&_float_registers[code]); + } + } else { + // What the hell again + std::abort(); + } +} + +#if defined(_LINUX) +#define DTOR_PARAMS void +#define DTOR_PARAMS_NONAME +#define DTOR_PARAMS_ARGS +#define DTOR_VTABLE_INDEX 1 +#elif defined(_WIN32) +#define DTOR_PARAMS unsigned int arg +#define DTOR_PARAMS_NONAME , unsigned int +#define DTOR_PARAMS_ARGS arg +#define DTOR_VTABLE_INDEX 0 +#else +static_assert(false, "You forgort to provide a platform define!"); +#endif + +class CGenericClass { +public: + void KHook_Detour_PRE(DTOR_PARAMS) { + auto it = locals::class_dynamichooks.find(this); + if (it != locals::class_dynamichooks.end()) { + const auto& ids = it->second; + for (auto id : ids) { + auto hndl = DynamicHook::FindByHookID(id); + if (hndl != BAD_HANDLE) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + handle::DynamicHook* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, DynamicHook::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + obj = nullptr; + } + + if (obj) { + obj->RemoveHook(id); + } else { + Capsule::RemoveCallbackById(id); + } + } else { + Capsule::RemoveCallbackById(id); + } + } + locals::class_dynamichooks.erase(it); + } + + ::KHook::SaveReturnValue(KHook::Action::Ignore, nullptr, 0, nullptr, nullptr, false); + return; + } + void KHook_Make_CallOriginal(DTOR_PARAMS) { + void (CGenericClass::*ptr)(DTOR_PARAMS) = ::KHook::BuildMFP(::KHook::GetOriginalFunction()); + (this->*ptr)(DTOR_PARAMS_ARGS); + ::KHook::SaveReturnValue(KHook::Action::Ignore, nullptr, 0, nullptr, nullptr, true); + return; + } + void KHook_Make_Return(DTOR_PARAMS) { + ::KHook::DestroyReturnValue(); + return; + } +}; + +bool DynamicDetour::Enable(SourcePawn::IPluginFunction* callback, sp::HookMode mode) { + if (!this->IsImmutable()) { + return false; + } + + auto& detours = (mode == sp::HookMode::Hook_Post) ? _post_detours : _pre_detours; + if (detours.find(callback) != detours.end()) { + return false; + } + + const auto& capsule = Capsule::FindOrCreate(this); + if (capsule.get() == nullptr) { + return false; + } + + auto id = capsule->AddCallback(callback, nullptr, mode, this->_this_pointer, nullptr); + if (detours.try_emplace(callback, id).second == false) { + Capsule::RemoveCallbackById(id); + return false; + } + return true; +} + +bool DynamicDetour::Disable(SourcePawn::IPluginFunction* callback, sp::HookMode mode) { + auto& detours = (mode == sp::HookMode::Hook_Post) ? _post_detours : _pre_detours; + auto it = detours.find(callback); + if (it != detours.end()) { + return false; + } + + Capsule::RemoveCallbackById(it->second); + detours.erase(it); + return true; +} + +std::uint32_t DynamicHook::AddHook(SourcePawn::IPluginFunction* callback, SourcePawn::IPluginFunction* rm_callback, sp::HookMode mode, void* obj) { + if (!this->IsImmutable()) { + return 0; + } + + auto vtable = *(void***)obj; + const auto& capsule = Capsule::FindOrCreate(this, vtable); + if (capsule.get() == nullptr) { + globals::sourcemod->LogError(globals::myself, "Failed to create capsule"); + return 0; + } + + auto id = capsule->AddCallback(callback, rm_callback, mode, this->_this_pointer, obj); + if (_associated_hook.insert(id).second == false || locals::associated_handle.try_emplace(id, this->GetHandle()).second == false) { + Capsule::RemoveCallbackById(id); + globals::sourcemod->LogError(globals::myself, "Failed to insert callback"); + return 0; + } + + auto it = locals::class_dynamichooks.find((CGenericClass*)obj); + if (it == locals::class_dynamichooks.end()) { + auto insert = locals::class_dynamichooks.emplace((CGenericClass*)obj, std::vector()); + if (insert.second == false) { + return id; + } + it = insert.first; + + if (locals::class_vtables.find(vtable) == locals::class_vtables.end()) { + // Hook the virtual destructor, and perform hook cleaning actions under there + KHook::SetupVirtualHook( + vtable, + DTOR_VTABLE_INDEX, + nullptr, + nullptr, + KHook::ExtractMFP(&CGenericClass::KHook_Detour_PRE), + nullptr, + KHook::ExtractMFP(&CGenericClass::KHook_Make_Return), + KHook::ExtractMFP(&CGenericClass::KHook_Make_CallOriginal), + true + ); + locals::class_vtables.insert(vtable); + } + } + it->second.push_back(id); + return id; +} + +bool DynamicHook::RemoveHook(std::uint32_t id) { + if (_associated_hook.find(id) == _associated_hook.end()) { + return false; + } + Capsule::RemoveCallbackById(id); + _associated_hook.erase(id); + return true; +} + +cell_t DynamicHook::FindByHookID(std::uint32_t id) { + auto it = locals::associated_handle.find(id); + if (locals::associated_handle.end() == it) { + return BAD_HANDLE; + } + return it->second; +} + +HookSetup::HookSetup( + dhooks::sp::ThisPointerType thisptr_type, + dhooks::sp::CallingConvention callconv, + std::vector const& args, + dhooks::ReturnInfo const& ret + ) : + _handle(BAD_HANDLE), + _immutable(false), + _this_pointer(thisptr_type), + _dhook_call_conv(callconv) { + + for (const auto& arg : args) { + Variable var; + var.dhook_type = arg.info.type; + var.dhook_size = arg.info.size; + var.dhook_pass_flags = arg.info.flags; + var.dhook_custom_register = arg.info.custom_register; + + _dhook_params.push_back(var); + } + + _dhook_return.dhook_type = ret.type; + _dhook_return.dhook_size = ret.size; + _dhook_return.dhook_pass_flags = ret.flags; + _dhook_return.dhook_custom_register = ret.custom_register; +} + +DynamicDetour::DynamicDetour( + SourceMod::IdentityToken_t* plugin_ident, + dhooks::sp::ThisPointerType thisptr_type, + dhooks::sp::CallingConvention callconv, + void* address, + std::vector const& params, + dhooks::ReturnInfo const& ret) : + HookSetup(thisptr_type, callconv, params, ret), + _address(address) + { + SourceMod::HandleError err = SourceMod::HandleError_None; + _handle = globals::handlesys->CreateHandle( + DynamicDetour::HANDLE_TYPE, + this, + plugin_ident, + globals::myself->GetIdentity(), + &err + ); + if (_handle == BAD_HANDLE) { + globals::sourcemod->LogError(globals::myself, "Failed to create DynamicDetour: \"%s\" (%d)", globals::HandleErrorToString(err), err); + } +} + +DynamicDetour::~DynamicDetour() { + for (const auto& it : _post_detours) { + Capsule::RemoveCallbackById(it.second); + } + for (const auto& it : _pre_detours) { + Capsule::RemoveCallbackById(it.second); + } +} + +DynamicHook::DynamicHook( + SourceMod::IdentityToken_t* plugin_ident, + sp::ThisPointerType thisptr_type, + std::uint32_t offset, + sp::HookType type, + const std::vector& params, + const ReturnInfo& ret, + SourcePawn::IPluginFunction* default_callbakc) : + HookSetup(thisptr_type, sp::CallingConvention::CallConv_THISCALL, params, ret), + _offset(offset), + _hook_type(type), + _default_callback(default_callbakc) { + _handle = globals::handlesys->CreateHandle( + DynamicHook::HANDLE_TYPE, + this, + plugin_ident, + globals::myself->GetIdentity(), + nullptr + ); +} + +class HookSetupDispatch : public SourceMod::IHandleTypeDispatch { + virtual void OnHandleDestroy(SourceMod::HandleType_t type, void* object) override { + if (type == DynamicDetour::HANDLE_TYPE) { + delete (DynamicDetour*)object; + } + if (type == DynamicHook::HANDLE_TYPE) { + delete (DynamicHook*)object; + } + } +}; +HookSetupDispatch gHookSetupDispatcher; + +void init() { + SourceMod::HandleAccess security; + globals::handlesys->InitAccessDefaults(nullptr, &security); + // Do not allow cloning, the struct self-manage its handle + security.access[SourceMod::HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY; + ParamReturn::HANDLE_TYPE = globals::handlesys->CreateType("DHookParamReturn", &gHookSetupDispatcher, 0, nullptr, &security, globals::myself->GetIdentity(), nullptr); + HookSetup::HANDLE_TYPE = globals::handlesys->CreateType("DHookSetup", &gHookSetupDispatcher, 0, nullptr, &security, globals::myself->GetIdentity(), nullptr); + DynamicHook::HANDLE_TYPE = globals::handlesys->CreateType("DynamicHook", &gHookSetupDispatcher, HookSetup::HANDLE_TYPE, nullptr, &security, globals::myself->GetIdentity(), nullptr); + DynamicDetour::HANDLE_TYPE = globals::handlesys->CreateType("DynamicDetour", &gHookSetupDispatcher, HookSetup::HANDLE_TYPE, nullptr, &security, globals::myself->GetIdentity(), nullptr); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/handle.hpp b/extensions/dhooks/src/handle.hpp new file mode 100644 index 0000000000..0f56cd39df --- /dev/null +++ b/extensions/dhooks/src/handle.hpp @@ -0,0 +1,149 @@ +#pragma once + +#include "register.hpp" +#include "signatures.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace dhooks { +class Capsule; +} + +namespace dhooks::handle { + +void init(); + +class ParamReturn { +public: + operator cell_t() const { + return _handle; + } + operator cell_t() { + return _handle; + } + + ParamReturn(const Capsule*, GeneralRegister*, FloatRegister*, void*); + ~ParamReturn(); + + template + inline T* Get(size_t index) const { return reinterpret_cast(_Get(index)); }; + template + inline T* GetReturn() const { return reinterpret_cast(_return); }; + inline const Capsule* GetCapsule() const { return _capsule; }; + + static SourceMod::HandleType_t HANDLE_TYPE; +private: + void* _Get(size_t index) const; + + cell_t _handle; + const Capsule* _capsule; + GeneralRegister* _general_registers; + FloatRegister* _float_registers; + void* _return; +}; + +class HookSetup { +protected: + HookSetup( + dhooks::sp::ThisPointerType, + dhooks::sp::CallingConvention, + std::vector const&, + dhooks::ReturnInfo const& + ); +public: + + virtual ~HookSetup() = default; + static SourceMod::HandleType_t HANDLE_TYPE; + + bool IsImmutable() const { return _immutable; } + void SetImmutable() { _immutable = true; } + + void AddParam(const Variable& var) { if (!_immutable) { _dhook_params.push_back(var); } } + cell_t GetHandle() const { return _handle; } + + const sp::CallingConvention GetCallConv() const { return _dhook_call_conv; } + const std::vector& GetParameters() const { return _dhook_params; } + const ReturnVariable& GetReturn() const { return _dhook_return; } +protected: + cell_t _handle; + bool _immutable = false; + sp::ThisPointerType _this_pointer; + sp::CallingConvention _dhook_call_conv; + std::vector _dhook_params; + ReturnVariable _dhook_return; +}; + +class DynamicHook : public HookSetup { +public: + DynamicHook( + SourceMod::IdentityToken_t*, + sp::ThisPointerType, + std::uint32_t, + sp::HookType, + const std::vector& params, + const ReturnInfo& ret, + SourcePawn::IPluginFunction* + ); + static SourceMod::HandleType_t HANDLE_TYPE; + + void SetOffset(int offset) { + if (offset < 0) { + return; + } + _offset = offset; + } + + std::uint32_t GetOffset() const { + return _offset; + } + + sp::HookType GetType() const { + return _hook_type; + } + + SourcePawn::IPluginFunction* GetDefaultCallback() const { + return _default_callback; + } + + std::uint32_t AddHook(SourcePawn::IPluginFunction* callback, SourcePawn::IPluginFunction* rm_callback, sp::HookMode, void* obj); + bool RemoveHook(std::uint32_t id); + static cell_t FindByHookID(std::uint32_t id); +protected: + std::uint32_t _offset; + sp::HookType _hook_type; + SourcePawn::IPluginFunction* _default_callback; + std::unordered_set _associated_hook; +}; + +class DynamicDetour : public HookSetup { +public: + DynamicDetour(SourceMod::IdentityToken_t*, sp::ThisPointerType, sp::CallingConvention, void* address, const std::vector& params, const ReturnInfo& ret); + virtual ~DynamicDetour(); + static SourceMod::HandleType_t HANDLE_TYPE; + + void SetAddress(void* address) { + if (address == nullptr) { + return; + } + _address = address; + } + + void* GetAddress() const { + return _address; + } + + bool Enable(SourcePawn::IPluginFunction*, sp::HookMode); + bool Disable(SourcePawn::IPluginFunction*, sp::HookMode); +protected: + void* _address; + std::unordered_map _pre_detours; + std::unordered_map _post_detours; +}; + +}; \ No newline at end of file diff --git a/extensions/dhooks/src/hook.hpp b/extensions/dhooks/src/hook.hpp new file mode 100644 index 0000000000..215d505267 --- /dev/null +++ b/extensions/dhooks/src/hook.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "sp_inc.hpp" + +#include +#include + +namespace dhooks { + +class Capsule; + +struct HookCallback { + sp::ThisPointerType this_pointer_type; + void* associated_this; + Capsule* associated_capsule; + SourcePawn::IPluginFunction* callback; + SourcePawn::IPluginFunction* remove_callback; + bool using_int64_address; +}; + +} \ No newline at end of file diff --git a/extensions/dhooks/src/main.cpp b/extensions/dhooks/src/main.cpp new file mode 100644 index 0000000000..a93be556a5 --- /dev/null +++ b/extensions/dhooks/src/main.cpp @@ -0,0 +1,42 @@ +#include "globals.hpp" +#include "natives.hpp" +#include "signatures.hpp" +#include "handle.hpp" + +#include + +std::vector gNatives; + +class ExtensionBridge : public SDKExtension { + virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late) override { + if (dhooks::globals::init(g_SMAPI, myself, g_pShareSys, error, maxlength, late) == false) { + return false; + } + dhooks::handle::init(); + + gNatives.reserve(1000); + dhooks::natives::init(gNatives); + gNatives.push_back({nullptr, nullptr}); + sharesys->AddNatives(myself, gNatives.data()); + sharesys->AddDependency(myself, "sdktools.ext", true, true); + + dhooks::globals::gameconfs->AddUserConfigHook("Functions", &dhooks::globals::dhooks_config); + return true; + } + + virtual void SDK_OnAllLoaded() override { + SM_GET_LATE_IFACE(SDKTOOLS, dhooks::globals::sdktools); + } + + virtual bool QueryInterfaceDrop(SourceMod::SMInterface* interface) override { + if (interface == dhooks::globals::sdktools) { + dhooks::globals::sdktools = nullptr; + return false; + } + + return SDKExtension::QueryInterfaceDrop(interface); + } +}; + +ExtensionBridge extension; +SMEXT_LINK(&extension); \ No newline at end of file diff --git a/extensions/dhooks/src/natives.cpp b/extensions/dhooks/src/natives.cpp new file mode 100644 index 0000000000..75317e125f --- /dev/null +++ b/extensions/dhooks/src/natives.cpp @@ -0,0 +1,16 @@ +#include "natives.hpp" +#include "natives/dhookparam.hpp" +#include "natives/dhookreturn.hpp" +#include "natives/dhooksetup.hpp" +#include "natives/dynamicdetour.hpp" +#include "natives/dynamichook.hpp" + +namespace dhooks::natives { +void init(std::vector& natives) { + dhookparam::init(natives); + dhookreturn::init(natives); + dhooksetup::init(natives); + dynamicdetour::init(natives); + dynamichook::init(natives); +} +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives.hpp b/extensions/dhooks/src/natives.hpp new file mode 100644 index 0000000000..7d9ea0cce6 --- /dev/null +++ b/extensions/dhooks/src/natives.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhookparam.cpp b/extensions/dhooks/src/natives/dhookparam.cpp new file mode 100644 index 0000000000..40c9c2e2f1 --- /dev/null +++ b/extensions/dhooks/src/natives/dhookparam.cpp @@ -0,0 +1,550 @@ +#include "../globals.hpp" +#include "../sdk_types.hpp" +#include "../handle.hpp" +#include "../capsule.hpp" + +namespace dhooks::natives::dhookparam { + +static void FreeChangedVector(void* data) { + delete (sdk::Vector*)data; +} + +static void FreeChangedCharPtr(void* data) { + delete[] (const char*)data; +} + +inline handle::ParamReturn* Get(SourcePawn::IPluginContext* context, const cell_t param) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + SourceMod::Handle_t hndl = static_cast(param); + handle::ParamReturn* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::ParamReturn::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + context->ThrowNativeError("Invalid Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr)); + return nullptr; + } + return obj; +} + +inline cell_t GetParam(SourcePawn::IPluginContext* context, handle::ParamReturn* obj, const cell_t param) { + int index = param - 1; + if (obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) { + // Skip the |this| ptr parameter + index += 1; + } + + if (param <= 0 || index >= obj->GetCapsule()->GetParameters().size()) { + context->ThrowNativeError("Invalid param number %i max params is %i", param, obj->GetCapsule()->GetParameters().size() - ((obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) ? 1 : 0)); + return -1; + } + return index; +} + +cell_t DHookParam_GetParam(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + if (params[2] == 0) { + return obj->GetCapsule()->GetParameters().size(); + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get(index) == nullptr) { + return context->ThrowNativeError("Trying to get value for null pointer."); + } + + switch(var.dhook_type) { + case sp::HookParamType_Int: + return *obj->Get(index); + case sp::HookParamType_Bool: + return (*obj->Get(index)) ? 1 : 0; + case sp::HookParamType_CBaseEntity: + return globals::gamehelpers->EntityToBCompatRef(*obj->Get(index)); + case sp::HookParamType_Edict: + return globals::gamehelpers->IndexOfEdict(*obj->Get(index)); + case sp::HookParamType_Float: + return sp_ftoc(*obj->Get(index)); + default: + return context->ThrowNativeError("Invalid param type (%i) to get", var.dhook_type); + } +} + +cell_t DHookParam_SetParam(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + switch (var.dhook_type) { + case sp::HookParamType_Int: + *obj->Get(index) = params[3]; + break; + case sp::HookParamType_Bool: + *obj->Get(index) = (params[3] ? true : false); + break; + case sp::HookParamType_CBaseEntity: { + CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[3]); + + if (params[3] != -1 && entity == nullptr) { + return context->ThrowNativeError("Invalid entity reference passed for param value"); + } + + *obj->Get(index) = entity; + break; + } + case sp::HookParamType_Edict: { + sdk::edict_t* edict = reinterpret_cast(globals::gamehelpers->EdictOfIndex(params[3])); + + if (params[3] != -1 && (edict == nullptr || edict->IsFree())) { + return context->ThrowNativeError("Invalid edict index passed for param value"); + } + + *obj->Get(index) = edict; + break; + } + case sp::HookParamType_Float: + *obj->Get(index) = sp_ctof(params[3]); + break; + default: + return context->ThrowNativeError("Invalid param type (%i) to set", var.dhook_type); + } + return 0; +} + +cell_t DHookParam_GetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type == sp::HookParamType_VectorPtr) { + cell_t* buffer; + context->LocalToPhysAddr(params[3], &buffer); + + auto vec = *obj->Get(index); + if (vec == nullptr) { + return context->ThrowNativeError("Trying to get value for null pointer."); + } + buffer[0] = sp_ftoc(vec->x); + buffer[1] = sp_ftoc(vec->y); + buffer[2] = sp_ftoc(vec->z); + } else { + return context->ThrowNativeError("Invalid param type to get. Param is not a vector."); + } + return 0; +} + +cell_t DHookParam_SetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type == sp::HookParamType_VectorPtr) { + cell_t* buffer; + context->LocalToPhysAddr(params[3], &buffer); + + auto vec = *obj->Get(index); + if (vec == nullptr) { + vec = new sdk::Vector; + globals::sourcemod->AddFrameAction(FreeChangedVector, vec); + *obj->Get(index) = vec; + } + + vec->x = sp_ctof(buffer[0]); + vec->y = sp_ctof(buffer[1]); + vec->z = sp_ctof(buffer[2]); + } else { + return context->ThrowNativeError("Invalid param type to set. Param is not a vector."); + } + return 0; +} + +cell_t DHookParam_GetParamString(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get(index) == nullptr) { + return context->ThrowNativeError("Trying to get value for null pointer."); + } + + switch (var.dhook_type) { + case sp::HookParamType_CharPtr: { + auto str = *obj->Get(index); + context->StringToLocal(params[3], params[4], str); + break; + } + case sp::HookParamType_String: { + auto str = *obj->Get(index); + context->StringToLocal(params[3], params[4], str.ToCStr()); + break; + } + case sp::HookParamType_StringPtr: { + auto str = *obj->Get(index); + context->StringToLocal(params[3], params[4], str->ToCStr()); + break; + } + default: + return context->ThrowNativeError("Invalid param type to get. Param is not a string."); + } + + return 0; +} + +cell_t DHookParam_SetParamString(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + char* value; + context->LocalToString(params[3], &value); + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type == sp::HookParamType_CharPtr) { + auto str = new char[strlen(value) + 1]; + strcpy(str, value); + *obj->Get(index) = str; + // Free it later (cheaply) after the function returned. + globals::sourcemod->AddFrameAction(FreeChangedCharPtr, str); + } else if (var.dhook_type == sp::HookParamType_String || var.dhook_type == sp::HookParamType_StringPtr) { + return context->ThrowNativeError("DHooks currently lacks support for setting string_t. Pull requests are welcome!"); + } else { + return context->ThrowNativeError("Invalid param type to set. Param is not a string."); + } + return 0; +} + +cell_t DHookParam_GetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) { + return context->ThrowNativeError("Invalid object value type %i", var.dhook_type); + } + + std::uint8_t* object = obj->Get(index); + if (var.dhook_type == sp::HookParamType_ObjectPtr) { + object = *(std::uint8_t**)object; + } + + switch((sp::ObjectValueType)params[4]) { + case sp::ObjectValueType_Int: + return *(int *)(object + params[3]); + case sp::ObjectValueType_Bool: + return (*(bool *)(object + params[3])) ? 1 : 0; + case sp::ObjectValueType_Ehandle: { + auto edict = reinterpret_cast(globals::gamehelpers->GetHandleEntity(*(CBaseHandle *)(object + params[3]))); + if (edict == nullptr || edict->IsFree()) { + return -1; + } + return globals::gamehelpers->IndexOfEdict(reinterpret_cast(edict)); + } + case sp::ObjectValueType_EhandlePtr: { + auto edict = reinterpret_cast(globals::gamehelpers->GetHandleEntity(**(CBaseHandle **)(object + params[3]))); + if (edict == nullptr || edict->IsFree()) { + return -1; + } + return globals::gamehelpers->IndexOfEdict(reinterpret_cast(edict)); + } + case sp::ObjectValueType_Float: + return sp_ftoc(*(float *)(object + params[3])); + // This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins + // Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't.... + case sp::ObjectValueType_CBaseEntityPtr: + return globals::gamehelpers->EntityToBCompatRef(*(CBaseEntity **)(object + params[3])); + case sp::ObjectValueType_IntPtr: + return **(int **)(object + params[3]); + case sp::ObjectValueType_BoolPtr: + return (**(bool **)(object + params[3])) ? 1 : 0; + case sp::ObjectValueType_FloatPtr: + return sp_ftoc(**(float **)(object + params[3])); + default: + return context->ThrowNativeError("Invalid Object value type"); + } +} + +cell_t DHookParam_SetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) { + return context->ThrowNativeError("Invalid object value type %i", var.dhook_type); + } + + std::uint8_t* object = obj->Get(index); + if (var.dhook_type == sp::HookParamType_ObjectPtr) { + object = *(std::uint8_t**)object; + } + + switch((sp::ObjectValueType)params[4]) { + case sp::ObjectValueType_Int: + *(int *)(object + params[3]) = params[5]; + break; + case sp::ObjectValueType_Bool: + *(bool *)(object + params[3]) = params[5] != 0; + break; + case sp::ObjectValueType_Ehandle: + globals::gamehelpers->SetHandleEntity(*(CBaseHandle *)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5])); + break; + case sp::ObjectValueType_EhandlePtr: + globals::gamehelpers->SetHandleEntity(**(CBaseHandle **)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5])); + break; + case sp::ObjectValueType_Float: + *(float *)(object + params[3]) = sp_ctof(params[5]); + break; + // This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins + // Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't.... + case sp::ObjectValueType_CBaseEntityPtr: { + CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[5]); + + if (params[5] != -1 && entity == nullptr) { + return context->ThrowNativeError("Invalid entity passed"); + } + + *(CBaseEntity **)(object + params[3]) = entity; + break; + } + case sp::ObjectValueType_IntPtr: + **(int **)(object + params[3]) = params[5]; + break; + case sp::ObjectValueType_BoolPtr: + **(int **)(object + params[3]) = params[5] != 0; + break; + case sp::ObjectValueType_FloatPtr: + **(float **)(object + params[3]) = sp_ctof(params[5]); + break; + default: + return context->ThrowNativeError("Invalid Object value type"); + } + return 0; +} + +cell_t DHookParam_GetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) { + return context->ThrowNativeError("Invalid object value type %i", var.dhook_type); + } + + std::uint8_t* object = obj->Get(index); + if (var.dhook_type == sp::HookParamType_ObjectPtr) { + object = *(std::uint8_t**)object; + } + + cell_t *buffer; + context->LocalToPhysAddr(params[5], &buffer); + + if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) { + sdk::Vector* vec = (sdk::Vector*)(object + params[3]); + + if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) { + vec = *(sdk::Vector**)vec; + if (vec == nullptr) { + return context->ThrowNativeError("Trying to get value for null pointer."); + } + } + + buffer[0] = sp_ftoc(vec->x); + buffer[1] = sp_ftoc(vec->y); + buffer[2] = sp_ftoc(vec->z); + return 1; + } + + return context->ThrowNativeError("Invalid Object value type (not a type of vector)"); +} + +cell_t DHookParam_SetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) { + return context->ThrowNativeError("Invalid object value type %i", var.dhook_type); + } + + std::uint8_t* object = obj->Get(index); + if (var.dhook_type == sp::HookParamType_ObjectPtr) { + object = *(std::uint8_t**)object; + } + + cell_t *buffer; + context->LocalToPhysAddr(params[5], &buffer); + + if((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) { + sdk::Vector* vec = (sdk::Vector*)(object + params[3]); + + if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) { + vec = *(sdk::Vector**)vec; + if (vec == nullptr) { + return context->ThrowNativeError("Trying to set value for null pointer."); + } + } + + vec->x = sp_ctof(buffer[0]); + vec->y = sp_ctof(buffer[1]); + vec->z = sp_ctof(buffer[2]); + return 0; + } + return context->ThrowNativeError("Invalid Object value type (not a type of vector)"); +} + +cell_t DHookParam_GetParamObjectPtrString(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) { + return context->ThrowNativeError("Invalid object value type %i", var.dhook_type); + } + + std::uint8_t* object = obj->Get(index); + if (var.dhook_type == sp::HookParamType_ObjectPtr) { + object = *(std::uint8_t**)object; + } + + + switch((sp::ObjectValueType)params[4]) { + case sp::ObjectValueType_CharPtr: { + char *ptr = *(char **)(object + params[3]); + context->StringToLocal(params[5], params[6], ptr == NULL ? "" : (const char *)ptr); + break; + } + case sp::ObjectValueType_String: { + auto str = *(sdk::string_t *)(object + params[3]); + context->StringToLocal(params[5], params[6], str.ToCStr()); + break; + } + default: + return context->ThrowNativeError("Invalid Object value type (not a type of string)"); + } + return 0; +} + +cell_t DHookParam_IsNullParam(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + int index = GetParam(context, obj, params[2]); + if (index == -1) { + return 0; + } + + const auto& var = obj->GetCapsule()->GetParameters()[index]; + if (sp::HookParamTypeIsPtr(var.dhook_type)) { + return (*obj->Get(index) != nullptr) ? 1 : 0; + } + return context->ThrowNativeError("Param is not a pointer!"); +} + +void init(std::vector& natives) { + sp_nativeinfo_t list[] = { + {"DHookGetParam", DHookParam_GetParam}, + {"DHookSetParam", DHookParam_SetParam}, + {"DHookGetParamVector", DHookParam_GetParamVector}, + {"DHookSetParamVector", DHookParam_SetParamVector}, + {"DHookGetParamString", DHookParam_GetParamString}, + {"DHookSetParamString", DHookParam_SetParamString}, + {"DHookGetParamObjectPtrVar", DHookParam_GetParamObjectPtrVar}, + {"DHookSetParamObjectPtrVar", DHookParam_SetParamObjectPtrVar}, + {"DHookGetParamObjectPtrVarVector", DHookParam_GetParamObjectPtrVarVector}, + {"DHookSetParamObjectPtrVarVector", DHookParam_SetParamObjectPtrVarVector}, + {"DHookGetParamObjectPtrString", DHookParam_GetParamObjectPtrString}, + {"DHookIsNullParam", DHookParam_IsNullParam}, + {"DHookParam.Get", DHookParam_GetParam}, + {"DHookParam.Set", DHookParam_SetParam}, + {"DHookParam.GetVector", DHookParam_GetParamVector}, + {"DHookParam.SetVector", DHookParam_SetParamVector}, + {"DHookParam.GetString", DHookParam_GetParamString}, + {"DHookParam.SetString", DHookParam_SetParamString}, + {"DHookParam.GetObjectVar", DHookParam_GetParamObjectPtrVar}, + {"DHookParam.SetObjectVar", DHookParam_SetParamObjectPtrVar}, + {"DHookParam.GetObjectVarVector", DHookParam_GetParamObjectPtrVarVector}, + {"DHookParam.SetObjectVarVector", DHookParam_SetParamObjectPtrVarVector}, + {"DHookParam.GetObjectVarString", DHookParam_GetParamObjectPtrString}, + {"DHookParam.IsNull", DHookParam_IsNullParam} + }; + natives.insert(natives.end(), std::begin(list), std::end(list)); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhookparam.hpp b/extensions/dhooks/src/natives/dhookparam.hpp new file mode 100644 index 0000000000..537726f812 --- /dev/null +++ b/extensions/dhooks/src/natives/dhookparam.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives::dhookparam { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhookreturn.cpp b/extensions/dhooks/src/natives/dhookreturn.cpp new file mode 100644 index 0000000000..c86ffe830d --- /dev/null +++ b/extensions/dhooks/src/natives/dhookreturn.cpp @@ -0,0 +1,211 @@ +#include "../globals.hpp" +#include "../sdk_types.hpp" +#include "../handle.hpp" +#include "../capsule.hpp" + +namespace dhooks::natives::dhookreturn { + +static void FreeChangedVector(void* data) { + delete (sdk::Vector*)data; +} + +static void FreeChangedCharPtr(void* data) { + delete[] (const char*)data; +} + +inline handle::ParamReturn* Get(SourcePawn::IPluginContext* context, const cell_t param) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + SourceMod::Handle_t hndl = static_cast(param); + handle::ParamReturn* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::ParamReturn::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + context->ThrowNativeError("Invalid Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr)); + return nullptr; + } + return obj; +} + +cell_t DHookReturn_GetReturn(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + const auto& ret = obj->GetCapsule()->GetReturn(); + switch (ret.dhook_type) { + case sp::ReturnType_Int: + return *obj->GetReturn(); + case sp::ReturnType_Bool: + return (*obj->GetReturn()) ? 1 : 0; + case sp::ReturnType_CBaseEntity: + return globals::gamehelpers->EntityToBCompatRef(*obj->GetReturn()); + case sp::ReturnType_Edict: + return globals::gamehelpers->IndexOfEdict(*obj->GetReturn()); + case sp::ReturnType_Float: + return sp_ftoc(*obj->GetReturn()); + default: + return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type); + } + return 0; +} + +cell_t DHookReturn_SetReturn(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + const auto& ret = obj->GetCapsule()->GetReturn(); + switch (ret.dhook_type) { + case sp::ReturnType_Int: + *obj->GetReturn() = params[2]; + break; + case sp::ReturnType_Bool: + *obj->GetReturn() = params[2] != 0; + break; + case sp::ReturnType_CBaseEntity: { + CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[2]); + if (entity == nullptr) { + return context->ThrowNativeError("Invalid entity index passed for return value"); + } + *obj->GetReturn() = entity; + break; + } + case sp::ReturnType_Edict: { + sdk::edict_t* edict = reinterpret_cast(globals::gamehelpers->EdictOfIndex(params[2])); + if (edict == nullptr || edict->IsFree()) { + return context->ThrowNativeError("Invalid entity index passed for return value"); + } + *obj->GetReturn() = edict; + break; + } + case sp::ReturnType_Float: + *obj->GetReturn() = sp_ctof(params[2]); + break; + default: + return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type); + } + return 0; +} + +cell_t DHookReturn_GetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + cell_t *buffer; + context->LocalToPhysAddr(params[2], &buffer); + + const auto& ret = obj->GetCapsule()->GetReturn(); + + sdk::Vector* vector = nullptr; + if (ret.dhook_type == sp::ReturnType_Vector) { + vector = obj->GetReturn(); + } else if(ret.dhook_type == sp::ReturnType_VectorPtr) { + auto pvector = obj->GetReturn(); + if (*pvector == nullptr) { + return context->ThrowNativeError("Vector pointer is null"); + } + vector = *pvector; + } else { + return context->ThrowNativeError("Return type is not a vector type"); + } + buffer[0] = sp_ftoc(vector->x); + buffer[1] = sp_ftoc(vector->y); + buffer[2] = sp_ftoc(vector->z); + return 0; +} + +cell_t DHookReturn_SetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + cell_t *buffer; + context->LocalToPhysAddr(params[2], &buffer); + const auto& ret = obj->GetCapsule()->GetReturn(); + + if (ret.dhook_type == sp::ReturnType_Vector) { + *(obj->GetReturn()) = sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); + } + else if (ret.dhook_type == sp::ReturnType_VectorPtr) { + // Lazily free the vector a frame later + auto vector = new sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); + *(obj->GetReturn()) = vector; + globals::sourcemod->AddFrameAction(FreeChangedVector, vector); + } else { + return context->ThrowNativeError("Return type is not a vector type"); + } + return 0; +} + +cell_t DHookReturn_GetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + const auto& ret = obj->GetCapsule()->GetReturn(); + switch (ret.dhook_type) { + case sp::ReturnType_String: + context->StringToLocal(params[2], params[3], obj->GetReturn()->ToCStr()); + return 1; + case sp::ReturnType_StringPtr: + context->StringToLocal(params[2], params[3], (obj->GetReturn() != nullptr) ? (*obj->GetReturn())->ToCStr() : ""); + return 1; + case sp::ReturnType_CharPtr: + context->StringToLocal(params[2], params[3], (*(obj->GetReturn()) == nullptr) ? "" : *(obj->GetReturn())); + return 1; + default: + return context->ThrowNativeError("Invalid param type to get. Param is not a string."); + } +} + +cell_t DHookReturn_SetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) { + auto obj = Get(context, params[1]); + if (obj == nullptr) { + return 0; + } + + const auto& ret = obj->GetCapsule()->GetReturn(); + + char *value; + context->LocalToString(params[2], &value); + + switch (ret.dhook_type) { + case sp::ReturnType_CharPtr: { + auto new_str = new char[strlen(value) + 1]; + strcpy(new_str, value); + *(obj->GetReturn()) = new_str; + // Free it later (cheaply) after the function returned. + globals::sourcemod->AddFrameAction(FreeChangedCharPtr, new_str); + return 1; + } + default: + return context->ThrowNativeError("Invalid param type to get. Param is not a char pointer."); + } +} + +void init(std::vector& natives) { + sp_nativeinfo_t list[] = { + {"DHookGetReturn", DHookReturn_GetReturn}, + {"DHookSetReturn", DHookReturn_SetReturn}, + {"DHookGetReturnVector", DHookReturn_GetReturnVector}, + {"DHookSetReturnVector", DHookReturn_SetReturnVector}, + {"DHookGetReturnString", DHookReturn_GetReturnString}, + {"DHookSetReturnString", DHookReturn_SetReturnString}, + {"DHookReturn.Value.get", DHookReturn_GetReturn}, + {"DHookReturn.Value.set", DHookReturn_SetReturn}, + {"DHookReturn.GetVector", DHookReturn_GetReturnVector}, + {"DHookReturn.SetVector", DHookReturn_SetReturnVector}, + {"DHookReturn.GetString", DHookReturn_GetReturnString}, + {"DHookReturn.SetString", DHookReturn_SetReturnString} + }; + natives.insert(natives.end(), std::begin(list), std::end(list)); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhookreturn.hpp b/extensions/dhooks/src/natives/dhookreturn.hpp new file mode 100644 index 0000000000..8eba3d1491 --- /dev/null +++ b/extensions/dhooks/src/natives/dhookreturn.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives::dhookreturn { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhooksetup.cpp b/extensions/dhooks/src/natives/dhooksetup.cpp new file mode 100644 index 0000000000..3d14736acd --- /dev/null +++ b/extensions/dhooks/src/natives/dhooksetup.cpp @@ -0,0 +1,225 @@ +#include "../handle.hpp" +#include "../globals.hpp" +#include "../sp_inc.hpp" +#include "../signatures.hpp" + +namespace dhooks::natives::dhooksetup { + +inline handle::HookSetup* Get(SourcePawn::IPluginContext* context, const cell_t param) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + SourceMod::Handle_t hndl = static_cast(param); + handle::HookSetup* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::HookSetup::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + context->ThrowNativeError("Invalid Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr)); + return nullptr; + } + return obj; +} + +cell_t DHookSetup_AddParam(SourcePawn::IPluginContext* context, const cell_t* params) { + auto setup = Get(context, params[1]); + if (setup == nullptr) { + return 0; + } + + if (setup->IsImmutable()) { + return context->ThrowNativeError("This setup handle can no longer be modified."); + } + + sp::HookParamType type = static_cast(params[2]); + if (type == sp::HookParamType_Object) { + return context->ThrowNativeError("HookParamType_Object is currently unsupported."); + } + if (type == sp::HookParamType_Unknown) { + return context->ThrowNativeError("HookParamType_Unknown isn't a valid param type."); + } + + sp::DHookPassFlag flags = sp::DHookPass_ByVal; + if (params[0] >= 4) { + flags = static_cast(params[4]); + } + + sp::DHookRegister param_register = sp::DHookRegister_Default; + if (params[0] >= 5) { + param_register = static_cast(params[5]); + } + + std::size_t size = sp::GetParamTypeSize(type).value_or(0); + if (params[0] >= 3 && params[3] != -1) { + size = params[3]; + } + + if (size == 0) { + return context->ThrowNativeError("Param type size cannot be 0 bytes."); + } + + Variable var; + var.dhook_custom_register = param_register; + var.dhook_pass_flags = flags; + var.dhook_size = size; + var.dhook_type = type; + + setup->AddParam(var); + return 0; +} + +cell_t DHookSetup_SetFromConf(SourcePawn::IPluginContext* context, const cell_t* params) { + auto setup = Get(context, params[1]); + if (setup == nullptr) { + return 0; + } + + if (setup->IsImmutable()) { + return context->ThrowNativeError("This setup handle can no longer be modified."); + } + + SourceMod::IGameConfig* conf = nullptr; + SourceMod::HandleError chnderr = SourceMod::HandleError_None; + if ((conf = globals::gameconfs->ReadHandle(params[2], context->GetIdentity(), &chnderr)) == nullptr || chnderr != SourceMod::HandleError_None) { + return context->ThrowNativeError("Invalid GameData handle %x (error %i: %s)", params[2], chnderr, globals::HandleErrorToString(chnderr)); + } + + sp::SDKFuncConfSource source = static_cast(params[3]); + + char* key; + context->LocalToString(params[4], &key); + + // Only change offset if HookSetup is a virtual hook + auto virtual_setup = dynamic_cast(setup); + if (virtual_setup) { + int offset = 0; + if (source == sp::SDKConf_Virtual && conf->GetOffset(key, &offset)) { + virtual_setup->SetOffset(offset); + return 0; + } + return context->ThrowNativeError("Invalid SDKFuncConfSource: %d", source); + } + + // Only change address if HookSetup is an address hook + auto detour_setup = dynamic_cast(setup); + if (detour_setup) { + void* addr = nullptr; + if (source == sp::SDKConf_Signature && conf->GetMemSig(key, &addr)) { + detour_setup->SetAddress(addr); + return 0; + } + if (source == sp::SDKConf_Address && conf->GetAddress(key, &addr)) { + detour_setup->SetAddress(addr); + return 0; + } + return context->ThrowNativeError("Invalid SDKFuncConfSource: %d", source); + } + + return context->ThrowNativeError("Unknown HookSetup type."); +} + +enum class DHookCreateFromConf { + ANY, + VIRTUAL, + ADDRESS +}; + +cell_t DHookCreateFromConf_Ex(SourcePawn::IPluginContext* context, const cell_t* params, DHookCreateFromConf hook_type) { + SourceMod::IGameConfig* conf = nullptr; + SourceMod::HandleError chnderr = SourceMod::HandleError_None; + if ((conf = globals::gameconfs->ReadHandle(params[1], context->GetIdentity(), &chnderr)) == nullptr || chnderr != SourceMod::HandleError_None) { + return context->ThrowNativeError("Invalid GameData handle %x (error %i: %s)", params[1], chnderr, globals::HandleErrorToString(chnderr)); + } + + char* function; + context->LocalToString(params[2], &function); + + SignatureWrapper* sig = globals::dhooks_config.GetFunctionSignature(function); + if (!sig) { + return context->ThrowNativeError("Hook definition \"%s\" was not found.", function); + } + + // Validate the params + for (const auto& arg: sig->args) { + if (arg.info.type == sp::HookParamType_Unknown) { + return context->ThrowNativeError("Undefined type for parameter \"%s\".", arg.name.c_str()); + } + if (arg.info.size == 0) { + return context->ThrowNativeError("Undefined size for parameter \"%s\".", arg.name.c_str()); + } + if (arg.info.flags != sp::DHookPass_ByVal) { + return context->ThrowNativeError("Parameters can only be passed byval in this version."); + } + } + + if (sig->ret.type == sp::ReturnType_Unknown) { + return context->ThrowNativeError("Return type cannot be unknown."); + } + + if (sig->ret.type != sp::ReturnType_Void && sig->ret.size == 0) { + return context->ThrowNativeError("Return type cannot have a size 0 bytes."); + } + + if (sig->ret.flags != sp::DHookPass_ByVal) { + return context->ThrowNativeError("Return type can only be passed byval in this version."); + } + + // Setup a virtual hook + if (hook_type == DHookCreateFromConf::ANY || hook_type == DHookCreateFromConf::VIRTUAL) { + int offset = 0; + if (conf->GetOffset(sig->offset.c_str(), &offset)) { + auto setup = new handle::DynamicHook(context->GetIdentity(), sig->thisType, offset, sig->hookType, sig->args, sig->ret, nullptr); + auto hndl = setup->GetHandle(); + if (hndl == BAD_HANDLE) { + delete setup; + } + return hndl; + } + if (hook_type == DHookCreateFromConf::VIRTUAL) { + return context->ThrowNativeError("Failed to retrieve offset \"%s\" for hook.", sig->offset.c_str()); + } + } + + if (hook_type == DHookCreateFromConf::ANY || hook_type == DHookCreateFromConf::ADDRESS) { + void* addr = nullptr; + if (conf->GetAddress(sig->address.c_str(), &addr) || conf->GetMemSig(sig->signature.c_str(), &addr)) { + auto setup = new handle::DynamicDetour(context->GetIdentity(), sig->thisType, sig->callConv, addr, sig->args, sig->ret); + auto hndl = setup->GetHandle(); + if (hndl == BAD_HANDLE) { + delete setup; + } + return hndl; + } + if (hook_type == DHookCreateFromConf::ADDRESS) { + return context->ThrowNativeError("Failed to retrieve signature \"%s\" for hook.", sig->offset.c_str()); + } + } + + return context->ThrowNativeError("Failed to create hook"); +} + +cell_t DHookCreateFromConf(SourcePawn::IPluginContext* context, const cell_t* params) { + return DHookCreateFromConf_Ex(context, params, DHookCreateFromConf::ANY); +} + +cell_t DynamicHook_FromConf(SourcePawn::IPluginContext* context, const cell_t* params) { + return DHookCreateFromConf_Ex(context, params, DHookCreateFromConf::VIRTUAL); +} + +cell_t DynamicDetour_FromConf(SourcePawn::IPluginContext* context, const cell_t* params) { + return DHookCreateFromConf_Ex(context, params, DHookCreateFromConf::ADDRESS); +} + +void init(std::vector& natives) { + sp_nativeinfo_t list[] = { + {"DHookSetFromConf", DHookSetup_SetFromConf}, + {"DHookAddParam", DHookSetup_AddParam}, + {"DHookCreateFromConf", DHookCreateFromConf}, + {"DHookSetup.AddParam", DHookSetup_AddParam}, + {"DHookSetup.SetFromConf", DHookSetup_SetFromConf}, + + {"DynamicHook.FromConf", DynamicHook_FromConf}, + {"DynamicDetour.FromConf", DynamicDetour_FromConf}, + }; + natives.insert(natives.end(), std::begin(list), std::end(list)); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dhooksetup.hpp b/extensions/dhooks/src/natives/dhooksetup.hpp new file mode 100644 index 0000000000..9c176e5866 --- /dev/null +++ b/extensions/dhooks/src/natives/dhooksetup.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives::dhooksetup { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dynamicdetour.cpp b/extensions/dhooks/src/natives/dynamicdetour.cpp new file mode 100644 index 0000000000..0c6e9de543 --- /dev/null +++ b/extensions/dhooks/src/natives/dynamicdetour.cpp @@ -0,0 +1,84 @@ +#include "../handle.hpp" +#include "../globals.hpp" +#include "../capsule.hpp" + +namespace dhooks::natives::dynamicdetour { + +inline handle::DynamicDetour* Get(SourcePawn::IPluginContext* context, const cell_t param) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + SourceMod::Handle_t hndl = static_cast(param); + handle::DynamicDetour* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::DynamicDetour::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + context->ThrowNativeError("Invalid DynamicDetour Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr)); + return nullptr; + } + return obj; +} + +cell_t DynamicDetour_DynamicDetour(SourcePawn::IPluginContext* context, const cell_t* params) { + auto addr = globals::cell_to_ptr(context, params[1]); + auto callconv = static_cast(params[2]); + auto returntype = static_cast(params[3]); + auto thisptrtype = static_cast(params[4]); + + ReturnInfo info; + info.custom_register = sp::DHookRegister_Default; + info.flags = sp::DHookPass_ByVal; + info.type = returntype; + info.size = sp::GetReturnTypeSize(returntype).value_or(0); + if (info.size == 0 && returntype != sp::ReturnType_Void) { + return context->ThrowNativeError("Return type size cannot be 0 bytes"); + } + + auto hndl = new handle::DynamicDetour(context->GetIdentity(), thisptrtype, callconv, addr, {}, info); + return hndl->GetHandle(); +} + +cell_t DynamicDetour_Enable(SourcePawn::IPluginContext* context, const cell_t* params) { + auto setup = Get(context, params[1]); + if (setup == nullptr) { + return 0; + } + + SourcePawn::IPluginFunction* callback = context->GetFunctionById(params[3]); + if (!callback) { + return context->ThrowNativeError("Failed to retrieve function by id"); + } + + auto mode = static_cast(params[2]); + + // As soon as a detour is enabled, it becomes immutable + setup->SetImmutable(); + return setup->Enable(callback, mode); +} + +cell_t DynamicDetour_Disable(SourcePawn::IPluginContext* context, const cell_t* params) { + auto setup = Get(context, params[1]); + if (setup == nullptr) { + return 0; + } + + SourcePawn::IPluginFunction* callback = context->GetFunctionById(params[3]); + if (!callback) { + return context->ThrowNativeError("Failed to retrieve function by id"); + } + + auto mode = static_cast(params[2]); + return setup->Disable(callback, mode); +} + +void init(std::vector& natives) { + sp_nativeinfo_t list[] = { + {"DHookCreateDetour", DynamicDetour_DynamicDetour}, + {"DynamicDetour.DynamicDetour", DynamicDetour_DynamicDetour}, + /* DynamicDetour.FromConf is implemented in dhooksetup.cpp */ + {"DynamicDetour.Enable", DynamicDetour_Enable}, + {"DynamicDetour.Disable", DynamicDetour_Disable}, + }; + natives.insert(natives.end(), std::begin(list), std::end(list)); +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dynamicdetour.hpp b/extensions/dhooks/src/natives/dynamicdetour.hpp new file mode 100644 index 0000000000..e06254538f --- /dev/null +++ b/extensions/dhooks/src/natives/dynamicdetour.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives::dynamicdetour { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dynamichook.cpp b/extensions/dhooks/src/natives/dynamichook.cpp new file mode 100644 index 0000000000..7dd14e6264 --- /dev/null +++ b/extensions/dhooks/src/natives/dynamichook.cpp @@ -0,0 +1,278 @@ +#include "../natives.hpp" +#include "../handle.hpp" +#include "../globals.hpp" +#include "dynamicdetour.hpp" + +namespace dhooks::natives::dynamichook { + +inline handle::DynamicHook* Get(SourcePawn::IPluginContext* context, const cell_t param) { + SourceMod::HandleSecurity security; + security.pOwner = globals::myself->GetIdentity(); + security.pIdentity = globals::myself->GetIdentity(); + SourceMod::Handle_t hndl = static_cast(param); + handle::DynamicHook* obj = nullptr; + SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::DynamicHook::HANDLE_TYPE, &security, (void **)&obj); + if (chnderr != SourceMod::HandleError_None) { + context->ThrowNativeError("Invalid DynamicHook Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr)); + return nullptr; + } + return obj; +} + +cell_t DynamicHook_DynamicHook(SourcePawn::IPluginContext* context, const cell_t* params) { + auto offset = params[1]; + auto type = static_cast(params[2]); + auto returntype = static_cast(params[3]); + auto thisptrtype = static_cast(params[4]); + + ReturnInfo ret_info; + ret_info.custom_register = sp::DHookRegister_Default; + ret_info.flags = sp::DHookPass_ByVal; + ret_info.type = returntype; + ret_info.size = sp::GetReturnTypeSize(returntype).value_or(0); + if (ret_info.size == 0 && returntype != sp::ReturnType_Void) { + return context->ThrowNativeError("Return type size cannot be 0 bytes"); + } + + auto hndl = new handle::DynamicHook(context->GetIdentity(), thisptrtype, offset, type, {}, ret_info, nullptr); + return hndl->GetHandle(); +} + +cell_t DynamicHook_Create(SourcePawn::IPluginContext* context, const cell_t* params) { + auto offset = params[1]; + auto type = static_cast(params[2]); + auto returntype = static_cast(params[3]); + auto thisptrtype = static_cast(params[4]); + auto callback = context->GetFunctionById(params[5]); + + ReturnInfo ret_info; + ret_info.custom_register = sp::DHookRegister_Default; + ret_info.flags = sp::DHookPass_ByVal; + ret_info.type = returntype; + ret_info.size = sp::GetReturnTypeSize(returntype).value_or(0); + if (ret_info.size == 0 && returntype != sp::ReturnType_Void) { + return context->ThrowNativeError("Return type size cannot be 0 bytes"); + } + + auto hndl = new handle::DynamicHook(context->GetIdentity(), thisptrtype, offset, type, {}, ret_info, callback); + return hndl->GetHandle(); +} + +cell_t DynamicHook_HookEntity(SourcePawn::IPluginContext* context, const cell_t* params) { + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_Entity) { + return context->ThrowNativeError("DynamicHook isn't an entity hook!"); + } + + auto mode = static_cast(params[2]); + + auto entity = globals::gamehelpers->ReferenceToEntity(params[3]); + if (entity == nullptr) { + return context->ThrowNativeError("Invalid entity index/reference %d!", params[3]); + } + + auto callback = context->GetFunctionById(params[4]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + if (callback == nullptr) { + return context->ThrowNativeError("A callback must be provided to the hook!"); + } + + auto removal_callback = context->GetFunctionById(params[5]); + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, removal_callback, mode, entity); +} + +cell_t DynamicHook_DHookEntity(SourcePawn::IPluginContext* context, const cell_t* params) { + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_Entity) { + return context->ThrowNativeError("DynamicHook isn't an entity hook!"); + } + + bool post = (params[2] == 0) ? false : true; + + auto entity = globals::gamehelpers->ReferenceToEntity(params[3]); + if (entity == nullptr) { + return context->ThrowNativeError("Invalid entity index/reference %d!", params[3]); + } + + auto removal_callback = context->GetFunctionById(params[4]); + + auto callback = context->GetFunctionById(params[5]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + if (callback == nullptr) { + return context->ThrowNativeError("A callback must be provided to the hook!"); + } + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, removal_callback, (post) ? sp::HookMode::Hook_Post : sp::HookMode::Hook_Pre, entity); +} + +cell_t DynamicHook_HookGamerules(SourcePawn::IPluginContext* context, const cell_t* params) { + if (dhooks::globals::sdktools == nullptr) { + return context->ThrowNativeError("SDKTools is not loaded!"); + } + + auto gamerules = dhooks::globals::sdktools->GetGameRules(); + if (gamerules == nullptr) { + return context->ThrowNativeError("Failed to retrieve GameRules with SDKTools!"); + } + + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_GameRules) { + return context->ThrowNativeError("DynamicHook isn't a gamerules hook!"); + } + + auto mode = static_cast(params[2]); + + auto callback = context->GetFunctionById(params[3]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + if (callback == nullptr) { + return context->ThrowNativeError("A callback must be provided to the hook!"); + } + + auto removal_callback = context->GetFunctionById(params[4]); + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, removal_callback, mode, gamerules); +} + +cell_t DynamicHook_DHookGamerules(SourcePawn::IPluginContext* context, const cell_t* params) { + if (dhooks::globals::sdktools == nullptr) { + return context->ThrowNativeError("SDKTools is not loaded!"); + } + + auto gamerules = dhooks::globals::sdktools->GetGameRules(); + if (gamerules == nullptr) { + return context->ThrowNativeError("Failed to retrieve GameRules with SDKTools!"); + } + + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_GameRules) { + return context->ThrowNativeError("DynamicHook isn't a gamerules hook!"); + } + + auto post = (params[2] == 0) ? false : true; + + auto removal_callback = context->GetFunctionById(params[3]); + + auto callback = context->GetFunctionById(params[4]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + if (callback == nullptr) { + return context->ThrowNativeError("A callback must be provided to the hook!"); + } + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, removal_callback, (post) ? sp::HookMode::Hook_Post : sp::HookMode::Hook_Pre, gamerules); +} + +cell_t DynamicHook_HookRaw(SourcePawn::IPluginContext* context, const cell_t* params) { + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_Raw) { + return context->ThrowNativeError("DynamicHook isn't a raw hook!"); + } + + auto mode = static_cast(params[2]); + + auto addr = globals::cell_to_ptr(context, params[3]); + + auto callback = context->GetFunctionById(params[4]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, nullptr, mode, addr); +} + +cell_t DynamicHook_DHookRaw(SourcePawn::IPluginContext* context, const cell_t* params) { + auto dynhook = Get(context, params[1]); + if (dynhook == nullptr) { + return 0; + } + + if (dynhook->GetType() != sp::HookType::HookType_Raw) { + return context->ThrowNativeError("DynamicHook isn't a raw hook!"); + } + + auto post = (params[2] == 0) ? false : true; + + auto addr = globals::cell_to_ptr(context, params[3]); + + auto removal_callback = context->GetFunctionById(params[4]); + + auto callback = context->GetFunctionById(params[5]); + if (callback == nullptr) { + callback = dynhook->GetDefaultCallback(); + } + + if (callback == nullptr) { + return context->ThrowNativeError("A callback must be provided to the hook!"); + } + + dynhook->SetImmutable(); + return dynhook->AddHook(callback, removal_callback, (post) ? sp::HookMode::Hook_Post : sp::HookMode::Hook_Pre, addr); +} + +cell_t DynamicHook_RemoveHook(SourcePawn::IPluginContext* context, const cell_t* params) { + auto hndl = handle::DynamicHook::FindByHookID(params[1]); + if (hndl == BAD_HANDLE) { + return 0; + } + auto dynhook = Get(context, hndl); + if (dynhook == nullptr) { + return 0; + } + return (dynhook->RemoveHook(params[1])) ? 1 : 0; +} + +void init(std::vector& natives) { + sp_nativeinfo_t list[] = { + {"DynamicHook.DynamicHook", DynamicHook_DynamicHook}, + {"DynamicHook.HookEntity", DynamicHook_HookEntity}, + {"DynamicHook.HookGamerules", DynamicHook_HookGamerules}, + {"DynamicHook.HookRaw", DynamicHook_HookRaw}, + {"DynamicHook.RemoveHook", DynamicHook_RemoveHook}, + + {"DHookCreate", DynamicHook_Create}, + {"DHookEntity", DynamicHook_DHookEntity}, + {"DHookGamerules", DynamicHook_DHookGamerules}, + {"DHookRaw", DynamicHook_DHookRaw}, + {"DHookRemoveHookID", DynamicHook_RemoveHook} + }; + + natives.insert(natives.end(), std::begin(list), std::end(list)); +} +} \ No newline at end of file diff --git a/extensions/dhooks/src/natives/dynamichook.hpp b/extensions/dhooks/src/natives/dynamichook.hpp new file mode 100644 index 0000000000..ad14dd7f3d --- /dev/null +++ b/extensions/dhooks/src/natives/dynamichook.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace dhooks::natives::dynamichook { +void init(std::vector& natives); +} \ No newline at end of file diff --git a/extensions/dhooks/src/register.cpp b/extensions/dhooks/src/register.cpp new file mode 100644 index 0000000000..051609fe85 --- /dev/null +++ b/extensions/dhooks/src/register.cpp @@ -0,0 +1,97 @@ +#include "register.hpp" + +namespace dhooks { + +std::optional Translate_DHookRegister(sp::DHookRegister reg) { + switch (reg) { + case sp::DHookRegister_AL: + case sp::DHookRegister_AH: + case sp::DHookRegister_EAX: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RAX: + return KHook::Asm::rax; +#else + return KHook::Asm::eax; +#endif + case sp::DHookRegister_CL: + case sp::DHookRegister_CH: + case sp::DHookRegister_ECX: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RCX: + return KHook::Asm::rcx; +#else + return KHook::Asm::ecx; +#endif + case sp::DHookRegister_DL: + case sp::DHookRegister_DH: + case sp::DHookRegister_EDX: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RDX: + return KHook::Asm::rdx; +#else + return KHook::Asm::edx; +#endif + case sp::DHookRegister_BL: + case sp::DHookRegister_BH: + case sp::DHookRegister_EBX: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RBX: + return KHook::Asm::rbx; +#else + return KHook::Asm::ebx; +#endif + case sp::DHookRegister_ESP: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RSP: + return KHook::Asm::rsp; +#else + return KHook::Asm::esp; +#endif + case sp::DHookRegister_EBP: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RBP: + return KHook::Asm::rbp; +#else + return KHook::Asm::ebp; +#endif + case sp::DHookRegister_ESI: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RSI: + return KHook::Asm::rsi; +#else + return KHook::Asm::esi; +#endif + case sp::DHookRegister_EDI: +#ifdef DHOOKS_X86_64 + case sp::DHookRegister_RDI: + return KHook::Asm::rdi; +#else + return KHook::Asm::edi; +#endif + } + return {}; +} + +std::optional Translate_DHookRegister_Float(sp::DHookRegister reg) { + switch (reg) { + case sp::DHookRegister_XMM0: + return KHook::Asm::xmm0; + case sp::DHookRegister_XMM1: + return KHook::Asm::xmm1; + case sp::DHookRegister_XMM2: + return KHook::Asm::xmm2; + case sp::DHookRegister_XMM3: + return KHook::Asm::xmm3; + case sp::DHookRegister_XMM4: + return KHook::Asm::xmm4; + case sp::DHookRegister_XMM5: + return KHook::Asm::xmm5; + case sp::DHookRegister_XMM6: + return KHook::Asm::xmm6; + case sp::DHookRegister_XMM7: + return KHook::Asm::xmm7; + } + return {}; +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/register.hpp b/extensions/dhooks/src/register.hpp new file mode 100644 index 0000000000..2ec98a1edc --- /dev/null +++ b/extensions/dhooks/src/register.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "sp_inc.hpp" + +#include +#include + +#ifdef DHOOKS_X86_64 +#include +#else +#include +#endif + +namespace dhooks +{ + +#ifdef DHOOKS_X86_64 +const auto STACK_REG = KHook::Asm::rsp; +using AsmRegCode = KHook::Asm::x8664Reg; +using AsmReg = KHook::Asm::x86_64_Reg; +using AsmFloatRegCode = KHook::Asm::x8664FloatReg; +using AsmFloatReg = KHook::Asm::x86_64_FloatReg; +static constexpr const std::size_t MAX_GENERAL_REGISTERS = 16; +static constexpr const std::size_t MAX_FLOAT_REGISTERS = 16; +static_assert(KHook::Asm::RAX == 0); +#elif DHOOKS_X86 +const auto STACK_REG = KHook::Asm::esp; +using AsmRegCode = KHook::Asm::x86Reg; +using AsmReg = KHook::Asm::x86_Reg; +using AsmFloatRegCode = KHook::Asm::x86FloatReg; +using AsmFloatReg = KHook::Asm::x86_Float_Reg; +static constexpr const std::size_t MAX_GENERAL_REGISTERS = 8; +static constexpr const std::size_t MAX_FLOAT_REGISTERS = 8; +static_assert(KHook::Asm::EAX == 0); +#endif + +class GeneralRegister { +public: + operator float() { return (float)_value; } + operator bool() { return _value != 0; } +#if defined(DHOOKS_X86_64) /* || defined() */ + operator std::int64_t() { return (std::int64_t)_value; } + operator std::uint64_t() { return (std::uint64_t)_value; } +#endif + operator std::int32_t() { return (std::int32_t)_value; } + operator std::uint32_t() { return (std::uint32_t)_value; } + operator std::int16_t() { return (std::int16_t)_value; } + operator std::uint16_t() { return (std::uint16_t)_value; } + operator std::int8_t() { return (std::int8_t)_value; } + operator std::uint8_t() { return (std::int8_t)_value; } + + std::uintptr_t _value; +}; + +class FloatRegister { +public: + operator float() { return *(float*)&_value; } + operator double() { return *(double*)&_value; } +protected: + std::uint8_t _value[16]; +}; + +static_assert(sizeof(GeneralRegister) == sizeof(void*), "GeneralRegister class size isn't the size of a pointer!"); +static_assert(sizeof(FloatRegister) == 16, "FloatRegister class size isn't 128 bits!"); + +std::optional Translate_DHookRegister(sp::DHookRegister reg); +std::optional Translate_DHookRegister_Float(sp::DHookRegister reg); +} \ No newline at end of file diff --git a/extensions/dhooks/src/sdk_types.hpp b/extensions/dhooks/src/sdk_types.hpp new file mode 100644 index 0000000000..94a3966159 --- /dev/null +++ b/extensions/dhooks/src/sdk_types.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include + +namespace sdk { + +class CBaseEntity; + +static constexpr std::size_t FL_EDICT_FREE = (1<<1); +struct edict_t { +public: + bool IsFree() { return (m_fStateFlags & FL_EDICT_FREE) != 0; } +private: + int m_fStateFlags; +}; + +class Vector +{ +public: + Vector(float x1, float y1, float z1) + { + this->x = x1; + this->y = y1; + this->z = z1; + } + Vector(void) + { + this->x = 0.0; + this->y = 0.0; + this->z = 0.0; + } + float x; + float y; + float z; +}; + +static constexpr std::uintptr_t NULL_STRING = 0; +struct string_t +{ +public: + bool operator!() const { return ( pszValue == nullptr ); } + bool operator==( const string_t &rhs ) const { return ( pszValue == rhs.pszValue ); } + bool operator!=( const string_t &rhs ) const { return ( pszValue != rhs.pszValue ); } + bool operator<( const string_t &rhs ) const { return ((void *)pszValue < (void *)rhs.pszValue ); } + + const char *ToCStr() const { return ( pszValue ) ? pszValue : ""; } + +protected: + const char *pszValue; +}; +static_assert(sizeof(string_t) == sizeof(void*)); + +} \ No newline at end of file diff --git a/extensions/dhooks/src/signatures.cpp b/extensions/dhooks/src/signatures.cpp new file mode 100644 index 0000000000..e94d441813 --- /dev/null +++ b/extensions/dhooks/src/signatures.cpp @@ -0,0 +1,662 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Dynamic Hooks Extension + * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program 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 + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include "signatures.hpp" +#include "globals.hpp" + +namespace dhooks { + +SignatureGameConfig* dhooks_config = nullptr; +SignatureWrapper* g_CurrentSignature; + +enum class ParseState +{ + None, + Root, + Function, + Arguments, + Argument +}; + +ParseState g_ParseState; +unsigned int g_IgnoreLevel; +// The parent section type of a platform specific "windows" or "linux" section. +ParseState g_PlatformOnlyState; +std::string g_CurrentFunctionName; +ArgumentInfo g_CurrentArgumentInfo; + +SignatureWrapper* SignatureGameConfig::GetFunctionSignature(const char* function) +{ + auto sig = signatures_.find(function); + if (sig == signatures_.end()) + return nullptr; + + return (*sig).second; +} + +/** + * Game config "Functions" section parsing. + */ +SourceMod::SMCResult SignatureGameConfig::ReadSMC_NewSection(const SourceMod::SMCStates *states, const char *name) +{ + // We're ignoring the parent section. Ignore all child sections as well. + if (g_IgnoreLevel > 0) + { + g_IgnoreLevel++; + return SourceMod::SMCResult_Continue; + } + + // Handle platform specific sections first. +#ifdef DHOOKS_X86_64 +#if defined WIN32 + if (!strcmp(name, "windows64")) +#elif defined _LINUX + if (!strcmp(name, "linux64")) +#elif defined _OSX + if (!strcmp(name, "mac64")) +#endif +#else +#if defined WIN32 + if (!strcmp(name, "windows")) +#elif defined _LINUX + if (!strcmp(name, "linux")) +#elif defined _OSX + if (!strcmp(name, "mac")) +#endif +#endif + { + // We're already in a section for a different OS that we're ignoring. Can't have a section for our OS in here. + if (g_IgnoreLevel > 0) + { + globals::sourcemod->LogError(globals::myself, "Unreachable platform specific section in \"%s\" Function: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + // We don't support nested (useless) sections of the same OS like "windows" { "windows" { "foo" "bar" } } + if (g_PlatformOnlyState != ParseState::None) + { + globals::sourcemod->LogError(globals::myself, "Duplicate platform specific section for \"%s\". Already parsing only for that OS: line: %i col: %i", name, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + // This is a specific block for us. + g_PlatformOnlyState = g_ParseState; + return SourceMod::SMCResult_Continue; + } + else if (!strcmp(name, "windows") || !strcmp(name, "linux") || !strcmp(name, "mac") + || !strcmp(name, "windows64") || !strcmp(name, "linux64") || !strcmp(name, "mac64")) + { + if (g_PlatformOnlyState != ParseState::None) + { + globals::sourcemod->LogError(globals::myself, "Unreachable platform specific section in \"%s\" Function: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + // A specific block for a different platform. + g_IgnoreLevel++; + return SourceMod::SMCResult_Continue; + } + + switch (g_ParseState) { + case ParseState::Root: { + auto sig = signatures_.find(name); + if (sig != signatures_.end()) + g_CurrentSignature = (*sig).second; + else + g_CurrentSignature = new SignatureWrapper(); + g_CurrentFunctionName = name; + g_ParseState = ParseState::Function; + break; + } + + case ParseState::Function: { + if (!strcmp(name, "arguments")) + { + g_ParseState = ParseState::Arguments; + } + else + { + globals::sourcemod->LogError(globals::myself, "Unknown subsection \"%s\" (expected \"arguments\"): line: %i col: %i", name, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + break; + } + case ParseState::Arguments: { + g_ParseState = ParseState::Argument; + g_CurrentArgumentInfo.name = name; + + // Reset the parameter info. + ParamInfo info; + g_CurrentArgumentInfo.info = info; + + // See if we already have info about this argument. + for (auto &arg : g_CurrentSignature->args) { + if (!arg.name.compare(name)) { + // Continue changing that argument now. + g_CurrentArgumentInfo.info = arg.info; + break; + } + } + break; + } + default: { + globals::sourcemod->LogError(globals::myself, "Unknown subsection \"%s\": line: %i col: %i", name, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + + return SourceMod::SMCResult_Continue; +} + +SourceMod::SMCResult SignatureGameConfig::ReadSMC_KeyValue(const SourceMod::SMCStates* states, const char* key, const char* value) +{ + // We don't care for anything in this section or subsections. + if (g_IgnoreLevel > 0) + return SourceMod::SMCResult_Continue; + + switch (g_ParseState) + { + case ParseState::Function: { + if (!strcmp(key, "signature")) + { + if (g_CurrentSignature->address.length() > 0 || g_CurrentSignature->offset.length() > 0) + { + globals::sourcemod->LogError(globals::myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + g_CurrentSignature->signature = value; + } + else if (!strcmp(key, "address")) + { + if (g_CurrentSignature->signature.length() > 0 || g_CurrentSignature->offset.length() > 0) + { + globals::sourcemod->LogError(globals::myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + g_CurrentSignature->address = value; + } + else if (!strcmp(key, "offset")) + { + if (g_CurrentSignature->address.length() > 0 || g_CurrentSignature->signature.length() > 0) + { + globals::sourcemod->LogError(globals::myself, "Cannot have \"signature\", \"address\" or \"offset\" keys at the same time in one function: line: %i col: %i", states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + g_CurrentSignature->offset = value; + } + else if (!strcmp(key, "callconv")) + { + sp::CallingConvention callConv; + + if (!strcmp(value, "cdecl")) + callConv = sp::CallConv_CDECL; + else if (!strcmp(value, "thiscall")) + callConv = sp::CallConv_THISCALL; + else if (!strcmp(value, "stdcall")) + callConv = sp::CallConv_STDCALL; + else if (!strcmp(value, "fastcall")) + callConv = sp::CallConv_FASTCALL; + else + { + globals::sourcemod->LogError(globals::myself, "Invalid calling convention \"%s\": line: %i col: %i", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + g_CurrentSignature->callConv = callConv; + } + else if (!strcmp(key, "hooktype")) + { + sp::HookType hookType; + + if (!strcmp(value, "entity")) + hookType = sp::HookType_Entity; + else if (!strcmp(value, "gamerules")) + hookType = sp::HookType_GameRules; + else if (!strcmp(value, "raw")) + hookType = sp::HookType_Raw; + else + { + globals::sourcemod->LogError(globals::myself, "Invalid hook type \"%s\": line: %i col: %i", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + g_CurrentSignature->hookType = hookType; + } + else if (!strcmp(key, "return")) + { + g_CurrentSignature->ret.type = GetReturnTypeFromString(value); + + if (g_CurrentSignature->ret.type == sp::ReturnType_Unknown) + { + globals::sourcemod->LogError(globals::myself, "Invalid return type \"%s\": line: %i col: %i", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + g_CurrentSignature->ret.size = sp::GetReturnTypeSize(g_CurrentSignature->ret.type).value_or(0); + if (g_CurrentSignature->ret.size == 0 && g_CurrentSignature->ret.type != sp::ReturnType_Void) + { + globals::sourcemod->LogError(globals::myself, "Invalid return type \"%s\": its is 0 bytes", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + g_CurrentSignature->ret.flags = sp::DHookPass_ByVal; + } + else if (!strcmp(key, "this")) + { + if (!strcmp(value, "ignore")) + g_CurrentSignature->thisType = sp::ThisPointer_Ignore; + else if (!strcmp(value, "entity")) + g_CurrentSignature->thisType = sp::ThisPointer_CBaseEntity; + else if (!strcmp(value, "address")) + g_CurrentSignature->thisType = sp::ThisPointer_Address; + else + { + globals::sourcemod->LogError(globals::myself, "Invalid this type \"%s\": line: %i col: %i", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + else + { + globals::sourcemod->LogError(globals::myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + break; + } + case ParseState::Argument: { + if (!strcmp(key, "type")) + { + g_CurrentArgumentInfo.info.type = GetHookParamTypeFromString(value); + if (g_CurrentArgumentInfo.info.type == sp::HookParamType_Unknown || g_CurrentArgumentInfo.info.type == sp::HookParamType_Object) + { + globals::sourcemod->LogError(globals::myself, "Invalid argument type \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + else if (!strcmp(key, "size")) + { + g_CurrentArgumentInfo.info.size = static_cast(strtol(value, NULL, 0)); + + if (g_CurrentArgumentInfo.info.size < 1) + { + globals::sourcemod->LogError(globals::myself, "Invalid argument size \"%s\" for argument \"%s\": line: %i col: %i", value, g_CurrentArgumentInfo.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + else if (!strcmp(key, "flags")) + { + sp::DHookPassFlag flags = static_cast(0); + if (strstr(value, "byval")) + flags = static_cast(static_cast(flags)|sp::DHookPass_ByVal); + if (strstr(value, "byref")) + flags = static_cast(static_cast(flags)|sp::DHookPass_ByRef); + /* + if (strstr(value, "odtor")) + flags |= PASSFLAG_ODTOR; + if (strstr(value, "octor")) + flags |= PASSFLAG_OCTOR; + if (strstr(value, "oassignop")) + flags |= PASSFLAG_OASSIGNOP; + #ifdef PASSFLAG_OCOPYCTOR + if (strstr(value, "ocopyctor")) + flags |= PASSFLAG_OCOPYCTOR; + #endif + #ifdef PASSFLAG_OUNALIGN + if (strstr(value, "ounalign")) + flags |= PASSFLAG_OUNALIGN; + #endif + */ + g_CurrentArgumentInfo.info.flags = flags; + } + else if (!strcmp(key, "register")) + { + g_CurrentArgumentInfo.info.custom_register = GetCustomRegisterFromString(value); + + if (g_CurrentArgumentInfo.info.custom_register == sp::DHookRegister_Default) + { + globals::sourcemod->LogError(globals::myself, "Invalid register \"%s\": line: %i col: %i", value, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + else + { + globals::sourcemod->LogError(globals::myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + break; + } + default: { + globals::sourcemod->LogError(globals::myself, "Unknown key in Functions section \"%s\": line: %i col: %i", key, states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + return SourceMod::SMCResult_Continue; +} + +SourceMod::SMCResult SignatureGameConfig::ReadSMC_LeavingSection(const SourceMod::SMCStates* states) +{ + // We were ignoring this section. + if (g_IgnoreLevel > 0) + { + g_IgnoreLevel--; + return SourceMod::SMCResult_Continue; + } + + // We were in a section only for our OS. + if (g_PlatformOnlyState == g_ParseState) + { + g_PlatformOnlyState = ParseState::None; + return SourceMod::SMCResult_Continue; + } + + switch (g_ParseState) + { + case ParseState::Function: + g_ParseState = ParseState::Root; + + if (!g_CurrentSignature->address.length() && !g_CurrentSignature->signature.length() && !g_CurrentSignature->offset.length()) + { + globals::sourcemod->LogError(globals::myself, "Function \"%s\" doesn't have a \"signature\", \"offset\" nor \"address\" set: line: %i col: %i", g_CurrentFunctionName.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + if (!g_CurrentSignature->offset.length()) + { + // DynamicDetours doesn't expose the passflags concept like SourceHook. + // See if we're trying to set some invalid flags on detour arguments. + for (auto &arg : g_CurrentSignature->args) + { + if ((arg.info.flags & ~sp::DHookPass_ByVal) > 0) + { + globals::sourcemod->LogError(globals::myself, "Function \"%s\" uses unsupported pass flags in argument \"%s\". Flags are only supported for virtual hooks: line: %i col: %i", g_CurrentFunctionName.c_str(), arg.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + } + + // Save this function signature in our cache. + signatures_[g_CurrentFunctionName] = g_CurrentSignature; + g_CurrentFunctionName = ""; + g_CurrentSignature = nullptr; + break; + case ParseState::Arguments: + g_ParseState = ParseState::Function; + break; + case ParseState::Argument: + g_ParseState = ParseState::Arguments; + + if (g_CurrentArgumentInfo.info.type == sp::HookParamType_Unknown) + { + globals::sourcemod->LogError(globals::myself, "Missing argument type for argument \"%s\": line: %i col: %i", g_CurrentArgumentInfo.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + + // The size wasn't set in the config. See if that's fine and we can guess it from the type. + if (!g_CurrentArgumentInfo.info.size) + { + if (g_CurrentArgumentInfo.info.type == sp::HookParamType_Object) + { + globals::sourcemod->LogError(globals::myself, "Object param \"%s\" being set with no size: line: %i col: %i", g_CurrentArgumentInfo.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + else + { + g_CurrentArgumentInfo.info.size = sp::GetParamTypeSize(g_CurrentArgumentInfo.info.type).value_or(0); + if (g_CurrentArgumentInfo.info.size == 0) + { + globals::sourcemod->LogError(globals::myself, "param \"%s\" size could not be auto-determined!", g_CurrentArgumentInfo.name.c_str(), states->line, states->col); + return SourceMod::SMCResult_HaltFail; + } + } + } + + // See if we were changing an existing argument. + bool changed = false; + for (auto &arg : g_CurrentSignature->args) + { + if (!arg.name.compare(g_CurrentArgumentInfo.name)) + { + arg.info = g_CurrentArgumentInfo.info; + changed = true; + break; + } + } + // This was a new argument. Add it to the end of the list. + if (!changed) + g_CurrentSignature->args.push_back(g_CurrentArgumentInfo); + + g_CurrentArgumentInfo.name = ""; + break; + } + + return SourceMod::SMCResult_Continue; +} + +void SignatureGameConfig::ReadSMC_ParseStart() +{ + g_ParseState = ParseState::Root; + g_IgnoreLevel = 0; + g_PlatformOnlyState = ParseState::None; + g_CurrentSignature = nullptr; + g_CurrentFunctionName = ""; + g_CurrentArgumentInfo.name = ""; +} + +sp::ReturnType SignatureGameConfig::GetReturnTypeFromString(const char* str) +{ + if (!strcmp(str, "void")) + return sp::ReturnType_Void; + else if (!strcmp(str, "int")) + return sp::ReturnType_Int; + else if (!strcmp(str, "bool")) + return sp::ReturnType_Bool; + else if (!strcmp(str, "float")) + return sp::ReturnType_Float; + else if (!strcmp(str, "string")) + return sp::ReturnType_String; + else if (!strcmp(str, "stringptr")) + return sp::ReturnType_StringPtr; + else if (!strcmp(str, "charptr")) + return sp::ReturnType_CharPtr; + else if (!strcmp(str, "vector")) + return sp::ReturnType_Vector; + else if (!strcmp(str, "vectorptr")) + return sp::ReturnType_VectorPtr; + else if (!strcmp(str, "cbaseentity")) + return sp::ReturnType_CBaseEntity; + else if (!strcmp(str, "edict")) + return sp::ReturnType_Edict; + + return sp::ReturnType_Unknown; +} + +sp::HookParamType SignatureGameConfig::GetHookParamTypeFromString(const char* str) +{ + if (!strcmp(str, "int")) + return sp::HookParamType_Int; + else if (!strcmp(str, "bool")) + return sp::HookParamType_Bool; + else if (!strcmp(str, "float")) + return sp::HookParamType_Float; + else if (!strcmp(str, "string")) + return sp::HookParamType_String; + else if (!strcmp(str, "stringptr")) + return sp::HookParamType_StringPtr; + else if (!strcmp(str, "charptr")) + return sp::HookParamType_CharPtr; + else if (!strcmp(str, "vectorptr")) + return sp::HookParamType_VectorPtr; + else if (!strcmp(str, "cbaseentity")) + return sp::HookParamType_CBaseEntity; + else if (!strcmp(str, "objectptr")) + return sp::HookParamType_ObjectPtr; + else if (!strcmp(str, "edict")) + return sp::HookParamType_Edict; + else if (!strcmp(str, "object")) + return sp::HookParamType_Object; + return sp::HookParamType_Unknown; +} + +sp::DHookRegister SignatureGameConfig::GetCustomRegisterFromString(const char* str) +{ + if (!strcmp(str, "al")) + return sp::DHookRegister_AL; + else if (!strcmp(str, "cl")) + return sp::DHookRegister_CL; + else if (!strcmp(str, "dl")) + return sp::DHookRegister_DL; + else if (!strcmp(str, "bl")) + return sp::DHookRegister_BL; + else if (!strcmp(str, "ah")) + return sp::DHookRegister_AH; + else if (!strcmp(str, "ch")) + return sp::DHookRegister_CH; + else if (!strcmp(str, "dh")) + return sp::DHookRegister_DH; + else if (!strcmp(str, "bh")) + return sp::DHookRegister_BH; + else if (!strcmp(str, "ax")) + return sp::DHookRegister_EAX; + else if (!strcmp(str, "cx")) + return sp::DHookRegister_ECX; + else if (!strcmp(str, "dx")) + return sp::DHookRegister_EDX; + else if (!strcmp(str, "bx")) + return sp::DHookRegister_EBX; + else if (!strcmp(str, "sp")) + return sp::DHookRegister_ESP; + else if (!strcmp(str, "bp")) + return sp::DHookRegister_EBP; + else if (!strcmp(str, "si")) + return sp::DHookRegister_ESI; + else if (!strcmp(str, "di")) + return sp::DHookRegister_EDI; + else if (!strcmp(str, "eax")) + return sp::DHookRegister_EAX; + else if (!strcmp(str, "ecx")) + return sp::DHookRegister_ECX; + else if (!strcmp(str, "edx")) + return sp::DHookRegister_EDX; + else if (!strcmp(str, "ebx")) + return sp::DHookRegister_EBX; + else if (!strcmp(str, "esp")) + return sp::DHookRegister_ESP; + else if (!strcmp(str, "ebp")) + return sp::DHookRegister_EBP; + else if (!strcmp(str, "esi")) + return sp::DHookRegister_ESI; + else if (!strcmp(str, "edi")) + return sp::DHookRegister_EDI; + else if (!strcmp(str, "rax")) + return sp::DHookRegister_RAX; + else if (!strcmp(str, "rcx")) + return sp::DHookRegister_RCX; + else if (!strcmp(str, "rdx")) + return sp::DHookRegister_RDX; + else if (!strcmp(str, "rbx")) + return sp::DHookRegister_RBX; + else if (!strcmp(str, "rsp")) + return sp::DHookRegister_RSP; + else if (!strcmp(str, "rbp")) + return sp::DHookRegister_RBP; + else if (!strcmp(str, "rsi")) + return sp::DHookRegister_RSI; + else if (!strcmp(str, "rdi")) + return sp::DHookRegister_RDI; + else if (!strcmp(str, "r8")) + return sp::DHookRegister_R8; + else if (!strcmp(str, "r9")) + return sp::DHookRegister_R9; + else if (!strcmp(str, "r10")) + return sp::DHookRegister_R10; + else if (!strcmp(str, "r11")) + return sp::DHookRegister_R11; + else if (!strcmp(str, "r12")) + return sp::DHookRegister_R12; + else if (!strcmp(str, "r13")) + return sp::DHookRegister_R13; + else if (!strcmp(str, "r14")) + return sp::DHookRegister_R14; + else if (!strcmp(str, "r15")) + return sp::DHookRegister_R15; + else if (!strcmp(str, "mm0")) + return sp::DHookRegister_XMM0; + else if (!strcmp(str, "mm1")) + return sp::DHookRegister_XMM1; + else if (!strcmp(str, "mm2")) + return sp::DHookRegister_XMM2; + else if (!strcmp(str, "mm3")) + return sp::DHookRegister_XMM3; + else if (!strcmp(str, "mm4")) + return sp::DHookRegister_XMM4; + else if (!strcmp(str, "mm5")) + return sp::DHookRegister_XMM5; + else if (!strcmp(str, "mm6")) + return sp::DHookRegister_XMM6; + else if (!strcmp(str, "mm7")) + return sp::DHookRegister_XMM7; + else if (!strcmp(str, "xmm0")) + return sp::DHookRegister_XMM0; + else if (!strcmp(str, "xmm1")) + return sp::DHookRegister_XMM1; + else if (!strcmp(str, "xmm2")) + return sp::DHookRegister_XMM2; + else if (!strcmp(str, "xmm3")) + return sp::DHookRegister_XMM3; + else if (!strcmp(str, "xmm4")) + return sp::DHookRegister_XMM4; + else if (!strcmp(str, "xmm5")) + return sp::DHookRegister_XMM5; + else if (!strcmp(str, "xmm6")) + return sp::DHookRegister_XMM6; + else if (!strcmp(str, "xmm7")) + return sp::DHookRegister_XMM7; + else if (!strcmp(str, "xmm8")) + return sp::DHookRegister_XMM8; + else if (!strcmp(str, "xmm9")) + return sp::DHookRegister_XMM9; + else if (!strcmp(str, "xmm10")) + return sp::DHookRegister_XMM10; + else if (!strcmp(str, "xmm11")) + return sp::DHookRegister_XMM11; + else if (!strcmp(str, "xmm12")) + return sp::DHookRegister_XMM12; + else if (!strcmp(str, "xmm13")) + return sp::DHookRegister_XMM13; + else if (!strcmp(str, "xmm14")) + return sp::DHookRegister_XMM14; + else if (!strcmp(str, "xmm15")) + return sp::DHookRegister_XMM15; + else if (!strcmp(str, "st0")) + return sp::DHookRegister_ST0; + return sp::DHookRegister_Default; +} + +} \ No newline at end of file diff --git a/extensions/dhooks/signatures.h b/extensions/dhooks/src/signatures.hpp similarity index 50% rename from extensions/dhooks/signatures.h rename to extensions/dhooks/src/signatures.hpp index 2a1a2c61ad..9866a5070b 100644 --- a/extensions/dhooks/signatures.h +++ b/extensions/dhooks/src/signatures.hpp @@ -32,11 +32,52 @@ #ifndef _INCLUDE_SIGNATURES_H_ #define _INCLUDE_SIGNATURES_H_ -#include "extension.h" -#include "util.h" +#include "sp_inc.hpp" +#include "variable.hpp" + +#include "ITextParsers.h" + #include #include -#include +#include + +namespace dhooks { + +struct ParamInfo +{ + ParamInfo() : type(sp::HookParamType_Unknown), size(0), flags(sp::DHookPass_ByVal), custom_register(sp::DHookRegister_Default) {} + sp::HookParamType type; + size_t size; + sp::DHookPassFlag flags; + sp::DHookRegister custom_register; + + operator Variable() const { + Variable var; + var.dhook_type = type; + var.dhook_size = size; + var.dhook_pass_flags = flags; + var.dhook_custom_register = custom_register; + return var; + } +}; + +struct ReturnInfo +{ + ReturnInfo() : type(sp::ReturnType_Unknown), size(0), flags(sp::DHookPass_ByVal), custom_register(sp::DHookRegister_Default) {} + sp::ReturnType type; + size_t size; + sp::DHookPassFlag flags; + sp::DHookRegister custom_register; + + operator ReturnVariable() const { + ReturnVariable var; + var.dhook_type = type; + var.dhook_size = size; + var.dhook_pass_flags = flags; + var.dhook_custom_register = custom_register; + return var; + } +}; struct ArgumentInfo { ArgumentInfo() : name() @@ -55,30 +96,30 @@ class SignatureWrapper { std::string address; std::string offset; std::vector args; - CallingConvention callConv; - HookType hookType; - ReturnType retType; - ThisPointerType thisType; + sp::CallingConvention callConv; + sp::HookType hookType; + ReturnInfo ret; + sp::ThisPointerType thisType; }; -class SignatureGameConfig : public ITextListener_SMC { +class SignatureGameConfig : public SourceMod::ITextListener_SMC { public: - SignatureWrapper *GetFunctionSignature(const char *function); + SignatureWrapper* GetFunctionSignature(const char *function); public: //ITextListener_SMC - SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); - SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); - SMCResult ReadSMC_LeavingSection(const SMCStates *states); - void ReadSMC_ParseStart(); + virtual SourceMod::SMCResult ReadSMC_NewSection(const SourceMod::SMCStates* states, const char* name) override; + virtual SourceMod::SMCResult ReadSMC_KeyValue(const SourceMod::SMCStates* states, const char* key, const char* value) override; + virtual SourceMod::SMCResult ReadSMC_LeavingSection(const SourceMod::SMCStates* states) override; + virtual void ReadSMC_ParseStart() override; private: - ReturnType GetReturnTypeFromString(const char *str); - HookParamType GetHookParamTypeFromString(const char *str); - Register_t GetCustomRegisterFromString(const char *str); + sp::ReturnType GetReturnTypeFromString(const char* str); + sp::HookParamType GetHookParamTypeFromString(const char* str); + sp::DHookRegister GetCustomRegisterFromString(const char* str); private: - StringHashMap signatures_; + std::unordered_map signatures_; }; -extern SignatureGameConfig *g_pSignatures; -#endif +} +#endif \ No newline at end of file diff --git a/extensions/dhooks/smsdk_config.h b/extensions/dhooks/src/smsdk_config.h similarity index 69% rename from extensions/dhooks/smsdk_config.h rename to extensions/dhooks/src/smsdk_config.h index c5e1c00099..b4a65016e9 100644 --- a/extensions/dhooks/smsdk_config.h +++ b/extensions/dhooks/src/smsdk_config.h @@ -1,14 +1,14 @@ /** * vim: set ts=4 : * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. + * SourceMod SDK Hooks Extension + * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License, version 3.0, as published by the * Free Software Foundation. - * + * * This program 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 @@ -28,9 +28,7 @@ * * Version: $Id$ */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#pragma once #include @@ -58,27 +56,5 @@ * @brief Sets whether or not this plugin required Metamod. * NOTE: Uncomment to enable, comment to disable. */ -#define SMEXT_CONF_METAMOD - -/** Enable interfaces you want to use here by uncommenting lines */ -//#define SMEXT_ENABLE_FORWARDSYS -#define SMEXT_ENABLE_HANDLESYS -#define SMEXT_ENABLE_PLAYERHELPERS -//#define SMEXT_ENABLE_DBMANAGER -#define SMEXT_ENABLE_GAMECONF -//#define SMEXT_ENABLE_MEMUTILS -#define SMEXT_ENABLE_GAMEHELPERS -//#define SMEXT_ENABLE_TIMERSYS -//#define SMEXT_ENABLE_THREADER -//#define SMEXT_ENABLE_LIBSYS -//#define SMEXT_ENABLE_MENUS -//#define SMEXT_ENABLE_ADTFACTORY -#define SMEXT_ENABLE_PLUGINSYS -//#define SMEXT_ENABLE_ADMINSYS -//#define SMEXT_ENABLE_TEXTPARSERS -//#define SMEXT_ENABLE_USERMSGS -//#define SMEXT_ENABLE_TRANSLATOR -//#define SMEXT_ENABLE_NINVOKE -//#define SMEXT_ENABLE_ROOTCONSOLEMENU - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define SMEXT_CONF_METAMOD +#define META_NO_HL2SDK \ No newline at end of file diff --git a/extensions/dhooks/src/sp_inc.cpp b/extensions/dhooks/src/sp_inc.cpp new file mode 100644 index 0000000000..0b09812834 --- /dev/null +++ b/extensions/dhooks/src/sp_inc.cpp @@ -0,0 +1,60 @@ +#include "sp_inc.hpp" +#include "sdk_types.hpp" + +namespace dhooks::sp { + +std::optional GetParamTypeSize(HookParamType type) { + switch (type) { + case HookParamType_Int: + return sizeof(int); + case HookParamType_Bool: + return sizeof(bool); + case HookParamType_Float: + return sizeof(float); + case HookParamType_String: + return sizeof(sdk::string_t); + case HookParamType_StringPtr: + return sizeof(sdk::string_t*); + case HookParamType_CharPtr: + return sizeof(const char*); + case HookParamType_VectorPtr: + return sizeof(sdk::Vector*); + case HookParamType_CBaseEntity: + return sizeof(sdk::CBaseEntity*); + case HookParamType_ObjectPtr: + return sizeof(void*); + case HookParamType_Edict: + return sizeof(sdk::edict_t*); + } + return {}; +} + +std::optional GetReturnTypeSize(ReturnType type) { + switch (type) { + case sp::ReturnType_Void: + return 0; + case sp::ReturnType_Int: + return sizeof(int); + case sp::ReturnType_Bool: + return sizeof(bool); + case sp::ReturnType_Float: + return sizeof(float); + case sp::ReturnType_String: + return sizeof(sdk::string_t); + case sp::ReturnType_StringPtr: + return sizeof(sdk::string_t*); + case sp::ReturnType_CharPtr: + return sizeof(const char*); + case sp::ReturnType_Vector: + return sizeof(sdk::Vector); + case sp::ReturnType_VectorPtr: + return sizeof(sdk::Vector*); + case sp::ReturnType_CBaseEntity: + return sizeof(sdk::CBaseEntity*); + case sp::ReturnType_Edict: + return sizeof(sdk::edict_t*); + } + return {}; +} + +} \ No newline at end of file diff --git a/extensions/dhooks/src/sp_inc.hpp b/extensions/dhooks/src/sp_inc.hpp new file mode 100644 index 0000000000..61edf60354 --- /dev/null +++ b/extensions/dhooks/src/sp_inc.hpp @@ -0,0 +1,172 @@ +#pragma once + +#include +#include + +namespace dhooks::sp { + +enum HookMode +{ + Hook_Pre, + Hook_Post +}; + +enum HookType +{ + HookType_Entity, + HookType_GameRules, + HookType_Raw +}; + +enum ThisPointerType +{ + ThisPointer_Ignore, + ThisPointer_CBaseEntity, + ThisPointer_Address +}; + +enum CallingConvention +{ + CallConv_CDECL, + CallConv_THISCALL, + CallConv_STDCALL, + CallConv_FASTCALL, +}; + +enum HookParamType +{ + HookParamType_Unknown, + HookParamType_Int, + HookParamType_Bool, + HookParamType_Float, + HookParamType_String, + HookParamType_StringPtr, + HookParamType_CharPtr, + HookParamType_VectorPtr, + HookParamType_CBaseEntity, + HookParamType_ObjectPtr, + HookParamType_Edict, + HookParamType_Object +}; + +inline bool HookParamTypeIsPtr(HookParamType type) { + return (type == HookParamType_StringPtr || type == HookParamType_CharPtr || type == HookParamType_VectorPtr || type == HookParamType_CBaseEntity || type == HookParamType_ObjectPtr || type == HookParamType_Edict); +} + +enum ReturnType +{ + ReturnType_Unknown, + ReturnType_Void, + ReturnType_Int, + ReturnType_Bool, + ReturnType_Float, + ReturnType_String, + ReturnType_StringPtr, + ReturnType_CharPtr, + ReturnType_Vector, + ReturnType_VectorPtr, + ReturnType_CBaseEntity, + ReturnType_Edict +}; + +enum DHookPassFlag : std::uint8_t +{ + DHookPass_ByVal = (1<<0), + DHookPass_ByRef = (1<<1), + DHookPass_ODTOR = (1<<2), + DHookPass_OCTOR = (1<<3), + DHookPass_OASSIGNOP = (1<<4), +}; + +enum MRESReturn +{ + MRES_ChangedHandled = -2, + MRES_ChangedOverride, + MRES_Ignored, + MRES_Handled, + MRES_Override, + MRES_Supercede +}; + +enum DHookRegister +{ + DHookRegister_Default, + DHookRegister_AL, + DHookRegister_CL, + DHookRegister_DL, + DHookRegister_BL, + DHookRegister_AH, + DHookRegister_CH, + DHookRegister_DH, + DHookRegister_BH, + DHookRegister_EAX, + DHookRegister_ECX, + DHookRegister_EDX, + DHookRegister_EBX, + DHookRegister_ESP, + DHookRegister_EBP, + DHookRegister_ESI, + DHookRegister_EDI, + DHookRegister_XMM0, + DHookRegister_XMM1, + DHookRegister_XMM2, + DHookRegister_XMM3, + DHookRegister_XMM4, + DHookRegister_XMM5, + DHookRegister_XMM6, + DHookRegister_XMM7, + DHookRegister_ST0, + DHookRegister_RAX, + DHookRegister_RCX, + DHookRegister_RDX, + DHookRegister_RBX, + DHookRegister_RSP, + DHookRegister_RBP, + DHookRegister_RSI, + DHookRegister_RDI, + DHookRegister_R8, + DHookRegister_R9, + DHookRegister_R10, + DHookRegister_R11, + DHookRegister_R12, + DHookRegister_R13, + DHookRegister_R14, + DHookRegister_R15, + DHookRegister_XMM8, + DHookRegister_XMM9, + DHookRegister_XMM10, + DHookRegister_XMM11, + DHookRegister_XMM12, + DHookRegister_XMM13, + DHookRegister_XMM14, + DHookRegister_XMM15 +}; + +enum ObjectValueType +{ + ObjectValueType_Int = 0, + ObjectValueType_Bool, + ObjectValueType_Ehandle, + ObjectValueType_Float, + ObjectValueType_CBaseEntityPtr, + ObjectValueType_IntPtr, + ObjectValueType_BoolPtr, + ObjectValueType_EhandlePtr, + ObjectValueType_FloatPtr, + ObjectValueType_Vector, + ObjectValueType_VectorPtr, + ObjectValueType_CharPtr, + ObjectValueType_String +}; + +enum SDKFuncConfSource +{ + SDKConf_Virtual, + SDKConf_Signature, + SDKConf_Address +}; + +std::optional GetParamTypeSize(HookParamType type); +std::optional GetReturnTypeSize(ReturnType type); + +} \ No newline at end of file diff --git a/extensions/dhooks/src/variable.hpp b/extensions/dhooks/src/variable.hpp new file mode 100644 index 0000000000..1e234bc29d --- /dev/null +++ b/extensions/dhooks/src/variable.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "sp_inc.hpp" +#include "register.hpp" + +#include +#include + +namespace dhooks { +struct Variable { +public: + enum Alignment { + OneByte = 1, + TwoBytes = 2, + FourBytes = 4, + EightBytes = 8, + SixteenBytes = 16 + }; + + sp::HookParamType dhook_type; + std::size_t dhook_size; + sp::DHookPassFlag dhook_pass_flags; + sp::DHookRegister dhook_custom_register; + + // Provided by the ABI, used by the JIT + // If DHook is to ever support complex type, transform those fields + // into an array so that the SP natives know where to look when offsetting into an object + std::optional reg_index; + std::optional float_reg_index; + std::optional reg_offset; + Alignment alignment; + // Atm it's exactly the same as _dhook_size + // We differentiate it anyways, to avoid having to refactor the JIT + std::size_t type_size; +}; + +struct ReturnVariable { +public: + enum Alignment { + OneByte = 1, + TwoBytes = 2, + FourBytes = 4, + EightBytes = 8, + SixteenBytes = 16 + }; + + sp::ReturnType dhook_type; + size_t dhook_size; + sp::DHookPassFlag dhook_pass_flags; + sp::DHookRegister dhook_custom_register; + + std::optional reg_index; + std::optional float_reg_index; + size_t reg_offset; +}; +} \ No newline at end of file diff --git a/extensions/dhooks/util.cpp b/extensions/dhooks/util.cpp deleted file mode 100644 index ac9b678a10..0000000000 --- a/extensions/dhooks/util.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "util.h" - -void * GetObjectAddr(HookParamType type, unsigned int flags, void **params, size_t offset) -{ -#ifdef WIN32 - if (type == HookParamType_Object) - return (void *)((intptr_t)params + offset); -#elif POSIX - if (type == HookParamType_Object && !(flags & PASSFLAG_ODTOR)) //Objects are passed by rrefrence if they contain destructors. - return (void *)((intptr_t)params + offset); -#endif - return *(void **)((intptr_t)params + offset); - -} - -size_t GetStackParamOffset(HookParamsStruct *paramStruct, unsigned int index) -{ - assert(paramStruct->dg->params[index].custom_register == None); - - size_t offset = 0; - for (unsigned int i = 0; i < index; i++) - { - // Only care for arguments on the stack before us. - if (paramStruct->dg->params[i].custom_register != None) - continue; - -#ifndef WIN32 - if (paramStruct->dg->params[i].type == HookParamType_Object && (paramStruct->dg->params[i].flags & PASSFLAG_ODTOR)) //Passed by refrence - { - offset += sizeof(void *); - continue; - } -#endif -#ifdef KE_ARCH_X64 - offset += 8; -#else - offset += paramStruct->dg->params[i].size; -#endif - } - return offset; -} - -size_t GetRegisterParamOffset(HookParamsStruct *paramStruct, unsigned int index) -{ - // TODO: Fix this up and get a pointer to the CDetour - assert(paramStruct->dg->params[index].custom_register != None); - - // Need to get the size of the stack arguments first. Register arguments are stored after them in the buffer. - size_t stackSize = 0; - for (int i = paramStruct->dg->params.size() - 1; i >= 0; i--) - { - if (paramStruct->dg->params[i].custom_register == None) - { - stackSize += paramStruct->dg->params[i].size; - } - } - - size_t offset = stackSize; - for (unsigned int i = 0; i < index; i++) - { - // Only care for arguments passed through a register as well before us. - if (paramStruct->dg->params[i].custom_register == None) - continue; - - offset += paramStruct->dg->params[i].size; - } - return offset; -} - -size_t GetParamOffset(HookParamsStruct *paramStruct, unsigned int index) -{ - if (paramStruct->dg->params[index].custom_register == None) - return GetStackParamOffset(paramStruct, index); - else - return GetRegisterParamOffset(paramStruct, index); -} - -size_t GetParamTypeSize(HookParamType type) -{ - return sizeof(void *); -} - -size_t GetParamsSize(DHooksCallback *dg)//Get the full size, this is for creating the STACK. -{ - size_t res = 0; - - for (int i = dg->params.size() - 1; i >= 0; i--) - { - res += dg->params.at(i).size; - } - - return res; -} - -DataType_t DynamicHooks_ConvertParamTypeFrom(HookParamType type) -{ - switch (type) - { - case HookParamType_Int: - return DATA_TYPE_INT; - case HookParamType_Bool: - return DATA_TYPE_BOOL; - case HookParamType_Float: - return DATA_TYPE_FLOAT; - case HookParamType_StringPtr: - case HookParamType_CharPtr: - case HookParamType_VectorPtr: - case HookParamType_CBaseEntity: - case HookParamType_ObjectPtr: - case HookParamType_Edict: - return DATA_TYPE_POINTER; - case HookParamType_Object: - return DATA_TYPE_OBJECT; - default: - smutils->LogError(myself, "Unhandled parameter type %d!", type); - } - - return DATA_TYPE_POINTER; -} - -DataType_t DynamicHooks_ConvertReturnTypeFrom(ReturnType type) -{ - switch (type) - { - case ReturnType_Void: - return DATA_TYPE_VOID; - case ReturnType_Int: - return DATA_TYPE_INT; - case ReturnType_Bool: - return DATA_TYPE_BOOL; - case ReturnType_Float: - return DATA_TYPE_FLOAT; - case ReturnType_StringPtr: - case ReturnType_CharPtr: - case ReturnType_VectorPtr: - case ReturnType_CBaseEntity: - case ReturnType_Edict: - return DATA_TYPE_POINTER; - case ReturnType_Vector: - return DATA_TYPE_OBJECT; - default: - smutils->LogError(myself, "Unhandled return type %d!", type); - } - - return DATA_TYPE_VOID; -} - -Register_t DynamicHooks_ConvertRegisterFrom(PluginRegister reg) -{ - switch (reg) - { - case DHookRegister_Default: - return None; - - case DHookRegister_AL: - return AL; - case DHookRegister_CL: - return CL; - case DHookRegister_DL: - return DL; - case DHookRegister_BL: - return BL; - case DHookRegister_AH: - return AH; - case DHookRegister_CH: - return CH; - case DHookRegister_DH: - return DH; - case DHookRegister_BH: - return BH; - - case DHookRegister_EAX: - return EAX; - case DHookRegister_ECX: - return ECX; - case DHookRegister_EDX: - return EDX; - case DHookRegister_EBX: - return EBX; - case DHookRegister_ESP: - return ESP; - case DHookRegister_EBP: - return EBP; - case DHookRegister_ESI: - return ESI; - case DHookRegister_EDI: - return EDI; - - case DHookRegister_XMM0: - return XMM0; - case DHookRegister_XMM1: - return XMM1; - case DHookRegister_XMM2: - return XMM2; - case DHookRegister_XMM3: - return XMM3; - case DHookRegister_XMM4: - return XMM4; - case DHookRegister_XMM5: - return XMM5; - case DHookRegister_XMM6: - return XMM6; - case DHookRegister_XMM7: - return XMM7; - - case DHookRegister_ST0: - return ST0; - } - - return None; -} diff --git a/extensions/dhooks/util.h b/extensions/dhooks/util.h deleted file mode 100644 index a168c6babe..0000000000 --- a/extensions/dhooks/util.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_UTIL_FUNCTIONS_H_ -#define _INCLUDE_UTIL_FUNCTIONS_H_ - -#include "vhook.h" -#include "convention.h" - -enum PluginRegister -{ - // Don't change the register and use the default for the calling convention. - DHookRegister_Default, - - // 8-bit general purpose registers - DHookRegister_AL, - DHookRegister_CL, - DHookRegister_DL, - DHookRegister_BL, - DHookRegister_AH, - DHookRegister_CH, - DHookRegister_DH, - DHookRegister_BH, - - // 32-bit general purpose registers - DHookRegister_EAX, - DHookRegister_ECX, - DHookRegister_EDX, - DHookRegister_EBX, - DHookRegister_ESP, - DHookRegister_EBP, - DHookRegister_ESI, - DHookRegister_EDI, - - // 128-bit XMM registers - DHookRegister_XMM0, - DHookRegister_XMM1, - DHookRegister_XMM2, - DHookRegister_XMM3, - DHookRegister_XMM4, - DHookRegister_XMM5, - DHookRegister_XMM6, - DHookRegister_XMM7, - - // 80-bit FPU registers - DHookRegister_ST0 -}; - -size_t GetParamOffset(HookParamsStruct *params, unsigned int index); -void * GetObjectAddr(HookParamType type, unsigned int flags, void **params, size_t offset); -size_t GetParamTypeSize(HookParamType type); -size_t GetParamsSize(DHooksCallback *dg); - -DataType_t DynamicHooks_ConvertParamTypeFrom(HookParamType type); -DataType_t DynamicHooks_ConvertReturnTypeFrom(ReturnType type); -Register_t DynamicHooks_ConvertRegisterFrom(PluginRegister reg); -#endif diff --git a/extensions/dhooks/version.rc b/extensions/dhooks/version.rc deleted file mode 100644 index 076f972806..0000000000 --- a/extensions/dhooks/version.rc +++ /dev/null @@ -1,45 +0,0 @@ -#include "winres.h" - -#include - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif - -#ifndef SM_GENERATED_BUILD -#define BINARY_NAME "dhooks.ext.dll\0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION SM_VERSION_FILE - PRODUCTVERSION SM_VERSION_FILE - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "DHooks Extension" - VALUE "FileDescription", "SourceMod Dynamic Hooks Extension" - VALUE "FileVersion", SM_VERSION_STRING - VALUE "InternalName", "SourceMod DHooks Extension" - VALUE "LegalCopyright", "Copyright (c) 2021, AlliedModders LLC" - VALUE "OriginalFilename", BINARY_NAME - VALUE "ProductName", "SourceMod DHooks Extension" - VALUE "ProductVersion", SM_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 0x04B0 - END -END diff --git a/extensions/dhooks/vfunc_call.h b/extensions/dhooks/vfunc_call.h deleted file mode 100644 index d12ebae447..0000000000 --- a/extensions/dhooks/vfunc_call.h +++ /dev/null @@ -1,355 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_VFUNC_CALL_H_ -#define _INCLUDE_VFUNC_CALL_H_ - -#include "vhook.h" -#include "extension.h" -#include "util.h" - -#define PARAMINFO_SWITCH(passType) \ - paramInfo[i].flags = dg->params.at(i).flags; \ - paramInfo[i].size = dg->params.at(i).size; \ - paramInfo[i].type = passType; - -#define VSTK_PARAM_SWITCH(paramType) \ - if(paramStruct->isChanged[i]) \ - { \ - *(paramType *)vptr = *(paramType *)newAddr; \ - } \ - else \ - { \ - *(paramType *)vptr = *(paramType *)orgAddr; \ - } \ - if(i + 1 != dg->params.size()) \ - { \ - vptr += dg->params.at(i).size; \ - } \ - break; - -#define VSTK_PARAM_SWITCH_OBJECT() \ - memcpy(vptr, objAddr, dg->params.at(i).size); \ - if(i + 1 != dg->params.size()) \ - { \ - vptr += dg->params.at(i).size; \ - } \ - break; - -template -T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) -{ - SourceMod::PassInfo *paramInfo = NULL; - SourceMod::PassInfo returnInfo; - - if(dg->returnType != ReturnType_Void) - { - returnInfo.flags = dg->returnFlag; - returnInfo.size = sizeof(T); - if( dg->returnType != ReturnType_Vector) - { - returnInfo.type = PassType_Basic; - } - else - { - returnInfo.type = PassType_Object; - } - } - - ICallWrapper *pCall; - - size_t size = GetParamsSize(dg); - - unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size); - unsigned char *vptr = vstk; - - *(void **)vptr = iface; - - if(paramStruct) - { - vptr += sizeof(void *); - paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); - - for(int i = 0; i < (int)dg->params.size(); i++) - { - size_t offset = GetParamOffset(paramStruct, i); - - void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset); - void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset); - - switch(dg->params.at(i).type) - { - case HookParamType_Int: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(int); - case HookParamType_Bool: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(cell_t); - case HookParamType_Float: - PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH(float); - case HookParamType_String: - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(string_t); - case HookParamType_StringPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(string_t *); - case HookParamType_CharPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(char *); - case HookParamType_VectorPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(SDKVector *); - case HookParamType_CBaseEntity: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(CBaseEntity *); - case HookParamType_Edict: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(edict_t *); - case HookParamType_Object: - { - void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH_OBJECT(); - } - default: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(void *); - } - } - } - - T ret = 0; - - if(dg->returnType == ReturnType_Void) - { - pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.size()); - pCall->Execute(vstk, NULL); - } - else - { - pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size()); - pCall->Execute(vstk, &ret); - } - - pCall->Destroy(); - free(vstk); - - if(paramInfo != NULL) - { - free(paramInfo); - } - - return ret; -} -template <> -SDKVector CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) -{ - SourceMod::PassInfo *paramInfo = NULL; - SourceMod::PassInfo returnInfo; - - if(dg->returnType != ReturnType_Void) - { - returnInfo.flags = dg->returnFlag; - returnInfo.size = sizeof(SDKVector); - returnInfo.type = PassType_Object; - } - - ICallWrapper *pCall; - - size_t size = GetParamsSize(dg); - - unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size); - unsigned char *vptr = vstk; - - *(void **)vptr = iface; - - if(paramStruct) - { - vptr += sizeof(void *); - paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); - for(int i = 0; i < (int)dg->params.size(); i++) - { - size_t offset = GetParamOffset(paramStruct, i); - - void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset); - void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset); - - switch (dg->params.at(i).type) - { - case HookParamType_Int: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(int); - case HookParamType_Bool: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(cell_t); - case HookParamType_Float: - PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH(float); - case HookParamType_String: - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(string_t); - case HookParamType_StringPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(string_t *); - case HookParamType_CharPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(char *); - case HookParamType_VectorPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(SDKVector *); - case HookParamType_CBaseEntity: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(CBaseEntity *); - case HookParamType_Edict: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(edict_t *); - case HookParamType_Object: - { - void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH_OBJECT(); - } - default: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(void *); - } - } - } - - SDKVector ret; - - pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size()); - pCall->Execute(vstk, &ret); - - pCall->Destroy(); - free(vstk); - - if(paramInfo != NULL) - { - free(paramInfo); - } - - return ret; -} -#ifndef WIN32 -template <> -string_t CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) -{ - SourceMod::PassInfo *paramInfo = NULL; - SourceMod::PassInfo returnInfo; - - if(dg->returnType != ReturnType_Void) - { - returnInfo.flags = dg->returnFlag; - returnInfo.size = sizeof(string_t); - returnInfo.type = PassType_Object; - } - - ICallWrapper *pCall; - - size_t size = GetParamsSize(dg); - - unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size); - unsigned char *vptr = vstk; - - *(void **)vptr = iface; - - if(paramStruct) - { - vptr += sizeof(void *); - paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size()); - for(int i = 0; i < dg->params.size(); i++) - { - size_t offset = GetParamOffset(paramStruct, i); - - void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset); - void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset); - - switch (dg->params.at(i).type) - { - case HookParamType_Int: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(int); - case HookParamType_Bool: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(cell_t); - case HookParamType_Float: - PARAMINFO_SWITCH(PassType_Float); - VSTK_PARAM_SWITCH(float); - case HookParamType_String: - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH(string_t); - case HookParamType_StringPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(string_t *); - case HookParamType_CharPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(char *); - case HookParamType_VectorPtr: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(SDKVector *); - case HookParamType_CBaseEntity: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(CBaseEntity *); - case HookParamType_Edict: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(edict_t *); - case HookParamType_Object: - { - void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset); - PARAMINFO_SWITCH(PassType_Object); - VSTK_PARAM_SWITCH_OBJECT(); - } - default: - PARAMINFO_SWITCH(PassType_Basic); - VSTK_PARAM_SWITCH(void *); - } - } - } - - string_t ret; - - pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size()); - pCall->Execute(vstk, &ret); - - pCall->Destroy(); - free(vstk); - - if(paramInfo != NULL) - { - free(paramInfo); - } - - return ret; -} -#endif -#endif diff --git a/extensions/dhooks/vhook.cpp b/extensions/dhooks/vhook.cpp deleted file mode 100644 index 228d875a64..0000000000 --- a/extensions/dhooks/vhook.cpp +++ /dev/null @@ -1,1170 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#include "vhook.h" -#include "vfunc_call.h" -#include "util.h" -#ifdef KE_ARCH_X64 -#include "sh_asm_x86_64.h" -#else -#include -#endif - -SourceHook::IHookManagerAutoGen *g_pHookManager = NULL; - -std::vector g_pHooks; - -using namespace SourceHook; -using namespace sp; - -#ifdef WIN32 -#define OBJECT_OFFSET sizeof(void *) -#else -#define OBJECT_OFFSET (sizeof(void *)*2) -#endif - -#ifdef KE_ARCH_X64 -using namespace SourceHook::Asm; - -SourceHook::Asm::x64JitWriter* GenerateThunk(HookSetup* hook) -{ - auto masm = new x64JitWriter(); - auto type = hook->returnType; - - // We're going to transform rbp into our stack - masm->push(rbp); - - // Copy all the arguments into the stack - // 8 bytes per parameter + 8 bytes for potential return value - int32_t fakeStackSize = ke::Align((int32_t)hook->params.size() * 8 + 8, 16) + 8; // Add another +8 bytes to realign on 16 bytes, due to 'push rbp' earlier - int32_t parameterOffset = fakeStackSize + 8 /* push rbp */ + 8 /* return address */ + 32 /* shadow space */; - masm->sub(rsp, fakeStackSize); - masm->mov(rbp, rsp); - - static x86_64_Reg arg_reg[] = { rcx, rdx, r8, r9 }; - static x86_64_FloatReg arg_reg_float[] = { xmm0, xmm1, xmm2, xmm3 }; - - int stack_index = 0; - int fake_stack_index = 0; - int reg_index = 1; // Account |this| right away - if (type == ReturnType_Vector) { // Special return types occupy another register - masm->mov(rbp(8 * fake_stack_index), rdx); // Store return ptr at the bottom of the stack - reg_index++; - fake_stack_index++; - } - - for (int i = 0; i < hook->params.size(); i++, fake_stack_index++) { - if (reg_index < 4) { - if (hook->params[i].type == HookParamType_Float && hook->params[i].flags == PASSFLAG_BYVAL) { - masm->movsd(rbp(8 * fake_stack_index), arg_reg_float[reg_index]); - } else { - masm->mov(rax, arg_reg[reg_index]); - masm->mov(rbp(8 * fake_stack_index), rax); - } - reg_index++; - } else { - masm->mov(rax, rbp(parameterOffset + 8 * stack_index)); - masm->mov(rbp(8 * fake_stack_index), rax); - stack_index++; - } - } - - //masm->mov(rbp(8 * 2), 0x7777777777777777); - //masm->mov(rbp(8 * 1), 0xDEADBEEFDEADBEEF); - - // Setup 2nd parameter (our fake stack) - masm->mov(rdx, rbp); - - if (type == ReturnType_Float) - { - masm->mov(rax, (uintptr_t)Callback_float); - } - else if (type == ReturnType_Vector) - { - masm->mov(rax, (uintptr_t)Callback_vector); - } - /*else if (type == ReturnType_String) - { - masm->mov(rax, (uintptr_t)Callback_stringt); - }*/ - else - { - masm->mov(rax, (uintptr_t)Callback); - } - masm->sub(rsp, 40); - masm->call(rax); - masm->add(rsp, 40); - - masm->add(rsp, fakeStackSize); - masm->pop(rbp); - masm->retn(); - - masm->SetRE(); - return masm; -} -#elif !defined( WIN32 ) -void *GenerateThunk(HookSetup* hook) -{ - auto type = hook->returnType; - sp::MacroAssembler masm; - static const size_t kStackNeeded = (2) * 4; // 2 args max - static const size_t kReserve = ke::Align(kStackNeeded + 8, 16) - 8; - - masm.push(ebp); - masm.movl(ebp, esp); - masm.subl(esp, kReserve); - if (type != ReturnType_String && type != ReturnType_Vector) - { - masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector - masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument - masm.movl(eax, Operand(ebp, 8)); // grab the |this| - masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/ - } - else - { - masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector - masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument - masm.movl(eax, Operand(ebp, 12)); // grab the |this| - masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/ - } - if (type == ReturnType_Float) - { - masm.call(ExternalAddress((void *)Callback_float)); - } - else if (type == ReturnType_Vector) - { - masm.call(ExternalAddress((void *)Callback_vector)); - } - else if (type == ReturnType_String) - { - masm.call(ExternalAddress((void *)Callback_stringt)); - } - else - { - masm.call(ExternalAddress((void *)Callback)); - } - masm.addl(esp, kReserve); - masm.pop(ebp); // restore ebp - masm.ret(); - - void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length()); - masm.emitToExecutableMemory(base); - return base; -} -#else -// HUGE THANKS TO BAILOPAN (dvander)! -void *GenerateThunk(HookSetup* hook) -{ - auto type = hook->returnType; - sp::MacroAssembler masm; - static const size_t kStackNeeded = (3 + 1) * 4; // 3 args max, 1 locals max - static const size_t kReserve = ke::Align(kStackNeeded + 8, 16) - 8; - - masm.push(ebp); - masm.movl(ebp, esp); - masm.subl(esp, kReserve); - masm.lea(eax, Operand(esp, 3 * 4)); // ptr to 2nd var after argument space - masm.movl(Operand(esp, 2 * 4), eax); // set the ptr as the third argument - masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector - masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument - masm.movl(Operand(esp, 0 * 4), ecx); // set |this| as the 1st argument - if (type == ReturnType_Float) - { - masm.call(ExternalAddress(Callback_float)); - } - else if (type == ReturnType_Vector) - { - masm.call(ExternalAddress(Callback_vector)); - } - else - { - masm.call(ExternalAddress(Callback)); - } - masm.movl(ecx, Operand(esp, 3 * 4)); - masm.addl(esp, kReserve); - masm.pop(ebp); // restore ebp - masm.pop(edx); // grab return address in edx - masm.addl(esp, ecx); // remove arguments - masm.jmp(edx); // return to caller - - void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length()); - masm.emitToExecutableMemory(base); - return base; -} -#endif - -DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, IPluginFunction *plugincb, bool post) -{ - this->callback = MakeHandler(setup); - this->hookid = 0; - this->remove_callback = remove_callback; - this->callback->offset = setup->offset; - this->callback->plugin_callback = plugincb; - this->callback->returnFlag = setup->returnFlag; - this->callback->thisType = setup->thisType; - this->callback->post = post; - this->callback->hookType = setup->hookType; - this->callback->params = setup->params; - - this->addr = 0; - - if(this->callback->hookType == HookType_Entity) - { - this->callback->entity = gamehelpers->EntityToBCompatRef((CBaseEntity *)iface); - } - else - { - if(this->callback->hookType == HookType_Raw) - { - this->addr = (intptr_t)iface; - } - this->callback->entity = -1; - } - - CProtoInfoBuilder protoInfo(ProtoInfo::CallConv_ThisCall); - - for(int i = this->callback->params.size() -1; i >= 0; i--) - { - protoInfo.AddParam(this->callback->params.at(i).size, this->callback->params.at(i).pass_type, PASSFLAG_BYVAL, NULL, NULL, NULL, NULL);//This seems like we need to do something about it at some point... - } - - if(this->callback->returnType == ReturnType_Void) - { - protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, NULL, NULL, NULL, NULL); - } - else if(this->callback->returnType == ReturnType_Float) - { - protoInfo.SetReturnType(sizeof(float), SourceHook::PassInfo::PassType_Float, setup->returnFlag, NULL, NULL, NULL, NULL); - } - else if(this->callback->returnType == ReturnType_String) - { - protoInfo.SetReturnType(sizeof(string_t), SourceHook::PassInfo::PassType_Object, setup->returnFlag, NULL, NULL, NULL, NULL);//We have to be 4 really... or else RIP - } - else if(this->callback->returnType == ReturnType_Vector) - { - protoInfo.SetReturnType(sizeof(SDKVector), SourceHook::PassInfo::PassType_Object, setup->returnFlag, NULL, NULL, NULL, NULL); - } - else - { - protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Basic, setup->returnFlag, NULL, NULL, NULL, NULL); - } - this->pManager = g_pHookManager->MakeHookMan(protoInfo, 0, this->callback->offset); - - this->hookid = g_SHPtr->AddHook(g_PLID,ISourceHook::Hook_Normal, iface, 0, this->pManager, this->callback, this->callback->post); -} - -void CleanupHooks(IPluginContext *pContext) -{ - for(int i = g_pHooks.size() -1; i >= 0; i--) - { - DHooksManager *manager = g_pHooks.at(i); - - if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext()) - { - delete manager; - g_pHooks.erase(g_pHooks.begin() + i); - } - } -} - -bool SetupHookManager(ISmmAPI *ismm) -{ - g_pHookManager = static_cast(ismm->MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL)); - - return g_pHookManager != NULL; -} - -SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type) -{ - switch(type) - { - case HookParamType_Float: - return SourceHook::PassInfo::PassType_Float; - case HookParamType_Object: - return SourceHook::PassInfo::PassType_Object; - } - return SourceHook::PassInfo::PassType_Basic; -} - -size_t GetStackArgsSize(DHooksCallback *dg) -{ - size_t res = GetParamsSize(dg); -#ifdef WIN32 - if(dg->returnType == ReturnType_Vector)//Account for result vector ptr. -#else - if(dg->returnType == ReturnType_Vector || dg->returnType == ReturnType_String) -#endif - { - res += OBJECT_OFFSET; - } - return res; -} - -HookReturnStruct::~HookReturnStruct() -{ - if (this->type == ReturnType_String || this->type == ReturnType_Int || this->type == ReturnType_Bool || this->type == ReturnType_Float || this->type == ReturnType_Vector) - { - free(this->newResult); - free(this->orgResult); - } -} - -HookParamsStruct::~HookParamsStruct() -{ - if (this->orgParams != NULL) - { - free(this->orgParams); - } - if (this->isChanged != NULL) - { - free(this->isChanged); - } - if (this->newParams != NULL) - { - free(this->newParams); - } -} - -HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t argStackSize) -{ - HookParamsStruct *params = new HookParamsStruct(); - params->dg = dg; -#ifdef WIN32 - if(dg->returnType != ReturnType_Vector) -#else - if(dg->returnType != ReturnType_Vector && dg->returnType != ReturnType_String) -#endif - { - params->orgParams = (void **)malloc(argStackSize); - memcpy(params->orgParams, argStack, argStackSize); - } - else //Offset result ptr - { - params->orgParams = (void **)malloc(argStackSize-OBJECT_OFFSET); - memcpy(params->orgParams, (void*)((uintptr_t)argStack + OBJECT_OFFSET), argStackSize - OBJECT_OFFSET); - } - size_t paramsSize = GetParamsSize(dg); - - params->newParams = (void **)malloc(paramsSize); - params->isChanged = (bool *)malloc(dg->params.size() * sizeof(bool)); - - for (unsigned int i = 0; i < dg->params.size(); i++) - { - *(void **)((intptr_t)params->newParams + GetParamOffset(params, i)) = NULL; - params->isChanged[i] = false; - } - - return params; -} - -HookReturnStruct *GetReturnStruct(DHooksCallback *dg) -{ - HookReturnStruct *res = new HookReturnStruct(); - res->isChanged = false; - res->type = dg->returnType; - res->orgResult = NULL; - res->newResult = NULL; - - if(g_SHPtr->GetOrigRet() && dg->post) - { - switch(dg->returnType) - { - case ReturnType_String: - res->orgResult = malloc(sizeof(string_t)); - res->newResult = malloc(sizeof(string_t)); - *(string_t *)res->orgResult = META_RESULT_ORIG_RET(string_t); - break; - case ReturnType_Int: - res->orgResult = malloc(sizeof(int)); - res->newResult = malloc(sizeof(int)); - *(int *)res->orgResult = META_RESULT_ORIG_RET(int); - break; - case ReturnType_Bool: - res->orgResult = malloc(sizeof(bool)); - res->newResult = malloc(sizeof(bool)); - *(bool *)res->orgResult = META_RESULT_ORIG_RET(bool); - break; - case ReturnType_Float: - res->orgResult = malloc(sizeof(float)); - res->newResult = malloc(sizeof(float)); - *(float *)res->orgResult = META_RESULT_ORIG_RET(float); - break; - case ReturnType_Vector: - { - res->orgResult = malloc(sizeof(SDKVector)); - res->newResult = malloc(sizeof(SDKVector)); - SDKVector vec = META_RESULT_ORIG_RET(SDKVector); - *(SDKVector *)res->orgResult = vec; - break; - } - default: - res->orgResult = META_RESULT_ORIG_RET(void *); - break; - } - } - else - { - switch(dg->returnType) - { - case ReturnType_String: - res->orgResult = malloc(sizeof(string_t)); - res->newResult = malloc(sizeof(string_t)); - *(string_t *)res->orgResult = NULL_STRING; - break; - case ReturnType_Vector: - res->orgResult = malloc(sizeof(SDKVector)); - res->newResult = malloc(sizeof(SDKVector)); - *(SDKVector *)res->orgResult = SDKVector(); - break; - case ReturnType_Int: - res->orgResult = malloc(sizeof(int)); - res->newResult = malloc(sizeof(int)); - *(int *)res->orgResult = 0; - break; - case ReturnType_Bool: - res->orgResult = malloc(sizeof(bool)); - res->newResult = malloc(sizeof(bool)); - *(bool *)res->orgResult = false; - break; - case ReturnType_Float: - res->orgResult = malloc(sizeof(float)); - res->newResult = malloc(sizeof(float)); - *(float *)res->orgResult = 0.0; - break; - } - } - - return res; -} - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) -void *Callback(DHooksCallback *dg, void **argStack, size_t *argsizep) -#else -void *Callback(DHooksCallback *dg, void **argStack) -#endif -{ - HookReturnStruct *returnStruct = NULL; - HookParamsStruct *paramStruct = NULL; - Handle_t rHndl; - Handle_t pHndl; - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - *argsizep = GetStackArgsSize(dg); -#else - size_t argsize = GetStackArgsSize(dg); -#endif - //g_pSM->LogMessage(myself, "[DEFAULT]DHooksCallback(%p) argStack(%p) - argsize(%d)", dg, argStack, argsize); - - if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address) - { - auto thisAddr = g_SHPtr->GetIfacePtr(); - if (dg->thisType == ThisPointer_CBaseEntity) { - if (thisAddr == nullptr) { - dg->plugin_callback->PushCell(-1); - } else { - dg->plugin_callback->PushCell(gamehelpers->EntityToBCompatRef((CBaseEntity *)thisAddr)); - } - } else { - if (dg->int64_address) { - std::int64_t addr = reinterpret_cast(thisAddr); - dg->plugin_callback->PushArray(reinterpret_cast(&addr), 2); - } else { - dg->plugin_callback->PushCell((cell_t)thisAddr); - } - } - } - if(dg->returnType != ReturnType_Void) - { - returnStruct = GetReturnStruct(dg); - rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - if(!rHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(rHndl); - } - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - if(*argsizep > 0) - { - paramStruct = GetParamStruct(dg, argStack, *argsizep); -#else - if(argsize > 0) - { - paramStruct = GetParamStruct(dg, argStack, argsize); -#endif - pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - if(!pHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - handlesys->FreeHandle(rHndl, &sec); - } - if(paramStruct) - { - delete paramStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(pHndl); - } - cell_t result = (cell_t)MRES_Ignored; - META_RES mres = MRES_IGNORED; - - dg->plugin_callback->Execute(&result); - - void *ret = g_SHPtr->GetOverrideRetPtr(); - switch((MRESReturn)result) - { - case MRES_Handled: - case MRES_ChangedHandled: - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - ret = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_ChangedOverride: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool) - { - ret = *(void **)returnStruct->newResult; - } - else - { - ret = returnStruct->newResult; - } - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - break; - } - } - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_Override: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_OVERRIDE); - mres = MRES_OVERRIDE; - if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool) - { - ret = *(void **)returnStruct->newResult; - } - else - { - ret = returnStruct->newResult; - } - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - case MRES_Supercede: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool) - { - ret = *(void **)returnStruct->newResult; - } - else - { - ret = returnStruct->newResult; - } - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - else - { - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - } - break; - default: - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - break; - } - - HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - - if(returnStruct) - { - handlesys->FreeHandle(rHndl, &sec); - } - if(paramStruct) - { - handlesys->FreeHandle(pHndl, &sec); - } - - if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED) - { - return NULL; - } - return ret; -} -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) -float Callback_float(DHooksCallback *dg, void **argStack, size_t *argsizep) -#else -float Callback_float(DHooksCallback *dg, void **argStack) -#endif -{ - HookReturnStruct *returnStruct = NULL; - HookParamsStruct *paramStruct = NULL; - Handle_t rHndl; - Handle_t pHndl; - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - *argsizep = GetStackArgsSize(dg); -#else - size_t argsize = GetStackArgsSize(dg); -#endif - //g_pSM->LogMessage(myself, "[FLOAT]DHooksCallback(%p) argStack(%p) - argsize(%d)", dg, argStack, argsize); - - if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address) - { - auto thisAddr = g_SHPtr->GetIfacePtr(); - if (dg->thisType == ThisPointer_CBaseEntity) { - if (thisAddr == nullptr) { - dg->plugin_callback->PushCell(-1); - } else { - dg->plugin_callback->PushCell(gamehelpers->EntityToBCompatRef((CBaseEntity *)thisAddr)); - } - } else { - if (dg->int64_address) { - std::int64_t addr = reinterpret_cast(thisAddr); - dg->plugin_callback->PushArray(reinterpret_cast(&addr), 2); - } else { - dg->plugin_callback->PushCell((cell_t)thisAddr); - } - } - } - - returnStruct = GetReturnStruct(dg); - rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - - if(!rHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return 0.0; - } - dg->plugin_callback->PushCell(rHndl); - - #if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - if(*argsizep > 0) - { - paramStruct = GetParamStruct(dg, argStack, *argsizep); - #else - if(argsize > 0) - { - paramStruct = GetParamStruct(dg, argStack, argsize); - #endif - pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - if(!pHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - if(paramStruct) - { - delete paramStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return 0.0; - } - dg->plugin_callback->PushCell(pHndl); - } - cell_t result = (cell_t)MRES_Ignored; - META_RES mres = MRES_IGNORED; - dg->plugin_callback->Execute(&result); - - void *ret = g_SHPtr->GetOverrideRetPtr(); - switch((MRESReturn)result) - { - case MRES_Handled: - case MRES_ChangedHandled: - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *(float *)ret = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_ChangedOverride: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - *(float *)ret = *(float *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - break; - } - } - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_Override: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_OVERRIDE); - mres = MRES_OVERRIDE; - *(float *)ret = *(float *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - case MRES_Supercede: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *(float *)ret = *(float *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - default: - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - break; - } - - HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - - if(returnStruct) - { - handlesys->FreeHandle(rHndl, &sec); - } - if(paramStruct) - { - handlesys->FreeHandle(pHndl, &sec); - } - - if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED) - { - return 0.0; - } - return *(float *)ret; -} -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) -SDKVector *Callback_vector(DHooksCallback *dg, void **argStack, size_t *argsizep) -#else -SDKVector *Callback_vector(DHooksCallback *dg, void **argStack) -#endif -{ - SDKVector *vec_result = (SDKVector *)argStack[0]; - - HookReturnStruct *returnStruct = NULL; - HookParamsStruct *paramStruct = NULL; - Handle_t rHndl; - Handle_t pHndl; - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - *argsizep = GetStackArgsSize(dg); -#else - size_t argsize = GetStackArgsSize(dg); -#endif - //g_pSM->LogMessage(myself, "[VECTOR]DHooksCallback(%p) argStack(%p) - argsize(%d) - params count %d", dg, argStack, argsize, dg->params.size()); - - if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address) - { - auto thisAddr = g_SHPtr->GetIfacePtr(); - if (dg->thisType == ThisPointer_CBaseEntity) { - if (thisAddr == nullptr) { - dg->plugin_callback->PushCell(-1); - } else { - dg->plugin_callback->PushCell(gamehelpers->EntityToBCompatRef((CBaseEntity *)thisAddr)); - } - } else { - if (dg->int64_address) { - std::int64_t addr = reinterpret_cast(thisAddr); - dg->plugin_callback->PushArray(reinterpret_cast(&addr), 2); - } else { - dg->plugin_callback->PushCell((cell_t)thisAddr); - } - } - } - - returnStruct = GetReturnStruct(dg); - rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - - if(!rHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(rHndl); - - #if defined( WIN32 ) && !defined( KE_ARCH_X64 ) - if(*argsizep > 0) - { - paramStruct = GetParamStruct(dg, argStack, *argsizep); - #else - if(argsize > 0) - { - paramStruct = GetParamStruct(dg, argStack, argsize); - #endif - pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - if(!pHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - if(paramStruct) - { - delete paramStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(pHndl); - } - cell_t result = (cell_t)MRES_Ignored; - META_RES mres = MRES_IGNORED; - dg->plugin_callback->Execute(&result); - - void *ret = g_SHPtr->GetOverrideRetPtr(); - ret = vec_result; - switch((MRESReturn)result) - { - case MRES_Handled: - case MRES_ChangedHandled: - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *vec_result = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_ChangedOverride: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - *vec_result = *(SDKVector *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - break; - } - } - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_Override: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_OVERRIDE); - mres = MRES_OVERRIDE; - *vec_result = *(SDKVector *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - case MRES_Supercede: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *vec_result = *(SDKVector *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - default: - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - break; - } - - HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - - if(returnStruct) - { - handlesys->FreeHandle(rHndl, &sec); - } - if(paramStruct) - { - handlesys->FreeHandle(pHndl, &sec); - } - - if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED) - { - vec_result->x = 0; - vec_result->y = 0; - vec_result->z = 0; - return vec_result; - } - return vec_result; -} - -#ifndef WIN32 -string_t *Callback_stringt(DHooksCallback *dg, void **argStack) -{ - string_t *string_result = (string_t *)argStack[0]; // Save the result - - HookReturnStruct *returnStruct = NULL; - HookParamsStruct *paramStruct = NULL; - Handle_t rHndl; - Handle_t pHndl; - - size_t argsize = GetStackArgsSize(dg); - - if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address) - { - auto thisAddr = g_SHPtr->GetIfacePtr(); - if (dg->thisType == ThisPointer_CBaseEntity) { - if (thisAddr == nullptr) { - dg->plugin_callback->PushCell(-1); - } else { - dg->plugin_callback->PushCell(gamehelpers->EntityToBCompatRef((CBaseEntity *)thisAddr)); - } - } else { - if (dg->int64_address) { - std::int64_t addr = reinterpret_cast(thisAddr); - dg->plugin_callback->PushArray(reinterpret_cast(&addr), 2); - } else { - dg->plugin_callback->PushCell((cell_t)thisAddr); - } - } - } - - returnStruct = GetReturnStruct(dg); - rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - - if(!rHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(rHndl); - - if(argsize > 0) - { - paramStruct = GetParamStruct(dg, argStack, argsize); - pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL); - if(!pHndl) - { - dg->plugin_callback->Cancel(); - if(returnStruct) - { - delete returnStruct; - } - if(paramStruct) - { - delete paramStruct; - } - g_SHPtr->SetRes(MRES_IGNORED); - return NULL; - } - dg->plugin_callback->PushCell(pHndl); - } - cell_t result = (cell_t)MRES_Ignored; - META_RES mres = MRES_IGNORED; - dg->plugin_callback->Execute(&result); - - void *ret = g_SHPtr->GetOverrideRetPtr(); - ret = string_result; - switch((MRESReturn)result) - { - case MRES_Handled: - case MRES_ChangedHandled: - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *string_result = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_ChangedOverride: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - *string_result = *(string_t *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - break; - } - } - g_SHPtr->DoRecall(); - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); - break; - case MRES_Override: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_OVERRIDE); - mres = MRES_OVERRIDE; - *string_result = *(string_t *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - case MRES_Supercede: - if(dg->returnType != ReturnType_Void) - { - if(returnStruct->isChanged) - { - g_SHPtr->SetRes(MRES_SUPERCEDE); - mres = MRES_SUPERCEDE; - *string_result = *(string_t *)returnStruct->newResult; - } - else //Throw an error if no override was set - { - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set"); - } - } - break; - default: - g_SHPtr->SetRes(MRES_IGNORED); - mres = MRES_IGNORED; - break; - } - - HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); - - if(returnStruct) - { - handlesys->FreeHandle(rHndl, &sec); - } - if(paramStruct) - { - handlesys->FreeHandle(pHndl, &sec); - } - - if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED) - { - *string_result = NULL_STRING; - return string_result; - } - return string_result; -} -#endif diff --git a/extensions/dhooks/vhook.h b/extensions/dhooks/vhook.h deleted file mode 100644 index fc095047ad..0000000000 --- a/extensions/dhooks/vhook.h +++ /dev/null @@ -1,347 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Dynamic Hooks Extension - * Copyright (C) 2012-2021 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_VHOOK_H_ -#define _INCLUDE_VHOOK_H_ - -#include "extension.h" -#include -#include -#include -#include -#include - -#ifdef KE_ARCH_X64 -#include "sh_asm_x86_64.h" -#endif - -enum CallingConvention -{ - CallConv_CDECL, - CallConv_THISCALL, - CallConv_STDCALL, - CallConv_FASTCALL, -}; - -enum MRESReturn -{ - MRES_ChangedHandled = -2, // Use changed values and return MRES_Handled - MRES_ChangedOverride, // Use changed values and return MRES_Override - MRES_Ignored, // plugin didn't take any action - MRES_Handled, // plugin did something, but real function should still be called - MRES_Override, // call real function, but use my return value - MRES_Supercede // skip real function; use my return value -}; - -enum ObjectValueType -{ - ObjectValueType_Int = 0, - ObjectValueType_Bool, - ObjectValueType_Ehandle, - ObjectValueType_Float, - ObjectValueType_CBaseEntityPtr, - ObjectValueType_IntPtr, - ObjectValueType_BoolPtr, - ObjectValueType_EhandlePtr, - ObjectValueType_FloatPtr, - ObjectValueType_Vector, - ObjectValueType_VectorPtr, - ObjectValueType_CharPtr, - ObjectValueType_String -}; - -enum HookParamType -{ - HookParamType_Unknown, - HookParamType_Int, - HookParamType_Bool, - HookParamType_Float, - HookParamType_String, - HookParamType_StringPtr, - HookParamType_CharPtr, - HookParamType_VectorPtr, - HookParamType_CBaseEntity, - HookParamType_ObjectPtr, - HookParamType_Edict, - HookParamType_Object -}; - -enum ReturnType -{ - ReturnType_Unknown, - ReturnType_Void, - ReturnType_Int, - ReturnType_Bool, - ReturnType_Float, - ReturnType_String, - ReturnType_StringPtr, - ReturnType_CharPtr, - ReturnType_Vector, - ReturnType_VectorPtr, - ReturnType_CBaseEntity, - ReturnType_Edict -}; - -enum ThisPointerType -{ - ThisPointer_Ignore, - ThisPointer_CBaseEntity, - ThisPointer_Address -}; - -enum HookType -{ - HookType_Entity, - HookType_GameRules, - HookType_Raw -}; - -struct ParamInfo -{ - HookParamType type; - size_t size; - unsigned int flags; - SourceHook::PassInfo::PassType pass_type; - Register_t custom_register; -}; - -#ifdef WIN32 -#define OBJECT_OFFSET sizeof(void *) -#else -#define OBJECT_OFFSET (sizeof(void *)*2) -#endif - -class HookReturnStruct -{ -public: - ~HookReturnStruct(); -public: - ReturnType type; - bool isChanged; - void *orgResult; - void *newResult; -}; - -class DHooksInfo -{ -public: - SourceHook::CVector params; - int offset; - unsigned int returnFlag; - ReturnType returnType; - bool post; - IPluginFunction *plugin_callback; - bool int64_address; - int entity; - ThisPointerType thisType; - HookType hookType; - CallingConvention thisFuncCallConv; -}; - -class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo -{ -public: - DHooksCallback() - { - //g_pSM->LogMessage(myself, "DHooksCallback(%p)", this); - } - - virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;}; - virtual void DeleteThis() - { - *(void ***)this = this->oldvtable; -#ifdef KE_ARCH_X64 - delete callThunk; -#else - g_pSM->GetScriptingEngine()->FreePageMemory(this->newvtable[2]); -#endif - delete this->newvtable; - delete this; - }; - virtual void Call() {}; -public: - void **newvtable; - void **oldvtable; -#ifdef KE_ARCH_X64 - SourceHook::Asm::x64JitWriter* callThunk; -#endif -}; - -#if defined( WIN32 ) && !defined( KE_ARCH_X64 ) -void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep); -float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep); -SDKVector *Callback_vector(DHooksCallback *dg, void **stack, size_t *argsizep); -#else -void *Callback(DHooksCallback *dg, void **stack); -float Callback_float(DHooksCallback *dg, void **stack); -SDKVector *Callback_vector(DHooksCallback *dg, void **stack); -string_t *Callback_stringt(DHooksCallback *dg, void **stack); -#endif - -bool SetupHookManager(ISmmAPI *ismm); -void CleanupHooks(IPluginContext *pContext = NULL); -size_t GetParamTypeSize(HookParamType type); -SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type); - -class HookParamsStruct -{ -public: - HookParamsStruct() - { - this->orgParams = NULL; - this->newParams = NULL; - this->dg = NULL; - this->isChanged = NULL; - } - ~HookParamsStruct(); -public: - void **orgParams; - void **newParams; - bool *isChanged; - DHooksInfo *dg; -}; - -enum HookMethod { - Virtual, - Detour -}; - -class HookSetup -{ -public: - HookSetup(ReturnType returnType, unsigned int returnFlag, HookType hookType, ThisPointerType thisType, int offset, IPluginFunction *callback) - { - this->returnType = returnType; - this->returnFlag = returnFlag; - this->hookType = hookType; - this->callConv = CallConv_THISCALL; - this->thisType = thisType; - this->offset = offset; - this->funcAddr = nullptr; - this->callback = callback; - this->hookMethod = Virtual; - }; - HookSetup(ReturnType returnType, unsigned int returnFlag, CallingConvention callConv, ThisPointerType thisType, void *funcAddr) - { - this->returnType = returnType; - this->returnFlag = returnFlag; - this->hookType = HookType_Raw; - this->callConv = callConv; - this->thisType = thisType; - this->offset = -1; - this->funcAddr = funcAddr; - this->callback = nullptr; - this->hookMethod = Detour; - }; - ~HookSetup(){}; - - bool IsVirtual() - { - return this->offset != -1; - } -public: - unsigned int returnFlag; - ReturnType returnType; - HookType hookType; - CallingConvention callConv; - ThisPointerType thisType; - SourceHook::CVector params; - int offset; - void *funcAddr; - IPluginFunction *callback; - HookMethod hookMethod; -}; - -#ifdef KE_ARCH_X64 -SourceHook::Asm::x64JitWriter* GenerateThunk(HookSetup* type); -static DHooksCallback *MakeHandler(HookSetup* hook) -{ - DHooksCallback *dg = new DHooksCallback(); - dg->returnType = hook->returnType; - dg->oldvtable = *(void ***)dg; - dg->newvtable = new void *[3]; - dg->newvtable[0] = dg->oldvtable[0]; - dg->newvtable[1] = dg->oldvtable[1]; - dg->callThunk = GenerateThunk(hook); - dg->newvtable[2] = dg->callThunk->GetData(); - *(void ***)dg = dg->newvtable; - return dg; -} -#else -void *GenerateThunk(HookSetup* type); -static DHooksCallback *MakeHandler(HookSetup* hook) -{ - DHooksCallback *dg = new DHooksCallback(); - dg->returnType = hook->returnType; - dg->oldvtable = *(void ***)dg; - dg->newvtable = new void *[3]; - dg->newvtable[0] = dg->oldvtable[0]; - dg->newvtable[1] = dg->oldvtable[1]; - dg->newvtable[2] = GenerateThunk(hook); - *(void ***)dg = dg->newvtable; - return dg; -} -#endif - -class DHooksManager -{ -public: - DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, IPluginFunction *plugincb, bool post); - ~DHooksManager() - { - if(this->hookid) - { - g_SHPtr->RemoveHookByID(this->hookid); - if(this->remove_callback) - { - this->remove_callback->PushCell(this->hookid); - this->remove_callback->Execute(NULL); - } - if(this->pManager) - { - g_pHookManager->ReleaseHookMan(this->pManager); - } - } - } -public: - intptr_t addr; - int hookid; - DHooksCallback *callback; - IPluginFunction *remove_callback; - SourceHook::HookManagerPubFunc pManager; -}; - -size_t GetStackArgsSize(DHooksCallback *dg); - -extern IBinTools *g_pBinTools; -extern HandleType_t g_HookParamsHandle; -extern HandleType_t g_HookReturnHandle; -#endif diff --git a/extensions/mysql/mysql/MyDriver.cpp b/extensions/mysql/mysql/MyDriver.cpp index f30dce49f0..f93eeab1a1 100644 --- a/extensions/mysql/mysql/MyDriver.cpp +++ b/extensions/mysql/mysql/MyDriver.cpp @@ -41,10 +41,9 @@ MyDriver::MyDriver() m_MyHandle = BAD_HANDLE; } -void CloseDBList(List &l) +void CloseDBList(std::list &l) { - List::iterator iter; - for (iter=l.begin(); iter!=l.end(); iter++) + for (auto iter=l.begin(); iter!=l.end(); iter++) { MyDatabase *db = (*iter); while (!db->Close()) @@ -57,7 +56,6 @@ void CloseDBList(List &l) void MyDriver::Shutdown() { - List::iterator iter; CloseDBList(m_PermDbs); if (m_MyHandle != BAD_HANDLE) @@ -165,8 +163,7 @@ IDatabase *MyDriver::Connect(const DatabaseInfo *info, bool persistent, char *er if (persistent) { /* Try to find a matching persistent connection */ - List::iterator iter; - for (iter=m_PermDbs.begin(); + for (auto iter=m_PermDbs.begin(); iter!=m_PermDbs.end(); iter++) { diff --git a/extensions/mysql/mysql/MyDriver.h b/extensions/mysql/mysql/MyDriver.h index 86c9dfa603..bb035b15dd 100644 --- a/extensions/mysql/mysql/MyDriver.h +++ b/extensions/mysql/mysql/MyDriver.h @@ -51,13 +51,11 @@ # undef max #endif -#include -#include - +#include +#include #include using namespace SourceMod; -using namespace SourceHook; #define M_CLIENT_MULTI_RESULTS ((1) << 17) /* Enable/disable multi-results */ @@ -82,8 +80,8 @@ class MyDriver : public IDBDriver private: std::mutex m_Lock; Handle_t m_MyHandle; - List m_TempDbs; - List m_PermDbs; + std::list m_TempDbs; + std::list m_PermDbs; }; extern MyDriver g_MyDriver; diff --git a/extensions/pgsql/pgsql/PgDatabase.h b/extensions/pgsql/pgsql/PgDatabase.h index 908577c450..76bf5d7324 100644 --- a/extensions/pgsql/pgsql/PgDatabase.h +++ b/extensions/pgsql/pgsql/PgDatabase.h @@ -34,6 +34,7 @@ #include #include +#include #include "PgDriver.h" class PgQuery; @@ -81,10 +82,10 @@ class PgDatabase /* ---------- */ DatabaseInfo m_Info; - String m_Host; - String m_Database; - String m_User; - String m_Pass; + std::string m_Host; + std::string m_Database; + std::string m_User; + std::string m_Pass; bool m_bPersistent; }; diff --git a/extensions/pgsql/pgsql/PgDriver.cpp b/extensions/pgsql/pgsql/PgDriver.cpp index cda7aceb14..62979805eb 100644 --- a/extensions/pgsql/pgsql/PgDriver.cpp +++ b/extensions/pgsql/pgsql/PgDriver.cpp @@ -40,10 +40,9 @@ PgDriver::PgDriver() m_Handle = BAD_HANDLE; } -void CloseDBList(List &l) +void CloseDBList(std::list &l) { - List::iterator iter; - for (iter=l.begin(); iter!=l.end(); iter++) + for (auto iter=l.begin(); iter!=l.end(); iter++) { PgDatabase *db = (*iter); while (!db->Close()) @@ -56,7 +55,6 @@ void CloseDBList(List &l) void PgDriver::Shutdown() { - List::iterator iter; CloseDBList(m_PermDbs); if (m_Handle != BAD_HANDLE) @@ -161,8 +159,7 @@ IDatabase *PgDriver::Connect(const DatabaseInfo *info, bool persistent, char *er if (persistent) { /* Try to find a matching persistent connection */ - List::iterator iter; - for (iter=m_PermDbs.begin(); + for (auto iter=m_PermDbs.begin(); iter!=m_PermDbs.end(); iter++) { diff --git a/extensions/pgsql/pgsql/PgDriver.h b/extensions/pgsql/pgsql/PgDriver.h index 5a59fe012a..83f946011c 100644 --- a/extensions/pgsql/pgsql/PgDriver.h +++ b/extensions/pgsql/pgsql/PgDriver.h @@ -41,13 +41,10 @@ #include -#include -#include - #include +#include using namespace SourceMod; -using namespace SourceHook; #define M_CLIENT_MULTI_RESULTS ((1) << 17) /* Enable/disable multi-results */ @@ -72,7 +69,7 @@ class PgDriver : public IDBDriver private: std::mutex m_Lock; Handle_t m_Handle; - List m_PermDbs; + std::list m_PermDbs; }; extern PgDriver g_PgDriver; diff --git a/extensions/regex/extension.cpp b/extensions/regex/extension.cpp index 0483dba5b3..bf082f4770 100644 --- a/extensions/regex/extension.cpp +++ b/extensions/regex/extension.cpp @@ -31,11 +31,10 @@ #include #include "extension.h" -#include +#include #include "pcre.h" #include "posix_map.h" #include "CRegEx.h" -using namespace SourceHook; /** * @file extension.cpp diff --git a/extensions/sdkhooks/extension.cpp b/extensions/sdkhooks/extension.cpp index 3a457fb51c..eacaacbd21 100644 --- a/extensions/sdkhooks/extension.cpp +++ b/extensions/sdkhooks/extension.cpp @@ -48,58 +48,60 @@ // Order MUST match SDKHookType enum HookTypeData g_HookTypes[SDKHook_MAXHOOKS] = { -// Hook name DT required Supported (always false til later) - {"EndTouch", "", false}, - {"FireBulletsPost", "", false}, - {"OnTakeDamage", "", false}, - {"OnTakeDamagePost", "", false}, - {"PreThink", "DT_BasePlayer", false}, - {"PostThink", "DT_BasePlayer", false}, - {"SetTransmit", "", false}, - {"Spawn", "", false}, - {"StartTouch", "", false}, - {"Think", "", false}, - {"Touch", "", false}, - {"TraceAttack", "", false}, - {"TraceAttackPost", "", false}, - {"WeaponCanSwitchTo", "DT_BaseCombatCharacter", false}, - {"WeaponCanUse", "DT_BaseCombatCharacter", false}, - {"WeaponDrop", "DT_BaseCombatCharacter", false}, - {"WeaponEquip", "DT_BaseCombatCharacter", false}, - {"WeaponSwitch", "DT_BaseCombatCharacter", false}, - {"ShouldCollide", "", false}, - {"PreThinkPost", "DT_BasePlayer", false}, - {"PostThinkPost", "DT_BasePlayer", false}, - {"ThinkPost", "", false}, - {"EndTouchPost", "", false}, - {"GroundEntChangedPost", "", false}, - {"SpawnPost", "", false}, - {"StartTouchPost", "", false}, - {"TouchPost", "", false}, - {"VPhysicsUpdate", "", false}, - {"VPhysicsUpdatePost", "", false}, - {"WeaponCanSwitchToPost", "DT_BaseCombatCharacter", false}, - {"WeaponCanUsePost", "DT_BaseCombatCharacter", false}, - {"WeaponDropPost", "DT_BaseCombatCharacter", false}, - {"WeaponEquipPost", "DT_BaseCombatCharacter", false}, - {"WeaponSwitchPost", "DT_BaseCombatCharacter", false}, - {"Use", "", false}, - {"UsePost", "", false}, - {"Reload", "DT_BaseCombatWeapon", false}, - {"ReloadPost", "DT_BaseCombatWeapon", false}, - {"GetMaxHealth", "", false}, - {"Blocked", "", false}, - {"BlockedPost", "", false}, - {"OnTakeDamageAlive", "DT_BaseCombatCharacter", false}, - {"OnTakeDamageAlivePost", "DT_BaseCombatCharacter", false}, +// Hook name DT required Supported (always false til later) Vtable Offset + {"EndTouch", "", false, 0}, + {"FireBulletsPost", "", false, 0}, + {"OnTakeDamage", "", false, 0}, + {"OnTakeDamagePost", "", false, 0}, + {"PreThink", "DT_BasePlayer", false, 0}, + {"PostThink", "DT_BasePlayer", false, 0}, + {"SetTransmit", "", false, 0}, + {"Spawn", "", false, 0}, + {"StartTouch", "", false, 0}, + {"Think", "", false, 0}, + {"Touch", "", false, 0}, + {"TraceAttack", "", false, 0}, + {"TraceAttackPost", "", false, 0}, + {"WeaponCanSwitchTo", "DT_BaseCombatCharacter", false, 0}, + {"WeaponCanUse", "DT_BaseCombatCharacter", false, 0}, + {"WeaponDrop", "DT_BaseCombatCharacter", false, 0}, + {"WeaponEquip", "DT_BaseCombatCharacter", false, 0}, + {"WeaponSwitch", "DT_BaseCombatCharacter", false, 0}, + {"ShouldCollide", "", false, 0}, + {"PreThinkPost", "DT_BasePlayer", false, 0}, + {"PostThinkPost", "DT_BasePlayer", false, 0}, + {"ThinkPost", "", false, 0}, + {"EndTouchPost", "", false, 0}, + {"GroundEntChangedPost", "", false, 0}, + {"SpawnPost", "", false, 0}, + {"StartTouchPost", "", false, 0}, + {"TouchPost", "", false, 0}, + {"VPhysicsUpdate", "", false, 0}, + {"VPhysicsUpdatePost", "", false, 0}, + {"WeaponCanSwitchToPost", "DT_BaseCombatCharacter", false, 0}, + {"WeaponCanUsePost", "DT_BaseCombatCharacter", false, 0}, + {"WeaponDropPost", "DT_BaseCombatCharacter", false, 0}, + {"WeaponEquipPost", "DT_BaseCombatCharacter", false, 0}, + {"WeaponSwitchPost", "DT_BaseCombatCharacter", false, 0}, + {"Use", "", false, 0}, + {"UsePost", "", false, 0}, + {"Reload", "DT_BaseCombatWeapon", false, 0}, + {"ReloadPost", "DT_BaseCombatWeapon", false, 0}, + {"GetMaxHealth", "", false, 0}, + {"Blocked", "", false, 0}, + {"BlockedPost", "", false, 0}, + {"OnTakeDamageAlive", "DT_BaseCombatCharacter", false, 0}, + {"OnTakeDamageAlivePost", "DT_BaseCombatCharacter", false, 0}, // There is no DT for CBaseMultiplayerPlayer. Going up a level - {"CanBeAutobalanced", "DT_BasePlayer", false}, + {"CanBeAutobalanced", "DT_BasePlayer", false, 0}, }; SDKHooks g_Interface; SMEXT_LINK(&g_Interface); +unsigned int g_hookOffset[SDKHook_MAXHOOKS]; + CGlobalVars *gpGlobals; std::vector g_HookList[SDKHook_MAXHOOKS]; @@ -115,11 +117,9 @@ IForward *g_pOnEntityCreated = NULL; IForward *g_pOnEntityDestroyed = NULL; #ifdef GAMEDESC_CAN_CHANGE -int g_hookOnGetGameDescription = 0; IForward *g_pOnGetGameNameDescription = NULL; #endif -int g_hookOnLevelInit = 0; IForward *g_pOnLevelInit = NULL; IGameConfig *g_pGameConf = NULL; @@ -147,52 +147,13 @@ CUtlVector *EntListeners() return NULL; } - -/** - * IServerGameDLL & IVEngineServer Hooks - */ -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, const char *, const char *, const char *, const char *, bool, bool); +SDKHooks::SDKHooks() : + m_HookLevelShutdown(&IServerGameDLL::LevelShutdown, this, &SDKHooks::LevelShutdown, nullptr), #ifdef GAMEDESC_CAN_CHANGE -SH_DECL_HOOK0(IServerGameDLL, GetGameDescription, SH_NOATTRIB, 0, const char *); -#endif - -/** - * CBaseEntity Hooks - */ -SH_DECL_MANUALHOOK1_void(EndTouch, 0, 0, 0, CBaseEntity *); -SH_DECL_MANUALHOOK1_void(FireBullets, 0, 0, 0, FireBulletsInfo_t const&); -#ifdef GETMAXHEALTH_IS_VIRTUAL -SH_DECL_MANUALHOOK0(GetMaxHealth, 0, 0, 0, int); + m_HookGetGameDescription(&IServerGameDLL::GetGameDescription, this, &SDKHooks::Hook_GetGameDescription, nullptr), #endif -SH_DECL_MANUALHOOK1_void(GroundEntChanged, 0, 0, 0, void *); -SH_DECL_MANUALHOOK1(OnTakeDamage, 0, 0, 0, int, CTakeDamageInfoHack &); -SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, int, CTakeDamageInfoHack &); -SH_DECL_MANUALHOOK0_void(PreThink, 0, 0, 0); -SH_DECL_MANUALHOOK0_void(PostThink, 0, 0, 0); -SH_DECL_MANUALHOOK0(Reload, 0, 0, 0, bool); -SH_DECL_MANUALHOOK2_void(SetTransmit, 0, 0, 0, CCheckTransmitInfo *, bool); -SH_DECL_MANUALHOOK2(ShouldCollide, 0, 0, 0, bool, int, int); -SH_DECL_MANUALHOOK0_void(Spawn, 0, 0, 0); -SH_DECL_MANUALHOOK1_void(StartTouch, 0, 0, 0, CBaseEntity *); -SH_DECL_MANUALHOOK0_void(Think, 0, 0, 0); -SH_DECL_MANUALHOOK1_void(Touch, 0, 0, 0, CBaseEntity *); -#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ - || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_PVKII -SH_DECL_MANUALHOOK4_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *, CDmgAccumulator *); -#else -SH_DECL_MANUALHOOK3_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *); -#endif -SH_DECL_MANUALHOOK4_void(Use, 0, 0, 0, CBaseEntity *, CBaseEntity *, USE_TYPE, float); -SH_DECL_MANUALHOOK1_void(VPhysicsUpdate, 0, 0, 0, IPhysicsObject *); -SH_DECL_MANUALHOOK1(Weapon_CanSwitchTo, 0, 0, 0, bool, CBaseCombatWeapon *); -SH_DECL_MANUALHOOK1(Weapon_CanUse, 0, 0, 0, bool, CBaseCombatWeapon *); -SH_DECL_MANUALHOOK3_void(Weapon_Drop, 0, 0, 0, CBaseCombatWeapon *, const Vector *, const Vector *); -SH_DECL_MANUALHOOK1_void(Weapon_Equip, 0, 0, 0, CBaseCombatWeapon *); -SH_DECL_MANUALHOOK2(Weapon_Switch, 0, 0, 0, bool, CBaseCombatWeapon *, int); -SH_DECL_MANUALHOOK1_void(Blocked, 0, 0, 0, CBaseEntity *); -SH_DECL_MANUALHOOK0(CanBeAutobalanced, 0, 0, 0, bool); - + m_HookLevelInit(&IServerGameDLL::LevelInit, this, &SDKHooks::Hook_LevelInit, nullptr) +{} /** * Forwards @@ -248,7 +209,7 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late) sharesys->AddCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD"); sharesys->AddCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport"); - SH_ADD_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SDKHooks::LevelShutdown), false); + m_HookLevelShutdown.Add(gamedll); playerhelpers->AddClientListener(&g_Interface); @@ -293,20 +254,6 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late) return true; } -inline void HookLevelInit() -{ - assert(g_hookOnLevelInit == 0); - g_hookOnLevelInit = SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_LevelInit), false); -} - -#ifdef GAMEDESC_CAN_CHANGE -inline void HookGetGameDescription() -{ - assert(g_hookOnGetGameDescription == 0); - g_hookOnGetGameDescription = SH_ADD_HOOK(IServerGameDLL, GetGameDescription, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetGameDescription), false); -} -#endif - void SDKHooks::SDK_OnAllLoaded() { SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools); @@ -318,10 +265,10 @@ void SDKHooks::SDK_OnAllLoaded() } if (g_pOnLevelInit->GetFunctionCount() > 0) - HookLevelInit(); + m_HookLevelInit.Add(gamedll); #ifdef GAMEDESC_CAN_CHANGE if (g_pOnGetGameNameDescription->GetFunctionCount() > 0) - HookGetGameDescription(); + m_HookGetGameDescription.Add(gamedll); #endif } @@ -354,10 +301,10 @@ void SDKHooks::SDK_OnUnload() // Remove left over hooks Unhook(reinterpret_cast(NULL)); - KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit); + m_HookLevelInit.Remove(gamedll); #ifdef GAMEDESC_CAN_CHANGE - KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription); + m_HookGetGameDescription.Remove(gamedll); #endif forwards->ReleaseForward(g_pOnEntityCreated); @@ -369,7 +316,7 @@ void SDKHooks::SDK_OnUnload() plsys->RemovePluginsListener(&g_Interface); - SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SDKHooks::LevelShutdown), true); + m_HookLevelShutdown.Remove(gamedll); playerhelpers->RemoveClientListener(&g_Interface); @@ -412,12 +359,12 @@ const char *SDKHooks::GetExtensionDateString() void SDKHooks::OnPluginLoaded(IPlugin *plugin) { - if (g_pOnLevelInit->GetFunctionCount() > 0 && g_hookOnLevelInit == 0) - HookLevelInit(); + if (g_pOnLevelInit->GetFunctionCount() > 0) + m_HookLevelInit.Add(gamedll); #ifdef GAMEDESC_CAN_CHANGE - if (g_pOnGetGameNameDescription->GetFunctionCount() > 0 && g_hookOnGetGameDescription == 0) - HookGetGameDescription(); + if (g_pOnGetGameNameDescription->GetFunctionCount() > 0) + m_HookGetGameDescription.Add(gamedll); #endif } @@ -427,12 +374,12 @@ void SDKHooks::OnPluginUnloaded(IPlugin *plugin) if (g_pOnLevelInit->GetFunctionCount() == 0) { - KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit); + m_HookLevelInit.Remove(gamedll); } #ifdef GAMEDESC_CAN_CHANGE if (g_pOnGetGameNameDescription->GetFunctionCount() == 0) - KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription); + m_HookGetGameDescription.Remove(gamedll); #endif } @@ -450,7 +397,7 @@ void SDKHooks::OnClientDisconnecting(int client) HandleEntityDeleted(pEntity); } -void SDKHooks::LevelShutdown() +KHook::Return SDKHooks::LevelShutdown(IServerGameDLL*) { #if defined PLATFORM_LINUX for (size_t type = 0; type < SDKHook_MAXHOOKS; ++type) @@ -466,6 +413,7 @@ void SDKHooks::LevelShutdown() vtablehooklist.clear(); } #endif + return { KHook::Action::Ignore }; } void SDKHooks::AddEntityListener(ISMEntityListener *listener) @@ -521,11 +469,11 @@ cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther) { cell_t ret = Pl_Continue; - CVTableHook vhook(pEnt); + void** vtable = *(void***)pEnt; std::vector &vtablehooklist = g_HookList[type]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -592,7 +540,6 @@ void SDKHooks::SetupHooks() g_pGameConf->GetOffset("GroundEntChanged", &offset); if (offset > 0) { - SH_MANUALHOOK_RECONFIGURE(GroundEntChanged, offset, 0, 0); g_HookTypes[SDKHook_GroundEntChangedPost].supported = true; } @@ -625,13 +572,12 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac return HookRet_BadEntForHookType; } } - size_t entry; - CVTableHook vhook(pEnt); + void** vtable = *(void***)pEnt; std::vector &vtablehooklist = g_HookList[type]; for (entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook == vtablehooklist[entry]->vtablehook) + if (vtable == vtablehooklist[entry]->vtablehook->GetVTablePtr()) { break; } @@ -639,149 +585,279 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac if (entry == vtablehooklist.size()) { - int hookid = 0; + KHook::__Hook* khook = nullptr; switch(type) { - case SDKHook_EndTouch: - hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouch), false); + case SDKHook_EndTouch: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_EndTouch, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_EndTouchPost: - hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouchPost), true); + } + case SDKHook_EndTouchPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_EndTouchPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_FireBulletsPost: - hookid = SH_ADD_MANUALVPHOOK(FireBullets, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_FireBulletsPost), true); + } + case SDKHook_FireBulletsPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_FireBulletsPost); + local->AddGlobal(pEnt); + khook = local; break; + } #ifdef GETMAXHEALTH_IS_VIRTUAL - case SDKHook_GetMaxHealth: - hookid = SH_ADD_MANUALVPHOOK(GetMaxHealth, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetMaxHealth), false); + case SDKHook_GetMaxHealth: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_GetMaxHealth, nullptr); + local->AddGlobal(pEnt); + khook = local; break; + } #endif - case SDKHook_GroundEntChangedPost: - hookid = SH_ADD_MANUALVPHOOK(GroundEntChanged, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GroundEntChangedPost), true); + case SDKHook_GroundEntChangedPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_GroundEntChangedPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_OnTakeDamage: - hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage), false); + } + case SDKHook_OnTakeDamage: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_OnTakeDamage, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_OnTakeDamagePost: - hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamagePost), true); + } + case SDKHook_OnTakeDamagePost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_OnTakeDamagePost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_OnTakeDamage_Alive: - hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_Alive), false); + } + case SDKHook_OnTakeDamage_Alive: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_OnTakeDamage_Alive, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_OnTakeDamage_AlivePost: - hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_AlivePost), true); + } + case SDKHook_OnTakeDamage_AlivePost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_OnTakeDamage_AlivePost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_PreThink: - hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThink), false); + } + case SDKHook_PreThink: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_PreThink, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_PreThinkPost: - hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThinkPost), true); + } + case SDKHook_PreThinkPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_PreThinkPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_PostThink: - hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThink), false); + } + case SDKHook_PostThink: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_PostThink, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_PostThinkPost: - hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThinkPost), true); + } + case SDKHook_PostThinkPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_PostThinkPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Reload: - hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Reload), false); + } + case SDKHook_Reload: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Reload, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_ReloadPost: - hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ReloadPost), true); + } + case SDKHook_ReloadPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_ReloadPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_SetTransmit: - hookid = SH_ADD_MANUALVPHOOK(SetTransmit, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SetTransmit), false); + } + case SDKHook_SetTransmit: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_SetTransmit, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Spawn: - hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Spawn), false); + } + case SDKHook_Spawn: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Spawn, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_SpawnPost: - hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SpawnPost), true); + } + case SDKHook_SpawnPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_SpawnPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_StartTouch: - hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouch), false); + } + case SDKHook_StartTouch: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_StartTouch, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_StartTouchPost: - hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouchPost), true); + } + case SDKHook_StartTouchPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_StartTouchPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Think: - hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Think), false); + } + case SDKHook_Think: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Think, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_ThinkPost: - hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ThinkPost), true); + } + case SDKHook_ThinkPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_ThinkPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Touch: - hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Touch), false); + } + case SDKHook_Touch: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Touch, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_TouchPost: - hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TouchPost), true); + } + case SDKHook_TouchPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_TouchPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_TraceAttack: - hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttack), false); + } + case SDKHook_TraceAttack: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_TraceAttack, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_TraceAttackPost: - hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttackPost), true); + } + case SDKHook_TraceAttackPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_TraceAttackPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Use: - hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Use), false); + } + case SDKHook_Use: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Use, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_UsePost: - hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_UsePost), true); + } + case SDKHook_UsePost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_UsePost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_VPhysicsUpdate: - hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdate), false); + } + case SDKHook_VPhysicsUpdate: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_VPhysicsUpdate, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_VPhysicsUpdatePost: - hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdatePost), true); + } + case SDKHook_VPhysicsUpdatePost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_VPhysicsUpdatePost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponCanSwitchTo: - hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchTo), false); + } + case SDKHook_WeaponCanSwitchTo: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_WeaponCanSwitchTo, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponCanSwitchToPost: - hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchToPost), true); + } + case SDKHook_WeaponCanSwitchToPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_WeaponCanSwitchToPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponCanUse: - hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUse), false); + } + case SDKHook_WeaponCanUse: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_WeaponCanUse, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponCanUsePost: - hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUsePost), true); + } + case SDKHook_WeaponCanUsePost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_WeaponCanUsePost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponDrop: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDrop), false); + } + case SDKHook_WeaponDrop: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_WeaponDrop, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponDropPost: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDropPost), true); + } + case SDKHook_WeaponDropPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_WeaponDropPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponEquip: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquip), false); + } + case SDKHook_WeaponEquip: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_WeaponEquip, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponEquipPost: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquipPost), true); + } + case SDKHook_WeaponEquipPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_WeaponEquipPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponSwitch: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitch), false); + } + case SDKHook_WeaponSwitch: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_WeaponSwitch, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_WeaponSwitchPost: - hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitchPost), true); + } + case SDKHook_WeaponSwitchPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_WeaponSwitchPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_ShouldCollide: - hookid = SH_ADD_MANUALVPHOOK(ShouldCollide, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ShouldCollide), true); + } + case SDKHook_ShouldCollide: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_ShouldCollide); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_Blocked: - hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Blocked), false); + } + case SDKHook_Blocked: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_Blocked, nullptr); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_BlockedPost: - hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_BlockedPost), true); + } + case SDKHook_BlockedPost: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, nullptr, &SDKHooks::Hook_BlockedPost); + local->AddGlobal(pEnt); + khook = local; break; - case SDKHook_CanBeAutobalanced: - hookid = SH_ADD_MANUALVPHOOK(CanBeAutobalanced, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_CanBeAutobalanced), false); + } + case SDKHook_CanBeAutobalanced: { + auto local = new KHook::Virtual(g_HookTypes[type].offset, this, &SDKHooks::Hook_CanBeAutobalanced, nullptr); + local->AddGlobal(pEnt); + khook = local; break; + } } - vhook.SetHookID(hookid); - CVTableList *vtablelist = new CVTableList; - vtablelist->vtablehook = new CVTableHook(vhook); + vtablelist->vtablehook = new CVTableHook(vtable, khook); vtablehooklist.push_back(vtablelist); } @@ -790,7 +866,6 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac hook.entity = gamehelpers->EntityToBCompatRef(pEnt); hook.callback = callback; vtablehooklist[entry]->hooks.push_back(hook); - return HookRet_Successful; } @@ -870,11 +945,11 @@ void SDKHooks::Unhook(int entity, SDKHookType type, IPluginFunction *pCallback) return; } - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[type]; for (size_t listentry = 0; listentry < vtablehooklist.size(); ++listentry) { - if (vhook != vtablehooklist[listentry]->vtablehook) + if (vtable != vtablehooklist[listentry]->vtablehook->GetVTablePtr()) { continue; } @@ -936,55 +1011,56 @@ void SDKHooks::OnEntityCreated(CBaseEntity *pEntity) } #ifdef GAMEDESC_CAN_CHANGE -const char *SDKHooks::Hook_GetGameDescription() +KHook::Return SDKHooks::Hook_GetGameDescription(IServerGameDLL*) { static char szGameDesc[64]; cell_t result = Pl_Continue; g_pSM->Format(szGameDesc, sizeof(szGameDesc), "%s", - SH_CALL(gamedll, &IServerGameDLL::GetGameDescription)()); + KHook::Recall(&IServerGameDLL::GetGameDescription, { KHook::Action::Ignore, nullptr }, gamedll)); // Call OnGetGameDescription forward g_pOnGetGameNameDescription->PushStringEx(szGameDesc, sizeof(szGameDesc), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); g_pOnGetGameNameDescription->Execute(&result); if(result == Pl_Changed) - RETURN_META_VALUE(MRES_SUPERCEDE, szGameDesc); + return { KHook::Action::Supersede, szGameDesc }; - RETURN_META_VALUE(MRES_IGNORED, NULL); + return { KHook::Action::Ignore }; } #endif -bool SDKHooks::Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) +KHook::Return SDKHooks::Hook_LevelInit(IServerGameDLL*, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { // Call OnLevelInit forward g_pOnLevelInit->PushString(pMapName); g_pOnLevelInit->PushString(""); g_pOnLevelInit->Execute(); - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } /** * CBaseEntity Hook Handlers */ -bool SDKHooks::Hook_CanBeAutobalanced() +KHook::Return SDKHooks::Hook_CanBeAutobalanced(CBaseEntity* this_ptr) { - CBaseEntity *pPlayer = META_IFACEPTR(CBaseEntity); + CBaseEntity *pPlayer = this_ptr; - CVTableHook vhook(pPlayer); + void** vtable = *(void***)pPlayer; std::vector &vtablehooklist = g_HookList[SDKHook_CanBeAutobalanced]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } int entity = gamehelpers->EntityToBCompatRef(pPlayer); - bool origRet = SH_MCALL(pPlayer, CanBeAutobalanced)(); + auto mfp = KHook::BuildMFP(KHook::FindOriginalVirtual(*(void***)this_ptr, g_HookTypes[SDKHook_CanBeAutobalanced].offset)); + bool origRet = (this_ptr->*mfp)(); bool newRet = origRet; std::vector callbackList; @@ -1005,47 +1081,47 @@ bool SDKHooks::Hook_CanBeAutobalanced() } if (newRet != origRet) - RETURN_META_VALUE(MRES_SUPERCEDE, newRet); + return { KHook::Action::Supersede, newRet }; break; } - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore, false }; } -void SDKHooks::Hook_EndTouch(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_EndTouch(CBaseEntity* this_ptr, CBaseEntity *pOther) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouch, pOther); + cell_t result = Call(this_ptr, SDKHook_EndTouch, pOther); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Supersede }; } -void SDKHooks::Hook_EndTouchPost(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_EndTouchPost(CBaseEntity* this_ptr, CBaseEntity *pOther) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouchPost, pOther); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_EndTouchPost, pOther); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info) +KHook::Return SDKHooks::Hook_FireBulletsPost(CBaseEntity* this_ptr, const FireBulletsInfo_t &info) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; int entity = gamehelpers->EntityToBCompatRef(pEntity); IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(entity); if(!pPlayer) - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; IPlayerInfo *pInfo = pPlayer->GetPlayerInfo(); if(!pInfo) - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_FireBulletsPost]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1066,20 +1142,21 @@ void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info) break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } #ifdef GETMAXHEALTH_IS_VIRTUAL -int SDKHooks::Hook_GetMaxHealth() +KHook::Return SDKHooks::Hook_GetMaxHealth(CBaseEntity* this_ptr) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); - int original_max = SH_MCALL(pEntity, GetMaxHealth)(); + CBaseEntity *pEntity = this_ptr; + auto mfp = KHook::BuildMFP(KHook::FindOriginalVirtual(*(void***)pEntity, g_HookTypes[SDKHook_GetMaxHealth].offset)); + int original_max = (pEntity->*mfp)(); - CVTableHook vhook(pEntity); + void** vtable = *(void***)this_ptr; std::vector &vtablehooklist = g_HookList[SDKHook_GetMaxHealth]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1108,32 +1185,33 @@ int SDKHooks::Hook_GetMaxHealth() } if (ret >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, original_max); + return { KHook::Action::Supersede, original_max }; if (ret >= Pl_Changed) - RETURN_META_VALUE(MRES_SUPERCEDE, new_max); + return { KHook::Action::Supersede, new_max }; break; } - RETURN_META_VALUE(MRES_IGNORED, original_max); + return { KHook::Action::Ignore, original_max }; } #endif -void SDKHooks::Hook_GroundEntChangedPost(void *pVar) +KHook::Return SDKHooks::Hook_GroundEntChangedPost(CBaseEntity* this_ptr, void *pVar) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_GroundEntChangedPost); + Call(this_ptr, SDKHook_GroundEntChangedPost); + return { KHook::Action::Ignore }; } -int SDKHooks::HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType) +KHook::Return SDKHooks::HandleOnTakeDamageHook(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, SDKHookType hookType) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[hookType]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1178,13 +1256,13 @@ int SDKHooks::HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hook if (!pEntAttacker && attacker != -1) { callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for attacker is invalid", attacker); - RETURN_META_VALUE(MRES_IGNORED, 0); + return { KHook::Action::Ignore, 0 }; } CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor); if (!pEntInflictor && inflictor != -1) { callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for inflictor is invalid", inflictor); - RETURN_META_VALUE(MRES_IGNORED, 0); + return { KHook::Action::Ignore, 0 }; } info.SetAttacker(pEntAttacker); @@ -1205,26 +1283,26 @@ int SDKHooks::HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hook } if (ret >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, 1); + return { KHook::Action::Supersede, 1 }; if (ret == Pl_Changed) - RETURN_META_VALUE(MRES_HANDLED, 1); + return { KHook::Action::Override, 1 }; break; } - RETURN_META_VALUE(MRES_IGNORED, 0); + return { KHook::Action::Ignore, 0 }; } -int SDKHooks::HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType) +KHook::Return SDKHooks::HandleOnTakeDamageHookPost(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, SDKHookType hookType) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[hookType]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1259,60 +1337,62 @@ int SDKHooks::HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType break; } - RETURN_META_VALUE(MRES_IGNORED, 0); + return { KHook::Action::Ignore, 0 }; } -int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info) +KHook::Return SDKHooks::Hook_OnTakeDamage(CBaseEntity* this_ptr, CTakeDamageInfoHack &info) { - return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage); + return HandleOnTakeDamageHook(this_ptr, info, SDKHook_OnTakeDamage); } -int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info) +KHook::Return SDKHooks::Hook_OnTakeDamagePost(CBaseEntity* this_ptr, CTakeDamageInfoHack &info) { - return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamagePost); + return HandleOnTakeDamageHookPost(this_ptr, info, SDKHook_OnTakeDamagePost); } -int SDKHooks::Hook_OnTakeDamage_Alive(CTakeDamageInfoHack &info) +KHook::Return SDKHooks::Hook_OnTakeDamage_Alive(CBaseEntity* this_ptr, CTakeDamageInfoHack &info) { - return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage_Alive); + return HandleOnTakeDamageHook(this_ptr, info, SDKHook_OnTakeDamage_Alive); } -int SDKHooks::Hook_OnTakeDamage_AlivePost(CTakeDamageInfoHack &info) +KHook::Return SDKHooks::Hook_OnTakeDamage_AlivePost(CBaseEntity* this_ptr, CTakeDamageInfoHack &info) { - return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamage_AlivePost); + return HandleOnTakeDamageHookPost(this_ptr, info, SDKHook_OnTakeDamage_AlivePost); } -void SDKHooks::Hook_PreThink() +KHook::Return SDKHooks::Hook_PreThink(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThink); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_PreThink); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_PreThinkPost() +KHook::Return SDKHooks::Hook_PreThinkPost(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThinkPost); + Call(this_ptr, SDKHook_PreThinkPost); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_PostThink() +KHook::Return SDKHooks::Hook_PostThink(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThink); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_PostThink); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_PostThinkPost() +KHook::Return SDKHooks::Hook_PostThinkPost(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThinkPost); + Call(this_ptr, SDKHook_PostThinkPost); + return { KHook::Action::Ignore }; } -bool SDKHooks::Hook_Reload() +KHook::Return SDKHooks::Hook_Reload(CBaseEntity* this_ptr) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_Reload]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1330,29 +1410,29 @@ bool SDKHooks::Hook_Reload() } if (res >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; break; } - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } -bool SDKHooks::Hook_ReloadPost() +KHook::Return SDKHooks::Hook_ReloadPost(CBaseEntity* this_ptr) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_ReloadPost]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } int entity = gamehelpers->EntityToBCompatRef(pEntity); - cell_t origreturn = META_RESULT_ORIG_RET(bool) ? 1 : 0; + cell_t origreturn = (*(bool*)::KHook::GetOriginalValuePtr()) ? 1 : 0; std::vector callbackList; PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity); @@ -1367,34 +1447,34 @@ bool SDKHooks::Hook_ReloadPost() break; } - return true; + return { KHook::Action::Ignore, true }; } -void SDKHooks::Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways) +KHook::Return SDKHooks::Hook_SetTransmit(CBaseEntity* this_ptr, CCheckTransmitInfo *pInfo, bool bAlways) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_SetTransmit, gamehelpers->IndexOfEdict(pInfo->m_pClientEnt)); + cell_t result = Call(this_ptr, SDKHook_SetTransmit, gamehelpers->IndexOfEdict(pInfo->m_pClientEnt)); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask) +KHook::Return SDKHooks::Hook_ShouldCollide(CBaseEntity* this_ptr, int collisionGroup, int contentsMask) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_ShouldCollide]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } int entity = gamehelpers->EntityToBCompatRef(pEntity); - cell_t origRet = ((META_RESULT_STATUS >= MRES_OVERRIDE)?(META_RESULT_OVERRIDE_RET(bool)):(META_RESULT_ORIG_RET(bool))) ? 1 : 0; + cell_t origRet = (*(bool*)KHook::GetCurrentValuePtr()) ? 1 : 0; cell_t res = 0; std::vector callbackList; @@ -1415,21 +1495,21 @@ bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask) ret = true; } - RETURN_META_VALUE(MRES_SUPERCEDE, ret); + return { KHook::Action::Supersede, ret }; } - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } -void SDKHooks::Hook_Spawn() +KHook::Return SDKHooks::Hook_Spawn(CBaseEntity* this_ptr) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_Spawn]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1454,79 +1534,81 @@ void SDKHooks::Hook_Spawn() } if (ret >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_SpawnPost() +KHook::Return SDKHooks::Hook_SpawnPost(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_SpawnPost); + Call(this_ptr, SDKHook_SpawnPost); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_StartTouch(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_StartTouch(CBaseEntity* this_ptr, CBaseEntity *pOther) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouch, pOther); + cell_t result = Call(this_ptr, SDKHook_StartTouch, pOther); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_StartTouchPost(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_StartTouchPost(CBaseEntity* this_ptr, CBaseEntity *pOther) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouchPost, pOther); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_StartTouchPost, pOther); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_Think() +KHook::Return SDKHooks::Hook_Think(CBaseEntity* this_ptr) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Think); + cell_t result = Call(this_ptr, SDKHook_Think); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_ThinkPost() +KHook::Return SDKHooks::Hook_ThinkPost(CBaseEntity* this_ptr) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_ThinkPost); + Call(this_ptr, SDKHook_ThinkPost); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_Touch(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_Touch(CBaseEntity* this_ptr, CBaseEntity *pOther) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Touch, pOther); + cell_t result = Call(this_ptr, SDKHook_Touch, pOther); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_TouchPost(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_TouchPost(CBaseEntity* this_ptr, CBaseEntity *pOther) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_TouchPost, pOther); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_TouchPost, pOther); + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_PVKII -void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator) +KHook::Return SDKHooks::Hook_TraceAttack(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator) #else -void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr) +KHook::Return SDKHooks::Hook_TraceAttack(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr) #endif { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_TraceAttack]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1564,13 +1646,13 @@ void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, if(!pEntAttacker) { callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for attacker is invalid", attacker); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor); if(!pEntInflictor) { callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for inflictor is invalid", inflictor); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } info.SetAttacker(pEntAttacker); @@ -1583,31 +1665,31 @@ void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, } if(ret >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; if(ret == Pl_Changed) - RETURN_META(MRES_HANDLED); + return { KHook::Action::Ignore }; break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_PVKII -void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator) +KHook::Return SDKHooks::Hook_TraceAttackPost(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator) #else -void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr) +KHook::Return SDKHooks::Hook_TraceAttackPost(CBaseEntity* this_ptr, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr) #endif { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_TraceAttackPost]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1633,18 +1715,18 @@ void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vec break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) +KHook::Return SDKHooks::Hook_Use(CBaseEntity* this_ptr, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_Use]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1675,23 +1757,23 @@ void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE } if (ret >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) +KHook::Return SDKHooks::Hook_UsePost(CBaseEntity* this_ptr, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; - CVTableHook vhook(pEntity); + void** vtable = *(void***)pEntity; std::vector &vtablehooklist = g_HookList[SDKHook_UsePost]; for (size_t entry = 0; entry < vtablehooklist.size(); ++entry) { - if (vhook != vtablehooklist[entry]->vtablehook) + if (vtable != vtablehooklist[entry]->vtablehook->GetVTablePtr()) { continue; } @@ -1716,7 +1798,7 @@ void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T break; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity) @@ -1732,111 +1814,112 @@ void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity) HandleEntityDeleted(pEntity); } -void SDKHooks::Hook_VPhysicsUpdate(IPhysicsObject *pPhysics) +KHook::Return SDKHooks::Hook_VPhysicsUpdate(CBaseEntity* this_ptr, IPhysicsObject *pPhysics) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdate); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_VPhysicsUpdate); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics) +KHook::Return SDKHooks::Hook_VPhysicsUpdatePost(CBaseEntity* this_ptr, IPhysicsObject *pPhysics) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdatePost); + Call(this_ptr, SDKHook_VPhysicsUpdatePost); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_Blocked(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_Blocked(CBaseEntity* this_ptr, CBaseEntity *pOther) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Blocked, pOther); + cell_t result = Call(this_ptr, SDKHook_Blocked, pOther); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_BlockedPost(CBaseEntity *pOther) +KHook::Return SDKHooks::Hook_BlockedPost(CBaseEntity* this_ptr, CBaseEntity *pOther) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_BlockedPost, pOther); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_BlockedPost, pOther); + return { KHook::Action::Ignore }; } -bool SDKHooks::Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponCanSwitchTo(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchTo, pWeapon); + cell_t result = Call(this_ptr, SDKHook_WeaponCanSwitchTo, pWeapon); if(result >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } -bool SDKHooks::Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponCanSwitchToPost(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchToPost, pWeapon); - RETURN_META_VALUE(MRES_IGNORED, true); + Call(this_ptr, SDKHook_WeaponCanSwitchToPost, pWeapon); + return { KHook::Action::Ignore, true }; } -bool SDKHooks::Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponCanUse(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUse, pWeapon); + cell_t result = Call(this_ptr, SDKHook_WeaponCanUse, pWeapon); if(result >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } -bool SDKHooks::Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponCanUsePost(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUsePost, pWeapon); - RETURN_META_VALUE(MRES_IGNORED, true); + Call(this_ptr, SDKHook_WeaponCanUsePost, pWeapon); + return { KHook::Action::Ignore, true }; } -void SDKHooks::Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity) +KHook::Return SDKHooks::Hook_WeaponDrop(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDrop, pWeapon); + cell_t result = Call(this_ptr, SDKHook_WeaponDrop, pWeapon); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity) +KHook::Return SDKHooks::Hook_WeaponDropPost(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDropPost, pWeapon); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_WeaponDropPost, pWeapon); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_WeaponEquip(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponEquip(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquip, pWeapon); + cell_t result = Call(this_ptr, SDKHook_WeaponEquip, pWeapon); if(result >= Pl_Handled) - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void SDKHooks::Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon) +KHook::Return SDKHooks::Hook_WeaponEquipPost(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon) { - Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquipPost, pWeapon); - RETURN_META(MRES_IGNORED); + Call(this_ptr, SDKHook_WeaponEquipPost, pWeapon); + return { KHook::Action::Ignore }; } -bool SDKHooks::Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex) +KHook::Return SDKHooks::Hook_WeaponSwitch(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon, int viewmodelindex) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitch, pWeapon); + cell_t result = Call(this_ptr, SDKHook_WeaponSwitch, pWeapon); if(result >= Pl_Handled) - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore, true }; } -bool SDKHooks::Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex) +KHook::Return SDKHooks::Hook_WeaponSwitchPost(CBaseEntity* this_ptr, CBaseCombatWeapon *pWeapon, int viewmodelindex) { - cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitchPost, pWeapon); - RETURN_META_VALUE(MRES_IGNORED, true); + cell_t result = Call(this_ptr, SDKHook_WeaponSwitchPost, pWeapon); + return { KHook::Action::Ignore, true }; } void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref) @@ -1845,9 +1928,8 @@ void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref) cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity); // Send OnEntityCreated to SM listeners - SourceHook::List::iterator iter; ISMEntityListener *pListener = NULL; - for (iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++) + for (auto iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++) { pListener = (*iter); pListener->OnEntityCreated(pEntity, pName ? pName : ""); @@ -1866,9 +1948,8 @@ void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity) cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity); // Send OnEntityDestroyed to SM listeners - SourceHook::List::iterator iter; ISMEntityListener *pListener = NULL; - for (iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++) + for (auto iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++) { pListener = (*iter); pListener->OnEntityDestroyed(pEntity); diff --git a/extensions/sdkhooks/extension.h b/extensions/sdkhooks/extension.h index e502c609df..dac711ba92 100644 --- a/extensions/sdkhooks/extension.h +++ b/extensions/sdkhooks/extension.h @@ -6,7 +6,7 @@ #include "smsdk_ext.h" #include #include -#include +#include #include #include @@ -36,6 +36,7 @@ struct HookTypeData const char *name; const char *dtReq; bool supported; + unsigned int offset; }; enum SDKHookType @@ -87,6 +88,8 @@ enum SDKHookType SDKHook_MAXHOOKS }; +extern HookTypeData g_HookTypes[SDKHook_MAXHOOKS]; + enum HookReturn { HookRet_Successful, @@ -130,6 +133,9 @@ class CVTableList { delete vtablehook; }; + + CVTableList(const CVTableList&) = delete; + CVTableList& operator= (const CVTableList&) = delete; public: CVTableHook *vtablehook; std::vector hooks; @@ -160,6 +166,8 @@ class SDKHooks : public ISDKHooks { public: + SDKHooks(); + /** * @brief This is called after the initial loading sequence has been processed. * @@ -260,9 +268,10 @@ class SDKHooks : virtual void RemoveEntityListener(ISMEntityListener *listener); public: // IServerGameDLL - void LevelShutdown(); + KHook::Return LevelShutdown(IServerGameDLL*); + KHook::Virtual m_HookLevelShutdown; private: - SourceHook::List m_EntListeners; + std::list m_EntListeners; public: /** @@ -280,65 +289,67 @@ class SDKHooks : * IServerGameDLL & IVEngineServer Hook Handlers */ #ifdef GAMEDESC_CAN_CHANGE - const char *Hook_GetGameDescription(); + KHook::Return Hook_GetGameDescription(IServerGameDLL*); + KHook::Virtual m_HookGetGameDescription; #endif - bool Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); + KHook::Return Hook_LevelInit(IServerGameDLL*, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); + KHook::Virtual m_HookLevelInit; /** * CBaseEntity Hook Handlers */ - bool Hook_CanBeAutobalanced(); - void Hook_EndTouch(CBaseEntity *pOther); - void Hook_EndTouchPost(CBaseEntity *pOther); - void Hook_FireBulletsPost(const FireBulletsInfo_t &info); + KHook::Return Hook_CanBeAutobalanced(CBaseEntity*); + KHook::Return Hook_EndTouch(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_EndTouchPost(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_FireBulletsPost(CBaseEntity*, const FireBulletsInfo_t &info); #ifdef GETMAXHEALTH_IS_VIRTUAL - int Hook_GetMaxHealth(); + KHook::Return Hook_GetMaxHealth(CBaseEntity*); #endif - void Hook_GroundEntChangedPost(void *pVar); - int Hook_OnTakeDamage(CTakeDamageInfoHack &info); - int Hook_OnTakeDamagePost(CTakeDamageInfoHack &info); - int Hook_OnTakeDamage_Alive(CTakeDamageInfoHack &info); - int Hook_OnTakeDamage_AlivePost(CTakeDamageInfoHack &info); - void Hook_PreThink(); - void Hook_PreThinkPost(); - void Hook_PostThink(); - void Hook_PostThinkPost(); - bool Hook_Reload(); - bool Hook_ReloadPost(); - void Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways); - bool Hook_ShouldCollide(int collisonGroup, int contentsMask); - void Hook_Spawn(); - void Hook_SpawnPost(); - void Hook_StartTouch(CBaseEntity *pOther); - void Hook_StartTouchPost(CBaseEntity *pOther); - void Hook_Think(); - void Hook_ThinkPost(); - void Hook_Touch(CBaseEntity *pOther); - void Hook_TouchPost(CBaseEntity *pOther); + KHook::Return Hook_GroundEntChangedPost(CBaseEntity*, void *pVar); + KHook::Return Hook_OnTakeDamage(CBaseEntity*, CTakeDamageInfoHack &info); + KHook::Return Hook_OnTakeDamagePost(CBaseEntity*, CTakeDamageInfoHack &info); + KHook::Return Hook_OnTakeDamage_Alive(CBaseEntity*, CTakeDamageInfoHack &info); + KHook::Return Hook_OnTakeDamage_AlivePost(CBaseEntity*, CTakeDamageInfoHack &info); + KHook::Return Hook_PreThink(CBaseEntity*); + KHook::Return Hook_PreThinkPost(CBaseEntity*); + KHook::Return Hook_PostThink(CBaseEntity*); + KHook::Return Hook_PostThinkPost(CBaseEntity*); + KHook::Return Hook_Reload(CBaseEntity*); + KHook::Return Hook_ReloadPost(CBaseEntity*); + KHook::Return Hook_SetTransmit(CBaseEntity*, CCheckTransmitInfo *pInfo, bool bAlways); + KHook::Return Hook_ShouldCollide(CBaseEntity*, int collisonGroup, int contentsMask); + KHook::Return Hook_Spawn(CBaseEntity*); + KHook::Return Hook_SpawnPost(CBaseEntity*); + KHook::Return Hook_StartTouch(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_StartTouchPost(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_Think(CBaseEntity*); + KHook::Return Hook_ThinkPost(CBaseEntity*); + KHook::Return Hook_Touch(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_TouchPost(CBaseEntity*, CBaseEntity *pOther); #if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_PVKII - void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator); - void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator); + KHook::Return Hook_TraceAttack(CBaseEntity*, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator); + KHook::Return Hook_TraceAttackPost(CBaseEntity*, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator); #else - void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr); - void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr); + KHook::Return Hook_TraceAttack(CBaseEntity*, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr); + KHook::Return Hook_TraceAttackPost(CBaseEntity*, CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr); #endif - void Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void Hook_VPhysicsUpdate(IPhysicsObject *pPhysics); - void Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics); - void Hook_Blocked(CBaseEntity *pOther); - void Hook_BlockedPost(CBaseEntity *pOther); - bool Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon); - bool Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon); - bool Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon); - bool Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon); - void Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity); - void Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity); - void Hook_WeaponEquip(CBaseCombatWeapon *pWeapon); - void Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon); - bool Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex); - bool Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex); + KHook::Return Hook_Use(CBaseEntity*, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); + KHook::Return Hook_UsePost(CBaseEntity*, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); + KHook::Return Hook_VPhysicsUpdate(CBaseEntity*, IPhysicsObject *pPhysics); + KHook::Return Hook_VPhysicsUpdatePost(CBaseEntity*, IPhysicsObject *pPhysics); + KHook::Return Hook_Blocked(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_BlockedPost(CBaseEntity*, CBaseEntity *pOther); + KHook::Return Hook_WeaponCanSwitchTo(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponCanSwitchToPost(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponCanUse(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponCanUsePost(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponDrop(CBaseEntity*, CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity); + KHook::Return Hook_WeaponDropPost(CBaseEntity*, CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity); + KHook::Return Hook_WeaponEquip(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponEquipPost(CBaseEntity*, CBaseCombatWeapon *pWeapon); + KHook::Return Hook_WeaponSwitch(CBaseEntity*, CBaseCombatWeapon *pWeapon, int viewmodelindex); + KHook::Return Hook_WeaponSwitchPost(CBaseEntity*, CBaseCombatWeapon *pWeapon, int viewmodelindex); private: void HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref); @@ -347,8 +358,8 @@ class SDKHooks : void Unhook(IPluginContext *pContext); private: - int HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType); - int HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType); + KHook::Return HandleOnTakeDamageHook(CBaseEntity*, CTakeDamageInfoHack &info, SDKHookType hookType); + KHook::Return HandleOnTakeDamageHookPost(CBaseEntity*, CTakeDamageInfoHack &info, SDKHookType hookType); private: inline bool IsEntityIndexInRange(int i) { return i >= 0 && i < NUM_ENT_ENTRIES; } diff --git a/extensions/sdkhooks/macros.h b/extensions/sdkhooks/macros.h index 86476026c8..8913145d95 100644 --- a/extensions/sdkhooks/macros.h +++ b/extensions/sdkhooks/macros.h @@ -30,19 +30,23 @@ * Version: $Id$ */ -#define SET_PRE_true(gamedataname) g_HookTypes[SDKHook_##gamedataname].supported = true; -#define SET_PRE_false(gamedataname) -#define SET_POST_true(gamedataname) g_HookTypes[SDKHook_##gamedataname##Post].supported = true; -#define SET_POST_false(gamedataname) +#define SET_PRE_true(gamedataname, index) g_HookTypes[SDKHook_##gamedataname].supported = true; \ + g_HookTypes[SDKHook_##gamedataname].offset = index; + +#define SET_PRE_false(gamedataname, index) + +#define SET_POST_true(gamedataname, index) g_HookTypes[SDKHook_##gamedataname##Post].supported = true; \ + g_HookTypes[SDKHook_##gamedataname##Post].offset = index; + +#define SET_POST_false(gamedataname, index) #define CHECKOFFSET(gamedataname, supportsPre, supportsPost) \ offset = 0; \ g_pGameConf->GetOffset(#gamedataname, &offset); \ if (offset > 0) \ { \ - SH_MANUALHOOK_RECONFIGURE(gamedataname, offset, 0, 0); \ - SET_PRE_##supportsPre(gamedataname) \ - SET_POST_##supportsPost(gamedataname) \ + SET_PRE_##supportsPre(gamedataname, offset) \ + SET_POST_##supportsPost(gamedataname, offset) \ } #define CHECKOFFSET_W(gamedataname, supportsPre, supportsPost) \ @@ -50,9 +54,8 @@ g_pGameConf->GetOffset("Weapon_"#gamedataname, &offset); \ if (offset > 0) \ { \ - SH_MANUALHOOK_RECONFIGURE(Weapon_##gamedataname, offset, 0, 0); \ - SET_PRE_##supportsPre(Weapon##gamedataname) \ - SET_POST_##supportsPost(Weapon##gamedataname) \ + SET_PRE_##supportsPre(Weapon##gamedataname, offset) \ + SET_POST_##supportsPost(Weapon##gamedataname, offset) \ } #define HOOKLOOP \ diff --git a/extensions/sdkhooks/natives.cpp b/extensions/sdkhooks/natives.cpp index 526bc68622..5cd19c9a78 100644 --- a/extensions/sdkhooks/natives.cpp +++ b/extensions/sdkhooks/natives.cpp @@ -38,9 +38,6 @@ using namespace SourceMod; -SH_DECL_MANUALEXTERN1(OnTakeDamage, int, CTakeDamageInfoHack &); -SH_DECL_MANUALEXTERN3_void(Weapon_Drop, CBaseCombatWeapon *, const Vector *, const Vector *); - cell_t Native_Hook(IPluginContext *pContext, const cell_t *params) { int entity = (int)params[1]; @@ -102,6 +99,9 @@ cell_t Native_Unhook(IPluginContext *pContext, const cell_t *params) cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params) { + if (g_HookTypes[SDKHook_OnTakeDamage].supported == false) + return pContext->ThrowNativeError("SDKHooks_DropWeapon isn't supported by this mod."); + CBaseEntity *pVictim = gamehelpers->ReferenceToEntity(params[1]); if (!pVictim) return pContext->ThrowNativeError("Invalid entity index %d for victim", params[1]); @@ -177,7 +177,9 @@ cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params) if (params[0] < 9 || params[9] != 0) { - SH_MCALL(pVictim, OnTakeDamage)((CTakeDamageInfoHack&)info); + auto func = KHook::FindOriginalVirtual(*(void***)pVictim, g_HookTypes[SDKHook_OnTakeDamage].offset); + auto mfp = KHook::BuildMFP(func); + (pVictim->*mfp)(info); } else { @@ -198,7 +200,7 @@ cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params) pass[1].size = sizeof(int); pass[1].flags = PASSFLAG_BYVAL; - pCall = g_pBinTools->CreateVCall(offset, 0, 0, &pass[1], &pass[0], 1); + pCall = g_pBinTools->CreateVCall(g_HookTypes[SDKHook_OnTakeDamage].offset, 0, 0, &pass[1], &pass[0], 1); } // Can't ArgBuffer here until we upgrade our Clang version on the Linux builder @@ -218,6 +220,9 @@ cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params) cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params) { + if (g_HookTypes[SDKHook_WeaponDrop].supported == false) + return pContext->ThrowNativeError("SDKHooks_DropWeapon isn't supported by this mod."); + CBaseEntity *pPlayer = gamehelpers->ReferenceToEntity(params[1]); if (!pPlayer) return pContext->ThrowNativeError("Invalid client index %d", params[1]); @@ -286,19 +291,15 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params) if (params[0] < 5 || params[5] != 0) { - SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon*)pWeapon, pVecTarget, pVecVelocity); + auto func = KHook::FindOriginalVirtual(*(void***)pPlayer, g_HookTypes[SDKHook_WeaponDrop].offset); + auto mfp = KHook::BuildMFP(func); + (pPlayer->*mfp)((CBaseCombatWeapon*)pWeapon, pVecTarget, pVecVelocity); } else { static ICallWrapper* pCall = nullptr; if (!pCall) { - int offset; - if (!g_pGameConf->GetOffset("Weapon_Drop", &offset)) - { - return pContext->ThrowNativeError("Could not find Weapon_Drop offset"); - } - PassInfo pass[3]; pass[0].type = PassType_Basic; pass[0].size = sizeof(CBaseEntity *); @@ -310,7 +311,7 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params) pass[2].size = sizeof(Vector *); pass[2].flags = PASSFLAG_BYVAL; - pCall = g_pBinTools->CreateVCall(offset, 0, 0, nullptr, pass, 3); + pCall = g_pBinTools->CreateVCall(g_HookTypes[SDKHook_WeaponDrop].offset, 0, 0, nullptr, pass, 3); } pCall->Execute(ArgBuffer(pPlayer, pWeapon, pVecTarget, pVecVelocity), nullptr); diff --git a/extensions/sdktools/AMBuilder b/extensions/sdktools/AMBuilder index e71c365718..2b6bc35cf0 100644 --- a/extensions/sdktools/AMBuilder +++ b/extensions/sdktools/AMBuilder @@ -37,12 +37,6 @@ for sdk_name in SM.sdks: continue binary = SM.HL2ExtConfig(project, builder, cxx, 'sdktools.ext.' + sdk['extension'], sdk) - SM.AddCDetour(binary) - - binary.compiler.cxxincludes += [ - os.path.join(builder.sourcePath, 'public', 'jit'), - os.path.join(builder.sourcePath, 'public', 'jit', 'x86'), - ] if sdk['name'] in ('episode1', 'darkm'): binary.compiler.cxxincludes += [os.path.join(sdk['path'], 'game_shared')] diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index 66ff208cec..4a646ff588 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -52,16 +52,6 @@ * @file extension.cpp * @brief Implements SDK Tools extension code. */ - -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); -#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO -SH_DECL_HOOK1_void_vafmt(IVEngineServer, ClientCommand, SH_NOATTRIB, 0, edict_t *); -#endif -#if defined CLIENTVOICE_HOOK_SUPPORT -SH_DECL_HOOK1_void(IServerGameClients, ClientVoice, SH_NOATTRIB, 0, edict_t *); -#endif - SDKTools g_SdkTools; /**< Global singleton for extension's main interface */ IServerGameEnts *gameents = NULL; IEngineTrace *enginetrace = NULL; @@ -88,8 +78,6 @@ IForward *m_OnClientSpeakingEnd; IServerTools *servertools = NULL; #endif -SourceHook::CallClass *enginePatch = NULL; -SourceHook::CallClass *enginesoundPatch = NULL; HandleType_t g_CallHandle = 0; HandleType_t g_TraceHandle = 0; ISDKTools *g_pSDKTools; @@ -109,17 +97,30 @@ extern sp_nativeinfo_t g_ClientNatives[]; static void InitSDKToolsAPI(); #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -CDetour *g_WriteBaselinesDetour = NULL; - -DETOUR_DECL_MEMBER3(CNetworkStringTableContainer__WriteBaselines, void, char const *, mapName, void *, buffer, int, currentTick) -{ +class CNetworkStringTableContainer; +KHook::Return CNetworkStringTableContainer__WriteBaselines(CNetworkStringTableContainer* container, char const * mapName, void * buffer, int currentTick) { // Replace nAtTick with INT_MAX to work around CS:GO engine bug. // Due to a timing issue in the engine, stringtable entries added in OnConfigsExecuted can be considered // to have been added in the future for the first client that connects, which causes them to be ignored // when iterating for networking, which triggers a Host_Error encoding the CreateStringTable netmsg. - return DETOUR_MEMBER_CALL(CNetworkStringTableContainer__WriteBaselines)(mapName, buffer, INT_MAX); + void (CNetworkStringTableContainer::*dummy_func)(const char*, void*, int) = nullptr; + return KHook::Recall(dummy_func, { KHook::Action::Ignore }, container, mapName, buffer, INT_MAX); } +KHook::Member g_WriteBaselinesDetour(CNetworkStringTableContainer__WriteBaselines, nullptr); +#endif + +SDKTools::SDKTools() : +#if defined CLIENTVOICE_HOOK_SUPPORT + m_HookClientVoice(&IServerGameClients::ClientVoice, this, nullptr, &SDKTools::OnClientVoice), +#endif + m_HookSetClientListening(&IVoiceServer::SetClientListening, this, &SDKTools::OnSetClientListening, nullptr), + m_HookClientCommand(&IServerGameClients::ClientCommand, this, nullptr, &SDKTools::OnClientCommand), +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO + m_HookOnSendClientCommand(KHook::GetVtableIndex(&IVEngineServer::ClientCommand), this, &SDKTools::OnSendClientCommand, nullptr), #endif + m_HookLevelInit(&IServerGameDLL::LevelInit, this, nullptr, &SDKTools::LevelInit), + m_HookLevelShutdown(&IServerGameDLL::LevelShutdown, this, nullptr, &SDKTools::LevelShutdown) +{} bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) { @@ -174,8 +175,8 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) #endif CONVAR_REGISTER(this); - SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SDKTools::LevelInit), true); - SH_ADD_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SDKTools::LevelShutdown), true); + m_HookLevelInit.Add(gamedll); + m_HookLevelShutdown.Add(gamedll); playerhelpers->RegisterCommandTargetProcessor(this); @@ -184,8 +185,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) spengine = g_pSM->GetScriptingEngine(); plsys->AddPluginsListener(&g_OutputManager); - - CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf); + g_OutputManager.Init(); VoiceInit(); @@ -210,12 +210,12 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late) #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - g_WriteBaselinesDetour = DETOUR_CREATE_MEMBER(CNetworkStringTableContainer__WriteBaselines, "WriteBaselines"); - if (g_WriteBaselinesDetour) { - g_WriteBaselinesDetour->EnableDetour(); - } else { - g_pSM->LogError(myself, "Failed to find WriteBaselines signature -- stringtable error workaround disabled."); + void* addr = nullptr; + if (!g_pGameConf->GetMemSig("WriteBaselines", &addr) || addr == nullptr) { + ke::SafeSprintf(error, maxlength, "Failed to find WriteBaselines signature -- stringtable error workaround disabled."); + return false; } + g_WriteBaselinesDetour.Configure(addr); #endif return true; @@ -237,8 +237,7 @@ void SDKTools::OnHandleDestroy(HandleType_t type, void *object) void SDKTools::SDK_OnUnload() { - SourceHook::List::iterator iter; - for (iter = g_RegCalls.begin(); + for (auto iter = g_RegCalls.begin(); iter != g_RegCalls.end(); iter++) { @@ -248,10 +247,7 @@ void SDKTools::SDK_OnUnload() ShutdownHelpers(); #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - if (g_WriteBaselinesDetour) { - g_WriteBaselinesDetour->DisableDetour(); - g_WriteBaselinesDetour = NULL; - } + g_WriteBaselinesDetour.Configure((void*)nullptr); #endif if (g_pAcceptInput) @@ -275,19 +271,8 @@ void SDKTools::SDK_OnUnload() playerhelpers->UnregisterCommandTargetProcessor(this); plsys->RemovePluginsListener(&g_OutputManager); - SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SDKTools::LevelInit), true); - SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SDKTools::LevelShutdown), true); - - if (enginePatch) - { - SH_RELEASE_CALLCLASS(enginePatch); - enginePatch = NULL; - } - if (enginesoundPatch) - { - SH_RELEASE_CALLCLASS(enginesoundPatch); - enginesoundPatch = NULL; - } + m_HookLevelInit.Remove(gamedll); + m_HookLevelShutdown.Remove(gamedll); bool err; if (g_CallHandle != 0) @@ -327,14 +312,12 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool GET_V_IFACE_ANY(GetEngineFactory, soundemitterbase, ISoundEmitterSystemBase, SOUNDEMITTERSYSTEM_INTERFACE_VERSION); #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO - SH_ADD_HOOK(IVEngineServer, ClientCommand, engine, SH_MEMBER(this, &SDKTools::OnSendClientCommand), false); + m_HookOnSendClientCommand.Add(engine); #endif #if defined CLIENTVOICE_HOOK_SUPPORT - SH_ADD_HOOK(IServerGameClients, ClientVoice, serverClients, SH_MEMBER(this, &SDKTools::OnClientVoice), true); + m_HookClientVoice.Add(serverClients); #endif gpGlobals = ismm->GetCGlobals(); - enginePatch = SH_GET_CALLCLASS(engine); - enginesoundPatch = SH_GET_CALLCLASS(engsound); return true; } @@ -342,10 +325,10 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool bool SDKTools::SDK_OnMetamodUnload(char *error, size_t maxlen) { #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO - SH_REMOVE_HOOK(IVEngineServer, ClientCommand, engine, SH_MEMBER(this, &SDKTools::OnSendClientCommand), false); + m_HookOnSendClientCommand.Remove(engine); #endif #if defined CLIENTVOICE_HOOK_SUPPORT - SH_REMOVE_HOOK(IServerGameClients, ClientVoice, serverClients, SH_MEMBER(this, &SDKTools::OnClientVoice), true); + m_HookClientVoice.Remove(serverClients); #endif return true; } @@ -395,8 +378,7 @@ bool SDKTools::QueryInterfaceDrop(SMInterface *pInterface) void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface) { - SourceHook::List::iterator iter; - for (iter = g_RegCalls.begin(); + for (auto iter = g_RegCalls.begin(); iter != g_RegCalls.end(); iter++) { @@ -420,7 +402,7 @@ bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar) return g_SMAPI->RegisterConCommandBase(g_PLAPI, pVar); } -bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) +KHook::Return SDKTools::LevelInit(IServerGameDLL*, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) { m_bAnyLevelInited = true; @@ -432,7 +414,7 @@ bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char co if (!(name=g_pGameConf->GetKeyValue("SlapSoundCount"))) { - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore }; } count = atoi(name); @@ -447,12 +429,14 @@ bool SDKTools::LevelInit(char const *pMapName, char const *pMapEntities, char co n++; } - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore }; } -void SDKTools::LevelShutdown() +KHook::Return SDKTools::LevelShutdown(IServerGameDLL*) { ClearValveGlobals(); + + return { KHook::Action::Ignore }; } bool SDKTools::ProcessCommandTarget(cmd_target_info_t *info) @@ -552,7 +536,7 @@ void SDKTools::OnClientConnected(int client) #endif #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO -void SDKTools::OnSendClientCommand(edict_t *pPlayer, const char *szFormat) +KHook::Return SDKTools::OnSendClientCommand(IVEngineServer*, edict_t *pPlayer, const char *szFormat) { // Due to legacy code, CS:S and CS:GO still sends "name \"newname\"" to the // client after aname change. The engine has a change hook on name causing @@ -560,10 +544,10 @@ void SDKTools::OnSendClientCommand(edict_t *pPlayer, const char *szFormat) // SetClientName work properly. if (!strncmp(szFormat, "name ", 5)) { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } #endif @@ -583,11 +567,11 @@ void SDKTools::OnTimerEnd(ITimer *pTimer, void *pData) } #if defined CLIENTVOICE_HOOK_SUPPORT -void SDKTools::OnClientVoice(edict_t *pPlayer) +KHook::Return SDKTools::OnClientVoice(IServerGameClients*, edict_t *pPlayer) { if (!pPlayer) { - return; + return { KHook::Action::Ignore }; } int client = IndexOfEdict(pPlayer); @@ -601,6 +585,8 @@ void SDKTools::OnClientVoice(edict_t *pPlayer) m_OnClientSpeaking->PushCell(client); m_OnClientSpeaking->Execute(); + + return { KHook::Action::Ignore }; } #endif @@ -637,4 +623,4 @@ static void InitSDKToolsAPI() { g_pSDKTools = &g_SDKTools_API; sharesys->AddInterface(myself, g_pSDKTools); -} +} \ No newline at end of file diff --git a/extensions/sdktools/extension.h b/extensions/sdktools/extension.h index c985d0d4d7..1eaafc1c52 100644 --- a/extensions/sdktools/extension.h +++ b/extensions/sdktools/extension.h @@ -80,6 +80,8 @@ class SDKTools : public ITimedEvent, public ICommandTargetProcessor { +public: + SDKTools(); public: //public IHandleTypeDispatch void OnHandleDestroy(HandleType_t type, void *object); public: //public SDKExtension @@ -110,19 +112,26 @@ class SDKTools : void OnClientDisconnecting(int client); public: #if defined CLIENTVOICE_HOOK_SUPPORT - void OnClientVoice(edict_t *pPlayer); + KHook::Virtual m_HookClientVoice; + KHook::Return OnClientVoice(IServerGameClients*, edict_t *pPlayer); #endif public: // IVoiceServer - bool OnSetClientListening(int iReceiver, int iSender, bool bListen); + KHook::Virtual m_HookSetClientListening; + KHook::Return OnSetClientListening(IVoiceServer*, int iReceiver, int iSender, bool bListen); + bool DecListeningHookCount(); + void IncListeningHookCount(); void VoiceInit(); void VoiceShutdown(); #if SOURCE_ENGINE >= SE_ORANGEBOX - void OnClientCommand(edict_t *pEntity, const CCommand &args); + KHook::Return OnClientCommand(class IServerGameClients*, edict_t *pEntity, const CCommand &args); + KHook::Virtual m_HookClientCommand; #else - void OnClientCommand(edict_t *pEntity); + KHook::Return OnClientCommand(class IServerGameClients*, edict_t *pEntity); + KHook::Virtual m_HookClientCommand; #endif #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_CSGO - void OnSendClientCommand(edict_t *pPlayer, const char *szFormat); + KHook::Virtual m_HookOnSendClientCommand; + KHook::Return OnSendClientCommand(IVEngineServer*, edict_t *pPlayer, const char *szFormat); #endif public: //ITimedEvent ResultType OnTimer(ITimer *pTimer, void *pData); @@ -131,8 +140,10 @@ class SDKTools : public: //ICommandTargetProcessor bool ProcessCommandTarget(cmd_target_info_t *info); public: - bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); - void LevelShutdown(); + KHook::Virtual m_HookLevelInit; + KHook::Return LevelInit(IServerGameDLL*, char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); + KHook::Virtual m_HookLevelShutdown; + KHook::Return LevelShutdown(IServerGameDLL*); void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); public: bool HasAnyLevelInited() { return m_bAnyLevelInited; } @@ -181,12 +192,7 @@ extern ITimer *g_hTimerSpeaking[SM_MAXPLAYERS+1]; /* Forwards */ extern IForward *m_OnClientSpeaking; extern IForward *m_OnClientSpeakingEnd; -/* Call classes */ -extern SourceHook::CallClass *enginePatch; -extern SourceHook::CallClass *enginesoundPatch; #include -#define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func) - #endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/sdktools/hooks.cpp b/extensions/sdktools/hooks.cpp index 979753835f..fec5748300 100644 --- a/extensions/sdktools/hooks.cpp +++ b/extensions/sdktools/hooks.cpp @@ -53,19 +53,7 @@ static bool FILE_used = false; static bool PVD_used = false; #endif -SH_DECL_MANUALHOOK2_void(PlayerRunCmdHook, 0, 0, 0, CUserCmd *, IMoveHelper *); -SH_DECL_HOOK2(IBaseFileSystem, FileExists, SH_NOATTRIB, 0, bool, const char*, const char *); -#if (SOURCE_ENGINE >= SE_ALIENSWARM || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2) -SH_DECL_HOOK3(INetChannel, SendFile, SH_NOATTRIB, 0, bool, const char *, unsigned int, bool); -#else -SH_DECL_HOOK2(INetChannel, SendFile, SH_NOATTRIB, 0, bool, const char *, unsigned int); -#endif -#if !defined CLIENTVOICE_HOOK_SUPPORT -SH_DECL_HOOK1(IClientMessageHandler, ProcessVoiceData, SH_NOATTRIB, 0, bool, CLC_VoiceData *); -#endif -SH_DECL_HOOK2_void(INetChannel, ProcessPacket, SH_NOATTRIB, 0, struct netpacket_s *, bool); - -SourceHook::CallClass *basefilesystemPatch = NULL; +unsigned int g_iPlayerRunCmdHook = 0; CHookManager::CHookManager() { @@ -82,7 +70,7 @@ void CHookManager::Initialize() int offset; if (g_pGameConf->GetOffset("PlayerRunCmd", &offset)) { - SH_MANUALHOOK_RECONFIGURE(PlayerRunCmdHook, offset, 0, 0); + g_iPlayerRunCmdHook = offset; PRCH_enabled = true; } else @@ -91,8 +79,6 @@ void CHookManager::Initialize() PRCH_enabled = false; } - basefilesystemPatch = SH_GET_CALLCLASS(basefilesystem); - m_netFileSendFwd = forwards->CreateForward("OnFileSend", ET_Event, 2, NULL, Param_Cell, Param_String); m_netFileReceiveFwd = forwards->CreateForward("OnFileReceive", ET_Event, 2, NULL, Param_Cell, Param_String); @@ -141,11 +127,6 @@ void CHookManager::Initialize() void CHookManager::Shutdown() { - if (basefilesystemPatch) - { - SH_RELEASE_CALLCLASS(basefilesystemPatch); - basefilesystemPatch = NULL; - } if (PRCH_used) { @@ -228,18 +209,23 @@ void CHookManager::OnClientConnected(int client) } std::vector &netProcessVoiceData = m_netProcessVoiceData; - CVTableHook hook(pClient); + void** vtable = *(void***)pClient; for (size_t i = 0; i < netProcessVoiceData.size(); ++i) { - if (hook == netProcessVoiceData[i]) + if (vtable == netProcessVoiceData[i]->GetVTablePtr()) { return; } } - int hookid = SH_ADD_VPHOOK(IClientMessageHandler, ProcessVoiceData, (IClientMessageHandler *)((intptr_t)(pClient) + sizeof(void *)), SH_MEMBER(this, &CHookManager::ProcessVoiceData), true); - hook.SetHookID(hookid); - netProcessVoiceData.push_back(new CVTableHook(hook)); + auto msghndl = (IClientMessageHandler *)((intptr_t)(pClient) + sizeof(void *)); + auto func = KHook::GetVtableFunction(msghndl, &IClientMessageHandler::ProcessVoiceData); + + netProcessVoiceData.push_back(new CVTableHook(vtable, + new KHook::Member( + func, + this, nullptr, &CHookManager::ProcessVoiceData + ))); } #endif @@ -272,30 +258,29 @@ void CHookManager::PlayerRunCmdHook(int client, bool post) } std::vector &runUserCmdHookVec = post ? m_runUserCmdPostHooks : m_runUserCmdHooks; - CVTableHook hook(pEntity); + void** vtable = *(void***)pEntity; for (size_t i = 0; i < runUserCmdHookVec.size(); ++i) { - if (hook == runUserCmdHookVec[i]) + if (vtable == runUserCmdHookVec[i]->GetVTablePtr()) { return; } } - int hookid; - if (post) - hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmdPost), true); - else - hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); + auto func = KHook::GetVtableFunction(pEntity, g_iPlayerRunCmdHook); - hook.SetHookID(hookid); - runUserCmdHookVec.push_back(new CVTableHook(hook)); + runUserCmdHookVec.push_back(new CVTableHook(vtable, + new KHook::Member( + func, + this, (post) ? nullptr : &CHookManager::PlayerRunCmd, (post) ? &CHookManager::PlayerRunCmdPost : nullptr + ))); } -void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) +KHook::Return CHookManager::PlayerRunCmd(CBaseEntity* this_ptr, CUserCmd *ucmd, IMoveHelper *moveHelper) { if (!ucmd) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } bool hasUsercmdsPreFwds = (m_usercmdsPreFwd->GetFunctionCount() > 0); @@ -303,21 +288,21 @@ void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) if (!hasUsercmdsPreFwds && !hasUsercmdsFwds) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; if (!pEntity) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } edict_t *pEdict = gameents->BaseEntityToEdict(pEntity); if (!pEdict) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } int client = IndexOfEdict(pEdict); @@ -374,37 +359,37 @@ void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) if (result == Pl_Handled) { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -void CHookManager::PlayerRunCmdPost(CUserCmd *ucmd, IMoveHelper *moveHelper) +KHook::Return CHookManager::PlayerRunCmdPost(CBaseEntity* this_ptr, CUserCmd *ucmd, IMoveHelper *moveHelper) { if (!ucmd) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } if (m_usercmdsPostFwd->GetFunctionCount() == 0) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } - CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity); + CBaseEntity *pEntity = this_ptr; if (!pEntity) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } edict_t *pEdict = gameents->BaseEntityToEdict(pEntity); if (!pEdict) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } int client = IndexOfEdict(pEdict); @@ -425,7 +410,7 @@ void CHookManager::PlayerRunCmdPost(CUserCmd *ucmd, IMoveHelper *moveHelper) m_usercmdsPostFwd->PushArray(mouse, 2); m_usercmdsPostFwd->Execute(); - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } void CHookManager::NetChannelHook(int client) @@ -441,7 +426,7 @@ void CHookManager::NetChannelHook(int client) /* Normal NetChannel Hooks. */ { - CVTableHook nethook(pNetChannel); + void** vtable = *(void***)pNetChannel; size_t iter; /* Initial Hook */ @@ -459,16 +444,16 @@ void CHookManager::NetChannelHook(int client) #endif if (!m_netChannelHooks.size()) { - CVTableHook filehook(basefilesystem); - - int hookid = SH_ADD_VPHOOK(IBaseFileSystem, FileExists, basefilesystem, SH_MEMBER(this, &CHookManager::FileExists), false); - filehook.SetHookID(hookid); - m_netChannelHooks.push_back(new CVTableHook(filehook)); + m_netChannelHooks.push_back(new CVTableHook(*(void***)basefilesystem, + new KHook::Member( + KHook::GetVtableFunction(basefilesystem, &IBaseFileSystem::FileExists), + this, &CHookManager::FileExists, nullptr + ))); } for (iter = 0; iter < m_netChannelHooks.size(); ++iter) { - if (nethook == m_netChannelHooks[iter]) + if (vtable == m_netChannelHooks[iter]->GetVTablePtr()) { break; } @@ -476,43 +461,43 @@ void CHookManager::NetChannelHook(int client) if (iter == m_netChannelHooks.size()) { - int hookid = SH_ADD_VPHOOK(INetChannel, SendFile, pNetChannel, SH_MEMBER(this, &CHookManager::SendFile), false); - nethook.SetHookID(hookid); - m_netChannelHooks.push_back(new CVTableHook(nethook)); - - hookid = SH_ADD_VPHOOK(INetChannel, ProcessPacket, pNetChannel, SH_MEMBER(this, &CHookManager::ProcessPacket), false); - nethook.SetHookID(hookid); - m_netChannelHooks.push_back(new CVTableHook(nethook)); - - hookid = SH_ADD_VPHOOK(INetChannel, ProcessPacket, pNetChannel, SH_MEMBER(this, &CHookManager::ProcessPacket_Post), true); - nethook.SetHookID(hookid); - m_netChannelHooks.push_back(new CVTableHook(nethook)); + m_netChannelHooks.push_back(new CVTableHook(*(void***)pNetChannel, + new KHook::Member( + KHook::GetVtableFunction(pNetChannel, &INetChannel::SendFile), + this, &CHookManager::SendFile, nullptr + ))); + + m_netChannelHooks.push_back(new CVTableHook(*(void***)pNetChannel, + new KHook::Member( + KHook::GetVtableFunction(pNetChannel, &INetChannel::ProcessPacket), + this, &CHookManager::ProcessPacket, &CHookManager::ProcessPacket_Post + ))); } } } -void CHookManager::ProcessPacket(struct netpacket_s *packet, bool bHasHeader) +KHook::Return CHookManager::ProcessPacket(INetChannel* this_ptr, struct netpacket_s *packet, bool bHasHeader) { if (m_netFileReceiveFwd->GetFunctionCount() == 0) { - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } - m_pActiveNetChannel = META_IFACEPTR(INetChannel); - RETURN_META(MRES_IGNORED); + m_pActiveNetChannel = this_ptr; + return { KHook::Action::Ignore }; } -bool CHookManager::FileExists(const char *filename, const char *pathID) +KHook::Return CHookManager::FileExists(IBaseFileSystem*, const char *filename, const char *pathID) { if (m_pActiveNetChannel == NULL || m_netFileReceiveFwd->GetFunctionCount() == 0) { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } - bool ret = SH_CALL(basefilesystemPatch, &IBaseFileSystem::FileExists)(filename, pathID); + bool ret = KHook::CallOriginal(&IBaseFileSystem::FileExists, basefilesystem, filename, pathID); if (ret == true) /* If the File Exists, the engine historically bails out. */ { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } int userid = 0; @@ -529,33 +514,33 @@ bool CHookManager::FileExists(const char *filename, const char *pathID) if (res != Pl_Continue) { - RETURN_META_VALUE(MRES_SUPERCEDE, true); + return { KHook::Action::Supersede, true }; } - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } -void CHookManager::ProcessPacket_Post(struct netpacket_s* packet, bool bHasHeader) +KHook::Return CHookManager::ProcessPacket_Post(INetChannel*, struct netpacket_s* packet, bool bHasHeader) { m_pActiveNetChannel = NULL; - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } #if (SOURCE_ENGINE >= SE_ALIENSWARM || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2) -bool CHookManager::SendFile(const char *filename, unsigned int transferID, bool isReplayDemo) +KHook::Return CHookManager::SendFile(INetChannel* this_ptr, const char *filename, unsigned int transferID, bool isReplayDemo) #else -bool CHookManager::SendFile(const char *filename, unsigned int transferID) +KHook::Return CHookManager::SendFile(INetChannel* this_ptr, const char *filename, unsigned int transferID) #endif { if (m_netFileSendFwd->GetFunctionCount() == 0) { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } - INetChannel *pNetChannel = META_IFACEPTR(INetChannel); + INetChannel *pNetChannel = this_ptr; if (pNetChannel == NULL) { - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } int userid = 0; @@ -578,19 +563,19 @@ bool CHookManager::SendFile(const char *filename, unsigned int transferID) #else pNetChannel->DenyFile(filename, transferID); #endif - RETURN_META_VALUE(MRES_SUPERCEDE, false); + return { KHook::Action::Supersede, false }; } - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } #if !defined CLIENTVOICE_HOOK_SUPPORT -bool CHookManager::ProcessVoiceData(CLC_VoiceData *msg) +KHook::Return CHookManager::ProcessVoiceData(IClientMessageHandler* this_ptr, CLC_VoiceData *msg) { - IClient *pClient = (IClient *)((intptr_t)(META_IFACEPTR(IClient)) - sizeof(void *)); + IClient *pClient = (IClient *)((intptr_t)(this_ptr) - sizeof(void *)); if (pClient == NULL) { - return true; + return { KHook::Action::Ignore, true }; } int client = pClient->GetPlayerSlot() + 1; @@ -605,7 +590,7 @@ bool CHookManager::ProcessVoiceData(CLC_VoiceData *msg) m_OnClientSpeaking->PushCell(client); m_OnClientSpeaking->Execute(); - return true; + return { KHook::Action::Ignore, true }; } #endif diff --git a/extensions/sdktools/hooks.h b/extensions/sdktools/hooks.h index cdb97dd07c..4d1e997e3e 100644 --- a/extensions/sdktools/hooks.h +++ b/extensions/sdktools/hooks.h @@ -51,21 +51,21 @@ class CHookManager : IPluginsListener, IFeatureProvider void OnClientConnected(int client); #endif void OnClientPutInServer(int client); - void PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper); - void PlayerRunCmdPost(CUserCmd *ucmd, IMoveHelper *moveHelper); + KHook::Return PlayerRunCmd(CBaseEntity*, CUserCmd *ucmd, IMoveHelper *moveHelper); + KHook::Return PlayerRunCmdPost(CBaseEntity*, CUserCmd *ucmd, IMoveHelper *moveHelper); void OnMapStart(); public: /* NetChannel/Related Hooks */ - bool FileExists(const char *filename, const char *pathID); + KHook::Return FileExists(IBaseFileSystem*, const char *filename, const char *pathID); #if (SOURCE_ENGINE >= SE_ALIENSWARM || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2) - bool SendFile(const char *filename, unsigned int transferID, bool isReplayDemo); + KHook::Return SendFile(INetChannel*, const char *filename, unsigned int transferID, bool isReplayDemo); #else - bool SendFile(const char *filename, unsigned int transferID); + KHook::Return SendFile(INetChannel*, const char *filename, unsigned int transferID); #endif #if !defined CLIENTVOICE_HOOK_SUPPORT - bool ProcessVoiceData(CLC_VoiceData *msg); + KHook::Return ProcessVoiceData(class IClientMessageHandler*, CLC_VoiceData *msg); #endif - void ProcessPacket(struct netpacket_s *packet, bool bHasHeader); - void ProcessPacket_Post(struct netpacket_s *packet, bool bHasHeader); + KHook::Return ProcessPacket(INetChannel*, struct netpacket_s *packet, bool bHasHeader); + KHook::Return ProcessPacket_Post(INetChannel*, struct netpacket_s *packet, bool bHasHeader); public: //IPluginsListener void OnPluginLoaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin); diff --git a/extensions/sdktools/output.cpp b/extensions/sdktools/output.cpp index 4e4db005a9..3333aa5614 100644 --- a/extensions/sdktools/output.cpp +++ b/extensions/sdktools/output.cpp @@ -35,9 +35,9 @@ ISourcePawnEngine *spengine = NULL; EntityOutputManager g_OutputManager; -CDetour *fireOutputDetour = NULL; -EntityOutputManager::EntityOutputManager() +EntityOutputManager::EntityOutputManager() : + m_HookFireOutput(this, &EntityOutputManager::Hook_FireOutput, nullptr) { info_address = NULL; info_callback = NULL; @@ -53,7 +53,6 @@ void EntityOutputManager::Shutdown() } ClassNames->Destroy(); - fireOutputDetour->Destroy(); } void EntityOutputManager::Init() @@ -74,46 +73,35 @@ bool EntityOutputManager::IsEnabled() } #if defined PLATFORM_WINDOWS && defined KE_ARCH_X86 -DETOUR_DECL_MEMBER8(FireOutput, void, int, what, int, the, int, hell, int, msvc, void *, variant_t, CBaseEntity *, pActivator, CBaseEntity *, pCaller, float, fDelay) -{ - bool fireOutput = g_OutputManager.FireEventDetour((void *)this, pActivator, pCaller, fDelay); - - if (!fireOutput) - { - return; - } - - DETOUR_MEMBER_CALL(FireOutput)(what, the, hell, msvc, variant_t, pActivator, pCaller, fDelay); -} +KHook::Return Hook_FireOutput(CBaseEntity* this_ptr, int what, int the, int hell, int msvc, void*, CBaseEntity* pActivator, CBaseEntity* pCaller, float fDelay) #else -DETOUR_DECL_MEMBER4(FireOutput, void, void *, variant_t, CBaseEntity *, pActivator, CBaseEntity *, pCaller, float, fDelay) +KHook::Return EntityOutputManager::Hook_FireOutput(CBaseEntity* this_ptr, void*, CBaseEntity* pActivator, CBaseEntity* pCaller, float fDelay) +#endif { - bool fireOutput = g_OutputManager.FireEventDetour((void *)this, pActivator, pCaller, fDelay); + bool fireOutput = g_OutputManager.FireEventDetour(this_ptr, pActivator, pCaller, fDelay); if (!fireOutput) { - return; + return { KHook::Action::Supersede }; } - DETOUR_MEMBER_CALL(FireOutput)(variant_t, pActivator, pCaller, fDelay); + return { KHook::Action::Ignore }; } -#endif bool EntityOutputManager::CreateFireEventDetour() { - fireOutputDetour = DETOUR_CREATE_MEMBER(FireOutput, "FireOutput"); - - if (fireOutputDetour) - { - return true; + void (CBaseEntity::*func)(void*, CBaseEntity*, CBaseEntity*, float) = nullptr; + if (!g_pGameConf->GetMemSig("FireOutput", reinterpret_cast(&func)) || func == nullptr) { + return false; } - return false; + m_HookFireOutput.Configure(func); + return true; } bool EntityOutputManager::FireEventDetour(void *pOutput, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay) { - if (!pCaller) + if (!pCaller || HookCount == 0) { return true; } @@ -138,11 +126,9 @@ bool EntityOutputManager::FireEventDetour(void *pOutput, CBaseEntity *pActivator if (!pOutputName->hooks.empty()) { - SourceHook::List::iterator _iter; - omg_hooks *hook; - _iter = pOutputName->hooks.begin(); + auto _iter = pOutputName->hooks.begin(); // by default we'll call the game's output func, unless a plugin overrides it bool fireOriginal = true; @@ -221,7 +207,7 @@ omg_hooks *EntityOutputManager::NewHook() } else { - hook = g_OutputManager.FreeHooks.front(); + hook = g_OutputManager.FreeHooks.top(); g_OutputManager.FreeHooks.pop(); } @@ -231,22 +217,11 @@ omg_hooks *EntityOutputManager::NewHook() void EntityOutputManager::OnHookAdded() { HookCount++; - - if (HookCount == 1) - { - // This is the first hook created - fireOutputDetour->EnableDetour(); - } } void EntityOutputManager::OnHookRemoved() { HookCount--; - - if (HookCount == 0) - { - fireOutputDetour->DisableDetour(); - } } void EntityOutputManager::CleanUpHook(omg_hooks *hook) @@ -256,14 +231,14 @@ void EntityOutputManager::CleanUpHook(omg_hooks *hook) OnHookRemoved(); IPlugin *pPlugin = plsys->FindPluginByContext(hook->pf->GetParentContext()->GetContext()); - SourceHook::List *pList = NULL; + std::list *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { return; } - SourceHook::List::iterator p_iter = pList->begin(); + auto p_iter = pList->begin(); omg_hooks *pluginHook; @@ -283,11 +258,11 @@ void EntityOutputManager::CleanUpHook(omg_hooks *hook) void EntityOutputManager::OnPluginDestroyed(IPlugin *plugin) { - SourceHook::List *pList = NULL; + std::list *pList = NULL; if (plugin->GetProperty("OutputHookList", (void **)&pList, true)) { - SourceHook::List::iterator p_iter = pList->begin(); + auto p_iter = pList->begin(); omg_hooks *hook; while (p_iter != pList->end()) diff --git a/extensions/sdktools/output.h b/extensions/sdktools/output.h index 02ec9da5d4..f53d8c14d4 100644 --- a/extensions/sdktools/output.h +++ b/extensions/sdktools/output.h @@ -34,10 +34,9 @@ #include #include -#include "sh_list.h" -#include "sh_stack.h" +#include +#include #include "sm_trie_tpl.h" -#include "CDetour/detours.h" extern ISourcePawnEngine *spengine; @@ -62,7 +61,7 @@ struct omg_hooks */ struct OutputNameStruct { - SourceHook::List hooks; + std::list hooks; char Name[50]; }; @@ -108,6 +107,15 @@ class EntityOutputManager : public IPluginsListener void OnHookAdded(); void OnHookRemoved(); +protected: +#if defined PLATFORM_WINDOWS && defined KE_ARCH_X86 + KHook::Return Hook_FireOutput(CBaseEntity*, int what, int the, int hell, int msvc, void*, CBaseEntity* pActivator, CBaseEntity* pCaller, float fDelay); + KHook::Member m_HookFireOutput; +#else + KHook::Return Hook_FireOutput(CBaseEntity*, void*, CBaseEntity* pActivator, CBaseEntity* pCaller, float fDelay); + KHook::Member m_HookFireOutput; +#endif + private: bool enabled; @@ -124,7 +132,7 @@ class EntityOutputManager : public IPluginsListener // Maps classname to a ClassNameStruct IBasicTrie *ClassNames; - SourceHook::CStack FreeHooks; //Stores hook pointers to avoid calls to new + std::stack FreeHooks; //Stores hook pointers to avoid calls to new int HookCount; diff --git a/extensions/sdktools/outputnatives.cpp b/extensions/sdktools/outputnatives.cpp index c90cb42a15..4a8a618f62 100644 --- a/extensions/sdktools/outputnatives.cpp +++ b/extensions/sdktools/outputnatives.cpp @@ -65,14 +65,14 @@ cell_t HookSingleEntityOutput(IPluginContext *pContext, const cell_t *params) OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true); //Check for an existing identical hook - SourceHook::List::iterator _iter; + std::list::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); - for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) + for (auto _iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; if (hook->pf == pFunction && hook->entity_ref == gamehelpers->EntityToReference(pEntity)) @@ -95,11 +95,11 @@ cell_t HookSingleEntityOutput(IPluginContext *pContext, const cell_t *params) g_OutputManager.OnHookAdded(); IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); - SourceHook::List *pList = NULL; + std::list *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { - pList = new SourceHook::List; + pList = new std::list; pPlugin->SetProperty("OutputHookList", pList); } @@ -126,14 +126,13 @@ cell_t HookEntityOutput(IPluginContext *pContext, const cell_t *params) OutputNameStruct *pOutputName = g_OutputManager.FindOutputPointer((const char *)classname, outputname, true); //Check for an existing identical hook - SourceHook::List::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); - for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) + for (auto _iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; if (hook->pf == pFunction && hook->entity_ref == -1) @@ -158,11 +157,11 @@ cell_t HookEntityOutput(IPluginContext *pContext, const cell_t *params) g_OutputManager.OnHookAdded(); IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext()); - SourceHook::List *pList = NULL; + std::list *pList = NULL; if (!pPlugin->GetProperty("OutputHookList", (void **)&pList, false) || !pList) { - pList = new SourceHook::List; + pList = new std::list; pPlugin->SetProperty("OutputHookList", pList); } @@ -193,14 +192,13 @@ cell_t UnHookEntityOutput(IPluginContext *pContext, const cell_t *params) } //Check for an existing identical hook - SourceHook::List::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); - for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) + for (auto _iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; if (hook->pf == pFunction && hook->entity_ref == -1) @@ -250,14 +248,13 @@ cell_t UnHookSingleEntityOutput(IPluginContext *pContext, const cell_t *params) } //Check for an existing identical hook - SourceHook::List::iterator _iter; omg_hooks *hook; IPluginFunction *pFunction; pFunction = pContext->GetFunctionById(params[3]); - for (_iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) + for (auto _iter=pOutputName->hooks.begin(); _iter!=pOutputName->hooks.end(); _iter++) { hook = (omg_hooks *)*_iter; /* We're not serial checking and just removing by index here - This was always allowed so is left for bcompat */ diff --git a/extensions/sdktools/teamnatives.cpp b/extensions/sdktools/teamnatives.cpp index c35bb0b5ad..dbe03b1524 100644 --- a/extensions/sdktools/teamnatives.cpp +++ b/extensions/sdktools/teamnatives.cpp @@ -31,7 +31,7 @@ #include "extension.h" #include "vhelpers.h" -#include +#include struct TeamInfo { @@ -41,7 +41,7 @@ struct TeamInfo char m_iScore[64] = { 0 }; -SourceHook::CVector g_Teams; +std::vector g_Teams; void InitTeamNatives() { diff --git a/extensions/sdktools/tempents.cpp b/extensions/sdktools/tempents.cpp index 7cf1ef24e6..94fcabc11b 100644 --- a/extensions/sdktools/tempents.cpp +++ b/extensions/sdktools/tempents.cpp @@ -412,8 +412,7 @@ void TempEntityManager::Shutdown() return; } - SourceHook::List::iterator iter; - for (iter=m_TEList.begin(); iter!=m_TEList.end(); iter++) + for (auto iter=m_TEList.begin(); iter!=m_TEList.end(); iter++) { delete (*iter); } diff --git a/extensions/sdktools/tempents.h b/extensions/sdktools/tempents.h index fddb86144c..75c3beafba 100644 --- a/extensions/sdktools/tempents.h +++ b/extensions/sdktools/tempents.h @@ -34,8 +34,8 @@ #include "extension.h" #include -#include -#include +#include +#include #include class TempEntityInfo @@ -61,7 +61,7 @@ class TempEntityInfo private: void *m_Me; ServerClass *m_Sc; - SourceHook::String m_Name; + std::string m_Name; }; class TempEntityManager @@ -79,7 +79,7 @@ class TempEntityManager void DumpList(); void DumpProps(FILE *fp); private: - SourceHook::List m_TEList; + std::list m_TEList; IBasicTrie *m_TempEntInfo; void *m_ListHead; int m_NameOffs; @@ -91,7 +91,7 @@ class TempEntityManager struct TEHookInfo { TempEntityInfo *te; - SourceHook::List lst; + std::list lst; }; class TempEntHooks : public IPluginsListener @@ -99,18 +99,20 @@ class TempEntHooks : public IPluginsListener public: //IPluginsListener void OnPluginUnloaded(IPlugin *plugin); public: + TempEntHooks(); void Initialize(); void Shutdown(); bool AddHook(const char *name, IPluginFunction *pFunc); bool RemoveHook(const char *name, IPluginFunction *pFunc); - void OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID); + KHook::Return OnPlaybackTempEntity(IVEngineServer*, IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID); + KHook::Virtual m_HookPlaybackTempEntity; private: void _IncRefCounter(); void _DecRefCounter(); size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter); private: IBasicTrie *m_TEHooks; - SourceHook::List m_HookInfo; + std::list m_HookInfo; size_t m_HookCount; }; diff --git a/extensions/sdktools/tenatives.cpp b/extensions/sdktools/tenatives.cpp index 014538aea5..ea1327c03b 100644 --- a/extensions/sdktools/tenatives.cpp +++ b/extensions/sdktools/tenatives.cpp @@ -33,8 +33,6 @@ #include "CellRecipientFilter.h" #include -SH_DECL_HOOK5_void(IVEngineServer, PlaybackTempEntity, SH_NOATTRIB, 0, IRecipientFilter &, float, const void *, const SendTable *, int); - CellRecipientFilter g_TERecFilter; TempEntityInfo *g_CurrentTE = NULL; int g_TEPlayers[SM_MAXPLAYERS+1]; @@ -46,6 +44,10 @@ bool tenatives_initialized = false; * * **************************/ +TempEntHooks::TempEntHooks() : + m_HookPlaybackTempEntity(&IVEngineServer::PlaybackTempEntity, this, &TempEntHooks::OnPlaybackTempEntity, nullptr) +{} + void TempEntHooks::Initialize() { m_TEHooks = adtfactory->CreateBasicTrie(); @@ -61,8 +63,7 @@ void TempEntHooks::Shutdown() } plsys->RemovePluginsListener(this); - SourceHook::List::iterator iter; - for (iter=m_HookInfo.begin(); iter!=m_HookInfo.end(); iter++) + for (auto iter=m_HookInfo.begin(); iter!=m_HookInfo.end(); iter++) { delete (*iter); } @@ -77,13 +78,13 @@ void TempEntHooks::Shutdown() void TempEntHooks::OnPluginUnloaded(IPlugin *plugin) { - SourceHook::List::iterator iter = m_HookInfo.begin(); + auto iter = m_HookInfo.begin(); IPluginContext *pContext = plugin->GetBaseContext(); /* For each hook list... */ while (iter != m_HookInfo.end()) { - SourceHook::List::iterator f_iter = (*iter)->lst.begin(); + auto f_iter = (*iter)->lst.begin(); /* Find the hooks on the given temp entity */ while (f_iter != (*iter)->lst.end()) @@ -120,7 +121,7 @@ void TempEntHooks::_IncRefCounter() { if (m_HookCount++ == 0) { - SH_ADD_HOOK(IVEngineServer, PlaybackTempEntity, engine, SH_MEMBER(this, &TempEntHooks::OnPlaybackTempEntity), false); + m_HookPlaybackTempEntity.Add(engine); } } @@ -128,7 +129,7 @@ void TempEntHooks::_DecRefCounter() { if (--m_HookCount == 0) { - SH_REMOVE_HOOK(IVEngineServer, PlaybackTempEntity, engine, SH_MEMBER(this, &TempEntHooks::OnPlaybackTempEntity), false); + m_HookPlaybackTempEntity.Remove(engine); } } @@ -177,8 +178,9 @@ bool TempEntHooks::RemoveHook(const char *name, IPluginFunction *pFunc) if (m_TEHooks->Retrieve(name, reinterpret_cast(&pInfo))) { - SourceHook::List::iterator iter; - if ((iter=pInfo->lst.find(pFunc)) != pInfo->lst.end()) + auto iter = pInfo->lst.begin(); + while (iter != pInfo->lst.end() && *iter != pFunc) { iter++; }; + if (iter != pInfo->lst.end()) { pInfo->lst.erase(iter); if (pInfo->lst.empty()) @@ -198,14 +200,13 @@ bool TempEntHooks::RemoveHook(const char *name, IPluginFunction *pFunc) return true; } -void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID) +KHook::Return TempEntHooks::OnPlaybackTempEntity(IVEngineServer*, IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID) { TEHookInfo *pInfo; const char *name = g_TEManager.GetNameFromThisPtr(const_cast(pSender)); if (m_TEHooks->Retrieve(name, reinterpret_cast(&pInfo))) { - SourceHook::List::iterator iter; IPluginFunction *pFunc; size_t size; cell_t res = static_cast(Pl_Continue); @@ -214,7 +215,7 @@ void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, c g_CurrentTE = pInfo->te; size = _FillInPlayers(g_TEPlayers, &filter); - for (iter=pInfo->lst.begin(); iter!=pInfo->lst.end(); iter++) + for (auto iter=pInfo->lst.begin(); iter!=pInfo->lst.end(); iter++) { pFunc = (*iter); pFunc->PushString(name); @@ -226,13 +227,13 @@ void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, c if (res != Pl_Continue) { g_CurrentTE = oldinfo; - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } } g_CurrentTE = oldinfo; - RETURN_META(MRES_IGNORED); } + return { KHook::Action::Ignore }; } /********************** diff --git a/extensions/sdktools/vcallbuilder.cpp b/extensions/sdktools/vcallbuilder.cpp index 36d3a1f526..17c6231c73 100644 --- a/extensions/sdktools/vcallbuilder.cpp +++ b/extensions/sdktools/vcallbuilder.cpp @@ -46,7 +46,7 @@ ValveCall::~ValveCall() { while (!stk.empty()) { - unsigned char *ptr = stk.front(); + unsigned char *ptr = stk.top(); delete [] ptr; stk.pop(); } @@ -65,7 +65,7 @@ unsigned char *ValveCall::stk_get() { ptr = new unsigned char[stackSize]; } else { - ptr = stk.front(); + ptr = stk.top(); stk.pop(); } return ptr; diff --git a/extensions/sdktools/vcallbuilder.h b/extensions/sdktools/vcallbuilder.h index 3237fe5dc0..2a63cd8794 100644 --- a/extensions/sdktools/vcallbuilder.h +++ b/extensions/sdktools/vcallbuilder.h @@ -32,7 +32,7 @@ #ifndef _INCLUDE_SOURCEMOD_VALVE_CALLER_H_ #define _INCLUDE_SOURCEMOD_VALVE_CALLER_H_ -#include +#include #include #include "vdecoder.h" @@ -51,7 +51,7 @@ struct ValveCall size_t stackSize; /**< Stack size */ size_t stackEnd; /**< End of the bintools stack */ unsigned char *retbuf; /**< Return buffer */ - SourceHook::CStack stk; /**< Parameter stack */ + std::stack stk; /**< Parameter stack */ unsigned char *stk_get(); void stk_put(unsigned char *ptr); diff --git a/extensions/sdktools/vglobals.cpp b/extensions/sdktools/vglobals.cpp index 49cd4b4def..b75f4d815e 100644 --- a/extensions/sdktools/vglobals.cpp +++ b/extensions/sdktools/vglobals.cpp @@ -45,7 +45,6 @@ void *GameRules() void InitializeValveGlobals() { g_EntList = gamehelpers->GetGlobalEntityList(); - /* * g_pGameRules * @@ -53,8 +52,7 @@ void InitializeValveGlobals() * If symbols aren't present (Windows or stripped Linux/Mac), * attempt find via CreateGameRulesObject + offset */ - - char *addr; + char *addr = nullptr; if (g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) && addr) { g_ppGameRules = reinterpret_cast(addr); @@ -262,7 +260,7 @@ void GetIServer() } /* Get the CreateFakeClient function pointer */ - if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient))) + if (!(vfunc=KHook::FindOriginalVirtual(*(void***)engine, KHook::GetVtableIndex(&IVEngineServer::CreateFakeClient)))) { return; } diff --git a/extensions/sdktools/vhelpers.h b/extensions/sdktools/vhelpers.h index 47180b9505..fb31a0bb82 100644 --- a/extensions/sdktools/vhelpers.h +++ b/extensions/sdktools/vhelpers.h @@ -32,7 +32,7 @@ #ifndef _INCLUDE_SDKTOOLS_VHELPERS_H_ #define _INCLUDE_SDKTOOLS_VHELPERS_H_ -#include +#include #include #include diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp index 559276ff27..df144416fa 100644 --- a/extensions/sdktools/vnatives.cpp +++ b/extensions/sdktools/vnatives.cpp @@ -30,7 +30,7 @@ */ #include -#include +#include #include "extension.h" #include "vcallbuilder.h" #include "vnatives.h" @@ -43,8 +43,8 @@ #include "am-string.h" #include -SourceHook::List g_RegCalls; -SourceHook::List g_CallWraps; +std::list g_RegCalls; +std::list g_CallWraps; #define ENTINDEX_TO_CBASEENTITY(ref, buffer) \ buffer = gamehelpers->ReferenceToEntity(ref); \ @@ -631,7 +631,7 @@ static cell_t SetClientViewEntity(IPluginContext *pContext, const cell_t *params return 1; } -static SourceHook::String *g_lightstyle[MAX_LIGHTSTYLES] = {NULL}; +static std::string *g_lightstyle[MAX_LIGHTSTYLES] = {NULL}; static cell_t SetLightStyle(IPluginContext *pContext, const cell_t *params) { int style = params[1]; @@ -647,7 +647,7 @@ static cell_t SetLightStyle(IPluginContext *pContext, const cell_t *params) * this or not on shutdown, but for ~4K of memory MAX, it doesn't seem worth it yet. * So, it's a :TODO:! */ - g_lightstyle[style] = new SourceHook::String(); + g_lightstyle[style] = new std::string(); } char *str; diff --git a/extensions/sdktools/vnatives.h b/extensions/sdktools/vnatives.h index 746123608a..faacdafd1e 100644 --- a/extensions/sdktools/vnatives.h +++ b/extensions/sdktools/vnatives.h @@ -32,9 +32,9 @@ #ifndef _INCLUDE_SDKTOOLS_VNATIVES_H_ #define _INCLUDE_SDKTOOLS_VNATIVES_H_ -#include +#include -extern SourceHook::List g_RegCalls; +extern std::list g_RegCalls; extern sp_nativeinfo_t g_Natives[]; extern sp_nativeinfo_t g_SoundNatives[]; diff --git a/extensions/sdktools/voice.cpp b/extensions/sdktools/voice.cpp index d872b8f7e0..4fa7c25845 100644 --- a/extensions/sdktools/voice.cpp +++ b/extensions/sdktools/voice.cpp @@ -56,30 +56,22 @@ size_t g_VoiceHookCount = 0; ListenOverride g_VoiceMap[SM_MAXPLAYERS+1][SM_MAXPLAYERS+1]; bool g_ClientMutes[SM_MAXPLAYERS+1][SM_MAXPLAYERS+1]; -SH_DECL_HOOK3(IVoiceServer, SetClientListening, SH_NOATTRIB, 0, bool, int, int, bool); - -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); -#else -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -#endif - -bool DecHookCount() +bool SDKTools::DecListeningHookCount() { if (--g_VoiceHookCount == 0) { - SH_REMOVE_HOOK(IVoiceServer, SetClientListening, voiceserver, SH_MEMBER(&g_SdkTools, &SDKTools::OnSetClientListening), false); + m_HookSetClientListening.Remove(voiceserver); return true; } return false; } -void IncHookCount() +void SDKTools::IncListeningHookCount() { if (!g_VoiceHookCount++) { - SH_ADD_HOOK(IVoiceServer, SetClientListening, voiceserver, SH_MEMBER(&g_SdkTools, &SDKTools::OnSetClientListening), false); + m_HookSetClientListening.Add(voiceserver); } } @@ -88,7 +80,7 @@ void SDKTools::VoiceInit() memset(g_VoiceMap, 0, sizeof(g_VoiceMap)); memset(g_ClientMutes, 0, sizeof(g_ClientMutes)); - SH_ADD_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &SDKTools::OnClientCommand), true); + m_HookClientCommand.Add(serverClients); } void SDKTools::VoiceShutdown() @@ -96,17 +88,17 @@ void SDKTools::VoiceShutdown() if (g_VoiceHookCount > 0) { g_VoiceHookCount = 1; - DecHookCount(); + g_SdkTools.DecListeningHookCount(); } - SH_REMOVE_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &SDKTools::OnClientCommand), true); + m_HookClientCommand.Remove(serverClients); } #if SOURCE_ENGINE >= SE_ORANGEBOX -void SDKTools::OnClientCommand(edict_t *pEntity, const CCommand &args) +KHook::Return SDKTools::OnClientCommand(IServerGameClients*, edict_t *pEntity, const CCommand &args) { int client = IndexOfEdict(pEntity); #else -void SDKTools::OnClientCommand(edict_t *pEntity) +KHook::Return SDKTools::OnClientCommand(IServerGameClients*, edict_t *pEntity) { CCommand args; int client = IndexOfEdict(pEntity); @@ -126,33 +118,33 @@ void SDKTools::OnClientCommand(edict_t *pEntity) } } - RETURN_META(MRES_IGNORED); + return { KHook::Action::Ignore }; } -bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen) +KHook::Return SDKTools::OnSetClientListening(IVoiceServer* server, int iReceiver, int iSender, bool bListen) { if (g_ClientMutes[iReceiver][iSender]) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, false); } if (g_VoiceFlags[iSender] & SPEAK_MUTED) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, false); } if (g_VoiceMap[iReceiver][iSender] == Listen_No) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, false)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, false); } else if (g_VoiceMap[iReceiver][iSender] == Listen_Yes) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, true); } if ((g_VoiceFlags[iSender] & SPEAK_ALL) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENALL)) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, true); } if ((g_VoiceFlags[iSender] & SPEAK_TEAM) || (g_VoiceFlags[iReceiver] & SPEAK_LISTENTEAM)) @@ -167,12 +159,12 @@ bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen) if (pRInfo && pSInfo && pRInfo->GetTeamIndex() == pSInfo->GetTeamIndex()) { - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, bListen, &IVoiceServer::SetClientListening, (iReceiver, iSender, true)); + return KHook::Recall(&IVoiceServer::SetClientListening, KHook::Return{ KHook::Action::Ignore, bListen }, server, iReceiver, iSender, true); } } } - RETURN_META_VALUE(MRES_IGNORED, bListen); + return { KHook::Action::Ignore, bListen }; } void SDKTools::OnClientDisconnecting(int client) @@ -207,7 +199,7 @@ void SDKTools::OnClientDisconnecting(int client) if (g_VoiceMap[i][client] != Listen_Default) { g_VoiceMap[i][client] = Listen_Default; - if (DecHookCount()) + if (g_SdkTools.DecListeningHookCount()) { break; } @@ -215,7 +207,7 @@ void SDKTools::OnClientDisconnecting(int client) if (g_VoiceMap[client][i] != Listen_Default) { g_VoiceMap[client][i] = Listen_Default; - if (DecHookCount()) + if (g_SdkTools.DecListeningHookCount()) { break; } @@ -225,7 +217,7 @@ void SDKTools::OnClientDisconnecting(int client) if (g_VoiceFlags[client]) { g_VoiceFlags[client] = SPEAK_NORMAL; - DecHookCount(); + g_SdkTools.DecListeningHookCount(); } } @@ -243,11 +235,11 @@ static cell_t SetClientListeningFlags(IPluginContext *pContext, const cell_t *pa if (!params[2] && g_VoiceFlags[params[1]]) { - DecHookCount(); + g_SdkTools.DecListeningHookCount(); } else if (!g_VoiceFlags[params[1]] && params[2]) { - IncHookCount(); + g_SdkTools.IncListeningHookCount(); } g_VoiceFlags[params[1]] = params[2]; @@ -301,12 +293,12 @@ static cell_t SetClientListening(IPluginContext *pContext, const cell_t *params) if (g_VoiceMap[r][s] == Listen_Default && params[3] != Listen_Default) { g_VoiceMap[r][s] = (ListenOverride) params[3]; - IncHookCount(); + g_SdkTools.IncListeningHookCount(); } else if (g_VoiceMap[r][s] != Listen_Default && params[3] == Listen_Default) { g_VoiceMap[r][s] = (ListenOverride) params[3]; - DecHookCount(); + g_SdkTools.DecListeningHookCount(); } else { diff --git a/extensions/sdktools/vsound.cpp b/extensions/sdktools/vsound.cpp index 52a131da62..72aea4f097 100644 --- a/extensions/sdktools/vsound.cpp +++ b/extensions/sdktools/vsound.cpp @@ -32,23 +32,6 @@ #include "vsound.h" #include -SH_DECL_HOOK8_void(IVEngineServer, EmitAmbientSound, SH_NOATTRIB, 0, int, const Vector &, const char *, float, soundlevel_t, int, int, float); - -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -SH_DECL_HOOK18(IEngineSound, EmitSound, SH_NOATTRIB, 0, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int, void *); -SH_DECL_HOOK18(IEngineSound, EmitSound, SH_NOATTRIB, 1, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int, void *); -#elif SOURCE_ENGINE >= SE_PORTAL2 -SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 0, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -SH_DECL_HOOK17(IEngineSound, EmitSound, SH_NOATTRIB, 1, int, IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -#elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ - || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII -SH_DECL_HOOK15_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -SH_DECL_HOOK15_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -#else -SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 0, IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -SH_DECL_HOOK14_void(IEngineSound, EmitSound, SH_NOATTRIB, 1, IRecipientFilter &, int, int, const char *, float, soundlevel_t, int, int, const Vector *, const Vector *, CUtlVector *, bool, float, int); -#endif - bool g_InSoundHook = false; /*************************** @@ -79,21 +62,27 @@ size_t SoundHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter) return size; } +SoundHooks::SoundHooks() : + m_HookEmitAmbientSound(&IVEngineServer::EmitAmbientSound, this, &SoundHooks::OnEmitAmbientSound, nullptr), + m_HookEmitSound(&IEngineSound::EmitSound, this, &SoundHooks::OnEmitSound, nullptr), + m_HookEmitSound2(&IEngineSound::EmitSound, this, &SoundHooks::OnEmitSound2, nullptr) +{} + void SoundHooks::_IncRefCounter(int type) { if (type == NORMAL_SOUND_HOOK) -{ - if (m_NormalCount++ == 0) { - SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); - SH_ADD_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); + if (m_NormalCount++ == 0) + { + m_HookEmitSound.Add(engsound); + m_HookEmitSound2.Add(engsound); + } } -} else if (type == AMBIENT_SOUND_HOOK) { if (m_AmbientCount++ == 0) { - SH_ADD_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); + m_HookEmitAmbientSound.Add(engine); } } } @@ -104,15 +93,15 @@ void SoundHooks::_DecRefCounter(int type) { if (--m_NormalCount == 0) { - SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); - SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); + m_HookEmitSound.Remove(engsound); + m_HookEmitSound2.Remove(engsound); } } else if (type == AMBIENT_SOUND_HOOK) { if (--m_AmbientCount == 0) { - SH_REMOVE_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); + m_HookEmitAmbientSound.Remove(engine); } } } @@ -127,12 +116,12 @@ void SoundHooks::Shutdown() plsys->RemovePluginsListener(this); if (m_NormalCount) { - SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound), false); - SH_REMOVE_HOOK(IEngineSound, EmitSound, engsound, SH_MEMBER(this, &SoundHooks::OnEmitSound2), false); + m_HookEmitSound.Remove(engsound); + m_HookEmitSound2.Remove(engsound); } if (m_AmbientCount) { - SH_REMOVE_HOOK(IVEngineServer, EmitAmbientSound, engine, SH_MEMBER(this, &SoundHooks::OnEmitAmbientSound), false); + m_HookEmitAmbientSound.Remove(engine); } } @@ -189,10 +178,11 @@ void SoundHooks::AddHook(int type, IPluginFunction *pFunc) bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc) { - SoundHookIter iter; if (type == NORMAL_SOUND_HOOK) { - if ((iter=m_NormalFuncs.find(pFunc)) != m_NormalFuncs.end()) + auto iter = m_NormalFuncs.begin(); + while (iter != m_NormalFuncs.end() && *iter != pFunc) { iter++; } + if (iter != m_NormalFuncs.end()) { m_NormalFuncs.erase(iter); _DecRefCounter(NORMAL_SOUND_HOOK); @@ -205,7 +195,9 @@ bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc) } else if (type == AMBIENT_SOUND_HOOK) { - if ((iter=m_AmbientFuncs.find(pFunc)) != m_AmbientFuncs.end()) + auto iter = m_AmbientFuncs.begin(); + while (iter != m_AmbientFuncs.end() && *iter != pFunc) { iter++; } + if (iter != m_AmbientFuncs.end()) { m_AmbientFuncs.erase(iter); _DecRefCounter(AMBIENT_SOUND_HOOK); @@ -220,7 +212,7 @@ bool SoundHooks::RemoveHook(int type, IPluginFunction *pFunc) return false; } -void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, +KHook::Return SoundHooks::OnEmitAmbientSound(IVEngineServer* this_ptr, int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay) { SoundHookIter iter; @@ -250,7 +242,7 @@ void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char case Pl_Handled: case Pl_Stop: { - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; } case Pl_Changed: { @@ -258,11 +250,11 @@ void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char vec2.x = sp_ctof(vec[0]); vec2.y = sp_ctof(vec[1]); vec2.z = sp_ctof(vec[2]); - RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, - (entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay)); + return KHook::Recall(&IVEngineServer::EmitAmbientSound, { KHook::Action::Ignore }, this_ptr, entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay); } } } + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE >= SE_PORTAL2 @@ -317,23 +309,23 @@ uint32 GenerateSoundEntryHash(char const *pSoundEntry) #endif #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, +KHook::Return SoundHooks::OnEmitSound(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity, void *pUnknown) #elif SOURCE_ENGINE >= SE_PORTAL2 -int SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, +KHook::Return SoundHooks::OnEmitSound(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII -void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, +KHook::Return SoundHooks::OnEmitSound(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #else -void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, +KHook::Return SoundHooks::OnEmitSound(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) @@ -381,9 +373,9 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann case Pl_Stop: { #if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_SUPERCEDE, -1); + return { KHook::Action::Supersede, -1 }; #else - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; #endif } case Pl_Changed: @@ -391,12 +383,7 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann if (size < 0 || size > SM_ARRAYSIZE(players)) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Callback-provided size %d is invalid", size); - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1); -#else - return; -#endif + return { KHook::Action::Ignore }; } /* Client validation */ @@ -408,12 +395,7 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann if (!pPlayer) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Callback-provided client index %d is invalid", client); - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1); -#else - return; -#endif + return { KHook::Action::Ignore }; } else if (!pPlayer->IsInGame()) { // Shift array down to remove non-ingame client memmove(&players[i], &players[i+1], (size-i-1) * sizeof(int)); @@ -435,68 +417,67 @@ void SoundHooks::OnEmitSound(IRecipientFilter &filter, int iEntIndex, int iChann CellRecipientFilter crf; crf.Initialize(players, size); #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - RETURN_META_VALUE_NEWPARAMS( - MRES_IGNORED, - -1, - static_cast *, bool, float, int, void *)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin, - pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, nullptr) + return KHook::Recall *, bool, float, int, void *)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore, -1 }, + this_ptr, + crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin, + pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, nullptr ); #elif SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE_NEWPARAMS( - MRES_IGNORED, - -1, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin, - pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore, -1 }, + this_ptr, + crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, iSoundlevel, nSeed, iFlags, iPitch, pOrigin, + pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII - RETURN_META_NEWPARAMS( - MRES_IGNORED, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, iSpecialDSP, pOrigin, - pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore }, + this_ptr, + crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, iSpecialDSP, pOrigin, + pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #else - RETURN_META_NEWPARAMS( - MRES_IGNORED, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin, - pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore }, + this_ptr, + crf, iEntIndex, iChannel, buffer, flVolume, iSoundlevel, iFlags, iPitch, pOrigin, + pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #endif } } } - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1 ); -#endif + return { KHook::Action::Ignore }; } #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, +KHook::Return SoundHooks::OnEmitSound2(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity, void *pUnknown) #elif SOURCE_ENGINE >= SE_PORTAL2 -int SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, +KHook::Return SoundHooks::OnEmitSound2(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII -void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, +KHook::Return SoundHooks::OnEmitSound2(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #else -void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, +KHook::Return SoundHooks::OnEmitSound2(IEngineSound* this_ptr, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) @@ -545,9 +526,9 @@ void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChan case Pl_Stop: { #if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_SUPERCEDE, -1); + return { KHook::Action::Supersede, -1 }; #else - RETURN_META(MRES_SUPERCEDE); + return { KHook::Action::Supersede }; #endif } case Pl_Changed: @@ -555,12 +536,7 @@ void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChan if (size < 0 || size > SM_ARRAYSIZE(players)) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Callback-provided size %d is invalid", size); - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1); -#else - return; -#endif + return { KHook::Action::Ignore }; } /* Client validation */ @@ -572,12 +548,7 @@ void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChan if (!pPlayer) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Client index %d is invalid", client); - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1); -#else - return; -#endif + return { KHook::Action::Ignore }; } else if (!pPlayer->IsInGame()) { // Shift array down to remove non-ingame client memmove(&players[i], &players[i+1], (size-i-1) * sizeof(int)); @@ -599,48 +570,47 @@ void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChan CellRecipientFilter crf; crf.Initialize(players, size); #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - RETURN_META_VALUE_NEWPARAMS( - MRES_IGNORED, - -1, - static_cast *, bool, float, int, void *)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), - nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, pUnknown) + return KHook::Recall *, bool, float, int, void *)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore, -1 }, + this_ptr, + crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, (float)SNDLVL_TO_ATTN(static_cast(sndlevel)), + nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, pUnknown ); #elif SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE_NEWPARAMS( - MRES_IGNORED, - -1, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), - nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore, -1 }, + this_ptr, + crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, (float)SNDLVL_TO_ATTN(static_cast(sndlevel)), + nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII -RETURN_META_NEWPARAMS( - MRES_IGNORED, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), - iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore }, + this_ptr, + crf, iEntIndex, iChannel, buffer, flVolume, (float)SNDLVL_TO_ATTN(static_cast(sndlevel)), + iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #else - RETURN_META_NEWPARAMS( - MRES_IGNORED, - static_cast *, bool, float, int)>(&IEngineSound::EmitSound), - (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast(sndlevel)), - iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) + return KHook::Recall *, bool, float, int)>( + &IEngineSound::EmitSound, + { KHook::Action::Ignore }, + this_ptr, + crf, iEntIndex, iChannel, buffer, flVolume, (float)SNDLVL_TO_ATTN(static_cast(sndlevel)), + iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity ); #endif } } } - -#if SOURCE_ENGINE >= SE_PORTAL2 - RETURN_META_VALUE(MRES_IGNORED, -1 ); -#endif + return { KHook::Action::Ignore }; } bool GetSoundParams(CSoundParameters *soundParams, const char *soundname, cell_t entindex) @@ -766,7 +736,8 @@ static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params) if (g_InSoundHook) { - ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); + KHook::CallOriginal + (&IVEngineServer::EmitAmbientSound, engine, entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); } else { @@ -910,12 +881,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int, void *)> - - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int, void *)>( + &IEngineSound::EmitSound, + engsound, + crf, player[0], channel, sample, @@ -958,13 +928,12 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #elif SOURCE_ENGINE >= SE_PORTAL2 if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - - (&IEngineSound::EmitSound)) - (crf, - player[0], + KHook::CallOriginal *, bool, float, int)>( + &IEngineSound::EmitSound, + engsound, + crf, + player[0], channel, sample, -1, @@ -1005,11 +974,12 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int)> + ( + &IEngineSound::EmitSound, + engsound, + crf, player[0], channel, sample, @@ -1046,11 +1016,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #else if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int)>( + &IEngineSound::EmitSound, + engsound, + crf, player[0], channel, sample, @@ -1088,11 +1058,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int, void *)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int, void *)>( + &IEngineSound::EmitSound, + engsound, + crf, entity, channel, sample, @@ -1135,11 +1105,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #elif SOURCE_ENGINE >= SE_PORTAL2 if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int)>( + &IEngineSound::EmitSound, + engsound, + crf, entity, channel, sample, @@ -1181,11 +1151,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int)>( + &IEngineSound::EmitSound, + engsound, + crf, entity, channel, sample, @@ -1222,11 +1192,11 @@ static cell_t EmitSound(IPluginContext *pContext, const cell_t *params) #else if (g_InSoundHook) { - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound)) - (crf, + KHook::CallOriginal *, bool, float, int)>( + &IEngineSound::EmitSound, + engsound, + crf, entity, channel, sample, @@ -1373,16 +1343,14 @@ static cell_t EmitSoundEntry(IPluginContext *pContext, const cell_t *params) if (g_InSoundHook) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV -SH_CALL(enginesoundPatch, - static_cast *, bool, float, int, void *)> - (&IEngineSound::EmitSound))(crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, + (&IEngineSound::EmitSound, engsound, crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity, nullptr); #else - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound))(crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, + &IEngineSound::EmitSound, engsound, crf, player[0], channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity); #endif } @@ -1397,16 +1365,14 @@ SH_CALL(enginesoundPatch, if (g_InSoundHook) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int, void *)> - (&IEngineSound::EmitSound))(crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, + (&IEngineSound::EmitSound, engsound, crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity, nullptr); #else - SH_CALL(enginesoundPatch, - static_cast *, bool, float, int)> - (&IEngineSound::EmitSound))(crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, + (&IEngineSound::EmitSound, engsound, crf, entity, channel, soundEntry, soundEntryHash, sample, vol, (soundlevel_t)level, seed, flags, pitch, pOrigin, pDir, pOrigVec, updatePos, soundtime, speakerentity); #endif } diff --git a/extensions/sdktools/vsound.h b/extensions/sdktools/vsound.h index 11f277aa81..f852615358 100644 --- a/extensions/sdktools/vsound.h +++ b/extensions/sdktools/vsound.h @@ -32,63 +32,72 @@ #ifndef _INCLUDE_SOURCEMOD_VSOUND_H_ #define _INCLUDE_SOURCEMOD_VSOUND_H_ -#include +#include #include "extension.h" #include "CellRecipientFilter.h" #define NORMAL_SOUND_HOOK 0 #define AMBIENT_SOUND_HOOK 1 -typedef SourceHook::List::iterator SoundHookIter; +typedef std::list::iterator SoundHookIter; class SoundHooks : public IPluginsListener { public: //IPluginsListener void OnPluginUnloaded(IPlugin *plugin); public: + SoundHooks(); void Initialize(); void Shutdown(); void AddHook(int type, IPluginFunction *pFunc); bool RemoveHook(int type, IPluginFunction *pFunc); - void OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay); + KHook::Virtual m_HookEmitAmbientSound; + KHook::Return OnEmitAmbientSound(IVEngineServer*, int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay); #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_MCV - int OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int, void*> m_HookEmitSound; + KHook::Return OnEmitSound(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity, void *pUnknown); - int OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, + KHook::Virtual*, bool, float, int, void*> m_HookEmitSound2; + KHook::Return OnEmitSound2(IEngineSound*, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity, void *pUnknown); #elif SOURCE_ENGINE >= SE_PORTAL2 - int OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int> m_HookEmitSound; + KHook::Return OnEmitSound(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *, unsigned int, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); - int OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, + KHook::Virtual*, bool, float, int> m_HookEmitSound2; + KHook::Return OnEmitSound2(IEngineSound*, IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSoundEntry, unsigned int nSoundEntryHash, const char *pSample, float flVolume, float flAttenuation, int nSeed, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); #else #if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_PVKII - - void OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int> m_HookEmitSound; + KHook::Return OnEmitSound(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); - void OnEmitSound2(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int> m_HookEmitSound2; + KHook::Return OnEmitSound2(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, int iSpecialDSP, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); #else - void OnEmitSound(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int> m_HookEmitSound; + KHook::Return OnEmitSound(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, soundlevel_t iSoundlevel, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); - void OnEmitSound2(IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, + KHook::Virtual*, bool, float, int> m_HookEmitSound2; + KHook::Return OnEmitSound2(IEngineSound*, IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity); @@ -99,8 +108,8 @@ class SoundHooks : public IPluginsListener void _IncRefCounter(int type); void _DecRefCounter(int type); private: - SourceHook::List m_AmbientFuncs; - SourceHook::List m_NormalFuncs; + std::list m_AmbientFuncs; + std::list m_NormalFuncs; size_t m_NormalCount; size_t m_AmbientCount; }; diff --git a/extensions/sqlite/driver/SqDatabase.h b/extensions/sqlite/driver/SqDatabase.h index ee4d49ac2d..dab02ba818 100644 --- a/extensions/sqlite/driver/SqDatabase.h +++ b/extensions/sqlite/driver/SqDatabase.h @@ -72,7 +72,7 @@ class SqDatabase sqlite3 *m_sq3; std::recursive_mutex m_FullLock; bool m_Persistent; - String m_LastError; + std::string m_LastError; int m_LastErrorCode; }; diff --git a/extensions/sqlite/driver/SqDriver.cpp b/extensions/sqlite/driver/SqDriver.cpp index 3b4ffbaff7..9b72e1ef3b 100644 --- a/extensions/sqlite/driver/SqDriver.cpp +++ b/extensions/sqlite/driver/SqDriver.cpp @@ -77,9 +77,8 @@ SqDriver::~SqDriver() { std::lock_guard lock(m_OpenLock); - List::iterator iter; SqDatabase *sqdb; - for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) + for (auto iter = m_Cache.begin(); iter != m_Cache.end(); iter++) { // Don't let SqDatabase try to remove itself from m_Cache // now that we're gone. @@ -258,8 +257,7 @@ IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *er if (persistent) { /* See if anything in the cache matches */ - List::iterator iter; - for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) + for (auto iter = m_Cache.begin(); iter != m_Cache.end(); iter++) { if ((*iter).path.compare(fullpath) == 0) { @@ -298,8 +296,7 @@ void SqDriver::RemovePersistent(IDatabase *pdb) { std::lock_guard lock(m_OpenLock); - List::iterator iter; - for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) + for (auto iter = m_Cache.begin(); iter != m_Cache.end(); iter++) { if ((*iter).db == pdb) { diff --git a/extensions/sqlite/driver/SqDriver.h b/extensions/sqlite/driver/SqDriver.h index e41c9e7028..6d2f0e48cf 100644 --- a/extensions/sqlite/driver/SqDriver.h +++ b/extensions/sqlite/driver/SqDriver.h @@ -34,17 +34,16 @@ #define SOURCEMOD_SQL_DRIVER_CODE #include -#include -#include +#include +#include #include #include "sqlite-source/sqlite3.h" using namespace SourceMod; -using namespace SourceHook; struct SqDbInfo { - String path; + std::string path; IDatabase *db; }; @@ -73,7 +72,7 @@ class SqDriver : public IDBDriver private: Handle_t m_Handle; std::mutex m_OpenLock; - List m_Cache; + std::list m_Cache; bool m_bThreadSafe; bool m_bShutdown; }; diff --git a/extensions/sqlite/driver/SqQuery.h b/extensions/sqlite/driver/SqQuery.h index 2881d2d61a..cc20993c29 100644 --- a/extensions/sqlite/driver/SqQuery.h +++ b/extensions/sqlite/driver/SqQuery.h @@ -86,7 +86,7 @@ class SqQuery : sqlite3_stmt *m_pStmt; SqResults *m_pResults; unsigned int m_ParamCount; - String m_LastError; + std::string m_LastError; int m_LastErrorCode; unsigned int m_AffectedRows; unsigned int m_InsertID; diff --git a/extensions/sqlite/driver/SqResults.cpp b/extensions/sqlite/driver/SqResults.cpp index 3bd0be388c..75a40b3c88 100644 --- a/extensions/sqlite/driver/SqResults.cpp +++ b/extensions/sqlite/driver/SqResults.cpp @@ -42,7 +42,7 @@ SqResults::SqResults(SqQuery *query) : m_ColCount = sqlite3_column_count(m_pStmt); if (m_ColCount) { - m_ColNames = new String[m_ColCount]; + m_ColNames = new std::string[m_ColCount]; for (unsigned int i=0; i enum MemberType { @@ -75,7 +75,7 @@ struct StructInfo char name[100]; int size; KTrie members; - SourceHook::List membersList; + std::list membersList; bool getOffset(const char *member, int *offset); bool getType(const char *member, MemberType*type); diff --git a/extensions/tf2/AMBuilder b/extensions/tf2/AMBuilder index ffd8f1e168..63f0b9ffe0 100644 --- a/extensions/tf2/AMBuilder +++ b/extensions/tf2/AMBuilder @@ -1,6 +1,19 @@ # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: import os +sources = [ + 'extension.cpp', + 'natives.cpp', + 'RegNatives.cpp', + 'util.cpp', + 'criticals.cpp', + 'holiday.cpp', + 'teleporter.cpp', + 'gameplayrules.cpp', + 'conditions.cpp', + '../../public/smsdk_ext.cpp' +] + if 'tf2' in SM.sdks: sdk = SM.sdks['tf2'] @@ -8,18 +21,6 @@ if 'tf2' in SM.sdks: if not cxx.target.arch in sdk['platforms'][cxx.target.platform]: continue binary = SM.HL2Library(builder, cxx, 'game.tf2.ext.' + sdk['extension'], sdk) - SM.AddCDetour(binary) - binary.sources += [ - 'extension.cpp', - 'natives.cpp', - 'RegNatives.cpp', - 'util.cpp', - 'criticals.cpp', - 'holiday.cpp', - 'teleporter.cpp', - 'gameplayrules.cpp', - 'conditions.cpp', - '../../public/smsdk_ext.cpp' - ] + binary.sources += sources binary.compiler.defines += ['HAVE_STRING_H'] SM.extensions += [builder.Add(binary)] diff --git a/extensions/tf2/criticals.cpp b/extensions/tf2/criticals.cpp index 3a4621f773..08fd9d126c 100644 --- a/extensions/tf2/criticals.cpp +++ b/extensions/tf2/criticals.cpp @@ -32,12 +32,11 @@ #include "criticals.h" #include "util.h" -CritManager g_CritManager; - IForward *g_critForward = NULL; -SH_DECL_MANUALHOOK0(CalcIsAttackCriticalHelper, 0, 0, 0, bool); -SH_DECL_MANUALHOOK0(CalcIsAttackCriticalHelperNoCrits, 0, 0, 0, bool); +KHook::Virtual g_HookCalcIsAttackCriticalHelper; +KHook::Virtual g_HookCalcIsAttackCriticalHelperNoCrits; +CritManager g_CritManager; const char TF_WEAPON_DATATABLE[] = "DT_TFWeaponBase"; @@ -46,6 +45,9 @@ CritManager::CritManager() : m_hooksSetup(false) { m_entsHooked.Init(); + + g_HookCalcIsAttackCriticalHelper.AddContext(this, &CritManager::Hook_CalcIsAttackCriticalHelper, nullptr); + g_HookCalcIsAttackCriticalHelperNoCrits.AddContext(this, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits, nullptr); } bool CritManager::TryEnable() @@ -60,7 +62,7 @@ bool CritManager::TryEnable() return false; } - SH_MANUALHOOK_RECONFIGURE(CalcIsAttackCriticalHelper, offset, 0, 0); + g_HookCalcIsAttackCriticalHelper.Configure(offset); if (!g_pGameConf->GetOffset("CalcIsAttackCriticalHelperNoCrits", &offset)) { @@ -68,7 +70,7 @@ bool CritManager::TryEnable() return false; } - SH_MANUALHOOK_RECONFIGURE(CalcIsAttackCriticalHelperNoCrits, offset, 0, 0); + g_HookCalcIsAttackCriticalHelperNoCrits.Configure(offset); m_hooksSetup = true; } @@ -92,8 +94,8 @@ bool CritManager::TryEnable() continue; } - SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); - SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false); + g_HookCalcIsAttackCriticalHelper.Add(pEntity); + g_HookCalcIsAttackCriticalHelperNoCrits.Add(pEntity); m_entsHooked.Set(i); } @@ -109,9 +111,8 @@ void CritManager::Disable() for (i; i != -1; i = m_entsHooked.FindNextSetBit(i)) { CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i); - SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); - SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false); - + g_HookCalcIsAttackCriticalHelper.Remove(pEntity); + g_HookCalcIsAttackCriticalHelperNoCrits.Remove(pEntity); m_entsHooked.Set(i, false); } @@ -136,9 +137,9 @@ void CritManager::OnEntityCreated(CBaseEntity *pEntity, const char *classname) return; } - SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); - SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false); - + g_HookCalcIsAttackCriticalHelper.Add(pEntity); + g_HookCalcIsAttackCriticalHelperNoCrits.Add(pEntity); + m_entsHooked.Set(gamehelpers->EntityToBCompatRef(pEntity)); } @@ -154,49 +155,47 @@ void CritManager::OnEntityDestroyed(CBaseEntity *pEntity) if (!m_entsHooked.IsBitSet(index)) return; - SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); - SH_REMOVE_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false); + g_HookCalcIsAttackCriticalHelper.Remove(pEntity); + g_HookCalcIsAttackCriticalHelperNoCrits.Remove(pEntity); m_entsHooked.Set(index, false); } -bool CritManager::Hook_CalcIsAttackCriticalHelper() +KHook::Return CritManager::Hook_CalcIsAttackCriticalHelper(CBaseEntity* ent) { - return Hook_CalcIsAttackCriticalHelpers(false); + return Hook_CalcIsAttackCriticalHelpers(ent, false); } -bool CritManager::Hook_CalcIsAttackCriticalHelperNoCrits() +KHook::Return CritManager::Hook_CalcIsAttackCriticalHelperNoCrits(CBaseEntity* ent) { - return Hook_CalcIsAttackCriticalHelpers(true); + return Hook_CalcIsAttackCriticalHelpers(ent, true); } -bool CritManager::Hook_CalcIsAttackCriticalHelpers(bool noCrits) +KHook::Return CritManager::Hook_CalcIsAttackCriticalHelpers(CBaseEntity* pWeapon, bool noCrits) { - CBaseEntity *pWeapon = META_IFACEPTR(CBaseEntity); - // If there's an invalid ent or invalid server class here, we've got issues elsewhere. ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon); if (pServerClass == nullptr) { g_pSM->LogError(myself, "Invalid server class on weapon."); - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } sm_sendprop_info_t info; if (!gamehelpers->FindSendPropInfo(pServerClass->GetName(), "m_hOwnerEntity", &info)) { g_pSM->LogError(myself, "Could not find m_hOwnerEntity on %s", pServerClass->GetName()); - RETURN_META_VALUE(MRES_IGNORED, false); + return { KHook::Action::Ignore }; } int returnValue; if (noCrits) { - returnValue = SH_MCALL(pWeapon, CalcIsAttackCriticalHelperNoCrits)() ? 1 : 0; + returnValue = g_HookCalcIsAttackCriticalHelperNoCrits.CallOriginal(pWeapon) ? 1 : 0; } else { - returnValue = SH_MCALL(pWeapon, CalcIsAttackCriticalHelper)() ? 1 : 0; + returnValue = g_HookCalcIsAttackCriticalHelper.CallOriginal(pWeapon) ? 1 : 0; } int origReturnValue = returnValue; @@ -220,8 +219,8 @@ bool CritManager::Hook_CalcIsAttackCriticalHelpers(bool noCrits) if (result > Pl_Continue) { - RETURN_META_VALUE(MRES_SUPERCEDE, returnValue); + return { KHook::Action::Supersede, returnValue }; } - RETURN_META_VALUE(MRES_SUPERCEDE, origReturnValue); + return { KHook::Action::Supersede, origReturnValue }; } diff --git a/extensions/tf2/criticals.h b/extensions/tf2/criticals.h index 4013bc9548..aeba0cf204 100644 --- a/extensions/tf2/criticals.h +++ b/extensions/tf2/criticals.h @@ -33,9 +33,6 @@ #define _INCLUDE_SOURCEMOD_CRITICALS_H_ #include "extension.h" -#include -#include -#include "CDetour/detours.h" #include "ISDKHooks.h" class CritManager : public ISMEntityListener @@ -58,10 +55,10 @@ class CritManager : public ISMEntityListener public: // CritHook - bool Hook_CalcIsAttackCriticalHelper(); - bool Hook_CalcIsAttackCriticalHelperNoCrits(); + KHook::Return Hook_CalcIsAttackCriticalHelper(CBaseEntity*); + KHook::Return Hook_CalcIsAttackCriticalHelperNoCrits(CBaseEntity*); private: - bool Hook_CalcIsAttackCriticalHelpers(bool noCrits); + KHook::Return Hook_CalcIsAttackCriticalHelpers(CBaseEntity*, bool noCrits); private: bool m_enabled; diff --git a/extensions/tf2/extension.cpp b/extensions/tf2/extension.cpp index 620eec5697..b6b02326c2 100644 --- a/extensions/tf2/extension.cpp +++ b/extensions/tf2/extension.cpp @@ -40,7 +40,6 @@ #include "conditions.h" #include "gameplayrules.h" #include "teleporter.h" -#include "CDetour/detours.h" #include "ISDKHooks.h" #include "ISDKTools.h" @@ -69,7 +68,7 @@ extern sp_nativeinfo_t g_TFNatives[]; int g_resourceEntity; -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int , int); +KHook::Virtual g_HookServerActivate(&IServerGameDLL::ServerActivate, nullptr, OnServerActivate); bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) { @@ -108,8 +107,6 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late) return false; } - CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf); - sharesys->AddNatives(myself, g_TFNatives); sharesys->RegisterLibrary(myself, "tf2"); @@ -152,7 +149,7 @@ bool TF2Tools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool gpGlobals = ismm->GetCGlobals(); - SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_STATIC(OnServerActivate), true); + g_HookServerActivate.Add(gamedll); GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); @@ -164,7 +161,7 @@ bool TF2Tools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool void TF2Tools::SDK_OnUnload() { - SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_STATIC(OnServerActivate), true); + g_HookServerActivate.Remove(gamedll); g_HolidayManager.OnSDKUnload(); m_GameEventManager->RemoveListener(this); @@ -265,10 +262,12 @@ void TF2Tools::NotifyInterfaceDrop(SMInterface *pInterface) g_RegNatives.UnregisterAll(); } -void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax) +KHook::Return OnServerActivate(IServerGameDLL*, edict_t *pEdictList, int edictCount, int clientMax) { g_resourceEntity = FindResourceEntity(); g_HolidayManager.OnServerActivated(); + + return { KHook::Action::Ignore }; } bool TF2Tools::ProcessCommandTarget(cmd_target_info_t *info) diff --git a/extensions/tf2/extension.h b/extensions/tf2/extension.h index d9b2233408..53c040e9af 100644 --- a/extensions/tf2/extension.h +++ b/extensions/tf2/extension.h @@ -145,7 +145,7 @@ extern sm_sendprop_info_t *playerSharedOffset; extern CGlobalVars *gpGlobals; -void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); +KHook::Return OnServerActivate(IServerGameDLL*, edict_t *pEdictList, int edictCount, int clientMax); int FindResourceEntity(); int FindEntityByNetClass(int start, const char *classname); diff --git a/extensions/tf2/gameplayrules.cpp b/extensions/tf2/gameplayrules.cpp index 7451f82c7a..6c275d5025 100644 --- a/extensions/tf2/gameplayrules.cpp +++ b/extensions/tf2/gameplayrules.cpp @@ -30,16 +30,15 @@ */ #include "gameplayrules.h" +#include "extension.h" -CDetour *setInWaitingForPlayersDetour = NULL; +class CTeamplayRoundBasedRules; IForward *g_waitingPlayersStartForward = NULL; IForward *g_waitingPlayersEndForward = NULL; -DETOUR_DECL_MEMBER1(SetInWaitingForPlayers, void, bool, bWaitingForPlayers) +KHook::Return SetInWaitingForPlayers(CTeamplayRoundBasedRules*, bool bWaitingForPlayers) { - DETOUR_MEMBER_CALL(SetInWaitingForPlayers)(bWaitingForPlayers); - if (bWaitingForPlayers) { if (!g_waitingPlayersStartForward) @@ -62,23 +61,22 @@ DETOUR_DECL_MEMBER1(SetInWaitingForPlayers, void, bool, bWaitingForPlayers) g_waitingPlayersEndForward->Execute(NULL); } } + + return { KHook::Action::Ignore }; } +KHook::Member g_HookSetInWaitingForPlayers(nullptr, SetInWaitingForPlayers); bool InitialiseRulesDetours() { - setInWaitingForPlayersDetour = DETOUR_CREATE_MEMBER(SetInWaitingForPlayers, "SetInWaitingForPlayers"); - - if (setInWaitingForPlayersDetour != NULL) - { - setInWaitingForPlayersDetour->EnableDetour(); - return true; + void* addr = nullptr; + if (!g_pGameConf->GetMemSig("SetInWaitingForPlayers", &addr) || addr == nullptr) { + g_pSM->LogError(myself, "Failed to retrieve SetInWaitingForPlayers."); + return false; } - - g_pSM->LogError(myself, "No Gameplay Rules detours could be initialized - Disabled Gameplay Rules functions"); - return false; + g_HookSetInWaitingForPlayers.Configure(KHook::BuildMFP(addr)); + return true; } void RemoveRulesDetours() { - setInWaitingForPlayersDetour->Destroy(); -} +} diff --git a/extensions/tf2/gameplayrules.h b/extensions/tf2/gameplayrules.h index fd5672d5fd..2559c3b591 100644 --- a/extensions/tf2/gameplayrules.h +++ b/extensions/tf2/gameplayrules.h @@ -33,9 +33,6 @@ #define _INCLUDE_SOURCEMOD_GAMEPLAY_RULES_H_ #include "extension.h" -#include -#include -#include "CDetour/detours.h" bool InitialiseRulesDetours(); void RemoveRulesDetours(); @@ -43,4 +40,4 @@ void RemoveRulesDetours(); extern IForward *g_waitingPlayersStartForward; extern IForward *g_waitingPlayersEndForward; -#endif //_INCLUDE_SOURCEMOD_GAMEPLAY_RULES_H_ +#endif //_INCLUDE_SOURCEMOD_GAMEPLAY_RULES_H_ diff --git a/extensions/tf2/holiday.cpp b/extensions/tf2/holiday.cpp index 012cc150aa..527071a2fe 100644 --- a/extensions/tf2/holiday.cpp +++ b/extensions/tf2/holiday.cpp @@ -31,13 +31,13 @@ #include "holiday.h" -SH_DECL_MANUALHOOK1(IsHolidayActive, 0, 0, 0, bool, int); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0); +class CTFGameRules; +KHook::Virtual g_HookIsHolidayActive; +KHook::Virtual g_HookLevelShutdown(&IServerGameDLL::LevelShutdown); HolidayManager g_HolidayManager; HolidayManager::HolidayManager() : -m_iHookID(0), m_isHolidayForward(NULL), m_bInMap(false) { @@ -50,13 +50,17 @@ void HolidayManager::OnSDKLoad(bool bLate) plsys->AddPluginsListener(this); m_isHolidayForward = forwards->CreateForward("TF2_OnIsHolidayActive", ET_Event, 2, NULL, Param_Cell, Param_CellByRef); - SH_ADD_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &HolidayManager::Hook_LevelShutdown), false); + g_HookLevelShutdown.AddContext(this, &HolidayManager::Hook_LevelShutdown, nullptr); + g_HookIsHolidayActive.AddContext(this, &HolidayManager::Hook_IsHolidayActive, nullptr); + g_HookLevelShutdown.Add(gamedll); } void HolidayManager::OnSDKUnload() { + g_HookLevelShutdown.RemoveContext(this); + g_HookIsHolidayActive.RemoveContext(this); Unhook(); - SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &HolidayManager::Hook_LevelShutdown), false); + g_HookLevelShutdown.Remove(gamedll); plsys->RemovePluginsListener(this); forwards->ReleaseForward(m_isHolidayForward); @@ -69,25 +73,26 @@ void HolidayManager::OnServerActivated() HookIfNecessary(); } -void HolidayManager::Hook_LevelShutdown() +KHook::Return HolidayManager::Hook_LevelShutdown(IServerGameDLL*) { // GameRules is going away momentarily. Unhook before it does. Unhook(); m_bInMap = false; + return { KHook::Action::Ignore }; } void HolidayManager::HookIfNecessary() { // Already hooked - if (m_iHookID) + if (g_HookIsHolidayActive.IsActive()) return; // Nothing wants us if (m_isHolidayForward->GetFunctionCount() == 0) return; - void *pGameRules = GetGameRules(); + auto *pGameRules = GetGameRules(); if (!pGameRules) { if (m_bInMap) @@ -106,20 +111,15 @@ void HolidayManager::HookIfNecessary() return; } - SH_MANUALHOOK_RECONFIGURE(IsHolidayActive, offset, 0, 0); + g_HookIsHolidayActive.Configure(offset); } - m_iHookID = SH_ADD_MANUALHOOK(IsHolidayActive, pGameRules, SH_MEMBER(this, &HolidayManager::Hook_IsHolidayActive), false); + g_HookIsHolidayActive.Add(pGameRules); } void HolidayManager::Unhook() { - // Not hooked - if (!m_iHookID) - return; - - SH_REMOVE_HOOK_ID(m_iHookID); - m_iHookID = 0; + g_HookIsHolidayActive.ClearHooks(); } static inline void PopulateHolidayVar(IPluginRuntime *pRuntime, const char *pszName) @@ -169,15 +169,13 @@ void HolidayManager::OnPluginUnloaded(IPlugin *plugin) Unhook(); } -bool HolidayManager::Hook_IsHolidayActive(int holiday) +KHook::Return HolidayManager::Hook_IsHolidayActive(CTFGameRules* pGameRules, int holiday) { - void *pGameRules = META_IFACEPTR(void *); - - bool actualres = SH_MCALL(pGameRules, IsHolidayActive)(holiday); + bool actualres = g_HookIsHolidayActive.CallOriginal(pGameRules, holiday); if (!m_isHolidayForward) { g_pSM->LogMessage(myself, "Invalid Forward"); - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore }; } cell_t result = 0; @@ -189,8 +187,12 @@ bool HolidayManager::Hook_IsHolidayActive(int holiday) if (result > Pl_Continue) { - RETURN_META_VALUE(MRES_SUPERCEDE, (newres == 0) ? false : true); + return { KHook::Action::Supersede, (newres == 0) ? false : true }; } - RETURN_META_VALUE(MRES_IGNORED, true); + return { KHook::Action::Ignore }; } + +bool HolidayManager::IsHookEnabled() const { + return g_HookIsHolidayActive.IsActive(); +} \ No newline at end of file diff --git a/extensions/tf2/holiday.h b/extensions/tf2/holiday.h index f0e357dc3c..6fa351e5c9 100644 --- a/extensions/tf2/holiday.h +++ b/extensions/tf2/holiday.h @@ -50,27 +50,26 @@ class HolidayManager : public IPluginsListener void OnPluginUnloaded(IPlugin *plugin); public: - bool Hook_IsHolidayActive(int holiday); - void Hook_LevelShutdown(); + KHook::Return Hook_IsHolidayActive(class CTFGameRules* pGameRules, int holiday); + KHook::Return Hook_LevelShutdown(IServerGameDLL*); private: - bool IsHookEnabled() const { return m_iHookID != 0; } - void *GetGameRules(); + bool IsHookEnabled() const; + class CTFGameRules *GetGameRules(); void HookIfNecessary(); void Unhook(); private: - int m_iHookID; IForward *m_isHolidayForward; bool m_bInMap; }; -inline void *HolidayManager::GetGameRules() +inline class CTFGameRules *HolidayManager::GetGameRules() { if (!g_pSDKTools) return NULL; - return g_pSDKTools->GetGameRules(); + return (class CTFGameRules *)g_pSDKTools->GetGameRules(); } extern HolidayManager g_HolidayManager; diff --git a/extensions/tf2/teleporter.cpp b/extensions/tf2/teleporter.cpp index 5905724db1..267f7d3595 100644 --- a/extensions/tf2/teleporter.cpp +++ b/extensions/tf2/teleporter.cpp @@ -30,27 +30,52 @@ */ #include "teleporter.h" +#include "extension.h" -CDetour *canPlayerBeTeleportedDetour = NULL; - +KHook::HookID_t g_HookCanPlayerBeTeleportedClass = KHook::INVALID_HOOK; IForward *g_teleportForward = NULL; class CTFPlayer; -#if defined(__linux__) && defined(__i386__) class CanPlayerBeTeleportedClass -{ +{ +#if defined(__linux__) && defined(__i386__) public: + __attribute__((regparm(2))) bool MakeReturn(CTFPlayer * pPlayer) { + bool ret = *(bool*)::KHook::GetCurrentValuePtr(true); + ::KHook::DestroyReturnValue(); + return ret; + } + + __attribute__((regparm(2))) bool MakeCallOriginal(CTFPlayer * pPlayer) { + __attribute__((regparm(2))) bool (CanPlayerBeTeleportedClass::* CanPlayerBeTeleported_Actual)(CTFPlayer *) = nullptr; + KHook::FillMFP(&CanPlayerBeTeleported_Actual, ::KHook::GetOriginalFunction()); + + return ::KHook::ManualReturn({ KHook::Action::Ignore, (this->*CanPlayerBeTeleported_Actual)(pPlayer) }, true); + } + __attribute__((regparm(2))) bool CanPlayerBeTeleported(CTFPlayer * pPlayer); - static __attribute__((regparm(2))) bool (CanPlayerBeTeleportedClass::* CanPlayerBeTeleported_Actual)(CTFPlayer *); }; -__attribute__((regparm(2))) bool (CanPlayerBeTeleportedClass::* CanPlayerBeTeleportedClass::CanPlayerBeTeleported_Actual)(CTFPlayer *) = NULL; __attribute__((regparm(2))) bool CanPlayerBeTeleportedClass::CanPlayerBeTeleported(CTFPlayer* pPlayer) #else -DETOUR_DECL_MEMBER1(CanPlayerBeTeleported, bool, CTFPlayer *, pPlayer) +public: + bool MakeReturn(CTFPlayer * pPlayer) { + bool ret = *(bool*)::KHook::GetCurrentValuePtr(true); + ::KHook::DestroyReturnValue(); + return ret; + } + + bool MakeCallOriginal(CTFPlayer * pPlayer) { + auto CanPlayerBeTeleported_Actual = KHook::BuildMFP(::KHook::GetOriginalFunction()); + + return ::KHook::ManualReturn({ KHook::Action::Ignore, (this->*CanPlayerBeTeleported_Actual)(pPlayer) }, true); + } + bool CanPlayerBeTeleported(CTFPlayer * pPlayer); +}; +bool CanPlayerBeTeleportedClass::CanPlayerBeTeleported(CTFPlayer* pPlayer) #endif { - bool origCanTeleport = DETOUR_MEMBER_CALL(CanPlayerBeTeleported)(pPlayer); + bool origCanTeleport = *(bool*)KHook::GetCurrentValuePtr(); cell_t teleporterCell = gamehelpers->EntityToBCompatRef((CBaseEntity *)this); cell_t playerCell = gamehelpers->EntityToBCompatRef((CBaseEntity *)pPlayer); @@ -58,7 +83,7 @@ DETOUR_DECL_MEMBER1(CanPlayerBeTeleported, bool, CTFPlayer *, pPlayer) if (!g_teleportForward) { g_pSM->LogMessage(myself, "Teleport forward is invalid"); - return origCanTeleport; + return KHook::ManualReturn({ KHook::Action::Ignore, origCanTeleport }); } cell_t returnValue = origCanTeleport ? 1 : 0; @@ -74,21 +99,38 @@ DETOUR_DECL_MEMBER1(CanPlayerBeTeleported, bool, CTFPlayer *, pPlayer) if (result > Pl_Continue) { // plugin wants to override the game (returned something other than Plugin_Continue) - return returnValue == 1; + return KHook::ManualReturn({ KHook::Action::Override, returnValue == 1 }); } else { - return origCanTeleport; // let the game decide + return KHook::ManualReturn({ KHook::Action::Ignore, origCanTeleport }); // let the game decide } } bool InitialiseTeleporterDetour() { - canPlayerBeTeleportedDetour = DETOUR_CREATE_MEMBER(CanPlayerBeTeleported, "CanPlayerBeTeleported"); + if (g_HookCanPlayerBeTeleportedClass != KHook::INVALID_HOOK) { + return true; + } - if (canPlayerBeTeleportedDetour != NULL) + void* addr = nullptr; + if (!g_pGameConf->GetMemSig("CanPlayerBeTeleported", &addr) || addr == nullptr) { + g_pSM->LogError(myself, "Failed to retrieve CanPlayerBeTeleported."); + return false; + } + g_HookCanPlayerBeTeleportedClass = KHook::SetupHook( + addr, + nullptr, + nullptr, + nullptr, + KHook::ExtractMFP(&CanPlayerBeTeleportedClass::CanPlayerBeTeleported), + KHook::ExtractMFP(&CanPlayerBeTeleportedClass::MakeReturn), + KHook::ExtractMFP(&CanPlayerBeTeleportedClass::MakeCallOriginal), + true + ); + + if (g_HookCanPlayerBeTeleportedClass != KHook::INVALID_HOOK) { - canPlayerBeTeleportedDetour->EnableDetour(); return true; } @@ -99,9 +141,6 @@ bool InitialiseTeleporterDetour() void RemoveTeleporterDetour() { - if (canPlayerBeTeleportedDetour != NULL) - { - canPlayerBeTeleportedDetour->Destroy(); - canPlayerBeTeleportedDetour = NULL; - } + KHook::RemoveHook(g_HookCanPlayerBeTeleportedClass, true); + g_HookCanPlayerBeTeleportedClass = KHook::INVALID_HOOK; } diff --git a/extensions/tf2/teleporter.h b/extensions/tf2/teleporter.h index ae28037f1c..813c824526 100644 --- a/extensions/tf2/teleporter.h +++ b/extensions/tf2/teleporter.h @@ -33,7 +33,6 @@ #define _INCLUDE_SOURCEMOD_TELEPORTER_H_ #include "extension.h" -#include "CDetour/detours.h" bool InitialiseTeleporterDetour(); void RemoveTeleporterDetour(); diff --git a/extensions/topmenus/TopMenu.cpp b/extensions/topmenus/TopMenu.cpp index db5ead6f23..c1246ee920 100644 --- a/extensions/topmenus/TopMenu.cpp +++ b/extensions/topmenus/TopMenu.cpp @@ -328,7 +328,7 @@ void TopMenu::RemoveFromMenu(unsigned int object_id) } /* Remove the category from the list, then delete it. */ - m_Categories.erase(m_Categories.iterAt(i)); + m_Categories.erase(m_Categories.begin() + i); delete cat; break; } @@ -358,7 +358,7 @@ void TopMenu::RemoveFromMenu(unsigned int object_id) { if (parent_cat->obj_list[i] == obj) { - parent_cat->obj_list.erase(parent_cat->obj_list.iterAt(i)); + parent_cat->obj_list.erase(parent_cat->obj_list.begin() + i); /* If this category now has no items, mark root as changed * so clients won't get the category drawn anymore. @@ -936,7 +936,7 @@ void TopMenu::SortCategoryIfNeeded(unsigned int category) return; } - CVector to_sort; + std::vector to_sort; for (size_t i = 0; i < cat->obj_list.size(); i++) { to_sort.push_back(i); @@ -966,7 +966,7 @@ void TopMenu::SortCategoryIfNeeded(unsigned int category) { /* Place in the final list, then remove from the temporary list */ cat->sorted.push_back(cat->obj_list[to_sort[j]]); - to_sort.erase(to_sort.iterAt(j)); + to_sort.erase(to_sort.begin() + j); break; } } @@ -999,7 +999,7 @@ void TopMenu::SortCategoriesIfNeeded() return; } - CVector to_sort; + std::vector to_sort; for (unsigned int i = 0; i < (unsigned int)m_Categories.size(); i++) { to_sort.push_back(i); @@ -1016,7 +1016,7 @@ void TopMenu::SortCategoriesIfNeeded() { /* Add to the real list and remove from the temporary */ m_SortedCats.push_back(to_sort[j]); - to_sort.erase(to_sort.iterAt(j)); + to_sort.erase(to_sort.begin() + j); break; } } @@ -1089,7 +1089,7 @@ bool TopMenu::LoadConfiguration(const char *file, char *error, size_t maxlength) bool TopMenu::OnIdentityRemoval(IdentityToken_t *owner) { /* First sweep the categories owned by us */ - CVector obj_list; + std::vector obj_list; for (size_t i = 0; i < m_Categories.size(); i++) { if (m_Categories[i]->obj->owner == owner) diff --git a/extensions/topmenus/TopMenu.h b/extensions/topmenus/TopMenu.h index 298c7f58a4..65122f39d6 100644 --- a/extensions/topmenus/TopMenu.h +++ b/extensions/topmenus/TopMenu.h @@ -32,14 +32,14 @@ #ifndef _INCLUDE_SOURCEMOD_TOP_MENU_H_ #define _INCLUDE_SOURCEMOD_TOP_MENU_H_ -#include -#include #include #include "smsdk_ext.h" #include "sm_memtable.h" #include -using namespace SourceHook; +#include +#include + using namespace SourceMod; #define TOPMENU_DISPLAY_BUFFER_SIZE 128 @@ -47,7 +47,7 @@ using namespace SourceMod; struct config_category_t { int name; - CVector commands; + std::vector commands; }; struct config_root_t @@ -56,7 +56,7 @@ struct config_root_t { } BaseStringTable strings; - CVector cats; + std::vector cats; }; struct topmenu_object_t @@ -85,9 +85,9 @@ struct topmenu_object_t struct topmenu_category_t { - CVector obj_list; /** Full object list */ - CVector sorted; /** Sorted items */ - CVector unsorted; /** Unsorted items */ + std::vector obj_list; /** Full object list */ + std::vector sorted; /** Sorted items */ + std::vector unsorted; /** Unsorted items */ topmenu_object_t *obj; /** Bound object */ unsigned int serial; /** Serial number */ bool reorder; /** Whether ordering needs updating */ @@ -181,10 +181,10 @@ class TopMenu : private: config_root_t m_Config; /* Configuration from file */ topmenu_player_t *m_clients; /* Client array */ - CVector m_SortedCats; /* Sorted categories */ - CVector m_UnsortedCats; /* Un-sorted categories */ - CVector m_Categories; /* Category array */ - CVector m_Objects; /* Object array */ + std::vector m_SortedCats; /* Sorted categories */ + std::vector m_UnsortedCats; /* Un-sorted categories */ + std::vector m_Categories; /* Category array */ + std::vector m_Objects; /* Object array */ NameHashSet m_ObjLookup; /* Object lookup trie */ unsigned int m_SerialNo; /* Serial number for updating */ ITopMenuObjectCallbacks *m_pTitle; /* Title callbacks */ diff --git a/extensions/topmenus/TopMenuManager.cpp b/extensions/topmenus/TopMenuManager.cpp index 8b61147385..debf1234db 100644 --- a/extensions/topmenus/TopMenuManager.cpp +++ b/extensions/topmenus/TopMenuManager.cpp @@ -56,9 +56,7 @@ ITopMenu *TopMenuManager::CreateTopMenu(ITopMenuObjectCallbacks *callbacks) void TopMenuManager::OnClientConnected(int client) { - List::iterator iter; - - for (iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) + for (auto iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) { (*iter)->OnClientConnected(client); } @@ -66,9 +64,7 @@ void TopMenuManager::OnClientConnected(int client) void TopMenuManager::OnClientDisconnected(int client) { - List::iterator iter; - - for (iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) + for (auto iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) { (*iter)->OnClientDisconnected(client); } @@ -81,9 +77,7 @@ void TopMenuManager::OnServerActivated(int max_clients) return; } - List::iterator iter; - - for (iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) + for (auto iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) { (*iter)->OnServerActivated(max_clients); } @@ -93,7 +87,7 @@ void TopMenuManager::OnServerActivated(int max_clients) void TopMenuManager::OnPluginUnloaded(IPlugin *plugin) { - List::iterator iter = m_TopMenus.begin(); + auto iter = m_TopMenus.begin(); while (iter != m_TopMenus.end()) { @@ -120,9 +114,7 @@ void TopMenuManager::DestroyTopMenu(ITopMenu *topmenu) void TopMenuManager::OnMaxPlayersChanged( int newvalue ) { - List::iterator iter; - - for (iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) + for (auto iter = m_TopMenus.begin(); iter != m_TopMenus.end(); iter++) { (*iter)->OnMaxPlayersChanged(newvalue); } diff --git a/extensions/topmenus/TopMenuManager.h b/extensions/topmenus/TopMenuManager.h index 3225a75322..8c90591460 100644 --- a/extensions/topmenus/TopMenuManager.h +++ b/extensions/topmenus/TopMenuManager.h @@ -36,10 +36,10 @@ #include #include #include -#include + +#include using namespace SourceMod; -using namespace SourceHook; class TopMenu; @@ -60,7 +60,7 @@ class TopMenuManager : void OnPluginUnloaded(IPlugin *plugin); void OnMaxPlayersChanged(int newvalue); private: - List m_TopMenus; + std::list m_TopMenus; }; extern TopMenuManager g_TopMenus; diff --git a/extensions/updater/Updater.h b/extensions/updater/Updater.h index 247b823159..ca6f1e5679 100644 --- a/extensions/updater/Updater.h +++ b/extensions/updater/Updater.h @@ -34,11 +34,9 @@ #include #include -#include +#include #include "MemoryDownloader.h" -using namespace SourceHook; - struct UpdatePart { UpdatePart* next; @@ -72,8 +70,8 @@ namespace SourceMod MemoryDownloader mdl; unsigned int ustate; unsigned int ignoreLevel; - SourceHook::String curfile; - SourceHook::String url; + std::string curfile; + std::string url; char checksum[33]; UpdatePart *partFirst; UpdatePart *partLast; diff --git a/extensions/updater/extension.cpp b/extensions/updater/extension.cpp index 4fcdbbc435..3fd5f26169 100644 --- a/extensions/updater/extension.cpp +++ b/extensions/updater/extension.cpp @@ -36,20 +36,18 @@ #include #include "extension.h" #include "Updater.h" -#include -#include +#include +#include #define DEFAULT_UPDATE_URL "http://www.sourcemod.net/update/" -using namespace SourceHook; - SmUpdater g_Updater; /**< Global singleton for extension's main interface */ SMEXT_LINK(&g_Updater); IWebternet *webternet; -static List update_errors; +static std::list update_errors; static IThreadHandle *update_thread; -static String update_url; +static std::string update_url; bool SmUpdater::SDK_OnLoad(char *error, size_t maxlength, bool late) { @@ -90,7 +88,7 @@ void SmUpdater::SDK_OnUnload() } /* Clear message tables */ - List::iterator iter = update_errors.begin(); + auto iter = update_errors.begin(); while (iter != update_errors.end()) { iter = update_errors.erase(iter); @@ -120,9 +118,8 @@ void SmUpdater::NotifyInterfaceDrop(SMInterface *pInterface) static void PumpUpdate(void *data) { - String *str; + std::string *str; bool new_files = false; - List::iterator iter; char path[PLATFORM_MAX_PATH]; UpdatePart *temp; @@ -185,7 +182,7 @@ static void PumpUpdate(void *data) { smutils->LogError(myself, "--- BEGIN ERRORS FROM AUTOMATIC UPDATER ---"); - for (iter = update_errors.begin(); + for (auto iter = update_errors.begin(); iter != update_errors.end(); iter++) { @@ -244,7 +241,7 @@ void AddUpdateError(const char *fmt, ...) smutils->FormatArgs(buffer, sizeof(buffer), fmt, ap); va_end(ap); - update_errors.push_back(new String(buffer)); + update_errors.push_back(new std::string(buffer)); } const char *SmUpdater::GetExtensionVerString() diff --git a/public/CDetour/detourhelpers.h b/public/CDetour/detourhelpers.h deleted file mode 100644 index 9c9bd2de47..0000000000 --- a/public/CDetour/detourhelpers.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program 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 - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $ - */ - -#ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ -#define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_ - -#if defined PLATFORM_POSIX -#include -#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC -#endif - -#include -#include -#include -#include - -struct patch_t -{ - patch_t() - { - patch[0] = 0; - bytes = 0; - } - unsigned char patch[20]; - size_t bytes; -}; - -inline void ProtectMemory(void *addr, int length, int prot) -{ - char error[256]; -#if defined PLATFORM_POSIX - long pageSize = sysconf(_SC_PAGESIZE); - void *startPage = ke::AlignedBase(addr, pageSize); - void *endPage = ke::AlignedBase((void *)((intptr_t)addr + length), pageSize); - if (mprotect(startPage, ((intptr_t)endPage - (intptr_t)startPage) + pageSize, prot) == -1) { - ke::FormatSystemError(error, sizeof(error)); - fprintf(stderr, "mprotect: %s\n", error); - } -#elif defined PLATFORM_WINDOWS - DWORD old_prot; - if (!VirtualProtect(addr, length, prot, &old_prot)) { - ke::FormatSystemError(error, sizeof(error)); - fprintf(stderr, "VirtualProtect: %s\n", error); - } -#endif -} - -inline void SetMemPatchable(void *address, size_t size) -{ - ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE); -} - -inline void PatchRelJump32(unsigned char *target, void *callback) -{ - SetMemPatchable(target, 5); - - // jmp <32-bit displacement> - target[0] = IA32_JMP_IMM32; - *(int32_t *)(&target[1]) = int32_t((unsigned char *)callback - (target + 5)); -} - -inline void PatchAbsJump64(unsigned char *target, void *callback) -{ - int i = 0; - SetMemPatchable(target, 14); - - // push ; allocates 64-bit stack space on x64 - // mov [rsp+4], ; unnecessary if upper bits are 0 - // ret ; jump to address on stack - target[i++] = IA32_PUSH_IMM32; - *(int32_t *)(&target[i]) = int32_t(int64_t(callback)); - i += 4; - if ((int64_t(callback) >> 32) != 0) - { - target[i++] = IA32_MOV_RM_IMM32; - target[i++] = ia32_modrm(MOD_DISP8, 0, kREG_SIB); - target[i++] = ia32_sib(NOSCALE, kREG_NOIDX, kREG_ESP); - target[i++] = 0x04; - *(int32_t *)(&target[i]) = (int64_t(callback) >> 32); - i += 4; - } - target[i] = IA32_RET; -} - -inline void DoGatePatch(unsigned char *target, void *callback) -{ -#if defined(_WIN64) || defined(__x86_64__) - int64_t diff = int64_t(callback) - (int64_t(target) + 5); - int32_t upperBits = (diff >> 32); - if (upperBits == 0 || upperBits == -1) - PatchRelJump32(target, callback); - else - PatchAbsJump64(target, callback); -#else - PatchRelJump32(target, callback); -#endif -} - -inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore) -{ - unsigned char *addr = (unsigned char *)address + offset; - SetMemPatchable(addr, patch->bytes); - - if (restore) - { - for (size_t i=0; ibytes; i++) - { - restore->patch[i] = addr[i]; - } - restore->bytes = patch->bytes; - } - - for (size_t i=0; ibytes; i++) - { - addr[i] = patch->patch[i]; - } -} - -#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_ diff --git a/public/CDetour/detours.cpp b/public/CDetour/detours.cpp deleted file mode 100644 index 0fe27c7213..0000000000 --- a/public/CDetour/detours.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "detours.h" -#include - -ISourcePawnEngine *CDetourManager::spengine = NULL; -IGameConfig *CDetourManager::gameconf = NULL; - -void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf) -{ - CDetourManager::spengine = spengine; - CDetourManager::gameconf = gameconf; -} - -CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame) -{ - void* pAddress; - if (!gameconf->GetMemSig(signame, &pAddress)) - { - g_pSM->LogError(myself, "Signature for %s not found in gamedata", signame); - return NULL; - } - - if (!pAddress) - { - g_pSM->LogError(myself, "Sigscan for %s failed", signame); - return NULL; - } - - return CreateDetour(callbackfunction, trampoline, pAddress); -} - -CDetour *CDetourManager::CreateDetour(void *callbackFunction, void **trampoline, void *pAddress) -{ - CDetour* detour = new CDetour(callbackFunction, trampoline, pAddress); - - auto result = safetyhook::InlineHook::create(pAddress, callbackFunction, safetyhook::InlineHook::Flags::StartDisabled); - if(result) - { - detour->m_hook = std::move(result.value()); - *trampoline = detour->m_hook.original(); - } - else - { - auto err = result.error(); - switch(err.type) - { - case safetyhook::InlineHook::Error::BAD_ALLOCATION: - if(err.allocator_error == safetyhook::Allocator::Error::BAD_VIRTUAL_ALLOC) - { - g_pSM->LogError(myself, "BAD_VIRTUAL_ALLOC hook %p", pAddress); - } - else if(err.allocator_error == safetyhook::Allocator::Error::NO_MEMORY_IN_RANGE) - { - g_pSM->LogError(myself, "NO_MEMORY_IN_RANGE hook %p", pAddress); - } - else - { - g_pSM->LogError(myself, "BAD_ALLOCATION hook %p errnum %i", pAddress, err.allocator_error); - } - break; - case safetyhook::InlineHook::Error::FAILED_TO_DECODE_INSTRUCTION: - g_pSM->LogError(myself, "FAILED_TO_DECODE_INSTRUCTION hook %p ip %p", pAddress, err.ip); - break; - case safetyhook::InlineHook::Error::SHORT_JUMP_IN_TRAMPOLINE: - g_pSM->LogError(myself, "SHORT_JUMP_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip); - break; - case safetyhook::InlineHook::Error::IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE: - g_pSM->LogError(myself, "IP_RELATIVE_INSTRUCTION_OUT_OF_RANGE hook %p ip %p", pAddress, err.ip); - break; - case safetyhook::InlineHook::Error::UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE: - g_pSM->LogError(myself, "UNSUPPORTED_INSTRUCTION_IN_TRAMPOLINE hook %p ip %p", pAddress, err.ip); - break; - case safetyhook::InlineHook::Error::FAILED_TO_UNPROTECT: - g_pSM->LogError(myself, "FAILED_TO_UNPROTECT hook %p ip %p", pAddress, err.ip); - break; - case safetyhook::InlineHook::Error::NOT_ENOUGH_SPACE: - g_pSM->LogError(myself, "NOT_ENOUGH_SPACE hook %p ip %p", pAddress, err.ip); - break; - default: - g_pSM->LogError(myself, "Unknown error %i hook %p ip %p", err.type, pAddress, err.ip); - break; - } - - delete detour; - return NULL; - } - - return detour; -} - -CDetour::CDetour(void* callbackFunction, void **trampoline, void *pAddress) -{ -} - -bool CDetour::IsEnabled() -{ - return m_hook.enabled(); -} - -void CDetour::EnableDetour() -{ - m_hook.enable(); -} - -void CDetour::DisableDetour() -{ - m_hook.disable(); -} - -void CDetour::Destroy() -{ - delete this; -} \ No newline at end of file diff --git a/public/CDetour/detours.h b/public/CDetour/detours.h deleted file mode 100644 index 43e16e245b..0000000000 --- a/public/CDetour/detours.h +++ /dev/null @@ -1,273 +0,0 @@ -/** -* vim: set ts=4 : -* ============================================================================= -* SourceMod -* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. -* ============================================================================= -* -* This program is free software; you can redistribute it and/or modify it under -* the terms of the GNU General Public License, version 3.0, as published by the -* Free Software Foundation. -* -* This program 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 -* this program. If not, see . -* -* As a special exception, AlliedModders LLC gives you permission to link the -* code of this program (as well as its derivative works) to "Half-Life 2," the -* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software -* by the Valve Corporation. You must obey the GNU General Public License in -* all respects for all other code used. Additionally, AlliedModders LLC grants -* this exception to all derivative works. AlliedModders LLC defines further -* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), -* or . -* -* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $ -*/ - -#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_ -#define _INCLUDE_SOURCEMOD_DETOURS_H_ - -#include "safetyhook.hpp" -#include - -#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual) -#define DETOUR_STATIC_CALL(name) (name##_Actual) - -#define DETOUR_DECL_STATIC0(name, ret) \ -ret (*name##_Actual)(void) = NULL; \ -ret name(void) - -#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \ -ret (*name##_Actual)(p1type) = NULL; \ -ret name(p1type p1name) - -#define DETOUR_DECL_STATIC2(name, ret, p1type, p1name, p2type, p2name) \ -ret (*name##_Actual)(p1type, p2type) = NULL; \ -ret name(p1type p1name, p2type p2name) - -#define DETOUR_DECL_STATIC3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ -ret (*name##_Actual)(p1type, p2type, p3type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name) - -#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) - -#define DETOUR_DECL_STATIC5(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name) - -#define DETOUR_DECL_STATIC6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name) - -#define DETOUR_DECL_STATIC7(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name) - -#define DETOUR_DECL_STATIC8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \ -ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \ -ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name) - -#define DETOUR_DECL_MEMBER0(name, ret) \ -class name##Class \ -{ \ -public: \ - ret name(); \ - static ret (name##Class::* name##_Actual)(void); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \ -ret name##Class::name() - -#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name); \ - static ret (name##Class::* name##_Actual)(p1type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \ -ret name##Class::name(p1type p1name) - -#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name) - -#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name) - -#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name) - -#define DETOUR_DECL_MEMBER5(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name) - -#define DETOUR_DECL_MEMBER6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name) - -#define DETOUR_DECL_MEMBER7(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name) - -#define DETOUR_DECL_MEMBER8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name) - - -#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name) -#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual) - -#define GET_STATIC_CALLBACK(name) (void *)&name -#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual - -#define DETOUR_CREATE_MEMBER(name, gamedata) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata); -#define DETOUR_CREATE_STATIC(name, gamedata) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata); - - -class GenericClass {}; -typedef void (GenericClass::*VoidFunc)(); - -inline void *GetCodeAddr(VoidFunc mfp) -{ - return *(void **)&mfp; -} - -/** - * Converts a member function pointer to a void pointer. - * This relies on the assumption that the code address lies at mfp+0 - * This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers - * Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp - */ -#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast(mfp)) - -class CDetourManager; - -class CDetour -{ -public: - - bool IsEnabled(); - - /** - * These would be somewhat self-explanatory I hope - */ - void EnableDetour(); - void DisableDetour(); - - void Destroy(); - - friend class CDetourManager; - -protected: - CDetour(void*callbackfunction, void **trampoline, void *pAddress); -private: - SafetyHookInline m_hook{}; -}; - -class CDetourManager -{ -public: - - static void Init(ISourcePawnEngine *spengine, IGameConfig *gameconf); - - /** - * Creates a new detour - * - * @param callbackfunction Void pointer to your detour callback function. - * @param trampoline Address of the trampoline pointer - * @param signame Section name containing a signature to fetch from the gamedata file. - * @return A new CDetour pointer to control your detour. - * - * Example: - * - * CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int) - * - * Define a new class with the required function and a member function pointer to the same type: - * - * class CBaseServerDetour - * { - * public: - * bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); - * static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int); - * } - * - * void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient); - * void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual); - * - * Creation: - * CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient"); - * - * Usage: - * - * CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int) - * { - * //pre hook code - * bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params); - * //post hook code - * return result; - * } - * - * Note we changed the netadr_s reference into a void* to avoid needing to define the type - */ - static CDetour *CreateDetour(void *callbackFunction, void **trampoline, const char *signame); - static CDetour *CreateDetour(void *callbackFunction, void **trampoline, void *pAddress); - - friend class CDetour; - -private: - static ISourcePawnEngine *spengine; - static IGameConfig *gameconf; -}; - -#endif // _INCLUDE_SOURCEMOD_DETOURS_H_ \ No newline at end of file diff --git a/public/safetyhook b/public/safetyhook deleted file mode 160000 index 8c6692c85a..0000000000 --- a/public/safetyhook +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8c6692c85a6c41f5d89f744da57b5ba43515b4ec diff --git a/public/sample_ext/AMBuildScript b/public/sample_ext/AMBuildScript index 271d109a02..7027cf0976 100644 --- a/public/sample_ext/AMBuildScript +++ b/public/sample_ext/AMBuildScript @@ -117,7 +117,7 @@ class ExtensionConfig(object): if builder.options.mms_path: self.mms_root = builder.options.mms_path else: - self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') + self.mms_root = ResolveEnvPath('MMSOURCE200', 'mmsource-2.0') if not self.mms_root: self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') if not self.mms_root: @@ -132,7 +132,7 @@ class ExtensionConfig(object): if builder.options.sm_path: self.sm_root = builder.options.sm_path else: - self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12') + self.sm_root = ResolveEnvPath('SOURCEMOD113', 'sourcemod-1.13') if not self.sm_root: self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') if not self.sm_root: diff --git a/public/sample_ext_nosdk/AMBuildScript b/public/sample_ext_nosdk/AMBuildScript index 29440b1097..c84ca72fae 100644 --- a/public/sample_ext_nosdk/AMBuildScript +++ b/public/sample_ext_nosdk/AMBuildScript @@ -72,7 +72,7 @@ class ExtensionConfig(object): if builder.options.mms_path: self.mms_root = builder.options.mms_path else: - self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') + self.mms_root = ResolveEnvPath('MMSOURCE200', 'mmsource-2.0') if not self.mms_root: self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') if not self.mms_root: @@ -87,7 +87,7 @@ class ExtensionConfig(object): if builder.options.sm_path: self.sm_root = builder.options.sm_path else: - self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12') + self.sm_root = ResolveEnvPath('SOURCEMOD113', 'sourcemod-1.13') if not self.sm_root: self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') if not self.sm_root: diff --git a/public/sm_queue.h b/public/sm_queue.h index ff46a583a4..fa76fede2f 100644 --- a/public/sm_queue.h +++ b/public/sm_queue.h @@ -34,9 +34,7 @@ #include #include -#include - -using namespace SourceHook; +#include /* A circular, doubly-linked List with one sentinel node @@ -109,7 +107,7 @@ class Queue while (!m_FreeNodes.empty()) { - free(m_FreeNodes.front()); + free(m_FreeNodes.top()); m_FreeNodes.pop(); } } @@ -122,7 +120,7 @@ class Queue { node = (QueueNode *)malloc(sizeof(QueueNode)); } else { - node = m_FreeNodes.front(); + node = m_FreeNodes.top(); m_FreeNodes.pop(); } @@ -169,7 +167,7 @@ class Queue private: QueueNode *m_Head; size_t m_Size; - CStack m_FreeNodes; + std::stack m_FreeNodes; public: class iterator { diff --git a/public/smsdk_ext.cpp b/public/smsdk_ext.cpp index e9b8d76854..b30fd8a5e3 100644 --- a/public/smsdk_ext.cpp +++ b/public/smsdk_ext.cpp @@ -305,7 +305,9 @@ void SDKExtension::SDK_OnDependenciesDropped() PluginId g_PLID = 0; /**< Metamod plugin ID */ ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */ -SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */ +namespace KHook { + IKHook* __exported__khook = NULL; /**< KHook pointer */ +} ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */ #ifndef META_NO_HL2SDK diff --git a/public/vtable_hook_helper.h b/public/vtable_hook_helper.h index 73875f6549..fb6fc5d438 100644 --- a/public/vtable_hook_helper.h +++ b/public/vtable_hook_helper.h @@ -32,83 +32,26 @@ #ifndef _INCLUDE_VTABLE_HOOK_HELPER_H_ #define _INCLUDE_VTABLE_HOOK_HELPER_H_ +#include + class CVTableHook { public: - CVTableHook(void *takenclass) - { - this->vtableptr = *reinterpret_cast(takenclass); - this->hookid = 0; - } - - CVTableHook(void *vtable, int hook) + CVTableHook(void** vtable, KHook::__Hook* hook) : vtableptr(vtable), _khook(hook) { this->vtableptr = vtable; - this->hookid = hook; - } - - CVTableHook(CVTableHook &other) - { - this->vtableptr = other.vtableptr; - this->hookid = other.hookid; - - other.hookid = 0; } - CVTableHook(CVTableHook *other) - { - this->vtableptr = other->vtableptr; - this->hookid = other->hookid; - - other->hookid = 0; - } - - ~CVTableHook() - { - if (this->hookid) - { - SH_REMOVE_HOOK_ID(this->hookid); - this->hookid = 0; - } - } + CVTableHook(const CVTableHook&) = delete; + CVTableHook& operator= (const CVTableHook&) = delete; public: - void *GetVTablePtr(void) + void** GetVTablePtr(void) { return this->vtableptr; } - - void SetHookID(int hook) - { - this->hookid = hook; - } - - bool IsHooked(void) - { - return (this->hookid != 0); - } -public: - bool operator == (CVTableHook &other) - { - return (this->GetVTablePtr() == other.GetVTablePtr()); - } - - bool operator == (CVTableHook *other) - { - return (this->GetVTablePtr() == other->GetVTablePtr()); - } - - bool operator != (CVTableHook &other) - { - return (this->GetVTablePtr() != other.GetVTablePtr()); - } - - bool operator != (CVTableHook *other) - { - return (this->GetVTablePtr() != other->GetVTablePtr()); - } private: - void *vtableptr; - int hookid; + void** vtableptr; + std::unique_ptr _khook; }; #endif //_INCLUDE_VTABLE_HOOK_HELPER_H_ diff --git a/tools/checkout-deps.ps1 b/tools/checkout-deps.ps1 index f2d720aa93..0654ff3bcb 100644 --- a/tools/checkout-deps.ps1 +++ b/tools/checkout-deps.ps1 @@ -61,6 +61,7 @@ Function Get-Repository } & git checkout $Branch 2>&1 | Write-Host & git pull origin $Branch 2>&1 | Write-Host + & git submodule update --recursive 2>&1 | Write-Host If ($Origin) { & git remote set-url origin $Origin 2>&1 | Write-Host @@ -75,7 +76,7 @@ if (-not (Test-Path "sourcemod" -PathType Container)) Exit 1 } -Get-Repository -Name "mmsource-1.12" -Branch "master" -Repo "https://github.com/alliedmodders/metamod-source.git" +Get-Repository -Name "mmsource-2.0" -Branch "k/sourcehook_alternative" -Repo "https://github.com/alliedmodders/metamod-source.git" if (-not (Test-Path "hl2sdk-proxy-repo" -PathType Container)) { diff --git a/tools/checkout-deps.sh b/tools/checkout-deps.sh index 895ef4322d..d45b3dec60 100755 --- a/tools/checkout-deps.sh +++ b/tools/checkout-deps.sh @@ -131,6 +131,7 @@ checkout () fi git checkout $branch git pull origin $branch + git submodule update --recursive if [ -n "$origin" ]; then git remote set-url origin $origin fi @@ -138,8 +139,8 @@ checkout () fi } -name=mmsource-1.12 -branch=master +name=mmsource-2.0 +branch=k/sourcehook_alternative repo="https://github.com/alliedmodders/metamod-source" origin= checkout