From df672dd8ce6f813fb98ae440eb0b91389e17244d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 8 Sep 2015 19:34:40 -0700 Subject: [PATCH 1/3] Remove the ability to compile against Metamod:Source versions lower than 1.8. --- core/GameHooks.cpp | 6 ------ core/HalfLife2.cpp | 29 ++--------------------------- core/HalfLife2.h | 3 --- core/smn_halflife.cpp | 15 ++------------- core/sourcemm_api.cpp | 31 ++++--------------------------- core/sourcemm_api.h | 4 ---- extensions/sdktools/vglobals.cpp | 13 ------------- 7 files changed, 8 insertions(+), 93 deletions(-) diff --git a/core/GameHooks.cpp b/core/GameHooks.cpp index 00320747..8c8be201 100644 --- a/core/GameHooks.cpp +++ b/core/GameHooks.cpp @@ -79,14 +79,8 @@ void GameHooks::OnVSPReceived() if (client_cvar_query_mode_ != ClientCvarQueryMode::Unavailable) return; - // For later MM:S versions, use the updated API, since it's cleaner. -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL || vsp_version < 2) return; -#else - if (g_HL2.IsOriginalEngine() || vsp_version < 2) - return; -#endif #if SOURCE_ENGINE != SE_DARKMESSIAH && SOURCE_ENGINE != SE_DOTA hooks_ += SH_ADD_HOOK(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, SH_MEMBER(this, &GameHooks::OnQueryCvarValueFinished), false); diff --git a/core/HalfLife2.cpp b/core/HalfLife2.cpp index e280b7be..cd8486a9 100644 --- a/core/HalfLife2.cpp +++ b/core/HalfLife2.cpp @@ -114,24 +114,10 @@ CHalfLife2::~CHalfLife2() CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; #endif -#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11 -bool is_original_engine = false; -#endif - void CHalfLife2::OnSourceModStartup(bool late) { #if SOURCE_ENGINE != SE_DARKMESSIAH - - /* The Ship currently is the only known game to use an older version of the engine */ -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 - if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL) -#else - if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) -#endif - { - is_original_engine = true; - } - else if (g_pSharedChangeInfo == NULL) + if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL && !g_pSharedChangeInfo) { g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo(); } @@ -238,7 +224,7 @@ void CHalfLife2::InitCommandLine() { char error[256]; #if SOURCE_ENGINE != SE_DARKMESSIAH - if (!is_original_engine) + if (g_SMAPI->GetSourceEngineBuild() != SOURCE_ENGINE_ORIGINAL) { ke::Ref lib = ke::SharedLib::Open(TIER0_NAME, error, sizeof(error)); if (!lib) { @@ -280,13 +266,6 @@ ICommandLine *CHalfLife2::GetValveCommandLine() return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))(); } -#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11 -bool CHalfLife2::IsOriginalEngine() -{ - return is_original_engine; -} -#endif - #if SOURCE_ENGINE != SE_DARKMESSIAH IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() { @@ -786,11 +765,7 @@ bool CHalfLife2::IsLANServer() bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) { -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL) -#else - if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) -#endif { Assert(filesystem); #ifdef _MSC_VER diff --git a/core/HalfLife2.h b/core/HalfLife2.h index 7756db49..b294053c 100644 --- a/core/HalfLife2.h +++ b/core/HalfLife2.h @@ -197,9 +197,6 @@ public: const char *CurrentCommandName(); void AddDelayedKick(int client, int userid, const char *msg); void ProcessDelayedKicks(); -#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11 - bool IsOriginalEngine(); -#endif private: void PushCommandStack(const ICommandArgs *cmd); void PopCommandStack(); diff --git a/core/smn_halflife.cpp b/core/smn_halflife.cpp index b32cb9e2..3f8b2944 100644 --- a/core/smn_halflife.cpp +++ b/core/smn_halflife.cpp @@ -482,7 +482,6 @@ static cell_t smn_IsPlayerAlive(IPluginContext *pContext, const cell_t *params) static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) { -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 int version = g_SMAPI->GetSourceEngineBuild(); switch (version) @@ -492,7 +491,7 @@ static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) case SOURCE_ENGINE_EPISODEONE: return 20; -# if defined METAMOD_PLAPI_VERSION +#if defined METAMOD_PLAPI_VERSION /* Newer games. */ case SOURCE_ENGINE_DARKMESSIAH: return 15; @@ -525,18 +524,8 @@ static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params) return 80; case SOURCE_ENGINE_DOTA: return 90; -# endif - } -#else - if (g_HL2.IsOriginalEngine()) - { - return 10; - } - else - { - return 20; - } #endif + } return 0; } diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index e3e5c4e2..7d787814 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -63,6 +63,10 @@ int vsp_version = 0; PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core); +#if !defined(METAMOD_PLAPI_VERSION) && PLAPI_VERSION < 11 +# error "SourceMod requires Metamod:Source 1.8 or higher." +#endif + ConVar sourcemod_version("sourcemod_version", SOURCEMOD_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version"); bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) @@ -100,9 +104,7 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen ismm->AddListener(this, this); -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 if ((vsp_interface = g_SMAPI->GetVSPInfo(&vsp_version)) == NULL) -#endif { g_SMAPI->EnableVSPListener(); } @@ -190,31 +192,15 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface) return; } -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 if (vsp_version == 0) { g_SMAPI->GetVSPInfo(&vsp_version); } -#else - if (vsp_version == 0) - { - if (strcmp(g_SourceMod.GetGameFolderName(), "ship") == 0) - { - vsp_version = 1; - } - else - { - vsp_version = 2; - } - } -#endif /* Notify! */ sCoreProviderImpl.OnVSPReceived(); } -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 - void SourceMod_Core::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand) { #if SOURCE_ENGINE < SE_ORANGEBOX @@ -222,15 +208,6 @@ void SourceMod_Core::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pComman #endif } -#else - -void SourceMod_Core::OnPluginUnload(PluginId id) -{ - Global_OnUnlinkConCommandBase(NULL); -} - -#endif - void *SourceMod_Core::OnMetamodQuery(const char *iface, int *ret) { void *ptr = NULL; diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index c813f27e..ab434426 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -80,11 +80,7 @@ public: const char *GetLogTag(); public: void OnVSPListening(IServerPluginCallbacks *iface); -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand); -#else - void OnPluginUnload(PluginId id); -#endif void *OnMetamodQuery(const char *iface, int *ret); }; diff --git a/extensions/sdktools/vglobals.cpp b/extensions/sdktools/vglobals.cpp index ded75ef4..daa6aa07 100644 --- a/extensions/sdktools/vglobals.cpp +++ b/extensions/sdktools/vglobals.cpp @@ -242,24 +242,11 @@ void GetIServer() return; } -#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 /* Get the CreateFakeClient function pointer */ if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient))) { return; } -#else - /* Get the interface manually */ - SourceHook::MemFuncInfo info = {true, -1, 0, 0}; - SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info); - - vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex); - if (!vfunc) - { - void **vtable = *reinterpret_cast(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs); - vfunc = vtable[info.vtblindex]; - } -#endif /* Get signature string for IVEngineServer::CreateFakeClient() */ sigstr = g_pGameConf->GetKeyValue(FAKECLIENT_KEY); From b548ba7b58c4f1c2f7e0f168762deb6c3eb0796f Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 8 Sep 2015 19:47:22 -0700 Subject: [PATCH 2/3] Remove bad-console-read protection logic for Metamod:Source 1.7 and earlier. --- core/ConCmdManager.cpp | 12 ++--- core/ConCmdManager.h | 4 +- core/ConVarManager.cpp | 2 +- core/ConVarManager.h | 2 +- core/concmd_cleaner.cpp | 105 +++++++++++++++------------------------- core/concmd_cleaner.h | 2 +- core/smn_console.cpp | 2 +- 7 files changed, 50 insertions(+), 79 deletions(-) diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index 937114a5..2d194b14 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -73,7 +73,7 @@ void ConCmdManager::OnSourceModShutdown() rootmenu->RemoveRootConsoleCommand("cmds", this); } -void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) +void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) { /* Whoa, first get its information struct */ ConCmdInfo *pInfo; @@ -108,7 +108,7 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na delete hook; } - RemoveConCmd(pInfo, name, is_read_safe, false); + RemoveConCmd(pInfo, name, false); } void ConCmdManager::OnPluginDestroyed(IPlugin *plugin) @@ -127,7 +127,7 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin) hook->admin->group->hooks.remove(hook); if (hook->info->hooks.empty()) - RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true); + RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true); iter = pList->erase(iter); delete hook; @@ -517,7 +517,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag } } -void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_read_safe, bool untrack) +void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool untrack) { /* Remove from the trie */ m_Cmds.remove(name); @@ -540,10 +540,6 @@ void ConCmdManager::RemoveConCmd(ConCmdInfo *info, const char *name, bool is_rea } else { - // If it's not safe to read the pointer, we zap the SourceHook hook so it - // doesn't attempt to access the pointer's vtable. - if (!is_read_safe) - info->sh_hook->Zap(); if (untrack) UntrackConCommandBase(info->pCmd, this); } diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index f68991e2..c6edeb90 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -129,7 +129,7 @@ public: //IPluginsListener public: //IRootConsoleCommand void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override; public: //IConCommandTracker - void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); + void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override; public: bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags); bool AddAdminCommand(IPluginFunction *pFunction, @@ -148,7 +148,7 @@ private: ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags); void SetCommandClient(int client); void AddToCmdList(ConCmdInfo *info); - void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack); + void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool untrack); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); // Case insensitive diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index 11fcd00e..e3dfafac 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -167,7 +167,7 @@ bool convar_cache_lookup(const char *name, ConVarInfo **pVar) return convar_cache.retrieve(name, pVar); } -void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) +void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) { /* Only check convars that have not been created by SourceMod's core */ ConVarInfo *pInfo; diff --git a/core/ConVarManager.h b/core/ConVarManager.h index 414a0c8a..07dfdd35 100644 --- a/core/ConVarManager.h +++ b/core/ConVarManager.h @@ -103,7 +103,7 @@ public: // IPluginsListener public: //IRootConsoleCommand void OnRootConsoleCommand(const char *cmdname, const ICommandArgs *command) override; public: //IConCommandTracker - void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); + void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override; public: //IClientListener void OnClientDisconnected(int client); public: diff --git a/core/concmd_cleaner.cpp b/core/concmd_cleaner.cpp index 009608b5..683cb68b 100644 --- a/core/concmd_cleaner.cpp +++ b/core/concmd_cleaner.cpp @@ -1,33 +1,29 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ============================================================================= - * SourceMod - * Copyright (C) 2004-2008 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$ - */ +// vim: set ts=4 sw=4 tw=99 et: +// ============================================================================= +// SourceMod +// Copyright (C) 2004-2008 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 . #include "sm_globals.h" #include @@ -104,41 +100,20 @@ public: listener = listener->next; } - if (pBase) - { - while (iter != tracked_bases.end()) - { - if ((*iter)->pBase == pBase) - { - pInfo = (*iter); - iter = tracked_bases.erase(iter); - pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true); - delete pInfo; - } - else - { - iter++; - } - } - } - else - { - while (iter != tracked_bases.end()) - { - /* This is just god-awful! */ - if (FindCommandBase((*iter)->name) != (*iter)->pBase) - { - pInfo = (*iter); - iter = tracked_bases.erase(iter); - pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false); - delete pInfo; - } - else - { - iter++; - } - } - } + while (iter != tracked_bases.end()) + { + if ((*iter)->pBase == pBase) + { + pInfo = (*iter); + iter = tracked_bases.erase(iter); + pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName()); + delete pInfo; + } + else + { + iter++; + } + } } void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls) diff --git a/core/concmd_cleaner.h b/core/concmd_cleaner.h index 330a984e..87ba73a6 100644 --- a/core/concmd_cleaner.h +++ b/core/concmd_cleaner.h @@ -35,7 +35,7 @@ class IConCommandTracker { public: - virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0; + virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) = 0; }; void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me); diff --git a/core/smn_console.cpp b/core/smn_console.cpp index 4ebd9123..ee59af55 100644 --- a/core/smn_console.cpp +++ b/core/smn_console.cpp @@ -131,7 +131,7 @@ public: class CommandFlagsHelper : public IConCommandTracker { public: - void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) + void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name) override { m_CmdFlags.remove(name); } From fd961f4712a7187002058ca166c7aae25a6643f1 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 8 Sep 2015 20:06:44 -0700 Subject: [PATCH 3/3] Remove code to handle SourceHook versions 3 and lower. --- core/ConsoleDetours.cpp | 342 +--------------------------------------- core/CoreConfig.cpp | 6 +- core/NextMap.cpp | 6 +- core/PlayerManager.cpp | 6 +- core/sourcemm_api.cpp | 3 + 5 files changed, 14 insertions(+), 349 deletions(-) diff --git a/core/ConsoleDetours.cpp b/core/ConsoleDetours.cpp index 035a1a06..36f880e6 100644 --- a/core/ConsoleDetours.cpp +++ b/core/ConsoleDetours.cpp @@ -70,17 +70,11 @@ SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); # endif #else -# if SH_IMPL_VERSION >= 4 - extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0,bool); - extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0); -# else - extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0); -# endif +extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0,bool); +extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0); #endif -#if SH_IMPL_VERSION >= 4 - class GenericCommandHooker : public IConCommandLinkListener { struct HackInfo @@ -136,18 +130,18 @@ class GenericCommandHooker : public IConCommandLinkListener } } -# if SOURCE_ENGINE == SE_DOTA +#if SOURCE_ENGINE == SE_DOTA void Dispatch(const CCommandContext &context, const CCommand& args) -# elif SOURCE_ENGINE >= SE_ORANGEBOX +#elif SOURCE_ENGINE >= SE_ORANGEBOX void Dispatch(const CCommand& args) -# else +#else void Dispatch() -# endif +#endif { cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand) -# if SOURCE_ENGINE >= SE_ORANGEBOX +#if SOURCE_ENGINE >= SE_ORANGEBOX , args -# endif +#endif ); if (res >= Pl_Handled) RETURN_META(MRES_SUPERCEDE); @@ -264,308 +258,6 @@ public: } }; -/** - * END DVP HOOK VERSION - */ - -#else /* SH_IMPL_VERSION >= 4 */ - -/** - * BEGIN ENGINE DETOUR VERSION - */ - -# include -# include - -class GenericCommandHooker -{ - struct Patch - { - Patch() : applied(false) - { - } - - bool applied; - void *base; - unsigned char search[16]; - size_t search_len; - size_t offset; - size_t saveat; - int regparam; - void *detour; - }; - - Patch ces; - Patch cgc; - -public: - static void DelayedActivation(void *inparam) - { - GenericCommandHooker *cdtrs = reinterpret_cast(inparam); - /* Safe to re-enter because the frame queue is lock+swapped. */ - if ((!cdtrs->ces.applied || !cdtrs->cgc.applied) && - g_HL2.PeekCommandStack() != NULL) - { - g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, cdtrs); - return; - } - - if (!cdtrs->ces.applied) - cdtrs->ApplyPatch(&cdtrs->ces); - if (!cdtrs->cgc.applied) - cdtrs->ApplyPatch(&cdtrs->cgc); - } - - bool Enable() - { - const char *platform = NULL; -# if defined(PLATFORM_WINDOWS) - platform = "Windows"; -# else - void *addrInBase = (void *)g_SMAPI->GetEngineFactory(false); - Dl_info info; - if (!dladdr(addrInBase, &info)) - { - g_Logger.LogError("Command filter could not find engine name"); - return false; - } - if (strstr(info.dli_fname, "engine_i486")) - { - platform = "Linux_486"; - } - else if (strstr(info.dli_fname, "engine_i686")) - { - platform = "Linux_686"; - } - else if (strstr(info.dli_fname, "engine_amd")) - { - platform = "Linux_AMD"; - } - else - { - g_Logger.LogError("Command filter could not determine engine (%s)", info.dli_fname); - return false; - } -# endif - - if (!PrepPatch("Cmd_ExecuteString", "CES", platform, &ces)) - return false; - if (!PrepPatch("CGameClient::ExecuteString", "CGC", platform, &cgc)) - return false; - - if (g_HL2.PeekCommandStack() != NULL) - { - g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, this); - return true; - } - - ApplyPatch(&ces); - ApplyPatch(&cgc); - - return true; - } - - void Disable() - { - UndoPatch(&ces); - UndoPatch(&cgc); - } - -private: - -# if !defined PLATFORM_WINDOWS -# define PAGE_READWRITE PROT_READ|PROT_WRITE -# define PAGE_EXECUTE_READ PROT_READ|PROT_EXEC - - static inline uintptr_t AddrToPage(uintptr_t address) - { - return (address & ~(uintptr_t(sysconf(_SC_PAGE_SIZE) - 1))); - } - -# endif - - void Protect(void *addr, size_t length, int prot) - { -# if defined PLATFORM_WINDOWS - DWORD ignore; - VirtualProtect(addr, length, prot, &ignore); -# else - uintptr_t startPage = AddrToPage(uintptr_t(addr)); - length += (uintptr_t(addr) - startPage); - mprotect((void*)startPage, length, prot); -# endif - } - - void UndoPatch(Patch *patch) - { - if (!patch->applied || patch->detour == NULL) - return; - - g_pSourcePawn->FreePageMemory(patch->detour); - - unsigned char *source = (unsigned char *)patch->base + patch->offset; - Protect(source, patch->search_len, PAGE_READWRITE); - for (size_t i = 0; i < patch->search_len; i++) - source[i] = patch->search[i]; - Protect(source, patch->search_len, PAGE_EXECUTE_READ); - } - - void ApplyPatch(Patch *patch) - { - assert(!patch->applied); - - size_t length = 0; - void *callback = (void*)&ConsoleDetours::Dispatch; - - /* Bogus assignment to make compiler is doing the right thing. */ - patch->detour = callback; - - /* Assemgle the detour. */ - JitWriter writer; - writer.outbase = NULL; - writer.outptr = NULL; - do - { - /* Need a specific register, or value on stack? */ - if (patch->regparam != -1) - IA32_Push_Reg(&writer, patch->regparam); - /* Call real function. */ - IA32_Write_Jump32_Abs(&writer, IA32_Call_Imm32(&writer, 0), callback); - /* Restore stack. */ - if (patch->regparam != -1) - IA32_Pop_Reg(&writer, patch->regparam); - /* Copy any saved bytes */ - if (patch->saveat) - { - for (size_t i = patch->saveat; i < patch->search_len; i++) - { - writer.write_ubyte(patch->search[i]); - } - } - /* Jump back to the caller. */ - unsigned char *target = (unsigned char *)patch->base + patch->offset + patch->search_len; - IA32_Jump_Imm32_Abs(&writer, target); - /* Assemble, if we can. */ - if (writer.outbase == NULL) - { - length = writer.outptr - writer.outbase; - patch->detour = g_pSourcePawn->AllocatePageMemory(length); - if (patch->detour == NULL) - { - g_Logger.LogError("Ran out of memory!"); - return; - } - g_pSourcePawn->SetReadWrite(patch->detour); - writer.outbase = (jitcode_t)patch->detour; - writer.outptr = writer.outbase; - } - else - { - break; - } - } while (true); - - g_pSourcePawn->SetReadExecute(patch->detour); - - unsigned char *source = (unsigned char *)patch->base + patch->offset; - Protect(source, 6, PAGE_READWRITE); - source[0] = 0xFF; - source[1] = 0x25; - *(void **)&source[2] = &patch->detour; - Protect(source, 6, PAGE_EXECUTE_READ); - - patch->applied = true; - } - - bool PrepPatch(const char *signature, const char *name, const char *platform, Patch *patch) - { - /* Get the base address of the function. */ - if (!g_pGameConf->GetMemSig(signature, &patch->base) || patch->base == NULL) - { - g_Logger.LogError("Command filter could not find signature: %s", signature); - return false; - } - - const char *value; - char keyname[255]; - - /* Get the verification bytes that will be written over. */ - UTIL_Format(keyname, sizeof(keyname), "%s_Patch_%s", name, platform); - if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL) - { - g_Logger.LogError("Command filter could not find key: %s", keyname); - return false; - } - patch->search_len = UTIL_DecodeHexString(patch->search, sizeof(patch->search), value); - if (patch->search_len < 6) - { - g_Logger.LogError("Error decoding %s value, or not long enough", keyname); - return false; - } - - /* Get the offset into the function. */ - UTIL_Format(keyname, sizeof(keyname), "%s_Offset_%s", name, platform); - if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL) - { - g_Logger.LogError("Command filter could not find key: %s", keyname); - return false; - } - patch->offset = atoi(value); - if (patch->offset > 20000) - { - g_Logger.LogError("Command filter %s value is bogus", keyname); - return false; - } - - /* Get the number of bytes to save from what was written over. */ - patch->saveat = 0; - UTIL_Format(keyname, sizeof(keyname), "%s_Save_%s", name, platform); - if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL) - { - patch->saveat = atoi(value); - if (patch->saveat >= patch->search_len) - { - g_Logger.LogError("Command filter %s value is too large", keyname); - return false; - } - } - - /* Get register for parameter, if any. */ - patch->regparam = -1; - UTIL_Format(keyname, sizeof(keyname), "%s_Reg_%s", name, platform); - if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL) - { - patch->regparam = atoi(value); - } - - /* Everything loaded from gamedata, make sure the patch will succeed. */ - unsigned char *address = (unsigned char *)patch->base + patch->offset; - for (size_t i = 0; i < patch->search_len; i++) - { - if (address[i] != patch->search[i]) - { - g_Logger.LogError("Command filter %s has changed (byte %x is not %x sub-offset %d)", - name, address[i], patch->search[i], i); - return false; - } - } - - return true; - } -}; - -static bool dummy_hook_set = false; -void DummyHook() -{ - if (dummy_hook_set) - { - dummy_hook_set = false; - RETURN_META(MRES_SUPERCEDE); - } -} - -#endif - /** * BEGIN THE ACTUALLY GENERIC CODE. */ @@ -722,23 +414,5 @@ cell_t ConsoleDetours::Dispatch(ConCommand *pBase) res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), &cargs); } -#if SH_IMPL_VERSION < 4 - if (res >= Pl_Handled) - { - /* See bug 4020 - we can't optimize this because looking at the vtable - * is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY. - */ - SH_ADD_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false); - dummy_hook_set = true; - pBase->Dispatch(); - SH_REMOVE_HOOK(ConCommand, Dispatch, pBase, SH_STATIC(DummyHook), false); - } - else - { - /* Make sure the command gets invoked. See bug 4019 on making this better. */ - pBase->Dispatch(); - } -#endif - return res; } diff --git a/core/CoreConfig.cpp b/core/CoreConfig.cpp index 6869401d..d65c9c76 100644 --- a/core/CoreConfig.cpp +++ b/core/CoreConfig.cpp @@ -77,11 +77,7 @@ void Hook_ExecDispatchPre(const CCommand &cmd) SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); void Hook_ExecDispatchPre() #else -# if SH_IMPL_VERSION >= 4 - extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -# else - extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -# endif +extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); void Hook_ExecDispatchPre() #endif diff --git a/core/NextMap.cpp b/core/NextMap.cpp index 59428cd0..f5995da3 100644 --- a/core/NextMap.cpp +++ b/core/NextMap.cpp @@ -55,11 +55,7 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &) #elif SOURCE_ENGINE == SE_DARKMESSIAH SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); #else -# if SH_IMPL_VERSION >= 4 - extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -# else - extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -#endif +extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); #endif diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 3b88207c..e32ae447 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -105,11 +105,7 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &) #elif SOURCE_ENGINE == SE_DARKMESSIAH SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); #else -# if SH_IMPL_VERSION >= 4 - extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -# else - extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); -# endif +extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0); #endif diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index 7d787814..ab2c9a9e 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -66,6 +66,9 @@ PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core); #if !defined(METAMOD_PLAPI_VERSION) && PLAPI_VERSION < 11 # error "SourceMod requires Metamod:Source 1.8 or higher." #endif +#if SH_IMPL_VERSION < 4 +# error "SourceMod requires a newer version of SourceHook." +#endif ConVar sourcemod_version("sourcemod_version", SOURCEMOD_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, "SourceMod Version");