1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/loader/loader.cpp Sun Oct 14 20:25:57 2007 +0000
1.3 @@ -0,0 +1,227 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2007 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 <ISmmPluginExt.h>
1.36 +#include <stdarg.h>
1.37 +#include <string.h>
1.38 +#include <stdio.h>
1.39 +
1.40 +#if defined _MSC_VER
1.41 + #define DLL_EXPORT extern "C" __declspec(dllexport)
1.42 + #define openlib(lib) LoadLibrary(lib)
1.43 + #define closelib(lib) FreeLibrary(lib)
1.44 + #define findsym(lib, sym) GetProcAddress(lib, sym)
1.45 + #define PLATFORM_EXT ".dll"
1.46 + #define vsnprintf _vsnprintf
1.47 + #define PATH_SEP_CHAR "\\"
1.48 + inline bool IsPathSepChar(char c)
1.49 + {
1.50 + return (c == '/' || c == '\\');
1.51 + }
1.52 + #include <Windows.h>
1.53 +#else
1.54 + #define DLL_EXPORT extern "C" __attribute__((visibility("default")))
1.55 + #define openlib(lib) dlopen(lib, RTLD_NOW)
1.56 + #define closelib(lib) dlclose(lib)
1.57 + #define findsym(lib, sym) dlsym(lib, sym)
1.58 + #define PLATFORM_EXT ".so"
1.59 + typedef void * HINSTANCE;
1.60 + #define PATH_SEP_CHAR "/"
1.61 + inline bool IsPathSepChar(char c)
1.62 + {
1.63 + return (c == '/');
1.64 + }
1.65 + #include <dlfcn.h>
1.66 +#endif
1.67 +
1.68 +#define METAMOD_API_MAJOR 2
1.69 +#define FILENAME_1_4_EP1 "sourcemod.1.ep1" PLATFORM_EXT
1.70 +#define FILENAME_1_6_EP2 "sourcemod.2.ep2" PLATFORM_EXT
1.71 +#define FILENAME_1_6_EP1 "sourcemod.2.ep1" PLATFORM_EXT
1.72 +
1.73 +HINSTANCE g_hCore = NULL;
1.74 +
1.75 +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
1.76 +{
1.77 + va_list ap;
1.78 +
1.79 + va_start(ap, fmt);
1.80 + size_t len = vsnprintf(buffer, maxlength, fmt, ap);
1.81 + va_end(ap);
1.82 +
1.83 + if (len >= maxlength)
1.84 + {
1.85 + len = maxlength - 1;
1.86 + buffer[len] = '\0';
1.87 + }
1.88 +
1.89 + return len;
1.90 +}
1.91 +
1.92 +METAMOD_PLUGIN *_GetPluginPtr(const char *path)
1.93 +{
1.94 + METAMOD_FN_ORIG_LOAD fn;
1.95 + METAMOD_PLUGIN *pl;
1.96 + int ret;
1.97 +
1.98 + if (!(g_hCore=openlib(path)))
1.99 + {
1.100 + return NULL;
1.101 + }
1.102 +
1.103 + if (!(fn=(METAMOD_FN_ORIG_LOAD)findsym(g_hCore, "CreateInterface")))
1.104 + {
1.105 + goto error;
1.106 + }
1.107 +
1.108 + pl = (METAMOD_PLUGIN *)fn(METAMOD_PLAPI_NAME, &ret);
1.109 + if (!pl)
1.110 + {
1.111 + goto error;
1.112 + }
1.113 +
1.114 + return pl;
1.115 +error:
1.116 + closelib(g_hCore);
1.117 + g_hCore = NULL;
1.118 + return NULL;
1.119 +}
1.120 +
1.121 +bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength)
1.122 +{
1.123 +#if defined _MSC_VER
1.124 + MEMORY_BASIC_INFORMATION mem;
1.125 + if (!VirtualQuery(pAddr, &mem, sizeof(mem)))
1.126 + return false;
1.127 + if (mem.AllocationBase == NULL)
1.128 + return false;
1.129 + HMODULE dll = (HMODULE)mem.AllocationBase;
1.130 + GetModuleFileName(dll, (LPTSTR)buffer, maxlength);
1.131 +#else
1.132 + Dl_info info;
1.133 + if (!dladdr(pAddr, &info))
1.134 + return false;
1.135 + if (!info.dli_fbase || !info.dli_fname)
1.136 + return false;
1.137 + const char *dllpath = info.dli_fname;
1.138 + snprintf(buffer, maxlength, "%s", dllpath);
1.139 +#endif
1.140 + return true;
1.141 +}
1.142 +
1.143 +DLL_EXPORT METAMOD_PLUGIN *CreateInterface_MMS(const MetamodVersionInfo *mvi, const MetamodLoaderInfo *mli)
1.144 +{
1.145 + char *filename;
1.146 +
1.147 + if (mvi->api_major > METAMOD_API_MAJOR)
1.148 + {
1.149 + return NULL;
1.150 + }
1.151 +
1.152 + switch (mvi->source_engine)
1.153 + {
1.154 + case SOURCE_ENGINE_ORANGEBOX:
1.155 + {
1.156 + filename = FILENAME_1_6_EP2;
1.157 + break;
1.158 + }
1.159 + case SOURCE_ENGINE_EPISODEONE:
1.160 + case SOURCE_ENGINE_ORIGINAL:
1.161 + {
1.162 + filename = FILENAME_1_6_EP1;
1.163 + break;
1.164 + }
1.165 + default:
1.166 + {
1.167 + return NULL;
1.168 + }
1.169 + }
1.170 +
1.171 + char abspath[256];
1.172 + UTIL_Format(abspath, sizeof(abspath), "%s" PATH_SEP_CHAR "%s", mli->pl_path, filename);
1.173 +
1.174 + return _GetPluginPtr(abspath);
1.175 +}
1.176 +
1.177 +DLL_EXPORT void UnloadInterface_MMS()
1.178 +{
1.179 + if (g_hCore)
1.180 + {
1.181 + closelib(g_hCore);
1.182 + g_hCore = NULL;
1.183 + }
1.184 +}
1.185 +
1.186 +DLL_EXPORT void *CreateInterface(const char *iface, int *ret)
1.187 +{
1.188 + if (strcmp(iface, METAMOD_PLAPI_NAME))
1.189 + {
1.190 + char thisfile[256];
1.191 + char targetfile[256];
1.192 +
1.193 + if (!GetFileOfAddress((void *)CreateInterface_MMS, thisfile, sizeof(thisfile)))
1.194 + {
1.195 + return NULL;
1.196 + }
1.197 +
1.198 + size_t len = strlen(thisfile);
1.199 + for (size_t iter=len-1; iter>=0 && iter<len; iter--)
1.200 + {
1.201 + if (IsPathSepChar(thisfile[iter]))
1.202 + {
1.203 + thisfile[iter] = '\0';
1.204 + break;
1.205 + }
1.206 + }
1.207 +
1.208 + UTIL_Format(targetfile, sizeof(targetfile), "%s" PATH_SEP_CHAR FILENAME_1_4_EP1, thisfile);
1.209 +
1.210 + return _GetPluginPtr(targetfile);
1.211 + }
1.212 +
1.213 + return NULL;
1.214 +}
1.215 +
1.216 +#if defined _MSC_VER
1.217 +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
1.218 +{
1.219 + if (fdwReason == DLL_PROCESS_DETACH)
1.220 + {
1.221 + UnloadInterface_MMS();
1.222 + }
1.223 + return TRUE;
1.224 +}
1.225 +#else
1.226 +__attribute__((destructor)) static void gcc_fini()
1.227 +{
1.228 + UnloadInterface_MMS();
1.229 +}
1.230 +#endif