From 6a47b6f1efcb9c9e51ebdd4559d9f960fa4d0a0f Mon Sep 17 00:00:00 2001 From: Dr!fter Date: Wed, 21 Aug 2013 22:18:52 -0400 Subject: [PATCH] Add more natives, Fix using deprecated functions, Add support for float returns, Fix more callback return stuff. --- extension.cpp | 18 ++-- extension.h | 4 +- listeners.cpp | 15 +++- listeners.h | 5 +- natives.cpp | 203 +++++++++++++++++++++++++++++++++++++++++--- natives.h | 3 +- vhook.cpp | 229 +++++++++++++++++++++++++++++++++++++++++++++----- vhook.h | 17 ++-- 8 files changed, 438 insertions(+), 56 deletions(-) diff --git a/extension.cpp b/extension.cpp index f3d6a7c..b5c411f 100644 --- a/extension.cpp +++ b/extension.cpp @@ -11,12 +11,12 @@ ISDKHooks *g_pSDKHooks; ISDKTools *g_pSDKTools; DHooksEntityListener *g_pEntityListener = NULL; -bool g_bAllowGamerules = true; - HandleType_t g_HookSetupHandle = 0; HandleType_t g_HookParamsHandle = 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) { HandleError err; @@ -47,6 +47,10 @@ bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late) plsys->AddPluginsListener(this); sharesys->AddNatives(myself, g_Natives); + g_pEntityListener = new DHooksEntityListener(); + + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, g_pEntityListener, &DHooksEntityListener::LevelShutdown, false); + return true; } @@ -69,18 +73,9 @@ void DHooks::OnHandleDestroy(HandleType_t type, void *object) void DHooks::SDK_OnAllLoaded() { SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools); - - if(g_pSDKTools->GetInterfaceVersion() < 2) - { - // 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_pEntityListener = new DHooksEntityListener(); g_pSDKHooks->AddEntityListener(g_pEntityListener); } @@ -91,6 +86,7 @@ void DHooks::SDK_OnUnload() { g_pEntityListener->CleanupListeners(NULL); g_pSDKHooks->RemoveEntityListener(g_pEntityListener); + SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, g_pEntityListener, &DHooksEntityListener::LevelShutdown, false); delete g_pEntityListener; } plsys->RemovePluginsListener(this); diff --git a/extension.h b/extension.h index 4f7936a..fd7f7f0 100644 --- a/extension.h +++ b/extension.h @@ -51,9 +51,9 @@ class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch { public: - void OnHandleDestroy(HandleType_t type, void *object); + virtual void OnHandleDestroy(HandleType_t type, void *object); public: //IPluginsListener - void OnPluginUnloaded(IPlugin *plugin); + virtual void OnPluginUnloaded(IPlugin *plugin); public: /** * @brief This is called after the initial loading sequence has been processed. diff --git a/listeners.cpp b/listeners.cpp index 09ffe67..172c0a9 100644 --- a/listeners.cpp +++ b/listeners.cpp @@ -5,11 +5,24 @@ using namespace SourceHook; CUtlVector 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) { 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); } diff --git a/listeners.h b/listeners.h index 23c3d94..87bc1b0 100644 --- a/listeners.h +++ b/listeners.h @@ -7,9 +7,10 @@ class DHooksEntityListener : public ISMEntityListener { public: - void OnEntityCreated(CBaseEntity *pEntity, const char *classname); - void OnEntityDestroyed(CBaseEntity *pEntity); + virtual void OnEntityCreated(CBaseEntity *pEntity, const char *classname); + virtual void OnEntityDestroyed(CBaseEntity *pEntity); void CleanupListeners(IPluginContext *func); + virtual void LevelShutdown(); }; enum ListenType diff --git a/natives.cpp b/natives.cpp index c634502..d6acb0b 100644 --- a/natives.cpp +++ b/natives.cpp @@ -36,7 +36,7 @@ cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params) 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); 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; } -/*cell_t Native_HookGamerules(IPluginContext *pContext, const cell_t *params); -cell_t Native_RemoveHookID(IPluginContext *pContext, const cell_t *params);*/ +// native DHookGamerules(Handle:setup, bool:post, DHookRemovalCB:removalcb); +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) { if(params[1] == BAD_HANDLE) @@ -172,6 +288,71 @@ cell_t Native_GetParam(IPluginContext *pContext, const cell_t *params) 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 **)¶mStruct)) != 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) { if(params[1] == BAD_HANDLE) @@ -205,6 +386,7 @@ cell_t Native_GetReturn(IPluginContext *pContext, const cell_t *params) } return 1; } +// native DHookSetReturn(Handle:hReturn, any:value) cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params) { if(params[1] == BAD_HANDLE) @@ -258,11 +440,12 @@ cell_t Native_SetReturn(IPluginContext *pContext, const cell_t *params) returnStruct->isChanged = true; 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_SetReturnVector(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) { 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->newParams[index] != NULL) + if((char *)paramStruct->newParams[index] != NULL && paramStruct->isChanged[index]) delete (char *)paramStruct->newParams[index]; paramStruct->newParams[index] = new char[strlen(value)+1]; @@ -342,14 +525,14 @@ sp_nativeinfo_t g_Natives[] = {"DHookCreate", Native_CreateHook}, {"DHookAddParam", Native_AddParam}, {"DHookEntity", Native_HookEntity}, - /*{"DHookGamerules", Native_HookGamerules}, + {"DHookGamerules", Native_HookGamerules}, {"DHookRaw", Native_HookRaw}, - {"DHookRemoveHookID", Native_RemoveHookID},*/ + {"DHookRemoveHookID", Native_RemoveHookID}, {"DHookGetParam", Native_GetParam}, {"DHookGetReturn", Native_GetReturn}, {"DHookSetReturn", Native_SetReturn}, - /*{"DHookSetParam", Native_SetParam}, - {"DHookGetParamVector", Native_GetParamVector}, + {"DHookSetParam", Native_SetParam}, + /*{"DHookGetParamVector", Native_GetParamVector}, {"DHookGetReturnVector", Native_GetReturnVector}, {"DHookSetReturnVector", Native_SetReturnVector}, {"DHookSetParamVector", Native_SetParamVector},*/ diff --git a/natives.h b/natives.h index 8213630..9b19b52 100644 --- a/natives.h +++ b/natives.h @@ -3,8 +3,7 @@ #include "extension.h" #include "vhook.h" - -extern bool g_bAllowGamerules; +extern ISDKTools *g_pSDKTools; extern HandleType_t g_HookSetupHandle; extern HandleType_t g_HookParamsHandle; extern HandleType_t g_HookReturnHandle; diff --git a/vhook.cpp b/vhook.cpp index 0ab76f5..429296c 100644 --- a/vhook.cpp +++ b/vhook.cpp @@ -19,6 +19,7 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem this->callback->post = post; this->callback->hookType = setup->hookType; this->callback->params = setup->params; + this->addr = 0; if(this->callback->hookType == HookType_Entity) { @@ -26,6 +27,10 @@ DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *rem } else { + if(this->callback->hookType == HookType_Raw) + { + this->addr = (intptr_t)iface; + } 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); } - else + else if(this->callback->returnType != ReturnType_Float) { 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); 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); - if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentContext()) + if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext()) { delete manager; g_pHooks.Remove(i); @@ -96,18 +105,18 @@ size_t GetStackArgsSize(DHooksCallback *dg) } 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); - res->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool)); - memcpy(res->orgParams, argStack, argStackSize); + HookParamsStruct *params = new HookParamsStruct(); + params->dg = dg; + params->orgParams = (void **)malloc(argStackSize); + params->newParams = (void **)malloc(dg->params.Count() * sizeof(void *)); + params->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool)); + memcpy(params->orgParams, argStack, argStackSize); for(int i = 0; i < dg->params.Count(); i++) { - res->newParams[i] = NULL; - res->isChanged[i] = false; + params->newParams[i] = NULL; + params->isChanged[i] = false; } - return res; + return params; } HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result) { @@ -138,7 +147,22 @@ HookReturnStruct *GetReturnStruct(DHooksCallback *dg, const void *result) } 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; @@ -186,7 +210,7 @@ void *Callback(DHooksCallback *dg, void **argStack) delete returnStruct; } g_SHPtr->SetRes(MRES_IGNORED); - return 0; + return NULL; } dg->plugin_callback->PushCell(rHndl); } @@ -213,11 +237,13 @@ void *Callback(DHooksCallback *dg, void **argStack) delete paramStruct; } g_SHPtr->SetRes(MRES_IGNORED); - return 0; + 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(); @@ -227,6 +253,7 @@ void *Callback(DHooksCallback *dg, void **argStack) 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: @@ -239,13 +266,14 @@ void *Callback(DHooksCallback *dg, void **argStack) else //Throw an error if no override was set { g_SHPtr->SetRes(MRES_IGNORED); - IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); - smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); + 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: @@ -254,13 +282,14 @@ void *Callback(DHooksCallback *dg, void **argStack) if(returnStruct->isChanged) { g_SHPtr->SetRes(MRES_OVERRIDE); + mres = MRES_OVERRIDE; ret = *(void **)returnStruct->newResult; } else //Throw an error if no override was set { g_SHPtr->SetRes(MRES_IGNORED); - IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); - smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); + mres = MRES_IGNORED; + dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Tried to override return value without return value being set"); } } break; @@ -270,22 +299,24 @@ void *Callback(DHooksCallback *dg, void **argStack) if(returnStruct->isChanged) { g_SHPtr->SetRes(MRES_SUPERCEDE); + mres = MRES_SUPERCEDE; ret = *(void **)returnStruct->newResult; } else //Throw an error if no override was set { g_SHPtr->SetRes(MRES_IGNORED); - IPlugin *plugin = plsys->FindPluginByContext(dg->plugin_callback->GetParentContext()->GetContext()); - smutils->LogError(myself, "Plugin %s tried to override a return without a return being set", plugin->GetFilename()); + 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->GetParentContext()->GetIdentity(), myself->GetIdentity()); + HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity()); if(returnStruct) { @@ -296,9 +327,163 @@ void *Callback(DHooksCallback *dg, void **argStack) 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 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; +} diff --git a/vhook.h b/vhook.h index ae581de..44b37d7 100644 --- a/vhook.h +++ b/vhook.h @@ -117,7 +117,7 @@ public: #ifndef __linux__ 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 void *Callback(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.push(eax); masm.push(Operand(ebp, 8)); - /*if(type == ReturnType_Float) + if(type == ReturnType_Float) masm.call(ExternalAddress((void *)Callback_float)); - else*/ + else masm.call(ExternalAddress((void *)Callback)); masm.addl(esp, 8); masm.pop(ebp); @@ -161,9 +161,9 @@ static void *GenerateThunk(ReturnType type) masm.lea(eax, Operand(ebp, 8)); masm.push(eax); masm.push(ecx); - //if(type == ReturnType_Float) - // masm.call(ExternalAddress(Callback_float)); - //else + if(type == ReturnType_Float) + masm.call(ExternalAddress(Callback_float)); + else masm.call(ExternalAddress(Callback)); masm.addl(esp, 12); masm.pop(ecx); // grab arg size @@ -226,6 +226,10 @@ public: { delete (char *)this->newParams[i]; } + else if(dg->params.Element(i).type == HookParamType_Float) + { + delete (float *)this->newParams[i]; + } } free(this->newParams); } @@ -277,6 +281,7 @@ public: } } public: + intptr_t addr; int hookid; DHooksCallback *callback; IPluginFunction *remove_callback;