mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 13:02:38 +02:00
ns: Implement all of ns:dev
This commit is contained in:
parent
bfad4d4557
commit
0a92b0eb07
@ -8,6 +8,7 @@
|
|||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
#include "../nacp.h"
|
#include "../nacp.h"
|
||||||
#include "../services/fs.h"
|
#include "../services/fs.h"
|
||||||
|
#include "../kernel/event.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
NacpStruct nacp;
|
NacpStruct nacp;
|
||||||
@ -34,6 +35,37 @@ typedef struct
|
|||||||
u8 unk_x11[7];
|
u8 unk_x11[7];
|
||||||
} NsApplicationRecord;
|
} NsApplicationRecord;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 titleID;
|
||||||
|
u32 version;
|
||||||
|
u8 storageID;
|
||||||
|
u8 index;
|
||||||
|
u8 is_application;
|
||||||
|
u8 padding[1];
|
||||||
|
} NsLaunchProperties;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NsLaunchFlag_SignalOnExit = (1 << 0),
|
||||||
|
NsLaunchFlag_SignalOnStart = (1 << 1),
|
||||||
|
NsLaunchFlag_SignalOnCrash = (1 << 2),
|
||||||
|
NsLaunchFlag_SignalOnDebug = (1 << 3),
|
||||||
|
NsLaunchFlag_StartSuspended = (1 << 4),
|
||||||
|
NsLaunchFlag_DisableAslr = (1 << 5),
|
||||||
|
} NsLaunchFlag;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NsShellEvent_None = 0,
|
||||||
|
NsShellEvent_Exit = 1,
|
||||||
|
NsShellEvent_Start = 2,
|
||||||
|
NsShellEvent_Crash = 3,
|
||||||
|
NsShellEvent_Debug = 4,
|
||||||
|
} NsShellEvent;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NsShellEvent event : 32;
|
||||||
|
u64 process_id;
|
||||||
|
} NsShellEventInfo;
|
||||||
|
|
||||||
Result nsInitialize(void);
|
Result nsInitialize(void);
|
||||||
void nsExit(void);
|
void nsExit(void);
|
||||||
|
|
||||||
@ -65,5 +97,15 @@ Result nsvmGetSafeSystemVersion(u16 *out);
|
|||||||
Result nsdevInitialize(void);
|
Result nsdevInitialize(void);
|
||||||
void nsdevExit(void);
|
void nsdevExit(void);
|
||||||
|
|
||||||
|
Result nsdevLaunchProgram(u64* out_pid, NsLaunchProperties* properties, u32 flags);
|
||||||
Result nsdevTerminateProcess(u64 pid);
|
Result nsdevTerminateProcess(u64 pid);
|
||||||
Result nsdevTerminateProgram(u64 tid);
|
Result nsdevTerminateProgram(u64 tid);
|
||||||
|
Result nsdevGetShellEvent(Event* out);
|
||||||
|
Result nsdevGetShellEventInfo(NsShellEventInfo* out);
|
||||||
|
Result nsdevTerminateApplication(void);
|
||||||
|
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len);
|
||||||
|
Result nsdevLaunchApplication(u64* out_pid, u64 app_title_id, u32 flags);
|
||||||
|
Result nsdevLaunchApplicationWithStorageId(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id);
|
||||||
|
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out);
|
||||||
|
Result nsdevGetRunningApplicationProcessId(u64* out_pid);
|
||||||
|
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active);
|
@ -383,6 +383,49 @@ Result nsvmGetSafeSystemVersion(u16 *out)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result nsdevLaunchProgram(u64* out_pid, NsLaunchProperties* properties, u32 flags) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 flags;
|
||||||
|
u32 pad;
|
||||||
|
NsLaunchProperties properties;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
Result nsdevTerminateProcess(u64 pid) {
|
Result nsdevTerminateProcess(u64 pid) {
|
||||||
IpcCommand c;
|
IpcCommand c;
|
||||||
ipcInitialize(&c);
|
ipcInitialize(&c);
|
||||||
@ -393,7 +436,7 @@ Result nsdevTerminateProcess(u64 pid) {
|
|||||||
u64 pid;
|
u64 pid;
|
||||||
} *raw;
|
} *raw;
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
raw->magic = SFCI_MAGIC;
|
||||||
raw->cmd_id = 1;
|
raw->cmd_id = 1;
|
||||||
@ -403,12 +446,13 @@ Result nsdevTerminateProcess(u64 pid) {
|
|||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
IpcParsedCommand r;
|
IpcParsedCommand r;
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u64 magic;
|
||||||
u64 result;
|
u64 result;
|
||||||
} *resp = r.Raw;
|
} *resp;
|
||||||
|
|
||||||
|
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
|
||||||
|
resp = r.Raw;
|
||||||
|
|
||||||
rc = resp->result;
|
rc = resp->result;
|
||||||
}
|
}
|
||||||
@ -426,7 +470,7 @@ Result nsdevTerminateProgram(u64 tid) {
|
|||||||
u64 tid;
|
u64 tid;
|
||||||
} *raw;
|
} *raw;
|
||||||
|
|
||||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
|
||||||
|
|
||||||
raw->magic = SFCI_MAGIC;
|
raw->magic = SFCI_MAGIC;
|
||||||
raw->cmd_id = 2;
|
raw->cmd_id = 2;
|
||||||
@ -436,12 +480,365 @@ Result nsdevTerminateProgram(u64 tid) {
|
|||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
IpcParsedCommand r;
|
IpcParsedCommand r;
|
||||||
ipcParse(&r);
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u64 magic;
|
u64 magic;
|
||||||
u64 result;
|
u64 result;
|
||||||
} *resp = r.Raw;
|
} *resp;
|
||||||
|
|
||||||
|
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
|
||||||
|
resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nsdevGetShellEventInfo(NsShellEventInfo* 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 = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nsdevLaunchApplication(u64* out_pid, u64 app_title_id, u32 flags) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 flags;
|
||||||
|
u32 pad;
|
||||||
|
u64 app_title_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nsdevLaunchApplicationWithStorageId(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;
|
||||||
|
u8 app_storage_id;
|
||||||
|
u8 patch_storage_id;
|
||||||
|
u16 pad;
|
||||||
|
u32 flags;
|
||||||
|
u64 app_title_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out) {
|
||||||
|
if (!kernelAbove600()) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nsdevGetRunningApplicationProcessId(u64* out_pid) {
|
||||||
|
if (!kernelAbove600()) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active) {
|
||||||
|
if (!kernelAbove600()) 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;
|
rc = resp->result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user