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");