From c3fcdbb7db171f592b197e3ccb4bcd6f353ab177 Mon Sep 17 00:00:00 2001 From: Dr!fter Date: Thu, 29 Aug 2013 15:18:43 -0400 Subject: [PATCH] More linux fixes. --- natives.cpp | 10 +++- vfunc_call.h | 90 ++++++++++++++++++++++++++++ vhook.cpp | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++- vhook.h | 23 +++++-- 4 files changed, 280 insertions(+), 9 deletions(-) diff --git a/natives.cpp b/natives.cpp index 9029f2d..ce93014 100644 --- a/natives.cpp +++ b/natives.cpp @@ -42,6 +42,7 @@ bool GetHandleIfValidOrError(HandleType_t type, void **object, IPluginContext *p return true; } +#ifndef __linux__ intptr_t GetObjectAddr(HookParamType type, void **params, int index) { if(type == HookParamType_Object) @@ -51,6 +52,12 @@ intptr_t GetObjectAddr(HookParamType type, void **params, int index) return 0; } +#else +intptr_t GetObjectAddr(HookParamType type, void **params, int index) +{ + return (intptr_t)params[index]; +} +#endif //native Handle:DHookCreate(offset, HookType:hooktype, ReturnType:returntype, ThisPointerType:thistype, DHookCallback:callback); cell_t Native_CreateHook(IPluginContext *pContext, const cell_t *params) @@ -495,8 +502,6 @@ cell_t Native_SetParamVector(IPluginContext *pContext, const cell_t *params) } return pContext->ThrowNativeError("Invalid param type to set. Param is not a vector."); } -/*cell_t Native_GetReturnVector(IPluginContext *pContext, const cell_t *params); -cell_t Native_SetReturnVector(IPluginContext *pContext, const cell_t *params);*/ // native DHookGetParamString(Handle:hParams, num, String:buffer[], size) cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params) @@ -526,6 +531,7 @@ cell_t Native_GetParamString(IPluginContext *pContext, const cell_t *params) return 1; } + // native DHookGetReturnString(Handle:hReturn, String:buffer[], size) cell_t Native_GetReturnString(IPluginContext *pContext, const cell_t *params) { diff --git a/vfunc_call.h b/vfunc_call.h index 07ca195..4f2fefc 100644 --- a/vfunc_call.h +++ b/vfunc_call.h @@ -110,6 +110,7 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) } T ret = 0; + if(dg->returnType == ReturnType_Void) { pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.Count()); @@ -132,4 +133,93 @@ T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) return ret; } +#ifdef __linux__ +template <> +string_t CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface) +{ + SourceMod::PassInfo *paramInfo = NULL; + SourceMod::PassInfo returnInfo; + + if(dg->returnType != ReturnType_Void) + { + returnInfo.flags = dg->returnFlag; + returnInfo.size = sizeof(string_t); + returnInfo.type = PassType_Object; + } + + ICallWrapper *pCall; + + size_t size = GetStackArgsSize(dg); + + unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size); + unsigned char *vptr = vstk; + + *(void **)vptr = iface; + + if(paramStruct) + { + vptr += sizeof(void *); + paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.Count()); + for(int i = 0; i < dg->params.Count(); i++) + { + switch(dg->params.Element(i).type) + { + case HookParamType_Int: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(int); + case HookParamType_Bool: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(cell_t); + case HookParamType_Float: + PARAMINFO_SWITCH(PassType_Float); + VSTK_PARAM_SWITCH_FLOAT(); + case HookParamType_String: + PARAMINFO_SWITCH(PassType_Object); + VSTK_PARAM_SWITCH(int); + case HookParamType_StringPtr: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(string_t *); + case HookParamType_CharPtr: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(char *); + case HookParamType_VectorPtr: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(Vector *); + case HookParamType_CBaseEntity: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(CBaseEntity *); + case HookParamType_Edict: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(edict_t *); + default: + PARAMINFO_SWITCH(PassType_Basic); + VSTK_PARAM_SWITCH(void *); + } + } + } + + string_t ret = NULL_STRING; + + if(dg->returnType == ReturnType_Void) + { + pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.Count()); + pCall->Execute(vstk, NULL); + } + else + { + pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.Count()); + pCall->Execute(vstk, &ret); + } + + pCall->Destroy(); + free(vstk); + + if(paramInfo != NULL) + { + free(paramInfo); + } + + return ret; +} +#endif #endif diff --git a/vhook.cpp b/vhook.cpp index d45532b..6eea825 100644 --- a/vhook.cpp +++ b/vhook.cpp @@ -7,6 +7,11 @@ CUtlVector g_pHooks; using namespace SourceHook; +#ifndef __linux__ +#define OBJECT_OFFSET sizeof(void *) +#else +#define OBJECT_OFFSET (sizeof(void *)*2) +#endif DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, bool post) { this->callback = MakeHandler(setup->returnType); @@ -110,9 +115,13 @@ size_t GetStackArgsSize(DHooksCallback *dg) res += dg->params.Element(i).size; } + #ifndef __linux__ if(dg->returnType == ReturnType_Vector)//Account for result vector ptr. + #else + if(dg->returnType == ReturnType_Vector || dg->returnType == ReturnType_String) + #endif { - res += sizeof(void *); + res += OBJECT_OFFSET; } return res; } @@ -120,15 +129,19 @@ HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t arg { HookParamsStruct *params = new HookParamsStruct(); params->dg = dg; + #ifndef __linux__ if(dg->returnType != ReturnType_Vector) + #else + if(dg->returnType != ReturnType_Vector && dg->returnType != ReturnType_String) + #endif { params->orgParams = (void **)malloc(argStackSize); memcpy(params->orgParams, argStack, argStackSize); } else //Offset result ptr { - params->orgParams = (void **)malloc(argStackSize-sizeof(void *)); - memcpy(params->orgParams, argStack+sizeof(void *), argStackSize); + params->orgParams = (void **)malloc(argStackSize-OBJECT_OFFSET); + memcpy(params->orgParams, argStack+OBJECT_OFFSET, argStackSize-OBJECT_OFFSET); } params->newParams = (void **)malloc(dg->params.Count() * sizeof(void *)); params->isChanged = (bool *)malloc(dg->params.Count() * sizeof(bool)); @@ -681,3 +694,150 @@ Vector *Callback_vector(DHooksCallback *dg, void **argStack) } return vec_result; } + +#ifdef __linux__ +string_t *Callback_stringt(DHooksCallback *dg, void **argStack) +{ + string_t *string_result = (string_t *)argStack[0]; // Save the result + + HookReturnStruct *returnStruct = NULL; + HookParamsStruct *paramStruct = NULL; + Handle_t rHndl; + Handle_t pHndl; + + size_t argsize = GetStackArgsSize(dg); + + if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address) + { + dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType)); + } + + returnStruct = GetReturnStruct(dg); + 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); + + if(argsize > 0) + { + paramStruct = GetParamStruct(dg, argStack, argsize); + 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(); + ret = string_result; + switch((MRESReturn)result) + { + case MRES_Handled: + case MRES_ChangedHandled: + g_SHPtr->DoRecall(); + g_SHPtr->SetRes(MRES_SUPERCEDE); + mres = MRES_SUPERCEDE; + *string_result = CallVFunction(dg, paramStruct, g_SHPtr->GetIfacePtr()); + break; + case MRES_ChangedOverride: + if(dg->returnType != ReturnType_Void) + { + if(returnStruct->isChanged) + { + *string_result = *(string_t *)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; + *string_result = *(string_t *)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; + *string_result = *(string_t *)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) + { + *string_result = NULL_STRING; + return string_result; + } + return string_result; +} +#endif diff --git a/vhook.h b/vhook.h index 1a2b846..e2860bc 100644 --- a/vhook.h +++ b/vhook.h @@ -166,6 +166,7 @@ Vector *Callback_vector(DHooksCallback *dg, void **stack, size_t *argsizep); void *Callback(DHooksCallback *dg, void **stack); float Callback_float(DHooksCallback *dg, void **stack); Vector *Callback_vector(DHooksCallback *dg, void **stack); +string_t *Callback_stringt(DHooksCallback *dg, void **stack); #endif bool SetupHookManager(ISmmAPI *ismm); void CleanupHooks(IPluginContext *pContext); @@ -182,10 +183,20 @@ static void *GenerateThunk(ReturnType type) masm.push(ebp); masm.movl(ebp, esp); masm.subl(esp, kReserve); - masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector - masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument - masm.lea(eax, Operand(ebp, 8)); // grab the |this| - masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument + if(type != ReturnType_String && type != ReturnType_Vector) + { + masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector + masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument + masm.movl(eax, Operand(ebp, 8)); // grab the |this| + masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/ + } + else + { + masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector + masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument + masm.movl(eax, Operand(ebp, 12)); // grab the |this| + masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/ + } if(type == ReturnType_Float) { masm.call(ExternalAddress((void *)Callback_float)); @@ -194,6 +205,10 @@ static void *GenerateThunk(ReturnType type) { masm.call(ExternalAddress((void *)Callback_vector)); } + else if(type == ReturnType_String) + { + masm.call(ExternalAddress((void *)Callback_stringt)); + } else { masm.call(ExternalAddress((void *)Callback));