Update code add natives and listeners

This commit is contained in:
Dr!fter 2013-08-19 11:07:25 -04:00
parent f9af5e9017
commit 2f38de616e
13 changed files with 914 additions and 324 deletions

View File

@ -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); \

View File

@ -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)
{
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);
CleanupHooks(plugin->GetBaseContext());
if(g_pEntityListener)
{
g_pEntityListener->CleanupListeners(plugin->GetBaseContext());
}
}
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;
}
}

View File

@ -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
View 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
View 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

View File

@ -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" />

View File

@ -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
View 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 **)&paramStruct)) != 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 **)&paramStruct)) != 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
View 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

View File

@ -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

455
vhook.cpp
View File

@ -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)
{
switch(type)
{
paramInfo = (PassInfo *)malloc(sizeof(PassInfo) * info->paramcount);
for(int i = 0; i < info->paramcount; i++)
case HookParamType_Float:
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);
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;
delete returnStruct;
}
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
{
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);
return 0;
}
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);*/
}
#endif

215
vhook.h
View File

@ -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

View File

@ -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