mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
250 lines
7.1 KiB
C
250 lines
7.1 KiB
C
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
|
#include "service_guard.h"
|
|
#include "runtime/hosversion.h"
|
|
#include "services/ns.h"
|
|
|
|
static Service g_nsAppManSrv, g_nsGetterSrv, g_nsvmSrv, g_nsdevSrv;
|
|
|
|
static Result _nsGetInterface(Service* srv_out, u32 cmd_id);
|
|
|
|
NX_GENERATE_SERVICE_GUARD(ns);
|
|
|
|
Result _nsInitialize(void)
|
|
{
|
|
Result rc=0;
|
|
|
|
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 = _nsGetInterface(&g_nsAppManSrv, 7996);
|
|
|
|
if (R_FAILED(rc)) serviceClose(&g_nsGetterSrv);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void _nsCleanup(void)
|
|
{
|
|
serviceClose(&g_nsAppManSrv);
|
|
if(hosversionBefore(3,0,0)) return;
|
|
|
|
serviceClose(&g_nsGetterSrv);
|
|
}
|
|
|
|
static Result _nsGetInterface(Service* srv_out, u32 cmd_id) {
|
|
return serviceDispatch(&g_nsGetterSrv, cmd_id,
|
|
.out_num_objects = 1,
|
|
.out_objects = srv_out,
|
|
);
|
|
}
|
|
|
|
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,
|
|
);
|
|
|
|
if (R_SUCCEEDED(rc))
|
|
eventLoadRemote(out_event, event, autoclear);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static Result _nsCmdNoIO(Service* srv, u32 cmd_id) {
|
|
return serviceDispatch(srv, cmd_id);
|
|
}
|
|
|
|
static Result _nsCmdInBool(Service* srv, u32 cmd_id, bool inval) {
|
|
u8 in = inval!=0;
|
|
|
|
return serviceDispatchIn(srv, cmd_id, in);
|
|
}
|
|
|
|
static Result _nsCmdInU64(Service* srv, u32 cmd_id, u64 inval) {
|
|
return serviceDispatchIn(srv, cmd_id, inval);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
static Result _nsCmdNoInOutU64(Service* srv, u32 cmd_id, u64 *out) {
|
|
return serviceDispatchOut(srv, cmd_id, *out);
|
|
}
|
|
|
|
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;
|
|
} in = { index, titleID };
|
|
|
|
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, u64* actual_size) {
|
|
const struct {
|
|
u8 flag;
|
|
u64 titleID;
|
|
} in = { flag, titleID };
|
|
|
|
return serviceDispatchInOut(&g_nsAppManSrv, 400, in, *actual_size,
|
|
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
|
.buffers = { { buffer, size } },
|
|
);
|
|
}
|
|
|
|
Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size) {
|
|
return _nsCmdInU64OutU64(&g_nsAppManSrv, 47, storage_id, size);
|
|
}
|
|
|
|
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size) {
|
|
return _nsCmdInU64OutU64(&g_nsAppManSrv, 48, storage_id, size);
|
|
}
|
|
|
|
NX_GENERATE_SERVICE_GUARD(nsvm);
|
|
|
|
Result _nsvmInitialize(void)
|
|
{
|
|
if (hosversionBefore(3,0,0))
|
|
return 0;
|
|
|
|
return smGetService(&g_nsvmSrv, "ns:vm");
|
|
}
|
|
|
|
void _nsvmCleanup(void)
|
|
{
|
|
if (hosversionBefore(3,0,0))
|
|
return;
|
|
|
|
serviceClose(&g_nsvmSrv);
|
|
}
|
|
|
|
Result nsvmNeedsUpdateVulnerability(bool *out) {
|
|
Service *srv = &g_nsAppManSrv;
|
|
if (hosversionAtLeast(3,0,0)) srv = &g_nsvmSrv;
|
|
|
|
return _nsCmdNoInOutBool(srv, 1200, out);
|
|
}
|
|
|
|
Result nsvmGetSafeSystemVersion(u16 *out) {
|
|
if (hosversionBefore(3,0,0))
|
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return serviceDispatchOut(&g_nsvmSrv, 1202, out);
|
|
}
|
|
|
|
NX_GENERATE_SERVICE_GUARD(nsdev);
|
|
|
|
Result _nsdevInitialize(void) {
|
|
return smGetService(&g_nsdevSrv, "ns:dev");
|
|
}
|
|
|
|
void _nsdevCleanup(void) {
|
|
serviceClose(&g_nsdevSrv);
|
|
}
|
|
|
|
Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) {
|
|
const struct {
|
|
u32 flags;
|
|
NsLaunchProperties properties;
|
|
} in = { flags, *properties};
|
|
|
|
return serviceDispatchInOut(&g_nsdevSrv, 0, in, *out_pid);
|
|
}
|
|
|
|
Result nsdevTerminateProcess(u64 pid) {
|
|
return _nsCmdInU64(&g_nsdevSrv, 1, pid);
|
|
}
|
|
|
|
Result nsdevTerminateProgram(u64 tid) {
|
|
return _nsCmdInU64(&g_nsdevSrv, 2, tid);
|
|
}
|
|
|
|
Result nsdevGetShellEvent(Event* out_event) {
|
|
return _appletGetEvent(&g_nsdevSrv, 4, out_event, true);
|
|
}
|
|
|
|
Result nsdevGetShellEventInfo(NsShellEventInfo* out) {
|
|
struct {
|
|
u32 event;
|
|
u64 process_id;
|
|
} tmpout;
|
|
|
|
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) {
|
|
return _nsCmdNoIO(&g_nsdevSrv, 6);
|
|
}
|
|
|
|
Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len) {
|
|
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) {
|
|
const struct {
|
|
u32 flags;
|
|
u64 app_title_id;
|
|
} in = { .flags = flags, .app_title_id = app_title_id};
|
|
|
|
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) {
|
|
const struct {
|
|
u8 app_storage_id;
|
|
u8 patch_storage_id;
|
|
u32 flags;
|
|
u64 app_title_id;
|
|
} in = { .app_storage_id = app_storage_id, .patch_storage_id = patch_storage_id, .flags = flags, .app_title_id = app_title_id};
|
|
|
|
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);
|
|
|
|
return _nsCmdNoInOutBool(&g_nsdevSrv, 10, out);
|
|
}
|
|
|
|
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid) {
|
|
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return _nsCmdNoInOutU64(&g_nsdevSrv, 11, out_pid);
|
|
}
|
|
|
|
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active) {
|
|
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
|
|
|
return _nsCmdInBool(&g_nsdevSrv, 12, can_be_active);
|
|
}
|