int amxx_DynaCallback(int idx, AMX *amx, cell *params) { if (idx < 0 || idx >= (int)g_RegNatives.size()) { LogError(amx, AMX_ERR_NATIVE, "Invalid dynamic native called"); return 0; } regnative *pNative = g_RegNatives[idx]; int numParams = params[0] / sizeof(cell); if (numParams > CALLFUNC_MAXPARAMS) { LogError(amx, AMX_ERR_NATIVE, "Called dynanative with too many parameters (%d)", CALLFUNC_MAXPARAMS); return 0; } CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx); CPluginMngr::CPlugin *pNativePlugin = g_plugins.findPluginFast(pNative->amx); if (!pNativePlugin->isExecutable(pNative->func)) { LogError(amx, AMX_ERR_NATIVE, "Called dynanative into a paused plugin."); pPlugin->setStatus(ps_paused); return 0; } /* Save old values on ZE STACK */ AMX *pSaveCaller = g_pCaller; cell saveParams[CALLFUNC_MAXPARAMS]; regnative *pSaveNative = g_pCurNative; int saveError = g_CurError; if (pSaveNative) { for (ucell i = 0; i <= g_Params[0] / sizeof(cell); i++) { saveParams[i] = g_Params[i]; } } /* Save current info */ g_CurError = AMX_ERR_NONE; g_pCaller = amx; g_pCurNative = pNative; int err = 0; cell ret = 0; if (pNative->style == 0) { amx_Push(pNative->amx, numParams); amx_Push(pNative->amx, pPlugin->getId()); for (int i=numParams; i>=0; i--) { g_Params[i] = params[i]; } } else if (pNative->style == 1) { /** * use dJeyL's system .. very clever! * NOTE: clever, but doesn't work at all since the JIT does bounds checking * this should REALLY be deprecated */ for (int i=numParams; i>=1; i--) { amx_Push(pNative->amx, params[i]); } } Debugger *pDebugger = (Debugger *)pNative->amx->userdata[UD_DEBUGGER]; if (pDebugger) { pDebugger->BeginExec(); } err=amx_Exec(pNative->amx, &ret, pNative->func); if (err != AMX_ERR_NONE) { if (pDebugger && pDebugger->ErrorExists()) { //don't care } else if (err != -1) { //nothing logged the error LogError(pNative->amx, err, NULL); } pNative->amx->error = AMX_ERR_NONE; //furthermore, log an error in the parent plugin. LogError(amx, AMX_ERR_NATIVE, "Unhandled dynamic native error"); } else if (g_CurError != AMX_ERR_NONE) { LogError(amx, g_CurError, g_errorStr); } if (pDebugger) { pDebugger->EndExec(); } /* Restore everything */ g_pCurNative = pSaveNative; g_CurError = saveError; g_pCaller = pSaveCaller; if (pSaveNative) { for (ucell i = 0; i <= saveParams[0] / sizeof(cell); i++) { g_Params[i] = saveParams[i]; } } return ret; }
cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; const int STRINGEX_MAXLENGTH = 128; cell globRetVal = 0; AMXForwardList::iterator iter; for (iter = m_Funcs.begin(); iter != m_Funcs.end(); iter++) { if (iter->pPlugin->isExecutable(iter->func)) { // Get debug info AMX *amx = (*iter).pPlugin->getAMX(); Debugger *pDebugger = (Debugger *)amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); cell *tmp; if (!str) str = ""; amx_Allot(iter->pPlugin->getAMX(), (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } //Push the parameters in reverse order. Weird, unfriendly part of Small 3.0! for (i = m_NumParams-1; i >= 0; i--) { amx_Push(amx, realParams[i]); } // exec cell retVal = 0; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, (*iter).pPlugin->getId(), iter->func); #endif int err = amx_Exec(amx, &retVal, iter->func); // log runtime error, if any if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(amx, err, NULL); } } amx->error = AMX_ERR_NONE; if (pDebugger) pDebugger->EndExec(); // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(iter->pPlugin->getAMX(), realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(iter->pPlugin->getAMX(), realParams[i]); } } // decide what to do (based on exectype and retval) switch (m_ExecType) { case ET_IGNORE: break; case ET_STOP: if (retVal > 0) return retVal; case ET_STOP2: if (retVal == 1) return 1; else if (retVal > globRetVal) globRetVal = retVal; break; case ET_CONTINUE: if (retVal > globRetVal) globRetVal = retVal; break; } } } return globRetVal; }
int Handler::HandleError(const char *msg) { if (m_iErrFunc <= 0) return 0; m_Handling = true; m_pTrace = NULL; m_FmtCache.clear(); Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; int error = m_pAmx->error; static char _buffer[512]; if (pDebugger) { pDebugger->SetTracedError(error); m_pTrace = pDebugger->GetTraceStart(); pDebugger->FormatError(_buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); pDebugger->BeginExec(); } else { Debugger::FmtGenericMsg(m_pAmx, error, _buffer, sizeof(_buffer)-1); m_FmtCache.assign(_buffer); } SetErrorMsg(msg); cell hea_addr, *phys_addr, result; amx_PushString(m_pAmx, &hea_addr, &phys_addr, msg, 0, 0); amx_Push(m_pAmx, pDebugger ? 1 : 0); amx_Push(m_pAmx, error); int err = amx_Exec(m_pAmx, &result, m_iErrFunc); if (err != AMX_ERR_NONE) { //handle this manually. if (pDebugger) { pDebugger->SetTracedError(err); pDebugger->DisplayTrace(msg); } else { if (GetLastMsg()) AMXXLOG_Error("%s", GetLastMsg()); Debugger::GenericMessage(m_pAmx, err); } AMXXLOG_Error("[AMXX] NOTE: Runtime failures in an error filter are not good!"); } if (pDebugger) pDebugger->EndExec(); amx_Release(m_pAmx, hea_addr); m_Handling = false; m_pTrace = NULL; m_FmtCache.clear(); if (err != AMX_ERR_NONE || !result) return 0; return result; }
cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays) { if (isFree) return 0; const int STRINGEX_MAXLENGTH = 128; cell realParams[FORWARD_MAX_PARAMS]; cell *physAddrs[FORWARD_MAX_PARAMS]; if (!m_HasFunc || m_ToDelete) return 0; CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(m_Amx); if (!pPlugin->isExecutable(m_Func)) return 0; m_InExec = true; Debugger *pDebugger = (Debugger *)m_Amx->userdata[UD_DEBUGGER]; if (pDebugger) pDebugger->BeginExec(); // handle strings & arrays int i; for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) { const char *str = reinterpret_cast<const char*>(params[i]); if (!str) str = ""; cell *tmp; amx_Allot(m_Amx, (m_ParamTypes[i] == FP_STRING) ? strlen(str) + 1 : STRINGEX_MAXLENGTH, &realParams[i], &tmp); amx_SetStringOld(tmp, str, 0, 0); physAddrs[i] = tmp; } else if (m_ParamTypes[i] == FP_ARRAY) { cell *tmp; amx_Allot(m_Amx, preparedArrays[params[i]].size, &realParams[i], &tmp); physAddrs[i] = tmp; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *tmp++ = (static_cast<cell>(*data++)) & 0xFF; } } else { realParams[i] = params[i]; } } for (i = m_NumParams - 1; i >= 0; i--) amx_Push(m_Amx, realParams[i]); // exec cell retVal; #if defined BINLOG_ENABLED g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func); #endif int err = amx_Exec(m_Amx, &retVal, m_Func); if (err != AMX_ERR_NONE) { //Did something else set an error? if (pDebugger && pDebugger->ErrorExists()) { //we don't care, something else logged the error. } else if (err != -1) { //nothing logged the error so spit it out anyway LogError(m_Amx, err, NULL); } } if (pDebugger) pDebugger->EndExec(); m_Amx->error = AMX_ERR_NONE; // cleanup strings & arrays for (i = 0; i < m_NumParams; ++i) { if (m_ParamTypes[i] == FP_STRING) { amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_STRINGEX) { // copy back amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_Release(m_Amx, realParams[i]); } else if (m_ParamTypes[i] == FP_ARRAY) { // copy back if (preparedArrays[params[i]].copyBack) { cell *tmp = physAddrs[i]; if (preparedArrays[params[i]].type == Type_Cell) { memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell)); } else { char *data = (char*)preparedArrays[params[i]].ptr; for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j) *data++ = static_cast<char>(*tmp++ & 0xFF); } } amx_Release(m_Amx, realParams[i]); } } m_InExec = false; return retVal; }
int Handler::HandleNative(const char *native, int index, int trap) { if (!IsNativeFiltering()) return 0; /** * Our handler here is a bit different from HandleError(). * For one, there is no current error in pDebugger, so we * don't have to save some states. */ m_InNativeFilter = true; Debugger *pDebugger = (Debugger *)m_pAmx->userdata[UD_DEBUGGER]; if (pDebugger && trap) pDebugger->BeginExec(); else if (pDebugger && !trap) DisableDebugHandler(m_pAmx); cell hea_addr, *phys_addr, retval; if (!trap) m_pAmx->flags |= AMX_FLAG_PRENIT; amx_Push(m_pAmx, trap); amx_Push(m_pAmx, index); amx_PushString(m_pAmx, &hea_addr, &phys_addr, native, 0, 0); int err = amx_Exec(m_pAmx, &retval, m_iNatFunc); if (err != AMX_ERR_NONE) { //LogError() took care of something for us. if (err == -1) { m_InNativeFilter = false; amx_Release(m_pAmx, hea_addr); return 1; } if (!trap) { AMXXLOG_Error("[AMXX] Runtime failure %d occurred in native filter. Aborting plugin load.", err); return 0; } //handle this manually. //we need to push this through an error filter, same as executeForwards! if (pDebugger && pDebugger->ErrorExists()) { //don't display, it was already handled. } else if (err != -1) { LogError(m_pAmx, err, NULL); } AMXXLOG_Error("[AMXX] NOTE: Runtime failures in native filters are not good!"); retval = 0; } if (!trap) m_pAmx->flags &= ~AMX_FLAG_PRENIT; if (pDebugger && trap) pDebugger->EndExec(); else if (pDebugger && !trap) EnableDebugHandler(m_pAmx, pDebugger); amx_Release(m_pAmx, hea_addr); m_InNativeFilter = false; return (int)retval; }