From ce2197302236c0990d2d5234ab52f1579c126090 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 24 Jun 2019 19:26:16 -0400 Subject: glue: Implement arp:w and arp:r services These keep track of running process' launch properties and control properties and allows for issuing and reading them by process and title ID. --- src/core/hle/service/glue/arp.cpp | 285 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 src/core/hle/service/glue/arp.cpp (limited to 'src/core/hle/service/glue/arp.cpp') diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp new file mode 100644 index 000000000..19c75ff2f --- /dev/null +++ b/src/core/hle/service/glue/arp.cpp @@ -0,0 +1,285 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/logging/log.h" +#include "core/file_sys/control_metadata.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/errors.h" +#include "core/hle/service/glue/manager.h" +#include "core/hle/service/service.h" + +namespace Service::Glue { + +namespace { +std::optional GetTitleIDForProcessID(const Core::System& system, u64 process_id) { + const auto& list = system.Kernel().GetProcessList(); + const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { + return process->GetProcessID() == process_id; + }); + + if (iter == list.end()) { + return std::nullopt; + } + + return (*iter)->GetTitleID(); +} +} // Anonymous namespace + +ARP_R::ARP_R(const Core::System& system, const ARPManager& manager) + : ServiceFramework{"arp:r"}, system(system), manager(manager) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"}, + {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, + {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, + {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ARP_R::~ARP_R() = default; + +void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + const auto title_id = GetTitleIDForProcessID(system, process_id); + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + const auto res = manager.GetLaunchProperty(*title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get launch property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*res); +} + +void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + + const auto res = manager.GetLaunchProperty(title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get launch property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(*res); +} + +void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + const auto title_id = GetTitleIDForProcessID(system, process_id); + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + const auto res = manager.GetControlProperty(*title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get control property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + ctx.WriteBuffer(*res); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + + const auto res = manager.GetControlProperty(title_id); + + if (res.Failed()) { + LOG_ERROR(Service_ARP, "Failed to get control property!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + ctx.WriteBuffer(*res); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +class IRegistrar final : public ServiceFramework { + friend class ARP_W; + +public: + explicit IRegistrar( + std::function)> issuer) + : ServiceFramework{"IRegistrar"}, issue_process_id(std::move(issuer)) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IRegistrar::Issue, "Issue"}, + {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"}, + {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void Issue(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + if (process_id == 0) { + LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_PROCESS_ID_ZERO); + } + + if (issued) { + LOG_ERROR(Service_ARP, + "Attempted to issue registrar, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + issue_process_id(process_id, launch, std::move(control)); + issued = true; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + if (issued) { + LOG_ERROR( + Service_ARP, + "Attempted to set application launch property, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + IPC::RequestParser rp{ctx}; + launch = rp.PopRaw(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + if (issued) { + LOG_ERROR( + Service_ARP, + "Attempted to set application control property, but registrar is already issued!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_ALREADY_ISSUED); + } + + control = ctx.ReadBuffer(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + std::function)> issue_process_id; + bool issued = false; + ApplicationLaunchProperty launch; + std::vector control; +}; + +ARP_W::ARP_W(const Core::System& system, ARPManager& manager) + : ServiceFramework{"arp:w"}, system(system), manager(manager) { + // clang-format off + static const FunctionInfo functions[] = { + {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, + {1, &ARP_W::DeleteProperties, "DeleteProperties"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +ARP_W::~ARP_W() = default; + +void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ARP, "called"); + + registrar = std::make_shared( + [this](u64 process_id, ApplicationLaunchProperty launch, std::vector control) { + const auto res = GetTitleIDForProcessID(system, process_id); + if (!res.has_value()) { + return ERR_NONEXISTENT; + } + + return manager.Register(*res, launch, std::move(control)); + }); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(registrar); +} + +void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw(); + + LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + + if (process_id == 0) { + LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_PROCESS_ID_ZERO); + } + + const auto title_id = GetTitleIDForProcessID(system, process_id); + + if (!title_id.has_value()) { + LOG_ERROR(Service_ARP, "No title ID for process ID!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERR_NONEXISTENT); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(manager.Unregister(*title_id)); +} + +} // namespace Service::Glue -- cgit v1.2.3 From d10fc2d7277cf075f875fe2831501cb79c50e21a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 25 Jun 2019 22:25:10 -0400 Subject: glue: Correct missing bytes in ApplicationLaunchParameter --- src/core/hle/service/glue/arp.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'src/core/hle/service/glue/arp.cpp') diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 19c75ff2f..b591ce31b 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -58,7 +58,8 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } const auto res = manager.GetLaunchProperty(*title_id); @@ -67,6 +68,7 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_ARP, "Failed to get launch property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -86,6 +88,7 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestCont LOG_ERROR(Service_ARP, "Failed to get launch property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -103,7 +106,8 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } const auto res = manager.GetControlProperty(*title_id); @@ -112,6 +116,7 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { LOG_ERROR(Service_ARP, "Failed to get control property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -132,6 +137,7 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestCon LOG_ERROR(Service_ARP, "Failed to get control property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -168,14 +174,16 @@ private: if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_PROCESS_ID_ZERO); + rb.Push(ERR_INVALID_PROCESS_ID); + return; } if (issued) { LOG_ERROR(Service_ARP, "Attempted to issue registrar, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } issue_process_id(process_id, launch, std::move(control)); @@ -193,7 +201,8 @@ private: Service_ARP, "Attempted to set application launch property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } IPC::RequestParser rp{ctx}; @@ -211,7 +220,8 @@ private: Service_ARP, "Attempted to set application control property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } control = ctx.ReadBuffer(); @@ -247,7 +257,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { [this](u64 process_id, ApplicationLaunchProperty launch, std::vector control) { const auto res = GetTitleIDForProcessID(system, process_id); if (!res.has_value()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return manager.Register(*res, launch, std::move(control)); @@ -267,7 +277,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_PROCESS_ID_ZERO); + rb.Push(ERR_INVALID_PROCESS_ID); + return; } const auto title_id = GetTitleIDForProcessID(system, process_id); @@ -275,7 +286,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "No title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } IPC::ResponseBuilder rb{ctx, 2}; -- cgit v1.2.3