Update code add natives and listeners
This commit is contained in:
parent
f9af5e9017
commit
2f38de616e
7
Makefile
7
Makefile
@ -5,7 +5,7 @@
|
|||||||
### EDIT THESE PATHS FOR YOUR OWN SETUP ###
|
### EDIT THESE PATHS FOR YOUR OWN SETUP ###
|
||||||
###########################################
|
###########################################
|
||||||
|
|
||||||
SMSDK = ../sourcemod-1.5
|
SMSDK = ../sourcemod-central
|
||||||
HL2SDK_ORIG = ../../../hl2sdk
|
HL2SDK_ORIG = ../../../hl2sdk
|
||||||
HL2SDK_OB = ../../../hl2sdk-ob
|
HL2SDK_OB = ../../../hl2sdk-ob
|
||||||
HL2SDK_CSS = ../hl2sdk-css
|
HL2SDK_CSS = ../hl2sdk-css
|
||||||
@ -24,7 +24,7 @@ PROJECT = sample
|
|||||||
#Uncomment for Metamod: Source enabled extension
|
#Uncomment for Metamod: Source enabled extension
|
||||||
USEMETA = true
|
USEMETA = true
|
||||||
|
|
||||||
OBJECTS = sdk/smsdk_ext.cpp extension.cpp vhook.cpp
|
OBJECTS = sdk/smsdk_ext.cpp extension.cpp vhook.cpp ../sourcemod-central/public/jit/x86/assembler-x86.cpp
|
||||||
|
|
||||||
##############################################
|
##############################################
|
||||||
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
|
||||||
@ -109,7 +109,7 @@ else
|
|||||||
LIB_SUFFIX = .$(LIB_EXT)
|
LIB_SUFFIX = .$(LIB_EXT)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions
|
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions -I$(SMSDK)/public/jit/x86 -I$(SMSDK)/public/jit
|
||||||
|
|
||||||
ifeq "$(USEMETA)" "true"
|
ifeq "$(USEMETA)" "true"
|
||||||
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/$(LIB_PREFIX)vstdlib_srv$(LIB_SUFFIX) $(HL2LIB)/$(LIB_PREFIX)tier0_srv$(LIB_SUFFIX)
|
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/$(LIB_PREFIX)vstdlib_srv$(LIB_SUFFIX) $(HL2LIB)/$(LIB_PREFIX)tier0_srv$(LIB_SUFFIX)
|
||||||
@ -205,6 +205,7 @@ $(BIN_DIR)/%.o: %.cpp
|
|||||||
|
|
||||||
all: check
|
all: check
|
||||||
mkdir -p $(BIN_DIR)/sdk
|
mkdir -p $(BIN_DIR)/sdk
|
||||||
|
mkdir -p $(BIN_DIR)/../sourcemod-central/public/jit/x86
|
||||||
if [ "$(USEMETA)" = "true" ]; then \
|
if [ "$(USEMETA)" = "true" ]; then \
|
||||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \
|
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \
|
||||||
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \
|
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \
|
||||||
|
137
extension.cpp
137
extension.cpp
@ -1,41 +1,101 @@
|
|||||||
#include "extension.h"
|
#include "extension.h"
|
||||||
#include "vhook.h"
|
#include "vhook.h"
|
||||||
|
#include "listeners.h"
|
||||||
|
#include <macro-assembler-x86.h>
|
||||||
|
|
||||||
DHooks g_Sample; /**< Global singleton for extension's main interface */
|
DHooks g_DHooksIface; /**< Global singleton for extension's main interface */
|
||||||
SMEXT_LINK(&g_Sample);
|
SMEXT_LINK(&g_DHooksIface);
|
||||||
|
|
||||||
IBinTools *g_pBinTools;
|
IBinTools *g_pBinTools;
|
||||||
ISDKHooks *g_pSDKHooks;
|
ISDKHooks *g_pSDKHooks;
|
||||||
ISDKTools *g_pSDKTools;
|
ISDKTools *g_pSDKTools;
|
||||||
|
DHooksEntityListener *g_pEntityListener = NULL;
|
||||||
|
|
||||||
CBitVec<NUM_ENT_ENTRIES> m_EntityExists;
|
bool g_bAllowGamerules = true;
|
||||||
|
|
||||||
|
HandleType_t g_HookSetupHandle = 0;
|
||||||
|
HandleType_t g_HookParamsHandle = 0;
|
||||||
|
HandleType_t g_HookReturnHandle = 0;
|
||||||
|
|
||||||
bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||||
sharesys->AddDependency(myself, "sdktools.ext", true, true);
|
sharesys->AddDependency(myself, "sdktools.ext", true, true);
|
||||||
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
|
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
|
||||||
|
|
||||||
sharesys->RegisterLibrary(myself, "dhooks");
|
sharesys->RegisterLibrary(myself, "dhooks");
|
||||||
|
plsys->AddPluginsListener(this);
|
||||||
|
sharesys->AddNatives(myself, g_Natives);
|
||||||
|
|
||||||
return true;
|
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()
|
void DHooks::SDK_OnAllLoaded()
|
||||||
{
|
{
|
||||||
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
|
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
|
||||||
if(g_pSDKTools == NULL)
|
|
||||||
{
|
if(g_pSDKTools->GetInterfaceVersion() < 2)
|
||||||
smutils->LogError(myself, "SDKTools interface not found. DHookGamerules native disabled.");
|
|
||||||
}
|
|
||||||
else if(g_pSDKTools->GetInterfaceVersion() < 2)
|
|
||||||
{
|
{
|
||||||
//<psychonic> THIS ISN'T DA LIMBO STICK. LOW IS BAD
|
//<psychonic> THIS ISN'T DA LIMBO STICK. LOW IS BAD
|
||||||
|
g_bAllowGamerules = false;
|
||||||
smutils->LogError(myself, "SDKTools interface is outdated. DHookGamerules native disabled.");
|
smutils->LogError(myself, "SDKTools interface is outdated. DHookGamerules native disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
||||||
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
|
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
|
||||||
g_pSDKHooks->AddEntityListener(this);
|
|
||||||
|
g_pEntityListener = new DHooksEntityListener();
|
||||||
|
g_pSDKHooks->AddEntityListener(g_pEntityListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DHooks::SDK_OnUnload()
|
||||||
|
{
|
||||||
|
CleanupHooks(NULL);
|
||||||
|
if(g_pEntityListener)
|
||||||
|
{
|
||||||
|
g_pEntityListener->CleanupListeners(NULL);
|
||||||
|
g_pSDKHooks->RemoveEntityListener(g_pEntityListener);
|
||||||
|
delete g_pEntityListener;
|
||||||
|
}
|
||||||
|
plsys->RemovePluginsListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
|
bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
|
||||||
{
|
{
|
||||||
if(!SetupHookManager(ismm))
|
if(!SetupHookManager(ismm))
|
||||||
@ -45,61 +105,12 @@ bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, boo
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
DHooksManager *manager1;
|
|
||||||
DHooksManager *manager2;
|
|
||||||
|
|
||||||
#ifndef __linux__
|
void DHooks::OnPluginUnloaded(IPlugin *plugin)
|
||||||
#define WEAPON_CANUSE 258
|
|
||||||
#define SET_MODEL 24
|
|
||||||
#else
|
|
||||||
#define WEAPON_CANUSE 259
|
|
||||||
#define SET_MODEL 25
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void DHooks::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
|
|
||||||
{
|
{
|
||||||
int entity = gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(pEntity));
|
CleanupHooks(plugin->GetBaseContext());
|
||||||
|
if(g_pEntityListener)
|
||||||
if(entity <= playerhelpers->GetMaxClients() && entity > 0)
|
{
|
||||||
{
|
g_pEntityListener->CleanupListeners(plugin->GetBaseContext());
|
||||||
SourceHook::HookManagerPubFunc hook;
|
|
||||||
SourceHook::CProtoInfoBuilder protoInfo(SourceHook::ProtoInfo::CallConv_ThisCall);
|
|
||||||
protoInfo.AddParam(sizeof(CBaseEntity *), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, NULL, NULL, NULL, NULL);
|
|
||||||
protoInfo.SetReturnType(sizeof(bool), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, NULL, NULL, NULL, NULL);
|
|
||||||
hook = g_pHookManager->MakeHookMan(protoInfo, 0, WEAPON_CANUSE);
|
|
||||||
manager1 = new DHooksManager();
|
|
||||||
manager1->callback_bool = new DHooksCallback<bool>();
|
|
||||||
manager1->callback_bool->paramcount = 1;
|
|
||||||
manager1->callback_bool->params[0].size = sizeof(CBaseEntity *);
|
|
||||||
manager1->callback_bool->params[0].type = HookParamType_CBaseEntity;
|
|
||||||
manager1->callback_bool->params[0].flag = PASSFLAG_BYVAL;
|
|
||||||
manager1->callback_bool->offset = WEAPON_CANUSE;
|
|
||||||
manager1->hookid = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, pEntity, 0, hook, manager1->callback_bool, false);
|
|
||||||
|
|
||||||
SourceHook::CProtoInfoBuilder protoInfo2(SourceHook::ProtoInfo::CallConv_ThisCall);
|
|
||||||
protoInfo2.AddParam(sizeof(char *), SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, NULL, NULL, NULL, NULL);
|
|
||||||
protoInfo2.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, NULL, NULL, NULL, NULL);
|
|
||||||
hook = g_pHookManager->MakeHookMan(protoInfo2, 0, SET_MODEL);
|
|
||||||
manager2 = new DHooksManager();
|
|
||||||
manager2->callback_void = new DHooksCallback<void>();
|
|
||||||
manager2->callback_void->paramcount = 1;
|
|
||||||
manager2->callback_void->params[0].size = sizeof(char *);
|
|
||||||
manager2->callback_void->params[0].type = HookParamType_CharPtr;
|
|
||||||
manager2->callback_void->params[0].flag = PASSFLAG_BYVAL;
|
|
||||||
manager2->callback_void->offset = SET_MODEL;
|
|
||||||
manager2->hookid = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, pEntity, 0, hook, manager2->callback_void, false);
|
|
||||||
|
|
||||||
META_CONPRINTF("Hooked entity %i\n", entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void DHooks::OnEntityDestroyed(CBaseEntity *pEntity)
|
|
||||||
{
|
|
||||||
int entity = gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(pEntity));
|
|
||||||
|
|
||||||
if(entity <= playerhelpers->GetMaxClients() && entity > 0)
|
|
||||||
{
|
|
||||||
META_CONPRINTF("Cleaning\n");
|
|
||||||
delete manager1;
|
|
||||||
delete manager2;
|
|
||||||
}
|
|
||||||
}
|
|
12
extension.h
12
extension.h
@ -48,12 +48,13 @@
|
|||||||
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DHooks : public SDKExtension, public ISMEntityListener
|
class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
|
void OnHandleDestroy(HandleType_t type, void *object);
|
||||||
void OnEntityDestroyed(CBaseEntity *pEntity);
|
public: //IPluginsListener
|
||||||
|
void OnPluginUnloaded(IPlugin *plugin);
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief This is called after the initial loading sequence has been processed.
|
* @brief This is called after the initial loading sequence has been processed.
|
||||||
*
|
*
|
||||||
@ -67,7 +68,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief This is called right before the extension is unloaded.
|
* @brief This is called right before the extension is unloaded.
|
||||||
*/
|
*/
|
||||||
//virtual void SDK_OnUnload();
|
virtual void SDK_OnUnload();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is called once all known extensions have been loaded.
|
* @brief This is called once all known extensions have been loaded.
|
||||||
@ -123,4 +124,5 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
extern SourceHook::IHookManagerAutoGen *g_pHookManager;
|
extern SourceHook::IHookManagerAutoGen *g_pHookManager;
|
||||||
|
extern sp_nativeinfo_t g_Natives[];
|
||||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||||
|
61
listeners.cpp
Normal file
61
listeners.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "listeners.h"
|
||||||
|
#include "vhook.h"
|
||||||
|
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
CUtlVector<EntityListener> g_EntityListeners;
|
||||||
|
|
||||||
|
void DHooksEntityListener::CleanupListeners(IPluginContext *pContext)
|
||||||
|
{
|
||||||
|
for(int i = g_EntityListeners.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(pContext == NULL || pContext == g_EntityListeners.Element(i).callback->GetParentContext())
|
||||||
|
{
|
||||||
|
g_EntityListeners.Remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHooksEntityListener::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
|
||||||
|
{
|
||||||
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||||
|
|
||||||
|
for(int i = g_EntityListeners.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
EntityListener listerner = g_EntityListeners.Element(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.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
EntityListener listerner = g_EntityListeners.Element(i);
|
||||||
|
if(listerner.type == ListenType_Deleted)
|
||||||
|
{
|
||||||
|
IPluginFunction *callback = listerner.callback;
|
||||||
|
callback->PushCell(gamehelpers->EntityToBCompatRef(pEntity));
|
||||||
|
callback->Execute(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = g_pHooks.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
DHooksManager *manager = g_pHooks.Element(i);
|
||||||
|
if(manager->callback->entity == entity)
|
||||||
|
{
|
||||||
|
META_CONPRINT("Removing 1\n");
|
||||||
|
delete manager;
|
||||||
|
g_pHooks.Remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
listeners.h
Normal file
28
listeners.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _INCLUDE_FORWARDS_H_
|
||||||
|
#define _INCLUDE_FORWARDS_H_
|
||||||
|
|
||||||
|
#include "extension.h"
|
||||||
|
#include "vhook.h"
|
||||||
|
|
||||||
|
class DHooksEntityListener : public ISMEntityListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
|
||||||
|
void OnEntityDestroyed(CBaseEntity *pEntity);
|
||||||
|
void CleanupListeners(IPluginContext *func);
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ListenType
|
||||||
|
{
|
||||||
|
ListenType_Created,
|
||||||
|
ListenType_Deleted
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityListener
|
||||||
|
{
|
||||||
|
ListenType type;
|
||||||
|
IPluginFunction *callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CUtlVector<DHooksManager *> g_pHooks;
|
||||||
|
#endif
|
@ -599,7 +599,7 @@
|
|||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalOptions>/MP /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_ORANGEBOXVALVE=6 /D SE_LEFT4DEAD=7 /D SE_LEFT4DEAD2=8 /D SE_ALIENSWARM=9 /D SE_PORTAL2=10 /D SE_CSGO=11 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/MP /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_ORANGEBOXVALVE=6 /D SE_LEFT4DEAD=7 /D SE_LEFT4DEAD2=8 /D SE_ALIENSWARM=9 /D SE_PORTAL2=10 /D SE_CSGO=11 %(AdditionalOptions)</AdditionalOptions>
|
||||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||||
<AdditionalIncludeDirectories>..;..\sdk;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(SOURCEMOD)\public;$(SOURCEMOD)\public\sourcepawn;$(SOURCEMOD)\public\extensions;$(HL2SDKOBVALVE)\game\server;$(HL2SDKOBVALVE)\game\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..;..\sdk;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(SMCENTRAL)\public;$(SMCENTRAL)\public\sourcepawn;$(SMCENTRAL)\public\extensions;$(HL2SDKOBVALVE)\game\server;$(HL2SDKOBVALVE)\game\shared;$(SMCENTRAL)\public\jit;$(SMCENTRAL)\public\jit\x86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;SOURCE_ENGINE=6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCEMOD_BUILD;SOURCE_ENGINE=6;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
|
||||||
@ -610,7 +610,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>$(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<OutputFile>$(OutDir)sample.ext.2.css.dll</OutputFile>
|
<OutputFile>$(OutDir)dhooks.ext.2.css.dll</OutputFile>
|
||||||
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
@ -882,12 +882,17 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\sourcemod-central\public\jit\x86\assembler-x86.cpp" />
|
||||||
<ClCompile Include="..\extension.cpp" />
|
<ClCompile Include="..\extension.cpp" />
|
||||||
|
<ClCompile Include="..\listeners.cpp" />
|
||||||
|
<ClCompile Include="..\natives.cpp" />
|
||||||
<ClCompile Include="..\vhook.cpp" />
|
<ClCompile Include="..\vhook.cpp" />
|
||||||
<ClCompile Include="..\sdk\smsdk_ext.cpp" />
|
<ClCompile Include="..\sdk\smsdk_ext.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\extension.h" />
|
<ClInclude Include="..\extension.h" />
|
||||||
|
<ClInclude Include="..\listeners.h" />
|
||||||
|
<ClInclude Include="..\natives.h" />
|
||||||
<ClInclude Include="..\vhook.h" />
|
<ClInclude Include="..\vhook.h" />
|
||||||
<ClInclude Include="..\sdk\smsdk_config.h" />
|
<ClInclude Include="..\sdk\smsdk_config.h" />
|
||||||
<ClInclude Include="..\sdk\smsdk_ext.h" />
|
<ClInclude Include="..\sdk\smsdk_ext.h" />
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\vhook.cpp" />
|
<ClCompile Include="..\vhook.cpp" />
|
||||||
<ClCompile Include="..\extension.cpp" />
|
<ClCompile Include="..\extension.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\sourcemod-central\public\jit\x86\assembler-x86.cpp">
|
||||||
|
<Filter>JIT</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\natives.cpp" />
|
||||||
|
<ClCompile Include="..\listeners.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\extension.h">
|
<ClInclude Include="..\extension.h">
|
||||||
@ -23,6 +28,12 @@
|
|||||||
<ClInclude Include="..\vhook_macros.h">
|
<ClInclude Include="..\vhook_macros.h">
|
||||||
<Filter>Headers</Filter>
|
<Filter>Headers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\natives.h">
|
||||||
|
<Filter>Headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\listeners.h">
|
||||||
|
<Filter>Headers</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Headers">
|
<Filter Include="Headers">
|
||||||
@ -31,5 +42,8 @@
|
|||||||
<Filter Include="sdk">
|
<Filter Include="sdk">
|
||||||
<UniqueIdentifier>{8a0b4570-752f-44d9-b270-ef886743e9ea}</UniqueIdentifier>
|
<UniqueIdentifier>{8a0b4570-752f-44d9-b270-ef886743e9ea}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="JIT">
|
||||||
|
<UniqueIdentifier>{9ac7d92a-8a9d-4e7c-b108-09d915244278}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
252
natives.cpp
Normal file
252
natives.cpp
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#include "natives.h"
|
||||||
|
|
||||||
|
CBaseEntity *UTIL_GetCBaseEntity(int num)
|
||||||
|
{
|
||||||
|
edict_t *pEdict = gamehelpers->EdictOfIndex(num);
|
||||||
|
if (!pEdict || pEdict->IsFree())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
IServerUnknown *pUnk;
|
||||||
|
if ((pUnk=pEdict->GetUnknown()) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pUnk->GetBaseEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
//native Handle:DHookCreate(offset, HookType:hooktype, ReturnType:returntype, ThisPointerType:thistype, DHookCallback:callback);
|
||||||
|
cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if(!pContext->GetFunctionById(params[5]))
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Failed to retrieve function by id");
|
||||||
|
}
|
||||||
|
|
||||||
|
HookSetup *setup = new HookSetup((ReturnType)params[3], PASSFLAG_BYVAL,(HookType)params[2], (ThisPointerType)params[4], params[1], pContext->GetFunctionById(params[5]));
|
||||||
|
|
||||||
|
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:DHookAddParam(Handle:setup, HookParamType:type);
|
||||||
|
cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if(params[1] == BAD_HANDLE)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleError err;
|
||||||
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||||
|
HookSetup *setup;
|
||||||
|
|
||||||
|
if((err = handlesys->ReadHandle(params[1], g_HookSetupHandle, &sec, (void **)&setup)) != HandleError_None)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||||
|
}
|
||||||
|
ParamInfo info;
|
||||||
|
|
||||||
|
if(params[0] == 3)
|
||||||
|
{
|
||||||
|
info.flag = params[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.flag = PASSFLAG_BYVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.type = (HookParamType)params[2];
|
||||||
|
info.size = GetParamTypeSize(info.type);
|
||||||
|
info.pass_type = GetParamTypePassType(info.type);
|
||||||
|
setup->params.AddToTail(info);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cell_t Native_HookEntity(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if(params[1] == BAD_HANDLE)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleError err;
|
||||||
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||||
|
HookSetup *setup;
|
||||||
|
|
||||||
|
if((err = handlesys->ReadHandle(params[1], g_HookSetupHandle, &sec, (void **)&setup)) != HandleError_None)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||||
|
}
|
||||||
|
if(setup->hookType != HookType_Entity)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Hook is not an entity hook");
|
||||||
|
}
|
||||||
|
bool post = params[2] != 0;
|
||||||
|
|
||||||
|
for(int i = g_pHooks.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(g_pHooks.Element(i)->callback->hookType == HookType_Entity && g_pHooks.Element(i)->callback->entity == params[3] && g_pHooks.Element(i)->callback->offset == setup->offset && g_pHooks.Element(i)->callback->post == post && g_pHooks.Element(i)->remove_callback == pContext->GetFunctionById(params[4]) && g_pHooks.Element(i)->callback->plugin_callback == setup->callback)
|
||||||
|
{
|
||||||
|
return g_pHooks.Element(i)->hookid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CBaseEntity *pEnt = UTIL_GetCBaseEntity(params[3]);
|
||||||
|
|
||||||
|
if(!pEnt)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid entity passed %i", params[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DHooksManager *manager = new DHooksManager(setup, pEnt, pContext->GetFunctionById(params[4]), post);
|
||||||
|
|
||||||
|
if(!manager->hookid)
|
||||||
|
{
|
||||||
|
delete manager;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pHooks.AddToTail(manager);
|
||||||
|
|
||||||
|
return manager->hookid;
|
||||||
|
}
|
||||||
|
/*cell_t Native_HookGamerules(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_RemoveHookID(IPluginContext *pContext, const cell_t *params);*/
|
||||||
|
cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if(params[1] == BAD_HANDLE)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleError err;
|
||||||
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||||
|
HookParamsStruct *paramStruct;
|
||||||
|
if((err = handlesys->ReadHandle(params[1], g_HookParamsHandle, &sec, (void **)¶mStruct)) != HandleError_None)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params[2] > paramStruct->dg->params.Count() || params[2] < 0)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.Count());
|
||||||
|
}
|
||||||
|
if(params[2] == 0)
|
||||||
|
{
|
||||||
|
return paramStruct->dg->params.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = params[2] - 1;
|
||||||
|
|
||||||
|
if(paramStruct->orgParams[index] == NULL && (paramStruct->dg->params.Element(index).type == HookParamType_CBaseEntity || paramStruct->dg->params.Element(index).type == HookParamType_Edict))
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Trying to get value for null pointer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(paramStruct->dg->params.Element(index).type)
|
||||||
|
{
|
||||||
|
case HookParamType_Int:
|
||||||
|
return (int)paramStruct->orgParams[index];
|
||||||
|
case HookParamType_Bool:
|
||||||
|
return (cell_t)paramStruct->orgParams[index] != 0;
|
||||||
|
case HookParamType_CBaseEntity:
|
||||||
|
return gamehelpers->EntityToBCompatRef((CBaseEntity *)paramStruct->orgParams[index]);
|
||||||
|
case HookParamType_Edict:
|
||||||
|
return gamehelpers->IndexOfEdict((edict_t *)paramStruct->orgParams[index]);
|
||||||
|
case HookParamType_Float:
|
||||||
|
return sp_ftoc(*(float *)paramStruct->orgParams[index]);
|
||||||
|
default:
|
||||||
|
return pContext->ThrowNativeError("Invalid param type (%i) to get", paramStruct->dg->params.Element(index).type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*cell_t Native_SetParam(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_GetParamVector(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_GetReturnVector(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_SetReturnVector(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params);*/
|
||||||
|
cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
if(params[1] == BAD_HANDLE)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %i", BAD_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleError err;
|
||||||
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
||||||
|
HookParamsStruct *paramStruct;
|
||||||
|
if((err = handlesys->ReadHandle(params[1], g_HookParamsHandle, &sec, (void **)¶mStruct)) != HandleError_None)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params[2] > paramStruct->dg->params.Count() || params[2] <= 0)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.Count());
|
||||||
|
}
|
||||||
|
int index = params[2] - 1;
|
||||||
|
|
||||||
|
if(paramStruct->orgParams[index] == NULL)
|
||||||
|
{
|
||||||
|
return pContext->ThrowNativeError("Trying to get value for null pointer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(paramStruct->dg->params.Element(index).type == HookParamType_CharPtr)
|
||||||
|
{
|
||||||
|
pContext->StringToLocal(params[3], params[4], (const char *)paramStruct->orgParams[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//cell_t Native_GetReturnString(IPluginContext *pContext, const cell_t *params);
|
||||||
|
//cell_t Native_SetReturnString(IPluginContext *pContext, const cell_t *params);
|
||||||
|
cell_t Native_SetParamString(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_nativeinfo_t g_Natives[] =
|
||||||
|
{
|
||||||
|
{"DHookCreate", Native_CreateHook},
|
||||||
|
{"DHookAddParam", Native_AddParam},
|
||||||
|
{"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},
|
||||||
|
{"DHookIsNullParam", Native_IsNullParam},*/
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
12
natives.h
Normal file
12
natives.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _INCLUDE_NATIVES_H_
|
||||||
|
#define _INCLUDE_NATIVES_H_
|
||||||
|
|
||||||
|
#include "extension.h"
|
||||||
|
#include "vhook.h"
|
||||||
|
|
||||||
|
extern bool g_bAllowGamerules;
|
||||||
|
extern HandleType_t g_HookSetupHandle;
|
||||||
|
extern HandleType_t g_HookParamsHandle;
|
||||||
|
extern HandleType_t g_HookReturnHandle;
|
||||||
|
extern CUtlVector<DHooksManager *> g_pHooks;
|
||||||
|
#endif
|
@ -60,7 +60,7 @@
|
|||||||
|
|
||||||
/** Enable interfaces you want to use here by uncommenting lines */
|
/** Enable interfaces you want to use here by uncommenting lines */
|
||||||
//#define SMEXT_ENABLE_FORWARDSYS
|
//#define SMEXT_ENABLE_FORWARDSYS
|
||||||
//#define SMEXT_ENABLE_HANDLESYS
|
#define SMEXT_ENABLE_HANDLESYS
|
||||||
#define SMEXT_ENABLE_PLAYERHELPERS
|
#define SMEXT_ENABLE_PLAYERHELPERS
|
||||||
//#define SMEXT_ENABLE_DBMANAGER
|
//#define SMEXT_ENABLE_DBMANAGER
|
||||||
#define SMEXT_ENABLE_GAMECONF
|
#define SMEXT_ENABLE_GAMECONF
|
||||||
@ -71,7 +71,7 @@
|
|||||||
//#define SMEXT_ENABLE_LIBSYS
|
//#define SMEXT_ENABLE_LIBSYS
|
||||||
//#define SMEXT_ENABLE_MENUS
|
//#define SMEXT_ENABLE_MENUS
|
||||||
//#define SMEXT_ENABLE_ADTFACTORY
|
//#define SMEXT_ENABLE_ADTFACTORY
|
||||||
//#define SMEXT_ENABLE_PLUGINSYS
|
#define SMEXT_ENABLE_PLUGINSYS
|
||||||
//#define SMEXT_ENABLE_ADMINSYS
|
//#define SMEXT_ENABLE_ADMINSYS
|
||||||
//#define SMEXT_ENABLE_TEXTPARSERS
|
//#define SMEXT_ENABLE_TEXTPARSERS
|
||||||
//#define SMEXT_ENABLE_USERMSGS
|
//#define SMEXT_ENABLE_USERMSGS
|
||||||
|
455
vhook.cpp
455
vhook.cpp
@ -1,8 +1,71 @@
|
|||||||
#include "vhook.h"
|
#include "vhook.h"
|
||||||
#include "vhook_macros.h"
|
|
||||||
|
|
||||||
SourceHook::IHookManagerAutoGen *g_pHookManager = NULL;
|
SourceHook::IHookManagerAutoGen *g_pHookManager = NULL;
|
||||||
|
|
||||||
|
CUtlVector<DHooksManager *> g_pHooks;
|
||||||
|
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, bool post)
|
||||||
|
{
|
||||||
|
this->callback = MakeHandler(setup->returnType);
|
||||||
|
this->hookid = 0;
|
||||||
|
this->remove_callback = remove_callback;
|
||||||
|
this->callback->offset = setup->offset;
|
||||||
|
this->callback->plugin_callback = setup->callback;
|
||||||
|
this->callback->returnFlag = setup->returnFlag;
|
||||||
|
this->callback->thisType = setup->thisType;
|
||||||
|
this->callback->post = post;
|
||||||
|
this->callback->hookType = setup->hookType;
|
||||||
|
this->callback->params = setup->params;
|
||||||
|
|
||||||
|
if(this->callback->hookType == HookType_Entity)
|
||||||
|
{
|
||||||
|
this->callback->entity = gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->callback->entity = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CProtoInfoBuilder protoInfo(ProtoInfo::CallConv_ThisCall);
|
||||||
|
|
||||||
|
for(int i = this->callback->params.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
protoInfo.AddParam(this->callback->params.Element(i).size, this->callback->params.Element(i).pass_type, this->callback->params.Element(i).flag, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, 0, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Basic, 0, NULL, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
HookManagerPubFunc hook = g_pHookManager->MakeHookMan(protoInfo, 0, this->callback->offset);
|
||||||
|
|
||||||
|
this->hookid = g_SHPtr->AddHook(g_PLID,ISourceHook::Hook_Normal, iface, 0, hook, this->callback, this->callback->post);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CleanupHooks(IPluginContext *pContext)
|
||||||
|
{
|
||||||
|
for(int i = g_pHooks.Count() -1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
DHooksManager *manager = g_pHooks.Element(i);
|
||||||
|
|
||||||
|
if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentContext())
|
||||||
|
{
|
||||||
|
delete manager;
|
||||||
|
g_pHooks.Remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool SetupHookManager(ISmmAPI *ismm)
|
bool SetupHookManager(ISmmAPI *ismm)
|
||||||
{
|
{
|
||||||
g_pHookManager = static_cast<SourceHook::IHookManagerAutoGen *>(ismm->MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));
|
g_pHookManager = static_cast<SourceHook::IHookManagerAutoGen *>(ismm->MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));
|
||||||
@ -10,210 +73,208 @@ bool SetupHookManager(ISmmAPI *ismm)
|
|||||||
return g_pHookManager != NULL;
|
return g_pHookManager != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallFunction_Void(DHooksCallback<void> *info, unsigned long stack, void *iface)
|
size_t GetParamTypeSize(HookParamType type)
|
||||||
{
|
{
|
||||||
PassInfo *paramInfo = NULL;
|
return sizeof(void *);
|
||||||
ICallWrapper *call;
|
}
|
||||||
size_t size = 0;
|
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type)
|
||||||
|
{
|
||||||
if(info->paramcount > 0)
|
switch(type)
|
||||||
{
|
{
|
||||||
paramInfo = (PassInfo *)malloc(sizeof(PassInfo) * info->paramcount);
|
case HookParamType_Float:
|
||||||
for(int i = 0; i < info->paramcount; i++)
|
return SourceHook::PassInfo::PassType::PassType_Float;
|
||||||
|
default:
|
||||||
|
return SourceHook::PassInfo::PassType::PassType_Basic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t GetStackArgsSize(DHooksCallback *dg)
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
for(int i = dg->params.Count() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
res += dg->params.Element(i).size;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t argStackSize)
|
||||||
|
{
|
||||||
|
HookParamsStruct *res = new HookParamsStruct();
|
||||||
|
res->dg = dg;
|
||||||
|
res->orgParams = (void **)malloc(argStackSize);
|
||||||
|
res->newParams = (void **)malloc(argStackSize);
|
||||||
|
memcpy(res->orgParams, argStack, argStackSize);
|
||||||
|
for(int i = 0; i < dg->params.Count(); i++)
|
||||||
|
{
|
||||||
|
res->newParams[i] = NULL;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result)
|
||||||
|
{
|
||||||
|
HookReturnStruct *res = new HookReturnStruct();
|
||||||
|
res->isChanged = false;
|
||||||
|
res->type = dg->returnType;
|
||||||
|
res->orgResult = &result;
|
||||||
|
res->newResult = 0;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
cell_t GetThisPtr(void *iface, ThisPointerType type)
|
||||||
|
{
|
||||||
|
if(ThisPointer_CBaseEntity)
|
||||||
|
{
|
||||||
|
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (cell_t)iface;
|
||||||
|
}
|
||||||
|
#ifndef __linux__
|
||||||
|
void *Callback(DHooksCallback *dg, void **argStack, size_t *argsizep)
|
||||||
|
{
|
||||||
|
HookReturnStruct *returnStruct = NULL;
|
||||||
|
HookParamsStruct *paramStruct = NULL;
|
||||||
|
Handle_t rHndl;
|
||||||
|
Handle_t pHndl;
|
||||||
|
|
||||||
|
*argsizep = GetStackArgsSize(dg);
|
||||||
|
|
||||||
|
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||||
|
{
|
||||||
|
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||||
|
}
|
||||||
|
if(dg->returnType != ReturnType_Void)
|
||||||
|
{
|
||||||
|
returnStruct = GetReturnStruct(dg, g_SHPtr->GetOrigRet());
|
||||||
|
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||||
|
if(!rHndl)
|
||||||
{
|
{
|
||||||
switch(info->params[i].type)
|
if(returnStruct)
|
||||||
{
|
{
|
||||||
PARAMINFO_SWITCH_CASE(int, HookParamType_Int ,PassType_Basic);
|
delete returnStruct;
|
||||||
PARAMINFO_SWITCH_CASE(bool, HookParamType_Bool ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(float, HookParamType_Float ,PassType_Float);
|
|
||||||
PARAMINFO_SWITCH_CASE(string_t, HookParamType_String ,PassType_Object);
|
|
||||||
PARAMINFO_SWITCH_CASE(string_t *, HookParamType_StringPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(char *, HookParamType_CharPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(Vector *, HookParamType_VectorPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(CBaseEntity *, HookParamType_CBaseEntity ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(edict_t *, HookParamType_Edict ,PassType_Basic);
|
|
||||||
default:
|
|
||||||
paramInfo[i].flags = info->params[i].flag;
|
|
||||||
paramInfo[i].size = sizeof(void *);
|
|
||||||
paramInfo[i].type = PassType_Basic;
|
|
||||||
size += sizeof(void *);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
g_SHPtr->SetRes(MRES_IGNORED);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
call = g_pBinTools->CreateVCall(info->offset, 0, 0, NULL, paramInfo, info->paramcount);
|
dg->plugin_callback->PushCell(rHndl);
|
||||||
|
}
|
||||||
|
if(*argsizep > 0)
|
||||||
|
{
|
||||||
|
paramStruct = GetParamStruct(dg, argStack, *argsizep);
|
||||||
|
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||||
|
if(!pHndl)
|
||||||
|
{
|
||||||
|
if(returnStruct)
|
||||||
|
{
|
||||||
|
delete returnStruct;
|
||||||
|
}
|
||||||
|
if(paramStruct)
|
||||||
|
{
|
||||||
|
delete paramStruct;
|
||||||
|
}
|
||||||
|
g_SHPtr->SetRes(MRES_IGNORED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dg->plugin_callback->PushCell(pHndl);
|
||||||
|
}
|
||||||
|
cell_t result = (cell_t)MRES_Ignored;
|
||||||
|
dg->plugin_callback->Execute(&result);
|
||||||
|
|
||||||
|
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||||
|
void *res = 0;
|
||||||
|
|
||||||
|
switch((MRESReturn)result)
|
||||||
|
{
|
||||||
|
case MRES_Handled:
|
||||||
|
case MRES_ChangedHandled:
|
||||||
|
g_SHPtr->DoRecall();
|
||||||
|
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||||
|
//ret = CallVFunction(dg, argStack, g_SHPtr->GetIfacePtr());
|
||||||
|
memcpy(res, ret, sizeof(void *));
|
||||||
|
break;
|
||||||
|
case MRES_ChangedOverride:
|
||||||
|
g_SHPtr->DoRecall();
|
||||||
|
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||||
|
//CallVFunction(dg, argStack, g_SHPtr->GetIfacePtr());
|
||||||
|
if(dg->returnType != ReturnType_Void)
|
||||||
|
{
|
||||||
|
if(returnStruct->isChanged)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->newResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->newResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
else if(dg->post)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->orgResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->orgResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MRES_Override:
|
||||||
|
g_SHPtr->SetRes(MRES_OVERRIDE);
|
||||||
|
if(dg->returnType != ReturnType_Void)
|
||||||
|
{
|
||||||
|
if(returnStruct->isChanged)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->newResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->newResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
else if(dg->post)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->orgResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->orgResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MRES_Supercede:
|
||||||
|
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||||
|
if(dg->returnType != ReturnType_Void)
|
||||||
|
{
|
||||||
|
if(returnStruct->isChanged)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->newResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->newResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
else if(dg->post)
|
||||||
|
{
|
||||||
|
memcpy(ret, returnStruct->orgResult, sizeof(void *));
|
||||||
|
memcpy(res, returnStruct->orgResult, sizeof(void *));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_SHPtr->SetRes(MRES_IGNORED);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleSecurity sec(dg->plugin_callback->GetParentContext()->GetIdentity(), myself->GetIdentity());
|
||||||
|
|
||||||
|
if(returnStruct)
|
||||||
|
{
|
||||||
|
handlesys->FreeHandle(rHndl, &sec);
|
||||||
|
}
|
||||||
|
if(paramStruct)
|
||||||
|
{
|
||||||
|
handlesys->FreeHandle(pHndl, &sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void *Callback(DHooksCallback *dg, void **argStack)
|
||||||
|
{
|
||||||
|
if(dg->returnType == ReturnType_Void)
|
||||||
|
{
|
||||||
|
META_CONPRINTF("String is %s\n", argStack[0]);
|
||||||
|
g_SHPtr->SetRes(MRES_IGNORED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
call = g_pBinTools->CreateVCall(info->offset, 0, 0, NULL, NULL, 0);
|
//META_CONPRINTF("Entity %i\n", gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef((CBaseEntity *)g_SHPtr->GetIfacePtr())));
|
||||||
|
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||||
|
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||||
|
ret = (void *)false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
|
|
||||||
unsigned char *vptr = vstk;
|
|
||||||
|
|
||||||
*(void **)vptr = iface;
|
|
||||||
vptr += sizeof(void *);
|
|
||||||
|
|
||||||
size_t offset = STACK_OFFSET;
|
|
||||||
|
|
||||||
if(info->paramcount > 0)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < info->paramcount; i++)
|
|
||||||
{
|
|
||||||
switch(info->params[i].type)
|
|
||||||
{
|
|
||||||
VSTK_PARAM_SWITCH(int, HookParamType_Int);
|
|
||||||
VSTK_PARAM_SWITCH(bool, HookParamType_Bool);
|
|
||||||
VSTK_PARAM_SWITCH(float, HookParamType_Float);
|
|
||||||
VSTK_PARAM_SWITCH(string_t, HookParamType_String);
|
|
||||||
VSTK_PARAM_SWITCH(string_t *, HookParamType_StringPtr);
|
|
||||||
VSTK_PARAM_SWITCH(char *, HookParamType_CharPtr);
|
|
||||||
VSTK_PARAM_SWITCH(Vector *, HookParamType_VectorPtr);
|
|
||||||
VSTK_PARAM_SWITCH(CBaseEntity *, HookParamType_CBaseEntity);
|
|
||||||
VSTK_PARAM_SWITCH(edict_t *, HookParamType_Edict);
|
|
||||||
default:
|
|
||||||
*(void **)vptr = *(void **)(stack+offset);
|
|
||||||
if(i + 1 != info->paramcount)
|
|
||||||
{
|
|
||||||
vptr += sizeof(void *);
|
|
||||||
}
|
|
||||||
offset += sizeof(void *);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
call->Execute(vstk, NULL);
|
|
||||||
call->Destroy();
|
|
||||||
|
|
||||||
free(vstk);
|
|
||||||
|
|
||||||
if(paramInfo)
|
|
||||||
free(paramInfo);
|
|
||||||
}
|
}
|
||||||
template<class T>
|
#endif
|
||||||
T CallFunction(DHooksCallback<T> *info, unsigned long stack, void *iface)
|
|
||||||
{
|
|
||||||
PassInfo *paramInfo = NULL;
|
|
||||||
ICallWrapper *call;
|
|
||||||
size_t size = 0;
|
|
||||||
|
|
||||||
PassInfo returnInfo;
|
|
||||||
returnInfo.flags = PASSFLAG_BYVAL;
|
|
||||||
returnInfo.size = sizeof(T);
|
|
||||||
returnInfo.type = PassType_Basic;
|
|
||||||
|
|
||||||
if(info->paramcount > 0)
|
|
||||||
{
|
|
||||||
paramInfo = (PassInfo *)malloc(sizeof(PassInfo) * info->paramcount);
|
|
||||||
for(int i = 0; i < info->paramcount; i++)
|
|
||||||
{
|
|
||||||
switch(info->params[i].type)
|
|
||||||
{
|
|
||||||
PARAMINFO_SWITCH_CASE(int, HookParamType_Int ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(bool, HookParamType_Bool ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(float, HookParamType_Float ,PassType_Float);
|
|
||||||
PARAMINFO_SWITCH_CASE(string_t, HookParamType_String ,PassType_Object);
|
|
||||||
PARAMINFO_SWITCH_CASE(string_t *, HookParamType_StringPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(char *, HookParamType_CharPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(Vector *, HookParamType_VectorPtr ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(CBaseEntity *, HookParamType_CBaseEntity ,PassType_Basic);
|
|
||||||
PARAMINFO_SWITCH_CASE(edict_t *, HookParamType_Edict ,PassType_Basic);
|
|
||||||
default:
|
|
||||||
paramInfo[i].flags = info->params[i].flag;
|
|
||||||
paramInfo[i].size = sizeof(void *);
|
|
||||||
paramInfo[i].type = PassType_Basic;
|
|
||||||
size += sizeof(void *);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
call = g_pBinTools->CreateVCall(info->offset, 0, 0, &returnInfo, paramInfo, info->paramcount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
call = g_pBinTools->CreateVCall(info->offset, 0, 0, &returnInfo, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
|
|
||||||
unsigned char *vptr = vstk;
|
|
||||||
|
|
||||||
*(void **)vptr = iface;
|
|
||||||
vptr += sizeof(void *);
|
|
||||||
|
|
||||||
size_t offset = STACK_OFFSET;
|
|
||||||
|
|
||||||
if(info->paramcount > 0)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < info->paramcount; i++)
|
|
||||||
{
|
|
||||||
switch(info->params[i].type)
|
|
||||||
{
|
|
||||||
VSTK_PARAM_SWITCH(int, HookParamType_Int);
|
|
||||||
VSTK_PARAM_SWITCH(bool, HookParamType_Bool);
|
|
||||||
VSTK_PARAM_SWITCH(float, HookParamType_Float);
|
|
||||||
VSTK_PARAM_SWITCH(string_t, HookParamType_String);
|
|
||||||
VSTK_PARAM_SWITCH(string_t *, HookParamType_StringPtr);
|
|
||||||
VSTK_PARAM_SWITCH(char *, HookParamType_CharPtr);
|
|
||||||
VSTK_PARAM_SWITCH(Vector *, HookParamType_VectorPtr);
|
|
||||||
VSTK_PARAM_SWITCH(CBaseEntity *, HookParamType_CBaseEntity);
|
|
||||||
VSTK_PARAM_SWITCH(edict_t *, HookParamType_Edict);
|
|
||||||
default:
|
|
||||||
*(void **)vptr = *(void **)(stack+offset);
|
|
||||||
if(i + 1 != info->paramcount)
|
|
||||||
{
|
|
||||||
vptr += sizeof(void *);
|
|
||||||
}
|
|
||||||
offset += sizeof(void *);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
T ret;
|
|
||||||
call->Execute(vstk, &ret);
|
|
||||||
call->Destroy();
|
|
||||||
|
|
||||||
free(vstk);
|
|
||||||
|
|
||||||
if(paramInfo)
|
|
||||||
free(paramInfo);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
void DHooksCallback<void>::Call()
|
|
||||||
{
|
|
||||||
GET_STACK;
|
|
||||||
META_CONPRINTF("String %s\n", *(char **)(stack+STACK_OFFSET));
|
|
||||||
strcpy(*(char **)(stack+STACK_OFFSET), "models/player/t_phoenix.mdl");
|
|
||||||
|
|
||||||
SH_GLOB_SHPTR->DoRecall();
|
|
||||||
CallFunction_Void(this, stack, g_SHPtr->GetIfacePtr());
|
|
||||||
RETURN_META(MRES_IGNORED);
|
|
||||||
}
|
|
||||||
template <>
|
|
||||||
bool DHooksCallback<bool>::Call()
|
|
||||||
{
|
|
||||||
GET_STACK;
|
|
||||||
META_CONPRINTF("Entity %i\n", gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(*(CBaseEntity **)(stack+STACK_OFFSET))));
|
|
||||||
/*__asm
|
|
||||||
{
|
|
||||||
mov ebp, stack
|
|
||||||
};*/
|
|
||||||
META_RES result = MRES_IGNORED;
|
|
||||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
||||||
/*do
|
|
||||||
{
|
|
||||||
SH_GLOB_SHPTR->DoRecall();
|
|
||||||
if ((result) >= MRES_OVERRIDE)
|
|
||||||
{
|
|
||||||
void *pOverride = g_SHPtr->GetOverrideRetPtr();
|
|
||||||
pOverride = (void *)false;
|
|
||||||
}
|
|
||||||
if(result != MRES_SUPERCEDE)
|
|
||||||
{
|
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, CallFunction<bool>(this, stack, g_SHPtr->GetIfacePtr()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, true);
|
|
||||||
}
|
|
||||||
} while (0);*/
|
|
||||||
}
|
|
||||||
|
215
vhook.h
215
vhook.h
@ -3,8 +3,18 @@
|
|||||||
|
|
||||||
#include "extension.h"
|
#include "extension.h"
|
||||||
#include <sourcehook.h>
|
#include <sourcehook.h>
|
||||||
|
#include <macro-assembler-x86.h>
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
#define MAX_PARAMS 10
|
|
||||||
enum HookParamType
|
enum HookParamType
|
||||||
{
|
{
|
||||||
HookParamType_Unknown,
|
HookParamType_Unknown,
|
||||||
@ -19,6 +29,7 @@ enum HookParamType
|
|||||||
HookParamType_ObjectPtr,
|
HookParamType_ObjectPtr,
|
||||||
HookParamType_Edict
|
HookParamType_Edict
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ReturnType
|
enum ReturnType
|
||||||
{
|
{
|
||||||
ReturnType_Unknown,
|
ReturnType_Unknown,
|
||||||
@ -35,52 +46,216 @@ enum ReturnType
|
|||||||
ReturnType_Edict
|
ReturnType_Edict
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParamInfo
|
enum ThisPointerType
|
||||||
|
{
|
||||||
|
ThisPointer_Ignore,
|
||||||
|
ThisPointer_CBaseEntity,
|
||||||
|
ThisPointer_Address
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HookType
|
||||||
|
{
|
||||||
|
HookType_Entity,
|
||||||
|
HookType_GameRules,
|
||||||
|
HookType_Raw
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParamInfo
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
HookParamType type;
|
HookParamType type;
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned int flag;
|
unsigned int flag;
|
||||||
|
SourceHook::PassInfo::PassType pass_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HookReturnStruct
|
||||||
|
{
|
||||||
|
ReturnType type;
|
||||||
|
bool isChanged;
|
||||||
|
void *orgResult;
|
||||||
|
void *newResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DHooksInfo
|
class DHooksInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int paramcount;
|
CUtlVector<ParamInfo> params;
|
||||||
ParamInfo params[MAX_PARAMS];
|
|
||||||
int offset;
|
int offset;
|
||||||
|
unsigned int returnFlag;
|
||||||
|
ReturnType returnType;
|
||||||
|
bool post;
|
||||||
|
IPluginFunction *plugin_callback;
|
||||||
|
int entity;
|
||||||
|
ThisPointerType thisType;
|
||||||
|
HookType hookType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo
|
class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;};
|
virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;};
|
||||||
virtual void DeleteThis(){delete this;};
|
virtual void DeleteThis()
|
||||||
virtual T Call();
|
{
|
||||||
|
*(void ***)this = this->oldvtable;
|
||||||
|
g_pSM->GetScriptingEngine()->FreePageMemory(this->newvtable[2]);
|
||||||
|
delete this->newvtable;
|
||||||
|
delete this;
|
||||||
|
};
|
||||||
|
virtual void Call() {};
|
||||||
|
public:
|
||||||
|
void **newvtable;
|
||||||
|
void **oldvtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef __linux__
|
||||||
|
void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep);
|
||||||
|
//float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep);
|
||||||
|
#else
|
||||||
|
void *Callback(DHooksCallback *dg, void **stack);
|
||||||
|
float Callback_float(DHooksCallback *dg, void **stack);
|
||||||
|
#endif
|
||||||
|
bool SetupHookManager(ISmmAPI *ismm);
|
||||||
|
void CleanupHooks(IPluginContext *pContext);
|
||||||
|
size_t GetParamTypeSize(HookParamType type);
|
||||||
|
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
static void *GenerateThunk(ReturnType type)
|
||||||
|
{
|
||||||
|
MacroAssemblerX86 masm;
|
||||||
|
|
||||||
|
masm.push(ebp);
|
||||||
|
masm.movl(ebp, esp);
|
||||||
|
masm.lea(eax, Operand(ebp, 12));
|
||||||
|
masm.push(eax);
|
||||||
|
masm.push(Operand(ebp, 8));
|
||||||
|
if(type == ReturnType_Float)
|
||||||
|
masm.call(ExternalAddress((void *)Callback_float));
|
||||||
|
else
|
||||||
|
masm.call(ExternalAddress((void *)Callback));
|
||||||
|
masm.addl(esp, 8);
|
||||||
|
masm.pop(ebp);
|
||||||
|
masm.ret();
|
||||||
|
|
||||||
|
void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length());
|
||||||
|
masm.emitToExecutableMemory(base);
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void *GenerateThunk(ReturnType type)
|
||||||
|
{
|
||||||
|
MacroAssemblerX86 masm;
|
||||||
|
|
||||||
|
masm.push(ebp);
|
||||||
|
masm.movl(ebp, esp);
|
||||||
|
masm.subl(esp, 4);
|
||||||
|
masm.push(esp);
|
||||||
|
masm.lea(eax, Operand(ebp, 8));
|
||||||
|
masm.push(eax);
|
||||||
|
masm.push(ecx);
|
||||||
|
//if(type == ReturnType_Float)
|
||||||
|
// masm.call(ExternalAddress(Callback_float));
|
||||||
|
//else
|
||||||
|
masm.call(ExternalAddress(Callback));
|
||||||
|
masm.addl(esp, 12);
|
||||||
|
masm.pop(ecx); // grab arg size
|
||||||
|
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
|
||||||
|
|
||||||
|
static DHooksCallback *MakeHandler(ReturnType type)
|
||||||
|
{
|
||||||
|
DHooksCallback *dg = new DHooksCallback();
|
||||||
|
dg->returnType = type;
|
||||||
|
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(type);
|
||||||
|
*(void ***)dg = dg->newvtable;
|
||||||
|
return dg;
|
||||||
|
}
|
||||||
|
|
||||||
|
class HookParamsStruct
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HookParamsStruct()
|
||||||
|
{
|
||||||
|
this->orgParams = NULL;
|
||||||
|
this->newParams = NULL;
|
||||||
|
this->dg = NULL;
|
||||||
|
}
|
||||||
|
~HookParamsStruct()
|
||||||
|
{
|
||||||
|
if(this->orgParams != NULL)
|
||||||
|
{
|
||||||
|
delete this->orgParams;
|
||||||
|
}
|
||||||
|
if(this->newParams != NULL)
|
||||||
|
{
|
||||||
|
delete this->newParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
//CUtlVector<int> cleanup;
|
||||||
|
void **orgParams;
|
||||||
|
void **newParams;
|
||||||
|
DHooksCallback *dg;
|
||||||
|
};
|
||||||
|
|
||||||
|
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->thisType = thisType;
|
||||||
|
this->offset = offset;
|
||||||
|
this->callback = callback;
|
||||||
|
};
|
||||||
|
~HookSetup(){};
|
||||||
|
public:
|
||||||
|
unsigned int returnFlag;
|
||||||
|
ReturnType returnType;
|
||||||
|
HookType hookType;
|
||||||
|
ThisPointerType thisType;
|
||||||
|
CUtlVector<ParamInfo> params;
|
||||||
|
int offset;
|
||||||
|
IPluginFunction *callback;
|
||||||
|
};
|
||||||
|
|
||||||
class DHooksManager
|
class DHooksManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DHooksManager()
|
DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, bool post);
|
||||||
{
|
|
||||||
this->callback_bool = NULL;
|
|
||||||
this->callback_void = NULL;
|
|
||||||
this->hookid = 0;
|
|
||||||
};
|
|
||||||
~DHooksManager()
|
~DHooksManager()
|
||||||
{
|
{
|
||||||
if(this->hookid != 0)
|
if(this->hookid)
|
||||||
{
|
{
|
||||||
SH_REMOVE_HOOK_ID(this->hookid);
|
g_SHPtr->RemoveHookByID(this->hookid);
|
||||||
|
if(this->remove_callback)
|
||||||
|
{
|
||||||
|
this->remove_callback->PushCell(this->hookid);
|
||||||
|
this->remove_callback->Execute(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DHooksCallback<bool> *callback_bool;
|
public:
|
||||||
DHooksCallback<void> *callback_void;
|
|
||||||
int hookid;
|
int hookid;
|
||||||
unsigned int returnFlag;
|
DHooksCallback *callback;
|
||||||
|
IPluginFunction *remove_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SetupHookManager(ISmmAPI *ismm);
|
|
||||||
extern IBinTools *g_pBinTools;
|
extern IBinTools *g_pBinTools;
|
||||||
|
extern HandleType_t g_HookParamsHandle;
|
||||||
|
extern HandleType_t g_HookReturnHandle;
|
||||||
#endif
|
#endif
|
@ -1,32 +0,0 @@
|
|||||||
#define PARAMINFO_SWITCH_CASE(paramType, enumType, passType) \
|
|
||||||
case enumType: \
|
|
||||||
paramInfo[i].flags = info->params[i].flag; \
|
|
||||||
paramInfo[i].size = sizeof(paramType); \
|
|
||||||
paramInfo[i].type = passType; \
|
|
||||||
size += sizeof(paramType); \
|
|
||||||
break;
|
|
||||||
|
|
||||||
#define VSTK_PARAM_SWITCH(paramType, enumType) \
|
|
||||||
case enumType: \
|
|
||||||
*(paramType *)vptr = *(paramType *)(stack+offset); \
|
|
||||||
if(i + 1 != info->paramcount) \
|
|
||||||
{ \
|
|
||||||
vptr += sizeof(paramType); \
|
|
||||||
} \
|
|
||||||
offset += sizeof(paramType); \
|
|
||||||
break;
|
|
||||||
#ifndef __linux__
|
|
||||||
|
|
||||||
#define STACK_OFFSET 8
|
|
||||||
#define GET_STACK \
|
|
||||||
unsigned long stack; \
|
|
||||||
__asm \
|
|
||||||
{ \
|
|
||||||
mov stack, ebp \
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#define STACK_OFFSET 4
|
|
||||||
#define GET_STACK \
|
|
||||||
unsigned long stack = 0; \
|
|
||||||
asm ("movl %%esp, %0;" : "=r" (stack));
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user