/* * Copyright (c) 2018-2020 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 . */ #pragma once #include "../sf_common.hpp" #include "../sf_service_object.hpp" #include "../sf_out.hpp" #include "../sf_buffers.hpp" #include "../sf_handles.hpp" #include "../cmif/sf_cmif_pointer_and_size.hpp" #include "../cmif/sf_cmif_service_dispatch.hpp" #include "../cmif/sf_cmif_service_object_holder.hpp" #include "../cmif/sf_cmif_domain_api.hpp" #include "../hipc/sf_hipc_api.hpp" #include "../hipc/sf_hipc_server_session_manager.hpp" /* Serialization classes. */ namespace ams::sf { namespace impl { struct ProcessIdHolder { os::ProcessId process_id; constexpr explicit operator os::ProcessId() const { return this->process_id; } constexpr os::ProcessId GetValue() const { return this->process_id; } constexpr void SetValue(const os::ProcessId &p) { this->process_id = p; } }; } struct ClientProcessId : public impl::ProcessIdHolder {}; static_assert(std::is_trivial::value && sizeof(ClientProcessId) == sizeof(os::ProcessId), "ClientProcessId"); struct ClientAppletResourceUserId : public impl::ProcessIdHolder {}; static_assert(std::is_trivial::value && sizeof(ClientAppletResourceUserId ) == sizeof(os::ProcessId), "ClientAppletResourceUserId"); namespace impl { constexpr inline Result MarshalProcessId(ClientProcessId &client, const os::ProcessId &client_process_id) { client.SetValue(client_process_id); return ResultSuccess(); } constexpr inline Result MarshalProcessId(ClientAppletResourceUserId &client, const os::ProcessId &client_process_id) { if (client.GetValue() != client_process_id && client.GetValue() != os::ProcessId{}) { return sf::ResultPreconditionViolation(); } return ResultSuccess(); } } namespace impl { struct OutObjectTag{}; template class InOutObjectHolder; } template requires std::derived_from class Out> : public impl::OutObjectTag { template friend class Out; public: using Interface = ServiceImpl; private: impl::SharedPointerBase *m_out; cmif::DomainObjectId *m_object_id; private: Out(impl::SharedPointerBase *p, cmif::DomainObjectId *o = nullptr) : m_out(p), m_object_id(o) { /* ... */ } public: Out(const Out &rhs) : m_out(rhs.m_out), m_object_id(rhs.m_object_id) { /* ... */ } Out(SharedPointer *out, cmif::DomainObjectId *o = nullptr) : m_out(std::addressof(out->m_base)), m_object_id(o) { /* .... */ } template requires std::derived_from Out(Out> out) : m_out(out.m_out), m_object_id(out.m_object_id) { /* ... */ } template requires std::derived_from Out(SharedPointer *out, cmif::DomainObjectId *o = nullptr) : m_out(std::addressof(out->m_base)), m_object_id(o) { /* .... */ } void SetValue(SharedPointer s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) { *m_out = std::move(s.m_base); if (new_object_id != cmif::InvalidDomainObjectId) { AMS_ABORT_UNLESS(m_object_id != nullptr); *m_object_id = new_object_id; } } template requires std::derived_from void SetValue(SharedPointer s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) { *m_out = std::move(s.m_base); if (new_object_id != cmif::InvalidDomainObjectId) { AMS_ABORT_UNLESS(m_object_id != nullptr); *m_object_id = new_object_id; } } class DerefProxy { template friend class Out; private: Out &m_target; private: explicit DerefProxy(Out &t) : m_target(t) { /* ... */ } public: DerefProxy &operator=(SharedPointer p) { m_target.SetValue(std::move(p)); return *this; } template requires std::derived_from DerefProxy &operator=(SharedPointer p) { m_target.SetValue(std::move(p)); return *this; } }; DerefProxy operator *() { return DerefProxy(*this); } template Out> DownCast() { return Out>(m_out, m_object_id); } }; } namespace ams::sf::impl { /* Machinery for filtering type lists. */ template struct TupleCat; template struct TupleCat, std::tuple> { using type = std::tuple; }; template