From c92354debbfa4f169a9d60018160c2becd5c8412 Mon Sep 17 00:00:00 2001 From: peace-maker Date: Tue, 31 May 2022 14:55:47 +0200 Subject: [PATCH 1/7] DHooks: Fix changing of byref vector parameters (#1772) We always created a new vector object instead of changing the passed in vector directly. This works for the function being called using our changed values - but the caller doesn't see the changed values if it's passing a vector by reference. Only create a new vector if there isn't one being passed in and set the values directly in the passed in vector otherwise. --- extensions/dhooks/natives.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/extensions/dhooks/natives.cpp b/extensions/dhooks/natives.cpp index db1384f8..e1ace0b4 100644 --- a/extensions/dhooks/natives.cpp +++ b/extensions/dhooks/natives.cpp @@ -884,7 +884,8 @@ cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params) int index = params[2] - 1; size_t offset = GetParamOffset(paramStruct, index); - void *addr = (void **)((intptr_t)paramStruct->newParams + offset); + void **origAddr = (void **)((intptr_t)paramStruct->orgParams + offset); + void **newAddr = (void **)((intptr_t)paramStruct->newParams + offset); switch(paramStruct->dg->params.at(index).type) { @@ -892,11 +893,23 @@ cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params) { cell_t *buffer; pContext->LocalToPhysAddr(params[3], &buffer); + SDKVector *origVec = *(SDKVector **)origAddr; + SDKVector **newVec = (SDKVector **)newAddr; - *(SDKVector **)addr = new SDKVector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2])); + 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; - // Free it later (cheaply) after the function returned. - smutils->AddFrameAction(FreeChangedVector, *(SDKVector **)addr); return 1; } } From 7424deefb9d0d21a008d000347abe76f59fd57c0 Mon Sep 17 00:00:00 2001 From: peace-maker Date: Tue, 31 May 2022 14:58:36 +0200 Subject: [PATCH 2/7] DHooks: Error on argument passflags for detours (#1773) The passflags are only supported by SourceHook for virtual hooks and are ignored for detours with DynamicDetours. This caused confusion, so throw an error when trying to set e.g. the DHookPass_ByRef flag on detour arguments. --- extensions/dhooks/natives.cpp | 16 ++++++++++++++++ extensions/dhooks/signatures.cpp | 14 ++++++++++++++ extensions/dhooks/vhook.h | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/extensions/dhooks/natives.cpp b/extensions/dhooks/natives.cpp index e1ace0b4..8757e831 100644 --- a/extensions/dhooks/natives.cpp +++ b/extensions/dhooks/natives.cpp @@ -256,6 +256,15 @@ cell_t Native_SetFromConf(IPluginContext *pContext, const cell_t *params) setup->funcAddr = addr; setup->offset = offset; + if (addr == nullptr) + { + setup->hookMethod = Virtual; + } + else + { + setup->hookMethod = Detour; + } + return 1; } @@ -282,6 +291,13 @@ cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params) 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]; diff --git a/extensions/dhooks/signatures.cpp b/extensions/dhooks/signatures.cpp index e5ddd8b9..45b673cc 100644 --- a/extensions/dhooks/signatures.cpp +++ b/extensions/dhooks/signatures.cpp @@ -376,6 +376,20 @@ SMCResult SignatureGameConfig::ReadSMC_LeavingSection(const SMCStates *states) 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 = ""; diff --git a/extensions/dhooks/vhook.h b/extensions/dhooks/vhook.h index 3340049c..6146d1ad 100644 --- a/extensions/dhooks/vhook.h +++ b/extensions/dhooks/vhook.h @@ -225,6 +225,11 @@ public: DHooksInfo *dg; }; +enum HookMethod { + Virtual, + Detour +}; + class HookSetup { public: @@ -238,6 +243,7 @@ public: this->offset = offset; this->funcAddr = nullptr; this->callback = callback; + this->hookMethod = Virtual; }; HookSetup(ReturnType returnType, unsigned int returnFlag, CallingConvention callConv, ThisPointerType thisType, void *funcAddr) { @@ -249,6 +255,7 @@ public: this->offset = -1; this->funcAddr = funcAddr; this->callback = nullptr; + this->hookMethod = Detour; }; ~HookSetup(){}; @@ -266,6 +273,7 @@ public: int offset; void *funcAddr; IPluginFunction *callback; + HookMethod hookMethod; }; class DHooksManager From 5c0ae11a4619e9cba93478683c7737253ea93ba6 Mon Sep 17 00:00:00 2001 From: Vauff Date: Mon, 6 Jun 2022 08:45:35 -0400 Subject: [PATCH 3/7] Expand ShowHudText message buffer for Protobuf games (#1777) * Expand ShowHudText message buffer for CS:GO * Expand buffer on Blade Symphony too --- core/smn_hudtext.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/smn_hudtext.cpp b/core/smn_hudtext.cpp index 90b04052..6f7af02e 100644 --- a/core/smn_hudtext.cpp +++ b/core/smn_hudtext.cpp @@ -373,7 +373,11 @@ static cell_t ShowSyncHudText(IPluginContext *pContext, const cell_t *params) Handle_t err; CPlayer *pPlayer; hud_syncobj_t *obj; +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE + char message_buffer[512]; +#else char message_buffer[255-36]; +#endif if (!s_HudMsgHelpers.IsSupported()) { @@ -453,7 +457,11 @@ static cell_t ShowHudText(IPluginContext *pContext, const cell_t *params) { int client; CPlayer *pPlayer; +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE + char message_buffer[512]; +#else char message_buffer[255-36]; +#endif if (!s_HudMsgHelpers.IsSupported()) { From d41ffaad7efb887f36ca2ae4b3feb5f7a7d6d629 Mon Sep 17 00:00:00 2001 From: Margen67 Date: Wed, 15 Jun 2022 04:49:57 -0700 Subject: [PATCH 4/7] .gitmodules: Make submodules shallow (#1769) --- .gitmodules | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitmodules b/.gitmodules index fde0c20f..e799562e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,8 @@ [submodule "public/amtl"] path = public/amtl url = https://github.com/alliedmodders/amtl + shallow = true [submodule "sourcepawn"] path = sourcepawn url = https://github.com/alliedmodders/sourcepawn + shallow = true From 42763014994bcf15273ffcfc2591c3f4883c582a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 18 Jun 2022 15:17:48 -0700 Subject: [PATCH 5/7] Update SourcePawn. --- sourcepawn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sourcepawn b/sourcepawn index 18cce5f8..208001a0 160000 --- a/sourcepawn +++ b/sourcepawn @@ -1 +1 @@ -Subproject commit 18cce5f84247302126b5b6292516752d8a6bd1a7 +Subproject commit 208001a01baaf98d4601e31fda0ab9c849fa700d From 0f7f9dad97b9d7fbad26a5064002ebf1fad5ca45 Mon Sep 17 00:00:00 2001 From: dysphie Date: Mon, 20 Jun 2022 13:47:11 -0300 Subject: [PATCH 6/7] Add sdktools gamerules support for NMRiH (#1784) --- gamedata/sdktools.games/game.nmrih.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gamedata/sdktools.games/game.nmrih.txt b/gamedata/sdktools.games/game.nmrih.txt index 44d1c316..b1603498 100644 --- a/gamedata/sdktools.games/game.nmrih.txt +++ b/gamedata/sdktools.games/game.nmrih.txt @@ -185,5 +185,11 @@ "mac" "211" } } + + "Keys" + { + "GameRulesProxy" "CNMRiH_GameRulesProxy" + "GameRulesDataTable" "nmrih_gamerules_data" + } } } From 37c2a83523a1854623826dd36da7a9f500de55c4 Mon Sep 17 00:00:00 2001 From: Deathreus Date: Fri, 24 Jun 2022 02:46:03 -0700 Subject: [PATCH 7/7] Add a PluginIterator methodmap (#1779) * Add a PluginIterator methodmap * Follow convention * Update sourcemod.inc * Turn method ReadPlugin into property Plugin * Requested change * Update sourcemod.inc * Curse you VSC * Follow behavior of other iterators instead of the natives * Fix a stray space * Implement a hacked CPluginIterator * Oops Copy paste go brr * Revert a change made before the custom impl --- core/logic/smn_core.cpp | 129 +++++++++++++++++++++++++++++++++- plugins/include/sourcemod.inc | 22 ++++++ 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/core/logic/smn_core.cpp b/core/logic/smn_core.cpp index adf0a0fb..490a6a00 100644 --- a/core/logic/smn_core.cpp +++ b/core/logic/smn_core.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "common_logic.h" #include "Logger.h" @@ -56,6 +57,7 @@ #include #include #include +#include using namespace SourceMod; using namespace SourcePawn; @@ -114,6 +116,71 @@ public: } } g_CoreNativeHelpers; +/** + * @brief Nearly identical to the standard core plugin iterator + * with one key difference. Next doesn't increment the counter + * the first time it is ran. This is a hack for the methodmap.. + */ +class CMMPluginIterator + : public IPluginIterator, + public IPluginsListener +{ +public: + CMMPluginIterator(const CVector *list) + : m_hasStarted(false) + { + for(auto iter = list->begin(); iter != list->end(); ++iter) { + m_list.push_back(*iter); + } + scripts->FreePluginList(list); + + m_current = m_list.begin(); + + scripts->AddPluginsListener(this); + } + + virtual ~CMMPluginIterator() + { + scripts->RemovePluginsListener(this); + } + virtual bool MorePlugins() override + { + return (m_current != m_list.end()); + } + virtual IPlugin *GetPlugin() override + { + return *m_current; + } + virtual void NextPlugin() override + { + if(!m_hasStarted) + { + m_hasStarted = true; + return; + } + + m_current++; + } + virtual void Release() override + { + delete this; + } + +public: + virtual void OnPluginDestroyed(IPlugin *plugin) override + { + if (*m_current == plugin) + m_current = m_list.erase(m_current); + else + m_list.remove(static_cast(plugin)); + } + +private: + std::list m_list; + std::list::iterator m_current; + bool m_hasStarted; +}; + void LogAction(Handle_t hndl, int type, int client, int target, const char *message) { if (g_OnLogAction->GetFunctionCount()) @@ -146,7 +213,7 @@ void LogAction(Handle_t hndl, int type, int client, int target, const char *mess g_Logger.LogMessage("[%s] %s", logtag, message); } - static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) +static cell_t ThrowError(IPluginContext *pContext, const cell_t *params) { char buffer[512]; @@ -264,6 +331,60 @@ static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params) return pPlugin->GetMyHandle(); } +static cell_t PluginIterator_Create(IPluginContext *pContext, const cell_t *params) +{ + IPluginIterator *iter = new CMMPluginIterator(scripts->ListPlugins()); + + Handle_t hndl = handlesys->CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL); + + if (hndl == BAD_HANDLE) + { + iter->Release(); + } + + return hndl; +} + +static cell_t PluginIterator_Next(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = (Handle_t)params[1]; + HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent}; + HandleError err{}; + IPluginIterator *pIter = nullptr; + + if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None) + { + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err); + } + + if(!pIter->MorePlugins()) + return 0; + + pIter->NextPlugin(); + return 1; +} + +static cell_t PluginIterator_Plugin_get(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = (Handle_t)params[1]; + HandleSecurity sec{pContext->GetIdentity(), g_pCoreIdent}; + HandleError err{}; + IPluginIterator *pIter = nullptr; + + if ((err=handlesys->ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None) + { + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err); + } + + IPlugin *pPlugin = pIter->GetPlugin(); + if (!pPlugin) + { + return BAD_HANDLE; + } + + return pPlugin->GetMyHandle(); +} + IPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl) { if (hndl == BAD_HANDLE) @@ -969,7 +1090,7 @@ REGISTER_NATIVES(coreNatives) {"FormatTime", FormatTime}, {"GetPluginIterator", GetPluginIterator}, {"MorePlugins", MorePlugins}, - {"ReadPlugin", ReadPlugin}, + {"ReadPlugin", ReadPlugin}, {"GetPluginStatus", GetPluginStatus}, {"GetPluginFilename", GetPluginFilename}, {"IsPluginDebugging", IsPluginDebugging}, @@ -1000,5 +1121,9 @@ REGISTER_NATIVES(coreNatives) {"FrameIterator.LineNumber.get", FrameIterator_LineNumber}, {"FrameIterator.GetFunctionName", FrameIterator_GetFunctionName}, {"FrameIterator.GetFilePath", FrameIterator_GetFilePath}, + + {"PluginIterator.PluginIterator", PluginIterator_Create}, + {"PluginIterator.Next", PluginIterator_Next}, + {"PluginIterator.Plugin.get", PluginIterator_Plugin_get}, {NULL, NULL}, }; diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index 610ff48c..1a704bd9 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -243,6 +243,28 @@ forward void OnAllPluginsLoaded(); */ native Handle GetMyHandle(); +methodmap PluginIterator < Handle +{ + // Returns an iterator that can be used to search through plugins. + // + // @return A new Handle to a PluginIterator. + public native PluginIterator(); + + // Advances the iterator. Returns whether there are more plugins available in the iterator. + // + // @return True on more plugins, false otherwise. + // @error Invalid Handle. + public native bool Next(); + + // Returns the current plugin in the iterator. + // + // @return Current plugin the iterator is at + // @error Invalid Handle. + property Handle Plugin { + public native get(); + } +} + /** * Returns an iterator that can be used to search through plugins. *