core/logic/smn_fakenatives.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Aug 14 14:20:57 2013 -0400 (2013-08-14)
changeset 4008 490b01aa0683
parent 3946 0fe6ce0499d1
child 4069 336e32fe098f
permissions -rw-r--r--
Updated some CS:GO gamedata.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include <sh_list.h>
    33 #include <sh_string.h>
    34 #include <sm_trie_tpl.h>
    35 #include <ISourceMod.h>
    36 #include "common_logic.h"
    37 #include "ShareSys.h"
    38 #include "PluginSys.h"
    39 
    40 using namespace SourceHook;
    41 
    42 static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1];
    43 static FakeNative *s_curnative = NULL;
    44 static IPluginContext *s_curcaller = NULL;
    45 
    46 cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pData)
    47 {
    48 	FakeNative *native = (FakeNative *)pData;
    49 
    50 	/* Check if too many parameters were passed */
    51 	if (params[0] > SP_MAX_EXEC_PARAMS)
    52 	{
    53 		return pContext->ThrowNativeError("Called native with too many parameters (%d>%d)", params[0], SP_MAX_EXEC_PARAMS);
    54 	}
    55 
    56 	/* Check if the native is paused */
    57 	if (native->ctx->GetRuntime()->IsPaused())
    58 	{
    59 		return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
    60 	}
    61 
    62 	CPlugin *pCaller = g_PluginSys.GetPluginByCtx(pContext->GetContext());
    63 
    64 	/* Save any old data on the stack */
    65 	FakeNative *pSaveNative = s_curnative;
    66 	IPluginContext *pSaveCaller = s_curcaller;
    67 	cell_t save_params[SP_MAX_EXEC_PARAMS+1];
    68 	if (pSaveNative != NULL)
    69 	{
    70 		/* Copy all old parameters */
    71 		for (cell_t i=0; i<=s_curparams[0]; i++)
    72 		{
    73 			save_params[i] = s_curparams[i];
    74 		}
    75 	}
    76 
    77 	/* Save the current parameters */
    78 	s_curnative = native;
    79 	s_curcaller = pContext;
    80 	for (cell_t i=0; i<=params[0]; i++)
    81 	{
    82 		s_curparams[i] = params[i];
    83 	}
    84 
    85 	/* Push info and execute. */
    86 	cell_t result = 0;
    87 	native->call->PushCell(pCaller->GetMyHandle());
    88 	native->call->PushCell(params[0]);
    89 	int error;
    90 	if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
    91 	{
    92 		if (pContext->GetLastNativeError() == SP_ERROR_NONE)
    93 		{
    94 			pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
    95 		}
    96 	}
    97 
    98 	/* Restore everything from the stack if necessary */
    99 	s_curnative = pSaveNative;
   100 	s_curcaller = pSaveCaller;
   101 	if (pSaveNative != NULL)
   102 	{
   103 		for (cell_t i=0; i<=save_params[0]; i++)
   104 		{
   105 			s_curparams[i] = save_params[i];
   106 		}
   107 	}
   108 
   109 	return result;
   110 }
   111 
   112 static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
   113 {
   114 	char *name;
   115 	CPlugin *pPlugin;
   116 
   117 	pContext->LocalToString(params[1], &name);
   118 
   119 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
   120 	if (!pFunction)
   121 	{
   122 		return pContext->ThrowNativeError("Function %x is not a valid function", params[2]);
   123 	}
   124 
   125 	pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   126 
   127 	if (!pPlugin->AddFakeNative(pFunction, name, FakeNativeRouter))
   128 	{
   129 		return pContext->ThrowNativeError("Fatal error creating dynamic native!");
   130 	}
   131 
   132 	return 1;
   133 }
   134 
   135 static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
   136 {
   137 	if (!s_curnative || (s_curnative->ctx != pContext))
   138 	{
   139 		return pContext->ThrowNativeError("Not called from inside a native function");
   140 	}
   141 
   142 	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   143 
   144 	char buffer[512];
   145 	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
   146 
   147 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   148 	{
   149 		s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
   150 	} else {
   151 		s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
   152 	}
   153 
   154 	return 0;
   155 }
   156 
   157 static cell_t GetNativeStringLength(IPluginContext *pContext, const cell_t *params)
   158 {
   159 	if (!s_curnative || (s_curnative->ctx != pContext))
   160 	{
   161 		return pContext->ThrowNativeError("Not called from inside a native function");
   162 	}
   163 
   164 	cell_t param = params[1];
   165 	if (param < 1 || param > s_curparams[0])
   166 	{
   167 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   168 	}
   169 
   170 	int err;
   171 	char *str;
   172 	if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
   173 	{
   174 		return err;
   175 	}
   176 
   177 	cell_t *addr;
   178 	pContext->LocalToPhysAddr(params[2], &addr);
   179 	*addr = (cell_t)strlen(str);
   180 
   181 	return SP_ERROR_NONE;
   182 }
   183 
   184 static cell_t GetNativeString(IPluginContext *pContext, const cell_t *params)
   185 {
   186 	if (!s_curnative || (s_curnative->ctx != pContext))
   187 	{
   188 		return pContext->ThrowNativeError("Not called from inside a native function");
   189 	}
   190 
   191 	cell_t param = params[1];
   192 	if (param < 1 || param > s_curparams[0])
   193 	{
   194 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   195 	}
   196 
   197 	int err;
   198 	char *str;
   199 	if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
   200 	{
   201 		return err;
   202 	}
   203 
   204 	size_t bytes = 0;
   205 	pContext->StringToLocalUTF8(params[2], params[3], str, &bytes);
   206 
   207 	cell_t *addr;
   208 	pContext->LocalToPhysAddr(params[4], &addr);
   209 	*addr = (cell_t)bytes;
   210 
   211 	return SP_ERROR_NONE;
   212 }
   213 
   214 static cell_t SetNativeString(IPluginContext *pContext, const cell_t *params)
   215 {
   216 	if (!s_curnative || (s_curnative->ctx != pContext))
   217 	{
   218 		return pContext->ThrowNativeError("Not called from inside a native function");
   219 	}
   220 
   221 	cell_t param = params[1];
   222 	if (param < 1 || param > s_curparams[0])
   223 	{
   224 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   225 	}
   226 
   227 	char *str;
   228 	pContext->LocalToString(params[2], &str);
   229 
   230 	int err;
   231 	size_t bytes = 0;
   232 	if (params[4])
   233 	{
   234 		err = s_curcaller->StringToLocalUTF8(s_curparams[param], params[3], str, &bytes);
   235 	} else {
   236 		err = s_curcaller->StringToLocal(s_curparams[param], params[3], str);
   237 		/* Eww */
   238 		bytes = strlen(str);
   239 		if (bytes >= (size_t)params[3])
   240 		{
   241 			bytes = params[3] - 1;
   242 		}
   243 	}
   244 
   245 	if (err != SP_ERROR_NONE)
   246 	{
   247 		return err;
   248 	}
   249 
   250 	cell_t *addr;
   251 	pContext->LocalToPhysAddr(params[5], &addr);
   252 	*addr = (cell_t)bytes;
   253 
   254 	return SP_ERROR_NONE;
   255 }
   256 
   257 static cell_t GetNativeCell(IPluginContext *pContext, const cell_t *params)
   258 {
   259 	if (!s_curnative || (s_curnative->ctx != pContext))
   260 	{
   261 		return pContext->ThrowNativeError("Not called from inside a native function");
   262 	}
   263 
   264 	cell_t param = params[1];
   265 	if (param < 1 || param > s_curparams[0])
   266 	{
   267 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   268 	}
   269 
   270 	return s_curparams[param];
   271 }
   272 
   273 static cell_t GetNativeCellRef(IPluginContext *pContext, const cell_t *params)
   274 {
   275 	if (!s_curnative || (s_curnative->ctx != pContext))
   276 	{
   277 		return pContext->ThrowNativeError("Not called from inside a native function");
   278 	}
   279 
   280 	cell_t param = params[1];
   281 	if (param < 1 || param > s_curparams[0])
   282 	{
   283 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   284 	}
   285 
   286 	cell_t *addr;
   287 	if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
   288 	{
   289 		return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
   290 	}
   291 
   292 	return *addr;
   293 }
   294 
   295 static cell_t SetNativeCellRef(IPluginContext *pContext, const cell_t *params)
   296 {
   297 	if (!s_curnative || (s_curnative->ctx != pContext))
   298 	{
   299 		return pContext->ThrowNativeError("Not called from inside a native function");
   300 	}
   301 
   302 	cell_t param = params[1];
   303 	if (param < 1 || param > s_curparams[0])
   304 	{
   305 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   306 	}
   307 
   308 	cell_t *addr;
   309 	if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
   310 	{
   311 		return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
   312 	}
   313 
   314 	*addr = params[2];
   315 
   316 	return 1;
   317 }
   318 
   319 static cell_t GetNativeArray(IPluginContext *pContext, const cell_t *params)
   320 {
   321 	if (!s_curnative || (s_curnative->ctx != pContext))
   322 	{
   323 		return pContext->ThrowNativeError("Not called from inside a native function");
   324 	}
   325 
   326 	cell_t param = params[1];
   327 	if (param < 1 || param > s_curparams[0])
   328 	{
   329 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   330 	}
   331 
   332 	int err;
   333 	cell_t *addr;
   334 	if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
   335 	{
   336 		return err;
   337 	}
   338 
   339 	cell_t *src;
   340 	pContext->LocalToPhysAddr(params[2], &src);
   341 
   342 	memcpy(src, addr, sizeof(cell_t) * params[3]);
   343 
   344 	return SP_ERROR_NONE;
   345 }
   346 
   347 static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params)
   348 {
   349 	if (!s_curnative || (s_curnative->ctx != pContext))
   350 	{
   351 		return pContext->ThrowNativeError("Not called from inside a native function");
   352 	}
   353 
   354 	cell_t param = params[1];
   355 	if (param < 1 || param > s_curparams[0])
   356 	{
   357 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   358 	}
   359 
   360 	int err;
   361 	cell_t *addr;
   362 	if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
   363 	{
   364 		return err;
   365 	}
   366 
   367 	cell_t *src;
   368 	pContext->LocalToPhysAddr(params[2], &src);
   369 
   370 	memcpy(addr, src, sizeof(cell_t) * params[3]);
   371 
   372 	return SP_ERROR_NONE;
   373 }
   374 
   375 static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
   376 {
   377 	if (!s_curnative || (s_curnative->ctx != pContext))
   378 	{
   379 		return pContext->ThrowNativeError("Not called from inside a native function");
   380 	}
   381 
   382 	int out_param = params[1];
   383 	int fmt_param = params[2];
   384 	int var_param = params[3];
   385 
   386 	/* Validate input */
   387 	if (out_param && (out_param < 1 || out_param > s_curparams[0]))
   388 	{
   389 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", out_param);
   390 	}
   391 	if (fmt_param && (fmt_param < 1 || fmt_param > s_curparams[0]))
   392 	{
   393 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
   394 	}
   395 	if (var_param && (var_param < 1 || var_param > s_curparams[0] + 1))
   396 	{
   397 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
   398 	}
   399 
   400 	/* Get buffer information */
   401 	int err;
   402 	char *output_buffer;
   403 	char *format_buffer;
   404 
   405 	if (out_param)
   406 	{
   407 		if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
   408 		{
   409 			return err;
   410 		}
   411 	} else {
   412 		pContext->LocalToString(params[6], &output_buffer);
   413 	}
   414 
   415 	if (fmt_param)
   416 	{
   417 		if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
   418 		{
   419 			return err;
   420 		}
   421 	} else {
   422 		pContext->LocalToString(params[7], &format_buffer);
   423 	}
   424 
   425 	/* Get maximum length */
   426 	size_t maxlen = (size_t)params[4];
   427 
   428 	/* Do the format */
   429 	size_t written = smcore.atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
   430 
   431 	cell_t *addr;
   432 	pContext->LocalToPhysAddr(params[5], &addr);
   433 	*addr = (cell_t)written;
   434 
   435 	return s_curcaller->GetLastNativeError();
   436 }
   437 
   438 //tee hee
   439 REGISTER_NATIVES(nativeNatives)
   440 {
   441 	{"CreateNative",			CreateNative},
   442 	{"GetNativeArray",			GetNativeArray},
   443 	{"GetNativeCell",			GetNativeCell},
   444 	{"GetNativeCellRef",		GetNativeCellRef},
   445 	{"GetNativeString",			GetNativeString},
   446 	{"GetNativeStringLength",	GetNativeStringLength},
   447 	{"FormatNativeString",		FormatNativeString},
   448 	{"ThrowNativeError",		ThrowNativeError},
   449 	{"SetNativeArray",			SetNativeArray},
   450 	{"SetNativeCellRef",		SetNativeCellRef},
   451 	{"SetNativeString",			SetNativeString},
   452 	{NULL,						NULL},
   453 };