core/logic/smn_fakenatives.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 22 09:49:27 2014 -0400 (2014-05-22)
changeset 4378 568f4497ef4a
parent 4069 336e32fe098f
permissions -rw-r--r--
Update CS:GO team score 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 <ISourceMod.h>
    35 #include "common_logic.h"
    36 #include "ShareSys.h"
    37 #include "PluginSys.h"
    38 
    39 using namespace SourceHook;
    40 
    41 static cell_t s_curparams[SP_MAX_EXEC_PARAMS+1];
    42 static FakeNative *s_curnative = NULL;
    43 static IPluginContext *s_curcaller = NULL;
    44 
    45 cell_t FakeNativeRouter(IPluginContext *pContext, const cell_t *params, void *pData)
    46 {
    47 	FakeNative *native = (FakeNative *)pData;
    48 
    49 	/* Check if too many parameters were passed */
    50 	if (params[0] > SP_MAX_EXEC_PARAMS)
    51 	{
    52 		return pContext->ThrowNativeError("Called native with too many parameters (%d>%d)", params[0], SP_MAX_EXEC_PARAMS);
    53 	}
    54 
    55 	/* Check if the native is paused */
    56 	if (native->ctx->GetRuntime()->IsPaused())
    57 	{
    58 		return pContext->ThrowNativeError("Plugin owning this native is currently paused.");
    59 	}
    60 
    61 	CPlugin *pCaller = g_PluginSys.GetPluginByCtx(pContext->GetContext());
    62 
    63 	/* Save any old data on the stack */
    64 	FakeNative *pSaveNative = s_curnative;
    65 	IPluginContext *pSaveCaller = s_curcaller;
    66 	cell_t save_params[SP_MAX_EXEC_PARAMS+1];
    67 	if (pSaveNative != NULL)
    68 	{
    69 		/* Copy all old parameters */
    70 		for (cell_t i=0; i<=s_curparams[0]; i++)
    71 		{
    72 			save_params[i] = s_curparams[i];
    73 		}
    74 	}
    75 
    76 	/* Save the current parameters */
    77 	s_curnative = native;
    78 	s_curcaller = pContext;
    79 	for (cell_t i=0; i<=params[0]; i++)
    80 	{
    81 		s_curparams[i] = params[i];
    82 	}
    83 
    84 	/* Push info and execute. */
    85 	cell_t result = 0;
    86 	native->call->PushCell(pCaller->GetMyHandle());
    87 	native->call->PushCell(params[0]);
    88 	int error;
    89 	if ((error=native->call->Execute(&result)) != SP_ERROR_NONE)
    90 	{
    91 		if (pContext->GetLastNativeError() == SP_ERROR_NONE)
    92 		{
    93 			pContext->ThrowNativeErrorEx(error, "Error encountered while processing a dynamic native");
    94 		}
    95 	}
    96 
    97 	/* Restore everything from the stack if necessary */
    98 	s_curnative = pSaveNative;
    99 	s_curcaller = pSaveCaller;
   100 	if (pSaveNative != NULL)
   101 	{
   102 		for (cell_t i=0; i<=save_params[0]; i++)
   103 		{
   104 			s_curparams[i] = save_params[i];
   105 		}
   106 	}
   107 
   108 	return result;
   109 }
   110 
   111 static cell_t CreateNative(IPluginContext *pContext, const cell_t *params)
   112 {
   113 	char *name;
   114 	CPlugin *pPlugin;
   115 
   116 	pContext->LocalToString(params[1], &name);
   117 
   118 	IPluginFunction *pFunction = pContext->GetFunctionById(params[2]);
   119 	if (!pFunction)
   120 	{
   121 		return pContext->ThrowNativeError("Function %x is not a valid function", params[2]);
   122 	}
   123 
   124 	pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
   125 
   126 	if (!pPlugin->AddFakeNative(pFunction, name, FakeNativeRouter))
   127 	{
   128 		return pContext->ThrowNativeError("Fatal error creating dynamic native!");
   129 	}
   130 
   131 	return 1;
   132 }
   133 
   134 static cell_t ThrowNativeError(IPluginContext *pContext, const cell_t *params)
   135 {
   136 	if (!s_curnative || (s_curnative->ctx != pContext))
   137 	{
   138 		return pContext->ThrowNativeError("Not called from inside a native function");
   139 	}
   140 
   141 	g_pSM->SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   142 
   143 	char buffer[512];
   144 	g_pSM->FormatString(buffer, sizeof(buffer), pContext, params, 2);
   145 
   146 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   147 	{
   148 		s_curcaller->ThrowNativeError("Error encountered while processing a dynamic native");
   149 	} else {
   150 		s_curcaller->ThrowNativeErrorEx(params[1], "%s", buffer);
   151 	}
   152 
   153 	return 0;
   154 }
   155 
   156 static cell_t GetNativeStringLength(IPluginContext *pContext, const cell_t *params)
   157 {
   158 	if (!s_curnative || (s_curnative->ctx != pContext))
   159 	{
   160 		return pContext->ThrowNativeError("Not called from inside a native function");
   161 	}
   162 
   163 	cell_t param = params[1];
   164 	if (param < 1 || param > s_curparams[0])
   165 	{
   166 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   167 	}
   168 
   169 	int err;
   170 	char *str;
   171 	if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
   172 	{
   173 		return err;
   174 	}
   175 
   176 	cell_t *addr;
   177 	pContext->LocalToPhysAddr(params[2], &addr);
   178 	*addr = (cell_t)strlen(str);
   179 
   180 	return SP_ERROR_NONE;
   181 }
   182 
   183 static cell_t GetNativeString(IPluginContext *pContext, const cell_t *params)
   184 {
   185 	if (!s_curnative || (s_curnative->ctx != pContext))
   186 	{
   187 		return pContext->ThrowNativeError("Not called from inside a native function");
   188 	}
   189 
   190 	cell_t param = params[1];
   191 	if (param < 1 || param > s_curparams[0])
   192 	{
   193 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   194 	}
   195 
   196 	int err;
   197 	char *str;
   198 	if ((err=s_curcaller->LocalToString(s_curparams[param], &str)) != SP_ERROR_NONE)
   199 	{
   200 		return err;
   201 	}
   202 
   203 	size_t bytes = 0;
   204 	pContext->StringToLocalUTF8(params[2], params[3], str, &bytes);
   205 
   206 	cell_t *addr;
   207 	pContext->LocalToPhysAddr(params[4], &addr);
   208 	*addr = (cell_t)bytes;
   209 
   210 	return SP_ERROR_NONE;
   211 }
   212 
   213 static cell_t SetNativeString(IPluginContext *pContext, const cell_t *params)
   214 {
   215 	if (!s_curnative || (s_curnative->ctx != pContext))
   216 	{
   217 		return pContext->ThrowNativeError("Not called from inside a native function");
   218 	}
   219 
   220 	cell_t param = params[1];
   221 	if (param < 1 || param > s_curparams[0])
   222 	{
   223 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   224 	}
   225 
   226 	char *str;
   227 	pContext->LocalToString(params[2], &str);
   228 
   229 	int err;
   230 	size_t bytes = 0;
   231 	if (params[4])
   232 	{
   233 		err = s_curcaller->StringToLocalUTF8(s_curparams[param], params[3], str, &bytes);
   234 	} else {
   235 		err = s_curcaller->StringToLocal(s_curparams[param], params[3], str);
   236 		/* Eww */
   237 		bytes = strlen(str);
   238 		if (bytes >= (size_t)params[3])
   239 		{
   240 			bytes = params[3] - 1;
   241 		}
   242 	}
   243 
   244 	if (err != SP_ERROR_NONE)
   245 	{
   246 		return err;
   247 	}
   248 
   249 	cell_t *addr;
   250 	pContext->LocalToPhysAddr(params[5], &addr);
   251 	*addr = (cell_t)bytes;
   252 
   253 	return SP_ERROR_NONE;
   254 }
   255 
   256 static cell_t GetNativeCell(IPluginContext *pContext, const cell_t *params)
   257 {
   258 	if (!s_curnative || (s_curnative->ctx != pContext))
   259 	{
   260 		return pContext->ThrowNativeError("Not called from inside a native function");
   261 	}
   262 
   263 	cell_t param = params[1];
   264 	if (param < 1 || param > s_curparams[0])
   265 	{
   266 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   267 	}
   268 
   269 	return s_curparams[param];
   270 }
   271 
   272 static cell_t GetNativeCellRef(IPluginContext *pContext, const cell_t *params)
   273 {
   274 	if (!s_curnative || (s_curnative->ctx != pContext))
   275 	{
   276 		return pContext->ThrowNativeError("Not called from inside a native function");
   277 	}
   278 
   279 	cell_t param = params[1];
   280 	if (param < 1 || param > s_curparams[0])
   281 	{
   282 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   283 	}
   284 
   285 	cell_t *addr;
   286 	if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
   287 	{
   288 		return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
   289 	}
   290 
   291 	return *addr;
   292 }
   293 
   294 static cell_t SetNativeCellRef(IPluginContext *pContext, const cell_t *params)
   295 {
   296 	if (!s_curnative || (s_curnative->ctx != pContext))
   297 	{
   298 		return pContext->ThrowNativeError("Not called from inside a native function");
   299 	}
   300 
   301 	cell_t param = params[1];
   302 	if (param < 1 || param > s_curparams[0])
   303 	{
   304 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   305 	}
   306 
   307 	cell_t *addr;
   308 	if (s_curcaller->LocalToPhysAddr(s_curparams[param], &addr) != SP_ERROR_NONE)
   309 	{
   310 		return s_curcaller->ThrowNativeErrorEx(SP_ERROR_INVALID_ADDRESS, "Invalid address value");
   311 	}
   312 
   313 	*addr = params[2];
   314 
   315 	return 1;
   316 }
   317 
   318 static cell_t GetNativeArray(IPluginContext *pContext, const cell_t *params)
   319 {
   320 	if (!s_curnative || (s_curnative->ctx != pContext))
   321 	{
   322 		return pContext->ThrowNativeError("Not called from inside a native function");
   323 	}
   324 
   325 	cell_t param = params[1];
   326 	if (param < 1 || param > s_curparams[0])
   327 	{
   328 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   329 	}
   330 
   331 	int err;
   332 	cell_t *addr;
   333 	if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
   334 	{
   335 		return err;
   336 	}
   337 
   338 	cell_t *src;
   339 	pContext->LocalToPhysAddr(params[2], &src);
   340 
   341 	memcpy(src, addr, sizeof(cell_t) * params[3]);
   342 
   343 	return SP_ERROR_NONE;
   344 }
   345 
   346 static cell_t SetNativeArray(IPluginContext *pContext, const cell_t *params)
   347 {
   348 	if (!s_curnative || (s_curnative->ctx != pContext))
   349 	{
   350 		return pContext->ThrowNativeError("Not called from inside a native function");
   351 	}
   352 
   353 	cell_t param = params[1];
   354 	if (param < 1 || param > s_curparams[0])
   355 	{
   356 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", param);
   357 	}
   358 
   359 	int err;
   360 	cell_t *addr;
   361 	if ((err=s_curcaller->LocalToPhysAddr(s_curparams[param], &addr)) != SP_ERROR_NONE)
   362 	{
   363 		return err;
   364 	}
   365 
   366 	cell_t *src;
   367 	pContext->LocalToPhysAddr(params[2], &src);
   368 
   369 	memcpy(addr, src, sizeof(cell_t) * params[3]);
   370 
   371 	return SP_ERROR_NONE;
   372 }
   373 
   374 static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params)
   375 {
   376 	if (!s_curnative || (s_curnative->ctx != pContext))
   377 	{
   378 		return pContext->ThrowNativeError("Not called from inside a native function");
   379 	}
   380 
   381 	int out_param = params[1];
   382 	int fmt_param = params[2];
   383 	int var_param = params[3];
   384 
   385 	/* Validate input */
   386 	if (out_param && (out_param < 1 || out_param > s_curparams[0]))
   387 	{
   388 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", out_param);
   389 	}
   390 	if (fmt_param && (fmt_param < 1 || fmt_param > s_curparams[0]))
   391 	{
   392 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
   393 	}
   394 	if (var_param && (var_param < 1 || var_param > s_curparams[0] + 1))
   395 	{
   396 		return pContext->ThrowNativeErrorEx(SP_ERROR_PARAM, "Invalid parameter number: %d", fmt_param);
   397 	}
   398 
   399 	/* Get buffer information */
   400 	int err;
   401 	char *output_buffer;
   402 	char *format_buffer;
   403 
   404 	if (out_param)
   405 	{
   406 		if ((err=s_curcaller->LocalToString(s_curparams[out_param], &output_buffer)) != SP_ERROR_NONE)
   407 		{
   408 			return err;
   409 		}
   410 	} else {
   411 		pContext->LocalToString(params[6], &output_buffer);
   412 	}
   413 
   414 	if (fmt_param)
   415 	{
   416 		if ((err=s_curcaller->LocalToString(s_curparams[fmt_param], &format_buffer)) != SP_ERROR_NONE)
   417 		{
   418 			return err;
   419 		}
   420 	} else {
   421 		pContext->LocalToString(params[7], &format_buffer);
   422 	}
   423 
   424 	/* Get maximum length */
   425 	size_t maxlen = (size_t)params[4];
   426 
   427 	/* Do the format */
   428 	size_t written = smcore.atcprintf(output_buffer, maxlen, format_buffer, s_curcaller, s_curparams, &var_param);
   429 
   430 	cell_t *addr;
   431 	pContext->LocalToPhysAddr(params[5], &addr);
   432 	*addr = (cell_t)written;
   433 
   434 	return s_curcaller->GetLastNativeError();
   435 }
   436 
   437 //tee hee
   438 REGISTER_NATIVES(nativeNatives)
   439 {
   440 	{"CreateNative",			CreateNative},
   441 	{"GetNativeArray",			GetNativeArray},
   442 	{"GetNativeCell",			GetNativeCell},
   443 	{"GetNativeCellRef",		GetNativeCellRef},
   444 	{"GetNativeString",			GetNativeString},
   445 	{"GetNativeStringLength",	GetNativeStringLength},
   446 	{"FormatNativeString",		FormatNativeString},
   447 	{"ThrowNativeError",		ThrowNativeError},
   448 	{"SetNativeArray",			SetNativeArray},
   449 	{"SetNativeCellRef",		SetNativeCellRef},
   450 	{"SetNativeString",			SetNativeString},
   451 	{NULL,						NULL},
   452 };