Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ extern plugin_globals_t g_plugin_globals;
extern std::vector<plugin_t> g_plugins;

const char* plugin_result_to_str(pluginres_t res);
bool plugin_load(plugin_t& p, std::string file);
// returns: -1 if failed to load and don't continue, 0 if failed to load and continue, 1 if loaded
int plugin_load(plugin_t& p, std::string file);
void plugin_unload(plugin_t& p);

#endif // __QMM2_PLUGIN_H__
34 changes: 20 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static void s_main_detect_env();
static void s_main_load_config(bool quiet = false);
static void s_main_detect_game(std::string cfg_game, bool is_GetGameAPI_mode);
static bool s_main_load_mod(std::string cfg_mod);
static void s_main_load_plugin(std::string plugin_path);
static bool s_main_load_plugin(std::string plugin_path);
static intptr_t s_main_handle_command_qmm(int arg_inc);
static intptr_t s_main_route_vmmain(intptr_t cmd, intptr_t* args);
static intptr_t s_main_route_syscall(intptr_t cmd, intptr_t* args);
Expand Down Expand Up @@ -347,8 +347,11 @@ C_DLLEXPORT intptr_t vmMain(intptr_t cmd, ...) {
// load plugins
LOG(QMM_LOG_INFO, "QMM") << "Attempting to load plugins\n";
for (auto plugin_path : cfg_get_array_str(g_cfg, "plugins")) {
LOG(QMM_LOG_INFO, "QMM") << fmt::format("Attempting to load plugin \"{}\"\n", plugin_path);
s_main_load_plugin(plugin_path);
LOG(QMM_LOG_INFO, "QMM") << fmt::format("Attempting to load plugin \"{}\"...\n", plugin_path);
if (s_main_load_plugin(plugin_path))
LOG(QMM_LOG_INFO, "QMM") << fmt::format("Plugin \"{}\" loaded\n", plugin_path);
else
LOG(QMM_LOG_INFO, "QMM") << fmt::format("Plugin \"{}\" not loaded\n", plugin_path);
}
LOG(QMM_LOG_NOTICE, "QMM") << fmt::format("Successfully loaded {} plugin(s)\n", g_plugins.size());

Expand Down Expand Up @@ -606,16 +609,16 @@ static bool s_main_load_mod(std::string cfg_mod) {


// general code to find a plugin file to load
static void s_main_load_plugin(std::string plugin_path) {
static bool s_main_load_plugin(std::string plugin_path) {
plugin_t p;
// absolute path, just attempt to load it directly
if (!path_is_relative(plugin_path)) {
// if the plugin decides to cancel itself in QMM_Attach, then plugin_load returns success
// but we only want to only store the plugin if it really loaded
if (plugin_load(p, plugin_path) && p.dll) {
// plugin_load returns 0 if no plugin file was found, 1 if success, and -1 if file was found but failure
if (plugin_load(p, plugin_path) > 0) {
g_plugins.push_back(p);
return true;
}
return;
return false;
}
// relative path, try the following locations in order:
// "<qmmdir>/<plugin>"
Expand All @@ -627,14 +630,17 @@ static void s_main_load_plugin(std::string plugin_path) {
fmt::format("./{}/{}", g_gameinfo.moddir, plugin_path)
};
for (auto& try_path : try_paths) {
// if the plugin decides to cancel itself in QMM_Attach, then plugin_load returns success
// but we only want to only store the plugin if it really loaded
if (plugin_load(p, try_path)) {
if (p.dll)
g_plugins.push_back(p);
return;
// plugin_load returns 0 if no plugin file was found, 1 if success, and -1 if file was found but failure
int ret = plugin_load(p, try_path);
if (ret > 0) {
g_plugins.push_back(p);
return true;
}
if (ret < 0)
return false;
}

return false;
}


Expand Down
29 changes: 22 additions & 7 deletions src/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ const char* plugin_result_to_str(pluginres_t res) {
}


bool plugin_load(plugin_t& p, std::string file) {
// returns: -1 if failed to load and don't continue, 0 if failed to load and continue, 1 if loaded
int plugin_load(plugin_t& p, std::string file) {
int ret = 0;

// if this plugin_t somehow already has a dll pointer, wipe it first
if (p.dll)
plugin_unload(p);
Expand All @@ -106,9 +109,21 @@ bool plugin_load(plugin_t& p, std::string file) {
// if this DLL is the same as QMM, cancel
if ((void*)p.dll == g_gameinfo.qmm_module_ptr) {
LOG(QMM_LOG_ERROR, "QMM") << fmt::format("plugin_load(\"{}\"): DLL is actually QMM?\n", file);
// treat this failure specially. this is a valid DLL, but it is QMM
ret = -1;
goto fail;
}

// if this DLL is the same as another loaded plugin, cancel
for (plugin_t& t : g_plugins) {
if (p.dll == t.dll) {
LOG(QMM_LOG_ERROR, "QMM") << fmt::format("plugin_load(\"{}\"): DLL is already loaded as plugin\n", file);
// treat this failure specially. this is a valid plugin, but it is already loaded
ret = -1;
goto fail;
}
}

if (!(p.QMM_Query = (plugin_query)dlsym(p.dll, "QMM_Query"))) {
LOG(QMM_LOG_ERROR, "QMM") << fmt::format("plugin_load(\"{}\"): Unable to find \"QMM_Query\" function\n", file);
goto fail;
Expand Down Expand Up @@ -178,18 +193,18 @@ bool plugin_load(plugin_t& p, std::string file) {
// QMM_Attach(engine syscall, mod vmmain, pointer to plugin result int, table of plugin helper functions, table of plugin variables)
if (!(p.QMM_Attach(g_gameinfo.pfnsyscall, g_mod.pfnvmMain, &g_plugin_globals.plugin_result, &s_pluginfuncs, &s_pluginvars))) {
LOG(QMM_LOG_ERROR, "QMM") << fmt::format("plugin_load(\"{}\"): QMM_Attach() returned 0\n", file);
// treat this failure specially. since this is a valid plugin, but decided on its own that it shouldn't be loaded,
// we return "true" so that QMM will not try to load the plugin again on a different path
plugin_unload(p);
return true;
// treat this failure specially. this is a valid plugin, but it decided on its own that it shouldn't be loaded
ret = -1;
goto fail;
}

p.path = file;
return true;
ret = 1;
return ret;

fail:
plugin_unload(p);
return false;
return ret;
}


Expand Down