mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
ro: update for new sf semantics
This commit is contained in:
parent
bc9da91362
commit
fb6a4e28a5
23 changed files with 192 additions and 119 deletions
|
@ -19,11 +19,11 @@
|
||||||
#include <stratosphere/ldr/ldr_types.hpp>
|
#include <stratosphere/ldr/ldr_types.hpp>
|
||||||
#include <stratosphere/sf.hpp>
|
#include <stratosphere/sf.hpp>
|
||||||
|
|
||||||
#define AMS_LDR_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \
|
#define AMS_LDR_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentsDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \
|
AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentsDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArguments, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \
|
AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArguments, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 1, Result, FlushArguments, (), ()) \
|
AMS_SF_METHOD_INFO(C, H, 1, Result, FlushArguments, (), ()) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 2, Result, GetProcessModuleInfo, (sf::Out<u32> count, const sf::OutPointerArray<ldr::ModuleInfo> &out, os::ProcessId process_id), (count, out, process_id)) \
|
AMS_SF_METHOD_INFO(C, H, 2, Result, GetProcessModuleInfo, (sf::Out<u32> count, const sf::OutPointerArray<ldr::ModuleInfo> &out, os::ProcessId process_id), (count, out, process_id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereHasLaunchedProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id))
|
AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereHasLaunchedBootProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::ldr::impl, IDebugMonitorInterface, AMS_LDR_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::ldr::impl, IDebugMonitorInterface, AMS_LDR_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO)
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
#include <stratosphere/ldr/ldr_types.hpp>
|
#include <stratosphere/ldr/ldr_types.hpp>
|
||||||
#include <stratosphere/sf.hpp>
|
#include <stratosphere/sf.hpp>
|
||||||
|
|
||||||
#define AMS_LDR_I_PROCESS_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
|
#define AMS_LDR_I_PROCESS_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 0, Result, CreateProcess, (sf::OutMoveHandle proc_h, ldr::PinId id, u32 flags, sf::CopyHandle reslimit_h), (proc_h, id, flags, reslimit_h)) \
|
AMS_SF_METHOD_INFO(C, H, 0, Result, CreateProcess, (sf::OutMoveHandle proc_h, ldr::PinId id, u32 flags, sf::CopyHandle reslimit_h), (proc_h, id, flags, reslimit_h)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 1, Result, GetProgramInfo, (sf::Out<ldr::ProgramInfo> out_program_info, const ncm::ProgramLocation &loc), (out_program_info, loc)) \
|
AMS_SF_METHOD_INFO(C, H, 1, Result, GetProgramInfo, (sf::Out<ldr::ProgramInfo> out_program_info, const ncm::ProgramLocation &loc), (out_program_info, loc)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 2, Result, PinProgram, (sf::Out<ldr::PinId> out_id, const ncm::ProgramLocation &loc), (out_id, loc)) \
|
AMS_SF_METHOD_INFO(C, H, 2, Result, PinProgram, (sf::Out<ldr::PinId> out_id, const ncm::ProgramLocation &loc), (out_id, loc)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 3, Result, UnpinProgram, (ldr::PinId id), (id)) \
|
AMS_SF_METHOD_INFO(C, H, 3, Result, UnpinProgram, (ldr::PinId id), (id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 4, Result, SetEnabledProgramVerification, (bool enabled), (enabled), hos::Version_10_0_0) \
|
AMS_SF_METHOD_INFO(C, H, 4, Result, SetEnabledProgramVerification, (bool enabled), (enabled), hos::Version_10_0_0) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereHasLaunchedProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
|
AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereHasLaunchedBootProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereGetProgramInfo, (sf::Out<ldr::ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc), (out_program_info, out_status, loc)) \
|
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereGetProgramInfo, (sf::Out<ldr::ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc), (out_program_info, out_status, loc)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmospherePinProgram, (sf::Out<ldr::PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status), (out_id, loc, override_status))
|
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmospherePinProgram, (sf::Out<ldr::PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status), (out_id, loc, override_status))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::ldr::impl, IProcessManagerInterface, AMS_LDR_I_PROCESS_MANAGER_INTERFACE_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::ldr::impl, IProcessManagerInterface, AMS_LDR_I_PROCESS_MANAGER_INTERFACE_INTERFACE_INFO)
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace ams::ldr::pm {
|
||||||
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc);
|
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc);
|
||||||
Result UnpinProgram(PinId pin_id);
|
Result UnpinProgram(PinId pin_id);
|
||||||
Result SetEnabledProgramVerification(bool enabled);
|
Result SetEnabledProgramVerification(bool enabled);
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id);
|
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id);
|
||||||
|
|
||||||
/* Atmosphere extension API. */
|
/* Atmosphere extension API. */
|
||||||
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc);
|
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc);
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include <stratosphere/pm/pm_types.hpp>
|
#include <stratosphere/pm/pm_types.hpp>
|
||||||
#include <stratosphere/sf.hpp>
|
#include <stratosphere/sf.hpp>
|
||||||
|
|
||||||
#define AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO(C, H) \
|
#define AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO(C, H) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
|
AMS_SF_METHOD_INFO(C, H, 0, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, os::ProcessId process_id), (out, process_id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessId, (sf::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id)) \
|
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetProcessId, (sf::Out<os::ProcessId> out, ncm::ProgramId program_id), (out, program_id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereHasLaunchedProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
|
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereHasLaunchedBootProgram, (sf::Out<bool> out, ncm::ProgramId program_id), (out, program_id)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmosphereGetProcessInfo, (sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_loc, out_status, process_id))
|
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmosphereGetProcessInfo, (sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id), (out_loc, out_status, process_id))
|
||||||
|
|
||||||
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IInformationInterface, AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO)
|
AMS_SF_DEFINE_INTERFACE(ams::pm::impl, IInformationInterface, AMS_PM_I_INFORMATION_INTERFACE_INTERFACE_INFO)
|
||||||
|
|
|
@ -27,12 +27,12 @@ namespace ams::pm::info {
|
||||||
/* Information API. */
|
/* Information API. */
|
||||||
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id);
|
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id);
|
||||||
Result GetProcessId(os::ProcessId *out_process_id, ncm::ProgramId program_id);
|
Result GetProcessId(os::ProcessId *out_process_id, ncm::ProgramId program_id);
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id);
|
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id);
|
||||||
|
|
||||||
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
||||||
|
|
||||||
/* Information convenience API. */
|
/* Information convenience API. */
|
||||||
bool HasLaunchedProgram(ncm::ProgramId program_id);
|
bool HasLaunchedBootProgram(ncm::ProgramId program_id);
|
||||||
|
|
||||||
Result IsHblProcessId(bool *out, os::ProcessId process_id);
|
Result IsHblProcessId(bool *out, os::ProcessId process_id);
|
||||||
Result IsHblProgramId(bool *out, ncm::ProgramId program_id);
|
Result IsHblProgramId(bool *out, ncm::ProgramId program_id);
|
||||||
|
|
|
@ -294,7 +294,7 @@ namespace ams::boot2 {
|
||||||
void LaunchFlaggedProgramsOnSdCard() {
|
void LaunchFlaggedProgramsOnSdCard() {
|
||||||
IterateOverFlaggedProgramsOnSdCard([](ncm::ProgramId program_id) {
|
IterateOverFlaggedProgramsOnSdCard([](ncm::ProgramId program_id) {
|
||||||
/* Check if we've already launched the program. */
|
/* Check if we've already launched the program. */
|
||||||
if (pm::info::HasLaunchedProgram(program_id)) {
|
if (pm::info::HasLaunchedBootProgram(program_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -388,7 +388,7 @@ namespace ams::cfg {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For system modules and anything launched before the home menu, always override. */
|
/* For system modules and anything launched before the home menu, always override. */
|
||||||
if (program_id < ncm::SystemAppletId::Start || !pm::info::HasLaunchedProgram(ncm::SystemAppletId::Qlaunch)) {
|
if (program_id < ncm::SystemAppletId::Start || !pm::info::HasLaunchedBootProgram(ncm::SystemAppletId::Qlaunch)) {
|
||||||
status.SetProgramSpecific();
|
status.SetProgramSpecific();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace ams::hid {
|
||||||
Result EnsureHidInitialized() {
|
Result EnsureHidInitialized() {
|
||||||
if (!g_initialized_hid) {
|
if (!g_initialized_hid) {
|
||||||
if (!serviceIsActive(hidGetServiceSession())) {
|
if (!serviceIsActive(hidGetServiceSession())) {
|
||||||
if (!pm::info::HasLaunchedProgram(ncm::SystemProgramId::Hid)) {
|
if (!pm::info::HasLaunchedBootProgram(ncm::SystemProgramId::Hid)) {
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID);
|
return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID);
|
||||||
}
|
}
|
||||||
InitializeHid();
|
InitializeHid();
|
||||||
|
|
|
@ -17,19 +17,19 @@
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include "ldr_ams.h"
|
#include "ldr_ams.h"
|
||||||
|
|
||||||
static Result _ldrAtmosphereHasLaunchedProgram(Service *srv, bool *out, u64 program_id) {
|
static Result _ldrAtmosphereHasLaunchedBootProgram(Service *srv, bool *out, u64 program_id) {
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
Result rc = serviceDispatchInOut(srv, 65000, program_id, tmp);
|
Result rc = serviceDispatchInOut(srv, 65000, program_id, tmp);
|
||||||
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
|
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ldrDmntAtmosphereHasLaunchedProgram(bool *out, u64 program_id) {
|
Result ldrDmntAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id) {
|
||||||
return _ldrAtmosphereHasLaunchedProgram(ldrDmntGetServiceSession(), out, program_id);
|
return _ldrAtmosphereHasLaunchedBootProgram(ldrDmntGetServiceSession(), out, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ldrPmAtmosphereHasLaunchedProgram(bool *out, u64 program_id) {
|
Result ldrPmAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id) {
|
||||||
return _ldrAtmosphereHasLaunchedProgram(ldrPmGetServiceSession(), out, program_id);
|
return _ldrAtmosphereHasLaunchedBootProgram(ldrPmGetServiceSession(), out, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ldrPmAtmosphereGetProgramInfo(LoaderProgramInfo *out_program_info, CfgOverrideStatus *out_status, const NcmProgramLocation *loc) {
|
Result ldrPmAtmosphereGetProgramInfo(LoaderProgramInfo *out_program_info, CfgOverrideStatus *out_status, const NcmProgramLocation *loc) {
|
||||||
|
|
|
@ -16,8 +16,8 @@ typedef struct {
|
||||||
u64 flags;
|
u64 flags;
|
||||||
} CfgOverrideStatus;
|
} CfgOverrideStatus;
|
||||||
|
|
||||||
Result ldrPmAtmosphereHasLaunchedProgram(bool *out, u64 program_id);
|
Result ldrPmAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id);
|
||||||
Result ldrDmntAtmosphereHasLaunchedProgram(bool *out, u64 program_id);
|
Result ldrDmntAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id);
|
||||||
|
|
||||||
Result ldrPmAtmosphereGetProgramInfo(LoaderProgramInfo *out, CfgOverrideStatus *out_status, const NcmProgramLocation *loc);
|
Result ldrPmAtmosphereGetProgramInfo(LoaderProgramInfo *out, CfgOverrideStatus *out_status, const NcmProgramLocation *loc);
|
||||||
Result ldrPmAtmospherePinProgram(u64 *out, const NcmProgramLocation *loc, const CfgOverrideStatus *status);
|
Result ldrPmAtmospherePinProgram(u64 *out, const NcmProgramLocation *loc, const CfgOverrideStatus *status);
|
||||||
|
|
|
@ -36,8 +36,8 @@ namespace ams::ldr::pm {
|
||||||
return ldrPmUnpinProgram(pin_id.value);
|
return ldrPmUnpinProgram(pin_id.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
|
||||||
return ldrPmAtmosphereHasLaunchedProgram(out, static_cast<u64>(program_id));
|
return ldrPmAtmosphereHasLaunchedBootProgram(out, static_cast<u64>(program_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
|
Result AtmosphereGetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 program_id) {
|
||||||
return serviceDispatchInOut(pminfoGetServiceSession(), 65000, program_id, *out_pid);
|
return serviceDispatchInOut(pminfoGetServiceSession(), 65000, program_id, *out_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result pminfoAtmosphereHasLaunchedProgram(bool *out, u64 program_id) {
|
Result pminfoAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id) {
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
Result rc = serviceDispatchInOut(pminfoGetServiceSession(), 65001, program_id, tmp);
|
Result rc = serviceDispatchInOut(pminfoGetServiceSession(), 65001, program_id, tmp);
|
||||||
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
|
if (R_SUCCEEDED(rc) && out) *out = tmp & 1;
|
||||||
|
|
|
@ -17,7 +17,7 @@ typedef struct {
|
||||||
} CfgOverrideStatus;
|
} CfgOverrideStatus;
|
||||||
|
|
||||||
Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 program_id);
|
Result pminfoAtmosphereGetProcessId(u64 *out_pid, u64 program_id);
|
||||||
Result pminfoAtmosphereHasLaunchedProgram(bool *out, u64 program_id);
|
Result pminfoAtmosphereHasLaunchedBootProgram(bool *out, u64 program_id);
|
||||||
Result pminfoAtmosphereGetProcessInfo(NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
|
Result pminfoAtmosphereGetProcessInfo(NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
|
||||||
|
|
||||||
Result pmdmntAtmosphereGetProcessInfo(Handle *out, NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
|
Result pmdmntAtmosphereGetProcessInfo(Handle *out, NcmProgramLocation *loc_out, CfgOverrideStatus *status_out, u64 pid);
|
||||||
|
|
|
@ -18,58 +18,32 @@
|
||||||
|
|
||||||
namespace ams::pm::info {
|
namespace ams::pm::info {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/* Global lock. */
|
|
||||||
os::Mutex g_info_lock(false);
|
|
||||||
/* TODO: Less memory-intensive storage? */
|
|
||||||
std::set<u64> g_cached_launched_programs;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Information API. */
|
/* Information API. */
|
||||||
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id) {
|
Result GetProgramId(ncm::ProgramId *out_program_id, os::ProcessId process_id) {
|
||||||
std::scoped_lock lk(g_info_lock);
|
|
||||||
|
|
||||||
return pminfoGetProgramId(reinterpret_cast<u64 *>(out_program_id), static_cast<u64>(process_id));
|
return pminfoGetProgramId(reinterpret_cast<u64 *>(out_program_id), static_cast<u64>(process_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessId(os::ProcessId *out_process_id, ncm::ProgramId program_id) {
|
Result GetProcessId(os::ProcessId *out_process_id, ncm::ProgramId program_id) {
|
||||||
std::scoped_lock lk(g_info_lock);
|
|
||||||
|
|
||||||
return pminfoAtmosphereGetProcessId(reinterpret_cast<u64 *>(out_process_id), static_cast<u64>(program_id));
|
return pminfoAtmosphereGetProcessId(reinterpret_cast<u64 *>(out_process_id), static_cast<u64>(program_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
Result GetProcessInfo(ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
||||||
std::scoped_lock lk(g_info_lock);
|
|
||||||
|
|
||||||
*out_loc = {};
|
*out_loc = {};
|
||||||
*out_status = {};
|
*out_status = {};
|
||||||
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus));
|
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus));
|
||||||
return pminfoAtmosphereGetProcessInfo(reinterpret_cast<NcmProgramLocation *>(out_loc), reinterpret_cast<CfgOverrideStatus *>(out_status), static_cast<u64>(process_id));
|
return pminfoAtmosphereGetProcessInfo(reinterpret_cast<NcmProgramLocation *>(out_loc), reinterpret_cast<CfgOverrideStatus *>(out_status), static_cast<u64>(process_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WEAK_SYMBOL HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
Result WEAK_SYMBOL HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
|
||||||
std::scoped_lock lk(g_info_lock);
|
|
||||||
|
|
||||||
if (g_cached_launched_programs.find(static_cast<u64>(program_id)) != g_cached_launched_programs.end()) {
|
|
||||||
*out = true;
|
|
||||||
return ResultSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_launched = false;
|
bool has_launched = false;
|
||||||
R_TRY(pminfoAtmosphereHasLaunchedProgram(&has_launched, static_cast<u64>(program_id)));
|
R_TRY(pminfoAtmosphereHasLaunchedBootProgram(&has_launched, static_cast<u64>(program_id)));
|
||||||
if (has_launched) {
|
|
||||||
g_cached_launched_programs.insert(static_cast<u64>(program_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = has_launched;
|
*out = has_launched;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasLaunchedProgram(ncm::ProgramId program_id) {
|
bool HasLaunchedBootProgram(ncm::ProgramId program_id) {
|
||||||
bool has_launched = false;
|
bool has_launched = false;
|
||||||
R_ABORT_UNLESS(HasLaunchedProgram(&has_launched, program_id));
|
R_ABORT_UNLESS(HasLaunchedBootProgram(&has_launched, program_id));
|
||||||
return has_launched;
|
return has_launched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,18 +20,49 @@ namespace ams::ldr {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* Global cache. */
|
static constexpr size_t MaxBootPrograms = 0x50;
|
||||||
std::set<u64> g_launched_programs;
|
constinit std::array<ncm::ProgramId, MaxBootPrograms> g_launched_boot_programs = [] {
|
||||||
|
std::array<ncm::ProgramId, MaxBootPrograms> arr = {};
|
||||||
|
for (size_t i = 0; i < MaxBootPrograms; ++i) {
|
||||||
|
arr[i] = ncm::InvalidProgramId;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}();
|
||||||
|
|
||||||
|
constinit bool g_boot_programs_done = false;
|
||||||
|
|
||||||
|
bool HasLaunchedBootProgramImpl(ncm::ProgramId program_id) {
|
||||||
|
for (const auto &launched : g_launched_boot_programs) {
|
||||||
|
if (launched == program_id) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLaunchedBootProgramImpl(ncm::ProgramId program_id) {
|
||||||
|
for (size_t i = 0; i < MaxBootPrograms; ++i) {
|
||||||
|
if (g_launched_boot_programs[i] == ncm::InvalidProgramId) {
|
||||||
|
g_launched_boot_programs[i] = program_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AMS_ABORT("Too many boot programs");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Launch Record API. */
|
/* Launch Record API. */
|
||||||
bool HasLaunchedProgram(ncm::ProgramId program_id) {
|
bool HasLaunchedBootProgram(ncm::ProgramId program_id) {
|
||||||
return g_launched_programs.find(program_id.value) != g_launched_programs.end();
|
return HasLaunchedBootProgramImpl(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLaunchedProgram(ncm::ProgramId program_id) {
|
void SetLaunchedBootProgram(ncm::ProgramId program_id) {
|
||||||
g_launched_programs.insert(program_id.value);
|
if (!g_boot_programs_done) {
|
||||||
|
SetLaunchedBootProgramImpl(program_id);
|
||||||
|
if (program_id == ncm::SystemAppletId::Qlaunch) {
|
||||||
|
g_boot_programs_done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -40,8 +71,8 @@ namespace ams::ldr {
|
||||||
/* This is necessary to prevent circular dependencies. */
|
/* This is necessary to prevent circular dependencies. */
|
||||||
namespace ams::pm::info {
|
namespace ams::pm::info {
|
||||||
|
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
|
||||||
*out = ldr::HasLaunchedProgram(program_id);
|
*out = ldr::HasLaunchedBootProgram(program_id);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
namespace ams::ldr {
|
namespace ams::ldr {
|
||||||
|
|
||||||
/* Launch Record API. */
|
/* Launch Record API. */
|
||||||
bool HasLaunchedProgram(ncm::ProgramId program_id);
|
bool HasLaunchedBootProgram(ncm::ProgramId program_id);
|
||||||
void SetLaunchedProgram(ncm::ProgramId program_id);
|
void SetLaunchedBootProgram(ncm::ProgramId program_id);
|
||||||
|
|
||||||
}
|
}
|
|
@ -115,8 +115,8 @@ namespace ams::ldr {
|
||||||
fssystem::DestroyExternalCode(program_id);
|
fssystem::DestroyExternalCode(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoaderService::AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
|
void LoaderService::AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
|
||||||
out.SetValue(ldr::HasLaunchedProgram(program_id));
|
out.SetValue(ldr::HasLaunchedBootProgram(program_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoaderService::AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc) {
|
Result LoaderService::AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace ams::ldr {
|
||||||
/* Atmosphere commands. */
|
/* Atmosphere commands. */
|
||||||
Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id);
|
Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id);
|
||||||
void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id);
|
void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id);
|
||||||
void AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
|
void AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id);
|
||||||
Result AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc);
|
Result AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc);
|
||||||
Result AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
|
Result AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,8 +22,8 @@ namespace ams::pm {
|
||||||
/* Overrides for libstratosphere pm::info commands. */
|
/* Overrides for libstratosphere pm::info commands. */
|
||||||
namespace info {
|
namespace info {
|
||||||
|
|
||||||
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
|
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
|
||||||
return ldr::pm::HasLaunchedProgram(out, program_id);
|
return ldr::pm::HasLaunchedBootProgram(out, program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,8 @@ namespace ams::pm {
|
||||||
return impl::GetProcessId(out.GetPointer(), program_id);
|
return impl::GetProcessId(out.GetPointer(), program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result InformationService::AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
|
Result InformationService::AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
|
||||||
return pm::info::HasLaunchedProgram(out.GetPointer(), program_id);
|
return pm::info::HasLaunchedBootProgram(out.GetPointer(), program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result InformationService::AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {
|
Result InformationService::AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace ams::pm {
|
||||||
|
|
||||||
/* Atmosphere extension commands. */
|
/* Atmosphere extension commands. */
|
||||||
Result AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
|
Result AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
|
||||||
Result AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
|
Result AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id);
|
||||||
Result AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
|
Result AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
|
||||||
};
|
};
|
||||||
static_assert(pm::impl::IsIInformationInterface<InformationService>);
|
static_assert(pm::impl::IsIInformationInterface<InformationService>);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
namespace ams::ro {
|
namespace ams::ro {
|
||||||
|
|
||||||
class DebugMonitorService final {
|
class DebugMonitorService {
|
||||||
public:
|
public:
|
||||||
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
|
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern "C" {
|
||||||
u32 __nx_applet_type = AppletType_None;
|
u32 __nx_applet_type = AppletType_None;
|
||||||
u32 __nx_fs_num_sessions = 1;
|
u32 __nx_fs_num_sessions = 1;
|
||||||
|
|
||||||
#define INNER_HEAP_SIZE 0x4000
|
#define INNER_HEAP_SIZE 0x0
|
||||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||||
|
|
||||||
|
@ -46,6 +46,88 @@ namespace ams {
|
||||||
|
|
||||||
using namespace ams;
|
using namespace ams;
|
||||||
|
|
||||||
|
namespace ams::ro {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* ldr:ro, ro:dmnt, ro:1. */
|
||||||
|
enum PortIndex {
|
||||||
|
PortIndex_DebugMonitor,
|
||||||
|
PortIndex_User,
|
||||||
|
PortIndex_JitPlugin,
|
||||||
|
PortIndex_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
|
||||||
|
constexpr size_t DebugMonitorMaxSessions = 2;
|
||||||
|
|
||||||
|
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
|
||||||
|
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
|
||||||
|
constexpr size_t UserMaxSessions = 2;
|
||||||
|
|
||||||
|
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
|
||||||
|
constexpr size_t JitPluginMaxSessions = 2;
|
||||||
|
|
||||||
|
static constexpr size_t MaxSessions = DebugMonitorMaxSessions + UserMaxSessions + JitPluginMaxSessions;
|
||||||
|
|
||||||
|
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||||
|
|
||||||
|
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||||
|
private:
|
||||||
|
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Allocator = sf::ExpHeapAllocator;
|
||||||
|
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
|
||||||
|
|
||||||
|
alignas(0x40) constinit u8 g_server_allocator_buffer[4_KB];
|
||||||
|
lmem::HeapHandle g_server_heap_handle;
|
||||||
|
Allocator g_server_allocator;
|
||||||
|
|
||||||
|
ServerManager g_server_manager;
|
||||||
|
|
||||||
|
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||||
|
switch (port_index) {
|
||||||
|
case PortIndex_DebugMonitor:
|
||||||
|
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(std::addressof(g_server_allocator)));
|
||||||
|
case PortIndex_User:
|
||||||
|
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_User));
|
||||||
|
case PortIndex_JitPlugin:
|
||||||
|
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_JitPlugin));
|
||||||
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Allocate(size_t size) {
|
||||||
|
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deallocate(void *p, size_t size) {
|
||||||
|
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeHeap() {
|
||||||
|
/* Setup server allocator. */
|
||||||
|
g_server_heap_handle = lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoopServer() {
|
||||||
|
/* Create services. */
|
||||||
|
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||||
|
|
||||||
|
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_User, UserServiceName, UserMaxSessions));
|
||||||
|
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||||
|
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_JitPlugin, JitPluginServiceName, JitPluginMaxSessions));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop forever, servicing our services. */
|
||||||
|
ro::g_server_manager.LoopProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void __libnx_initheap(void) {
|
void __libnx_initheap(void) {
|
||||||
void* addr = nx_inner_heap;
|
void* addr = nx_inner_heap;
|
||||||
size_t size = nx_inner_heap_size;
|
size_t size = nx_inner_heap_size;
|
||||||
|
@ -56,11 +138,15 @@ void __libnx_initheap(void) {
|
||||||
|
|
||||||
fake_heap_start = (char*)addr;
|
fake_heap_start = (char*)addr;
|
||||||
fake_heap_end = (char*)addr + size;
|
fake_heap_end = (char*)addr + size;
|
||||||
|
|
||||||
|
ams::ro::InitializeHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __appInit(void) {
|
void __appInit(void) {
|
||||||
hos::InitializeForStratosphere();
|
hos::InitializeForStratosphere();
|
||||||
|
|
||||||
|
fs::SetAllocator(ro::Allocate, ro::Deallocate);
|
||||||
|
|
||||||
sm::DoWithSession([&]() {
|
sm::DoWithSession([&]() {
|
||||||
R_ABORT_UNLESS(setsysInitialize());
|
R_ABORT_UNLESS(setsysInitialize());
|
||||||
R_ABORT_UNLESS(fsInitialize());
|
R_ABORT_UNLESS(fsInitialize());
|
||||||
|
@ -86,21 +172,15 @@ void __appExit(void) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* ldr:ro, ro:dmnt, ro:1. */
|
|
||||||
/* TODO: Consider max sessions enforcement? */
|
|
||||||
constexpr size_t NumServers = 3;
|
|
||||||
sf::hipc::ServerManager<NumServers> g_server_manager;
|
|
||||||
|
|
||||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
|
}
|
||||||
constexpr size_t DebugMonitorMaxSessions = 2;
|
|
||||||
|
|
||||||
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
|
void *operator new(size_t size) {
|
||||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
|
AMS_ABORT("operator new(size_t) was called");
|
||||||
constexpr size_t UserMaxSessions = 2;
|
}
|
||||||
|
|
||||||
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
|
|
||||||
constexpr size_t JitPluginMaxSessions = 2;
|
|
||||||
|
|
||||||
|
void operator delete(void *p) {
|
||||||
|
AMS_ABORT("operator delete(void *) was called");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
@ -109,6 +189,12 @@ int main(int argc, char **argv)
|
||||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ro, Main));
|
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ro, Main));
|
||||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ro, Main));
|
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ro, Main));
|
||||||
|
|
||||||
|
/* Attach the server allocator. */
|
||||||
|
ro::g_server_allocator.Attach(ro::g_server_heap_handle);
|
||||||
|
|
||||||
|
/* Disable auto-abort in fs operations. */
|
||||||
|
fs::SetEnabledAutoAbort(false);
|
||||||
|
|
||||||
/* Initialize Debug config. */
|
/* Initialize Debug config. */
|
||||||
{
|
{
|
||||||
ON_SCOPE_EXIT { spl::Finalize(); };
|
ON_SCOPE_EXIT { spl::Finalize(); };
|
||||||
|
@ -117,16 +203,8 @@ int main(int argc, char **argv)
|
||||||
ro::SetDevelopmentFunctionEnabled(spl::IsDevelopmentFunctionEnabled());
|
ro::SetDevelopmentFunctionEnabled(spl::IsDevelopmentFunctionEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create services. */
|
/* Run the ro server. */
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
|
ro::LoopServer();
|
||||||
|
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoUserService>(UserServiceName, UserMaxSessions)));
|
|
||||||
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoJitPluginService>(JitPluginServiceName, JitPluginMaxSessions)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop forever, servicing our services. */
|
|
||||||
g_server_manager.LoopProcess();
|
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -42,14 +42,4 @@ namespace ams::ro {
|
||||||
};
|
};
|
||||||
static_assert(ro::impl::IsIRoInterface<RoService>);
|
static_assert(ro::impl::IsIRoInterface<RoService>);
|
||||||
|
|
||||||
class RoUserService final : public RoService {
|
|
||||||
public:
|
|
||||||
RoUserService() : RoService(NrrKind_User) { /* ... */ }
|
|
||||||
};
|
|
||||||
|
|
||||||
class RoJitPluginService final : public RoService {
|
|
||||||
public:
|
|
||||||
RoJitPluginService() : RoService(NrrKind_JitPlugin) { /* ... */ }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue