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 ###
 | 
			
		||||
###########################################
 | 
			
		||||
 | 
			
		||||
SMSDK = ../sourcemod-1.5
 | 
			
		||||
SMSDK = ../sourcemod-central
 | 
			
		||||
HL2SDK_ORIG = ../../../hl2sdk
 | 
			
		||||
HL2SDK_OB = ../../../hl2sdk-ob
 | 
			
		||||
HL2SDK_CSS = ../hl2sdk-css
 | 
			
		||||
@ -24,7 +24,7 @@ PROJECT = sample
 | 
			
		||||
#Uncomment for Metamod: Source enabled extension
 | 
			
		||||
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 ###
 | 
			
		||||
@ -109,7 +109,7 @@ else
 | 
			
		||||
	LIB_SUFFIX = .$(LIB_EXT)
 | 
			
		||||
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"
 | 
			
		||||
	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
 | 
			
		||||
	mkdir -p $(BIN_DIR)/sdk
 | 
			
		||||
	mkdir -p $(BIN_DIR)/../sourcemod-central/public/jit/x86
 | 
			
		||||
	if [ "$(USEMETA)" = "true" ]; then \
 | 
			
		||||
		ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \
 | 
			
		||||
		ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								extension.cpp
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								extension.cpp
									
									
									
									
									
								
							@ -1,41 +1,101 @@
 | 
			
		||||
#include "extension.h"
 | 
			
		||||
#include "vhook.h"
 | 
			
		||||
#include "listeners.h"
 | 
			
		||||
#include <macro-assembler-x86.h>
 | 
			
		||||
 | 
			
		||||
DHooks g_Sample;		/**< Global singleton for extension's main interface */
 | 
			
		||||
SMEXT_LINK(&g_Sample);
 | 
			
		||||
DHooks g_DHooksIface;		/**< Global singleton for extension's main interface */
 | 
			
		||||
SMEXT_LINK(&g_DHooksIface);
 | 
			
		||||
 | 
			
		||||
IBinTools *g_pBinTools;
 | 
			
		||||
ISDKHooks *g_pSDKHooks;
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	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, "sdktools.ext", true, true);
 | 
			
		||||
	sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
 | 
			
		||||
 | 
			
		||||
	sharesys->RegisterLibrary(myself, "dhooks");
 | 
			
		||||
	plsys->AddPluginsListener(this);
 | 
			
		||||
	sharesys->AddNatives(myself, g_Natives);
 | 
			
		||||
 | 
			
		||||
	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()
 | 
			
		||||
{
 | 
			
		||||
	SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
 | 
			
		||||
	if(g_pSDKTools == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		smutils->LogError(myself, "SDKTools interface not found. DHookGamerules native disabled.");
 | 
			
		||||
	}
 | 
			
		||||
	else if(g_pSDKTools->GetInterfaceVersion() < 2)
 | 
			
		||||
 | 
			
		||||
	if(g_pSDKTools->GetInterfaceVersion() < 2)
 | 
			
		||||
	{
 | 
			
		||||
		//<psychonic> THIS ISN'T DA LIMBO STICK. LOW IS BAD
 | 
			
		||||
		g_bAllowGamerules = false;
 | 
			
		||||
		smutils->LogError(myself, "SDKTools interface is outdated. DHookGamerules native disabled.");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	if(!SetupHookManager(ismm))
 | 
			
		||||
@ -45,61 +105,12 @@ bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, boo
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
DHooksManager *manager1;
 | 
			
		||||
DHooksManager *manager2;
 | 
			
		||||
 | 
			
		||||
#ifndef __linux__
 | 
			
		||||
#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)
 | 
			
		||||
void DHooks::OnPluginUnloaded(IPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
	int entity = gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(pEntity));
 | 
			
		||||
 | 
			
		||||
	if(entity <= playerhelpers->GetMaxClients() && entity > 0)
 | 
			
		||||
	CleanupHooks(plugin->GetBaseContext());
 | 
			
		||||
	if(g_pEntityListener)
 | 
			
		||||
	{
 | 
			
		||||
		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;
 | 
			
		||||
		g_pEntityListener->CleanupListeners(plugin->GetBaseContext());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								extension.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								extension.h
									
									
									
									
									
								
							@ -48,12 +48,13 @@
 | 
			
		||||
 * 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:
 | 
			
		||||
	void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
 | 
			
		||||
	void OnEntityDestroyed(CBaseEntity *pEntity);
 | 
			
		||||
 | 
			
		||||
	void OnHandleDestroy(HandleType_t type, void *object);
 | 
			
		||||
public: //IPluginsListener
 | 
			
		||||
	void OnPluginUnloaded(IPlugin *plugin);
 | 
			
		||||
public:
 | 
			
		||||
	/**
 | 
			
		||||
	 * @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.
 | 
			
		||||
	 */
 | 
			
		||||
	//virtual void SDK_OnUnload();
 | 
			
		||||
	virtual void SDK_OnUnload();
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @brief This is called once all known extensions have been loaded.
 | 
			
		||||
@ -123,4 +124,5 @@ public:
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
extern SourceHook::IHookManagerAutoGen *g_pHookManager;
 | 
			
		||||
extern sp_nativeinfo_t g_Natives[];
 | 
			
		||||
#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>
 | 
			
		||||
      <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>
 | 
			
		||||
      <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>
 | 
			
		||||
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
 | 
			
		||||
      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
 | 
			
		||||
@ -610,7 +610,7 @@
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <Link>
 | 
			
		||||
      <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>
 | 
			
		||||
      <GenerateDebugInformation>true</GenerateDebugInformation>
 | 
			
		||||
      <SubSystem>Windows</SubSystem>
 | 
			
		||||
@ -882,12 +882,17 @@
 | 
			
		||||
    </Link>
 | 
			
		||||
  </ItemDefinitionGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClCompile Include="..\..\..\sourcemod-central\public\jit\x86\assembler-x86.cpp" />
 | 
			
		||||
    <ClCompile Include="..\extension.cpp" />
 | 
			
		||||
    <ClCompile Include="..\listeners.cpp" />
 | 
			
		||||
    <ClCompile Include="..\natives.cpp" />
 | 
			
		||||
    <ClCompile Include="..\vhook.cpp" />
 | 
			
		||||
    <ClCompile Include="..\sdk\smsdk_ext.cpp" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ClInclude Include="..\extension.h" />
 | 
			
		||||
    <ClInclude Include="..\listeners.h" />
 | 
			
		||||
    <ClInclude Include="..\natives.h" />
 | 
			
		||||
    <ClInclude Include="..\vhook.h" />
 | 
			
		||||
    <ClInclude Include="..\sdk\smsdk_config.h" />
 | 
			
		||||
    <ClInclude Include="..\sdk\smsdk_ext.h" />
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,11 @@
 | 
			
		||||
    </ClCompile>
 | 
			
		||||
    <ClCompile Include="..\vhook.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>
 | 
			
		||||
    <ClInclude Include="..\extension.h">
 | 
			
		||||
@ -23,6 +28,12 @@
 | 
			
		||||
    <ClInclude Include="..\vhook_macros.h">
 | 
			
		||||
      <Filter>Headers</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="..\natives.h">
 | 
			
		||||
      <Filter>Headers</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
    <ClInclude Include="..\listeners.h">
 | 
			
		||||
      <Filter>Headers</Filter>
 | 
			
		||||
    </ClInclude>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Filter Include="Headers">
 | 
			
		||||
@ -31,5 +42,8 @@
 | 
			
		||||
    <Filter Include="sdk">
 | 
			
		||||
      <UniqueIdentifier>{8a0b4570-752f-44d9-b270-ef886743e9ea}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
    <Filter Include="JIT">
 | 
			
		||||
      <UniqueIdentifier>{9ac7d92a-8a9d-4e7c-b108-09d915244278}</UniqueIdentifier>
 | 
			
		||||
    </Filter>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
</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 */
 | 
			
		||||
//#define SMEXT_ENABLE_FORWARDSYS
 | 
			
		||||
//#define SMEXT_ENABLE_HANDLESYS
 | 
			
		||||
#define SMEXT_ENABLE_HANDLESYS
 | 
			
		||||
#define SMEXT_ENABLE_PLAYERHELPERS
 | 
			
		||||
//#define SMEXT_ENABLE_DBMANAGER
 | 
			
		||||
#define SMEXT_ENABLE_GAMECONF
 | 
			
		||||
@ -71,7 +71,7 @@
 | 
			
		||||
//#define SMEXT_ENABLE_LIBSYS
 | 
			
		||||
//#define SMEXT_ENABLE_MENUS
 | 
			
		||||
//#define SMEXT_ENABLE_ADTFACTORY
 | 
			
		||||
//#define SMEXT_ENABLE_PLUGINSYS
 | 
			
		||||
#define SMEXT_ENABLE_PLUGINSYS
 | 
			
		||||
//#define SMEXT_ENABLE_ADMINSYS
 | 
			
		||||
//#define SMEXT_ENABLE_TEXTPARSERS
 | 
			
		||||
//#define SMEXT_ENABLE_USERMSGS
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										453
									
								
								vhook.cpp
									
									
									
									
									
								
							
							
						
						
									
										453
									
								
								vhook.cpp
									
									
									
									
									
								
							@ -1,8 +1,71 @@
 | 
			
		||||
#include "vhook.h"
 | 
			
		||||
#include "vhook_macros.h"
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CallFunction_Void(DHooksCallback<void> *info, unsigned long stack, void *iface)
 | 
			
		||||
size_t GetParamTypeSize(HookParamType type)
 | 
			
		||||
{
 | 
			
		||||
	PassInfo *paramInfo = NULL;
 | 
			
		||||
	ICallWrapper *call;
 | 
			
		||||
	size_t size = 0;
 | 
			
		||||
 | 
			
		||||
	if(info->paramcount > 0)
 | 
			
		||||
	return sizeof(void *);
 | 
			
		||||
}
 | 
			
		||||
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type)
 | 
			
		||||
{
 | 
			
		||||
		paramInfo = (PassInfo *)malloc(sizeof(PassInfo) * info->paramcount);
 | 
			
		||||
		for(int i = 0; i < info->paramcount; i++)
 | 
			
		||||
	switch(type)
 | 
			
		||||
	{
 | 
			
		||||
			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);
 | 
			
		||||
		case HookParamType_Float:
 | 
			
		||||
			return SourceHook::PassInfo::PassType::PassType_Float;
 | 
			
		||||
		default:
 | 
			
		||||
					paramInfo[i].flags = info->params[i].flag;
 | 
			
		||||
					paramInfo[i].size = sizeof(void *);
 | 
			
		||||
					paramInfo[i].type = PassType_Basic;
 | 
			
		||||
					size += sizeof(void *);
 | 
			
		||||
			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)
 | 
			
		||||
		{
 | 
			
		||||
			if(returnStruct)
 | 
			
		||||
			{
 | 
			
		||||
				delete returnStruct;
 | 
			
		||||
			}
 | 
			
		||||
			g_SHPtr->SetRes(MRES_IGNORED);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
		call = g_pBinTools->CreateVCall(info->offset, 0, 0, NULL, paramInfo, info->paramcount);
 | 
			
		||||
	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
 | 
			
		||||
	{
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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>
 | 
			
		||||
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);*/
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										215
									
								
								vhook.h
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								vhook.h
									
									
									
									
									
								
							@ -3,8 +3,18 @@
 | 
			
		||||
 | 
			
		||||
#include "extension.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
 | 
			
		||||
{
 | 
			
		||||
	HookParamType_Unknown,
 | 
			
		||||
@ -19,6 +29,7 @@ enum HookParamType
 | 
			
		||||
	HookParamType_ObjectPtr,
 | 
			
		||||
	HookParamType_Edict
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ReturnType
 | 
			
		||||
{
 | 
			
		||||
	ReturnType_Unknown,
 | 
			
		||||
@ -35,52 +46,216 @@ enum ReturnType
 | 
			
		||||
	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;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	unsigned int flag;
 | 
			
		||||
	SourceHook::PassInfo::PassType pass_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct HookReturnStruct
 | 
			
		||||
{
 | 
			
		||||
	ReturnType type;
 | 
			
		||||
	bool isChanged;
 | 
			
		||||
	void *orgResult;
 | 
			
		||||
	void *newResult;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DHooksInfo
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	int paramcount;
 | 
			
		||||
	ParamInfo params[MAX_PARAMS];
 | 
			
		||||
	CUtlVector<ParamInfo> params;
 | 
			
		||||
	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
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;};
 | 
			
		||||
    virtual void DeleteThis(){delete this;};
 | 
			
		||||
    virtual T Call();
 | 
			
		||||
    virtual void DeleteThis()
 | 
			
		||||
	{
 | 
			
		||||
		*(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
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	DHooksManager()
 | 
			
		||||
	{
 | 
			
		||||
		this->callback_bool = NULL; 
 | 
			
		||||
		this->callback_void = NULL;
 | 
			
		||||
		this->hookid = 0;
 | 
			
		||||
	};
 | 
			
		||||
	DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, bool post);
 | 
			
		||||
	~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;
 | 
			
		||||
	DHooksCallback<void> *callback_void;
 | 
			
		||||
	}
 | 
			
		||||
public:
 | 
			
		||||
	int hookid;
 | 
			
		||||
	unsigned int returnFlag;
 | 
			
		||||
	DHooksCallback *callback;
 | 
			
		||||
	IPluginFunction *remove_callback;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool SetupHookManager(ISmmAPI *ismm);
 | 
			
		||||
extern IBinTools *g_pBinTools;
 | 
			
		||||
extern HandleType_t g_HookParamsHandle;
 | 
			
		||||
extern HandleType_t g_HookReturnHandle;
 | 
			
		||||
#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