diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.cpp b/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.cpp new file mode 100644 index 000000000..1fd7e905e --- /dev/null +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "ns_am_mitm_service.hpp" +#include "ns_shim.h" + +namespace ams::mitm::ns { + + Result NsAmMitmService::GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type) { + return nsamGetApplicationContentPathFwd(this->forward_service.get(), out_path.GetPointer(), out_path.GetSize(), static_cast(application_id), static_cast(content_type)); + } + + Result NsAmMitmService::ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type) { + /* Always succeed for web applets asking about HBL. */ + /* This enables hbl html. */ + bool is_hbl; + if (R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, application_id)) && is_hbl) { + nsamResolveApplicationContentPathFwd(this->forward_service.get(), static_cast(application_id), static_cast(content_type)); + return ResultSuccess(); + } + return nsamResolveApplicationContentPathFwd(this->forward_service.get(), static_cast(application_id), static_cast(content_type)); + } + + Result NsAmMitmService::GetRunningApplicationProgramId(sf::Out out, ncm::ProgramId application_id) { + return nsamGetRunningApplicationProgramIdFwd(this->forward_service.get(), reinterpret_cast(out.GetPointer()), static_cast(application_id)); + } + +} diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.hpp b/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.hpp index a32166355..0d52d245e 100644 --- a/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_am_mitm_service.hpp @@ -18,23 +18,32 @@ namespace ams::mitm::ns { - class NsAmMitmService : public sf::IMitmServiceObject { + class NsAmMitmService : public sf::IMitmServiceObject { private: enum class CommandId { - /* TODO */ + GetApplicationContentPath = 21, + ResolveApplicationContentPath = 23, + GetRunningApplicationProgramId = 92, }; public: static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { - /* TODO */ - return false; + /* We will mitm: + * - web applets, to facilitate hbl web browser launching. + */ + return ncm::IsWebAppletProgramId(client_info.program_id); } public: SF_MITM_SERVICE_OBJECT_CTOR(NsAmMitmService) { /* ... */ } protected: - /* TODO */ + /* Actual command API. */ + Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type); + Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type); + Result GetRunningApplicationProgramId(sf::Out out, ncm::ProgramId application_id); public: DEFINE_SERVICE_DISPATCH_TABLE { - /* TODO */ + MAKE_SERVICE_COMMAND_META(GetApplicationContentPath), + MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath), + MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_600), }; }; diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_shim.c b/stratosphere/ams_mitm/source/ns_mitm/ns_shim.c new file mode 100644 index 000000000..4f5dcefc1 --- /dev/null +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_shim.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include "ns_shim.h" + +/* Command forwarders. */ +Result nsGetDocumentInterfaceFwd(Service* s, NsDocumentInterface* out) { + return serviceDispatch(s, 7999, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} + +static Result _nsGetApplicationContentPath(Service *s, void* out, size_t out_size, u64 app_id, NcmContentType content_type) { + const struct { + u8 content_type; + u64 app_id; + } in = { content_type, app_id }; + return serviceDispatchIn(s, 21, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, out_size } }, + ); +} + + +static Result _nsResolveApplicationContentPath(Service* s, u64 app_id, NcmContentType content_type) { + const struct { + u8 content_type; + u64 app_id; + } in = { content_type, app_id }; + return serviceDispatchIn(s, 23, in); +} + +static Result _nsGetRunningApplicationProgramId(Service* s, u64* out_program_id, u64 app_id) { + if (hosversionBefore(6, 0, 0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return serviceDispatchInOut(s, 92, app_id, *out_program_id); +} + +/* Application Manager forwarders. */ +Result nsamGetApplicationContentPathFwd(Service* s, void* out, size_t out_size, u64 app_id, NcmContentType content_type) { + return _nsGetApplicationContentPath(s, out, out_size, app_id, content_type); +} + +Result nsamResolveApplicationContentPathFwd(Service* s, u64 app_id, NcmContentType content_type) { + return _nsResolveApplicationContentPath(s, app_id, content_type); +} + +Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_program_id, u64 app_id) { + return _nsGetRunningApplicationProgramId(s, out_program_id, app_id); +} + +/* Web forwarders */ +Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, NcmContentType content_type) { + return _nsGetApplicationContentPath(&doc->s, out, out_size, app_id, content_type); +} + +Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type) { + return _nsResolveApplicationContentPath(&doc->s, app_id, content_type); +} + +Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id) { + return _nsGetRunningApplicationProgramId(&doc->s, out_program_id, app_id); +} + +void nsDocumentInterfaceClose(NsDocumentInterface* doc) { + serviceClose(&doc->s); +} + diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_shim.h b/stratosphere/ams_mitm/source/ns_mitm/ns_shim.h new file mode 100644 index 000000000..7749bbf14 --- /dev/null +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_shim.h @@ -0,0 +1,33 @@ +/** + * @file ns_shim.h + * @brief Nintendo Shell Services (ns) IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + Service s; +} NsDocumentInterface; + +/* Command forwarders. */ +Result nsGetDocumentInterfaceFwd(Service* s, NsDocumentInterface* out); + +Result nsamGetApplicationContentPathFwd(Service* s, void* out, size_t out_size, u64 app_id, NcmContentType content_type); +Result nsamResolveApplicationContentPathFwd(Service* s, u64 app_id, NcmContentType content_type); +Result nsamGetRunningApplicationProgramIdFwd(Service* s, u64* out_program_id, u64 app_id); + +Result nswebGetApplicationContentPath(NsDocumentInterface* doc, void* out, size_t out_size, u64 app_id, NcmContentType content_type); +Result nswebResolveApplicationContentPath(NsDocumentInterface* doc, u64 app_id, NcmContentType content_type); +Result nswebGetRunningApplicationProgramId(NsDocumentInterface* doc, u64* out_program_id, u64 app_id); + +void nsDocumentInterfaceClose(NsDocumentInterface* doc); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.cpp b/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.cpp new file mode 100644 index 000000000..d475c1d59 --- /dev/null +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "ns_web_mitm_service.hpp" + +namespace ams::mitm::ns { + + Result NsDocumentService::GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type) { + return nswebGetApplicationContentPath(this->srv.get(), out_path.GetPointer(), out_path.GetSize(), static_cast(application_id), static_cast(content_type)); + } + + Result NsDocumentService::ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type) { + /* Always succeed for web applets asking about HBL. */ + /* This enables hbl html. */ + bool is_hbl; + if (R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, application_id)) && is_hbl) { + nswebResolveApplicationContentPath(this->srv.get(), static_cast(application_id), static_cast(content_type)); + return ResultSuccess(); + } + return nswebResolveApplicationContentPath(this->srv.get(), static_cast(application_id), static_cast(content_type)); + } + + Result NsDocumentService::GetRunningApplicationProgramId(sf::Out out, ncm::ProgramId application_id) { + return nswebGetRunningApplicationProgramId(this->srv.get(), reinterpret_cast(out.GetPointer()), static_cast(application_id)); + } + + Result NsWebMitmService::GetDocumentInterface(sf::Out> out) { + /* Open a document interface. */ + NsDocumentInterface doc; + R_TRY(nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc)); + const sf::cmif::DomainObjectId target_object_id{serviceGetObjectId(&doc.s)}; + + out.SetValue(std::make_shared(this->client_info, std::make_unique(doc)), target_object_id); + return ResultSuccess(); + } + +} diff --git a/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.hpp b/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.hpp index 09f540a56..68ac3b460 100644 --- a/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/ns_mitm/ns_web_mitm_service.hpp @@ -16,25 +16,58 @@ #pragma once #include +#include "ns_shim.h" + namespace ams::mitm::ns { + class NsDocumentService : public sf::IServiceObject { + private: + enum class CommandId { + GetApplicationContentPath = 21, + ResolveApplicationContentPath = 23, + GetRunningApplicationProgramId = 92, + }; + private: + sm::MitmProcessInfo client_info; + std::unique_ptr<::NsDocumentInterface> srv; + public: + NsDocumentService(const sm::MitmProcessInfo &cl, std::unique_ptr<::NsDocumentInterface> s) : client_info(cl), srv(std::move(s)) { /* .. */ } + + virtual ~NsDocumentService() { + nsDocumentInterfaceClose(this->srv.get()); + } + protected: + /* Actual command API. */ + Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type); + Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type); + Result GetRunningApplicationProgramId(sf::Out out, ncm::ProgramId application_id); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MAKE_SERVICE_COMMAND_META(GetApplicationContentPath), + MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath), + MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_600), + }; + }; + class NsWebMitmService : public sf::IMitmServiceObject { private: enum class CommandId { - /* TODO */ + GetDocumentInterface = 7999, }; public: static bool ShouldMitm(const sm::MitmProcessInfo &client_info) { - /* TODO */ - return false; + /* We will mitm: + * - web applets, to facilitate hbl web browser launching. + */ + return ncm::IsWebAppletProgramId(client_info.program_id); } public: SF_MITM_SERVICE_OBJECT_CTOR(NsWebMitmService) { /* ... */ } protected: - /* TODO */ + Result GetDocumentInterface(sf::Out> out); public: DEFINE_SERVICE_DISPATCH_TABLE { - /* TODO */ + MAKE_SERVICE_COMMAND_META(GetDocumentInterface), }; }; diff --git a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp index 0c13966b3..b21adb947 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ncm/ncm_types.hpp @@ -421,6 +421,14 @@ namespace ams::ncm { return ProgramId::ApplicationStart <= program_id && program_id <= ProgramId::ApplicationEnd; } + inline constexpr bool IsWebAppletProgramId(const ProgramId &program_id) { + return program_id == ProgramId::AppletWeb || + program_id == ProgramId::AppletShop || + program_id == ProgramId::AppletOfflineWeb || + program_id == ProgramId::AppletLoginShare || + program_id == ProgramId::AppletWifiWebAuth; + } + static_assert(sizeof(ProgramId) == sizeof(u64) && std::is_pod::value, "ProgramId definition!"); /* Program Location. */ diff --git a/stratosphere/libstratosphere/include/stratosphere/pm/pm_info_api.hpp b/stratosphere/libstratosphere/include/stratosphere/pm/pm_info_api.hpp index 0b5e6dce9..6a56b13df 100644 --- a/stratosphere/libstratosphere/include/stratosphere/pm/pm_info_api.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/pm/pm_info_api.hpp @@ -31,4 +31,7 @@ namespace ams::pm::info { /* Information convenience API. */ bool HasLaunchedProgram(ncm::ProgramId program_id); + Result IsHblProcessId(bool *out, os::ProcessId process_id); + Result IsHblProgramId(bool *out, ncm::ProgramId program_id); + } diff --git a/stratosphere/libstratosphere/include/stratosphere/sf/sf_service_object.hpp b/stratosphere/libstratosphere/include/stratosphere/sf/sf_service_object.hpp index fd87ddb2a..f0c32f1b5 100644 --- a/stratosphere/libstratosphere/include/stratosphere/sf/sf_service_object.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/sf/sf_service_object.hpp @@ -20,7 +20,10 @@ namespace ams::sf { - class IServiceObject{}; + class IServiceObject { + public: + virtual ~IServiceObject() { /* ... */ } + }; class IMitmServiceObject : public IServiceObject { protected: @@ -29,6 +32,8 @@ namespace ams::sf { public: IMitmServiceObject(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : forward_service(std::move(s)), client_info(c) { /* ... */ } + virtual ~IMitmServiceObject() { /* ... */ } + static bool ShouldMitm(os::ProcessId process_id, ncm::ProgramId program_id); }; diff --git a/stratosphere/libstratosphere/source/pm/pm_info_api.cpp b/stratosphere/libstratosphere/source/pm/pm_info_api.cpp index e07a15310..e0028004e 100644 --- a/stratosphere/libstratosphere/source/pm/pm_info_api.cpp +++ b/stratosphere/libstratosphere/source/pm/pm_info_api.cpp @@ -73,4 +73,21 @@ namespace ams::pm::info { return has_launched; } + + Result IsHblProcessId(bool *out, os::ProcessId process_id) { + ncm::ProgramLocation loc; + cfg::OverrideStatus override_status; + R_TRY(GetProcessInfo(&loc, &override_status, process_id)); + + *out = override_status.IsHbl(); + return ResultSuccess(); + } + + Result IsHblProgramId(bool *out, ncm::ProgramId program_id) { + os::ProcessId process_id; + R_TRY(GetProcessId(&process_id, program_id)); + + return IsHblProcessId(out, process_id); + } + }