From 4ddd4cb604353da2c3afc639927907f28cd03cc8 Mon Sep 17 00:00:00 2001 From: Maschell Date: Fri, 7 Feb 2025 18:00:56 +0100 Subject: [PATCH] Implement ContentRedirection_AddFSLayerEx --- include/content_redirection/redirection.h | 41 +++++++++++++++-- source/utils.cpp | 56 ++++++++++++++++------- 2 files changed, 77 insertions(+), 20 deletions(-) diff --git a/include/content_redirection/redirection.h b/include/content_redirection/redirection.h index 992ece8..828cabf 100644 --- a/include/content_redirection/redirection.h +++ b/include/content_redirection/redirection.h @@ -49,6 +49,12 @@ typedef enum FSLayerType { FS_LAYER_TYPE_SAVE_REPLACE_FOR_CURRENT_USER, } FSLayerType; +typedef enum FSLayerTypeEx { + FS_LAYER_TYPE_EX_REPLACE_DIRECTORY, + FS_LAYER_TYPE_EX_MERGE_DIRECTORY, + FS_LAYER_TYPE_EX_REPLACE_FILE, +} FSLayerTypeEx; + typedef enum ContentRedirectionStatus { CONTENT_REDIRECTION_RESULT_SUCCESS = 0, CONTENT_REDIRECTION_RESULT_MODULE_NOT_FOUND = -0x1, @@ -104,9 +110,9 @@ ContentRedirectionStatus ContentRedirection_DeInitLibrary(); ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion *outVersion); /** - * Adds a a FSLayers that redirects the /vol/content or /vol/save fs calles for the Game/Wii U Menu process.
+ * Adds a FSLayers that redirects the /vol/content or /vol/save fs calls for the Game/Wii U Menu process.
* Make sure to remove all added the layers before the application ends.
- * The replacement dir has be to valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module.
+ * The replacement dir has to be valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module.
* Multiple layers can be added. Each layer is valid system wide for the Game/Wii U Menu process.
* The layers will be processed in reverse adding order. e.g. when you add Layer1, Layer2 and then Layer3; Layer3, Layer2 and finally Layer1 will be processed.
* An added layer is active by default. @@ -115,7 +121,7 @@ ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion * @param layerName Name of the layer, used for debugging. * @param replacementDir Path to the directory that will replace / merge into the original one. * @param layerType Type of the layer, see FSLayerType for more information.
- * If set to to false, errors of this layer will be returned to the OS. + * If set to false, errors of this layer will be returned to the OS. * @return CONTENT_REDIRECTION_RESULT_SUCCESS: The layer had been added successfully.
* The layer has to be removed before the currently running application ends.
* CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED: "ContentRedirection_InitLibrary()" was not called.
@@ -124,7 +130,34 @@ ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion * CONTENT_REDIRECTION_API_ERROR_UNKNOWN_LAYER_TYPE: Unknown/invalid LayerType. See FSLayerType for all supported layers.
* CONTENT_REDIRECTION_RESULT_UNKNOWN_ERROR: Unknown error. */ -ContentRedirectionStatus ContentRedirection_AddFSLayer(CRLayerHandle *handlePtr, const char *layerName, const char *replacementDir, FSLayerType layerType); +ContentRedirectionStatus ContentRedirection_AddFSLayer(CRLayerHandle *handlePtr, const char *layerName, const char *replacementDir, FSLayerTypeEx layerType); + +/** + * Adds a FSLayer that redirects a files or directories fs calls for the Game/Wii U Menu process.
+ * Make sure to remove all added the layers before the application ends.
+ * The replacement dir has to be valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module.
+ * Multiple layers can be added. Each layer is valid system mwide for the Game/Wii U Menu process.
+ * The layers will be processed in reverse adding order. e.g. when you add Layer1, Layer2 and then Layer3; Layer3, Layer2 and finally Layer1 will be processed.
+ * An added layer is active by default. + * + * **Requires API version 2 or higher** + * + * @param handlePtr The handle of the layer is written to this pointer. + * @param layerName Name of the layer, used for debugging. + * @param targetPath Path to the directory/file that should be replaced or merged. + * @param replacementPath Path to the directory/file that will replace / merge into the original one. + * @param layerType Type of the layer, see FSLayerType for more information.
+ * If set to false, errors of this layer will be returned to the OS. +* @return CONTENT_REDIRECTION_RESULT_SUCCESS: The layer had been added successfully.
+ * The layer has to be removed before the currently running application ends.
+* CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND: This function requires API version 2
+* CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED: "ContentRedirection_InitLibrary()" was not called.
+* CONTENT_REDIRECTION_RESULT_INVALID_ARGUMENT: "handlePtr", "layerName" or "replacementDir" is NULL
+* CONTENT_REDIRECTION_API_ERROR_NO_MEMORY: Not enough memory to create this layer.
+* CONTENT_REDIRECTION_API_ERROR_UNKNOWN_LAYER_TYPE: Unknown/invalid LayerType. See FSLayerType for all supported layers.
+* CONTENT_REDIRECTION_RESULT_UNKNOWN_ERROR: Unknown error. + */ +ContentRedirectionStatus ContentRedirection_AddFSLayerEx(CRLayerHandle *handlePtr, const char *layerName, const char *targetPath, const char *replacementPath, FSLayerTypeEx layerType); /** * Removes a previously added FS Layer. diff --git a/source/utils.cpp b/source/utils.cpp index 74643b2..50651f2 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -6,12 +6,13 @@ static OSDynLoad_Module sModuleHandle = nullptr; -static ContentRedirectionApiErrorType (*sCRAddFSLayer)(CRLayerHandle *, const char *, const char *, FSLayerType) = nullptr; -static ContentRedirectionApiErrorType (*sCRRemoveFSLayer)(CRLayerHandle) = nullptr; -static ContentRedirectionApiErrorType (*sCRSetActive)(CRLayerHandle) = nullptr; -static ContentRedirectionApiErrorType (*sCRGetVersion)(ContentRedirectionVersion *) = nullptr; -static int (*sCRAddDevice)(const devoptab_t *, int *) = nullptr; -static int (*sCRRemoveDevice)(const char *) = nullptr; +static ContentRedirectionApiErrorType (*sCRAddFSLayerEx)(CRLayerHandle *, const char *, const char *, const char *, FSLayerTypeEx) = nullptr; +static ContentRedirectionApiErrorType (*sCRAddFSLayer)(CRLayerHandle *, const char *, const char *, FSLayerType) = nullptr; +static ContentRedirectionApiErrorType (*sCRRemoveFSLayer)(CRLayerHandle) = nullptr; +static ContentRedirectionApiErrorType (*sCRSetActive)(CRLayerHandle, bool) = nullptr; +static ContentRedirectionApiErrorType (*sCRGetVersion)(ContentRedirectionVersion *) = nullptr; +static int (*sCRAddDevice)(const devoptab_t *, int *) = nullptr; +static int (*sCRRemoveDevice)(const char *) = nullptr; static ContentRedirectionVersion sContentRedirectionVersion = CONTENT_REDIRECTION_MODULE_VERSION_ERROR; @@ -62,6 +63,10 @@ ContentRedirectionStatus ContentRedirection_InitLibrary() { DEBUG_FUNCTION_LINE_ERR("FindExport CRAddFSLayer failed."); sCRAddFSLayer = nullptr; } + if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "CRAddFSLayerEx", (void **) &sCRAddFSLayerEx) != OS_DYNLOAD_OK) { + DEBUG_FUNCTION_LINE_ERR("FindExport CRAddFSLayerEx failed."); + sCRAddFSLayerEx = nullptr; + } if (OSDynLoad_FindExport(sModuleHandle, OS_DYNLOAD_EXPORT_FUNC, "CRRemoveFSLayer", (void **) &sCRRemoveFSLayer) != OS_DYNLOAD_OK) { DEBUG_FUNCTION_LINE_ERR("FindExport CRRemoveFSLayer failed."); @@ -90,8 +95,7 @@ ContentRedirectionStatus ContentRedirection_DeInitLibrary() { return CONTENT_REDIRECTION_RESULT_SUCCESS; } -ContentRedirectionApiErrorType GetVersion(ContentRedirectionVersion *); -ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion *outVariable) { +ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion *outVersion) { if (sCRGetVersion == nullptr) { if (OSDynLoad_Acquire("homebrew_content_redirection", &sModuleHandle) != OS_DYNLOAD_OK) { DEBUG_FUNCTION_LINE_WARN("OSDynLoad_Acquire failed."); @@ -104,7 +108,7 @@ ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion } } - auto res = reinterpret_cast(sCRGetVersion)(outVariable); + const auto res = sCRGetVersion(outVersion); if (res == CONTENT_REDIRECTION_API_ERROR_NONE) { return CONTENT_REDIRECTION_RESULT_SUCCESS; } @@ -112,15 +116,37 @@ ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion } -ContentRedirectionApiErrorType AddFSLayer(CRLayerHandle *, const char *, const char *, FSLayerType); -ContentRedirectionStatus ContentRedirection_AddFSLayer(CRLayerHandle *handlePtr, const char *layerName, const char *replacementDir, FSLayerType layerType) { +ContentRedirectionStatus ContentRedirection_AddFSLayer(CRLayerHandle *handlePtr, const char *layerName, const char *replacementDir, const FSLayerType layerType) { if (sContentRedirectionVersion == CONTENT_REDIRECTION_MODULE_VERSION_ERROR) { return CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED; } if (sCRAddFSLayer == nullptr || sContentRedirectionVersion < 1) { return CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND; } - auto res = reinterpret_cast(sCRAddFSLayer)(handlePtr, layerName, replacementDir, layerType); + auto res = sCRAddFSLayer(handlePtr, layerName, replacementDir, layerType); + if (res == CONTENT_REDIRECTION_API_ERROR_NONE) { + return CONTENT_REDIRECTION_RESULT_SUCCESS; + } + switch (res) { + case CONTENT_REDIRECTION_API_ERROR_INVALID_ARG: + return CONTENT_REDIRECTION_RESULT_INVALID_ARGUMENT; + case CONTENT_REDIRECTION_API_ERROR_NO_MEMORY: + return CONTENT_REDIRECTION_RESULT_NO_MEMORY; + case CONTENT_REDIRECTION_API_ERROR_UNKNOWN_FS_LAYER_TYPE: + return CONTENT_REDIRECTION_RESULT_UNKNOWN_FS_LAYER_TYPE; + default: + return CONTENT_REDIRECTION_RESULT_UNKNOWN_ERROR; + } +} + +ContentRedirectionStatus ContentRedirection_AddFSLayerEx(CRLayerHandle *handlePtr, const char *layerName, const char *targetPath, const char *replacementDir, const FSLayerTypeEx layerType) { + if (sContentRedirectionVersion == CONTENT_REDIRECTION_MODULE_VERSION_ERROR) { + return CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED; + } + if (sCRAddFSLayerEx == nullptr || sContentRedirectionVersion < 2) { + return CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND; + } + const auto res = sCRAddFSLayerEx(handlePtr, layerName, targetPath, replacementDir, layerType); if (res == CONTENT_REDIRECTION_API_ERROR_NONE) { return CONTENT_REDIRECTION_RESULT_SUCCESS; } @@ -136,7 +162,6 @@ ContentRedirectionStatus ContentRedirection_AddFSLayer(CRLayerHandle *handlePtr, } } -ContentRedirectionApiErrorType RemoveFSLayer(CRLayerHandle); ContentRedirectionStatus ContentRedirection_RemoveFSLayer(CRLayerHandle handlePtr) { if (sContentRedirectionVersion == CONTENT_REDIRECTION_MODULE_VERSION_ERROR) { return CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED; @@ -144,7 +169,7 @@ ContentRedirectionStatus ContentRedirection_RemoveFSLayer(CRLayerHandle handlePt if (sCRRemoveFSLayer == nullptr || sContentRedirectionVersion < 1) { return CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND; } - auto res = reinterpret_cast(sCRRemoveFSLayer)(handlePtr); + const auto res = sCRRemoveFSLayer(handlePtr); if (res == CONTENT_REDIRECTION_API_ERROR_NONE) { return CONTENT_REDIRECTION_RESULT_SUCCESS; } @@ -156,7 +181,6 @@ ContentRedirectionStatus ContentRedirection_RemoveFSLayer(CRLayerHandle handlePt return CONTENT_REDIRECTION_RESULT_UNKNOWN_ERROR; } -ContentRedirectionApiErrorType SetActive(CRLayerHandle, bool); ContentRedirectionStatus ContentRedirection_SetActive(CRLayerHandle handle, bool active) { if (sContentRedirectionVersion == CONTENT_REDIRECTION_MODULE_VERSION_ERROR) { return CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED; @@ -164,7 +188,7 @@ ContentRedirectionStatus ContentRedirection_SetActive(CRLayerHandle handle, bool if (sCRSetActive == nullptr || sContentRedirectionVersion < 1) { return CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND; } - auto res = reinterpret_cast(sCRSetActive)(handle, active); + const auto res = sCRSetActive(handle, active); if (res == CONTENT_REDIRECTION_API_ERROR_NONE) { return CONTENT_REDIRECTION_RESULT_SUCCESS; }