mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 16:20:05 +00:00
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:
parent
0cea9c54ac
commit
ac626edabc
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"},
|
||||
|
@ -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"},
|
||||
|
@ -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"},
|
||||
|
Loading…
Reference in New Issue
Block a user