mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2026-03-21 17:25:21 -05:00
Unload unactive plugin when wiiloading a plugin with the same name and author
This commit is contained in:
parent
b031576757
commit
5321272924
|
|
@ -172,6 +172,9 @@ bool PluginManagement::doRelocations(const std::vector<PluginContainer> &plugins
|
|||
|
||||
bool PluginManagement::RestoreFunctionPatches(std::vector<PluginContainer> &plugins) {
|
||||
for (auto &cur : std::ranges::reverse_view(plugins)) {
|
||||
if (!cur.isLinkedAndLoaded()) {
|
||||
continue;
|
||||
}
|
||||
for (auto &curFunction : std::ranges::reverse_view(cur.getPluginLinkInformation().getFunctionDataList())) {
|
||||
if (!curFunction.RemovePatch()) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to remove function patch for: plugin %s", cur.getMetaInformation().getName().c_str());
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@ namespace WUPSConfigAPIBackend {
|
|||
return WUPSCONFIG_API_RESULT_INVALID_ARGUMENT;
|
||||
}
|
||||
for (auto &cur : gLoadedPlugins) {
|
||||
if (!cur.isLinkedAndLoaded()) {
|
||||
continue;
|
||||
}
|
||||
if (cur.getHandle() == pluginIdentifier) {
|
||||
if (options.version != 1) {
|
||||
return WUPSCONFIG_API_RESULT_UNSUPPORTED_VERSION;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,10 @@ void CallHook(const std::vector<PluginContainer> &plugins, const wups_loader_hoo
|
|||
}
|
||||
}
|
||||
|
||||
void CallHook(const PluginContainer &plugin, wups_loader_hook_type_t hook_type) {
|
||||
void CallHook(const PluginContainer &plugin, const wups_loader_hook_type_t hook_type) {
|
||||
if (!plugin.isLinkedAndLoaded()) {
|
||||
return;
|
||||
}
|
||||
for (const auto &hook : plugin.getPluginLinkInformation().getHookDataList()) {
|
||||
if (hook.getType() == hook_type) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s for plugin %s [%d]", hook_names[hook.getType()], plugin.getMetaInformation().getName().c_str(), hook_type);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "plugin/PluginData.h"
|
||||
#include "plugin/PluginDataFactory.h"
|
||||
#include "plugin/PluginLoadWrapper.h"
|
||||
#include "plugin/PluginMetaInformationFactory.h"
|
||||
#include "plugin/RelocationData.h"
|
||||
#include "plugin/SectionInfo.h"
|
||||
#include "utils/DrawUtils.h"
|
||||
|
|
@ -197,15 +198,81 @@ WUMS_APPLICATION_STARTS() {
|
|||
DEBUG_FUNCTION_LINE_INFO("Got new list of plugins to load");
|
||||
std::vector<PluginContainer> pluginsToKeep;
|
||||
std::vector<PluginLoadWrapper> toBeLoaded;
|
||||
std::vector<PluginLoadWrapper> filteredLoadOnNextLaunch;
|
||||
|
||||
{
|
||||
struct MetaInfoShort {
|
||||
MetaInfoShort() = default;
|
||||
MetaInfoShort(const PluginMetaInformation &metaInfo) : name(metaInfo.getName()), author(metaInfo.getAuthor()) {}
|
||||
bool operator==(const MetaInfoShort &other) const {
|
||||
return name == other.name && author == other.author;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string author;
|
||||
};
|
||||
// Build a meta info cache for
|
||||
std::map<uint32_t, MetaInfoShort> pluginMetaInformationCache;
|
||||
for (const auto &pluginLoadWrapper : gLoadOnNextLaunch) {
|
||||
const auto &pluginData = pluginLoadWrapper.getPluginData();
|
||||
// Skip already cached entries
|
||||
if (pluginMetaInformationCache.contains(pluginData->getHandle())) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Skip parsing meta information for %08X because it's already cached", pluginData->getHandle());
|
||||
continue;
|
||||
}
|
||||
// First to get a copy of meta information from the already loaded plugins
|
||||
if (const auto it = std::ranges::find_if(gLoadedPlugins, [&pluginLoadWrapper](const PluginContainer &plugin) {
|
||||
return plugin.getPluginDataCopy()->getHandle() == pluginLoadWrapper.getPluginData()->getHandle();
|
||||
});
|
||||
it != gLoadedPlugins.end()) {
|
||||
pluginMetaInformationCache[pluginData->getHandle()] = it->getMetaInformation();
|
||||
continue;
|
||||
}
|
||||
// If this fails, we parse try to parse it instead
|
||||
PluginParseErrors err;
|
||||
if (const auto metaInfoOpt = PluginMetaInformationFactory::loadPlugin(*pluginData, err)) {
|
||||
pluginMetaInformationCache[pluginData->getHandle()] = *metaInfoOpt;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to parse meta data for plugin data handle %08X", pluginData->getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we want to link a plugin that's currently unloaded
|
||||
// E.g. if you disable a plugin from the config menu and then wiiload it, the disabled plugin copy should be unloaded
|
||||
for (const auto &pluginLoadWrapper : gLoadOnNextLaunch) {
|
||||
if (!pluginLoadWrapper.isLoadAndLink()) {
|
||||
const auto unloadedMetaInfoIt = pluginMetaInformationCache.find(pluginLoadWrapper.getPluginData()->getHandle());
|
||||
if (unloadedMetaInfoIt == pluginMetaInformationCache.end()) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to find meta information for plugin data handle %08X", pluginLoadWrapper.getPluginData()->getHandle());
|
||||
continue;
|
||||
}
|
||||
if (const auto it = std::ranges::find_if(gLoadOnNextLaunch, [&pluginLoadWrapper, &pluginMetaInformationCache, &unloadedMetaInfoIt](const PluginLoadWrapper &plugin) {
|
||||
const bool differentPluginData = plugin.getPluginData()->getHandle() != pluginLoadWrapper.getPluginData()->getHandle();
|
||||
const bool otherWillBeLinked = plugin.isLoadAndLink();
|
||||
bool sameAuthorAndName = false;
|
||||
if (const auto otherMetaInfoIt = pluginMetaInformationCache.find(plugin.getPluginData()->getHandle()); otherMetaInfoIt != pluginMetaInformationCache.end()) {
|
||||
const auto &otherMetaInfo = otherMetaInfoIt->second;
|
||||
const auto &unloadedMetaInfo = unloadedMetaInfoIt->second;
|
||||
sameAuthorAndName = otherMetaInfo == unloadedMetaInfo;
|
||||
}
|
||||
return differentPluginData && otherWillBeLinked && sameAuthorAndName;
|
||||
});
|
||||
it != gLoadOnNextLaunch.end()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
filteredLoadOnNextLaunch.push_back(pluginLoadWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
// Check which plugins are already loaded and which needs to be
|
||||
for (const auto &pluginLoadWrapper : gLoadOnNextLaunch) {
|
||||
for (const auto &pluginLoadWrapper : filteredLoadOnNextLaunch) {
|
||||
const auto &pluginNeedsNoReloadFn = [&pluginLoadWrapper](const PluginContainer &container) {
|
||||
return (container.getPluginDataCopy()->getHandle() == pluginLoadWrapper.getPluginData()->getHandle()) &&
|
||||
(container.isLinkedAndLoaded() == pluginLoadWrapper.isLoadAndLink());
|
||||
};
|
||||
// Check if the plugin data is already loaded
|
||||
if (auto it = std::ranges::find_if(gLoadedPlugins, pluginNeedsNoReloadFn);
|
||||
if (const auto it = std::ranges::find_if(gLoadedPlugins, pluginNeedsNoReloadFn);
|
||||
it != gLoadedPlugins.end()) {
|
||||
pluginsToKeep.push_back(std::move(*it));
|
||||
gLoadedPlugins.erase(it);
|
||||
|
|
@ -255,7 +322,7 @@ WUMS_APPLICATION_STARTS() {
|
|||
CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WRAPPER, needsInitsCheck);
|
||||
|
||||
for (auto &plugin : gLoadedPlugins) {
|
||||
if (plugin.isInitDone()) { continue; }
|
||||
if (plugin.isInitDone() && !plugin.isLinkedAndLoaded()) { continue; }
|
||||
if (const WUPSStorageError err = plugin.OpenStorage(); err != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to open storage for plugin: %s. (%s)", plugin.getMetaInformation().getName().c_str(), WUPSStorageAPI_GetStatusStr(err));
|
||||
}
|
||||
|
|
@ -275,6 +342,10 @@ void CleanupPlugins(std::vector<PluginContainer> &&pluginsToDeinit) {
|
|||
const auto saved_reent = currentThread->reserved[4];
|
||||
const auto saved_cleanupCallback = currentThread->cleanupCallback;
|
||||
|
||||
for (const auto &pluginContainer : pluginsToDeinit) {
|
||||
DEBUG_FUNCTION_LINE_INFO("De-init plugin %s from %s. PluginData: %08X", pluginContainer.getMetaInformation().getName().c_str(), pluginContainer.getMetaInformation().getAuthor().c_str(), pluginContainer.getPluginDataCopy()->getHandle());
|
||||
}
|
||||
|
||||
currentThread->reserved[4] = 0;
|
||||
|
||||
CallHook(pluginsToDeinit, WUPS_LOADER_HOOK_DEINIT_PLUGIN);
|
||||
|
|
@ -292,7 +363,7 @@ void CleanupPlugins(std::vector<PluginContainer> &&pluginsToDeinit) {
|
|||
PluginManagement::RestoreFunctionPatches(pluginsToDeinit);
|
||||
|
||||
for (auto &plugin : pluginsToDeinit) {
|
||||
if (!plugin.isInitDone()) { continue; }
|
||||
if (!plugin.isInitDone() || !plugin.isLinkedAndLoaded()) { continue; }
|
||||
if (const WUPSStorageError err = plugin.CloseStorage(); err != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to close storage for plugin: %s", plugin.getMetaInformation().getName().c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: What happens when we wiiload a new version of an inactive plugin? Do we consider that a problem?
|
||||
// add all loaded plugins that are not active as inactive
|
||||
// Keep inactive plugins loaded. Duplicates will be eliminated by comparing name/author
|
||||
for (const auto &plugin : gLoadedPlugins) {
|
||||
if (!plugin.isLinkedAndLoaded()) {
|
||||
gLoadOnNextLaunch.emplace_back(plugin.getPluginDataCopy(), false);
|
||||
|
|
@ -178,6 +177,9 @@ extern "C" PluginBackendApiErrorType WUPSGetPluginDataForContainerHandles(const
|
|||
const auto handle = plugin_container_handle_list[i];
|
||||
bool found = false;
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (!curContainer.isLinkedAndLoaded()) {
|
||||
continue;
|
||||
}
|
||||
if (curContainer.getHandle() == handle) {
|
||||
auto pluginData = curContainer.getPluginDataCopy();
|
||||
plugin_data_list[i] = pluginData->getHandle();
|
||||
|
|
@ -202,6 +204,9 @@ extern "C" PluginBackendApiErrorType WUPSGetMetaInformation(const wups_backend_p
|
|||
auto handle = plugin_container_handle_list[i];
|
||||
bool found = false;
|
||||
for (const auto &curContainer : gLoadedPlugins) {
|
||||
if (!curContainer.isLinkedAndLoaded()) {
|
||||
continue;
|
||||
}
|
||||
if (curContainer.getHandle() == handle) {
|
||||
const auto &metaInfo = curContainer.getMetaInformation();
|
||||
|
||||
|
|
@ -278,7 +283,7 @@ extern "C" PluginBackendApiErrorType WUPSGetNumberOfLoadedPlugins(uint32_t *outC
|
|||
if (outCount == nullptr) {
|
||||
return PLUGIN_BACKEND_API_ERROR_INVALID_ARG;
|
||||
}
|
||||
*outCount = std::count_if(gLoadedPlugins.begin(), gLoadedPlugins.end(), [](const auto &cur) { return cur.isLinkedAndLoaded(); });
|
||||
*outCount = std::ranges::count_if(gLoadedPlugins, [](const auto &cur) { return cur.isLinkedAndLoaded(); });
|
||||
return PLUGIN_BACKEND_API_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user