mirror of
https://github.com/wiiu-env/libwupsbackend.git
synced 2024-11-28 12:34:20 +01:00
193 lines
8.2 KiB
C++
193 lines
8.2 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2019-2022 Maschell
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
****************************************************************************/
|
|
|
|
#include "wups_backend/PluginUtils.h"
|
|
#include "logger.h"
|
|
#include "utils.h"
|
|
#include "wups_backend/api.h"
|
|
#include <cstring>
|
|
#include <memory>
|
|
|
|
namespace WUPSBackend {
|
|
|
|
const char *GetStatusStr(PluginBackendApiErrorType status) {
|
|
return WUPSBackend_GetStatusStr(status);
|
|
}
|
|
|
|
namespace PluginUtils {
|
|
static std::optional<PluginMetaInformation> getMetaInformation(const wups_backend_plugin_information &info, PluginBackendApiErrorType &err) {
|
|
if (info.plugin_information_version != WUPS_BACKEND_PLUGIN_INFORMATION_VERSION) {
|
|
err = PLUGIN_BACKEND_API_ERROR_UNSUPPORTED_VERSION;
|
|
DEBUG_FUNCTION_LINE_ERR("Version mismatch");
|
|
return {};
|
|
}
|
|
return PluginMetaInformation(info.name,
|
|
info.author,
|
|
info.version,
|
|
info.license,
|
|
info.buildTimestamp,
|
|
info.description,
|
|
info.storageId,
|
|
info.size);
|
|
}
|
|
|
|
std::optional<PluginMetaInformation> getMetaInformationForBuffer(char *buffer, size_t size, PluginBackendApiErrorType &err) {
|
|
wups_backend_plugin_information info = {};
|
|
if ((err = WUPSBackend_GetPluginMetaInformationByBuffer(&info, buffer, size)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to load meta infos for buffer %08X with size %08X", buffer, size);
|
|
return {};
|
|
}
|
|
return getMetaInformation(info, err);
|
|
}
|
|
|
|
std::optional<PluginMetaInformation> getMetaInformationForPath(const std::string &path, PluginBackendApiErrorType &err) {
|
|
wups_backend_plugin_information info = {};
|
|
if ((err = WUPSBackend_GetPluginMetaInformationByPath(&info, path.c_str())) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to load meta infos for %s", path.c_str());
|
|
return {};
|
|
}
|
|
return getMetaInformation(info, err);
|
|
}
|
|
|
|
std::optional<PluginContainer> getPluginForPath(const std::string &path, PluginBackendApiErrorType &err) {
|
|
auto metaInfoOpt = getMetaInformationForPath(path, err);
|
|
if (!metaInfoOpt) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to get MetaInformation for path %s", path.c_str());
|
|
return {};
|
|
}
|
|
|
|
wups_backend_plugin_data_handle dataHandle;
|
|
if ((err = WUPSBackend_LoadPluginAsDataByPath(&dataHandle, path.c_str())) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("WUPSLoadPluginAsDataByPath failed for path %s", path.c_str());
|
|
return {};
|
|
}
|
|
|
|
return PluginContainer(PluginData(dataHandle), std::move(metaInfoOpt.value()));
|
|
}
|
|
|
|
std::optional<PluginContainer> getPluginForBuffer(char *buffer, size_t size, PluginBackendApiErrorType &err) {
|
|
auto metaInfoOpt = getMetaInformationForBuffer(buffer, size, err);
|
|
if (!metaInfoOpt) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to get MetaInformation for buffer %08X (%d bytes)", buffer, size);
|
|
return {};
|
|
}
|
|
|
|
wups_backend_plugin_data_handle dataHandle;
|
|
if ((err = WUPSBackend_LoadPluginAsDataByBuffer(&dataHandle, buffer, size)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("WUPSLoadPluginAsDataByBuffer failed for buffer %08X (%d bytes)", buffer, size);
|
|
return {};
|
|
}
|
|
|
|
return PluginContainer(PluginData(dataHandle), std::move(metaInfoOpt.value()));
|
|
}
|
|
|
|
std::vector<PluginContainer> getLoadedPlugins(PluginBackendApiErrorType &err) {
|
|
std::vector<PluginContainer> result;
|
|
|
|
PluginBackendApiErrorType err2;
|
|
uint32_t maxSize;
|
|
if ((err2 = WUPSBackend_GetNumberOfLoadedPlugins(&maxSize)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_WARN("Failed to get number of loaded plugins: %s", WUPSBackend_GetStatusStr(err2));
|
|
maxSize = 120;
|
|
}
|
|
|
|
auto handles = make_unique_nothrow<wups_backend_plugin_container_handle[]>(maxSize);
|
|
if (!handles) {
|
|
err = PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
|
|
DEBUG_FUNCTION_LINE_ERR("Not enough memory");
|
|
return result;
|
|
}
|
|
uint32_t realSize = 0;
|
|
|
|
for (uint32_t i = 0; i < maxSize; i++) {
|
|
handles[i] = 0xFFFFFFFF;
|
|
}
|
|
|
|
uint32_t plugin_information_version = 0;
|
|
if ((err = WUPSBackend_GetLoadedPlugins(handles.get(), maxSize, &realSize, &plugin_information_version)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("WUPSGetLoadedPlugins: Failed");
|
|
return result;
|
|
}
|
|
if (realSize == 0 || plugin_information_version != WUPS_BACKEND_PLUGIN_INFORMATION_VERSION) {
|
|
err = PLUGIN_BACKEND_API_ERROR_UNSUPPORTED_VERSION;
|
|
DEBUG_FUNCTION_LINE_ERR("realSize is 0 or version mismatch");
|
|
return result;
|
|
}
|
|
|
|
auto dataHandles = make_unique_nothrow<wups_backend_plugin_data_handle[]>(realSize);
|
|
if (!dataHandles) {
|
|
err = PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
|
|
DEBUG_FUNCTION_LINE_ERR("Not enough memory");
|
|
return result;
|
|
}
|
|
|
|
if ((err = WUPSBackend_GetPluginDataForContainerHandles(handles.get(), dataHandles.get(), realSize)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to get plugin data");
|
|
return result;
|
|
}
|
|
|
|
auto information = make_unique_nothrow<wups_backend_plugin_information[]>(realSize);
|
|
if (!information) {
|
|
err = PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
|
|
DEBUG_FUNCTION_LINE_ERR("Not enough memory");
|
|
return result;
|
|
}
|
|
if ((err = WUPSBackend_GetMetaInformation(handles.get(), information.get(), realSize)) != PLUGIN_BACKEND_API_ERROR_NONE) {
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to get meta information for handles");
|
|
return result;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < realSize; i++) {
|
|
if (information[i].plugin_information_version != WUPS_BACKEND_PLUGIN_INFORMATION_VERSION) {
|
|
err = PLUGIN_BACKEND_API_ERROR_UNSUPPORTED_VERSION;
|
|
DEBUG_FUNCTION_LINE_ERR("Skip, wrong struct version.");
|
|
return {};
|
|
}
|
|
result.emplace_back(PluginData(dataHandles[i]), PluginMetaInformation(information[i].name,
|
|
information[i].author,
|
|
information[i].version,
|
|
information[i].license,
|
|
information[i].buildTimestamp,
|
|
information[i].description,
|
|
information[i].storageId,
|
|
information[i].size));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
PluginBackendApiErrorType LoadAndLinkOnRestart(const std::vector<PluginContainer> &plugins) {
|
|
uint32_t dataSize = plugins.size();
|
|
auto handles = make_unique_nothrow<wups_backend_plugin_data_handle[]>(dataSize);
|
|
if (!handles) {
|
|
return PLUGIN_BACKEND_API_ERROR_FAILED_ALLOC;
|
|
}
|
|
int i = 0;
|
|
for (const auto &plugin : plugins) {
|
|
const auto &handle = plugin.getPluginData().getHandle();
|
|
if (handle == 0) {
|
|
return PLUGIN_BACKEND_API_INVALID_HANDLE;
|
|
} else {
|
|
handles[i] = handle;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return WUPSBackend_LoadAndLinkByDataHandle(handles.get(), dataSize);
|
|
}
|
|
} // namespace PluginUtils
|
|
} // namespace WUPSBackend
|