1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_fakenatives.cpp Mon Mar 12 07:08:05 2007 +0000
1.3 @@ -0,0 +1,430 @@
1.4 +/**
1.5 + * ===============================================================
1.6 + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.7 + * ===============================================================
1.8 + *
1.9 + * This file is not open source and may not be copied without explicit
1.10 + * written permission of AlliedModders LLC. This file may not be redistributed
1.11 + * in whole or significant part.
1.12 + * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
1.13 + *
1.14 + * Version: $Id$
1.15 + */
1.16 +
1.17 +#include <sh_list.h>
1.18 +#include <sh_string.h>
1.19 +#include "sm_trie.h"
1.20 +#include "sm_globals.h"
1.21 +#include "PluginSys.h"
1.22 +#include "sourcemod.h"
1.23 +#include "sm_stringutil.h"
1.24 +
1.25 +using namespace SourceHook;
1.26 +
1.27 +static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1];
1.28 +static FakeNative *s_curnative = NULL;
1.29 +static IPluginContext *s_curcaller = NULL;
1.30 +
1.31 +cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pData)
1.32 +{
1.33 + FakeNative *native = (FakeNative *)pData;
1.34 +
1.35 + /* Check if too many parameters were passed */
1.36 + if (params[0] > SP_MAX_EXEC_PARAMS)
1.37 + {
1.38 + return pContext->ThrowNativeError("Called native with too many parameters (%d>%d)", params[9], SP_MAX_EXEC_PARAMS);
1.39 + }
1.40 +
1.41 + /* Check if the native is paused */
1.42 + sp_context_t *pNativeCtx = native->ctx->GetContext();
1.43 + if ((pNativeCtx->flags & SPFLAG_PLUGIN_PAUSED) == SPFLAG_PLUGIN_PAUSED)
1.44 + {
1.45 + return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
1.46 + }
1.47 +
1.48 + CPlugin *pCaller = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.49 +
1.50 + /* Save any old data on the stack */
1.51 + FakeNative *pSaveNative = s_curnative;
1.52 + IPluginContext *pSaveCaller = s_curcaller;
1.53 + cell_t save_params[SP_MAX_EXEC_PARAMS+1];
1.54 + if (pSaveNative != NULL)
1.55 + {
1.56 + /* Copy all old parameters */
1.57 + for (cell_t i=0; i<=s_curparams[0]; i++)
1.58 + {
1.59 + save_params[i] = s_curparams[i];
1.60 + }
1.61 + }
1.62 +
1.63 + /* Save the current parameters */
1.64 + s_curnative = native;
1.65 + s_curcaller = pContext;
1.66 + for (cell_t i=0; i<=params[0]; i++)
1.67 + {
1.68 + s_curparams[i] = params[i];
1.69 + }
1.70 +
1.71 + /* Push info and execute. */
1.72 + cell_t result = 0;
1.73 + native->call->PushCell(pCaller->GetMyHandle());
1.74 + native->call->PushCell(params[0]);
1.75 + if (native->call->Execute(&result) != SP_ERROR_NONE)
1.76 + {
1.77 + if (pContext->GetContext()->n_err == SP_ERROR_NONE)
1.78 + {
1.79 + pContext->ThrowNativeError("Error encountered while processing a dynamic native");
1.80 + }
1.81 + }
1.82 +
1.83 + /* Restore everything from the stack if necessary */
1.84 + if (pSaveNative != NULL)
1.85 + {
1.86 + s_curnative = pSaveNative;
1.87 + s_curcaller = pSaveCaller;
1.88 + for (cell_t i=0; i<=save_params[0]; i++)
1.89 + {
1.90 + s_curparams[i] = save_params[i];
1.91 + }
1.92 + }
1.93 +
1.94 + return result;
1.95 +}
1.96 +
1.97 +static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
1.98 +{
1.99 + char *name;
1.100 + pContext->LocalToString(params[1], &name);
1.101 +
1.102 + IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
1.103 + if (!pFunction)
1.104 + {
1.105 + return pContext->ThrowNativeError("Function %x is not a valid function", params[2]);
1.106 + }
1.107 +
1.108 + if (!g_PluginSys.AddFakeNative(pFunction, name, FakeNativeRouter))
1.109 + {
1.110 + return pContext->ThrowNativeError("Fatal error creating dynamic native!");
1.111 + }
1.112 +
1.113 + return 1;
1.114 +}
1.115 +
1.116 +static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
1.117 +{
1.118 + if (!s_curnative || (s_curnative->ctx != pContext))
1.119 + {
1.120 + return pContext->ThrowNativeError("Not called from inside a native function");
1.121 + }
1.122 +
1.123 + char buffer[512];
1.124 +
1.125 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.126 +
1.127 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.128 + {
1.129 + s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
1.130 + } else {
1.131 + s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
1.132 + }
1.133 +
1.134 + return 0;
1.135 +}
1.136 +
1.137 +static cell_t GetNativeStringLength(IPluginContext *pContext, const cell_t *params)
1.138 +{
1.139 + if (!s_curnative || (s_curnative->ctx != pContext))
1.140 + {
1.141 + return pContext->ThrowNativeError("Not called from inside a native function");
1.142 + }
1.143 +
1.144 + cell_t param = params[1];
1.145 + if (param < 1 || param > s_curparams[0])
1.146 + {
1.147 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.148 + }
1.149 +
1.150 + int err;
1.151 + char *str;
1.152 + if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
1.153 + {
1.154 + return err;
1.155 + }
1.156 +
1.157 + cell_t *addr;
1.158 + pContext->LocalToPhysAddr(params[2], &addr);
1.159 + *addr = (cell_t)strlen(str);
1.160 +
1.161 + return SP_ERROR_NONE;
1.162 +}
1.163 +
1.164 +static cell_t GetNativeString(IPluginContext *pContext, const cell_t *params)
1.165 +{
1.166 + if (!s_curnative || (s_curnative->ctx != pContext))
1.167 + {
1.168 + return pContext->ThrowNativeError("Not called from inside a native function");
1.169 + }
1.170 +
1.171 + cell_t param = params[1];
1.172 + if (param < 1 || param > s_curparams[0])
1.173 + {
1.174 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.175 + }
1.176 +
1.177 + int err;
1.178 + char *str;
1.179 + if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
1.180 + {
1.181 + return err;
1.182 + }
1.183 +
1.184 + size_t bytes = 0;
1.185 + pContext->StringToLocalUTF8(params[2], params[3], str, &bytes);
1.186 +
1.187 + cell_t *addr;
1.188 + pContext->LocalToPhysAddr(params[4], &addr);
1.189 + *addr = (cell_t)bytes;
1.190 +
1.191 + return SP_ERROR_NONE;
1.192 +}
1.193 +
1.194 +static cell_t SetNativeString(IPluginContext *pContext, const cell_t *params)
1.195 +{
1.196 + if (!s_curnative || (s_curnative->ctx != pContext))
1.197 + {
1.198 + return pContext->ThrowNativeError("Not called from inside a native function");
1.199 + }
1.200 +
1.201 + cell_t param = params[1];
1.202 + if (param < 1 || param > s_curparams[0])
1.203 + {
1.204 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.205 + }
1.206 +
1.207 + char *str;
1.208 + pContext->LocalToString(params[2], &str);
1.209 +
1.210 + int err;
1.211 + size_t bytes = 0;
1.212 + if (params[4])
1.213 + {
1.214 + err = s_curcaller->StringToLocalUTF8(s_curparams[param], params[3], str, &bytes);
1.215 + } else {
1.216 + err = s_curcaller->StringToLocal(s_curparams[param], params[3], str);
1.217 + /* Eww */
1.218 + bytes = strlen(str);
1.219 + if (bytes >= (size_t)params[3])
1.220 + {
1.221 + bytes = params[3] - 1;
1.222 + }
1.223 + }
1.224 +
1.225 + if (err != SP_ERROR_NONE)
1.226 + {
1.227 + return err;
1.228 + }
1.229 +
1.230 + cell_t *addr;
1.231 + pContext->LocalToPhysAddr(params[5], &addr);
1.232 + *addr = (cell_t)bytes;
1.233 +
1.234 + return SP_ERROR_NONE;
1.235 +}
1.236 +
1.237 +static cell_t GetNativeCell(IPluginContext *pContext, const cell_t *params)
1.238 +{
1.239 + if (!s_curnative || (s_curnative->ctx != pContext))
1.240 + {
1.241 + return pContext->ThrowNativeError("Not called from inside a native function");
1.242 + }
1.243 +
1.244 + cell_t param = params[1];
1.245 + if (param < 1 || param > s_curparams[0])
1.246 + {
1.247 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.248 + }
1.249 +
1.250 + return s_curparams[param];
1.251 +}
1.252 +
1.253 +static cell_t GetNativeCellRef(IPluginContext *pContext, const cell_t *params)
1.254 +{
1.255 + if (!s_curnative || (s_curnative->ctx != pContext))
1.256 + {
1.257 + return pContext->ThrowNativeError("Not called from inside a native function");
1.258 + }
1.259 +
1.260 + cell_t param = params[1];
1.261 + if (param < 1 || param > s_curparams[0])
1.262 + {
1.263 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.264 + }
1.265 +
1.266 + cell_t *addr;
1.267 + if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
1.268 + {
1.269 + return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
1.270 + }
1.271 +
1.272 + return *addr;
1.273 +}
1.274 +
1.275 +static cell_t SetNativeCellRef(IPluginContext *pContext, const cell_t *params)
1.276 +{
1.277 + if (!s_curnative || (s_curnative->ctx != pContext))
1.278 + {
1.279 + return pContext->ThrowNativeError("Not called from inside a native function");
1.280 + }
1.281 +
1.282 + cell_t param = params[1];
1.283 + if (param < 1 || param > s_curparams[0])
1.284 + {
1.285 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.286 + }
1.287 +
1.288 + cell_t *addr;
1.289 + if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
1.290 + {
1.291 + return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
1.292 + }
1.293 +
1.294 + *addr = params[2];
1.295 +
1.296 + return 1;
1.297 +}
1.298 +
1.299 +static cell_t GetNativeArray(IPluginContext *pContext, const cell_t *params)
1.300 +{
1.301 + if (!s_curnative || (s_curnative->ctx != pContext))
1.302 + {
1.303 + return pContext->ThrowNativeError("Not called from inside a native function");
1.304 + }
1.305 +
1.306 + cell_t param = params[1];
1.307 + if (param < 1 || param > s_curparams[0])
1.308 + {
1.309 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.310 + }
1.311 +
1.312 + int err;
1.313 + cell_t *addr;
1.314 + if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
1.315 + {
1.316 + return err;
1.317 + }
1.318 +
1.319 + cell_t *src;
1.320 + pContext->LocalToPhysAddr(params[2], &src);
1.321 +
1.322 + memcpy(src, addr, sizeof(cell_t) * params[3]);
1.323 +
1.324 + return SP_ERROR_NONE;
1.325 +}
1.326 +
1.327 +static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params)
1.328 +{
1.329 + if (!s_curnative || (s_curnative->ctx != pContext))
1.330 + {
1.331 + return pContext->ThrowNativeError("Not called from inside a native function");
1.332 + }
1.333 +
1.334 + cell_t param = params[1];
1.335 + if (param < 1 || param > s_curparams[0])
1.336 + {
1.337 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
1.338 + }
1.339 +
1.340 + int err;
1.341 + cell_t *addr;
1.342 + if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
1.343 + {
1.344 + return err;
1.345 + }
1.346 +
1.347 + cell_t *src;
1.348 + pContext->LocalToPhysAddr(params[2], &src);
1.349 +
1.350 + memcpy(addr, src, sizeof(cell_t) * params[3]);
1.351 +
1.352 + return SP_ERROR_NONE;
1.353 +}
1.354 +
1.355 +static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
1.356 +{
1.357 + if (!s_curnative || (s_curnative->ctx != pContext))
1.358 + {
1.359 + return pContext->ThrowNativeError("Not called from inside a native function");
1.360 + }
1.361 +
1.362 + int out_param = params[1];
1.363 + int fmt_param = params[2];
1.364 + int var_param = params[3];
1.365 +
1.366 + /* Validate input */
1.367 + if (out_param && (out_param < 1 || out_param > s_curparams[0]))
1.368 + {
1.369 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", out_param);
1.370 + }
1.371 + if (fmt_param && (fmt_param < 1 || fmt_param > s_curparams[0]))
1.372 + {
1.373 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
1.374 + }
1.375 + if (var_param && (var_param < 1 || var_param > s_curparams[0] + 1))
1.376 + {
1.377 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
1.378 + }
1.379 +
1.380 + /* Get buffer information */
1.381 + int err;
1.382 + char *output_buffer;
1.383 + char *format_buffer;
1.384 +
1.385 + if (out_param)
1.386 + {
1.387 + if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
1.388 + {
1.389 + return err;
1.390 + }
1.391 + } else {
1.392 + pContext->LocalToString(params[6], &output_buffer);
1.393 + }
1.394 +
1.395 + if (fmt_param)
1.396 + {
1.397 + if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
1.398 + {
1.399 + return err;
1.400 + }
1.401 + } else {
1.402 + pContext->LocalToString(params[7], &format_buffer);
1.403 + }
1.404 +
1.405 + /* Get maximum length */
1.406 + size_t maxlen = (size_t)params[4];
1.407 +
1.408 + /* Do the format */
1.409 + size_t written = atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
1.410 +
1.411 + cell_t *addr;
1.412 + pContext->LocalToPhysAddr(params[5], &addr);
1.413 + *addr = (cell_t)written;
1.414 +
1.415 + return s_curcaller->GetContext()->n_err;
1.416 +}
1.417 +
1.418 +//tee hee
1.419 +REGISTER_NATIVES(nativeNatives)
1.420 +{
1.421 + {"CreateNative", CreateNative},
1.422 + {"GetNativeArray", GetNativeArray},
1.423 + {"GetNativeCell", GetNativeCell},
1.424 + {"GetNativeCellRef", GetNativeCellRef},
1.425 + {"GetNativeString", GetNativeString},
1.426 + {"GetNativeStringLength", GetNativeStringLength},
1.427 + {"FormatNativeString", FormatNativeString},
1.428 + {"ThrowNativeError", ThrowNativeError},
1.429 + {"SetNativeArray", SetNativeArray},
1.430 + {"SetNativeCellRef", SetNativeCellRef},
1.431 + {"SetNativeString", SetNativeString},
1.432 + {NULL, NULL},
1.433 +};