diff -r 000000000000 -r c24a6fa957db core/smn_fakenatives.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/smn_fakenatives.cpp Sun Jul 06 04:49:55 2008 +0000
@@ -0,0 +1,455 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include
+#include
+#include "sm_trie.h"
+#include "sm_globals.h"
+#include "PluginSys.h"
+#include "sourcemod.h"
+#include "sm_stringutil.h"
+
+using namespace SourceHook;
+
+static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1];
+static FakeNative *s_curnative = NULL;
+static IPluginContext *s_curcaller = NULL;
+
+cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pData)
+{
+ FakeNative *native = (FakeNative *)pData;
+
+ /* Check if too many parameters were passed */
+ if (params[0] > SP_MAX_EXEC_PARAMS)
+ {
+ return pContext->ThrowNativeError("Called native with too many parameters (%d>%d)", params[9], SP_MAX_EXEC_PARAMS);
+ }
+
+ /* Check if the native is paused */
+ sp_context_t *pNativeCtx = native->ctx->GetContext();
+ if ((pNativeCtx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
+ {
+ return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
+ }
+
+ CPlugin *pCaller = g_PluginSys.GetPluginByCtx(pContext->GetContext());
+
+ /* Save any old data on the stack */
+ FakeNative *pSaveNative = s_curnative;
+ IPluginContext *pSaveCaller = s_curcaller;
+ cell_t save_params[SP_MAX_EXEC_PARAMS+1];
+ if (pSaveNative != NULL)
+ {
+ /* Copy all old parameters */
+ for (cell_t i=0; i<=s_curparams[0]; i++)
+ {
+ save_params[i] = s_curparams[i];
+ }
+ }
+
+ /* Save the current parameters */
+ s_curnative = native;
+ s_curcaller = pContext;
+ for (cell_t i=0; i<=params[0]; i++)
+ {
+ s_curparams[i] = params[i];
+ }
+
+ /* Push info and execute. */
+ cell_t result = 0;
+ native->call->PushCell(pCaller->GetMyHandle());
+ native->call->PushCell(params[0]);
+ int error;
+ if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
+ {
+ if (pContext->GetContext()->n_err == SP_ERROR_NONE)
+ {
+ pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
+ }
+ }
+
+ /* Restore everything from the stack if necessary */
+ s_curnative = pSaveNative;
+ s_curcaller = pSaveCaller;
+ if (pSaveNative != NULL)
+ {
+ for (cell_t i=0; i<=save_params[0]; i++)
+ {
+ s_curparams[i] = save_params[i];
+ }
+ }
+
+ return result;
+}
+
+static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
+{
+ char *name;
+ CPlugin *pPlugin;
+
+ pContext->LocalToString(params[1], &name);
+
+ IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
+ if (!pFunction)
+ {
+ return pContext->ThrowNativeError("Function %x is not a valid function", params[2]);
+ }
+
+ pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
+
+ if (!pPlugin->AddFakeNative(pFunction, name, FakeNativeRouter))
+ {
+ return pContext->ThrowNativeError("Fatal error creating dynamic native!");
+ }
+
+ return 1;
+}
+
+static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
+
+ char buffer[512];
+
+ g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
+
+ if (pContext->GetContext()->n_err != SP_ERROR_NONE)
+ {
+ s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
+ } else {
+ s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
+ }
+
+ return 0;
+}
+
+static cell_t GetNativeStringLength(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ int err;
+ char *str;
+ if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[2], &addr);
+ *addr = (cell_t)strlen(str);
+
+ return SP_ERROR_NONE;
+}
+
+static cell_t GetNativeString(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ int err;
+ char *str;
+ if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ size_t bytes = 0;
+ pContext->StringToLocalUTF8(params[2], params[3], str, &bytes);
+
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[4], &addr);
+ *addr = (cell_t)bytes;
+
+ return SP_ERROR_NONE;
+}
+
+static cell_t SetNativeString(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ char *str;
+ pContext->LocalToString(params[2], &str);
+
+ int err;
+ size_t bytes = 0;
+ if (params[4])
+ {
+ err = s_curcaller->StringToLocalUTF8(s_curparams[param], params[3], str, &bytes);
+ } else {
+ err = s_curcaller->StringToLocal(s_curparams[param], params[3], str);
+ /* Eww */
+ bytes = strlen(str);
+ if (bytes >= (size_t)params[3])
+ {
+ bytes = params[3] - 1;
+ }
+ }
+
+ if (err != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[5], &addr);
+ *addr = (cell_t)bytes;
+
+ return SP_ERROR_NONE;
+}
+
+static cell_t GetNativeCell(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ return s_curparams[param];
+}
+
+static cell_t GetNativeCellRef(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ cell_t *addr;
+ if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
+ {
+ return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
+ }
+
+ return *addr;
+}
+
+static cell_t SetNativeCellRef(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ cell_t *addr;
+ if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
+ {
+ return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
+ }
+
+ *addr = params[2];
+
+ return 1;
+}
+
+static cell_t GetNativeArray(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ int err;
+ cell_t *addr;
+ if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ cell_t *src;
+ pContext->LocalToPhysAddr(params[2], &src);
+
+ memcpy(src, addr, sizeof(cell_t) * params[3]);
+
+ return SP_ERROR_NONE;
+}
+
+static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ cell_t param = params[1];
+ if (param < 1 || param > s_curparams[0])
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
+ }
+
+ int err;
+ cell_t *addr;
+ if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+
+ cell_t *src;
+ pContext->LocalToPhysAddr(params[2], &src);
+
+ memcpy(addr, src, sizeof(cell_t) * params[3]);
+
+ return SP_ERROR_NONE;
+}
+
+static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
+{
+ if (!s_curnative || (s_curnative->ctx != pContext))
+ {
+ return pContext->ThrowNativeError("Not called from inside a native function");
+ }
+
+ int out_param = params[1];
+ int fmt_param = params[2];
+ int var_param = params[3];
+
+ /* Validate input */
+ if (out_param && (out_param < 1 || out_param > s_curparams[0]))
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", out_param);
+ }
+ if (fmt_param && (fmt_param < 1 || fmt_param > s_curparams[0]))
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
+ }
+ if (var_param && (var_param < 1 || var_param > s_curparams[0] + 1))
+ {
+ return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
+ }
+
+ /* Get buffer information */
+ int err;
+ char *output_buffer;
+ char *format_buffer;
+
+ if (out_param)
+ {
+ if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+ } else {
+ pContext->LocalToString(params[6], &output_buffer);
+ }
+
+ if (fmt_param)
+ {
+ if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
+ {
+ return err;
+ }
+ } else {
+ pContext->LocalToString(params[7], &format_buffer);
+ }
+
+ /* Get maximum length */
+ size_t maxlen = (size_t)params[4];
+
+ /* Do the format */
+ size_t written = atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
+
+ cell_t *addr;
+ pContext->LocalToPhysAddr(params[5], &addr);
+ *addr = (cell_t)written;
+
+ return s_curcaller->GetContext()->n_err;
+}
+
+//tee hee
+REGISTER_NATIVES(nativeNatives)
+{
+ {"CreateNative", CreateNative},
+ {"GetNativeArray", GetNativeArray},
+ {"GetNativeCell", GetNativeCell},
+ {"GetNativeCellRef", GetNativeCellRef},
+ {"GetNativeString", GetNativeString},
+ {"GetNativeStringLength", GetNativeStringLength},
+ {"FormatNativeString", FormatNativeString},
+ {"ThrowNativeError", ThrowNativeError},
+ {"SetNativeArray", SetNativeArray},
+ {"SetNativeCellRef", SetNativeCellRef},
+ {"SetNativeString", SetNativeString},
+ {NULL, NULL},
+};