diff --git a/source/PluginManagement.cpp b/source/PluginManagement.cpp index 60b912d..3a0c900 100644 --- a/source/PluginManagement.cpp +++ b/source/PluginManagement.cpp @@ -13,17 +13,18 @@ #include #include +static uint32_t sTrampolineID = 0; + std::vector -PluginManagement::loadPlugins(const std::set> &pluginDataList, std::vector &trampolineData) { +PluginManagement::loadPlugins(const std::set, PluginDataSharedPtrComparator> &pluginDataList, std::vector &trampolineData) { std::vector plugins; - uint32_t trampolineID = 0; for (const auto &pluginData : pluginDataList) { PluginParseErrors error = PLUGIN_PARSE_ERROR_UNKNOWN; auto metaInfo = PluginMetaInformationFactory::loadPlugin(*pluginData, error); if (metaInfo && error == PLUGIN_PARSE_ERROR_NONE) { - auto info = PluginInformationFactory::load(*pluginData, trampolineData, trampolineID++); + auto info = PluginInformationFactory::load(*pluginData, trampolineData, sTrampolineID++); if (!info) { auto errMsg = string_format("Failed to load plugin: %s", pluginData->getSource().c_str()); DEBUG_FUNCTION_LINE_ERR("%s", errMsg.c_str()); @@ -79,8 +80,7 @@ bool PluginManagement::doRelocation(const std::vector &relocData if (!usedRPls.contains(rplName)) { DEBUG_FUNCTION_LINE_VERBOSE("Acquire %s", rplName.c_str()); // Always acquire to increase refcount and make sure it won't get unloaded while we're using it. - OSDynLoad_Error err = OSDynLoad_Acquire(rplName.c_str(), &rplHandle); - if (err != OS_DYNLOAD_OK) { + if (const OSDynLoad_Error err = OSDynLoad_Acquire(rplName.c_str(), &rplHandle); err != OS_DYNLOAD_OK) { DEBUG_FUNCTION_LINE_ERR("Failed to acquire %s", rplName.c_str()); return false; } @@ -91,7 +91,7 @@ bool PluginManagement::doRelocation(const std::vector &relocData rplHandle = usedRPls[rplName]; } - OSDynLoad_FindExport(rplHandle, (OSDynLoad_ExportType) isData, functionName.c_str(), (void **) &functionAddress); + OSDynLoad_FindExport(rplHandle, static_cast(isData), functionName.c_str(), reinterpret_cast(&functionAddress)); } if (functionAddress == 0) { @@ -101,7 +101,7 @@ bool PluginManagement::doRelocation(const std::vector &relocData //DEBUG_FUNCTION_LINE("Found export for %s %s", rplName.c_str(), functionName.c_str()); } - if (!ElfUtils::elfLinkOne(cur.getType(), cur.getOffset(), cur.getAddend(), (uint32_t) cur.getDestination(), functionAddress, trampData, RELOC_TYPE_IMPORT, trampolineID)) { + if (!ElfUtils::elfLinkOne(cur.getType(), cur.getOffset(), cur.getAddend(), reinterpret_cast(cur.getDestination()), functionAddress, trampData, RELOC_TYPE_IMPORT, trampolineID)) { DEBUG_FUNCTION_LINE_ERR("elfLinkOne failed"); return false; } @@ -156,6 +156,7 @@ bool PluginManagement::RestoreFunctionPatches(std::vector &plug for (auto &cur : std::ranges::reverse_view(plugins)) { for (auto &curFunction : std::ranges::reverse_view(cur.getPluginInformation().getFunctionDataList())) { if (!curFunction.RemovePatch()) { + DEBUG_FUNCTION_LINE_ERR("Failed to remove function patch for: plugin %s", cur.getMetaInformation().getName().c_str()); return false; } } @@ -175,10 +176,10 @@ bool PluginManagement::DoFunctionPatches(std::vector &plugins) return true; } -void PluginManagement::callInitHooks(const std::vector &plugins) { - CallHook(plugins, WUPS_LOADER_HOOK_INIT_CONFIG); - CallHook(plugins, WUPS_LOADER_HOOK_INIT_STORAGE_DEPRECATED); - CallHook(plugins, WUPS_LOADER_HOOK_INIT_STORAGE); - CallHook(plugins, WUPS_LOADER_HOOK_INIT_PLUGIN); +void PluginManagement::callInitHooks(const std::vector &plugins, const std::function &pred) { + CallHook(plugins, WUPS_LOADER_HOOK_INIT_CONFIG, pred); + CallHook(plugins, WUPS_LOADER_HOOK_INIT_STORAGE_DEPRECATED, pred); + CallHook(plugins, WUPS_LOADER_HOOK_INIT_STORAGE, pred); + CallHook(plugins, WUPS_LOADER_HOOK_INIT_PLUGIN, pred); DEBUG_FUNCTION_LINE_VERBOSE("Done calling init hooks"); } \ No newline at end of file diff --git a/source/PluginManagement.h b/source/PluginManagement.h index f1b2d2c..f5a4691 100644 --- a/source/PluginManagement.h +++ b/source/PluginManagement.h @@ -1,7 +1,9 @@ #pragma once #include "plugin/PluginContainer.h" + #include +#include #include #include #include @@ -10,10 +12,10 @@ class PluginManagement { public: static std::vector loadPlugins( - const std::set> &pluginDataList, + const std::set, PluginDataSharedPtrComparator> &pluginDataList, std::vector &trampolineData); - static void callInitHooks(const std::vector &plugins); + static void callInitHooks(const std::vector &plugins, const std::function &pred); static bool doRelocations(const std::vector &plugins, std::vector &trampData, diff --git a/source/globals.cpp b/source/globals.cpp index 85f4f15..9046d00 100644 --- a/source/globals.cpp +++ b/source/globals.cpp @@ -8,8 +8,8 @@ StoredBuffer gStoredDRCBuffer = {}; std::vector gLoadedPlugins; std::vector gTrampData; -std::set> gLoadedData; -std::set> gLoadOnNextLaunch; +std::set, PluginDataSharedPtrComparator> gLoadedData; +std::vector> gLoadOnNextLaunch; std::mutex gLoadedDataMutex; std::map gUsedRPLs; std::vector gAllocatedAddresses; diff --git a/source/globals.h b/source/globals.h index 135d4c7..786c5d2 100644 --- a/source/globals.h +++ b/source/globals.h @@ -13,6 +13,7 @@ #define MODULE_VERSION "v0.3.4" #define MODULE_VERSION_FULL MODULE_VERSION MODULE_VERSION_EXTRA +class PluginDataSharedPtrComparator; class PluginData; class PluginContainer; @@ -23,8 +24,8 @@ extern StoredBuffer gStoredDRCBuffer; extern std::vector gTrampData; extern std::vector gLoadedPlugins; -extern std::set> gLoadedData; -extern std::set> gLoadOnNextLaunch; +extern std::set, PluginDataSharedPtrComparator> gLoadedData; +extern std::vector> gLoadOnNextLaunch; extern std::mutex gLoadedDataMutex; extern std::map gUsedRPLs; extern std::vector gAllocatedAddresses; diff --git a/source/hooks.cpp b/source/hooks.cpp index 7a09d9f..8ee67e9 100644 --- a/source/hooks.cpp +++ b/source/hooks.cpp @@ -3,6 +3,8 @@ #include "utils/StorageUtilsDeprecated.h" #include "utils/logger.h" #include "utils/storage/StorageUtils.h" + +#include #include static const char **hook_names = (const char *[]){ @@ -35,10 +37,16 @@ static const char **hook_names = (const char *[]){ "WUPS_LOADER_HOOK_INIT_STORAGE", "WUPS_LOADER_HOOK_INIT_CONFIG"}; -void CallHook(const std::vector &plugins, wups_loader_hook_type_t hook_type) { +void CallHook(const std::vector &plugins, const wups_loader_hook_type_t hook_type) { + CallHook(plugins, hook_type, [](const auto &) { return true; }); +} + +void CallHook(const std::vector &plugins, const wups_loader_hook_type_t hook_type, const std::function &pred) { DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d]", hook_names[hook_type], hook_type); for (const auto &plugin : plugins) { - CallHook(plugin, hook_type); + if (pred(plugin)) { + CallHook(plugin, hook_type); + } } } diff --git a/source/hooks.h b/source/hooks.h index c4eb63c..8ce5297 100644 --- a/source/hooks.h +++ b/source/hooks.h @@ -1,9 +1,13 @@ #pragma once #include "plugin/PluginContainer.h" + +#include #include #include +void CallHook(const std::vector &plugins, wups_loader_hook_type_t hook_type, const std::function &pred); + void CallHook(const std::vector &plugins, wups_loader_hook_type_t hook_type); void CallHook(const PluginContainer &plugin, wups_loader_hook_type_t hook_type); \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index 8ad4877..d8ddaee 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -7,10 +7,11 @@ #include "plugin/PluginDataFactory.h" #include "utils/logger.h" #include "utils/utils.h" +#include "version.h" #include #include -#include +#include #include WUMS_MODULE_EXPORT_NAME("homebrew_wupsbackend"); @@ -26,8 +27,7 @@ WUMS_INITIALIZE() { OSFatal("homebrew_wupsbackend: FunctionPatcher_InitLibrary failed"); } - NotificationModuleStatus res; - if ((res = NotificationModule_InitLibrary()) != NOTIFICATION_MODULE_RESULT_SUCCESS) { + if (const NotificationModuleStatus res = NotificationModule_InitLibrary(); res != NOTIFICATION_MODULE_RESULT_SUCCESS) { DEBUG_FUNCTION_LINE_ERR("Failed to init NotificationModule: %s (%d)", NotificationModule_GetStatusStr(res), res); gNotificationModuleLoaded = false; } else { @@ -45,7 +45,7 @@ WUMS_INITIALIZE() { } WUMS_APPLICATION_REQUESTS_EXIT() { - uint32_t upid = OSGetUPID(); + const uint32_t upid = OSGetUPID(); if (upid != 2 && upid != 15) { return; } @@ -53,7 +53,7 @@ WUMS_APPLICATION_REQUESTS_EXIT() { } WUMS_APPLICATION_ENDS() { - uint32_t upid = OSGetUPID(); + const uint32_t upid = OSGetUPID(); if (upid != 2 && upid != 15) { return; } @@ -62,8 +62,8 @@ WUMS_APPLICATION_ENDS() { CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_SOCKETS); CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_FINI_WUT_DEVOPTAB); - for (const auto &pair : gUsedRPLs) { - OSDynLoad_Release(pair.second); + for (const auto &val : gUsedRPLs | std::views::values) { + OSDynLoad_Release(val); } gUsedRPLs.clear(); @@ -71,9 +71,11 @@ WUMS_APPLICATION_ENDS() { } void CheckCleanupCallbackUsage(const std::vector &plugins); +void CleanupPlugins(std::vector &&pluginsToDeinit); + WUMS_APPLICATION_STARTS() { - uint32_t upid = OSGetUPID(); + const uint32_t upid = OSGetUPID(); if (upid != 2 && upid != 15) { return; } @@ -87,14 +89,13 @@ WUMS_APPLICATION_STARTS() { // Let's clean this up! for (const auto &addr : gAllocatedAddresses) { DEBUG_FUNCTION_LINE_WARN("Memory allocated by OSDynload was not freed properly, let's clean it up! (%08X)", addr); - free((void *) addr); + free(addr); } gAllocatedAddresses.clear(); initLogging(); - bool initNeeded = false; - std::lock_guard lock(gLoadedDataMutex); + std::lock_guard lock(gLoadedDataMutex); if (gTrampData.empty()) { gTrampData = std::vector(TRAMP_DATA_SIZE); @@ -103,109 +104,142 @@ WUMS_APPLICATION_STARTS() { } } + std::vector newLoadedPlugins; + if (gLoadedPlugins.empty()) { - auto pluginPath = getPluginPath(); + const auto pluginPath = getPluginPath(); DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str()); - auto pluginData = PluginDataFactory::loadDir(pluginPath); - gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData); - - initNeeded = true; + const auto pluginData = PluginDataFactory::loadDir(pluginPath); + newLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData); } if (!gLoadOnNextLaunch.empty()) { - auto *currentThread = OSGetCurrentThread(); - auto saved_reent = currentThread->reserved[4]; - auto saved_cleanupCallback = currentThread->cleanupCallback; + std::vector pluginsToKeep; + std::set, PluginDataSharedPtrComparator> toBeLoaded; - currentThread->reserved[4] = 0; - - CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_DEINIT_PLUGIN); - - CheckCleanupCallbackUsage(gLoadedPlugins); - - if (currentThread->cleanupCallback != saved_cleanupCallback) { - DEBUG_FUNCTION_LINE_WARN("WUPS_LOADER_HOOK_DEINIT_PLUGIN overwrote the ThreadCleanupCallback, we need to restore it!\n"); - OSSetThreadCleanupCallback(OSGetCurrentThread(), saved_cleanupCallback); - } - - currentThread->reserved[4] = saved_reent; - - DEBUG_FUNCTION_LINE("Restore function patches of currently loaded plugins."); - PluginManagement::RestoreFunctionPatches(gLoadedPlugins); - - for (auto &plugin : gLoadedPlugins) { - WUPSStorageError err = plugin.CloseStorage(); - if (err != WUPS_STORAGE_ERROR_SUCCESS) { - DEBUG_FUNCTION_LINE_ERR("Failed to close storage for plugin: %s", plugin.getMetaInformation().getName().c_str()); + // Check which plugins are already loaded and which needs to be + for (const auto &pluginData : gLoadOnNextLaunch) { + // Check if the plugin data is already loaded + if (auto it = std::ranges::find_if(gLoadedPlugins, + [&pluginData](const PluginContainer &container) { + return container.getPluginDataCopy()->getHandle() == pluginData->getHandle(); + }); + it != gLoadedPlugins.end()) { + pluginsToKeep.push_back(std::move(*it)); + gLoadedPlugins.erase(it); + } else { + // Load it if it's not already loaded + toBeLoaded.insert(pluginData); } } - DEBUG_FUNCTION_LINE("Unload existing plugins."); - gLoadedPlugins.clear(); - for (auto &cur : gTrampData) { - cur.status = RELOC_TRAMP_FREE; - } + std::vector pluginsToDeinit = std::move(gLoadedPlugins); + gLoadedPlugins = std::move(pluginsToKeep); + + DEBUG_FUNCTION_LINE("Deinit unused plugins"); + CleanupPlugins(std::move(pluginsToDeinit)); DEBUG_FUNCTION_LINE("Load new plugins"); - gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData); - initNeeded = true; + newLoadedPlugins = PluginManagement::loadPlugins(toBeLoaded, gTrampData); } DEBUG_FUNCTION_LINE("Clear plugin data lists."); gLoadOnNextLaunch.clear(); gLoadedData.clear(); - if (!gLoadedPlugins.empty()) { + if (!gLoadedPlugins.empty() || !newLoadedPlugins.empty()) { + for (auto &pluginContainer : newLoadedPlugins) { + pluginContainer.setInitDone(false); + } + + // Move all new plugin containers into gLoadedPlugins + append_move_all_values(gLoadedPlugins, newLoadedPlugins); + if (!PluginManagement::doRelocations(gLoadedPlugins, gTrampData, gUsedRPLs)) { DEBUG_FUNCTION_LINE_ERR("Relocations failed"); OSFatal("WiiUPluginLoaderBackend: Relocations failed.\n See crash logs for more information."); } // PluginManagement::memsetBSS(plugins); - if (initNeeded) { - CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_MALLOC); - CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB); - CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_STDCPP); - } + const auto &needsInitsCheck = [](const PluginContainer &container) { return !container.isInitDone(); }; + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_MALLOC, needsInitsCheck); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB, needsInitsCheck); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_STDCPP, needsInitsCheck); + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_DEVOPTAB); CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WUT_SOCKETS); - if (initNeeded) { - CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WRAPPER); - } + CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_INIT_WRAPPER, needsInitsCheck); - if (initNeeded) { - for (auto &plugin : gLoadedPlugins) { - WUPSStorageError err = plugin.OpenStorage(); - if (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)); - } + for (auto &plugin : gLoadedPlugins) { + if (plugin.isInitDone()) { 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)); } - PluginManagement::callInitHooks(gLoadedPlugins); } + PluginManagement::callInitHooks(gLoadedPlugins, needsInitsCheck); CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_APPLICATION_STARTS); + for (auto &pluginContainer : gLoadedPlugins) { + pluginContainer.setInitDone(true); + } } } +void CleanupPlugins(std::vector &&pluginsToDeinit) { + auto *currentThread = OSGetCurrentThread(); + const auto saved_reent = currentThread->reserved[4]; + const auto saved_cleanupCallback = currentThread->cleanupCallback; + + currentThread->reserved[4] = 0; + + CallHook(pluginsToDeinit, WUPS_LOADER_HOOK_DEINIT_PLUGIN); + + CheckCleanupCallbackUsage(pluginsToDeinit); + + if (currentThread->cleanupCallback != saved_cleanupCallback) { + DEBUG_FUNCTION_LINE_WARN("WUPS_LOADER_HOOK_DEINIT_PLUGIN overwrote the ThreadCleanupCallback, we need to restore it!\n"); + OSSetThreadCleanupCallback(OSGetCurrentThread(), saved_cleanupCallback); + } + + currentThread->reserved[4] = saved_reent; + + DEBUG_FUNCTION_LINE("Restore function patches of plugins."); + PluginManagement::RestoreFunctionPatches(pluginsToDeinit); + + for (auto &plugin : pluginsToDeinit) { + 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()); + } + } + + for (const auto &pluginContainer : pluginsToDeinit) { + for (auto &cur : gTrampData) { + if (cur.id != pluginContainer.getPluginInformation().getTrampolineId()) { + continue; + } + cur.status = RELOC_TRAMP_FREE; + } + } +} void CheckCleanupCallbackUsage(const std::vector &plugins) { auto *curThread = OSGetCurrentThread(); for (const auto &cur : plugins) { - auto textSection = cur.getPluginInformation().getSectionInfo(".text"); + const auto textSection = cur.getPluginInformation().getSectionInfo(".text"); if (!textSection) { continue; } - uint32_t startAddress = textSection->getAddress(); - uint32_t endAddress = textSection->getAddress() + textSection->getSize(); - auto *pluginName = cur.getMetaInformation().getName().c_str(); + const uint32_t startAddress = textSection->getAddress(); + const uint32_t endAddress = textSection->getAddress() + textSection->getSize(); + auto *pluginName = cur.getMetaInformation().getName().c_str(); { __OSLockScheduler(curThread); - int state = OSDisableInterrupts(); - OSThread *t = *((OSThread **) 0x100567F8); + const int state = OSDisableInterrupts(); + OSThread *t = *reinterpret_cast(0x100567F8); while (t) { - auto address = reinterpret_cast(t->cleanupCallback); + const auto address = reinterpret_cast(t->cleanupCallback); if (address != 0 && address >= startAddress && address <= endAddress) { OSReport("[WARN] PluginBackend: Thread 0x%08X is using a function from plugin %s for the threadCleanupCallback\n", t, pluginName); } diff --git a/source/plugin/PluginContainer.cpp b/source/plugin/PluginContainer.cpp index 89d6f7c..23d442a 100644 --- a/source/plugin/PluginContainer.cpp +++ b/source/plugin/PluginContainer.cpp @@ -1,6 +1,5 @@ #include "PluginContainer.h" - -#include +#include "utils/storage/StorageUtils.h" PluginContainer::PluginContainer(PluginMetaInformation metaInformation, PluginInformation pluginInformation, std::shared_ptr pluginData) : mMetaInformation(std::move(metaInformation)), @@ -12,21 +11,25 @@ PluginContainer::PluginContainer(PluginContainer &&src) noexcept : mMetaInformat mPluginInformation(std::move(src.mPluginInformation)), mPluginData(std::move(src.mPluginData)), mPluginConfigData(std::move(src.mPluginConfigData)), - storageRootItem(src.storageRootItem) + mStorageRootItem(src.mStorageRootItem), + mInitDone(src.mInitDone) { - src.storageRootItem = {}; + src.mStorageRootItem = {}; + src.mInitDone = {}; } PluginContainer &PluginContainer::operator=(PluginContainer &&src) noexcept { if (this != &src) { - this->mMetaInformation = src.mMetaInformation; + this->mMetaInformation = std::move(src.mMetaInformation); this->mPluginInformation = std::move(src.mPluginInformation); this->mPluginData = std::move(src.mPluginData); this->mPluginConfigData = std::move(src.mPluginConfigData); - this->storageRootItem = src.storageRootItem; + this->mStorageRootItem = src.mStorageRootItem; + this->mInitDone = src.mInitDone; - src.storageRootItem = nullptr; + src.mStorageRootItem = nullptr; + src.mInitDone = false; } return *this; } @@ -48,7 +51,7 @@ std::shared_ptr PluginContainer::getPluginDataCopy() const { } uint32_t PluginContainer::getHandle() const { - return (uint32_t) this; + return reinterpret_cast(this); } const std::optional &PluginContainer::getConfigData() const { @@ -67,9 +70,9 @@ WUPSStorageError PluginContainer::OpenStorage() { if (storageId.empty()) { return WUPS_STORAGE_ERROR_SUCCESS; } - auto res = StorageUtils::API::Internal::OpenStorage(storageId, storageRootItem); + auto res = StorageUtils::API::Internal::OpenStorage(storageId, mStorageRootItem); if (res != WUPS_STORAGE_ERROR_SUCCESS) { - storageRootItem = nullptr; + mStorageRootItem = nullptr; } return res; } @@ -78,8 +81,20 @@ WUPSStorageError PluginContainer::CloseStorage() { if (getMetaInformation().getWUPSVersion() < WUPSVersion(0, 8, 0)) { return WUPS_STORAGE_ERROR_SUCCESS; } - if (storageRootItem == nullptr) { + if (mStorageRootItem == nullptr) { return WUPS_STORAGE_ERROR_SUCCESS; } - return StorageUtils::API::Internal::CloseStorage(storageRootItem); + return StorageUtils::API::Internal::CloseStorage(mStorageRootItem); } + +wups_storage_root_item PluginContainer::getStorageRootItem() const { + return mStorageRootItem; +} + +void PluginContainer::setInitDone(const bool val) { + mInitDone = val; +} + +bool PluginContainer::isInitDone() const { + return mInitDone; +} \ No newline at end of file diff --git a/source/plugin/PluginContainer.h b/source/plugin/PluginContainer.h index 5a5f26f..fc08015 100644 --- a/source/plugin/PluginContainer.h +++ b/source/plugin/PluginContainer.h @@ -30,15 +30,12 @@ class PluginContainer { public: PluginContainer(PluginMetaInformation metaInformation, PluginInformation pluginInformation, std::shared_ptr pluginData); - PluginContainer(const PluginContainer &) = delete; - PluginContainer(PluginContainer &&src) noexcept; PluginContainer &operator=(PluginContainer &&src) noexcept; - [[nodiscard]] const PluginMetaInformation &getMetaInformation() const; [[nodiscard]] const PluginInformation &getPluginInformation() const; @@ -56,9 +53,11 @@ public: WUPSStorageError CloseStorage(); - [[nodiscard]] wups_storage_root_item getStorageRootItem() const { - return storageRootItem; - } + [[nodiscard]] wups_storage_root_item getStorageRootItem() const; + + void setInitDone(bool val); + + [[nodiscard]] bool isInitDone() const; private: PluginMetaInformation mMetaInformation; @@ -66,5 +65,6 @@ private: std::shared_ptr mPluginData; std::optional mPluginConfigData; - wups_storage_root_item storageRootItem = nullptr; + wups_storage_root_item mStorageRootItem = nullptr; + bool mInitDone = false; }; diff --git a/source/plugin/PluginData.h b/source/plugin/PluginData.h index a8d28eb..761c7ce 100644 --- a/source/plugin/PluginData.h +++ b/source/plugin/PluginData.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include #include @@ -44,3 +45,9 @@ private: std::vector mBuffer; std::string mSource; }; + +struct PluginDataSharedPtrComparator { + bool operator()(const std::shared_ptr &lhs, const std::shared_ptr &rhs) const { + return lhs->getHandle() < rhs->getHandle(); + } +}; diff --git a/source/plugin/PluginDataFactory.cpp b/source/plugin/PluginDataFactory.cpp index 582c054..7ada625 100644 --- a/source/plugin/PluginDataFactory.cpp +++ b/source/plugin/PluginDataFactory.cpp @@ -25,8 +25,8 @@ #include #include -std::set> PluginDataFactory::loadDir(const std::string_view path) { - std::set> result; +std::set, PluginDataSharedPtrComparator> PluginDataFactory::loadDir(const std::string_view path) { + std::set, PluginDataSharedPtrComparator> result; dirent *dp; DIR *dfd; diff --git a/source/plugin/PluginDataFactory.h b/source/plugin/PluginDataFactory.h index d3d91ab..38b8117 100644 --- a/source/plugin/PluginDataFactory.h +++ b/source/plugin/PluginDataFactory.h @@ -24,7 +24,7 @@ class PluginDataFactory { public: - static std::set> loadDir(std::string_view path); + static std::set, PluginDataSharedPtrComparator> loadDir(std::string_view path); static std::unique_ptr load(std::string_view path); diff --git a/source/utils/exports.cpp b/source/utils/exports.cpp index aac274e..60711ac 100644 --- a/source/utils/exports.cpp +++ b/source/utils/exports.cpp @@ -35,7 +35,7 @@ extern "C" PluginBackendApiErrorType WUPSLoadAndLinkByDataHandle(const wups_back for (const auto &pluginData : gLoadedData) { if (pluginData->getHandle() == handle) { - gLoadOnNextLaunch.insert(pluginData); + gLoadOnNextLaunch.push_back(pluginData); found = true; break; } diff --git a/source/utils/utils.h b/source/utils/utils.h index 17d0b13..f71d163 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -63,7 +63,7 @@ std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std:: } template -typename std::enable_if>::value, bool>::type +std::enable_if_t>, bool> remove_first_if(Container &container, Predicate pred) { auto it = container.before_begin(); @@ -78,7 +78,7 @@ remove_first_if(Container &container, Predicate pred) { } template -typename std::enable_if>::value, bool>::type +std::enable_if_t>, bool> remove_first_if(Container &container, Predicate pred) { auto it = container.begin(); while (it != container.end()) { @@ -92,7 +92,7 @@ remove_first_if(Container &container, Predicate pred) { } template -typename std::enable_if>::value, bool>::type +std::enable_if_t>, bool> remove_first_if(Container &container, Predicate pred) { auto it = container.begin(); while (it != container.end()) { @@ -129,6 +129,12 @@ T pop_locked_first_if(std::mutex &mutex, std::vector &container, Predicate pr return result; } +template +void append_move_all_values(Container &dest, Container &src) { + dest.insert(dest.end(), std::make_move_iterator(src.begin()), std::make_move_iterator(src.end())); + src.clear(); +} + std::string getPluginPath(); OSDynLoad_Error CustomDynLoadAlloc(int32_t size, int32_t align, void **outAddr);