Merge remote-tracking branch 'origin/master' into ncm-new-ipc

This commit is contained in:
Adubbz 2019-09-24 22:24:12 +10:00
commit 0a2d094fe9
2 changed files with 184 additions and 753 deletions

View File

@ -1,6 +1,6 @@
/**
* @file ns.h
* @brief NS service IPC wrapper.
* @brief NS services IPC wrapper.
* @author yellows8
* @copyright libnx Authors
*/
@ -10,70 +10,99 @@
#include "../services/fs.h"
#include "../kernel/event.h"
/// ApplicationControlData
typedef struct {
NacpStruct nacp;
u8 icon[0x20000];//JPEG
NacpStruct nacp; ///< \ref NacpStruct
u8 icon[0x20000]; ///< JPEG
} NsApplicationControlData;
typedef struct
{
u8 title_type;
u8 storageID;
u8 unk_x02;
u8 padding;
u32 title_version;
u64 titleID;
/// NsApplicationContentMetaStatus
typedef struct {
u8 title_type; ///< \ref NcmContentMetaType
u8 storageID; ///< \ref FsStorageId
u8 unk_x02; ///< Unknown.
u8 padding; ///< Padding.
u32 title_version; ///< Title version.
u64 titleID; ///< titleID.
} NsApplicationContentMetaStatus;
typedef struct
{
u64 titleID;
u8 type;
u8 unk_x09;
u8 unk_x0A[6];
u8 unk_x10;
u8 unk_x11[7];
/// ApplicationRecord
typedef struct {
u64 titleID; ///< titleID.
u8 type; ///< Type.
u8 unk_x09; ///< Unknown.
u8 unk_x0A[6]; ///< Unknown.
u8 unk_x10; ///< Unknown.
u8 unk_x11[7]; ///< Unknown.
} NsApplicationRecord;
/// LaunchProperties
typedef struct {
u64 titleID;
u32 version;
u8 storageID;
u8 index;
u8 is_application;
u64 titleID; ///< titleID.
u32 version; ///< Title version.
u8 storageID; ///< \ref FsStorageId
u8 index; ///< Index.
u8 is_application; ///< Whether this is an Application.
} NsLaunchProperties;
/// ShellEvent
typedef enum {
NsShellEvent_None = 0,
NsShellEvent_Exit = 1,
NsShellEvent_Start = 2,
NsShellEvent_Crash = 3,
NsShellEvent_Debug = 4,
NsShellEvent_None = 0, ///< None
NsShellEvent_Exit = 1, ///< Exit
NsShellEvent_Start = 2, ///< Start
NsShellEvent_Crash = 3, ///< Crash
NsShellEvent_Debug = 4, ///< Debug
} NsShellEvent;
/// ShellEventInfo
typedef struct {
NsShellEvent event;
u64 process_id;
NsShellEvent event; ///< \ref NsShellEvent
u64 process_id; ///< processID.
} NsShellEventInfo;
Result nsInitialize(void);
void nsExit(void);
Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t entry_offset, size_t* out_entrycount);
Result nsListApplicationContentMetaStatus(u64 titleID, u32 index, NsApplicationContentMetaStatus* buffer, size_t size, size_t* out_entrycount);
Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, size_t* actual_size);
/**
* @brief Gets an listing of \ref NsApplicationRecord.
* @param[out] records Output array of \ref NsApplicationRecord.
* @param[in] count Size of the records array in entries.
* @param[in] entry_offset Starting entry offset.
* @param[out] out_entrycount Total output entries.
*/
Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount);
/**
* @brief Gets an listing of \ref NsApplicationContentMetaStatus.
* @param[in] titleID titleID.
* @param[in] index Starting entry index.
* @param[out] list Output array of \ref NsApplicationContentMetaStatus.
* @param[in] count Size of the list array in entries.
* @param[out] out_entrycount Total output entries.
*/
Result nsListApplicationContentMetaStatus(u64 titleID, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount);
/**
* @brief Gets the \ref NsApplicationControlData for the specified title.
* @param[in] flag Flag, official sw uses value 1.
* @param[in] titleID titleID.
* @param[out] buffer \ref NsApplicationControlData
* @param[in] size Size of the buffer.
* @param[out] actual_size Actual output size.
*/
Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, u64* actual_size);
/**
* @brief Returns the total storage capacity (used + free) from content manager services.
* @param storage_id Specified FsStorageId. (Must be FsStorageId_SdCard)
* @param size Pointer to output the total storage size to.
* @param[in] storage_id Specified FsStorageId. (Must be FsStorageId_SdCard)
* @param[out] size Pointer to output the total storage size to.
*/
Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size);
/**
* @brief Returns the available storage capacity from content manager services.
* @param storage_id Specified FsStorageId. (Must be FsStorageId_SdCard)
* @param size Pointer to output the free storage size to.
* @param[in] storage_id Specified FsStorageId. (Must be FsStorageId_SdCard)
* @param[out] size Pointer to output the free storage size to.
*/
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size);
@ -90,12 +119,12 @@ void nsdevExit(void);
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags);
Result nsdevTerminateProcess(u64 pid);
Result nsdevTerminateProgram(u64 tid);
Result nsdevGetShellEvent(Event* out); ///< Autoclear for nsdevShellEvent is always true.
Result nsdevGetShellEvent(Event* out_event); ///< Autoclear for nsdevShellEvent is always true.
Result nsdevGetShellEventInfo(NsShellEventInfo* out);
Result nsdevTerminateApplication(void);
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len);
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 app_title_id, u32 flags);
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id);
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); ///< [6.0.0-8.1.0]
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid);
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active);
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid); ///< [6.0.0+]
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active); ///< [6.0.0+]

View File

@ -1,25 +1,18 @@
#include "types.h"
#include "result.h"
#include "arm/atomics.h"
#include "kernel/ipc.h"
#define NX_SERVICE_ASSUME_NON_DOMAIN
#include "service_guard.h"
#include "runtime/hosversion.h"
#include "services/sm.h"
#include "services/ns.h"
static Service g_nsAppManSrv, g_nsGetterSrv, g_nsvmSrv, g_nsdevSrv;
static u64 g_nsRefCnt, g_nsvmRefCnt, g_nsdevRefCnt;
static Result _nsGetInterface(Service* srv_out, u64 cmd_id);
static Result _nsGetInterface(Service* srv_out, u32 cmd_id);
Result nsInitialize(void)
NX_GENERATE_SERVICE_GUARD(ns);
Result _nsInitialize(void)
{
Result rc=0;
atomicIncrement64(&g_nsRefCnt);
if (serviceIsActive(&g_nsGetterSrv) || serviceIsActive(&g_nsAppManSrv))
return 0;
if(hosversionBefore(3,0,0))
return smGetService(&g_nsAppManSrv, "ns:am");
@ -33,815 +26,224 @@ Result nsInitialize(void)
return rc;
}
void nsExit(void)
void _nsCleanup(void)
{
if (atomicDecrement64(&g_nsRefCnt) == 0) {
serviceClose(&g_nsAppManSrv);
if(hosversionBefore(3,0,0)) return;
serviceClose(&g_nsAppManSrv);
if(hosversionBefore(3,0,0)) return;
serviceClose(&g_nsGetterSrv);
}
serviceClose(&g_nsGetterSrv);
}
Result nsdevInitialize(void) {
atomicIncrement64(&g_nsdevRefCnt);
if (serviceIsActive(&g_nsdevSrv))
return 0;
return smGetService(&g_nsdevSrv, "ns:dev");
static Result _nsGetInterface(Service* srv_out, u32 cmd_id) {
return serviceDispatch(&g_nsGetterSrv, cmd_id,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
void nsdevExit(void) {
if (atomicDecrement64(&g_nsdevRefCnt) == 0)
serviceClose(&g_nsdevSrv);
}
static Result _appletGetEvent(Service* srv, u32 cmd_id, Event* out_event, bool autoclear) {
Handle event = INVALID_HANDLE;
Result rc = serviceDispatch(srv, cmd_id,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &event,
);
static Result _nsGetInterface(Service* srv_out, u64 cmd_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = cmd_id;
Result rc = serviceIpcDispatch(&g_nsGetterSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
serviceCreate(srv_out, r.Handles[0]);
}
}
if (R_SUCCEEDED(rc))
eventLoadRemote(out_event, event, autoclear);
return rc;
}
Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t entry_offset, size_t* out_entrycount)
{
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buffer, size, 0);
static Result _nsCmdNoIO(Service* srv, u32 cmd_id) {
return serviceDispatch(srv, cmd_id);
}
struct {
u64 magic;
u64 cmd_id;
u32 entry_offset;
} *raw;
static Result _nsCmdInBool(Service* srv, u32 cmd_id, bool inval) {
u8 in = inval!=0;
raw = ipcPrepareHeader(&c, sizeof(*raw));
return serviceDispatchIn(srv, cmd_id, in);
}
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->entry_offset = entry_offset;
static Result _nsCmdInU64(Service* srv, u32 cmd_id, u64 inval) {
return serviceDispatchIn(srv, cmd_id, inval);
}
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 entry_count;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out_entrycount) *out_entrycount = resp->entry_count;
}
static Result _nsCmdInU64OutU64(Service* srv, u32 cmd_id, u64 inval, u64 *out) {
return serviceDispatchInOut(srv, cmd_id, inval, *out);
}
static Result _nsCmdNoInOutBool(Service* srv, u32 cmd_id, bool *out) {
u8 tmpout=0;
Result rc = serviceDispatchOut(srv, cmd_id, tmpout);
if (R_SUCCEEDED(rc) && out) *out = tmpout!=0;
return rc;
}
Result nsListApplicationContentMetaStatus(u64 titleID, u32 index, NsApplicationContentMetaStatus* buffer, size_t size, size_t* out_entrycount)
{
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buffer, size, 0);
static Result _nsCmdNoInOutU64(Service* srv, u32 cmd_id, u64 *out) {
return serviceDispatchOut(srv, cmd_id, *out);
}
struct {
u64 magic;
u64 cmd_id;
u32 index;
Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount) {
return serviceDispatchInOut(&g_nsAppManSrv, 0, entry_offset, *out_entrycount,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { records, count*sizeof(NsApplicationRecord) } },
);
}
Result nsListApplicationContentMetaStatus(u64 titleID, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount) {
const struct {
s32 index;
u64 titleID;
} *raw;
} in = { index, titleID };
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 601;
raw->index = index;
raw->titleID = titleID;
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 entry_count;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out_entrycount) *out_entrycount = resp->entry_count;
}
return rc;
return serviceDispatchInOut(&g_nsAppManSrv, 601, in, *out_entrycount,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { list, count*sizeof(NsApplicationContentMetaStatus) } },
);
}
Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, size_t* actual_size) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buffer, size, 0);
struct {
u64 magic;
u64 cmd_id;
Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, u64* actual_size) {
const struct {
u8 flag;
u64 titleID;
} *raw;
} in = { flag, titleID };
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 400;
raw->flag = flag;
raw->titleID = titleID;
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u64 actual_size;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && actual_size) *actual_size = resp->actual_size;
}
return rc;
return serviceDispatchInOut(&g_nsAppManSrv, 400, in, *actual_size,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { buffer, size } },
);
}
Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size)
{
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 storage_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 47;
raw->storage_id = storage_id;
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u64 size;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && size) *size = resp->size;
}
return rc;
Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size) {
return _nsCmdInU64OutU64(&g_nsAppManSrv, 47, storage_id, size);
}
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size)
{
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 storage_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 48;
raw->storage_id = storage_id;
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u64 size;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && size) *size = resp->size;
}
return rc;
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size) {
return _nsCmdInU64OutU64(&g_nsAppManSrv, 48, storage_id, size);
}
Result nsvmInitialize(void)
NX_GENERATE_SERVICE_GUARD(nsvm);
Result _nsvmInitialize(void)
{
if (hosversionBefore(3,0,0))
return 0;
atomicIncrement64(&g_nsvmRefCnt);
if (serviceIsActive(&g_nsvmSrv))
return 0;
return smGetService(&g_nsvmSrv, "ns:vm");
}
void nsvmExit(void)
void _nsvmCleanup(void)
{
if (hosversionBefore(3,0,0))
return;
if (atomicDecrement64(&g_nsvmRefCnt) == 0) {
serviceClose(&g_nsvmSrv);
}
serviceClose(&g_nsvmSrv);
}
Result nsvmNeedsUpdateVulnerability(bool *out) {
IpcCommand c;
ipcInitialize(&c);
Service *srv = &g_nsAppManSrv;
if (hosversionAtLeast(3,0,0)) srv = &g_nsvmSrv;
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1200;
Result rc;
if (hosversionAtLeast(3,0,0))
rc = serviceIpcDispatch(&g_nsvmSrv);
else
rc = serviceIpcDispatch(&g_nsAppManSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u8 out;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->out;
}
return rc;
return _nsCmdNoInOutBool(srv, 1200, out);
}
Result nsvmGetSafeSystemVersion(u16 *out)
{
Result nsvmGetSafeSystemVersion(u16 *out) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
return serviceDispatchOut(&g_nsvmSrv, 1202, out);
}
struct {
u64 magic;
u64 cmd_id;
} *raw;
NX_GENERATE_SERVICE_GUARD(nsdev);
raw = ipcPrepareHeader(&c, sizeof(*raw));
Result _nsdevInitialize(void) {
return smGetService(&g_nsdevSrv, "ns:dev");
}
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1202;
Result rc = serviceIpcDispatch(&g_nsvmSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u16 out;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->out;
}
return rc;
void _nsdevCleanup(void) {
serviceClose(&g_nsdevSrv);
}
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
const struct {
u32 flags;
u32 pad;
NsLaunchProperties properties;
} *raw;
} in = { flags, *properties};
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->flags = flags;
raw->pad = 0;
raw->properties = *properties;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 pid;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out_pid) *out_pid = resp->pid;
}
}
return rc;
return serviceDispatchInOut(&g_nsdevSrv, 0, in, *out_pid);
}
Result nsdevTerminateProcess(u64 pid) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 pid;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->pid = pid;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
return _nsCmdInU64(&g_nsdevSrv, 1, pid);
}
Result nsdevTerminateProgram(u64 tid) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 tid;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
raw->tid = tid;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
return _nsCmdInU64(&g_nsdevSrv, 2, tid);
}
Result nsdevGetShellEvent(Event* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 4;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
eventLoadRemote(out, r.Handles[0], true);
}
}
return rc;
Result nsdevGetShellEvent(Event* out_event) {
return _appletGetEvent(&g_nsdevSrv, 4, out_event, true);
}
Result nsdevGetShellEventInfo(NsShellEventInfo* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
u32 event;
u64 process_id;
} tmpout;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u32 event;
u32 pad;
u64 process_id;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out) {
out->event = (NsShellEvent)resp->event;
out->process_id = resp->process_id;
}
}
Result rc = serviceDispatchOut(&g_nsdevSrv, 5, tmpout);
if (R_SUCCEEDED(rc) && out) {
out->event = (NsShellEvent)tmpout.event;
out->process_id = tmpout.process_id;
}
return rc;
}
Result nsdevTerminateApplication(void) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 6;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
return _nsCmdNoIO(&g_nsdevSrv, 6);
}
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, path, path_len, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 7;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
NsLaunchProperties properties;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out) *out = resp->properties;
}
}
return rc;
return serviceDispatchOut(&g_nsdevSrv, 7, out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { path, path_len } },
);
}
Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 app_title_id, u32 flags) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
const struct {
u32 flags;
u32 pad;
u64 app_title_id;
} *raw;
} in = { .flags = flags, .app_title_id = app_title_id};
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
raw->flags = flags;
raw->pad = 0;
raw->app_title_id = app_title_id;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 pid;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out_pid) *out_pid = resp->pid;
}
}
return rc;
return serviceDispatchInOut(&g_nsdevSrv, 8, in, *out_pid);
}
Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
const struct {
u8 app_storage_id;
u8 patch_storage_id;
u16 pad;
u32 flags;
u64 app_title_id;
} *raw;
} in = { .app_storage_id = app_storage_id, .patch_storage_id = patch_storage_id, .flags = flags, .app_title_id = app_title_id};
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 9;
raw->app_storage_id = app_storage_id;
raw->patch_storage_id = patch_storage_id;
raw->pad = 0;
raw->flags = flags;
raw->app_title_id = app_title_id;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 pid;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out_pid) *out_pid = resp->pid;
}
}
return rc;
return serviceDispatchInOut(&g_nsdevSrv, 9, in, *out_pid);
}
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out) {
if (hosversionBefore(6,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 10;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u8 boosted;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out) *out = resp->boosted != 0;
}
}
return rc;
return _nsCmdNoInOutBool(&g_nsdevSrv, 10, out);
}
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid) {
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 11;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
u64 pid;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (out_pid) *out_pid = resp->pid;
}
}
return rc;
return _nsCmdNoInOutU64(&g_nsdevSrv, 11, out_pid);
}
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active) {
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u8 can_be_active;
} *raw;
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 12;
raw->can_be_active = can_be_active ? 1 : 0;
Result rc = serviceIpcDispatch(&g_nsdevSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
struct {
u64 magic;
u64 result;
} *resp;
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
}
return rc;
return _nsCmdInBool(&g_nsdevSrv, 12, can_be_active);
}