From ac626edabcafd122dc43db44743dfed32d47c627 Mon Sep 17 00:00:00 2001 From: Valentin Vanelslande Date: Wed, 28 Feb 2018 08:25:33 -0600 Subject: [PATCH] Service/AM: Implement DeleteProgram and DeleteUserProgram (#3446) * Update am.cpp * Update am.h * Update am_net.cpp * Service/AM: Implement DeleteProgram * fix clang * Address comments * Service/AM: DeleteProgram: Scan for all titles after deleting the title * fix * Service/AM: DeleteProgram: return error if the title was not found * fix clang * [skip ci] * [skip ci] * [skip ci] * [skip ci] * Service/AM: Implement DeleteUserProgram * fix clang * FileUtil::DeleteDirRecursively unexpectedly failed --- src/core/hle/service/am/am.cpp | 52 ++++++++++++++++++++++++++++++ src/core/hle/service/am/am.h | 24 ++++++++++++++ src/core/hle/service/am/am_net.cpp | 4 +-- src/core/hle/service/am/am_sys.cpp | 2 +- src/core/hle/service/am/am_u.cpp | 4 +-- 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ebaa2fc6e..355f12cc2 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -688,6 +688,36 @@ void GetProgramInfos(Service::Interface* self) { rb.PushMappedBuffer(title_info_out, title_info_size, title_info_perms); } +void DeleteUserProgram(Service::Interface* self) { + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x000400, 3, 0); + auto media_type = rp.PopEnum(); + u32 low = rp.Pop(); + u32 high = rp.Pop(); + u64 title_id = static_cast(low) | (static_cast(high) << 32); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + u16 category = static_cast((title_id >> 32) & 0xFFFF); + u8 variation = static_cast(title_id & 0xFF); + if (category & CATEGORY_SYSTEM || category & CATEGORY_DLP || variation & VARIATION_SYSTEM) { + LOG_ERROR(Service_AM, "Trying to uninstall system app"); + rb.Push(ResultCode(ErrCodes::TryingToUninstallSystemApp, ErrorModule::AM, + ErrorSummary::InvalidArgument, ErrorLevel::Usage)); + return; + } + LOG_INFO(Service_AM, "Deleting title 0x%016" PRIx64, title_id); + std::string path = GetTitlePath(media_type, title_id); + if (!FileUtil::Exists(path)) { + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::AM, ErrorSummary::InvalidState, + ErrorLevel::Permanent)); + LOG_ERROR(Service_AM, "Title not found"); + return; + } + bool success = FileUtil::DeleteDirRecursively(path); + ScanForAllTitles(); + rb.Push(RESULT_SUCCESS); + if (!success) + LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); +} + void GetDLCTitleInfos(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1005, 2, 4); // 0x10050084 @@ -1156,6 +1186,28 @@ void GetRequiredSizeFromCia(Service::Interface* self) { rb.Push(container.GetTitleMetadata().GetContentSizeByIndex(FileSys::TMDContentIndex::Main)); } +void DeleteProgram(Service::Interface* self) { + IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0410, 3, 0); + auto media_type = rp.PopEnum(); + u32 low = rp.Pop(); + u32 high = rp.Pop(); + u64 title_id = static_cast(low) | (static_cast(high) << 32); + LOG_INFO(Service_AM, "Deleting title 0x%016" PRIx64, title_id); + std::string path = GetTitlePath(media_type, title_id); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + if (!FileUtil::Exists(path)) { + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::AM, ErrorSummary::InvalidState, + ErrorLevel::Permanent)); + LOG_ERROR(Service_AM, "Title not found"); + return; + } + bool success = FileUtil::DeleteDirRecursively(path); + ScanForAllTitles(); + rb.Push(RESULT_SUCCESS); + if (!success) + LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); +} + void GetMetaSizeFromCia(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0413, 0, 2); // 0x04130002 diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index d4d834172..dfed1b523 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -28,6 +28,7 @@ enum { CIACurrentlyInstalling = 4, InvalidTID = 31, EmptyCIA = 32, + TryingToUninstallSystemApp = 44, InvalidTIDInList = 60, InvalidCIAHeader = 104, }; @@ -226,6 +227,17 @@ void GetProgramList(Service::Interface* self); */ void GetProgramInfos(Service::Interface* self); +/** + * AM::DeleteUserProgram service function + * Deletes a user program + * Inputs: + * 1 : Media Type + * 2-3 : Title ID + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ +void DeleteUserProgram(Service::Interface* self); + /** * AM::GetDLCTitleInfos service function * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004008C. @@ -439,6 +451,18 @@ void GetCoreVersionFromCia(Service::Interface* self); */ void GetRequiredSizeFromCia(Service::Interface* self); +/** + * AM::DeleteProgram service function + * Deletes a program + * Inputs: + * 0 : Command header (0x041000C0) + * 1 : Media type + * 2-3 : Title ID + * Outputs: + * 1 : Result, 0 on success, otherwise error code + */ +void DeleteProgram(Service::Interface* self); + /** * AM::GetMetaSizeFromCia service function * Returns the size of a given CIA's meta section diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp index 980518328..4ba5bddf9 100644 --- a/src/core/hle/service/am/am_net.cpp +++ b/src/core/hle/service/am/am_net.cpp @@ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetNumPrograms, "GetNumPrograms"}, {0x00020082, GetProgramList, "GetProgramList"}, {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, {0x000500C0, nullptr, "GetProductCode"}, {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, @@ -69,7 +69,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, {0x040F0000, nullptr, "UpdateFirmwareAuto"}, - {0x041000C0, nullptr, "DeleteProgram"}, + {0x041000C0, DeleteProgram, "DeleteProgram"}, {0x04110044, nullptr, "GetTwlProgramListForReboot"}, {0x04120000, nullptr, "GetSystemUpdaterMutex"}, {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp index a809ef4ca..7b2eebf17 100644 --- a/src/core/hle/service/am/am_sys.cpp +++ b/src/core/hle/service/am/am_sys.cpp @@ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetNumPrograms, "GetNumPrograms"}, {0x00020082, GetProgramList, "GetProgramList"}, {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, {0x000500C0, nullptr, "GetProductCode"}, {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp index 8fd024577..dc9b6985a 100644 --- a/src/core/hle/service/am/am_u.cpp +++ b/src/core/hle/service/am/am_u.cpp @@ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00010040, GetNumPrograms, "GetNumPrograms"}, {0x00020082, GetProgramList, "GetProgramList"}, {0x00030084, GetProgramInfos, "GetProgramInfos"}, - {0x000400C0, nullptr, "DeleteUserProgram"}, + {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, {0x000500C0, nullptr, "GetProductCode"}, {0x000600C0, nullptr, "GetStorageId"}, {0x00070080, DeleteTicket, "DeleteTicket"}, @@ -69,7 +69,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, {0x040F0000, nullptr, "UpdateFirmwareAuto"}, - {0x041000C0, nullptr, "DeleteProgram"}, + {0x041000C0, DeleteProgram, "DeleteProgram"}, {0x04110044, nullptr, "GetTwlProgramListForReboot"}, {0x04120000, nullptr, "GetSystemUpdaterMutex"}, {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"},