/* * 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 IsOutForceEnabled> : public std::true_type{}; template class Out> : public impl::OutObjectTag { static_assert(std::is_base_of::value, "Out> requires ServiceObject base."); template friend class Out; public: using ServiceImplType = ServiceImpl; private: cmif::ServiceObjectHolder *srv; cmif::DomainObjectId *object_id; public: Out(cmif::ServiceObjectHolder *s) : srv(s), object_id(nullptr) { /* ... */ } Out(cmif::ServiceObjectHolder *s, cmif::DomainObjectId *o) : srv(s), object_id(o) { /* ... */ } void SetValue(std::shared_ptr &&s, cmif::DomainObjectId new_object_id = cmif::InvalidDomainObjectId) { *this->srv = cmif::ServiceObjectHolder(std::move(s)); if (new_object_id != cmif::InvalidDomainObjectId) { AMS_ABORT_UNLESS(object_id != nullptr); *this->object_id = new_object_id; } } }; } namespace ams::sf::impl { /* Machinery for filtering type lists. */ template struct TupleCat; template struct TupleCat, std::tuple> { using type = std::tuple; }; template