C++ is a general-purpose programming language created by Bjarne Stroustrup as an extension of the C programming language, or "C with Classes". The language has expanded significantly over time, and modern C++ now has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation. It is almost always implemented as a compiled language, and many vendors provide C++ compilers, including the Free Software Foundation, LLVM, Microsoft, Intel, Oracle, and IBM, so it is available on many platforms.
* fix XCI installation if card was inserted prior * fix double expression call on ASSERT_OK failure * fix compatibility with latest libnx master to build with usb:ds changes for 11.0.0+ * remove unused functions
This commit is contained in:
parent
c1a9658313
commit
3f7b8497db
11
Makefile
11
Makefile
@ -54,16 +54,21 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
|||||||
|
|
||||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||||
$(ARCH) $(DEFINES)
|
$(ARCH) $(DEFINES)
|
||||||
|
CFLAGS += `curl-config --cflags`
|
||||||
|
CFLAGS += `sdl2-config --cflags` `freetype-config --cflags`
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -D__SWITCH__ -Wall -Werror #-D__DEBUG__ -DNXLINK_DEBUG
|
CFLAGS += $(INCLUDE) -D__SWITCH__ -Wall #-Werror -D__DEBUG__ -DNXLINK_DEBUG
|
||||||
|
|
||||||
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++17 -Wall -Werror
|
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++17
|
||||||
|
|
||||||
|
|
||||||
ASFLAGS := -g $(ARCH)
|
ASFLAGS := -g $(ARCH)
|
||||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
LIBS := -lcurl -lz -lmbedtls -lmbedcrypto -lmbedx509 -lminizip -lnx -lstdc++fs -lzzip -lpu -lfreetype -lSDL2_mixer -lopusfile -lopus -lmodplug -lmpg123 -lvorbisidec -lSDL2 -lc -logg -lSDL2_ttf -lSDL2_gfx -lSDL2_image -lwebp -lpng -ljpeg `sdl2-config --libs` `freetype-config --libs` -lzstd
|
LIBS := `curl-config --libs` # Networking
|
||||||
|
LIBS += -lSDL2_mixer -lopusfile -lopus -lmodplug -lmpg123 -lvorbisidec -logg # Audio
|
||||||
|
LIBS += -lpu -lSDL2_gfx -lSDL2_image -lwebp -lpng -ljpeg `sdl2-config --libs` `freetype-config --libs` # Graphics
|
||||||
|
LIBS += -lmbedtls -lmbedcrypto -lminizip -lzstd # Memes
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
@ -22,21 +22,9 @@ SOFTWARE.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <switch/services/ncm.h>
|
#include <switch/types.h>
|
||||||
|
|
||||||
typedef struct {
|
Result esInitialize(void);
|
||||||
u8 c[0x10];
|
void esExit(void);
|
||||||
} RightsId;
|
|
||||||
|
|
||||||
Result esInitialize();
|
Result esImportTicket(void const *tikBuf, size_t tikSize, void const *certBuf, size_t certSize);
|
||||||
void esExit();
|
|
||||||
Service* esGetServiceSession();
|
|
||||||
|
|
||||||
Result esImportTicket(void const *tikBuf, size_t tikSize, void const *certBuf, size_t certSize); //1
|
|
||||||
Result esDeleteTicket(const RightsId *rightsIdBuf, size_t bufSize); //3
|
|
||||||
Result esGetTitleKey(const RightsId *rightsId, u8 *outBuf, size_t bufSize); //8
|
|
||||||
Result esCountCommonTicket(u32 *numTickets); //9
|
|
||||||
Result esCountPersonalizedTicket(u32 *numTickets); // 10
|
|
||||||
Result esListCommonTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize);
|
|
||||||
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize);
|
|
||||||
Result esGetCommonTicketData(u64 *unkOut, void *outBuf1, size_t bufSize1, const RightsId* rightsId);
|
|
||||||
|
@ -25,29 +25,18 @@ SOFTWARE.
|
|||||||
#include <switch/services/ns.h>
|
#include <switch/services/ns.h>
|
||||||
#include <switch/services/ncm.h>
|
#include <switch/services/ncm.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef enum {
|
||||||
u64 titleID;
|
NsApplicationRecordType_Installed = 0x3,
|
||||||
u64 unk;
|
NsApplicationRecordType_GamecardMissing = 0x5,
|
||||||
u64 size;
|
NsApplicationRecordType_Archived = 0xB,
|
||||||
} PACKED ApplicationRecord;
|
} NsApplicationRecordType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NcmContentMetaKey metaRecord;
|
NcmContentMetaKey metaRecord;
|
||||||
u64 storageId;
|
u64 storageId;
|
||||||
} PACKED ContentStorageRecord;
|
} ContentStorageRecord;
|
||||||
|
|
||||||
Result nsextInitialize(void);
|
Result nsextInitialize(void);
|
||||||
void nsextExit(void);
|
void nsextExit(void);
|
||||||
|
|
||||||
Result nsPushApplicationRecord(u64 title_id, u8 last_modified_event, ContentStorageRecord *content_records_buf, size_t buf_size);
|
Result nsPushApplicationRecord(u64 application_id, NsApplicationRecordType last_modified_event, ContentStorageRecord *content_records, u32 count);
|
||||||
Result nsListApplicationRecordContentMeta(u64 offset, u64 titleID, void *out_buf, size_t out_buf_size, u32 *entries_read_out);
|
|
||||||
Result nsDeleteApplicationRecord(u64 titleID);
|
|
||||||
Result nsLaunchApplication(u64 titleID);
|
|
||||||
Result nsPushLaunchVersion(u64 titleID, u32 version);
|
|
||||||
Result nsDisableApplicationAutoUpdate(u64 titleID);
|
|
||||||
Result nsGetContentMetaStorage(const NcmContentMetaKey *record, u8 *out);
|
|
||||||
Result nsBeginInstallApplication(u64 tid, u32 unk, u8 storageId);
|
|
||||||
Result nsInvalidateAllApplicationControlCache(void);
|
|
||||||
Result nsInvalidateApplicationControlCache(u64 tid);
|
|
||||||
Result nsCheckApplicationLaunchRights(u64 tid);
|
|
||||||
Result nsGetApplicationContentPath(u64 titleId, u8 type, char *outBuf, size_t bufSize);
|
|
||||||
|
@ -31,4 +31,4 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,16 +24,27 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include "util/debug.h"
|
|
||||||
|
#define ASSERT_OK(res_expr, desc) \
|
||||||
|
({ \
|
||||||
|
const auto tmp_rc = (res_expr); \
|
||||||
|
if (R_FAILED(tmp_rc)) { \
|
||||||
|
char msg[256] = {}; std::snprintf(msg, 256-1, "%s:%u: %s. Error code: 0x%08x\n", __func__, __LINE__, desc, tmp_rc); \
|
||||||
|
throw std::runtime_error(msg); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define THROW_FORMAT(format, ...) \
|
||||||
|
({ \
|
||||||
|
char error_prefix[512] = {}; std::snprintf(error_prefix, 256-1, "%s:%u: ", __func__, __LINE__); \
|
||||||
|
char formatted_msg[256] = {}; std::snprintf(formatted_msg, 256-1, format, ##__VA_ARGS__); \
|
||||||
|
std::strncat(error_prefix, formatted_msg, 512-1); throw std::runtime_error(error_prefix); \
|
||||||
|
})
|
||||||
|
|
||||||
#define ASSERT_OK(rc_out, desc) if (R_FAILED(rc_out)) { char msg[256] = {0}; snprintf(msg, 256-1, "%s:%u: %s. Error code: 0x%08x\n", __func__, __LINE__, desc, rc_out); throw std::runtime_error(msg); }
|
|
||||||
#define THROW_FORMAT(format, ...) { char error_prefix[512] = {0}; snprintf(error_prefix, 256-1, "%s:%u: ", __func__, __LINE__);\
|
|
||||||
char formatted_msg[256] = {0}; snprintf(formatted_msg, 256-1, format, ##__VA_ARGS__);\
|
|
||||||
strncat(error_prefix, formatted_msg, 512-1); throw std::runtime_error(error_prefix); }
|
|
||||||
|
|
||||||
#ifdef NXLINK_DEBUG
|
#ifdef NXLINK_DEBUG
|
||||||
#define LOG_DEBUG(format, ...) { printf("%s:%u: ", __func__, __LINE__); printf(format, ##__VA_ARGS__); }
|
#define LOG_DEBUG(format, ...) { std::printf("%s:%u: ", __func__, __LINE__); std::printf(format, ##__VA_ARGS__); }
|
||||||
#else
|
#else
|
||||||
#define LOG_DEBUG(format, ...) ;
|
#define LOG_DEBUG(format, ...) ;
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,8 +29,8 @@ SOFTWARE.
|
|||||||
|
|
||||||
namespace tin::util
|
namespace tin::util
|
||||||
{
|
{
|
||||||
u64 GetRightsIdTid(RightsId rightsId);
|
u64 GetRightsIdTid(FsRightsId rightsId);
|
||||||
u64 GetRightsIdKeyGen(RightsId rightsId);
|
u64 GetRightsIdKeyGen(FsRightsId rightsId);
|
||||||
|
|
||||||
std::string GetNcaIdString(const NcmContentId& ncaId);
|
std::string GetNcaIdString(const NcmContentId& ncaId);
|
||||||
NcmContentId GetNcaIdFromString(std::string ncaIdStr);
|
NcmContentId GetNcaIdFromString(std::string ncaIdStr);
|
||||||
|
@ -19,7 +19,7 @@ namespace inst::util {
|
|||||||
std::string getDriveFileName(std::string fileId);
|
std::string getDriveFileName(std::string fileId);
|
||||||
std::vector<uint32_t> setClockSpeed(int deviceToClock, uint32_t clockSpeed);
|
std::vector<uint32_t> setClockSpeed(int deviceToClock, uint32_t clockSpeed);
|
||||||
std::string getIPAddress();
|
std::string getIPAddress();
|
||||||
int getUsbState();
|
bool usbIsConnected();
|
||||||
void playAudio(std::string audioPath);
|
void playAudio(std::string audioPath);
|
||||||
std::vector<std::string> checkForAppUpdate();
|
std::vector<std::string> checkForAppUpdate();
|
||||||
}
|
}
|
@ -69,56 +69,15 @@ namespace tin::install
|
|||||||
|
|
||||||
void Install::InstallApplicationRecord(int i)
|
void Install::InstallApplicationRecord(int i)
|
||||||
{
|
{
|
||||||
Result rc = 0;
|
const u64 baseTitleId = tin::util::GetBaseTitleId(this->GetTitleId(i), this->GetContentMetaType(i));
|
||||||
std::vector<ContentStorageRecord> storageRecords;
|
|
||||||
u64 baseTitleId = tin::util::GetBaseTitleId(this->GetTitleId(i), this->GetContentMetaType(i));
|
|
||||||
s32 contentMetaCount = 0;
|
|
||||||
|
|
||||||
LOG_DEBUG("Base title Id: 0x%lx", baseTitleId);
|
|
||||||
|
|
||||||
// TODO: Make custom error with result code field
|
|
||||||
// 0x410: The record doesn't already exist
|
|
||||||
if (R_FAILED(rc = nsCountApplicationContentMeta(baseTitleId, &contentMetaCount)) && rc != 0x410)
|
|
||||||
{
|
|
||||||
THROW_FORMAT("Failed to count application content meta");
|
|
||||||
}
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
LOG_DEBUG("Content meta count: %u\n", contentMetaCount);
|
|
||||||
|
|
||||||
// Obtain any existing app record content meta and append it to our vector
|
|
||||||
if (contentMetaCount > 0)
|
|
||||||
{
|
|
||||||
storageRecords.resize(contentMetaCount);
|
|
||||||
size_t contentStorageBufSize = contentMetaCount * sizeof(ContentStorageRecord);
|
|
||||||
auto contentStorageBuf = std::make_unique<ContentStorageRecord[]>(contentMetaCount);
|
|
||||||
u32 entriesRead;
|
|
||||||
|
|
||||||
ASSERT_OK(nsListApplicationRecordContentMeta(0, baseTitleId, contentStorageBuf.get(), contentStorageBufSize, &entriesRead), "Failed to list application record content meta");
|
|
||||||
|
|
||||||
if ((s32)entriesRead != contentMetaCount)
|
|
||||||
{
|
|
||||||
THROW_FORMAT("Mismatch between entries read and content meta count");
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(storageRecords.data(), contentStorageBuf.get(), contentStorageBufSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add our new content meta
|
// Add our new content meta
|
||||||
ContentStorageRecord storageRecord;
|
ContentStorageRecord storageRecord;
|
||||||
storageRecord.metaRecord = m_contentMeta[i].GetContentMetaKey();
|
storageRecord.metaRecord = m_contentMeta[i].GetContentMetaKey();
|
||||||
storageRecord.storageId = m_destStorageId;
|
storageRecord.storageId = m_destStorageId;
|
||||||
storageRecords.push_back(storageRecord);
|
|
||||||
|
|
||||||
// Replace the existing application records with our own
|
|
||||||
try
|
|
||||||
{
|
|
||||||
nsDeleteApplicationRecord(baseTitleId);
|
|
||||||
}
|
|
||||||
catch (...) {}
|
|
||||||
|
|
||||||
LOG_DEBUG("Pushing application record...\n");
|
LOG_DEBUG("Pushing application record...\n");
|
||||||
ASSERT_OK(nsPushApplicationRecord(baseTitleId, 0x3, storageRecords.data(), storageRecords.size() * sizeof(ContentStorageRecord)), "Failed to push application record");
|
ASSERT_OK(nsPushApplicationRecord(baseTitleId, NsApplicationRecordType_Installed, &storageRecord, 1), "Failed to push application record");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate and obtain all data needed for install
|
// Validate and obtain all data needed for install
|
||||||
|
@ -56,7 +56,7 @@ namespace tin::install::nsp
|
|||||||
const PFS0FileEntry* NSP::GetFileEntry(unsigned int index)
|
const PFS0FileEntry* NSP::GetFileEntry(unsigned int index)
|
||||||
{
|
{
|
||||||
if (index >= this->GetBaseHeader()->numFiles)
|
if (index >= this->GetBaseHeader()->numFiles)
|
||||||
THROW_FORMAT("File entry index is out of bounds\n")
|
THROW_FORMAT("File entry index is out of bounds\n");
|
||||||
|
|
||||||
size_t fileEntryOffset = sizeof(PFS0BaseHeader) + index * sizeof(PFS0FileEntry);
|
size_t fileEntryOffset = sizeof(PFS0BaseHeader) + index * sizeof(PFS0FileEntry);
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ namespace tin::install::xci
|
|||||||
const HFS0FileEntry* XCI::GetFileEntry(unsigned int index)
|
const HFS0FileEntry* XCI::GetFileEntry(unsigned int index)
|
||||||
{
|
{
|
||||||
if (index >= this->GetSecureHeader()->numFiles)
|
if (index >= this->GetSecureHeader()->numFiles)
|
||||||
THROW_FORMAT("File entry index is out of bounds\n")
|
THROW_FORMAT("File entry index is out of bounds\n");
|
||||||
|
|
||||||
return hfs0GetFileEntry(this->GetSecureHeader(), index);
|
return hfs0GetFileEntry(this->GetSecureHeader(), index);
|
||||||
}
|
}
|
||||||
|
@ -25,24 +25,17 @@ SOFTWARE.
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "service_guard.h"
|
|
||||||
|
|
||||||
static Service g_esSrv;
|
static Service g_esSrv;
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(es);
|
Result esInitialize(void) {
|
||||||
|
|
||||||
Result _esInitialize() {
|
|
||||||
return smGetService(&g_esSrv, "es");
|
return smGetService(&g_esSrv, "es");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _esCleanup() {
|
void esExit(void) {
|
||||||
serviceClose(&g_esSrv);
|
serviceClose(&g_esSrv);
|
||||||
}
|
}
|
||||||
|
|
||||||
Service* esGetServiceSession() {
|
|
||||||
return &g_esSrv;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esImportTicket(void const *tikBuf, size_t tikSize, void const *certBuf, size_t certSize) {
|
Result esImportTicket(void const *tikBuf, size_t tikSize, void const *certBuf, size_t certSize) {
|
||||||
return serviceDispatch(&g_esSrv, 1,
|
return serviceDispatch(&g_esSrv, 1,
|
||||||
.buffer_attrs = {
|
.buffer_attrs = {
|
||||||
@ -55,91 +48,3 @@ Result esImportTicket(void const *tikBuf, size_t tikSize, void const *certBuf, s
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result esDeleteTicket(const RightsId *rightsIdBuf, size_t bufSize) {
|
|
||||||
return serviceDispatch(&g_esSrv, 3,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
|
||||||
.buffers = { { rightsIdBuf, bufSize }, },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esGetTitleKey(const RightsId *rightsId, u8 *outBuf, size_t bufSize) {
|
|
||||||
struct {
|
|
||||||
RightsId rights_Id;
|
|
||||||
u32 key_generation;
|
|
||||||
} in;
|
|
||||||
memcpy(&in.rights_Id, rightsId, sizeof(RightsId));
|
|
||||||
in.key_generation = 0;
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_esSrv, 8, in,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { outBuf, bufSize } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esCountCommonTicket(u32 *numTickets) {
|
|
||||||
struct {
|
|
||||||
u32 num_tickets;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchOut(&g_esSrv, 9, out);
|
|
||||||
if (R_SUCCEEDED(rc) && numTickets) *numTickets = out.num_tickets;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esCountPersonalizedTicket(u32 *numTickets) {
|
|
||||||
struct {
|
|
||||||
u32 num_tickets;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchOut(&g_esSrv, 10, out);
|
|
||||||
if (R_SUCCEEDED(rc) && numTickets) *numTickets = out.num_tickets;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esListCommonTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize) {
|
|
||||||
struct {
|
|
||||||
u32 num_rights_ids_written;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(&g_esSrv, 11, *numRightsIdsWritten, out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { outBuf, bufSize } },
|
|
||||||
);
|
|
||||||
if (R_SUCCEEDED(rc) && numRightsIdsWritten) *numRightsIdsWritten = out.num_rights_ids_written;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize) {
|
|
||||||
struct {
|
|
||||||
u32 num_rights_ids_written;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(&g_esSrv, 12, *numRightsIdsWritten, out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { outBuf, bufSize } },
|
|
||||||
);
|
|
||||||
if (R_SUCCEEDED(rc) && numRightsIdsWritten) *numRightsIdsWritten = out.num_rights_ids_written;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result esGetCommonTicketData(u64 *unkOut, void *outBuf1, size_t bufSize1, const RightsId* rightsId) {
|
|
||||||
struct {
|
|
||||||
RightsId rights_id;
|
|
||||||
} in;
|
|
||||||
memcpy(&in.rights_id, rightsId, sizeof(RightsId));
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 unk;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(&g_esSrv, 16, in, out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { outBuf1, bufSize1 } },
|
|
||||||
);
|
|
||||||
return rc;
|
|
||||||
}
|
|
@ -22,176 +22,38 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include "nx/ipc/ns_ext.h"
|
#include "nx/ipc/ns_ext.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "service_guard.h"
|
|
||||||
|
|
||||||
static Service g_nsAppManSrv, g_nsGetterSrv;
|
Service g_nsAppManSrv;
|
||||||
|
|
||||||
static Result _nsextGetSession(Service* srv, Service* srv_out, u32 cmd_id);
|
Result nsextInitialize(void) {
|
||||||
|
Result rc = nsInitialize();
|
||||||
|
|
||||||
NX_GENERATE_SERVICE_GUARD(nsext);
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if(hosversionBefore(3,0,0)) {
|
||||||
Result _nsextInitialize(void) {
|
g_nsAppManSrv = *nsGetServiceSession_ApplicationManagerInterface();
|
||||||
Result rc=0;
|
} else {
|
||||||
|
rc = nsGetApplicationManagerInterface(&g_nsAppManSrv);
|
||||||
if(hosversionBefore(3,0,0))
|
}
|
||||||
return smGetService(&g_nsAppManSrv, "ns:am");
|
}
|
||||||
|
|
||||||
rc = smGetService(&g_nsGetterSrv, "ns:am2");//TODO: Support the other services?(Only useful when ns:am2 isn't accessible)
|
|
||||||
if (R_FAILED(rc)) return rc;
|
|
||||||
|
|
||||||
rc = _nsextGetSession(&g_nsGetterSrv, &g_nsAppManSrv, 7996);
|
|
||||||
|
|
||||||
if (R_FAILED(rc)) serviceClose(&g_nsGetterSrv);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _nsextCleanup(void) {
|
void nsextExit(void) {
|
||||||
serviceClose(&g_nsAppManSrv);
|
if(hosversionAtLeast(3,0,0))
|
||||||
if(hosversionBefore(3,0,0)) return;
|
serviceClose(&g_nsAppManSrv);
|
||||||
|
nsExit();
|
||||||
serviceClose(&g_nsGetterSrv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result _nsextGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
|
Result nsPushApplicationRecord(u64 application_id, NsApplicationRecordType last_modified_event, ContentStorageRecord *content_records, u32 count) {
|
||||||
return serviceDispatch(srv, cmd_id,
|
|
||||||
.out_num_objects = 1,
|
|
||||||
.out_objects = srv_out,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsPushApplicationRecord(u64 title_id, u8 last_modified_event, ContentStorageRecord *content_records_buf, size_t buf_size) {
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u8 last_modified_event;
|
u8 last_modified_event;
|
||||||
u8 padding[0x7];
|
u64 application_id;
|
||||||
u64 title_id;
|
} in = { last_modified_event, application_id };
|
||||||
} in = { last_modified_event, {0}, title_id };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 16, in,
|
return serviceDispatchIn(&g_nsAppManSrv, 16, in,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
||||||
.buffers = { { content_records_buf, buf_size } });
|
.buffers = { { content_records, count * sizeof(*content_records) }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Result nsListApplicationRecordContentMeta(u64 offset, u64 titleID, void *out_buf, size_t out_buf_size, u32 *entries_read_out) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 offset;
|
|
||||||
u64 titleID;
|
|
||||||
} in = { offset, titleID };
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u32 entries_read;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(&g_nsAppManSrv, 17, in, out,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { out_buf, out_buf_size } });
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && entries_read_out) *entries_read_out = out.entries_read;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsDeleteApplicationRecord(u64 titleID) {
|
|
||||||
struct {
|
|
||||||
u64 titleID;
|
|
||||||
} in = { titleID };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 27, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsLaunchApplication(u64 titleID) {
|
|
||||||
struct {
|
|
||||||
u64 titleID;
|
|
||||||
} in = { titleID };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 19, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsPushLaunchVersion(u64 titleID, u32 version) {
|
|
||||||
struct {
|
|
||||||
u64 titleID;
|
|
||||||
u32 version;
|
|
||||||
u32 padding;
|
|
||||||
} in = { titleID, version, 0 };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 36, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsGetContentMetaStorage(const NcmContentMetaKey *record, u8 *storageOut) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
NcmContentMetaKey metaRecord;
|
|
||||||
} in;
|
|
||||||
memcpy(&in.metaRecord, record, sizeof(NcmContentMetaKey));
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u8 out;
|
|
||||||
} out;
|
|
||||||
|
|
||||||
Result rc = serviceDispatchInOut(&g_nsAppManSrv, 606, in, out);
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && storageOut) *storageOut = out.out;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsBeginInstallApplication(u64 tid, u32 unk, u8 storageId) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u32 storageId;
|
|
||||||
u32 unk;
|
|
||||||
u64 tid;
|
|
||||||
} in = { storageId, unk, tid };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 26, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsInvalidateAllApplicationControlCache(void) {
|
|
||||||
return serviceDispatch(&g_nsAppManSrv, 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsInvalidateApplicationControlCache(u64 tid) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 tid;
|
|
||||||
} in = { tid };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 404, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsCheckApplicationLaunchRights(u64 tid) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 tid;
|
|
||||||
} in = { tid };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 39, in);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsGetApplicationContentPath(u64 tid, u8 type, char *out, size_t buf_size) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u8 padding[0x7];
|
|
||||||
u8 type;
|
|
||||||
u64 tid;
|
|
||||||
} in = { {0}, type, tid };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 21, in,
|
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
||||||
.buffers = { { out, buf_size } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result nsDisableApplicationAutoUpdate(u64 titleID) {
|
|
||||||
|
|
||||||
struct {
|
|
||||||
u64 title_id;
|
|
||||||
} in = { titleID };
|
|
||||||
|
|
||||||
return serviceDispatchIn(&g_nsAppManSrv, 903, in);
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2017-2018 Adubbz
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <switch.h>
|
|
||||||
|
|
||||||
typedef struct ServiceGuard {
|
|
||||||
Mutex mutex;
|
|
||||||
u32 refCount;
|
|
||||||
} ServiceGuard;
|
|
||||||
|
|
||||||
NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g)
|
|
||||||
{
|
|
||||||
mutexLock(&g->mutex);
|
|
||||||
return (g->refCount++) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void))
|
|
||||||
{
|
|
||||||
if (R_FAILED(rc)) {
|
|
||||||
cleanupFunc();
|
|
||||||
--g->refCount;
|
|
||||||
}
|
|
||||||
mutexUnlock(&g->mutex);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void))
|
|
||||||
{
|
|
||||||
mutexLock(&g->mutex);
|
|
||||||
if (g->refCount && (--g->refCount) == 0)
|
|
||||||
cleanupFunc();
|
|
||||||
mutexUnlock(&g->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \
|
|
||||||
\
|
|
||||||
static ServiceGuard g_##name##Guard; \
|
|
||||||
NX_INLINE Result _##name##Initialize _paramdecl; \
|
|
||||||
static void _##name##Cleanup(void); \
|
|
||||||
\
|
|
||||||
Result name##Initialize _paramdecl \
|
|
||||||
{ \
|
|
||||||
Result rc = 0; \
|
|
||||||
if (serviceGuardBeginInit(&g_##name##Guard)) \
|
|
||||||
rc = _##name##Initialize _parampass; \
|
|
||||||
return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void name##Exit(void) \
|
|
||||||
{ \
|
|
||||||
serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ())
|
|
@ -115,7 +115,7 @@ namespace inst::ui {
|
|||||||
inst::config::setConfig();
|
inst::config::setConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inst::util::getUsbState() == 5) mainApp->usbinstPage->startUsb();
|
if (inst::util::usbIsConnected()) mainApp->usbinstPage->startUsb();
|
||||||
else mainApp->CreateShowDialog("main.usb.error.title"_lang, "main.usb.error.desc"_lang, {"common.ok"_lang}, false);
|
else mainApp->CreateShowDialog("main.usb.error.title"_lang, "main.usb.error.desc"_lang, {"common.ok"_lang}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ namespace usbInstStuff {
|
|||||||
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
||||||
if (kDown & KEY_B) return {};
|
if (kDown & KEY_B) return {};
|
||||||
if (kDown & KEY_X) inst::ui::mainApp->CreateShowDialog("inst.usb.help.title"_lang, "inst.usb.help.desc"_lang, {"common.ok"_lang}, true);
|
if (kDown & KEY_X) inst::ui::mainApp->CreateShowDialog("inst.usb.help.title"_lang, "inst.usb.help.desc"_lang, {"common.ok"_lang}, true);
|
||||||
if (inst::util::getUsbState() != 5) return {};
|
if (!inst::util::usbIsConnected()) return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.magic != 0x304C5554) return {};
|
if (header.magic != 0x304C5554) return {};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "util/crypto.hpp"
|
#include "util/crypto.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <mbedtls/bignum.h>
|
#include <mbedtls/bignum.h>
|
||||||
#include <stdexcept>
|
|
||||||
#include "util/error.hpp"
|
|
||||||
|
|
||||||
void Crypto::calculateMGF1andXOR(unsigned char* data, size_t data_size, const void* source, size_t source_size) {
|
void Crypto::calculateMGF1andXOR(unsigned char* data, size_t data_size, const void* source, size_t source_size) {
|
||||||
unsigned char h_buf[RSA_2048_BYTES] = {0};
|
unsigned char h_buf[RSA_2048_BYTES] = {0};
|
||||||
@ -46,7 +46,7 @@ bool Crypto::rsa2048PssVerify(const void *data, size_t len, const unsigned char
|
|||||||
mbedtls_mpi_exp_mod(&message_mpi, &signature_mpi, &e_mpi, &modulus_mpi, NULL);
|
mbedtls_mpi_exp_mod(&message_mpi, &signature_mpi, &e_mpi, &modulus_mpi, NULL);
|
||||||
|
|
||||||
if (mbedtls_mpi_write_binary(&message_mpi, m_buf, RSA_2048_BYTES) != 0) {
|
if (mbedtls_mpi_write_binary(&message_mpi, m_buf, RSA_2048_BYTES) != 0) {
|
||||||
THROW_FORMAT("Failed to export exponentiated RSA message!");
|
throw std::runtime_error("Failed to export exponentiated RSA message!");
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_mpi_free(&signature_mpi);
|
mbedtls_mpi_free(&signature_mpi);
|
||||||
|
@ -27,12 +27,12 @@ SOFTWARE.
|
|||||||
|
|
||||||
namespace tin::util
|
namespace tin::util
|
||||||
{
|
{
|
||||||
u64 GetRightsIdTid(RightsId rightsId)
|
u64 GetRightsIdTid(FsRightsId rightsId)
|
||||||
{
|
{
|
||||||
return __bswap64(*(u64 *)rightsId.c);
|
return __bswap64(*(u64 *)rightsId.c);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetRightsIdKeyGen(RightsId rightsId)
|
u64 GetRightsIdKeyGen(FsRightsId rightsId)
|
||||||
{
|
{
|
||||||
return __bswap64(*(u64 *)(rightsId.c + 8));
|
return __bswap64(*(u64 *)(rightsId.c + 8));
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ namespace inst::util {
|
|||||||
|
|
||||||
void initInstallServices() {
|
void initInstallServices() {
|
||||||
ncmInitialize();
|
ncmInitialize();
|
||||||
nsInitialize();
|
|
||||||
nsextInitialize();
|
nsextInitialize();
|
||||||
esInitialize();
|
esInitialize();
|
||||||
splCryptoInitialize();
|
splCryptoInitialize();
|
||||||
@ -47,7 +46,6 @@ namespace inst::util {
|
|||||||
|
|
||||||
void deinitInstallServices() {
|
void deinitInstallServices() {
|
||||||
ncmExit();
|
ncmExit();
|
||||||
nsExit();
|
|
||||||
nsextExit();
|
nsextExit();
|
||||||
esExit();
|
esExit();
|
||||||
splCryptoExit();
|
splCryptoExit();
|
||||||
@ -266,10 +264,10 @@ namespace inst::util {
|
|||||||
return inet_ntoa(addr);
|
return inet_ntoa(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getUsbState() {
|
bool usbIsConnected() {
|
||||||
u32 usbState = 0;
|
UsbState state = UsbState_Detached;
|
||||||
usbDsGetState(&usbState);
|
usbDsGetState(&state);
|
||||||
return usbState;
|
return state == UsbState_Configured;
|
||||||
}
|
}
|
||||||
|
|
||||||
void playAudio(std::string audioPath) {
|
void playAudio(std::string audioPath) {
|
||||||
|
Reference in New Issue
Block a user