1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_core.cpp Sun Mar 30 07:00:22 2008 +0000
1.3 @@ -0,0 +1,648 @@
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 <time.h>
1.36 +#include <string.h>
1.37 +#include <stdlib.h>
1.38 +#include "sm_stringutil.h"
1.39 +#include "sm_globals.h"
1.40 +#include "sourcemod.h"
1.41 +#include "PluginSys.h"
1.42 +#include "HandleSys.h"
1.43 +#include "LibrarySys.h"
1.44 +#include "TimerSys.h"
1.45 +#include "ForwardSys.h"
1.46 +#include "Logger.h"
1.47 +#include "ExtensionSys.h"
1.48 +
1.49 +#if defined PLATFORM_WINDOWS
1.50 +#include <windows.h>
1.51 +#elif defined PLATFORM_LINUX
1.52 +#include <limits.h>
1.53 +#include <unistd.h>
1.54 +#include <sys/times.h>
1.55 +#endif
1.56 +
1.57 +HandleType_t g_PlIter;
1.58 +ConVar sm_datetime_format("sm_datetime_format", "%m/%d/%Y - %H:%M:%S", 0, "Default formatting time rules");
1.59 +IForward *g_OnLogAction = NULL;
1.60 +
1.61 +class CoreNativeHelpers :
1.62 + public SMGlobalClass,
1.63 + public IHandleTypeDispatch
1.64 +{
1.65 +public:
1.66 + void OnSourceModAllInitialized()
1.67 + {
1.68 + HandleAccess hacc;
1.69 + g_HandleSys.InitAccessDefaults(NULL, &hacc);
1.70 + hacc.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY|HANDLE_RESTRICT_OWNER;
1.71 +
1.72 + g_PlIter = g_HandleSys.CreateType("PluginIterator", this, 0, NULL, NULL, g_pCoreIdent, NULL);
1.73 +
1.74 + g_OnLogAction = g_Forwards.CreateForward("OnLogAction",
1.75 + ET_Hook,
1.76 + 5,
1.77 + NULL,
1.78 + Param_Cell,
1.79 + Param_Cell,
1.80 + Param_Cell,
1.81 + Param_Cell,
1.82 + Param_String);
1.83 + }
1.84 + void OnHandleDestroy(HandleType_t type, void *object)
1.85 + {
1.86 + IPluginIterator *iter = (IPluginIterator *)object;
1.87 + iter->Release();
1.88 + }
1.89 + void OnSourceModShutdown()
1.90 + {
1.91 + g_Forwards.ReleaseForward(g_OnLogAction);
1.92 + g_HandleSys.RemoveType(g_PlIter, g_pCoreIdent);
1.93 + }
1.94 +} g_CoreNativeHelpers;
1.95 +
1.96 +void LogAction(Handle_t hndl, int type, int client, int target, const char *message)
1.97 +{
1.98 + if (g_OnLogAction->GetFunctionCount())
1.99 + {
1.100 + cell_t result = 0;
1.101 + g_OnLogAction->PushCell(hndl);
1.102 + g_OnLogAction->PushCell(type);
1.103 + g_OnLogAction->PushCell(client);
1.104 + g_OnLogAction->PushCell(target);
1.105 + g_OnLogAction->PushString(message);
1.106 + g_OnLogAction->Execute(&result);
1.107 +
1.108 + if (result >= (ResultType)Pl_Handled)
1.109 + {
1.110 + return;
1.111 + }
1.112 + }
1.113 +
1.114 + const char *logtag = "SM";
1.115 + if (type == 2)
1.116 + {
1.117 + HandleError err;
1.118 + IPlugin *pPlugin = g_PluginSys.PluginFromHandle(hndl, &err);
1.119 + if (pPlugin)
1.120 + {
1.121 + logtag = pPlugin->GetFilename();
1.122 + }
1.123 + }
1.124 +
1.125 + g_Logger.LogMessage("[%s] %s", logtag, message);
1.126 +}
1.127 +
1.128 +static cell_t ThrowError(IPluginContext *pContext, const cell_t *params)
1.129 +{
1.130 + char buffer[512];
1.131 +
1.132 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.133 +
1.134 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
1.135 +
1.136 + if (pContext->GetContext()->n_err == SP_ERROR_NONE)
1.137 + {
1.138 + pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
1.139 + }
1.140 +
1.141 + return 0;
1.142 +}
1.143 +
1.144 +static cell_t GetTime(IPluginContext *pContext, const cell_t *params)
1.145 +{
1.146 + time_t t = GetAdjustedTime();
1.147 + cell_t *addr;
1.148 + pContext->LocalToPhysAddr(params[1], &addr);
1.149 +
1.150 + *(time_t *)addr = t;
1.151 +
1.152 + return static_cast<cell_t>(t);
1.153 +}
1.154 +
1.155 +#if defined SUBPLATFORM_SECURECRT
1.156 +void _ignore_invalid_parameter(
1.157 + const wchar_t * expression,
1.158 + const wchar_t * function,
1.159 + const wchar_t * file,
1.160 + unsigned int line,
1.161 + uintptr_t pReserved
1.162 + )
1.163 +{
1.164 + /* Wow we don't care, thanks Microsoft. */
1.165 +}
1.166 +#endif
1.167 +
1.168 +static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
1.169 +{
1.170 + char *format, *buffer;
1.171 + pContext->LocalToString(params[1], &buffer);
1.172 + pContext->LocalToStringNULL(params[3], &format);
1.173 +
1.174 + if (format == NULL)
1.175 + {
1.176 + format = const_cast<char *>(sm_datetime_format.GetString());
1.177 + }
1.178 +
1.179 +#if defined SUBPLATFORM_SECURECRT
1.180 + _invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
1.181 +#endif
1.182 +
1.183 + time_t t = (params[4] == -1) ? GetAdjustedTime() : (time_t)params[4];
1.184 + size_t written = strftime(buffer, params[2], format, localtime(&t));
1.185 +
1.186 +#if defined SUBPLATFORM_SECURECRT
1.187 + _set_invalid_parameter_handler(handler);
1.188 +#endif
1.189 +
1.190 + if (params[2] && format[0] != '\0' && !written)
1.191 + {
1.192 + pContext->ThrowNativeError("Invalid time format or buffer too small");
1.193 + return 0;
1.194 + }
1.195 +
1.196 + return 1;
1.197 +}
1.198 +
1.199 +static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
1.200 +{
1.201 + IPluginIterator *iter = g_PluginSys.GetPluginIterator();
1.202 +
1.203 + Handle_t hndl = g_HandleSys.CreateHandle(g_PlIter, iter, pContext->GetIdentity(), g_pCoreIdent, NULL);
1.204 +
1.205 + if (hndl == BAD_HANDLE)
1.206 + {
1.207 + iter->Release();
1.208 + }
1.209 +
1.210 + return hndl;
1.211 +}
1.212 +
1.213 +static cell_t MorePlugins(IPluginContext *pContext, const cell_t *params)
1.214 +{
1.215 + Handle_t hndl = (Handle_t)params[1];
1.216 + HandleError err;
1.217 + IPluginIterator *pIter;
1.218 +
1.219 + HandleSecurity sec;
1.220 + sec.pIdentity = g_pCoreIdent;
1.221 + sec.pOwner = pContext->GetIdentity();
1.222 +
1.223 + if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
1.224 + {
1.225 + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
1.226 + }
1.227 +
1.228 + return pIter->MorePlugins() ? 1 : 0;
1.229 +}
1.230 +
1.231 +static cell_t ReadPlugin(IPluginContext *pContext, const cell_t *params)
1.232 +{
1.233 + Handle_t hndl = (Handle_t)params[1];
1.234 + HandleError err;
1.235 + IPluginIterator *pIter;
1.236 +
1.237 + HandleSecurity sec;
1.238 + sec.pIdentity = g_pCoreIdent;
1.239 + sec.pOwner = pContext->GetIdentity();
1.240 +
1.241 + if ((err=g_HandleSys.ReadHandle(hndl, g_PlIter, &sec, (void **)&pIter)) != HandleError_None)
1.242 + {
1.243 + return pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
1.244 + }
1.245 +
1.246 + CPlugin *pPlugin = (CPlugin *)pIter->GetPlugin();
1.247 + if (!pPlugin)
1.248 + {
1.249 + return BAD_HANDLE;
1.250 + }
1.251 +
1.252 + pIter->NextPlugin();
1.253 +
1.254 + return pPlugin->GetMyHandle();
1.255 +}
1.256 +
1.257 +CPlugin *GetPluginFromHandle(IPluginContext *pContext, Handle_t hndl)
1.258 +{
1.259 + if (hndl == BAD_HANDLE)
1.260 + {
1.261 + return g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.262 + } else {
1.263 + HandleError err;
1.264 + CPlugin *pPlugin = (CPlugin *)g_PluginSys.PluginFromHandle(hndl, &err);
1.265 + if (!pPlugin)
1.266 + {
1.267 + pContext->ThrowNativeError("Could not read Handle %x (error %d)", hndl, err);
1.268 + }
1.269 + return pPlugin;
1.270 + }
1.271 +}
1.272 +
1.273 +static cell_t GetPluginStatus(IPluginContext *pContext, const cell_t *params)
1.274 +{
1.275 + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
1.276 + if (!pPlugin)
1.277 + {
1.278 + return 0;
1.279 + }
1.280 +
1.281 + return pPlugin->GetStatus();
1.282 +}
1.283 +
1.284 +static cell_t GetPluginFilename(IPluginContext *pContext, const cell_t *params)
1.285 +{
1.286 + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
1.287 + if (!pPlugin)
1.288 + {
1.289 + return 0;
1.290 + }
1.291 +
1.292 + pContext->StringToLocalUTF8(params[2], params[3], pPlugin->GetFilename(), NULL);
1.293 +
1.294 + return 1;
1.295 +}
1.296 +
1.297 +static cell_t IsPluginDebugging(IPluginContext *pContext, const cell_t *params)
1.298 +{
1.299 + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
1.300 + if (!pPlugin)
1.301 + {
1.302 + return 0;
1.303 + }
1.304 +
1.305 + return pPlugin->IsDebugging() ? 1 : 0;
1.306 +}
1.307 +
1.308 +/* Local to plugins only */
1.309 +enum PluginInfo
1.310 +{
1.311 + PlInfo_Name, /**< Plugin name */
1.312 + PlInfo_Author, /**< Plugin author */
1.313 + PlInfo_Description, /**< Plugin description */
1.314 + PlInfo_Version, /**< Plugin verison */
1.315 + PlInfo_URL, /**< Plugin URL */
1.316 +};
1.317 +
1.318 +static cell_t GetPluginInfo(IPluginContext *pContext, const cell_t *params)
1.319 +{
1.320 + CPlugin *pPlugin = GetPluginFromHandle(pContext, params[1]);
1.321 + if (!pPlugin)
1.322 + {
1.323 + return 0;
1.324 + }
1.325 +
1.326 + const sm_plugininfo_t *info = pPlugin->GetPublicInfo();
1.327 +
1.328 + if (!info)
1.329 + {
1.330 + return 0;
1.331 + }
1.332 +
1.333 + const char *str = NULL;
1.334 +
1.335 + switch ((PluginInfo)params[2])
1.336 + {
1.337 + case PlInfo_Name:
1.338 + {
1.339 + str = info->name;
1.340 + break;
1.341 + }
1.342 + case PlInfo_Author:
1.343 + {
1.344 + str = info->author;
1.345 + break;
1.346 + }
1.347 + case PlInfo_Description:
1.348 + {
1.349 + str = info->description;
1.350 + break;
1.351 + }
1.352 + case PlInfo_Version:
1.353 + {
1.354 + str = info->version;
1.355 + break;
1.356 + }
1.357 + case PlInfo_URL:
1.358 + {
1.359 + str = info->url;
1.360 + break;
1.361 + }
1.362 + }
1.363 +
1.364 + if (!str || str[0] == '\0')
1.365 + {
1.366 + return 0;
1.367 + }
1.368 +
1.369 + pContext->StringToLocalUTF8(params[3], params[4], str, NULL);
1.370 +
1.371 + return 1;
1.372 +}
1.373 +
1.374 +static cell_t SetFailState(IPluginContext *pContext, const cell_t *params)
1.375 +{
1.376 + char *str;
1.377 + CPlugin *pPlugin;
1.378 +
1.379 + pContext->LocalToString(params[1], &str);
1.380 + pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.381 +
1.382 + if (params[0] == 1)
1.383 + {
1.384 + pPlugin->SetErrorState(Plugin_Error, "%s", str);
1.385 +
1.386 + return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", str);
1.387 + }
1.388 + else
1.389 + {
1.390 + char buffer[2048];
1.391 +
1.392 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
1.393 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.394 + {
1.395 + pPlugin->SetErrorState(Plugin_Error, "%s", str);
1.396 + return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "Formatting error (%s)", str);
1.397 + }
1.398 + else
1.399 + {
1.400 + pPlugin->SetErrorState(Plugin_Error, "%s", buffer);
1.401 + return pContext->ThrowNativeErrorEx(SP_ERROR_ABORTED, "%s", buffer);
1.402 + }
1.403 + }
1.404 +
1.405 + return 0;
1.406 +}
1.407 +
1.408 +static cell_t GetSysTickCount(IPluginContext *pContext, const cell_t *params)
1.409 +{
1.410 +#if defined PLATFORM_WINDOWS
1.411 + return (cell_t)GetTickCount();
1.412 +#elif defined PLATFORM_LINUX
1.413 + tms tm;
1.414 + clock_t ticks = times(&tm);
1.415 + long ticks_per_sec = sysconf(_SC_CLK_TCK);
1.416 + double fticks = (double)ticks / (double)ticks_per_sec;
1.417 + fticks *= 1000.0f;
1.418 + if (fticks > INT_MAX)
1.419 + {
1.420 + double r = (int)(fticks / INT_MAX) * (double)INT_MAX;
1.421 + fticks -= r;
1.422 + }
1.423 + return (cell_t)fticks;
1.424 +#endif
1.425 +}
1.426 +
1.427 +static cell_t AutoExecConfig(IPluginContext *pContext, const cell_t *params)
1.428 +{
1.429 + CPlugin *plugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.430 +
1.431 + char *cfg, *folder;
1.432 + pContext->LocalToString(params[2], &cfg);
1.433 + pContext->LocalToString(params[3], &folder);
1.434 +
1.435 + if (cfg[0] == '\0')
1.436 + {
1.437 + static char temp_str[255];
1.438 + static char temp_file[PLATFORM_MAX_PATH];
1.439 + char *ptr;
1.440 +
1.441 + g_LibSys.GetFileFromPath(temp_str, sizeof(temp_str), plugin->GetFilename());
1.442 + if ((ptr = strstr(temp_str, ".smx")) != NULL)
1.443 + {
1.444 + *ptr = '\0';
1.445 + }
1.446 +
1.447 + /* We have the raw filename! */
1.448 + UTIL_Format(temp_file, sizeof(temp_file), "plugin.%s", temp_str);
1.449 + cfg = temp_file;
1.450 + }
1.451 +
1.452 + plugin->AddConfig(params[1] ? true : false, cfg, folder);
1.453 +
1.454 + return 1;
1.455 +}
1.456 +
1.457 +static cell_t MarkNativeAsOptional(IPluginContext *pContext, const cell_t *params)
1.458 +{
1.459 + char *name;
1.460 + uint32_t idx;
1.461 + sp_context_t *ctx = pContext->GetContext();
1.462 +
1.463 + pContext->LocalToString(params[1], &name);
1.464 + if (pContext->FindNativeByName(name, &idx) != SP_ERROR_NONE)
1.465 + {
1.466 + /* Oops! This HAS to silently fail! */
1.467 + return 0;
1.468 + }
1.469 +
1.470 + ctx->natives[idx].flags |= SP_NTVFLAG_OPTIONAL;
1.471 +
1.472 + return 1;
1.473 +}
1.474 +
1.475 +static cell_t RegPluginLibrary(IPluginContext *pContext, const cell_t *params)
1.476 +{
1.477 + char *name;
1.478 + CPlugin *pl = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.479 +
1.480 + pContext->LocalToString(params[1], &name);
1.481 +
1.482 + pl->AddLibrary(name);
1.483 +
1.484 + return 1;
1.485 +}
1.486 +
1.487 +static cell_t LibraryExists(IPluginContext *pContext, const cell_t *params)
1.488 +{
1.489 + char *str;
1.490 + pContext->LocalToString(params[1], &str);
1.491 +
1.492 + if (g_PluginSys.LibraryExists(str))
1.493 + {
1.494 + return 1;
1.495 + }
1.496 +
1.497 + if (g_Extensions.LibraryExists(str))
1.498 + {
1.499 + return 1;
1.500 + }
1.501 +
1.502 + return 0;
1.503 +}
1.504 +
1.505 +static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
1.506 +{
1.507 + char buffer[2048];
1.508 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.509 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
1.510 +
1.511 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.512 + {
1.513 + return 0;
1.514 + }
1.515 +
1.516 + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.517 +
1.518 + LogAction(pPlugin->GetMyHandle(), 2, params[1], params[2], buffer);
1.519 +
1.520 + return 1;
1.521 +}
1.522 +
1.523 +static cell_t LogToFile(IPluginContext *pContext, const cell_t *params)
1.524 +{
1.525 + char *file;
1.526 + pContext->LocalToString(params[1], &file);
1.527 +
1.528 + char path[PLATFORM_MAX_PATH];
1.529 + g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
1.530 +
1.531 + FILE *fp = fopen(path, "at");
1.532 + if (!fp)
1.533 + {
1.534 + return pContext->ThrowNativeError("Could not open file \"%s\"", path);
1.535 + }
1.536 +
1.537 + char buffer[2048];
1.538 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.539 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.540 +
1.541 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.542 + {
1.543 + fclose(fp);
1.544 + return 0;
1.545 + }
1.546 +
1.547 + CPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pContext->GetContext());
1.548 +
1.549 + g_Logger.LogToOpenFile(fp, "[%s] %s", pPlugin->GetFilename(), buffer);
1.550 +
1.551 + fclose(fp);
1.552 +
1.553 + return 1;
1.554 +}
1.555 +
1.556 +static cell_t LogToFileEx(IPluginContext *pContext, const cell_t *params)
1.557 +{
1.558 + char *file;
1.559 + pContext->LocalToString(params[1], &file);
1.560 +
1.561 + char path[PLATFORM_MAX_PATH];
1.562 + g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "%s", file);
1.563 +
1.564 + FILE *fp = fopen(path, "at");
1.565 + if (!fp)
1.566 + {
1.567 + return pContext->ThrowNativeError("Could not open file \"%s\"", path);
1.568 + }
1.569 +
1.570 + char buffer[2048];
1.571 + g_SourceMod.SetGlobalTarget(LANG_SERVER);
1.572 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.573 +
1.574 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.575 + {
1.576 + fclose(fp);
1.577 + return 0;
1.578 + }
1.579 +
1.580 + g_Logger.LogToOpenFile(fp, "%s", buffer);
1.581 +
1.582 + fclose(fp);
1.583 +
1.584 + return 1;
1.585 +}
1.586 +
1.587 +static cell_t GetExtensionFileStatus(IPluginContext *pContext, const cell_t *params)
1.588 +{
1.589 + char *str;
1.590 + pContext->LocalToString(params[1], &str);
1.591 +
1.592 + IExtension *pExtension = g_Extensions.FindExtensionByFile(str);
1.593 +
1.594 + if (!pExtension)
1.595 + {
1.596 + return -2;
1.597 + }
1.598 +
1.599 + if (!pExtension->IsLoaded())
1.600 + {
1.601 + return -1;
1.602 + }
1.603 +
1.604 + char *error;
1.605 + pContext->LocalToString(params[2], &error);
1.606 + if (!pExtension->IsRunning(error, params[3]))
1.607 + {
1.608 + return 0;
1.609 + }
1.610 +
1.611 + return 1;
1.612 +}
1.613 +
1.614 +static cell_t FindPluginByNumber(IPluginContext *pContext, const cell_t *params)
1.615 +{
1.616 + CPlugin *pPlugin = g_PluginSys.GetPluginByOrder(params[1]);
1.617 +
1.618 + if (pPlugin == NULL)
1.619 + {
1.620 + return BAD_HANDLE;
1.621 + }
1.622 +
1.623 + return pPlugin->GetMyHandle();
1.624 +}
1.625 +
1.626 +REGISTER_NATIVES(coreNatives)
1.627 +{
1.628 + {"AutoExecConfig", AutoExecConfig},
1.629 + {"GetPluginFilename", GetPluginFilename},
1.630 + {"GetPluginInfo", GetPluginInfo},
1.631 + {"GetPluginIterator", GetPluginIterator},
1.632 + {"GetPluginStatus", GetPluginStatus},
1.633 + {"GetSysTickCount", GetSysTickCount},
1.634 + {"GetTime", GetTime},
1.635 + {"IsPluginDebugging", IsPluginDebugging},
1.636 + {"MorePlugins", MorePlugins},
1.637 + {"ReadPlugin", ReadPlugin},
1.638 + {"ThrowError", ThrowError},
1.639 + {"SetFailState", SetFailState},
1.640 + {"FormatTime", FormatTime},
1.641 + {"MarkNativeAsOptional", MarkNativeAsOptional},
1.642 + {"RegPluginLibrary", RegPluginLibrary},
1.643 + {"LibraryExists", LibraryExists},
1.644 + {"LogAction", sm_LogAction},
1.645 + {"LogToFile", LogToFile},
1.646 + {"LogToFileEx", LogToFileEx},
1.647 + {"GetExtensionFileStatus", GetExtensionFileStatus},
1.648 + {"FindPluginByNumber", FindPluginByNumber},
1.649 + {NULL, NULL},
1.650 +};
1.651 +