libstrat/sm: add ScopedServiceHolder, Wait(Mitm/Service)

This commit is contained in:
Michael Scire 2019-07-02 22:21:18 -07:00
parent d7d7cba3d3
commit 45700a12e8
8 changed files with 154 additions and 0 deletions

View File

@ -48,4 +48,5 @@
#include "stratosphere/ncm.hpp" #include "stratosphere/ncm.hpp"
#include "stratosphere/pm.hpp" #include "stratosphere/pm.hpp"
#include "stratosphere/rnd.hpp" #include "stratosphere/rnd.hpp"
#include "stratosphere/sm.hpp"
#include "stratosphere/util.hpp" #include "stratosphere/util.hpp"

View File

@ -27,5 +27,6 @@ namespace sts::sm {
/* Atmosphere extensions. */ /* Atmosphere extensions. */
Result HasService(bool *out, ServiceName name); Result HasService(bool *out, ServiceName name);
Result WaitService(ServiceName name);
} }

View File

@ -26,5 +26,6 @@ namespace sts::sm::mitm {
Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id); Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id);
Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name); Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name);
Result HasMitm(bool *out, ServiceName name); Result HasMitm(bool *out, ServiceName name);
Result WaitMitm(ServiceName name);
} }

View File

@ -17,6 +17,8 @@
#pragma once #pragma once
#include <cstring> #include <cstring>
#include <switch.h> #include <switch.h>
#include "../defines.hpp"
#include "../results.hpp"
namespace sts::sm { namespace sts::sm {
@ -69,4 +71,71 @@ namespace sts::sm {
/* For process validation. */ /* For process validation. */
static constexpr u64 InvalidProcessId = static_cast<u64>(-1ull); static constexpr u64 InvalidProcessId = static_cast<u64>(-1ull);
/* Utility, for scoped access to libnx services. */
template<Result Initializer(), void Finalizer()>
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;
}
};
} }

View File

@ -60,6 +60,40 @@ Result smAtmosphereHasService(bool *out, const char *name) {
return rc; 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) { Result smAtmosphereHasMitm(bool *out, const char *name) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -99,6 +133,40 @@ Result smAtmosphereHasMitm(bool *out, const char *name) {
return rc; 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) { Result smAtmosphereMitmInitialize(void) {
atomicIncrement64(&g_mitmRefCnt); atomicIncrement64(&g_mitmRefCnt);

View File

@ -12,7 +12,9 @@ extern "C" {
#endif #endif
Result smAtmosphereHasService(bool *out, const char *name); Result smAtmosphereHasService(bool *out, const char *name);
Result smAtmosphereWaitService(const char *name);
Result smAtmosphereHasMitm(bool *out, const char *name); Result smAtmosphereHasMitm(bool *out, const char *name);
Result smAtmosphereWaitMitm(const char *name);
Result smAtmosphereMitmInitialize(void); Result smAtmosphereMitmInitialize(void);
void smAtmosphereMitmExit(void); void smAtmosphereMitmExit(void);

View File

@ -49,4 +49,10 @@ namespace sts::sm {
}); });
} }
Result WaitService(ServiceName name) {
return impl::DoWithUserSession([&]() {
return smAtmosphereWaitService(name.name);
});
}
} }

View File

@ -54,4 +54,10 @@ namespace sts::sm::mitm {
}); });
} }
Result WaitMitm(ServiceName name) {
return impl::DoWithUserSession([&]() {
return smAtmosphereWaitMitm(name.name);
});
}
} }