Add more natives, Fix using deprecated functions, Add support for float returns, Fix more callback return stuff.

This commit is contained in:
Dr!fter 2013-08-21 22:18:52 -04:00
parent 07f7869d10
commit 6a47b6f1ef
8 changed files with 438 additions and 56 deletions

View File

@ -11,12 +11,12 @@ ISDKHooks *g_pSDKHooks;
ISDKTools *g_pSDKTools; ISDKTools *g_pSDKTools;
DHooksEntityListener *g_pEntityListener = NULL; DHooksEntityListener *g_pEntityListener = NULL;
bool g_bAllowGamerules = true;
HandleType_t g_HookSetupHandle = 0; HandleType_t g_HookSetupHandle = 0;
HandleType_t g_HookParamsHandle = 0; HandleType_t g_HookParamsHandle = 0;
HandleType_t g_HookReturnHandle = 0; HandleType_t g_HookReturnHandle = 0;
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late) bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
{ {
HandleError err; HandleError err;
@ -47,6 +47,10 @@ bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
plsys->AddPluginsListener(this); plsys->AddPluginsListener(this);
sharesys->AddNatives(myself, g_Natives); sharesys->AddNatives(myself, g_Natives);
g_pEntityListener = new DHooksEntityListener();
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, g_pEntityListener, &DHooksEntityListener::LevelShutdown, false);
return true; return true;
} }
@ -69,18 +73,9 @@ void DHooks::OnHandleDestroy(HandleType_t type, void *object)
void DHooks::SDK_OnAllLoaded() void DHooks::SDK_OnAllLoaded()
{ {
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools); SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
if(g_pSDKTools->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(BINTOOLS, g_pBinTools);
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks); SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
g_pEntityListener = new DHooksEntityListener();
g_pSDKHooks->AddEntityListener(g_pEntityListener); g_pSDKHooks->AddEntityListener(g_pEntityListener);
} }
@ -91,6 +86,7 @@ void DHooks::SDK_OnUnload()
{ {
g_pEntityListener->CleanupListeners(NULL); g_pEntityListener->CleanupListeners(NULL);
g_pSDKHooks->RemoveEntityListener(g_pEntityListener); g_pSDKHooks->RemoveEntityListener(g_pEntityListener);
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, g_pEntityListener, &DHooksEntityListener::LevelShutdown, false);
delete g_pEntityListener; delete g_pEntityListener;
} }
plsys->RemovePluginsListener(this); plsys->RemovePluginsListener(this);

View File

@ -51,9 +51,9 @@
class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch
{ {
public: public:
void OnHandleDestroy(HandleType_t type, void *object); virtual void OnHandleDestroy(HandleType_t type, void *object);
public: //IPluginsListener public: //IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); virtual void OnPluginUnloaded(IPlugin *plugin);
public: public:
/** /**
* @brief This is called after the initial loading sequence has been processed. * @brief This is called after the initial loading sequence has been processed.

View File

@ -5,11 +5,24 @@ using namespace SourceHook;
CUtlVector<EntityListener> g_EntityListeners; CUtlVector<EntityListener> g_EntityListeners;
void DHooksEntityListener::LevelShutdown()
{
for(int i = g_pHooks.Count() -1; i >= 0; i--)
{
DHooksManager *manager = g_pHooks.Element(i);
if(manager->callback->hookType == HookType_GameRules)
{
delete manager;
g_pHooks.Remove(i);
}
}
}
void DHooksEntityListener::CleanupListeners(IPluginContext *pContext) void DHooksEntityListener::CleanupListeners(IPluginContext *pContext)
{ {
for(int i = g_EntityListeners.Count() -1; i >= 0; i--) for(int i = g_EntityListeners.Count() -1; i >= 0; i--)
{ {
if(pContext == NULL || pContext == g_EntityListeners.Element(i).callback->GetParentContext()) if(pContext == NULL || pContext == g_EntityListeners.Element(i).callback->GetParentRuntime()->GetDefaultContext())
{ {
g_EntityListeners.Remove(i); g_EntityListeners.Remove(i);
} }

View File

@ -7,9 +7,10 @@
class DHooksEntityListener : public ISMEntityListener class DHooksEntityListener : public ISMEntityListener
{ {
public: public:
void OnEntityCreated(CBaseEntity *pEntity, const char *classname); virtual void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
void OnEntityDestroyed(CBaseEntity *pEntity); virtual void OnEntityDestroyed(CBaseEntity *pEntity);
void CleanupListeners(IPluginContext *func); void CleanupListeners(IPluginContext *func);
virtual void LevelShutdown();
}; };
enum ListenType enum ListenType

View File

@ -36,7 +36,7 @@ cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params)
return hndl; return hndl;
} }
//native bool:DHookAddParam(Handle:setup, HookParamType:type); //native bool:DHookAddParam(Handle:setup, HookParamType:type); OLD
//native bool:DHookAddParam(Handle:setup, HookParamType:type, size=-1, flag=-1); //native bool:DHookAddParam(Handle:setup, HookParamType:type, size=-1, flag=-1);
cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params) cell_t Native_AddParam(IPluginContext *pContext, const cell_t *params)
{ {
@ -121,8 +121,124 @@ cell_t Native_HookEntity(IPluginContext *pContext, const cell_t *params)
return manager->hookid; return manager->hookid;
} }
/*cell_t Native_HookGamerules(IPluginContext *pContext, const cell_t *params); // native DHookGamerules(Handle:setup, bool:post, DHookRemovalCB:removalcb);
cell_t Native_RemoveHookID(IPluginContext *pContext, const cell_t *params);*/ cell_t Native_HookGamerules(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_GameRules)
{
return pContext->ThrowNativeError("Hook is not a gamerules hook");
}
bool post = params[2] != 0;
for(int i = g_pHooks.Count() -1; i >= 0; i--)
{
DHooksManager *manager = g_pHooks.Element(i);
if(manager->callback->hookType == HookType_GameRules && manager->callback->offset == setup->offset && manager->callback->post == post && manager->remove_callback == pContext->GetFunctionById(params[3]) && manager->callback->plugin_callback == setup->callback)
{
return manager->hookid;
}
}
void *rules = g_pSDKTools->GetGameRules();
if(!rules)
{
return pContext->ThrowNativeError("Could not get game rules pointer");
}
DHooksManager *manager = new DHooksManager(setup, rules, pContext->GetFunctionById(params[3]), post);
if(!manager->hookid)
{
delete manager;
return 0;
}
g_pHooks.AddToTail(manager);
return manager->hookid;
}
// DHookRaw(Handle:setup, bool:post, Address:addr, DHookRemovalCB:removalcb);
cell_t Native_HookRaw(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_Raw)
{
return pContext->ThrowNativeError("Hook is not a gamerules hook");
}
bool post = params[2] != 0;
for(int i = g_pHooks.Count() -1; i >= 0; i--)
{
DHooksManager *manager = g_pHooks.Element(i);
if(manager->callback->hookType == HookType_Raw && manager->callback->offset == setup->offset && manager->callback->post == post && manager->remove_callback == pContext->GetFunctionById(params[3]) && manager->callback->plugin_callback == setup->callback)
{
return manager->hookid;
}
}
void *iface = (void *)(params[3]);
if(!iface)
{
return pContext->ThrowNativeError("Invalid address passed");
}
DHooksManager *manager = new DHooksManager(setup, iface, pContext->GetFunctionById(params[3]), post);
if(!manager->hookid)
{
delete manager;
return 0;
}
g_pHooks.AddToTail(manager);
return manager->hookid;
}
// native bool:DHookRemoveHookID(hookid);
cell_t Native_RemoveHookID(IPluginContext *pContext, const cell_t *params)
{
for(int i = g_pHooks.Count() -1; i >= 0; i--)
{
DHooksManager *manager = g_pHooks.Element(i);
if(manager->hookid == params[1] && manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext() == pContext)
{
delete manager;
g_pHooks.Remove(i);
return 1;
}
}
return 0;
}
// native any:DHookGetParam(Handle:hParams, num);
cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params) cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params)
{ {
if(params[1] == BAD_HANDLE) if(params[1] == BAD_HANDLE)
@ -172,6 +288,71 @@ cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
// native DHookSetParam(Handle:hParams, param, any:value)
cell_t Native_SetParam(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] <= 0 || params[2] > paramStruct->dg->params.Count())
{
return pContext->ThrowNativeError("Invalid param number %i max params is %i", params[2], paramStruct->dg->params.Count());
}
int index = params[2] - 1;
switch(paramStruct->dg->params.Element(index).type)
{
case HookParamType_Int:
paramStruct->newParams[index] = (void *)params[3];
break;
case HookParamType_Bool:
paramStruct->newParams[index] = (void *)(params[3] ? 1 : 0);
break;
case HookParamType_CBaseEntity:
{
CBaseEntity *pEnt = UTIL_GetCBaseEntity(params[2]);
if(!pEnt)
{
return pContext->ThrowNativeError("Invalid entity index passed for param value");
}
paramStruct->newParams[index] = pEnt;
break;
}
case HookParamType_Edict:
{
edict_t *pEdict = gamehelpers->EdictOfIndex(params[2]);
if(!pEdict || pEdict->IsFree())
{
pContext->ThrowNativeError("Invalid entity index passed for param value");
}
paramStruct->newParams[index] = pEdict;
break;
}
case HookParamType_Float:
paramStruct->newParams[index] = new float;
*(float *)paramStruct->newParams[index] = sp_ctof(params[3]);
break;
default:
return pContext->ThrowNativeError("Invalid param type (%i) to set", paramStruct->dg->params.Element(index).type);
}
paramStruct->isChanged[index] = true;
return 1;
}
// native any:DHookGetReturn(Handle:hReturn);
cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params) cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params)
{ {
if(params[1] == BAD_HANDLE) if(params[1] == BAD_HANDLE)
@ -205,6 +386,7 @@ cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params)
} }
return 1; return 1;
} }
// native DHookSetReturn(Handle:hReturn, any:value)
cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params) cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params)
{ {
if(params[1] == BAD_HANDLE) if(params[1] == BAD_HANDLE)
@ -258,11 +440,12 @@ cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params)
returnStruct->isChanged = true; returnStruct->isChanged = true;
return 1; 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_GetParamVector(IPluginContext *pContext, const cell_t *params);
cell_t Native_GetReturnVector(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_SetReturnVector(IPluginContext *pContext, const cell_t *params);
cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params);*/ cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params);*/
// native DHookGetParamString(Handle:hParams, num, String:buffer[], size)
cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params) cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params)
{ {
if(params[1] == BAD_HANDLE) if(params[1] == BAD_HANDLE)
@ -327,7 +510,7 @@ cell_t Native_SetParamString(IPluginContext *pContext, const cell_t *params)
if(paramStruct->dg->params.Element(index).type == HookParamType_CharPtr) if(paramStruct->dg->params.Element(index).type == HookParamType_CharPtr)
{ {
if(paramStruct->newParams[index] != NULL) if((char *)paramStruct->newParams[index] != NULL && paramStruct->isChanged[index])
delete (char *)paramStruct->newParams[index]; delete (char *)paramStruct->newParams[index];
paramStruct->newParams[index] = new char[strlen(value)+1]; paramStruct->newParams[index] = new char[strlen(value)+1];
@ -342,14 +525,14 @@ sp_nativeinfo_t g_Natives[] =
{"DHookCreate", Native_CreateHook}, {"DHookCreate", Native_CreateHook},
{"DHookAddParam", Native_AddParam}, {"DHookAddParam", Native_AddParam},
{"DHookEntity", Native_HookEntity}, {"DHookEntity", Native_HookEntity},
/*{"DHookGamerules", Native_HookGamerules}, {"DHookGamerules", Native_HookGamerules},
{"DHookRaw", Native_HookRaw}, {"DHookRaw", Native_HookRaw},
{"DHookRemoveHookID", Native_RemoveHookID},*/ {"DHookRemoveHookID", Native_RemoveHookID},
{"DHookGetParam", Native_GetParam}, {"DHookGetParam", Native_GetParam},
{"DHookGetReturn", Native_GetReturn}, {"DHookGetReturn", Native_GetReturn},
{"DHookSetReturn", Native_SetReturn}, {"DHookSetReturn", Native_SetReturn},
/*{"DHookSetParam", Native_SetParam}, {"DHookSetParam", Native_SetParam},
{"DHookGetParamVector", Native_GetParamVector}, /*{"DHookGetParamVector", Native_GetParamVector},
{"DHookGetReturnVector", Native_GetReturnVector}, {"DHookGetReturnVector", Native_GetReturnVector},
{"DHookSetReturnVector", Native_SetReturnVector}, {"DHookSetReturnVector", Native_SetReturnVector},
{"DHookSetParamVector", Native_SetParamVector},*/ {"DHookSetParamVector", Native_SetParamVector},*/

View File

@ -3,8 +3,7 @@
#include "extension.h" #include "extension.h"
#include "vhook.h" #include "vhook.h"
extern ISDKTools *g_pSDKTools;
extern bool g_bAllowGamerules;
extern HandleType_t g_HookSetupHandle; extern HandleType_t g_HookSetupHandle;
extern HandleType_t g_HookParamsHandle; extern HandleType_t g_HookParamsHandle;
extern HandleType_t g_HookReturnHandle; extern HandleType_t g_HookReturnHandle;

229
vhook.cpp
View File

@ -19,6 +19,7 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem
this->callback->post = post; this->callback->post = post;
this->callback->hookType = setup->hookType; this->callback->hookType = setup->hookType;
this->callback->params = setup->params; this->callback->params = setup->params;
this->addr = 0;
if(this->callback->hookType == HookType_Entity) if(this->callback->hookType == HookType_Entity)
{ {
@ -26,6 +27,10 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem
} }
else else
{ {
if(this->callback->hookType == HookType_Raw)
{
this->addr = (intptr_t)iface;
}
this->callback->entity = -1; this->callback->entity = -1;
} }
@ -40,10 +45,14 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem
{ {
protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, NULL, NULL, NULL, NULL); protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, NULL, NULL, NULL, NULL);
} }
else else if(this->callback->returnType != ReturnType_Float)
{ {
protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Basic, setup->returnFlag, NULL, NULL, NULL, NULL); protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Basic, setup->returnFlag, NULL, NULL, NULL, NULL);
} }
else
{
protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Float, setup->returnFlag, NULL, NULL, NULL, NULL);
}
HookManagerPubFunc hook = g_pHookManager->MakeHookMan(protoInfo, 0, this->callback->offset); 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); this->hookid = g_SHPtr->AddHook(g_PLID,ISourceHook::Hook_Normal, iface, 0, hook, this->callback, this->callback->post);
@ -55,7 +64,7 @@ void CleanupHooks(IPluginContext *pContext)
{ {
DHooksManager *manager = g_pHooks.Element(i); DHooksManager *manager = g_pHooks.Element(i);
if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentContext()) if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext())
{ {
delete manager; delete manager;
g_pHooks.Remove(i); g_pHooks.Remove(i);
@ -96,18 +105,18 @@ size_t GetStackArgsSize(DHooksCallback *dg)
} }
HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t argStackSize) HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t argStackSize)
{ {
HookParamsStruct *res = new HookParamsStruct(); HookParamsStruct *params = new HookParamsStruct();
res->dg = dg; params->dg = dg;
res->orgParams = (void **)malloc(argStackSize); params->orgParams = (void **)malloc(argStackSize);
res->newParams = (void **)malloc(argStackSize); params->newParams = (void **)malloc(dg->params.Count() * sizeof(void *));
res->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool)); params->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool));
memcpy(res->orgParams, argStack, argStackSize); memcpy(params->orgParams, argStack, argStackSize);
for(int i = 0; i < dg->params.Count(); i++) for(int i = 0; i < dg->params.Count(); i++)
{ {
res->newParams[i] = NULL; params->newParams[i] = NULL;
res->isChanged[i] = false; params->isChanged[i] = false;
} }
return res; return params;
} }
HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result) HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result)
{ {
@ -138,7 +147,22 @@ HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result)
} }
else else
{ {
res->orgResult = NULL; switch(dg->returnType)
{
//ReturnType_String,
//ReturnType_Vector,
case ReturnType_Int:
*(int *)res->orgResult = 0;
case ReturnType_Bool:
*(bool *)res->orgResult = false;
break;
case ReturnType_Float:
*(float *)res->orgResult = 0.0;
break;
default:
*(void **)res->orgResult = NULL;
break;
}
} }
return res; return res;
@ -186,7 +210,7 @@ void *Callback(DHooksCallback *dg, void **argStack)
delete returnStruct; delete returnStruct;
} }
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
return 0; return NULL;
} }
dg->plugin_callback->PushCell(rHndl); dg->plugin_callback->PushCell(rHndl);
} }
@ -213,11 +237,13 @@ void *Callback(DHooksCallback *dg, void **argStack)
delete paramStruct; delete paramStruct;
} }
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
return 0; return NULL;
} }
dg->plugin_callback->PushCell(pHndl); dg->plugin_callback->PushCell(pHndl);
} }
cell_t result = (cell_t)MRES_Ignored; cell_t result = (cell_t)MRES_Ignored;
META_RES mres = MRES_IGNORED;
dg->plugin_callback->Execute(&result); dg->plugin_callback->Execute(&result);
void *ret = g_SHPtr->GetOverrideRetPtr(); void *ret = g_SHPtr->GetOverrideRetPtr();
@ -227,6 +253,7 @@ void *Callback(DHooksCallback *dg, void **argStack)
case MRES_ChangedHandled: case MRES_ChangedHandled:
g_SHPtr->DoRecall(); g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE); g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
ret = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); ret = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr());
break; break;
case MRES_ChangedOverride: case MRES_ChangedOverride:
@ -239,13 +266,14 @@ void *Callback(DHooksCallback *dg, void **argStack)
else //Throw an error if no override was set else //Throw an error if no override was set
{ {
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); mres = MRES_IGNORED;
smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
break; break;
} }
} }
g_SHPtr->DoRecall(); g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE); g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr());
break; break;
case MRES_Override: case MRES_Override:
@ -254,13 +282,14 @@ void *Callback(DHooksCallback *dg, void **argStack)
if(returnStruct->isChanged) if(returnStruct->isChanged)
{ {
g_SHPtr->SetRes(MRES_OVERRIDE); g_SHPtr->SetRes(MRES_OVERRIDE);
mres = MRES_OVERRIDE;
ret = *(void **)returnStruct->newResult; ret = *(void **)returnStruct->newResult;
} }
else //Throw an error if no override was set else //Throw an error if no override was set
{ {
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); mres = MRES_IGNORED;
smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
} }
} }
break; break;
@ -270,22 +299,24 @@ void *Callback(DHooksCallback *dg, void **argStack)
if(returnStruct->isChanged) if(returnStruct->isChanged)
{ {
g_SHPtr->SetRes(MRES_SUPERCEDE); g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
ret = *(void **)returnStruct->newResult; ret = *(void **)returnStruct->newResult;
} }
else //Throw an error if no override was set else //Throw an error if no override was set
{ {
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); mres = MRES_IGNORED;
smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
} }
} }
break; break;
default: default:
g_SHPtr->SetRes(MRES_IGNORED); g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
break; break;
} }
HandleSecurity sec(dg->plugin_callback->GetParentContext()->GetIdentity(), myself->GetIdentity()); HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
if(returnStruct) if(returnStruct)
{ {
@ -296,9 +327,163 @@ void *Callback(DHooksCallback *dg, void **argStack)
handlesys->FreeHandle(pHndl, &sec); handlesys->FreeHandle(pHndl, &sec);
} }
if(dg->returnType == ReturnType_Void || g_SHPtr->GetStatus() <= MRES_HANDLED) if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
{ {
return NULL; return NULL;
} }
return ret; return ret;
} }
#ifndef __linux__
float Callback_float(DHooksCallback *dg, void **argStack, size_t *argsizep)
#else
void *Callback_float(DHooksCallback *dg, void **argStack)
#endif
{
HookReturnStruct *returnStruct = NULL;
HookParamsStruct *paramStruct = NULL;
Handle_t rHndl;
Handle_t pHndl;
#ifndef __linux__
*argsizep = GetStackArgsSize(dg);
#else
size_t argsize = GetStackArgsSize(dg);
#endif
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
{
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
}
returnStruct = GetReturnStruct(dg, g_SHPtr->GetOrigRet());
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
if(!rHndl)
{
dg->plugin_callback->Cancel();
if(returnStruct)
{
delete returnStruct;
}
g_SHPtr->SetRes(MRES_IGNORED);
return NULL;
}
dg->plugin_callback->PushCell(rHndl);
#ifndef __linux__
if(*argsizep > 0)
{
paramStruct = GetParamStruct(dg, argStack, *argsizep);
#else
if(argsize > 0)
{
paramStruct = GetParamStruct(dg, argStack, argsize);
#endif
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
if(!pHndl)
{
dg->plugin_callback->Cancel();
if(returnStruct)
{
delete returnStruct;
}
if(paramStruct)
{
delete paramStruct;
}
g_SHPtr->SetRes(MRES_IGNORED);
return NULL;
}
dg->plugin_callback->PushCell(pHndl);
}
cell_t result = (cell_t)MRES_Ignored;
META_RES mres = MRES_IGNORED;
dg->plugin_callback->Execute(&result);
void *ret = g_SHPtr->GetOverrideRetPtr();
switch((MRESReturn)result)
{
case MRES_Handled:
case MRES_ChangedHandled:
g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
ret = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr());
break;
case MRES_ChangedOverride:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
*(float *)ret = *(float *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
break;
}
}
g_SHPtr->DoRecall();
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr());
break;
case MRES_Override:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
g_SHPtr->SetRes(MRES_OVERRIDE);
mres = MRES_OVERRIDE;
*(float *)ret = *(float *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
}
}
break;
case MRES_Supercede:
if(dg->returnType != ReturnType_Void)
{
if(returnStruct->isChanged)
{
g_SHPtr->SetRes(MRES_SUPERCEDE);
mres = MRES_SUPERCEDE;
*(float *)ret = *(float *)returnStruct->newResult;
}
else //Throw an error if no override was set
{
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set");
}
}
break;
default:
g_SHPtr->SetRes(MRES_IGNORED);
mres = MRES_IGNORED;
break;
}
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
if(returnStruct)
{
handlesys->FreeHandle(rHndl, &sec);
}
if(paramStruct)
{
handlesys->FreeHandle(pHndl, &sec);
}
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
{
return NULL;
}
return *(float *)ret;
}

17
vhook.h
View File

@ -117,7 +117,7 @@ public:
#ifndef __linux__ #ifndef __linux__
void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep); void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep);
//float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep); float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep);
#else #else
void *Callback(DHooksCallback *dg, void **stack); void *Callback(DHooksCallback *dg, void **stack);
float Callback_float(DHooksCallback *dg, void **stack); float Callback_float(DHooksCallback *dg, void **stack);
@ -137,9 +137,9 @@ static void *GenerateThunk(ReturnType type)
masm.lea(eax, Operand(ebp, 12)); masm.lea(eax, Operand(ebp, 12));
masm.push(eax); masm.push(eax);
masm.push(Operand(ebp, 8)); masm.push(Operand(ebp, 8));
/*if(type == ReturnType_Float) if(type == ReturnType_Float)
masm.call(ExternalAddress((void *)Callback_float)); masm.call(ExternalAddress((void *)Callback_float));
else*/ else
masm.call(ExternalAddress((void *)Callback)); masm.call(ExternalAddress((void *)Callback));
masm.addl(esp, 8); masm.addl(esp, 8);
masm.pop(ebp); masm.pop(ebp);
@ -161,9 +161,9 @@ static void *GenerateThunk(ReturnType type)
masm.lea(eax, Operand(ebp, 8)); masm.lea(eax, Operand(ebp, 8));
masm.push(eax); masm.push(eax);
masm.push(ecx); masm.push(ecx);
//if(type == ReturnType_Float) if(type == ReturnType_Float)
// masm.call(ExternalAddress(Callback_float)); masm.call(ExternalAddress(Callback_float));
//else else
masm.call(ExternalAddress(Callback)); masm.call(ExternalAddress(Callback));
masm.addl(esp, 12); masm.addl(esp, 12);
masm.pop(ecx); // grab arg size masm.pop(ecx); // grab arg size
@ -226,6 +226,10 @@ public:
{ {
delete (char *)this->newParams[i]; delete (char *)this->newParams[i];
} }
else if(dg->params.Element(i).type == HookParamType_Float)
{
delete (float *)this->newParams[i];
}
} }
free(this->newParams); free(this->newParams);
} }
@ -277,6 +281,7 @@ public:
} }
} }
public: public:
intptr_t addr;
int hookid; int hookid;
DHooksCallback *callback; DHooksCallback *callback;
IPluginFunction *remove_callback; IPluginFunction *remove_callback;