mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +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 "../nacp.h"
|
||||
#include "../services/fs.h"
|
||||
#include "../kernel/event.h"
|
||||
|
||||
typedef struct {
|
||||
NacpStruct nacp;
|
||||
@ -34,6 +35,37 @@ typedef struct
|
||||
u8 unk_x11[7];
|
||||
} 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);
|
||||
void nsExit(void);
|
||||
|
||||
@ -65,5 +97,15 @@ Result nsvmGetSafeSystemVersion(u16 *out);
|
||||
Result nsdevInitialize(void);
|
||||
void nsdevExit(void);
|
||||
|
||||
Result nsdevLaunchProgram(u64* out_pid, NsLaunchProperties* properties, u32 flags);
|
||||
Result nsdevTerminateProcess(u64 pid);
|
||||
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);
|
@ -45,10 +45,10 @@ void nsExit(void)
|
||||
|
||||
Result nsdevInitialize(void) {
|
||||
atomicIncrement64(&g_nsdevRefCnt);
|
||||
|
||||
|
||||
if (serviceIsActive(&g_nsdevSrv))
|
||||
return 0;
|
||||
|
||||
|
||||
return smGetService(&g_nsdevSrv, "ns:dev");
|
||||
}
|
||||
|
||||
@ -97,21 +97,21 @@ Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddRecvBuffer(&c, buffer, size, 0);
|
||||
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 entry_offset;
|
||||
} *raw;
|
||||
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 0;
|
||||
raw->entry_offset = entry_offset;
|
||||
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_nsAppManSrv);
|
||||
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
@ -123,7 +123,7 @@ Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
|
||||
if (R_SUCCEEDED(rc) && out_entrycount) *out_entrycount = resp->entry_count;
|
||||
}
|
||||
|
||||
@ -135,23 +135,23 @@ Result nsListApplicationContentMetaStatus(u64 titleID, u32 index, NsApplicationC
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
ipcAddRecvBuffer(&c, buffer, size, 0);
|
||||
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 index;
|
||||
u64 titleID;
|
||||
} *raw;
|
||||
|
||||
|
||||
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);
|
||||
@ -321,7 +321,7 @@ Result nsvmNeedsUpdateVulnerability(bool *out) {
|
||||
raw->cmd_id = 1200;
|
||||
|
||||
Result rc;
|
||||
|
||||
|
||||
if (kernelAbove300())
|
||||
rc = serviceIpcDispatch(&g_nsvmSrv);
|
||||
else
|
||||
@ -383,6 +383,49 @@ Result nsvmGetSafeSystemVersion(u16 *out)
|
||||
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) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
@ -393,7 +436,7 @@ Result nsdevTerminateProcess(u64 pid) {
|
||||
u64 pid;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 1;
|
||||
@ -403,12 +446,13 @@ Result nsdevTerminateProcess(u64 pid) {
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp = r.Raw;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
@ -426,7 +470,7 @@ Result nsdevTerminateProgram(u64 tid) {
|
||||
u64 tid;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 2;
|
||||
@ -436,15 +480,368 @@ Result nsdevTerminateProgram(u64 tid) {
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
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;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
Loading…
Reference in New Issue
Block a user