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 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; }