From 45700a12e80404e3c49e2bc4893412489fc72040 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 2 Jul 2019 22:21:18 -0700 Subject: [PATCH] libstrat/sm: add ScopedServiceHolder, Wait(Mitm/Service) --- include/stratosphere.hpp | 1 + include/stratosphere/sm/sm_api.hpp | 1 + include/stratosphere/sm/sm_mitm_api.hpp | 1 + include/stratosphere/sm/sm_types.hpp | 69 +++++++++++++++++++++++++ source/sm/sm_ams.c | 68 ++++++++++++++++++++++++ source/sm/sm_ams.h | 2 + source/sm/sm_api.cpp | 6 +++ source/sm/sm_mitm_api.cpp | 6 +++ 8 files changed, 154 insertions(+) diff --git a/include/stratosphere.hpp b/include/stratosphere.hpp index 5ba88a04..04ddaa2e 100644 --- a/include/stratosphere.hpp +++ b/include/stratosphere.hpp @@ -48,4 +48,5 @@ #include "stratosphere/ncm.hpp" #include "stratosphere/pm.hpp" #include "stratosphere/rnd.hpp" +#include "stratosphere/sm.hpp" #include "stratosphere/util.hpp" \ No newline at end of file diff --git a/include/stratosphere/sm/sm_api.hpp b/include/stratosphere/sm/sm_api.hpp index 152185e9..80e12cb7 100644 --- a/include/stratosphere/sm/sm_api.hpp +++ b/include/stratosphere/sm/sm_api.hpp @@ -27,5 +27,6 @@ namespace sts::sm { /* Atmosphere extensions. */ Result HasService(bool *out, ServiceName name); + Result WaitService(ServiceName name); } diff --git a/include/stratosphere/sm/sm_mitm_api.hpp b/include/stratosphere/sm/sm_mitm_api.hpp index b378aac7..a0837c97 100644 --- a/include/stratosphere/sm/sm_mitm_api.hpp +++ b/include/stratosphere/sm/sm_mitm_api.hpp @@ -26,5 +26,6 @@ namespace sts::sm::mitm { Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id); Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name); Result HasMitm(bool *out, ServiceName name); + Result WaitMitm(ServiceName name); } diff --git a/include/stratosphere/sm/sm_types.hpp b/include/stratosphere/sm/sm_types.hpp index 377c05fc..a1915e63 100644 --- a/include/stratosphere/sm/sm_types.hpp +++ b/include/stratosphere/sm/sm_types.hpp @@ -17,6 +17,8 @@ #pragma once #include #include +#include "../defines.hpp" +#include "../results.hpp" namespace sts::sm { @@ -69,4 +71,71 @@ namespace sts::sm { /* For process validation. */ static constexpr u64 InvalidProcessId = static_cast(-1ull); + /* Utility, for scoped access to libnx services. */ + template + class ScopedServiceHolder { + NON_COPYABLE(ScopedServiceHolder); + private: + Result result; + bool has_initialized; + public: + ScopedServiceHolder(bool initialize = true) : result(ResultSuccess), has_initialized(false) { + if (initialize) { + this->Initialize(); + } + } + + ~ScopedServiceHolder() { + if (this->has_initialized) { + this->Finalize(); + } + } + + ScopedServiceHolder(ScopedServiceHolder&& rhs) { + this->result = rhs.result; + this->has_initialized = rhs.has_initialized; + rhs.result = ResultSuccess; + rhs.has_initialized = false; + } + + ScopedServiceHolder& operator=(ScopedServiceHolder&& rhs) { + rhs.Swap(*this); + return *this; + } + + void Swap(ScopedServiceHolder& rhs) { + std::swap(this->result, rhs.result); + std::swap(this->has_initialized, rhs.has_initialized); + } + + explicit operator bool() const { + return this->has_initialized; + } + + Result Initialize() { + if (this->has_initialized) { + std::abort(); + } + + DoWithSmSession([&]() { + this->result = Initializer(); + }); + + this->has_initialized = R_SUCCEEDED(this->result); + return this->result; + } + + void Finalize() { + if (!this->has_initialized) { + std::abort(); + } + Finalizer(); + this->has_initialized = false; + } + + Result GetResult() const { + return this->result; + } + }; + } diff --git a/source/sm/sm_ams.c b/source/sm/sm_ams.c index 2b1ea46f..c933172d 100644 --- a/source/sm/sm_ams.c +++ b/source/sm/sm_ams.c @@ -60,6 +60,40 @@ Result smAtmosphereHasService(bool *out, const char *name) { return rc; } +Result smAtmosphereWaitService(const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = smGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65101; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result smAtmosphereHasMitm(bool *out, const char *name) { IpcCommand c; ipcInitialize(&c); @@ -99,6 +133,40 @@ Result smAtmosphereHasMitm(bool *out, const char *name) { return rc; } +Result smAtmosphereWaitMitm(const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = smGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65005; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + Result smAtmosphereMitmInitialize(void) { atomicIncrement64(&g_mitmRefCnt); diff --git a/source/sm/sm_ams.h b/source/sm/sm_ams.h index 1b6e60a6..26f9008d 100644 --- a/source/sm/sm_ams.h +++ b/source/sm/sm_ams.h @@ -12,7 +12,9 @@ extern "C" { #endif Result smAtmosphereHasService(bool *out, const char *name); +Result smAtmosphereWaitService(const char *name); Result smAtmosphereHasMitm(bool *out, const char *name); +Result smAtmosphereWaitMitm(const char *name); Result smAtmosphereMitmInitialize(void); void smAtmosphereMitmExit(void); diff --git a/source/sm/sm_api.cpp b/source/sm/sm_api.cpp index 53108607..a6b2be97 100644 --- a/source/sm/sm_api.cpp +++ b/source/sm/sm_api.cpp @@ -49,4 +49,10 @@ namespace sts::sm { }); } + Result WaitService(ServiceName name) { + return impl::DoWithUserSession([&]() { + return smAtmosphereWaitService(name.name); + }); + } + } diff --git a/source/sm/sm_mitm_api.cpp b/source/sm/sm_mitm_api.cpp index 640ca54b..d83518d0 100644 --- a/source/sm/sm_mitm_api.cpp +++ b/source/sm/sm_mitm_api.cpp @@ -54,4 +54,10 @@ namespace sts::sm::mitm { }); } + Result WaitMitm(ServiceName name) { + return impl::DoWithUserSession([&]() { + return smAtmosphereWaitMitm(name.name); + }); + } + }