Implement ContentRedirection_AddFSLayerEx

This commit is contained in:
Maschell 2025-02-07 18:00:56 +01:00
parent 8d51262585
commit 4ddd4cb604
2 changed files with 77 additions and 20 deletions

View File

@ -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. <br>
* Adds a FSLayers that redirects the /vol/content or /vol/save fs calls for the Game/Wii U Menu process. <br>
* Make sure to remove all added the layers before the application ends. <br>
* The replacement dir has be to valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module. <br>
* The replacement dir has to be valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module. <br>
* Multiple layers can be added. Each layer is valid system wide for the Game/Wii U Menu process. <br>
* 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. <br>
* 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. <br>
* 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. <br>
* The layer has to be removed before the currently running application ends. <br>
* CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED: "ContentRedirection_InitLibrary()" was not called. <br>
@ -124,7 +130,34 @@ ContentRedirectionStatus ContentRedirection_GetVersion(ContentRedirectionVersion
* CONTENT_REDIRECTION_API_ERROR_UNKNOWN_LAYER_TYPE: Unknown/invalid LayerType. See FSLayerType for all supported layers. <br>
* 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. <br>
* Make sure to remove all added the layers before the application ends. <br>
* The replacement dir has to be valid in the ContentRedirection Module, use "ContentRedirection_AddDevice" to add a Device for the ContentRedirection Module. <br>
* Multiple layers can be added. Each layer is valid system mwide for the Game/Wii U Menu process. <br>
* 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. <br>
* 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. <br>
* 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. <br>
* The layer has to be removed before the currently running application ends. <br>
* CONTENT_REDIRECTION_RESULT_UNSUPPORTED_COMMAND: This function requires API version 2 <br>
* CONTENT_REDIRECTION_RESULT_LIB_UNINITIALIZED: "ContentRedirection_InitLibrary()" was not called. <br>
* CONTENT_REDIRECTION_RESULT_INVALID_ARGUMENT: "handlePtr", "layerName" or "replacementDir" is NULL <br>
* CONTENT_REDIRECTION_API_ERROR_NO_MEMORY: Not enough memory to create this layer. <br>
* CONTENT_REDIRECTION_API_ERROR_UNKNOWN_LAYER_TYPE: Unknown/invalid LayerType. See FSLayerType for all supported layers. <br>
* 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.

View File

@ -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<decltype(&GetVersion)>(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<decltype(&AddFSLayer)>(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<decltype(&RemoveFSLayer)>(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<decltype(&SetActive)>(sCRSetActive)(handle, active);
const auto res = sCRSetActive(handle, active);
if (res == CONTENT_REDIRECTION_API_ERROR_NONE) {
return CONTENT_REDIRECTION_RESULT_SUCCESS;
}