fixed a bug where the menu watch processor removed the wrong index from its list
3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
16 #include <sh_string.h>
18 #include "sm_globals.h"
19 #include "PluginSys.h"
20 #include "sourcemod.h"
21 #include "sm_stringutil.h"
23 using namespace SourceHook;
25 static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1];
26 static FakeNative *s_curnative = NULL;
27 static IPluginContext *s_curcaller = NULL;
29 cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pData)
31 FakeNative *native = (FakeNative *)pData;
33 /* Check if too many parameters were passed */
34 if (params[0] > SP_MAX_EXEC_PARAMS)
36 return pContext->ThrowNativeError("Called native with too many parameters (%d>%d)", params[9], SP_MAX_EXEC_PARAMS);
39 /* Check if the native is paused */
40 sp_context_t *pNativeCtx = native->ctx->GetContext();
41 if ((pNativeCtx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
43 return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
46 CPlugin *pCaller = g_PluginSys.GetPluginByCtx(pContext->GetContext());
48 /* Save any old data on the stack */
49 FakeNative *pSaveNative = s_curnative;
50 IPluginContext *pSaveCaller = s_curcaller;
51 cell_t save_params[SP_MAX_EXEC_PARAMS+1];
52 if (pSaveNative != NULL)
54 /* Copy all old parameters */
55 for (cell_t i=0; i<=s_curparams[0]; i++)
57 save_params[i] = s_curparams[i];
61 /* Save the current parameters */
63 s_curcaller = pContext;
64 for (cell_t i=0; i<=params[0]; i++)
66 s_curparams[i] = params[i];
69 /* Push info and execute. */
71 native->call->PushCell(pCaller->GetMyHandle());
72 native->call->PushCell(params[0]);
74 if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
76 if (pContext->GetContext()->n_err == SP_ERROR_NONE)
78 pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
82 /* Restore everything from the stack if necessary */
83 s_curnative = pSaveNative;
84 s_curcaller = pSaveCaller;
85 if (pSaveNative != NULL)
87 for (cell_t i=0; i<=save_params[0]; i++)
89 s_curparams[i] = save_params[i];
96 static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
99 pContext->LocalToString(params[1], &name);
101 IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
104 return pContext->ThrowNativeError("Function %x is not a valid function", params[2]);
107 if (!g_PluginSys.AddFakeNative(pFunction, name, FakeNativeRouter))
109 return pContext->ThrowNativeError("Fatal error creating dynamic native!");
115 static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
117 if (!s_curnative || (s_curnative->ctx != pContext))
119 return pContext->ThrowNativeError("Not called from inside a native function");
124 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
126 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
128 s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
130 s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
136 static cell_t GetNativeStringLength(IPluginContext *pContext, const cell_t *params)
138 if (!s_curnative || (s_curnative->ctx != pContext))
140 return pContext->ThrowNativeError("Not called from inside a native function");
143 cell_t param = params[1];
144 if (param < 1 || param > s_curparams[0])
146 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
151 if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
157 pContext->LocalToPhysAddr(params[2], &addr);
158 *addr = (cell_t)strlen(str);
160 return SP_ERROR_NONE;
163 static cell_t GetNativeString(IPluginContext *pContext, const cell_t *params)
165 if (!s_curnative || (s_curnative->ctx != pContext))
167 return pContext->ThrowNativeError("Not called from inside a native function");
170 cell_t param = params[1];
171 if (param < 1 || param > s_curparams[0])
173 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
178 if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
184 pContext->StringToLocalUTF8(params[2], params[3], str, &bytes);
187 pContext->LocalToPhysAddr(params[4], &addr);
188 *addr = (cell_t)bytes;
190 return SP_ERROR_NONE;
193 static cell_t SetNativeString(IPluginContext *pContext, const cell_t *params)
195 if (!s_curnative || (s_curnative->ctx != pContext))
197 return pContext->ThrowNativeError("Not called from inside a native function");
200 cell_t param = params[1];
201 if (param < 1 || param > s_curparams[0])
203 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
207 pContext->LocalToString(params[2], &str);
213 err = s_curcaller->StringToLocalUTF8(s_curparams[param], params[3], str, &bytes);
215 err = s_curcaller->StringToLocal(s_curparams[param], params[3], str);
218 if (bytes >= (size_t)params[3])
220 bytes = params[3] - 1;
224 if (err != SP_ERROR_NONE)
230 pContext->LocalToPhysAddr(params[5], &addr);
231 *addr = (cell_t)bytes;
233 return SP_ERROR_NONE;
236 static cell_t GetNativeCell(IPluginContext *pContext, const cell_t *params)
238 if (!s_curnative || (s_curnative->ctx != pContext))
240 return pContext->ThrowNativeError("Not called from inside a native function");
243 cell_t param = params[1];
244 if (param < 1 || param > s_curparams[0])
246 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
249 return s_curparams[param];
252 static cell_t GetNativeCellRef(IPluginContext *pContext, const cell_t *params)
254 if (!s_curnative || (s_curnative->ctx != pContext))
256 return pContext->ThrowNativeError("Not called from inside a native function");
259 cell_t param = params[1];
260 if (param < 1 || param > s_curparams[0])
262 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
266 if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
268 return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
274 static cell_t SetNativeCellRef(IPluginContext *pContext, const cell_t *params)
276 if (!s_curnative || (s_curnative->ctx != pContext))
278 return pContext->ThrowNativeError("Not called from inside a native function");
281 cell_t param = params[1];
282 if (param < 1 || param > s_curparams[0])
284 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
288 if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
290 return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
298 static cell_t GetNativeArray(IPluginContext *pContext, const cell_t *params)
300 if (!s_curnative || (s_curnative->ctx != pContext))
302 return pContext->ThrowNativeError("Not called from inside a native function");
305 cell_t param = params[1];
306 if (param < 1 || param > s_curparams[0])
308 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
313 if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
319 pContext->LocalToPhysAddr(params[2], &src);
321 memcpy(src, addr, sizeof(cell_t) * params[3]);
323 return SP_ERROR_NONE;
326 static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params)
328 if (!s_curnative || (s_curnative->ctx != pContext))
330 return pContext->ThrowNativeError("Not called from inside a native function");
333 cell_t param = params[1];
334 if (param < 1 || param > s_curparams[0])
336 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
341 if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
347 pContext->LocalToPhysAddr(params[2], &src);
349 memcpy(addr, src, sizeof(cell_t) * params[3]);
351 return SP_ERROR_NONE;
354 static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
356 if (!s_curnative || (s_curnative->ctx != pContext))
358 return pContext->ThrowNativeError("Not called from inside a native function");
361 int out_param = params[1];
362 int fmt_param = params[2];
363 int var_param = params[3];
366 if (out_param && (out_param < 1 || out_param > s_curparams[0]))
368 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", out_param);
370 if (fmt_param && (fmt_param < 1 || fmt_param > s_curparams[0]))
372 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
374 if (var_param && (var_param < 1 || var_param > s_curparams[0] + 1))
376 return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
379 /* Get buffer information */
386 if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
391 pContext->LocalToString(params[6], &output_buffer);
396 if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
401 pContext->LocalToString(params[7], &format_buffer);
404 /* Get maximum length */
405 size_t maxlen = (size_t)params[4];
408 size_t written = atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
411 pContext->LocalToPhysAddr(params[5], &addr);
412 *addr = (cell_t)written;
414 return s_curcaller->GetContext()->n_err;
418 REGISTER_NATIVES(nativeNatives)
420 {"CreateNative", CreateNative},
421 {"GetNativeArray", GetNativeArray},
422 {"GetNativeCell", GetNativeCell},
423 {"GetNativeCellRef", GetNativeCellRef},
424 {"GetNativeString", GetNativeString},
425 {"GetNativeStringLength", GetNativeStringLength},
426 {"FormatNativeString", FormatNativeString},
427 {"ThrowNativeError", ThrowNativeError},
428 {"SetNativeArray", SetNativeArray},
429 {"SetNativeCellRef", SetNativeCellRef},
430 {"SetNativeString", SetNativeString},