mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +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
					
				
					 5 changed files with 81 additions and 5 deletions
				
			
		|  | @ -688,6 +688,36 @@ void GetProgramInfos(Service::Interface* self) { | ||||||
|     rb.PushMappedBuffer(title_info_out, title_info_size, title_info_perms); |     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) { | void GetDLCTitleInfos(Service::Interface* self) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1005, 2, 4); // 0x10050084
 |     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)); |     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) { | void GetMetaSizeFromCia(Service::Interface* self) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0413, 0, 2); // 0x04130002
 |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0413, 0, 2); // 0x04130002
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ enum { | ||||||
|     CIACurrentlyInstalling = 4, |     CIACurrentlyInstalling = 4, | ||||||
|     InvalidTID = 31, |     InvalidTID = 31, | ||||||
|     EmptyCIA = 32, |     EmptyCIA = 32, | ||||||
|  |     TryingToUninstallSystemApp = 44, | ||||||
|     InvalidTIDInList = 60, |     InvalidTIDInList = 60, | ||||||
|     InvalidCIAHeader = 104, |     InvalidCIAHeader = 104, | ||||||
| }; | }; | ||||||
|  | @ -226,6 +227,17 @@ void GetProgramList(Service::Interface* self); | ||||||
|  */ |  */ | ||||||
| void GetProgramInfos(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 |  * AM::GetDLCTitleInfos service function | ||||||
|  * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004008C. |  * 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); | 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 |  * AM::GetMetaSizeFromCia service function | ||||||
|  * Returns the size of a given CIA's meta section |  * Returns the size of a given CIA's meta section | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     {0x00010040, GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |     {0x00020082, GetProgramList, "GetProgramList"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |     {0x00030084, GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000400C0, nullptr, "DeleteUserProgram"}, |     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |     {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |     {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |     {0x00070080, DeleteTicket, "DeleteTicket"}, | ||||||
|  | @ -69,7 +69,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, |     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, | ||||||
|     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, |     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, | ||||||
|     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, |     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, | ||||||
|     {0x041000C0, nullptr, "DeleteProgram"}, |     {0x041000C0, DeleteProgram, "DeleteProgram"}, | ||||||
|     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, |     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, | ||||||
|     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, |     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, | ||||||
|     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, |     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     {0x00010040, GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |     {0x00020082, GetProgramList, "GetProgramList"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |     {0x00030084, GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000400C0, nullptr, "DeleteUserProgram"}, |     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |     {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |     {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |     {0x00070080, DeleteTicket, "DeleteTicket"}, | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     {0x00010040, GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |     {0x00020082, GetProgramList, "GetProgramList"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |     {0x00030084, GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000400C0, nullptr, "DeleteUserProgram"}, |     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |     {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |     {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |     {0x00070080, DeleteTicket, "DeleteTicket"}, | ||||||
|  | @ -69,7 +69,7 @@ const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, |     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, | ||||||
|     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, |     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, | ||||||
|     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, |     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, | ||||||
|     {0x041000C0, nullptr, "DeleteProgram"}, |     {0x041000C0, DeleteProgram, "DeleteProgram"}, | ||||||
|     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, |     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, | ||||||
|     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, |     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, | ||||||
|     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, |     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue