faluco@1557: /** faluco@1557: * vim: set ts=4 : faluco@1557: * ============================================================================= faluco@1557: * SourceMod faluco@1557: * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. faluco@1557: * ============================================================================= faluco@1557: * faluco@1557: * This program is free software; you can redistribute it and/or modify it under faluco@1557: * the terms of the GNU General Public License, version 3.0, as published by the faluco@1557: * Free Software Foundation. faluco@1557: * faluco@1557: * This program is distributed in the hope that it will be useful, but WITHOUT faluco@1557: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS faluco@1557: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more faluco@1557: * details. faluco@1557: * faluco@1557: * You should have received a copy of the GNU General Public License along with faluco@1557: * this program. If not, see . faluco@1557: * faluco@1557: * As a special exception, AlliedModders LLC gives you permission to link the faluco@1557: * code of this program (as well as its derivative works) to "Half-Life 2," the faluco@1557: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software faluco@1557: * by the Valve Corporation. You must obey the GNU General Public License in faluco@1557: * all respects for all other code used. Additionally, AlliedModders LLC grants faluco@1557: * this exception to all derivative works. AlliedModders LLC defines further faluco@1557: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), faluco@1557: * or . faluco@1557: * faluco@1557: * Version: $Id$ faluco@1557: */ faluco@1557: faluco@1557: #include faluco@1557: #include faluco@1557: #include faluco@1557: #include faluco@1557: faluco@1557: #if defined _MSC_VER faluco@1557: #define DLL_EXPORT extern "C" __declspec(dllexport) faluco@1557: #define openlib(lib) LoadLibrary(lib) faluco@1557: #define closelib(lib) FreeLibrary(lib) faluco@1557: #define findsym(lib, sym) GetProcAddress(lib, sym) faluco@1557: #define PLATFORM_EXT ".dll" faluco@1557: #define vsnprintf _vsnprintf faluco@1557: #define PATH_SEP_CHAR "\\" faluco@1557: inline bool IsPathSepChar(char c) faluco@1557: { faluco@1557: return (c == '/' || c == '\\'); faluco@1557: } faluco@1557: #include faluco@1557: #else faluco@1557: #define DLL_EXPORT extern "C" __attribute__((visibility("default"))) faluco@1557: #define openlib(lib) dlopen(lib, RTLD_NOW) faluco@1557: #define closelib(lib) dlclose(lib) faluco@1557: #define findsym(lib, sym) dlsym(lib, sym) faluco@1557: #define PLATFORM_EXT ".so" faluco@1557: typedef void * HINSTANCE; faluco@1557: #define PATH_SEP_CHAR "/" faluco@1557: inline bool IsPathSepChar(char c) faluco@1557: { faluco@1557: return (c == '/'); faluco@1557: } faluco@1557: #include faluco@1557: #endif faluco@1557: faluco@1557: #define METAMOD_API_MAJOR 2 faluco@1557: #define FILENAME_1_4_EP1 "sourcemod.1.ep1" PLATFORM_EXT faluco@1557: #define FILENAME_1_6_EP2 "sourcemod.2.ep2" PLATFORM_EXT faluco@1557: #define FILENAME_1_6_EP1 "sourcemod.2.ep1" PLATFORM_EXT faluco@1557: faluco@1557: HINSTANCE g_hCore = NULL; dvander@1561: bool load_attempted = false; faluco@1557: faluco@1557: size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) faluco@1557: { faluco@1557: va_list ap; faluco@1557: faluco@1557: va_start(ap, fmt); faluco@1557: size_t len = vsnprintf(buffer, maxlength, fmt, ap); faluco@1557: va_end(ap); faluco@1557: faluco@1557: if (len >= maxlength) faluco@1557: { faluco@1557: len = maxlength - 1; faluco@1557: buffer[len] = '\0'; faluco@1557: } faluco@1557: faluco@1557: return len; faluco@1557: } faluco@1557: faluco@1557: METAMOD_PLUGIN *_GetPluginPtr(const char *path) faluco@1557: { faluco@1557: METAMOD_FN_ORIG_LOAD fn; faluco@1557: METAMOD_PLUGIN *pl; faluco@1557: int ret; faluco@1557: faluco@1557: if (!(g_hCore=openlib(path))) faluco@1557: { faluco@1557: return NULL; faluco@1557: } faluco@1557: faluco@1557: if (!(fn=(METAMOD_FN_ORIG_LOAD)findsym(g_hCore, "CreateInterface"))) faluco@1557: { faluco@1557: goto error; faluco@1557: } faluco@1557: faluco@1557: pl = (METAMOD_PLUGIN *)fn(METAMOD_PLAPI_NAME, &ret); faluco@1557: if (!pl) faluco@1557: { faluco@1557: goto error; faluco@1557: } faluco@1557: faluco@1557: return pl; faluco@1557: error: faluco@1557: closelib(g_hCore); faluco@1557: g_hCore = NULL; faluco@1557: return NULL; faluco@1557: } faluco@1557: faluco@1557: bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength) faluco@1557: { faluco@1557: #if defined _MSC_VER faluco@1557: MEMORY_BASIC_INFORMATION mem; faluco@1557: if (!VirtualQuery(pAddr, &mem, sizeof(mem))) faluco@1557: return false; faluco@1557: if (mem.AllocationBase == NULL) faluco@1557: return false; faluco@1557: HMODULE dll = (HMODULE)mem.AllocationBase; faluco@1557: GetModuleFileName(dll, (LPTSTR)buffer, maxlength); faluco@1557: #else faluco@1557: Dl_info info; faluco@1557: if (!dladdr(pAddr, &info)) faluco@1557: return false; faluco@1557: if (!info.dli_fbase || !info.dli_fname) faluco@1557: return false; faluco@1557: const char *dllpath = info.dli_fname; faluco@1557: snprintf(buffer, maxlength, "%s", dllpath); faluco@1557: #endif faluco@1557: return true; faluco@1557: } faluco@1557: faluco@1557: DLL_EXPORT METAMOD_PLUGIN *CreateInterface_MMS(const MetamodVersionInfo *mvi, const MetamodLoaderInfo *mli) faluco@1557: { faluco@1557: char *filename; dvander@1561: dvander@1561: load_attempted = true; faluco@1557: faluco@1557: if (mvi->api_major > METAMOD_API_MAJOR) faluco@1557: { faluco@1557: return NULL; faluco@1557: } faluco@1557: faluco@1557: switch (mvi->source_engine) faluco@1557: { faluco@1557: case SOURCE_ENGINE_ORANGEBOX: faluco@1557: { faluco@1557: filename = FILENAME_1_6_EP2; faluco@1557: break; faluco@1557: } faluco@1557: case SOURCE_ENGINE_EPISODEONE: faluco@1557: case SOURCE_ENGINE_ORIGINAL: faluco@1557: { faluco@1557: filename = FILENAME_1_6_EP1; faluco@1557: break; faluco@1557: } faluco@1557: default: faluco@1557: { faluco@1557: return NULL; faluco@1557: } faluco@1557: } faluco@1557: faluco@1557: char abspath[256]; faluco@1557: UTIL_Format(abspath, sizeof(abspath), "%s" PATH_SEP_CHAR "%s", mli->pl_path, filename); faluco@1557: faluco@1557: return _GetPluginPtr(abspath); faluco@1557: } faluco@1557: faluco@1557: DLL_EXPORT void UnloadInterface_MMS() faluco@1557: { faluco@1557: if (g_hCore) faluco@1557: { faluco@1557: closelib(g_hCore); faluco@1557: g_hCore = NULL; faluco@1557: } faluco@1557: } faluco@1557: faluco@1557: DLL_EXPORT void *CreateInterface(const char *iface, int *ret) faluco@1557: { dvander@1561: /** dvander@1561: * If a load has already been attempted, bail out immediately. dvander@1561: */ dvander@1561: if (load_attempted) dvander@1561: { dvander@1561: return NULL; dvander@1561: } dvander@1561: dvander@1561: if (strcmp(iface, METAMOD_PLAPI_NAME) == 0) faluco@1557: { faluco@1557: char thisfile[256]; faluco@1557: char targetfile[256]; faluco@1557: faluco@1557: if (!GetFileOfAddress((void *)CreateInterface_MMS, thisfile, sizeof(thisfile))) faluco@1557: { faluco@1557: return NULL; faluco@1557: } faluco@1557: faluco@1557: size_t len = strlen(thisfile); faluco@1557: for (size_t iter=len-1; iter>=0 && iter