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
This commit is contained in:
Valentin Vanelslande 2018-02-28 08:25:33 -06:00 committed by Weiyi Wang
parent 0cea9c54ac
commit ac626edabc
5 changed files with 81 additions and 5 deletions

View file

@ -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<FS::MediaType>();
u32 low = rp.Pop<u32>();
u32 high = rp.Pop<u32>();
u64 title_id = static_cast<u64>(low) | (static_cast<u64>(high) << 32);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
u16 category = static_cast<u16>((title_id >> 32) & 0xFFFF);
u8 variation = static_cast<u8>(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<FS::MediaType>();
u32 low = rp.Pop<u32>();
u32 high = rp.Pop<u32>();
u64 title_id = static_cast<u64>(low) | (static_cast<u64>(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

View file

@ -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

View file

@ -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"},

View file

@ -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"},

View file

@ -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"},