diff --git a/metamod/msvc/metamod.vcxproj b/metamod/msvc/metamod.vcxproj
index f93cbe2..674f10a 100644
--- a/metamod/msvc/metamod.vcxproj
+++ b/metamod/msvc/metamod.vcxproj
@@ -77,7 +77,7 @@
$(OutDir)$(TargetName).lib
MachineX86
false
- %(AdditionalDependencies)
+ psapi.lib;%(AdditionalDependencies)
_DEBUG;%(PreprocessorDefinitions)
@@ -140,7 +140,7 @@
$(OutDir)$(TargetName).lib
MachineX86
false
- %(AdditionalDependencies)
+ psapi.lib;%(AdditionalDependencies)
NDEBUG;%(PreprocessorDefinitions)
diff --git a/metamod/src/dllapi.cpp b/metamod/src/dllapi.cpp
index 24574b0..1605f53 100644
--- a/metamod/src/dllapi.cpp
+++ b/metamod/src/dllapi.cpp
@@ -216,7 +216,7 @@ void compile_dllfunc_callbacks()
{
jitdata_t jitdata;
jitdata.plugins = g_plugins ? g_plugins->plist : nullptr;
- jitdata.plugins_count = g_plugins ? g_plugins->endlist : 0;
+ jitdata.plugins_count = g_plugins ? g_plugins->max_loaded_count : 0;
jitdata.table_offset = offsetof(MPlugin, dllapi_table);
jitdata.post_table_offset = offsetof(MPlugin, dllapi_post_table);
@@ -237,7 +237,7 @@ void compile_newdllfunc_callbacks()
{
jitdata_t jitdata;
jitdata.plugins = g_plugins ? g_plugins->plist : nullptr;
- jitdata.plugins_count = g_plugins ? g_plugins->endlist : 0;
+ jitdata.plugins_count = g_plugins ? g_plugins->max_loaded_count : 0;
jitdata.table_offset = offsetof(MPlugin, newapi_table);
jitdata.post_table_offset = offsetof(MPlugin, newapi_post_table);
diff --git a/metamod/src/engine_api.cpp b/metamod/src/engine_api.cpp
index e656923..e927a78 100644
--- a/metamod/src/engine_api.cpp
+++ b/metamod/src/engine_api.cpp
@@ -240,7 +240,7 @@ void compile_engfuncs_callbacks()
{
jitdata_t jitdata;
jitdata.plugins = g_plugins ? g_plugins->plist : nullptr;
- jitdata.plugins_count = g_plugins ? g_plugins->endlist : 0;
+ jitdata.plugins_count = g_plugins ? g_plugins->max_loaded_count : 0;
jitdata.table_offset = offsetof(MPlugin, engine_table);
jitdata.post_table_offset = offsetof(MPlugin, engine_post_table);
diff --git a/metamod/src/linkent.cpp b/metamod/src/linkent.cpp
index 4eb1b95..e46eb37 100644
--- a/metamod/src/linkent.cpp
+++ b/metamod/src/linkent.cpp
@@ -14,12 +14,12 @@ void do_link_ent(ENTITY_FN *pfnEntity, int *missing, const char *entStr, entvars
if (!*pfnEntity)
{
META_DEBUG(9, ("Looking up game entity '%s'", entStr));
- *pfnEntity = (ENTITY_FN)DLSYM(GameDLL.handle, entStr);
+ *pfnEntity = (ENTITY_FN)GameDLL.sys_module.getsym(entStr);
}
if (!*pfnEntity)
{
- META_ERROR("Couldn't find game entity '%s' in game DLL '%s': %s", entStr, GameDLL.name, DLERROR());
+ META_ERROR("Couldn't find game entity '%s' in game DLL '%s': %s", entStr, GameDLL.name, CSysModule::getloaderror());
*missing = 1;
return;
}
diff --git a/metamod/src/metamod.cpp b/metamod/src/metamod.cpp
index 42469ca..540891e 100644
--- a/metamod/src/metamod.cpp
+++ b/metamod/src/metamod.cpp
@@ -292,9 +292,9 @@ bool meta_load_gamedll(void)
}
// open the game DLL
- if (!(GameDLL.handle = DLOPEN(GameDLL.pathname)))
+ if (!GameDLL.sys_module.load(GameDLL.pathname))
{
- META_ERROR("dll: Couldn't load game DLL %s: %s", GameDLL.pathname, DLERROR());
+ META_ERROR("dll: Couldn't load game DLL %s: %s", GameDLL.pathname, CSysModule::getloaderror());
RETURN_ERRNO(false, ME_DLOPEN);
}
@@ -305,20 +305,21 @@ bool meta_load_gamedll(void)
// wanted to catch one of the functions, but now that plugins are
// dynamically loadable at any time, we have to always pass our table,
// so that any plugin loaded later can catch what they need to.
- if ((pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(GameDLL.handle, "GiveFnptrsToDll")))
+ if ((pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN)GameDLL.sys_module.getsym("GiveFnptrsToDll")))
{
pfn_give_engfuncs(&meta_engfuncs, gpGlobals);
META_DEBUG(3, ("dll: Game '%s': Called GiveFnptrsToDll", GameDLL.name));
}
else
{
- META_ERROR("dll: Couldn't find GiveFnptrsToDll() in game DLL '%s': %s", GameDLL.name, DLERROR());
+ META_ERROR("dll: Couldn't find GiveFnptrsToDll() in game DLL '%s'", GameDLL.name);
RETURN_ERRNO(false, ME_DLMISSING);
}
+ // TODO
// Yes...another macro.
#define GET_FUNC_TABLE_FROM_GAME(gamedll, pfnGetFuncs, STR_GetFuncs, struct_field, API_TYPE, TABLE_TYPE, vers_pass, vers_int, vers_want, gotit) \
- if ((pfnGetFuncs = (API_TYPE) DLSYM(gamedll.handle, STR_GetFuncs))) { \
+ if ((pfnGetFuncs = (API_TYPE)gamedll.sys_module.getsym(STR_GetFuncs))) { \
gamedll.funcs.struct_field = (TABLE_TYPE *)Q_calloc(1, sizeof(TABLE_TYPE)); \
if (!gamedll.funcs.struct_field) {\
META_ERROR("malloc failed for gamedll struct_field: %s", STR_GetFuncs); \
diff --git a/metamod/src/metamod.h b/metamod/src/metamod.h
index 547d93b..07b0f7f 100644
--- a/metamod/src/metamod.h
+++ b/metamod/src/metamod.h
@@ -36,7 +36,7 @@ struct gamedll_t
char pathname[PATH_MAX]; // ie "/home/willday/half-life/cstrike/dlls/cs_i386.so"
char const *file; // ie "cs_i386.so"
char real_pathname[PATH_MAX]; // in case pathname overridden by bot, etc
- DLHANDLE handle;
+ CSysModule sys_module;
gamedll_funcs_t funcs; // dllapi_table, newapi_table
};
diff --git a/metamod/src/mlist.cpp b/metamod/src/mlist.cpp
index bf2f651..848bf80 100644
--- a/metamod/src/mlist.cpp
+++ b/metamod/src/mlist.cpp
@@ -1,7 +1,7 @@
#include "precompiled.h"
// Constructor
-MPluginList::MPluginList(const char* ifile) : size(MAX_PLUGINS), endlist(0)
+MPluginList::MPluginList(const char* ifile) : max_loaded_count(0)
{
// store filename of ini file
Q_strncpy(inifile, ifile, sizeof inifile - 1);
@@ -9,28 +9,28 @@ MPluginList::MPluginList(const char* ifile) : size(MAX_PLUGINS), endlist(0)
// initialize array
Q_memset(plist, 0, sizeof(plist));
- for (int i = 0; i < size; i++)
+ for (int i = 0; i < MAX_PLUGINS; i++)
{
plist[i].index = i + 1; // 1-based
}
- endlist = 0;
+ max_loaded_count = 0;
}
// Find a plugin based on the plugin handle.
// meta_errno values:
// - ME_ARGUMENT invalid pindex
// - ME_NOTFOUND couldn't find a matching plugin
-MPlugin *MPluginList::find(DLHANDLE handle)
+MPlugin *MPluginList::find(module_handle_t handle)
{
if (!handle)
RETURN_ERRNO(NULL, ME_ARGUMENT);
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
if (plist[i].status < PL_VALID)
continue;
- if (plist[i].handle == handle)
+ if (handle == plist[i].sys_module.gethandle())
return &plist[i];
}
@@ -62,7 +62,7 @@ MPlugin *MPluginList::find(plid_t id)
if (!id)
RETURN_ERRNO(NULL, ME_ARGUMENT);
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
if (plist[i].status < PL_VALID)
continue;
@@ -85,7 +85,7 @@ MPlugin *MPluginList::find(const char* findpath)
META_DEBUG(8, ("Looking for loaded plugin with dlfnamepath: %s", findpath));
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
META_DEBUG(9, ("Looking at: plugin %s loadedpath: %s", plist[i].file, plist[i].pathname));
@@ -104,25 +104,16 @@ MPlugin *MPluginList::find(const char* findpath)
}
// Find a plugin that uses the given memory location.
-// meta_errno values:
-// - ME_ARGUMENT null memptr
-// - ME_NOTFOUND couldn't find a matching plugin
-// - errno's from DLFNAME()
MPlugin *MPluginList::find_memloc(void *memptr)
{
- const char* dlfile;
+ for (int i = 0; i < max_loaded_count; i++) {
+ auto iplug = &plist[i];
- if (!memptr)
- RETURN_ERRNO(NULL, ME_ARGUMENT);
-
- if (!(dlfile = DLFNAME(memptr)))
- {
- META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
- // meta_errno should be already set in DLFNAME
- return NULL;
+ if (iplug->sys_module.contain(memptr))
+ return iplug;
}
- return find(dlfile);
+ return nullptr;
}
// Find a plugin with non-ambiguous prefix string matching desc, file,
@@ -145,7 +136,7 @@ MPlugin *MPluginList::find_match(const char *prefix)
pfound = NULL;
len = Q_strlen(prefix);
Q_snprintf(buf, sizeof(buf), "mm_%s", prefix);
- for (i = 0; i < endlist; i++)
+ for (i = 0; i < max_loaded_count; i++)
{
iplug = &plist[i];
if (iplug->status < PL_VALID)
@@ -214,7 +205,7 @@ MPlugin *MPluginList::find_match(MPlugin* pmatch)
}
pfound = NULL;
- for (i = 0; i < endlist; i++)
+ for (i = 0; i < max_loaded_count; i++)
{
iplug = &plist[i];
if (pmatch->platform_match(iplug))
@@ -292,33 +283,34 @@ MPlugin* MPluginList::plugin_addload(plid_t plid, const char* fname, PLUG_LOADTI
return pl_added;
}
+MPlugin* MPluginList::find_empty_slot()
+{
+ for (int i = 0; i < MAX_PLUGINS; i++) {
+ if (plist[i].status == PL_EMPTY) {
+ if (i > max_loaded_count)
+ max_loaded_count = i + 1;
+
+ return &plist[i];
+ }
+ }
+
+ return nullptr;
+}
+
// Add a plugin to the list.
// meta_errno values:
// - ME_MAXREACHED reached max plugins
MPlugin* MPluginList::add(MPlugin* padd)
{
- int i;
- MPlugin* iplug;
-
- // Find either:
- // - a slot in the list that's not being used
- // - the end of the list
- for (i = 0; i < endlist && plist[i].status != PL_EMPTY; i++)
- ;
+ auto iplug = find_empty_slot();
// couldn't find a slot to use
- if (i == size)
+ if (!iplug)
{
- META_ERROR("Couldn't add plugin '%s' to list; reached max plugins (%d)", padd->file, i);
+ META_ERROR("Couldn't add plugin '%s' to list; reached max plugins (%d)", padd->file, MAX_PLUGINS);
RETURN_ERRNO(NULL, ME_MAXREACHED);
}
- // if we found the end of the list, advance end marker
- if (i == endlist)
- endlist++;
-
- iplug = &plist[i];
-
// copy filename into this free slot
Q_strncpy(iplug->filename, padd->filename, sizeof iplug->filename - 1);
iplug->filename[sizeof iplug->filename - 1] = '\0';
@@ -337,13 +329,8 @@ MPlugin* MPluginList::add(MPlugin* padd)
iplug->pathname[sizeof iplug->pathname - 1] = '\0';
normalize_pathname(iplug->pathname);
- // copy source
iplug->source = padd->source;
-
- // copy status
iplug->status = padd->status;
-
- //copy other things
iplug->source_plugin_index = padd->source_plugin_index;
return iplug;
@@ -375,7 +362,7 @@ bool MPluginList::ini_startup()
}
META_LOG("ini: Begin reading plugins list: %s", inifile);
- for (n = 0 , ln = 1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++)
+ for (n = 0 , ln = 1; !feof(fp) && fgets(line, sizeof(line), fp) && n < MAX_PLUGINS; ln++)
{
// Remove line terminations.
char* cp;
@@ -420,7 +407,7 @@ bool MPluginList::ini_startup()
plist[n].action = PA_LOAD;
META_LOG("ini: Read plugin config for: %s", plist[n].desc);
n++;
- endlist = n; // mark end of list
+ max_loaded_count = n; // mark end of list
}
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load", inifile, n);
@@ -452,7 +439,7 @@ bool MPluginList::ini_refresh()
}
META_LOG("ini: Begin re-reading plugins list: %s", inifile);
- for (n = 0 , ln = 1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++)
+ for (n = 0 , ln = 1; !feof(fp) && fgets(line, sizeof(line), fp) && n < MAX_PLUGINS; ln++)
{
// Remove line terminations.
char *cp;
@@ -655,7 +642,7 @@ bool MPluginList::load()
}
META_LOG("dll: Loading plugins...");
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
if (plist[i].status < PL_VALID)
continue;
@@ -690,7 +677,7 @@ bool MPluginList::refresh(PLUG_LOADTIME now)
}
META_LOG("dll: Updating plugins...");
- for (i = 0; i < endlist; i++)
+ for (i = 0; i < max_loaded_count; i++)
{
iplug = &plist[i];
if (iplug->status < PL_VALID)
@@ -767,7 +754,7 @@ bool MPluginList::refresh(PLUG_LOADTIME now)
// - none
void MPluginList::unpause_all(void)
{
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
auto iplug = &plist[i];
if (iplug->status == PL_PAUSED)
@@ -781,7 +768,7 @@ void MPluginList::unpause_all(void)
// - none
void MPluginList::retry_all(PLUG_LOADTIME now)
{
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
auto iplug = &plist[i];
if (iplug->action != PA_NONE)
@@ -806,7 +793,7 @@ void MPluginList::show(int source_index)
META_CONS(" %*s %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s", WIDTH_MAX_PLUGINS, "", sizeof(desc) - 1, "description", "stat", "pend",
sizeof(file) - 1, "file", sizeof(vers) - 1, "ers", 2 + WIDTH_MAX_PLUGINS, "src", "load ", "unlod");
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
pl = &plist[i];
if (pl->status < PL_VALID)
@@ -857,7 +844,7 @@ void MPluginList::show_client(edict_t *pEntity)
MPlugin *pl;
META_CLIENT(pEntity, "Currently running plugins:");
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
pl = &plist[i];
if (pl->status != PL_RUNNING || !pl->info)
@@ -880,7 +867,7 @@ bool MPluginList::found_child_plugins(int source_index) const
if (source_index <= 0)
return false;
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
if (plist[i].status < PL_VALID)
continue;
@@ -897,7 +884,7 @@ void MPluginList::clear_source_plugin_index(int source_index)
if (source_index <= 0)
return;
- for (int i = 0; i < endlist; i++)
+ for (int i = 0; i < max_loaded_count; i++)
{
if (plist[i].status < PL_VALID)
continue;
diff --git a/metamod/src/mlist.h b/metamod/src/mlist.h
index fb2a36d..9ffbbed 100644
--- a/metamod/src/mlist.h
+++ b/metamod/src/mlist.h
@@ -23,7 +23,8 @@ public:
MPlugin *find_memloc(void *memptr); // find by memory location
MPlugin *find_match(const char *prefix); // find by partial prefix match
MPlugin *find_match(MPlugin *pmatch); // find by platform_match()
- MPlugin *find(DLHANDLE handle); // find by handle
+ MPlugin *find(module_handle_t handle); // find by handle
+ MPlugin *find_empty_slot();
MPlugin *add(MPlugin *padd);
bool found_child_plugins(int source_index) const;
@@ -42,8 +43,7 @@ public:
void clear_source_plugin_index(int source_index);
public:
- int loaded_count; // index of last used entry
- int size; // size of list, ie MAX_PLUGINS
+ int max_loaded_count; // index of last used entry
char inifile[PATH_MAX]; // full pathname
MPlugin plist[MAX_PLUGINS]; // array of plugins
};
diff --git a/metamod/src/mplugin.cpp b/metamod/src/mplugin.cpp
index 0383121..ea7a6d9 100644
--- a/metamod/src/mplugin.cpp
+++ b/metamod/src/mplugin.cpp
@@ -382,7 +382,7 @@ char *MPlugin::resolve_dirs(char *path)
// dir/file
// meta_errno values:
// - none
-char *MPlugin::resolve_prefix(char *path)
+char *MPlugin::resolve_prefix(char *path) const
{
struct stat st;
char *cp, *fname;
@@ -432,7 +432,7 @@ char *MPlugin::resolve_prefix(char *path)
// path_i386.so, path_i486.so, etc (if linux)
// meta_errno values:
// - none
-char *MPlugin::resolve_suffix(char *path)
+char *MPlugin::resolve_suffix(char *path) const
{
struct stat st;
static char buf[PATH_MAX ];
@@ -595,12 +595,10 @@ bool MPlugin::load(PLUG_LOADTIME now)
META_ERROR("dll: Skipping plugin '%s'; couldn't query", desc);
if (meta_errno != ME_DLOPEN)
{
- if (DLCLOSE(handle) != 0)
+ if (!sys_module.unload())
{
- META_ERROR("dll: Couldn't close plugin file '%s': %s", file, DLERROR());
+ META_ERROR("dll: Couldn't close plugin file '%s': %s", file, "invalid handle");
}
- else
- handle = NULL;
}
status = PL_BADFILE;
info = NULL; //prevent crash
@@ -682,10 +680,9 @@ bool MPlugin::query(void)
META_QUERY_FN pfn_query;
// open the plugin DLL
- if (!(handle = DLOPEN(pathname)))
+ if (!sys_module.load(pathname))
{
- META_ERROR("dll: Failed query plugin '%s'; Couldn't open file '%s': %s",
- desc, pathname, DLERROR());
+ META_ERROR("dll: Failed query plugin '%s'; Couldn't open file '%s': %s", desc, pathname, sys_module.getloaderror());
RETURN_ERRNO(false, ME_DLOPEN);
}
@@ -699,10 +696,10 @@ bool MPlugin::query(void)
// GiveFnptrsToDll before Meta_Query, because the latter typically uses
// engine functions like AlertMessage, which have to be passed along via
// GiveFnptrsToDll.
- pfn_query = (META_QUERY_FN) DLSYM(handle, "Meta_Query");
+ pfn_query = (META_QUERY_FN)sys_module.getsym("Meta_Query");
if (!pfn_query)
{
- META_ERROR("dll: Failed query plugin '%s'; Couldn't find Meta_Query(): %s", desc, DLERROR());
+ META_ERROR("dll: Failed query plugin '%s'; Couldn't find Meta_Query(): %s", desc, "function not found");
// caller will dlclose()
RETURN_ERRNO(false, ME_DLMISSING);
}
@@ -721,7 +718,7 @@ bool MPlugin::query(void)
// This passes nothing and returns nothing, and the routine in the
// plugin can NOT use any g_engine functions, as they haven't been
// provided yet (done next, in GiveFnptrsToDll).
- pfn_init = (META_INIT_FN) DLSYM(handle, "Meta_Init");
+ pfn_init = (META_INIT_FN)sys_module.getsym("Meta_Init");
if (pfn_init)
{
pfn_init();
@@ -734,10 +731,10 @@ bool MPlugin::query(void)
}
// pass on engine function table and globals to plugin
- if (!(pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(handle, "GiveFnptrsToDll")))
+ if (!(pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN)sys_module.getsym("GiveFnptrsToDll")))
{
// META_ERROR("dll: Couldn't find GiveFnptrsToDll() in plugin '%s': %s", desc, DLERROR());
- META_ERROR("dll: Failed query plugin '%s'; Couldn't find GiveFnptrsToDll(): %s", desc, DLERROR());
+ META_ERROR("dll: Failed query plugin '%s'; Couldn't find GiveFnptrsToDll(): %s", desc, "function not found");
// caller will dlclose()
RETURN_ERRNO(false, ME_DLMISSING);
}
@@ -880,9 +877,9 @@ bool MPlugin::attach(PLUG_LOADTIME now)
}
static_cast(gamedll_funcs.newapi_table)->set_from(GameDLL.funcs.newapi_table);
}
- if (!(pfn_attach = (META_ATTACH_FN) DLSYM(handle, "Meta_Attach")))
+ if (!(pfn_attach = (META_ATTACH_FN)sys_module.getsym("Meta_Attach")))
{
- META_ERROR("dll: Failed attach plugin '%s': Couldn't find Meta_Attach(): %s", desc, DLERROR());
+ META_ERROR("dll: Failed attach plugin '%s': Couldn't find Meta_Attach(): %s", desc, "function not found");
// caller will dlclose()
RETURN_ERRNO(false, ME_DLMISSING);
}
@@ -1082,13 +1079,12 @@ bool MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, PL_UNLOAD_REASO
// Close the file. Note: after this, attempts to reference any memory
// locations in the file will produce a segfault.
- if (DLCLOSE(handle) != 0)
+ if (!sys_module.unload())
{
// If DLL cannot be closed, OS is badly broken or we are giving invalid handle.
// So we don't return here but instead remove plugin from our listings.
- META_WARNING("dll: Couldn't close plugin file '%s': %s", file, DLERROR());
+ META_WARNING("dll: Couldn't close plugin file '%s': %s", file, "invalid handle");
}
- handle = NULL;
if (action == PA_UNLOAD)
{
@@ -1118,12 +1114,12 @@ bool MPlugin::detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
// If we have no handle, i.e. no dll loaded, we return true because the
// dll is obviously detached. We shouldn't call DLSYM() with a NULL
// handle since this will DLSYM() ourself.
- if (!handle)
+ if (!sys_module.gethandle())
return true;
- if (!(pfn_detach = (META_DETACH_FN) DLSYM(handle, "Meta_Detach")))
+ if (!(pfn_detach = (META_DETACH_FN)sys_module.getsym("Meta_Detach")))
{
- META_ERROR("dll: Error detach plugin '%s': Couldn't find Meta_Detach(): %s", desc, DLERROR());
+ META_ERROR("dll: Error detach plugin '%s': Couldn't find Meta_Detach(): %s", desc, "function not found");
// caller will dlclose()
RETURN_ERRNO(false, ME_DLMISSING);
}
@@ -1279,13 +1275,12 @@ bool MPlugin::clear(void)
}
// If file is open, close the file. Note: after this, attempts to
// reference any memory locations in the file will produce a segfault.
- if (handle && DLCLOSE(handle) != 0)
+ if (!sys_module.unload())
{
- META_ERROR("dll: Couldn't close plugin file '%s': %s", file, DLERROR());
+ META_ERROR("dll: Couldn't close plugin file '%s': %s", file, "invalid handle");
status = PL_FAILED;
RETURN_ERRNO(false, ME_DLERROR);
}
- handle = NULL;
if (gamedll_funcs.dllapi_table) Q_free(gamedll_funcs.dllapi_table);
if (gamedll_funcs.newapi_table) Q_free(gamedll_funcs.newapi_table);
@@ -1298,7 +1293,6 @@ bool MPlugin::clear(void)
status = PL_EMPTY;
action = PA_NULL;
- handle = NULL;
info = NULL;
time_loaded = 0;
dllapi_table = NULL;
diff --git a/metamod/src/mplugin.h b/metamod/src/mplugin.h
index 34f7416..198c950 100644
--- a/metamod/src/mplugin.h
+++ b/metamod/src/mplugin.h
@@ -5,9 +5,9 @@
// Flags to indicate current "load" state of plugin.
// NOTE: order is important, as greater/less comparisons are made.
-enum PLUG_STATUS
+enum PLUG_STATUS : uint8
{
- PL_EMPTY = 0, // empty slot
+ PL_EMPTY = 0, // empty slot
PL_VALID, // has valid info in it
PL_BADFILE, // nonexistent file (open failed), or not a valid plugin file (query failed)
PL_OPENED, // dlopened and queried
@@ -17,7 +17,7 @@ enum PLUG_STATUS
};
// Action to take for plugin at next opportunity.
-enum PLUG_ACTION
+enum PLUG_ACTION : uint8
{
PA_NULL = 0,
PA_NONE, // no action needed right now
@@ -29,7 +29,7 @@ enum PLUG_ACTION
};
// Flags to indicate from where the plugin was loaded.
-enum PLOAD_SOURCE
+enum PLOAD_SOURCE : uint8
{
PS_INI = 0, // was loaded from the plugins.ini
PS_CMD, // was loaded via a server command
@@ -37,7 +37,7 @@ enum PLOAD_SOURCE
};
// Flags for how to word description of plugin loadtime.
-enum STR_LOADTIME
+enum STR_LOADTIME : uint8
{
SL_SIMPLE = 0, // single word
SL_SHOW, // for "show" output, 5 chars
@@ -46,21 +46,21 @@ enum STR_LOADTIME
};
// Flags for how to format description of status.
-enum STR_STATUS
+enum STR_STATUS : uint8
{
ST_SIMPLE = 0, // single word
ST_SHOW, // for "show" output, 4 chars
};
// Flags for how to format description of action.
-enum STR_ACTION
+enum STR_ACTION : uint8
{
SA_SIMPLE = 0, // single word
SA_SHOW, // for "show" output, 4 chars
};
// Flags for how to format description of source.
-enum STR_SOURCE
+enum STR_SOURCE : uint8
{
SO_SIMPLE = 0, // two words
SO_SHOW, // for "list" output, 3 chars
@@ -68,26 +68,13 @@ enum STR_SOURCE
// An individual plugin.
class MPlugin {
-private:
- bool query();
- bool attach(PLUG_LOADTIME now);
- bool detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
- gamedll_funcs_t gamedll_funcs;
- mutil_funcs_t mutil_funcs;
-
public:
- int index; // 1-based
- char filename[PATH_MAX]; // ie "dlls/mm_test_i386.so", from inifile
- char *file; // ie "mm_test_i386.so", ptr from filename
- char desc[MAX_DESC_LEN]; // ie "Test metamod plugin", from inifile
- char pathname[PATH_MAX]; // UNIQUE, ie "/home/willday/half-life/cstrike/dlls/mm_test_i386.so", built with GameDLL.gamedir
- int pfspecific; // level of specific platform affinity, used during load time
PLUG_STATUS status; // current status of plugin (loaded, etc)
PLUG_ACTION action; // what to do with plugin (load, unload, etc)
PLOAD_SOURCE source; // source of the request to load the plugin
-
- DLHANDLE handle; // handle for dlopen, dlsym, etc
+ int index; // 1-based
plugin_info_t *info; // information plugin provides about itself
+ CSysModule sys_module;
time_t time_loaded; // when plugin was loaded
int source_plugin_index; // who loaded this plugin
int unloader_index;
@@ -100,6 +87,15 @@ public:
enginefuncs_t *engine_table;
enginefuncs_t *engine_post_table;
+ gamedll_funcs_t gamedll_funcs;
+ mutil_funcs_t mutil_funcs;
+
+ char filename[PATH_MAX]; // ie "dlls/mm_test_i386.so", from inifile
+ char *file; // ie "mm_test_i386.so", ptr from filename
+ char desc[MAX_DESC_LEN]; // ie "Test metamod plugin", from inifile
+ char pathname[PATH_MAX]; // UNIQUE, ie "/home/willday/half-life/cstrike/dlls/mm_test_i386.so", built with GameDLL.gamedir
+ int pfspecific; // level of specific platform affinity, used during load time
+
bool ini_parseline(char *line); // parse line from inifile
bool cmd_parseline(const char *line); // parse from console command
bool plugin_parseline(const char *fname, int loader_index); // parse from plugin
@@ -107,8 +103,8 @@ public:
bool resolve(); // find a matching file on disk
char *resolve_dirs(char *path);
- char *resolve_prefix(char *path);
- char *resolve_suffix(char *path);
+ char *resolve_prefix(char *path) const;
+ char *resolve_suffix(char *path) const;
bool platform_match(MPlugin* plugin);
@@ -151,6 +147,11 @@ public:
if (info) return str_loadtime(info->unloadable, fmt);
else return " -";
};
+
+private:
+ bool query();
+ bool attach(PLUG_LOADTIME now);
+ bool detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);
};
// Macros used by MPlugin::show(), to list the functions that the plugin
diff --git a/metamod/src/mreg.cpp b/metamod/src/mreg.cpp
index 22ae49d..3d053e9 100644
--- a/metamod/src/mreg.cpp
+++ b/metamod/src/mreg.cpp
@@ -172,14 +172,6 @@ void MRegCmdList::show(int plugin_id) const
int n = 0;
MRegCmd *icmd;
- // If OS doesn't support DLFNAME, then we can't know what the plugin's
- // registered cvars are.
- DLFNAME(NULL);
- if (meta_errno == ME_OSNOTSUP)
- {
- META_CONS("Registered commands: unknown (can't get info under this OS)");
- return;
- }
META_CONS("Registered commands:");
for (int i = 0; i < endlist; i++)
{
@@ -375,15 +367,6 @@ void MRegCvarList::show(int plugin_id) const
MRegCvar *icvar;
char bname[30 + 1], bval[15 + 1]; // +1 for term null
- // If OS doesn't support DLFNAME, then we can't know what the plugin's
- // registered cvars are.
- DLFNAME(NULL);
- if (meta_errno == ME_OSNOTSUP)
- {
- META_CONS("Registered cvars: unknown (can't get info under this OS)");
- return;
- }
-
META_CONS("%-*s %*s %s", sizeof(bname) - 1, "Registered cvars:", sizeof(bval) - 1, "float value", "string value");
for (int i = 0; i < endlist; i++)
{
diff --git a/metamod/src/mreg.h b/metamod/src/mreg.h
index 9395a51..eb8193f 100644
--- a/metamod/src/mreg.h
+++ b/metamod/src/mreg.h
@@ -128,4 +128,4 @@ private:
MRegMsg mlist[MAX_REG_MSGS]; // array of registered msgs
int size; // size of list, ie MAX_REG_MSGS
int endlist; // index of last used entry
-};
\ No newline at end of file
+};
diff --git a/metamod/src/mutil.cpp b/metamod/src/mutil.cpp
index 6b80875..3604191 100644
--- a/metamod/src/mutil.cpp
+++ b/metamod/src/mutil.cpp
@@ -119,7 +119,7 @@ qboolean EXT_FUNC mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_
{
plugin_info_t *plinfo = (plugin_info_t *)plid;
META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr, plinfo->name));
- ENTITY_FN pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
+ ENTITY_FN pfnEntity = (ENTITY_FN)GameDLL.sys_module.getsym(entStr);
if (!pfnEntity)
{
META_ERROR("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name);
@@ -268,7 +268,7 @@ int EXT_FUNC mutil_LoadMetaPlugin(plid_t plid, const char* fname, PLUG_LOADTIME
else
{
if (plugin_handle)
- *plugin_handle = (void *)pl_loaded->handle;
+ *plugin_handle = (void *)pl_loaded->sys_module.gethandle();
return 0;
}
}
@@ -310,7 +310,7 @@ int EXT_FUNC mutil_UnloadMetaPluginByHandle(plid_t plid, void *plugin_handle, PL
return ME_ARGUMENT;
}
- if (!(findp = g_plugins->find((DLHANDLE)plugin_handle)))
+ if (!(findp = g_plugins->find((module_handle_t)plugin_handle)))
return ME_NOTFOUND;
meta_errno = ME_NOERROR;
diff --git a/metamod/src/osdep.cpp b/metamod/src/osdep.cpp
index e7965f6..591da38 100644
--- a/metamod/src/osdep.cpp
+++ b/metamod/src/osdep.cpp
@@ -1,36 +1,128 @@
#include "precompiled.h"
-bool dlclose_handle_invalid;
+CSysModule::CSysModule() : m_handle(0), m_base(0), m_size(0)
+{
+}
#ifdef _WIN32
-// Since windows doesn't provide a verison of strtok_r(), we include one
-// here. This may or may not operate exactly like strtok_r(), but does
-// what we need it it do.
-char *my_strtok_r(char *s, const char *delim, char **ptrptr)
+module_handle_t CSysModule::load(const char* filepath)
{
- char *begin = nullptr;
- char *end = nullptr;
- char *rest = nullptr;
- if (s)
- begin = s;
- else
- begin = *ptrptr;
- if (!begin)
- return nullptr;
+ m_handle = LoadLibrary(filepath);
- end = strpbrk(begin, delim);
- if (end)
- {
- *end = '\0';
- rest = end + 1;
- *ptrptr = rest + strspn(rest, delim);
+ MODULEINFO module_info;
+ if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof(module_info))) {
+ m_base = (uintptr_t)module_info.lpBaseOfDll;
+ m_size = module_info.SizeOfImage;
}
- else
- *ptrptr = nullptr;
- return begin;
+ return m_handle;
+}
+
+bool CSysModule::unload()
+{
+ bool ret = false;
+
+ if (m_handle) {
+ ret = FreeLibrary(m_handle) != ERROR;
+ m_handle = 0;
+ m_base = 0;
+ m_size = 0;
+ }
+
+ return ret;
+}
+
+void* CSysModule::getsym(const char* name) const
+{
+ return GetProcAddress(m_handle, name);
+}
+#else
+static ElfW(Addr) dlsize(void* base)
+{
+ ElfW(Ehdr) *ehdr;
+ ElfW(Phdr) *phdr;
+ ElfW(Addr) end;
+
+ ehdr = (ElfW(Ehdr) *)base;
+
+ /* Find the first program header */
+ phdr = (ElfW(Phdr)*)((ElfW(Addr))ehdr + ehdr->e_phoff);
+
+ /* Find the final PT_LOAD segment's extent */
+ for (int i = 0; i < ehdr->e_phnum; ++i)
+ if (phdr[i].p_type == PT_LOAD)
+ end = phdr[i].p_vaddr + phdr[i].p_memsz;
+
+ /* The start (virtual) address is always zero, so just return end.*/
+ return end;
+}
+
+module_handle_t CSysModule::load(const char* filepath)
+{
+ m_handle = dlopen(filepath, RTLD_NOW);
+
+ char buf[1024], dummy[1024], path[260];
+ sprintf(buf, "/proc/%i/maps", getpid());
+
+ FILE* fp = fopen(buf, "r");
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ uintptr_t start, end;
+
+ int args = sscanf(buf, "%x-%x %128s %128s %128s %128s %255s", &start, &end, dummy, dummy, dummy, dummy, path);
+ if (args != 7) {
+ continue;
+ }
+
+ if (!Q_stricmp(path, filepath)) {
+ m_base = start;
+ m_size = end - start;
+ break;
+ }
+ }
+
+ fclose(fp);
+ return m_handle;
+}
+
+bool CSysModule::unload()
+{
+ bool ret = false;
+
+ if (m_handle) {
+ ret = dlclose(m_handle) != 0;
+ m_handle = 0;
+ m_base = 0;
+ m_size = 0;
+ }
+
+ return ret;
+}
+
+void* CSysModule::getsym(const char* name) const
+{
+ return dlsym(m_handle, name);
+}
+#endif
+
+module_handle_t CSysModule::gethandle() const
+{
+ return m_handle;
+}
+
+bool CSysModule::contain(void* addr) const
+{
+ return addr && uintptr_t(addr) > m_base && uintptr_t(addr) < m_base + m_size;
+}
+
+const char* CSysModule::getloaderror()
+{
+#ifdef _WIN32
+ return str_GetLastError();
+#else
+ return dlerror;
+#endif
}
-#endif // _WIN32
#ifdef _WIN32
// Windows doesn't provide a functon analagous to dlerr() that returns a
@@ -44,70 +136,16 @@ const char *str_GetLastError()
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, MAX_STRBUF_LEN - 1, NULL);
return buf;
}
+
+const char* str_os_error()
+{
+#ifdef _WIN32
+ return str_GetLastError();
+#else
+ return strerror(errno);
#endif
-
-// Find the filename of the DLL/shared-lib where the given memory location
-// exists.
-#if defined(linux) || defined(__APPLE__)
-// Errno values:
-// - ME_NOTFOUND couldn't find a sharedlib that contains memory location
-const char *DLFNAME(void *memptr)
-{
- Dl_info dli;
- Q_memset(&dli, 0, sizeof(dli));
- if (dladdr(memptr, &dli))
- return dli.dli_fname;
- else
- RETURN_ERRNO(NULL, ME_NOTFOUND);
}
-#elif defined(_WIN32)
-// Implementation for win32 provided by Jussi Kivilinna :
-//
-// 1. Get memory location info on memptr with VirtualQuery.
-// 2. Check if memory location info is valid and use MBI.AllocationBase
-// as module start point.
-// 3. Get module file name with GetModuleFileName.
-//
-// Simple and should work pretty much same way as 'dladdr' in linux.
-// VirtualQuery and GetModuleFileName work even with win32s.
-//
-// Note that GetModuleFileName returns longfilenames rather than 8.3.
-//
-// Note also, the returned filename is local static storage, and should be
-// copied by caller if it needs to keep it around.
-//
-// Also note, normalize_pathname() should really be done by the caller, but
-// is done here to preserve "const char *" return consistent with linux
-// version.
-//
-// Errno values:
-// - ME_NOTFOUND couldn't find a DLL that contains memory location
-const char *DLFNAME(void *memptr)
-{
- MEMORY_BASIC_INFORMATION MBI;
- static char fname[PATH_MAX];
-
- if (!VirtualQuery(memptr, &MBI, sizeof(MBI)))
- RETURN_ERRNO(NULL, ME_NOTFOUND);
-
- if (MBI.State != MEM_COMMIT)
- RETURN_ERRNO(NULL, ME_NOTFOUND);
-
- if (!MBI.AllocationBase)
- RETURN_ERRNO(NULL, ME_NOTFOUND);
-
- // MSDN indicates that GetModuleFileName will leave string
- // null-terminated, even if it's truncated because buffer is too small.
- if (!GetModuleFileName((HMODULE)MBI.AllocationBase, fname, sizeof(fname) - 1))
- RETURN_ERRNO(NULL, ME_NOTFOUND);
- if (!fname[0])
- RETURN_ERRNO(NULL, ME_NOTFOUND);
-
- normalize_pathname(fname);
- return fname;
-}
-#endif // _WIN32
-
+#endif
// Determine whether the given memory location is valid (ie whether we
// should expect to be able to reference strings or functions at this
diff --git a/metamod/src/osdep.h b/metamod/src/osdep.h
index 6c51dfc..a162e82 100644
--- a/metamod/src/osdep.h
+++ b/metamod/src/osdep.h
@@ -1,10 +1,5 @@
#pragma once
-// Various differences between WIN32 and Linux.
-#include "types_meta.h" // bool
-#include "mreg.h" // REG_CMD_FN, etc
-#include "log_meta.h" // LOG_ERROR, etc
-
// String describing platform/DLL-type, for matching lines in plugins.ini.
#ifdef _WIN32
#define UNUSED /**/
@@ -20,75 +15,31 @@
#define PLATFORM_DLEXT ".so"
#endif
-extern bool dlclose_handle_invalid;
+#include "mreg.h"
-// Functions & types for DLL open/close/etc operations.
#ifdef _WIN32
- typedef HINSTANCE DLHANDLE;
- typedef FARPROC DLFUNC;
- inline DLHANDLE DLOPEN(const char *filename)
- {
- return LoadLibraryA(filename);
- }
- inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
- {
- return GetProcAddress(handle, string);
- }
- inline int DLCLOSE(DLHANDLE handle)
- {
- if (!handle)
- {
- dlclose_handle_invalid = true;
- return 1;
- }
-
- dlclose_handle_invalid = false;
- // NOTE: Windows FreeLibrary returns success=nonzero, fail=zero,
- // which is the opposite of the unix convention, thus the '!'.
- return !FreeLibrary(handle);
- }
- // Windows doesn't provide a function corresponding to dlerror(), so
- // we make our own.
- const char *str_GetLastError();
- inline const char *DLERROR()
- {
- if (dlclose_handle_invalid)
- return "Invalid handle.";
-
- return str_GetLastError();
- }
+typedef HINSTANCE module_handle_t;
#else
- typedef void *DLHANDLE;
- typedef void *DLFUNC;
- inline DLHANDLE DLOPEN(const char *filename)
- {
- return dlopen(filename, RTLD_NOW);
- }
- inline DLFUNC DLSYM(DLHANDLE handle, const char *string)
- {
- return dlsym(handle, string);
- }
- // dlclose crashes if handle is null.
- inline int DLCLOSE(DLHANDLE handle)
- {
- if (!handle)
- {
- dlclose_handle_invalid = true;
- return 1;
- }
- dlclose_handle_invalid = false;
- return dlclose(handle);
- }
- inline const char *DLERROR()
- {
- if (dlclose_handle_invalid)
- return "Invalid handle.";
-
- return dlerror();
- }
+typedef void* module_handle_t;
#endif
-const char *DLFNAME(void *memptr);
+class CSysModule
+{
+public:
+ CSysModule();
+ module_handle_t load(const char* filename);
+ bool unload();
+ void* getsym(const char* name) const;
+ module_handle_t gethandle() const;
+ bool contain(void* addr) const;
+ static const char* getloaderror();
+
+private:
+ module_handle_t m_handle;
+ uintptr_t m_base;
+ uintptr_t m_size;
+};
+
bool IS_VALID_PTR(void *memptr);
// Attempt to call the given function pointer, without segfaulting.
@@ -96,15 +47,9 @@ bool os_safe_call(REG_CMD_FN pfn);
// Windows doesn't have an strtok_r() routine, so we write our own.
#ifdef _WIN32
- #define strtok_r(s, delim, ptrptr) my_strtok_r(s, delim, ptrptr)
- char *my_strtok_r(char *s, const char *delim, char **ptrptr);
-#else
-// Linux doesn't have an strlwr() routine, so we write our own.
- #define strlwr(s) my_strlwr(s)
- char *my_strlwr(char *s);
+ #define strtok_r(s, delim, ptrptr) mm_strtok_r(s, delim, ptrptr)
#endif // _WIN32
-
// Set filename and pathname maximum lengths. Note some windows compilers
// provide a which is incomplete and/or causes problems; see
// doc/windows_notes.txt for more information.
@@ -165,89 +110,8 @@ bool os_safe_call(REG_CMD_FN pfn);
#ifndef S_IWGRP
#define S_IWGRP S_IWUSR
#endif
+
+ const char *str_GetLastError();
#endif // _WIN32
-// Normalize/standardize a pathname.
-// - For win32, this involves:
-// - Turning backslashes (\) into slashes (/), so that config files and
-// Metamod internal code can be simpler and just use slashes (/).
-// - Turning upper/mixed case into lowercase, since windows is
-// non-case-sensitive.
-// - For linux, this requires no work, as paths uses slashes (/) natively,
-// and pathnames are case-sensitive.
-#if defined(__linux) || defined(__APPLE__)
-#define normalize_pathname(a)
-#elif defined(_WIN32)
-inline void normalize_pathname(char *path)
-{
- char *cp;
-
- META_DEBUG(8, ("normalize: %s", path));
- for (cp = path; *cp; cp++)
- {
- if (isupper(*cp)) *cp = tolower(*cp);
- if (*cp == '\\') *cp = '/';
- }
-
- META_DEBUG(8, ("normalized: %s", path));
-}
-#endif // _WIN32
-
-// Indicate if pathname appears to be an absolute-path. Under linux this
-// is a leading slash (/). Under win32, this can be:
-// - a drive-letter path (ie "D:blah" or "C:\blah")
-// - a toplevel path (ie "\blah")
-// - a UNC network address (ie "\\srv1\blah").
-// Also, handle both native and normalized pathnames.
-inline int is_absolute_path(const char *path)
-{
- if (path[0] == '/') return TRUE;
-#ifdef _WIN32
- if (path[1] == ':') return TRUE;
- if (path[0] == '\\') return TRUE;
-#endif // _WIN32
- return FALSE;
-}
-
-#ifdef _WIN32
-// Buffer pointed to by resolved_name is assumed to be able to store a
-// string of PATH_MAX length.
-inline char *realpath(const char *file_name, char *resolved_name)
-{
- int ret;
- ret = GetFullPathName(file_name, PATH_MAX, resolved_name, NULL);
- if (ret > PATH_MAX)
- {
- errno = ENAMETOOLONG;
- return NULL;
- }
- else if (ret > 0)
- {
- HANDLE handle;
- WIN32_FIND_DATA find_data;
- handle = FindFirstFile(resolved_name, &find_data);
- if (INVALID_HANDLE_VALUE == handle)
- {
- errno = ENOENT;
- return NULL;
- }
-
- FindClose(handle);
- normalize_pathname(resolved_name);
- return resolved_name;
- }
-
- return NULL;
-}
-#endif // _WIN32
-
-// Generic "error string" from a recent OS call. For linux, this is based
-// on errno. For win32, it's based on GetLastError.
-inline const char *str_os_error()
-{
-#ifdef _WIN32
- return str_GetLastError();
-#else
- return strerror(errno);
-#endif
-}
+const char* str_os_error();
diff --git a/metamod/src/precompiled.h b/metamod/src/precompiled.h
index acdd63b..797db0f 100644
--- a/metamod/src/precompiled.h
+++ b/metamod/src/precompiled.h
@@ -2,6 +2,8 @@
#include "version/appversion.h"
+#define PSAPI_VERSION 1
+
#if defined(linux) || defined(__APPLE__)
// enable extra routines in system header files, like dladdr
#ifndef _GNU_SOURCE
diff --git a/metamod/src/reg_support.cpp b/metamod/src/reg_support.cpp
index 349b8b8..6ffb60e 100644
--- a/metamod/src/reg_support.cpp
+++ b/metamod/src/reg_support.cpp
@@ -80,13 +80,12 @@ void EXT_FUNC meta_command_handler()
// to a generic command-handler function (see above).
void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)())
{
- MPlugin *iplug = NULL;
- MRegCmd *icmd = NULL;
+ MPlugin *iplug = g_plugins->find_memloc(function);
META_DEBUG(4, ("called: meta_AddServerCommand; cmd_name=%s, function=%d", cmd_name, function));
// try to find which plugin is registering this command
- if (!(iplug = g_plugins->find_memloc((void *)function)))
+ if (!iplug)
{
// if this isn't supported on this OS, don't log an error
if (meta_errno != ME_OSNOTSUP)
@@ -94,7 +93,7 @@ void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)())
}
// See if this command was previously registered, ie a "reloaded" plugin.
- icmd = g_regCmds->find(cmd_name);
+ auto icmd = g_regCmds->find(cmd_name);
if (!icmd)
{
// If not found, add.
@@ -134,27 +133,18 @@ void EXT_FUNC meta_AddServerCommand(char *cmd_name, void (*function)())
// it will fail to work properly.
void EXT_FUNC meta_CVarRegister(cvar_t *pCvar)
{
- MPlugin *iplug = nullptr;
- MRegCvar *icvar = nullptr;
+ MPlugin *iplug = g_plugins->find_memloc(pCvar);
META_DEBUG(4, ("called: meta_CVarRegister; name=%s", pCvar->name));
- if (!strncmp(pCvar->name, "iz_", 3))
- __asm int 3;
-
// try to find which plugin is registering this cvar
- if (!(iplug = g_plugins->find_memloc((void *)pCvar)))
+ if (!iplug)
{
- // if this isn't supported on this OS, don't log an error
- if (meta_errno != ME_OSNOTSUP)
- // Note: if cvar_t was malloc'd by the plugin, we can't
- // determine the calling plugin. Thus, this becomes a Debug
- // rather than Error message.
META_DEBUG(1, ("Failed to find memloc for regcvar '%s'", pCvar->name));
}
// See if this cvar was previously registered, ie a "reloaded" plugin.
- icvar = g_regCvars->find(pCvar->name);
+ auto icvar = g_regCvars->find(pCvar->name);
if (!icvar)
{
// If not found, add.
diff --git a/metamod/src/studioapi.cpp b/metamod/src/studioapi.cpp
index b33f4f3..d088255 100644
--- a/metamod/src/studioapi.cpp
+++ b/metamod/src/studioapi.cpp
@@ -44,12 +44,11 @@ C_DLLEXPORT int Server_GetBlendingInterface(int version,
if (!getblend)
{
META_DEBUG(6, ("Looking up Server_GetBlendingInterface"));
- getblend = (GETBLENDAPI_FN) DLSYM(GameDLL.handle,
- "Server_GetBlendingInterface");
+ getblend = (GETBLENDAPI_FN)GameDLL.sys_module.getsym("Server_GetBlendingInterface");
}
if (!getblend)
{
- META_DEBUG(6, ("Couldn't find Server_GetBlendingInterface in game DLL '%s': %s", GameDLL.name, DLERROR()));
+ META_DEBUG(6, ("Couldn't find Server_GetBlendingInterface in game DLL '%s': %s", GameDLL.name, "function not found"));
missing = 1;
return 0;
}
diff --git a/metamod/src/utils.cpp b/metamod/src/utils.cpp
index 9211eec..2ce8c7e 100644
--- a/metamod/src/utils.cpp
+++ b/metamod/src/utils.cpp
@@ -58,3 +58,83 @@ void execmem_allocator::allocate_page()
m_used = 0;
m_pages.push_back(page);
}
+
+#ifdef _WIN32
+// Since windows doesn't provide a verison of strtok_r(), we include one
+// here. This may or may not operate exactly like strtok_r(), but does
+// what we need it it do.
+char *mm_strtok_r(char *s, const char *delim, char **ptrptr)
+{
+ char *begin = nullptr;
+ char *end = nullptr;
+ char *rest = nullptr;
+ if (s)
+ begin = s;
+ else
+ begin = *ptrptr;
+ if (!begin)
+ return nullptr;
+
+ end = strpbrk(begin, delim);
+ if (end) {
+ *end = '\0';
+ rest = end + 1;
+ *ptrptr = rest + strspn(rest, delim);
+ }
+ else
+ *ptrptr = nullptr;
+
+ return begin;
+}
+#endif // _WIN32
+
+void normalize_pathname(char *path)
+{
+#ifdef _WIN32
+ char *cp;
+
+ META_DEBUG(8, ("normalize: %s", path));
+ for (cp = path; *cp; cp++) {
+ if (isupper(*cp)) *cp = tolower(*cp);
+ if (*cp == '\\') *cp = '/';
+ }
+
+ META_DEBUG(8, ("normalized: %s", path));
+#endif
+}
+
+bool is_absolute_path(const char *path)
+{
+ if (path[0] == '/') return true;
+#ifdef _WIN32
+ if (path[1] == ':') return true;
+ if (path[0] == '\\') return true;
+#endif // _WIN32
+ return false;
+}
+
+char *realpath(const char *file_name, char *resolved_name)
+{
+ int ret = GetFullPathName(file_name, PATH_MAX, resolved_name, NULL);
+
+ if (ret > PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+
+ if (ret > 0) {
+ HANDLE handle;
+ WIN32_FIND_DATA find_data;
+ handle = FindFirstFile(resolved_name, &find_data);
+ if (INVALID_HANDLE_VALUE == handle) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ FindClose(handle);
+ normalize_pathname(resolved_name);
+ return resolved_name;
+ }
+
+ return NULL;
+}
diff --git a/metamod/src/utils.h b/metamod/src/utils.h
index 72d6f1b..dfb1351 100644
--- a/metamod/src/utils.h
+++ b/metamod/src/utils.h
@@ -23,3 +23,11 @@ bool is_yes(const char* str);
bool is_no(const char* str);
const char* LOCALINFO(char* key);
+
+#ifdef _WIN32
+char *mm_strtok_r(char *s, const char *delim, char **ptrptr);
+#endif
+
+void normalize_pathname(char *path);
+bool is_absolute_path(const char *path);
+char *realpath(const char *file_name, char *resolved_name);