Stub some missing AM Ticket functions (#7172)
This commit is contained in:
parent
ba702043f0
commit
b6acebcb11
|
@ -50,6 +50,9 @@ public:
|
||||||
|
|
||||||
Loader::ResultStatus Load(std::span<const u8> file_data, std::size_t offset = 0);
|
Loader::ResultStatus Load(std::span<const u8> file_data, std::size_t offset = 0);
|
||||||
std::optional<std::array<u8, 16>> GetTitleKey() const;
|
std::optional<std::array<u8, 16>> GetTitleKey() const;
|
||||||
|
u64 GetTitleID() const {
|
||||||
|
return ticket_body.title_id;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Body ticket_body;
|
Body ticket_body;
|
||||||
|
|
|
@ -374,6 +374,45 @@ bool CIAFile::Close() const {
|
||||||
|
|
||||||
void CIAFile::Flush() const {}
|
void CIAFile::Flush() const {}
|
||||||
|
|
||||||
|
TicketFile::TicketFile() {}
|
||||||
|
|
||||||
|
TicketFile::~TicketFile() {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultVal<std::size_t> TicketFile::Read(u64 offset, std::size_t length, u8* buffer) const {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultVal<std::size_t> TicketFile::Write(u64 offset, std::size_t length, bool flush,
|
||||||
|
const u8* buffer) {
|
||||||
|
written += length;
|
||||||
|
data.resize(written);
|
||||||
|
std::memcpy(data.data() + offset, buffer, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 TicketFile::GetSize() const {
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TicketFile::SetSize(u64 size) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TicketFile::Close() const {
|
||||||
|
FileSys::Ticket ticket;
|
||||||
|
if (ticket.Load(data, 0) == Loader::ResultStatus::Success) {
|
||||||
|
LOG_WARNING(Service_AM, "Discarding ticket for {:#016X}.", ticket.GetTitleID());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Service_AM, "Invalid ticket provided to TicketFile.");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TicketFile::Flush() const {}
|
||||||
|
|
||||||
InstallStatus InstallCIA(const std::string& path,
|
InstallStatus InstallCIA(const std::string& path,
|
||||||
std::function<ProgressCallback>&& update_callback) {
|
std::function<ProgressCallback>&& update_callback) {
|
||||||
LOG_INFO(Service_AM, "Installing {}...", path);
|
LOG_INFO(Service_AM, "Installing {}...", path);
|
||||||
|
@ -942,6 +981,10 @@ void Module::Interface::GetProgramInfos(Kernel::HLERequestContext& ctx) {
|
||||||
rb.PushMappedBuffer(title_info_out);
|
rb.PushMappedBuffer(title_info_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetProgramInfosIgnorePlatform(Kernel::HLERequestContext& ctx) {
|
||||||
|
GetProgramInfos(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void Module::Interface::DeleteUserProgram(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::DeleteUserProgram(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
auto media_type = rp.PopEnum<FS::MediaType>();
|
auto media_type = rp.PopEnum<FS::MediaType>();
|
||||||
|
@ -1177,6 +1220,16 @@ void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push<bool>(false);
|
rb.Push<bool>(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::Interface::DoCleanup(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
const auto media_type = rp.Pop<u8>();
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_AM, "(STUBBED) called, media_type={:#02x}", media_type);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
u8 media_type = rp.Pop<u8>();
|
u8 media_type = rp.Pop<u8>();
|
||||||
|
@ -1188,6 +1241,45 @@ void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& c
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) media_type={}", media_type);
|
LOG_WARNING(Service_AM, "(STUBBED) media_type={}", media_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetPersonalizedTicketInfoList(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
[[maybe_unused]] u32 ticket_count = rp.Pop<u32>();
|
||||||
|
[[maybe_unused]] auto& buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
|
rb.Push(RESULT_SUCCESS); // No error
|
||||||
|
rb.Push(0);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, ticket_count={}", ticket_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetNumImportTitleContextsFiltered(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
u8 media_type = rp.Pop<u8>();
|
||||||
|
u8 filter = rp.Pop<u8>();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
|
rb.Push(RESULT_SUCCESS); // No error
|
||||||
|
rb.Push(0);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, media_type={}, filter={}", media_type, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetImportTitleContextListFiltered(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
[[maybe_unused]] const u32 count = rp.Pop<u32>();
|
||||||
|
const u8 media_type = rp.Pop<u8>();
|
||||||
|
const u8 filter = rp.Pop<u8>();
|
||||||
|
auto& buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
||||||
|
rb.Push(RESULT_SUCCESS); // No error
|
||||||
|
rb.Push(0);
|
||||||
|
rb.PushMappedBuffer(buffer);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called, media_type={}, filter={}", media_type, filter);
|
||||||
|
}
|
||||||
|
|
||||||
void Module::Interface::CheckContentRights(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::CheckContentRights(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
u64 tid = rp.Pop<u64>();
|
u64 tid = rp.Pop<u64>();
|
||||||
|
@ -1674,6 +1766,30 @@ void Module::Interface::GetMetaDataFromCia(Kernel::HLERequestContext& ctx) {
|
||||||
rb.PushMappedBuffer(output_buffer);
|
rb.PushMappedBuffer(output_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Module::Interface::BeginImportTicket(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
|
// Create our TicketFile handle for the app to write to
|
||||||
|
auto file = std::make_shared<Service::FS::File>(am->kernel, std::make_unique<TicketFile>(),
|
||||||
|
FileSys::Path{});
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
|
rb.Push(RESULT_SUCCESS); // No error
|
||||||
|
rb.PushCopyObjects(file->Connect());
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::EndImportTicket(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
[[maybe_unused]] const auto ticket = rp.PopObject<Kernel::ClientSession>();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
}
|
||||||
|
|
||||||
Module::Module(Core::System& system) : kernel(system.Kernel()) {
|
Module::Module(Core::System& system) : kernel(system.Kernel()) {
|
||||||
ScanForAllTitles();
|
ScanForAllTitles();
|
||||||
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
||||||
|
|
|
@ -109,6 +109,25 @@ private:
|
||||||
std::unique_ptr<DecryptionState> decryption_state;
|
std::unique_ptr<DecryptionState> decryption_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A file handled returned for Tickets to be written into and subsequently installed.
|
||||||
|
class TicketFile final : public FileSys::FileBackend {
|
||||||
|
public:
|
||||||
|
explicit TicketFile();
|
||||||
|
~TicketFile();
|
||||||
|
|
||||||
|
ResultVal<std::size_t> Read(u64 offset, std::size_t length, u8* buffer) const override;
|
||||||
|
ResultVal<std::size_t> Write(u64 offset, std::size_t length, bool flush,
|
||||||
|
const u8* buffer) override;
|
||||||
|
u64 GetSize() const override;
|
||||||
|
bool SetSize(u64 size) const override;
|
||||||
|
bool Close() const override;
|
||||||
|
void Flush() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
u64 written = 0;
|
||||||
|
std::vector<u8> data;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs a CIA file from a specified file path.
|
* Installs a CIA file from a specified file path.
|
||||||
* @param path file path of the CIA file to install
|
* @param path file path of the CIA file to install
|
||||||
|
@ -272,6 +291,18 @@ public:
|
||||||
*/
|
*/
|
||||||
void GetProgramInfos(Kernel::HLERequestContext& ctx);
|
void GetProgramInfos(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::GetProgramInfosIgnorePlatform service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : u8 Mediatype
|
||||||
|
* 2 : Total titles
|
||||||
|
* 4 : TitleIDList pointer
|
||||||
|
* 6 : TitleList pointer
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void GetProgramInfosIgnorePlatform(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AM::DeleteUserProgram service function
|
* AM::DeleteUserProgram service function
|
||||||
* Deletes a user program
|
* Deletes a user program
|
||||||
|
@ -389,6 +420,15 @@ public:
|
||||||
*/
|
*/
|
||||||
void NeedsCleanup(Kernel::HLERequestContext& ctx);
|
void NeedsCleanup(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::DoCleanup service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Media Type
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void DoCleanup(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AM::QueryAvailableTitleDatabase service function
|
* AM::QueryAvailableTitleDatabase service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
|
@ -399,6 +439,42 @@ public:
|
||||||
*/
|
*/
|
||||||
void QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx);
|
void QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::GetPersonalizedTicketInfoList service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Count
|
||||||
|
* 2-3 : Buffer
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
* 2 : Out count
|
||||||
|
*/
|
||||||
|
void GetPersonalizedTicketInfoList(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::GetNumImportTitleContextsFiltered service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Count
|
||||||
|
* 2 : Filter
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
* 2 : Num import titles
|
||||||
|
*/
|
||||||
|
void GetNumImportTitleContextsFiltered(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::GetImportTitleContextListFiltered service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Count
|
||||||
|
* 2 : Media type
|
||||||
|
* 3 : filter
|
||||||
|
* 4-5 : Buffer
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
* 2 : Out count
|
||||||
|
* 3-4 : Out buffer
|
||||||
|
*/
|
||||||
|
void GetImportTitleContextListFiltered(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AM::CheckContentRights service function
|
* AM::CheckContentRights service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
|
@ -602,6 +678,25 @@ public:
|
||||||
*/
|
*/
|
||||||
void GetMetaDataFromCia(Kernel::HLERequestContext& ctx);
|
void GetMetaDataFromCia(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::BeginImportTicket service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Media type to install title to
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
* 2-3 : TicketHandle handle for application to write to
|
||||||
|
*/
|
||||||
|
void BeginImportTicket(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AM::EndImportTicket service function
|
||||||
|
* Inputs:
|
||||||
|
* 1-2 : TicketHandle handle application wrote to
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void EndImportTicket(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Module> am;
|
std::shared_ptr<Module> am;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,19 +42,19 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||||
{0x001E, nullptr, "ReadTwlBackupInfo"},
|
{0x001E, nullptr, "ReadTwlBackupInfo"},
|
||||||
{0x001F, nullptr, "DeleteAllExpiredUserPrograms"},
|
{0x001F, nullptr, "DeleteAllExpiredUserPrograms"},
|
||||||
{0x0020, nullptr, "GetTwlArchiveResourceInfo"},
|
{0x0020, nullptr, "GetTwlArchiveResourceInfo"},
|
||||||
{0x0021, nullptr, "GetPersonalizedTicketInfoList"},
|
{0x0021, &AM_NET::GetPersonalizedTicketInfoList, "GetPersonalizedTicketInfoList"},
|
||||||
{0x0022, nullptr, "DeleteAllImportContextsFiltered"},
|
{0x0022, nullptr, "DeleteAllImportContextsFiltered"},
|
||||||
{0x0023, nullptr, "GetNumImportTitleContextsFiltered"},
|
{0x0023, &AM_NET::GetNumImportTitleContextsFiltered, "GetNumImportTitleContextsFiltered"},
|
||||||
{0x0024, nullptr, "GetImportTitleContextListFiltered"},
|
{0x0024, &AM_NET::GetImportTitleContextListFiltered, "GetImportTitleContextListFiltered"},
|
||||||
{0x0025, nullptr, "CheckContentRights"},
|
{0x0025, &AM_NET::CheckContentRights, "CheckContentRights"},
|
||||||
{0x0026, nullptr, "GetTicketLimitInfos"},
|
{0x0026, nullptr, "GetTicketLimitInfos"},
|
||||||
{0x0027, nullptr, "GetDemoLaunchInfos"},
|
{0x0027, nullptr, "GetDemoLaunchInfos"},
|
||||||
{0x0028, nullptr, "ReadTwlBackupInfoEx"},
|
{0x0028, nullptr, "ReadTwlBackupInfoEx"},
|
||||||
{0x0029, nullptr, "DeleteUserProgramsAtomically"},
|
{0x0029, nullptr, "DeleteUserProgramsAtomically"},
|
||||||
{0x002A, nullptr, "GetNumExistingContentInfosSystem"},
|
{0x002A, nullptr, "GetNumExistingContentInfosSystem"},
|
||||||
{0x002B, nullptr, "ListExistingContentInfosSystem"},
|
{0x002B, nullptr, "ListExistingContentInfosSystem"},
|
||||||
{0x002C, nullptr, "GetProgramInfosIgnorePlatform"},
|
{0x002C, &AM_NET::GetProgramInfosIgnorePlatform, "GetProgramInfosIgnorePlatform"},
|
||||||
{0x002D, nullptr, "CheckContentRightsIgnorePlatform"},
|
{0x002D, &AM_NET::CheckContentRightsIgnorePlatform, "CheckContentRightsIgnorePlatform"},
|
||||||
{0x0401, nullptr, "UpdateFirmwareTo"},
|
{0x0401, nullptr, "UpdateFirmwareTo"},
|
||||||
{0x0402, &AM_NET::BeginImportProgram, "BeginImportProgram"},
|
{0x0402, &AM_NET::BeginImportProgram, "BeginImportProgram"},
|
||||||
{0x0403, nullptr, "BeginImportProgramTemporarily"},
|
{0x0403, nullptr, "BeginImportProgramTemporarily"},
|
||||||
|
@ -72,7 +72,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||||
{0x040F, nullptr, "UpdateFirmwareAuto"},
|
{0x040F, nullptr, "UpdateFirmwareAuto"},
|
||||||
{0x0410, &AM_NET::DeleteProgram, "DeleteProgram"},
|
{0x0410, &AM_NET::DeleteProgram, "DeleteProgram"},
|
||||||
{0x0411, nullptr, "GetTwlProgramListForReboot"},
|
{0x0411, nullptr, "GetTwlProgramListForReboot"},
|
||||||
{0x0412, nullptr, "GetSystemUpdaterMutex"},
|
{0x0412, &AM_NET::GetSystemUpdaterMutex, "GetSystemUpdaterMutex"},
|
||||||
{0x0413, &AM_NET::GetMetaSizeFromCia, "GetMetaSizeFromCia"},
|
{0x0413, &AM_NET::GetMetaSizeFromCia, "GetMetaSizeFromCia"},
|
||||||
{0x0414, &AM_NET::GetMetaDataFromCia, "GetMetaDataFromCia"},
|
{0x0414, &AM_NET::GetMetaDataFromCia, "GetMetaDataFromCia"},
|
||||||
{0x0415, nullptr, "CheckDemoLaunchRights"},
|
{0x0415, nullptr, "CheckDemoLaunchRights"},
|
||||||
|
@ -80,9 +80,9 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||||
{0x0417, nullptr, "PerpetuateAgbSaveData"},
|
{0x0417, nullptr, "PerpetuateAgbSaveData"},
|
||||||
{0x0418, nullptr, "BeginImportProgramForOverWrite"},
|
{0x0418, nullptr, "BeginImportProgramForOverWrite"},
|
||||||
{0x0419, nullptr, "BeginImportSystemProgram"},
|
{0x0419, nullptr, "BeginImportSystemProgram"},
|
||||||
{0x0801, nullptr, "BeginImportTicket"},
|
{0x0801, &AM_NET::BeginImportTicket, "BeginImportTicket"},
|
||||||
{0x0802, nullptr, "CancelImportTicket"},
|
{0x0802, nullptr, "CancelImportTicket"},
|
||||||
{0x0803, nullptr, "EndImportTicket"},
|
{0x0803, &AM_NET::EndImportTicket, "EndImportTicket"},
|
||||||
{0x0804, nullptr, "BeginImportTitle"},
|
{0x0804, nullptr, "BeginImportTitle"},
|
||||||
{0x0805, nullptr, "StopImportTitle"},
|
{0x0805, nullptr, "StopImportTitle"},
|
||||||
{0x0806, nullptr, "ResumeImportTitle"},
|
{0x0806, nullptr, "ResumeImportTitle"},
|
||||||
|
|
|
@ -29,7 +29,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||||
{0x0011, nullptr, "GetImportContentContexts"},
|
{0x0011, nullptr, "GetImportContentContexts"},
|
||||||
{0x0012, nullptr, "DeleteImportContentContexts"},
|
{0x0012, nullptr, "DeleteImportContentContexts"},
|
||||||
{0x0013, &AM_SYS::NeedsCleanup, "NeedsCleanup"},
|
{0x0013, &AM_SYS::NeedsCleanup, "NeedsCleanup"},
|
||||||
{0x0014, nullptr, "DoCleanup"},
|
{0x0014, &AM_SYS::DoCleanup, "DoCleanup"},
|
||||||
{0x0015, nullptr, "DeleteAllImportContexts"},
|
{0x0015, nullptr, "DeleteAllImportContexts"},
|
||||||
{0x0016, nullptr, "DeleteAllTemporaryPrograms"},
|
{0x0016, nullptr, "DeleteAllTemporaryPrograms"},
|
||||||
{0x0017, nullptr, "ImportTwlBackupLegacy"},
|
{0x0017, nullptr, "ImportTwlBackupLegacy"},
|
||||||
|
|
Reference in New Issue