diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 6fcf884578..4dcb0e9ff6 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -417,6 +417,7 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) case IOCTL_ES_SETUID: return SetUID(context->uid, request); case IOCTL_ES_DIVERIFY: + case IOCTL_ES_DIVERIFY_WITH_VIEW: return DIVerify(request); case IOCTL_ES_GETOWNEDTITLECNT: @@ -473,6 +474,8 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) return DeleteTitleContent(request); case IOCTL_ES_DELETESHAREDCONTENT: return DeleteSharedContent(request); + case IOCTL_ES_DELETE_CONTENT: + return DeleteContent(request); case IOCTL_ES_GETSTOREDTMDSIZE: return GetStoredTMDSize(request); case IOCTL_ES_GETSTOREDTMD: @@ -511,11 +514,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request) case IOCTL_ES_GET_TICKET_FROM_VIEW: return GetTicketFromView(request); + case IOCTL_ES_DELETE_STREAM_KEY: + return DeleteStreamKey(request); + case IOCTL_ES_VERIFYSIGN: - case IOCTL_ES_UNKNOWN_3B: case IOCTL_ES_UNKNOWN_3C: - case IOCTL_ES_UNKNOWN_3D: - case IOCTL_ES_UNKNOWN_3E: case IOCTL_ES_UNKNOWN_41: case IOCTL_ES_UNKNOWN_42: PanicAlert("IOS-ES: Unimplemented ioctlv 0x%x (%zu in vectors, %zu io vectors)", @@ -642,6 +645,15 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic return IPC_SUCCESS; } + +IPCCommandResult ES::DeleteStreamKey(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32)) + return GetDefaultReply(ES_EINVAL); + + const u32 handle = Memory::Read_U32(request.in_vectors[0].address); + return GetDefaultReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES)); +} } // namespace Device } // namespace HLE } // namespace IOS diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index a55297e760..a918a72d49 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -115,6 +115,7 @@ public: ReturnCode DeleteTitleContent(u64 title_id) const; ReturnCode DeleteTicket(const u8* ticket_view); ReturnCode DeleteSharedContent(const std::array& sha1) const; + ReturnCode DeleteContent(u64 title_id, u32 content_id) const; // Views ReturnCode GetV0TicketFromView(const u8* ticket_view, u8* ticket) const; @@ -181,10 +182,10 @@ private: IOCTL_ES_DELETESHAREDCONTENT = 0x38, IOCTL_ES_DIGETTMDSIZE = 0x39, IOCTL_ES_DIGETTMD = 0x3A, - IOCTL_ES_UNKNOWN_3B = 0x3B, + IOCTL_ES_DIVERIFY_WITH_VIEW = 0x3B, IOCTL_ES_UNKNOWN_3C = 0x3C, - IOCTL_ES_UNKNOWN_3D = 0x3D, - IOCTL_ES_UNKNOWN_3E = 0x3E, + IOCTL_ES_DELETE_STREAM_KEY = 0x3D, + IOCTL_ES_DELETE_CONTENT = 0x3E, IOCTL_ES_INVALID_3F = 0x3F, IOCTL_ES_GET_V0_TICKET_FROM_VIEW = 0x40, IOCTL_ES_UNKNOWN_41 = 0x41, @@ -215,6 +216,7 @@ private: IPCCommandResult DeleteTitleContent(const IOCtlVRequest& request); IPCCommandResult DeleteTicket(const IOCtlVRequest& request); IPCCommandResult DeleteSharedContent(const IOCtlVRequest& request); + IPCCommandResult DeleteContent(const IOCtlVRequest& request); // Device identity and encryption IPCCommandResult GetConsoleID(const IOCtlVRequest& request); @@ -232,6 +234,7 @@ private: IPCCommandResult Launch(const IOCtlVRequest& request); IPCCommandResult LaunchBC(const IOCtlVRequest& request); IPCCommandResult DIVerify(const IOCtlVRequest& request); + IPCCommandResult DeleteStreamKey(const IOCtlVRequest& request); // Title contents IPCCommandResult OpenTitleContent(u32 uid, const IOCtlVRequest& request); diff --git a/Source/Core/Core/IOS/ES/TitleManagement.cpp b/Source/Core/Core/IOS/ES/TitleManagement.cpp index a8e326d371..79b625ce59 100644 --- a/Source/Core/Core/IOS/ES/TitleManagement.cpp +++ b/Source/Core/Core/IOS/ES/TitleManagement.cpp @@ -440,6 +440,39 @@ IPCCommandResult ES::DeleteTitleContent(const IOCtlVRequest& request) return GetDefaultReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address))); } +ReturnCode ES::DeleteContent(u64 title_id, u32 content_id) const +{ + if (!CanDeleteTitle(title_id)) + return ES_EINVAL; + + const auto tmd = IOS::ES::FindInstalledTMD(title_id); + if (!tmd.IsValid()) + return FS_ENOENT; + + IOS::ES::Content content; + if (!tmd.FindContentById(content_id, &content)) + return ES_EINVAL; + + if (!File::Delete(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT) + + StringFromFormat("%08x.app", content_id))) + { + return FS_ENOENT; + } + + return IPC_SUCCESS; +} + +IPCCommandResult ES::DeleteContent(const IOCtlVRequest& request) +{ + if (!request.HasNumberOfValidVectors(2, 0) || request.in_vectors[0].size != sizeof(u64) || + request.in_vectors[1].size != sizeof(u32)) + { + return GetDefaultReply(ES_EINVAL); + } + return GetDefaultReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address), + Memory::Read_U32(request.in_vectors[1].address))); +} + ReturnCode ES::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size) { // No concurrent title import/export is allowed.