1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_functions.cpp Sun Jul 06 04:49:55 2008 +0000
1.3 @@ -0,0 +1,609 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "sm_globals.h"
1.36 +#include "PluginSys.h"
1.37 +#include "ForwardSys.h"
1.38 +#include "HandleSys.h"
1.39 +
1.40 +HandleType_t g_GlobalFwdType = 0;
1.41 +HandleType_t g_PrivateFwdType = 0;
1.42 +
1.43 +static bool s_CallStarted = false;
1.44 +static ICallable *s_pCallable = NULL;
1.45 +static IPluginFunction *s_pFunction = NULL;
1.46 +static IForward *s_pForward = NULL;
1.47 +
1.48 +class ForwardNativeHelpers :
1.49 + public SMGlobalClass,
1.50 + public IHandleTypeDispatch
1.51 +{
1.52 +public:
1.53 + void OnSourceModAllInitialized()
1.54 + {
1.55 + HandleAccess sec;
1.56 +
1.57 + /* Set GlobalFwd handle access security */
1.58 + g_HandleSys.InitAccessDefaults(NULL, &sec);
1.59 + sec.access[HandleAccess_Read] = 0;
1.60 + sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
1.61 +
1.62 + /* Create 'GlobalFwd' handle type */
1.63 + g_GlobalFwdType = g_HandleSys.CreateType("GlobalFwd", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.64 +
1.65 + /* Private forwards are cloneable */
1.66 + sec.access[HandleAccess_Clone] = 0;
1.67 +
1.68 + /* Create 'PrivateFwd' handle type */
1.69 + g_PrivateFwdType = g_HandleSys.CreateType("PrivateFwd", this, g_GlobalFwdType, NULL, &sec, g_pCoreIdent, NULL);
1.70 + }
1.71 +
1.72 + void OnSourceModShutdown()
1.73 + {
1.74 + g_HandleSys.RemoveType(g_PrivateFwdType, g_pCoreIdent);
1.75 + g_HandleSys.RemoveType(g_GlobalFwdType, g_pCoreIdent);
1.76 + }
1.77 +
1.78 + void OnHandleDestroy(HandleType_t type, void *object)
1.79 + {
1.80 + IForward *pForward = static_cast<IForward *>(object);
1.81 +
1.82 + g_Forwards.ReleaseForward(pForward);
1.83 + }
1.84 +
1.85 + bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.86 + {
1.87 + *pSize = sizeof(CForward) + (((IForward *)object)->GetFunctionCount() * 12);
1.88 + return true;
1.89 + }
1.90 +} g_ForwardNativeHelpers;
1.91 +
1.92 +
1.93 +/* Turn a public index into a function ID */
1.94 +inline funcid_t PublicIndexToFuncId(uint32_t idx)
1.95 +{
1.96 + return (idx << 1) | (1 << 0);
1.97 +}
1.98 +
1.99 +/* Reset global function/forward call variables */
1.100 +inline void ResetCall()
1.101 +{
1.102 + s_CallStarted = false;
1.103 + s_pFunction = NULL;
1.104 + s_pForward = NULL;
1.105 + s_pCallable = NULL;
1.106 +}
1.107 +
1.108 +static cell_t sm_GetFunctionByName(IPluginContext *pContext, const cell_t *params)
1.109 +{
1.110 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.111 + HandleError err;
1.112 + char *name;
1.113 + uint32_t idx;
1.114 + IPlugin *pPlugin;
1.115 +
1.116 + if (hndl == 0)
1.117 + {
1.118 + pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.119 + } else {
1.120 + pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
1.121 +
1.122 + if (!pPlugin)
1.123 + {
1.124 + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
1.125 + }
1.126 + }
1.127 +
1.128 + pContext->LocalToString(params[2], &name);
1.129 +
1.130 + /* Get public function index */
1.131 + if (pPlugin->GetBaseContext()->FindPublicByName(name, &idx) == SP_ERROR_NOT_FOUND)
1.132 + {
1.133 + /* Return INVALID_FUNCTION if not found */
1.134 + return -1;
1.135 + }
1.136 +
1.137 + /* Return function ID */
1.138 + return PublicIndexToFuncId(idx);
1.139 +}
1.140 +
1.141 +static cell_t sm_CreateGlobalForward(IPluginContext *pContext, const cell_t *params)
1.142 +{
1.143 + cell_t count = params[0];
1.144 + char *name;
1.145 + ParamType forwardParams[SP_MAX_EXEC_PARAMS];
1.146 +
1.147 + if (count - 2 > SP_MAX_EXEC_PARAMS)
1.148 + {
1.149 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
1.150 + }
1.151 +
1.152 + pContext->LocalToString(params[1], &name);
1.153 +
1.154 + cell_t *addr;
1.155 + for (int i = 3; i <= count; i++)
1.156 + {
1.157 + pContext->LocalToPhysAddr(params[i], &addr);
1.158 + forwardParams[i - 3] = static_cast<ParamType>(*addr);
1.159 + }
1.160 +
1.161 + IForward *pForward = g_Forwards.CreateForward(name, static_cast<ExecType>(params[2]), count - 2, forwardParams);
1.162 +
1.163 + return g_HandleSys.CreateHandle(g_GlobalFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.164 +}
1.165 +
1.166 +static cell_t sm_CreateForward(IPluginContext *pContext, const cell_t *params)
1.167 +{
1.168 + cell_t count = params[0];
1.169 + ParamType forwardParams[SP_MAX_EXEC_PARAMS];
1.170 +
1.171 + if (count - 1 > SP_MAX_EXEC_PARAMS)
1.172 + {
1.173 + return pContext->ThrowNativeErrorEx(SP_ERROR_PARAMS_MAX, NULL);
1.174 + }
1.175 +
1.176 + cell_t *addr;
1.177 + for (int i = 2; i <= count; i++)
1.178 + {
1.179 + pContext->LocalToPhysAddr(params[i], &addr);
1.180 + forwardParams[i - 2] = static_cast<ParamType>(*addr);
1.181 + }
1.182 +
1.183 + IChangeableForward *pForward = g_Forwards.CreateForwardEx(NULL, static_cast<ExecType>(params[1]), count - 1, forwardParams);
1.184 +
1.185 + return g_HandleSys.CreateHandle(g_PrivateFwdType, pForward, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.186 +}
1.187 +
1.188 +static cell_t sm_GetForwardFunctionCount(IPluginContext *pContext, const cell_t *params)
1.189 +{
1.190 + Handle_t hndl = static_cast<Handle_t>(params[1]);
1.191 + HandleError err;
1.192 + IForward *pForward;
1.193 +
1.194 + if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
1.195 + != HandleError_None)
1.196 + {
1.197 + return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
1.198 + }
1.199 +
1.200 + return pForward->GetFunctionCount();
1.201 +}
1.202 +
1.203 +static cell_t sm_AddToForward(IPluginContext *pContext, const cell_t *params)
1.204 +{
1.205 + Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
1.206 + Handle_t plHandle = static_cast<Handle_t>(params[2]);
1.207 + HandleError err;
1.208 + IChangeableForward *pForward;
1.209 + IPlugin *pPlugin;
1.210 +
1.211 + if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
1.212 + != HandleError_None)
1.213 + {
1.214 + return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
1.215 + }
1.216 +
1.217 + if (plHandle == 0)
1.218 + {
1.219 + pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.220 + } else {
1.221 + pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
1.222 +
1.223 + if (!pPlugin)
1.224 + {
1.225 + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
1.226 + }
1.227 + }
1.228 +
1.229 + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
1.230 +
1.231 + if (!pFunction)
1.232 + {
1.233 + return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
1.234 + }
1.235 +
1.236 + return pForward->AddFunction(pFunction);
1.237 +}
1.238 +
1.239 +static cell_t sm_RemoveFromForward(IPluginContext *pContext, const cell_t *params)
1.240 +{
1.241 + Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
1.242 + Handle_t plHandle = static_cast<Handle_t>(params[2]);
1.243 + HandleError err;
1.244 + IChangeableForward *pForward;
1.245 + IPlugin *pPlugin;
1.246 +
1.247 + if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
1.248 + != HandleError_None)
1.249 + {
1.250 + return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
1.251 + }
1.252 +
1.253 + if (plHandle == 0)
1.254 + {
1.255 + pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.256 + } else {
1.257 + pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
1.258 +
1.259 + if (!pPlugin)
1.260 + {
1.261 + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
1.262 + }
1.263 + }
1.264 +
1.265 + IPluginFunction *pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[3]);
1.266 +
1.267 + if (!pFunction)
1.268 + {
1.269 + return pContext->ThrowNativeError("Invalid function id (%X)", params[3]);
1.270 + }
1.271 +
1.272 + return pForward->RemoveFunction(pFunction);
1.273 +}
1.274 +
1.275 +static cell_t sm_RemoveAllFromForward(IPluginContext *pContext, const cell_t *params)
1.276 +{
1.277 + Handle_t fwdHandle = static_cast<Handle_t>(params[1]);
1.278 + Handle_t plHandle = static_cast<Handle_t>(params[2]);
1.279 + HandleError err;
1.280 + IChangeableForward *pForward;
1.281 + IPlugin *pPlugin;
1.282 +
1.283 + if ((err=g_HandleSys.ReadHandle(fwdHandle, g_PrivateFwdType, NULL, (void **)&pForward))
1.284 + != HandleError_None)
1.285 + {
1.286 + return pContext->ThrowNativeError("Invalid private forward handle %x (error %d)", fwdHandle, err);
1.287 + }
1.288 +
1.289 + if (plHandle == 0)
1.290 + {
1.291 + pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.292 + } else {
1.293 + pPlugin = g_PluginSys.PluginFromHandle(plHandle, &err);
1.294 +
1.295 + if (!pPlugin)
1.296 + {
1.297 + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", plHandle, err);
1.298 + }
1.299 + }
1.300 +
1.301 + return pForward->RemoveFunctionsOfPlugin(pPlugin);
1.302 +}
1.303 +
1.304 +static cell_t sm_CallStartFunction(IPluginContext *pContext, const cell_t *params)
1.305 +{
1.306 + Handle_t hndl;
1.307 + HandleError err;
1.308 + IPlugin *pPlugin;
1.309 +
1.310 + ResetCall();
1.311 +
1.312 + hndl = static_cast<Handle_t>(params[1]);
1.313 +
1.314 + if (hndl == 0)
1.315 + {
1.316 + pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.317 + } else {
1.318 + pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
1.319 +
1.320 + if (!pPlugin)
1.321 + {
1.322 + return pContext->ThrowNativeError("Plugin handle %x is invalid (error %d)", hndl, err);
1.323 + }
1.324 + }
1.325 +
1.326 + s_pFunction = pPlugin->GetBaseContext()->GetFunctionById(params[2]);
1.327 +
1.328 + if (!s_pFunction)
1.329 + {
1.330 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
1.331 + }
1.332 +
1.333 + s_pCallable = static_cast<ICallable *>(s_pFunction);
1.334 +
1.335 + s_CallStarted = true;
1.336 +
1.337 + return 1;
1.338 +}
1.339 +
1.340 +static cell_t sm_CallStartForward(IPluginContext *pContext, const cell_t *params)
1.341 +{
1.342 + Handle_t hndl;
1.343 + HandleError err;
1.344 + IForward *pForward;
1.345 +
1.346 + ResetCall();
1.347 +
1.348 + hndl = static_cast<Handle_t>(params[1]);
1.349 +
1.350 + if ((err=g_HandleSys.ReadHandle(hndl, g_GlobalFwdType, NULL, (void **)&pForward))
1.351 + != HandleError_None)
1.352 + {
1.353 + return pContext->ThrowNativeError("Invalid forward handle %x (error %d)", hndl, err);
1.354 + }
1.355 +
1.356 + s_pForward = pForward;
1.357 +
1.358 + s_pCallable = static_cast<ICallable *>(pForward);
1.359 +
1.360 + s_CallStarted = true;
1.361 +
1.362 + return 1;
1.363 +}
1.364 +
1.365 +static cell_t sm_CallPushCell(IPluginContext *pContext, const cell_t *params)
1.366 +{
1.367 + int err;
1.368 +
1.369 + if (!s_CallStarted)
1.370 + {
1.371 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.372 + }
1.373 +
1.374 + err = s_pCallable->PushCell(params[1]);
1.375 +
1.376 + if (err)
1.377 + {
1.378 + s_pCallable->Cancel();
1.379 + ResetCall();
1.380 + return pContext->ThrowNativeErrorEx(err, NULL);
1.381 + }
1.382 +
1.383 + return 1;
1.384 +}
1.385 +
1.386 +static cell_t sm_CallPushCellRef(IPluginContext *pContext, const cell_t *params)
1.387 +{
1.388 + int err;
1.389 + cell_t *addr;
1.390 +
1.391 + if (!s_CallStarted)
1.392 + {
1.393 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.394 + }
1.395 +
1.396 + pContext->LocalToPhysAddr(params[1], &addr);
1.397 +
1.398 + err = s_pCallable->PushCellByRef(addr);
1.399 +
1.400 + if (err)
1.401 + {
1.402 + s_pCallable->Cancel();
1.403 + ResetCall();
1.404 + return pContext->ThrowNativeErrorEx(err, NULL);
1.405 + }
1.406 +
1.407 + return 1;
1.408 +}
1.409 +
1.410 +static cell_t sm_CallPushFloat(IPluginContext *pContext, const cell_t *params)
1.411 +{
1.412 + int err;
1.413 +
1.414 + if (!s_CallStarted)
1.415 + {
1.416 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.417 + }
1.418 +
1.419 + err = s_pCallable->PushFloat(sp_ctof(params[1]));
1.420 +
1.421 + if (err)
1.422 + {
1.423 + s_pCallable->Cancel();
1.424 + ResetCall();
1.425 + return pContext->ThrowNativeErrorEx(err, NULL);
1.426 + }
1.427 +
1.428 + return 1;
1.429 +}
1.430 +
1.431 +static cell_t sm_CallPushFloatRef(IPluginContext *pContext, const cell_t *params)
1.432 +{
1.433 + int err;
1.434 + cell_t *addr;
1.435 +
1.436 + if (!s_CallStarted)
1.437 + {
1.438 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.439 + }
1.440 +
1.441 + pContext->LocalToPhysAddr(params[1], &addr);
1.442 +
1.443 + err = s_pCallable->PushFloatByRef(reinterpret_cast<float *>(addr));
1.444 +
1.445 + if (err)
1.446 + {
1.447 + s_pCallable->Cancel();
1.448 + ResetCall();
1.449 + return pContext->ThrowNativeErrorEx(err, NULL);
1.450 + }
1.451 +
1.452 + return 1;
1.453 +}
1.454 +
1.455 +static cell_t sm_CallPushArray(IPluginContext *pContext, const cell_t *params)
1.456 +{
1.457 + int err;
1.458 + cell_t *addr;
1.459 +
1.460 + if (!s_CallStarted)
1.461 + {
1.462 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.463 + }
1.464 +
1.465 + pContext->LocalToPhysAddr(params[1], &addr);
1.466 +
1.467 + err = s_pCallable->PushArray(addr, params[2]);
1.468 +
1.469 + if (err)
1.470 + {
1.471 + s_pCallable->Cancel();
1.472 + ResetCall();
1.473 + return pContext->ThrowNativeErrorEx(err, NULL);
1.474 + }
1.475 +
1.476 + return 1;
1.477 +}
1.478 +
1.479 +static cell_t sm_CallPushArrayEx(IPluginContext *pContext, const cell_t *params)
1.480 +{
1.481 + int err;
1.482 + cell_t *addr;
1.483 +
1.484 + if (!s_CallStarted)
1.485 + {
1.486 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.487 + }
1.488 +
1.489 + pContext->LocalToPhysAddr(params[1], &addr);
1.490 +
1.491 + err = s_pCallable->PushArray(addr, params[2], params[3]);
1.492 +
1.493 + if (err)
1.494 + {
1.495 + s_pCallable->Cancel();
1.496 + ResetCall();
1.497 + return pContext->ThrowNativeErrorEx(err, NULL);
1.498 + }
1.499 +
1.500 + return 1;
1.501 +}
1.502 +
1.503 +static cell_t sm_CallPushString(IPluginContext *pContext, const cell_t *params)
1.504 +{
1.505 + int err;
1.506 + char *value;
1.507 +
1.508 + if (!s_CallStarted)
1.509 + {
1.510 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.511 + }
1.512 +
1.513 + pContext->LocalToString(params[1], &value);
1.514 +
1.515 + err = s_pCallable->PushString(value);
1.516 +
1.517 + if (err)
1.518 + {
1.519 + s_pCallable->Cancel();
1.520 + ResetCall();
1.521 + return pContext->ThrowNativeErrorEx(err, NULL);
1.522 + }
1.523 +
1.524 + return 1;
1.525 +}
1.526 +
1.527 +static cell_t sm_CallPushStringEx(IPluginContext *pContext, const cell_t *params)
1.528 +{
1.529 + int err;
1.530 + char *value;
1.531 +
1.532 + if (!s_CallStarted)
1.533 + {
1.534 + return pContext->ThrowNativeError("Cannot push parameters when there is no call in progress");
1.535 + }
1.536 +
1.537 + pContext->LocalToString(params[1], &value);
1.538 +
1.539 + err = s_pCallable->PushStringEx(value, params[2], params[3], params[4]);
1.540 +
1.541 + if (err)
1.542 + {
1.543 + s_pCallable->Cancel();
1.544 + ResetCall();
1.545 + return pContext->ThrowNativeErrorEx(err, NULL);
1.546 + }
1.547 +
1.548 + return 1;
1.549 +}
1.550 +
1.551 +static cell_t sm_CallFinish(IPluginContext *pContext, const cell_t *params)
1.552 +{
1.553 + int err = SP_ERROR_NOT_RUNNABLE;
1.554 + cell_t *result;
1.555 +
1.556 + if (!s_CallStarted)
1.557 + {
1.558 + return pContext->ThrowNativeError("Cannot finish call when there is no call in progress");
1.559 + }
1.560 +
1.561 + pContext->LocalToPhysAddr(params[1], &result);
1.562 +
1.563 + if (s_pFunction)
1.564 + {
1.565 + IPluginFunction *pFunction = s_pFunction;
1.566 + ResetCall();
1.567 + err = pFunction->Execute(result);
1.568 + } else if (s_pForward) {
1.569 + IForward *pForward = s_pForward;
1.570 + ResetCall();
1.571 + err = pForward->Execute(result, NULL);
1.572 + }
1.573 +
1.574 + return err;
1.575 +}
1.576 +
1.577 +static cell_t sm_CallCancel(IPluginContext *pContext, const cell_t *params)
1.578 +{
1.579 + if (!s_CallStarted)
1.580 + {
1.581 + return pContext->ThrowNativeError("Cannot cancel call when there is no call in progress");
1.582 + }
1.583 +
1.584 + s_pCallable->Cancel();
1.585 + ResetCall();
1.586 +
1.587 + return 1;
1.588 +}
1.589 +
1.590 +REGISTER_NATIVES(functionNatives)
1.591 +{
1.592 + {"GetFunctionByName", sm_GetFunctionByName},
1.593 + {"CreateGlobalForward", sm_CreateGlobalForward},
1.594 + {"CreateForward", sm_CreateForward},
1.595 + {"GetForwardFunctionCount", sm_GetForwardFunctionCount},
1.596 + {"AddToForward", sm_AddToForward},
1.597 + {"RemoveFromForward", sm_RemoveFromForward},
1.598 + {"RemoveAllFromForward", sm_RemoveAllFromForward},
1.599 + {"Call_StartFunction", sm_CallStartFunction},
1.600 + {"Call_StartForward", sm_CallStartForward},
1.601 + {"Call_PushCell", sm_CallPushCell},
1.602 + {"Call_PushCellRef", sm_CallPushCellRef},
1.603 + {"Call_PushFloat", sm_CallPushFloat},
1.604 + {"Call_PushFloatRef", sm_CallPushFloatRef},
1.605 + {"Call_PushArray", sm_CallPushArray},
1.606 + {"Call_PushArrayEx", sm_CallPushArrayEx},
1.607 + {"Call_PushString", sm_CallPushString},
1.608 + {"Call_PushStringEx", sm_CallPushStringEx},
1.609 + {"Call_Finish", sm_CallFinish},
1.610 + {"Call_Cancel", sm_CallCancel},
1.611 + {NULL, NULL},
1.612 +};