From 9a168ff37d3dc27ed04d809974d37ab6fa6ec683 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Tue, 25 Oct 2016 22:44:49 +0700 Subject: [PATCH] Added features of priority for hookchains Remove useless string_t.h Update the major version --- rehlds/public/basetypes.h | 4 +- rehlds/public/rehlds/hookchains.h | 19 ++++-- rehlds/public/rehlds/rehlds_api.h | 2 +- rehlds/public/string_t.h | 106 ------------------------------ rehlds/rehlds/hookchains_impl.cpp | 57 ++++++++++++---- rehlds/rehlds/hookchains_impl.h | 24 +++---- rehlds/rehlds/rehlds_api_impl.cpp | 12 ++-- 7 files changed, 78 insertions(+), 146 deletions(-) delete mode 100644 rehlds/public/string_t.h diff --git a/rehlds/public/basetypes.h b/rehlds/public/basetypes.h index 19c3fa4..547fe3e 100644 --- a/rehlds/public/basetypes.h +++ b/rehlds/public/basetypes.h @@ -1,4 +1,4 @@ -//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ +//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============ // // Purpose: // @@ -70,8 +70,6 @@ typedef unsigned char BYTE; typedef unsigned char byte; typedef unsigned short word; -#include "string_t.h" - typedef float vec_t; diff --git a/rehlds/public/rehlds/hookchains.h b/rehlds/public/rehlds/hookchains.h index 9e16fa8..520d99b 100644 --- a/rehlds/public/rehlds/hookchains.h +++ b/rehlds/public/rehlds/hookchains.h @@ -48,14 +48,25 @@ public: virtual void callOriginal(t_args... args) = 0; }; +// Specifies priorities for hooks call order in the chain. +// For equal priorities first registered hook will be called first. +enum HookChainPriority : int +{ + HC_PRIORITY_UNINTERRUPTABLE = 255, // Hook will be called before other hooks. + HC_PRIORITY_HIGH = 192, // Hook will be called before hooks with default priority. + HC_PRIORITY_DEFAULT = 128, // Default hook call priority. + HC_PRIORITY_MEDIUM = 64, // Hook will be called after hooks with default priority. + HC_PRIORITY_LOW = 0, // Hook will be called after all other hooks. +}; + // Hook chain registry(for hooks [un]registration) template class IHookChainRegistry { public: typedef t_ret(*hookfunc_t)(IHookChain*, t_args...); - virtual void registerHook(hookfunc_t hook) = 0; - virtual void unregisterHook(hookfunc_t hook) = 0; + virtual void registerHook(hookfunc_t hook, int pri = HC_PRIORITY_DEFAULT) = 0; + virtual void unregisterHook(hookfunc_t hook, int pri = HC_PRIORITY_DEFAULT) = 0; }; // Hook chain registry(for hooks [un]registration) @@ -64,6 +75,6 @@ class IVoidHookChainRegistry { public: typedef void(*hookfunc_t)(IVoidHookChain*, t_args...); - virtual void registerHook(hookfunc_t hook) = 0; - virtual void unregisterHook(hookfunc_t hook) = 0; + virtual void registerHook(hookfunc_t hook, int pri = HC_PRIORITY_DEFAULT) = 0; + virtual void unregisterHook(hookfunc_t hook, int pri = HC_PRIORITY_DEFAULT) = 0; }; diff --git a/rehlds/public/rehlds/rehlds_api.h b/rehlds/public/rehlds/rehlds_api.h index f315f62..79e75d0 100644 --- a/rehlds/public/rehlds/rehlds_api.h +++ b/rehlds/public/rehlds/rehlds_api.h @@ -34,7 +34,7 @@ #include "interface.h" #include "model.h" -#define REHLDS_API_VERSION_MAJOR 2 +#define REHLDS_API_VERSION_MAJOR 3 #define REHLDS_API_VERSION_MINOR 13 //Steam_NotifyClientConnect hook diff --git a/rehlds/public/string_t.h b/rehlds/public/string_t.h deleted file mode 100644 index 385dc19..0000000 --- a/rehlds/public/string_t.h +++ /dev/null @@ -1,106 +0,0 @@ -//========= Copyright (c) 1996-2002, Valve LLC, All rights reserved. ========== -// -// Purpose: Defines the more complete set of operations on the string_t defined -// These should be used instead of direct manipulation to allow more -// flexibility in future ports or optimization. -// -// $NoKeywords: $ -//============================================================================= - -#ifndef STRING_T_H -#define STRING_T_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "osconfig.h" -#include - -#ifndef NO_STRING_T - -#ifdef WEAK_STRING_T - -typedef int valve_string_t; - -//----------------------------------------------------------------------------- -// Purpose: The correct way to specify the NULL string as a constant. -//----------------------------------------------------------------------------- - -#define NULL_STRING 0 - -//----------------------------------------------------------------------------- -// Purpose: Given a string_t, make a C string. By convention the result string -// pointer should be considered transient and should not be stored. -//----------------------------------------------------------------------------- - -#define STRING( offset ) ( ( offset ) ? reinterpret_cast( offset ) : "" ) - -//----------------------------------------------------------------------------- -// Purpose: Given a C string, obtain a string_t -//----------------------------------------------------------------------------- - -#define MAKE_STRING( str ) ( ( *str != 0 ) ? reinterpret_cast( str ) : 0 ) - -//----------------------------------------------------------------------------- - -#else // Strong string_t - -//----------------------------------------------------------------------------- - -struct valve_string_t -{ -public: - bool operator!() const { return (pszValue == NULL); } - bool operator==(const valve_string_t &rhs) const { return (pszValue == rhs.pszValue); } - bool operator!=(const valve_string_t &rhs) const { return (pszValue != rhs.pszValue); } - - const char *ToCStr() const { return (pszValue) ? pszValue : ""; } - -protected: - const char *pszValue; -}; - -//----------------------------------------------------------------------------- - -struct castable_string_t : public valve_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 != 0) ? pszFrom : 0; } -}; - -//----------------------------------------------------------------------------- -// Purpose: The correct way to specify the NULL string as a constant. -//----------------------------------------------------------------------------- - -#define NULL_STRING castable_string_t() - -//----------------------------------------------------------------------------- -// Purpose: Given a string_t, make a C string. By convention the result string -// pointer should be considered transient and should not be stored. -//----------------------------------------------------------------------------- - -#define STRING( string_t_obj ) (string_t_obj).ToCStr() - -//----------------------------------------------------------------------------- -// Purpose: Given a C string, obtain a string_t -//----------------------------------------------------------------------------- - -#define MAKE_STRING( c_str ) castable_string_t( c_str ) - -//----------------------------------------------------------------------------- - -#endif - -#else // NO_STRING_T - -typedef const char *string_t; -#define NULL_STRING 0 -#define STRING( c_str ) ( c_str ) -#define MAKE_STRING( c_str ) ( c_str ) - -#endif // NO_STRING_T - -//============================================================================= - -#endif // STRING_T_H diff --git a/rehlds/rehlds/hookchains_impl.cpp b/rehlds/rehlds/hookchains_impl.cpp index 5a21ec3..b117f10 100644 --- a/rehlds/rehlds/hookchains_impl.cpp +++ b/rehlds/rehlds/hookchains_impl.cpp @@ -25,28 +25,57 @@ AbstractHookChainRegistry::AbstractHookChainRegistry() m_NumHooks = 0; } -void AbstractHookChainRegistry::addHook(void* hookFunc) { +void AbstractHookChainRegistry::addHook(void* hookFunc, int priority) { if (m_NumHooks >= MAX_HOOKS_IN_CHAIN) { rehlds_syserror("MAX_HOOKS_IN_CHAIN limit hit"); } - m_Hooks[m_NumHooks++] = hookFunc; + for (int i = 0; i < MAX_HOOKS_IN_CHAIN; i++) + { + if (m_Hooks[i] && priority <= m_Priorities[i]) + continue; + + auto swapHookFunc = m_Hooks[i]; + auto swapPriority = m_Priorities[i]; + + m_Hooks[i] = hookFunc; + m_Priorities[i] = priority; + + hookFunc = swapHookFunc; + priority = swapPriority; + } + + m_NumHooks++; } -void AbstractHookChainRegistry::removeHook(void* hookFunc) { +void AbstractHookChainRegistry::removeHook(void* hookFunc, int priority) { - // erase hook - for (int i = 0; i < m_NumHooks; i++) { - if (hookFunc == m_Hooks[i]) { - if (--m_NumHooks != i) - { - Q_memmove(&m_Hooks[i], &m_Hooks[i + 1], (m_NumHooks - i) * sizeof(m_Hooks[0])); - m_Hooks[m_NumHooks] = NULL; - } - else - m_Hooks[i] = NULL; + int bestMatch = -1; - return; + // Search for matching hook func address and priority or at least address match + for (int i = 0; i < m_NumHooks; i++) + { + if (hookFunc == m_Hooks[i]) + { + bestMatch = i; + if (m_Priorities[i] == priority) + break; } } + + if (bestMatch >= 0) + { + // erase hook + --m_NumHooks; + + if (m_NumHooks != bestMatch) + { + Q_memmove(&m_Hooks[bestMatch], &m_Hooks[bestMatch + 1], (m_NumHooks - bestMatch) * sizeof(m_Hooks[0])); + Q_memmove(&m_Priorities[bestMatch], &m_Priorities[bestMatch + 1], (m_NumHooks - bestMatch) * sizeof(m_Priorities[0])); + + m_Hooks[m_NumHooks] = NULL; + } + else + m_Hooks[bestMatch] = NULL; + } } diff --git a/rehlds/rehlds/hookchains_impl.h b/rehlds/rehlds/hookchains_impl.h index 30cd24a..7a1cfbf 100644 --- a/rehlds/rehlds/hookchains_impl.h +++ b/rehlds/rehlds/hookchains_impl.h @@ -92,8 +92,7 @@ public: } virtual void callOriginal(t_args... args) { - origfunc_t origfunc = (origfunc_t)m_OriginalFunc; - origfunc(args...); + m_OriginalFunc(args...); } private: @@ -104,11 +103,12 @@ private: class AbstractHookChainRegistry { protected: void* m_Hooks[MAX_HOOKS_IN_CHAIN + 1]; // +1 for null + int m_Priorities[MAX_HOOKS_IN_CHAIN + 1]; int m_NumHooks; protected: - void addHook(void* hookFunc); - void removeHook(void* hookFunc); + void addHook(void* hookFunc, int priority); + void removeHook(void* hookFunc, int priority); public: AbstractHookChainRegistry(); @@ -127,11 +127,11 @@ public: return chain.callNext(args...); } - virtual void registerHook(hookfunc_t hook) { - addHook((void*)hook); + virtual void registerHook(hookfunc_t hook, int priority) { + addHook((void*)hook, priority); } - virtual void unregisterHook(hookfunc_t hook) { - removeHook((void*)hook); + virtual void unregisterHook(hookfunc_t hook, int priority) { + removeHook((void*)hook, priority); } }; @@ -148,11 +148,11 @@ public: chain.callNext(args...); } - virtual void registerHook(hookfunc_t hook) { - addHook((void*)hook); + virtual void registerHook(hookfunc_t hook, int priority) { + addHook((void*)hook, priority); } - virtual void unregisterHook(hookfunc_t hook) { - removeHook((void*)hook); + virtual void unregisterHook(hookfunc_t hook, int priority) { + removeHook((void*)hook, priority); } }; diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp index 312484f..d9f9472 100644 --- a/rehlds/rehlds/rehlds_api_impl.cpp +++ b/rehlds/rehlds/rehlds_api_impl.cpp @@ -36,11 +36,9 @@ struct plugin_api_t std::vector g_PluginApis; plugin_api_t* FindPluginApiByName(const char *name) { - for (auto it = g_PluginApis.begin(), end = g_PluginApis.end(); it != end; ++it) { - auto api = *it; - - if (!strcmp(api->name, name)) { - return api; + for (auto pl : g_PluginApis) { + if (!strcmp(pl->name, name)) { + return pl; } } @@ -147,7 +145,9 @@ void EXT_FUNC Rehlds_RegisterPluginApi(const char *name, void *impl) { if (!api) { api = new plugin_api_t; - strncpy(api->name, name, sizeof api->name - 1); + Q_strncpy(api->name, name, sizeof api->name - 1); + api->name[sizeof api->name - 1] = '\0'; + g_PluginApis.push_back(api); }