From ac43836714eaf3b2bb5b5f38a77c1d669421bb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 01:14:41 +0100 Subject: [PATCH] IOS/ES: Implement DeleteTitle No idea why this wasn't implemented whereas ES_DeleteTicket and ES_DeleteTitleContent were. This probably fixes title deletion in old System Menus, and maybe the new ones as well in some cases; I've seen 4.3 use this ioctlv. --- Source/Core/Core/IOS/ES/ES.cpp | 36 ++++++++++++++++++++++++++++++++++ Source/Core/Core/IOS/ES/ES.h | 1 + 2 files changed, 37 insertions(+) diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 57a430e7a3..7155a28c7f 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -272,6 +272,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) return GetTMDViews(request); case IOCTL_ES_GETCONSUMPTION: return GetConsumption(request); + case IOCTL_ES_DELETETITLE: + return DeleteTitle(request); case IOCTL_ES_DELETETICKET: return DeleteTicket(request); case IOCTL_ES_DELETETITLECONTENT: @@ -849,6 +851,40 @@ IPCCommandResult ES::GetConsumption(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } +static bool CanDeleteTitle(u64 title_id) +{ + // IOS only allows deleting non-system titles (or a system title higher than 00000001-00000101). + return static_cast(title_id >> 32) != 0x00000001 || static_cast(title_id) > 0x101; +} + +IPCCommandResult ES::DeleteTitle(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8) + return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); + + const u64 title_id = Memory::Read_U64(request.in_vectors[0].address); + + if (!CanDeleteTitle(title_id)) + return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); + + const std::string title_dir = + StringFromFormat("%s/title/%08x/%08x/", RootUserPath(Common::FROM_SESSION_ROOT).c_str(), + static_cast(title_id >> 32), static_cast(title_id)); + if (!File::IsDirectory(title_dir) || + !DiscIO::CNANDContentManager::Access().RemoveTitle(title_id, Common::FROM_SESSION_ROOT)) + { + return GetDefaultReply(FS_ENOENT); + } + + if (!File::DeleteDirRecursively(title_dir)) + { + ERROR_LOG(IOS_ES, "DeleteTitle: Failed to delete title directory: %s", title_dir.c_str()); + return GetDefaultReply(FS_EACCESS); + } + + return GetDefaultReply(IPC_SUCCESS); +} + IPCCommandResult ES::DeleteTicket(const IOCtlVRequest& request) { u64 TitleID = Memory::Read_U64(request.in_vectors[0].address); diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 045fc75f36..29e2bedff7 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -175,6 +175,7 @@ private: IPCCommandResult GetTMDViewCount(const IOCtlVRequest& request); IPCCommandResult GetTMDViews(const IOCtlVRequest& request); IPCCommandResult GetConsumption(const IOCtlVRequest& request); + IPCCommandResult DeleteTitle(const IOCtlVRequest& request); IPCCommandResult DeleteTicket(const IOCtlVRequest& request); IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request); IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);