예제 #1
0
파일: natives.cpp 프로젝트: Chuvi-w/amxmodx
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;
}
예제 #2
0
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;
}