Browse Source
glue: Implement arp:w and arp:r services
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.pull/15/merge
3 changed files with 330 additions and 2 deletions
-
285src/core/hle/service/glue/arp.cpp
-
43src/core/hle/service/glue/arp.h
-
4src/core/hle/service/service.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 <memory>
|
|||
|
|||
#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<u64> 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<u64>(); |
|||
|
|||
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<u64>(); |
|||
|
|||
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<u64>(); |
|||
|
|||
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<u64>(); |
|||
|
|||
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<IRegistrar> { |
|||
friend class ARP_W; |
|||
|
|||
public: |
|||
explicit IRegistrar( |
|||
std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> 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<u64>(); |
|||
|
|||
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<ApplicationLaunchProperty>(); |
|||
|
|||
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<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id; |
|||
bool issued = false; |
|||
ApplicationLaunchProperty launch; |
|||
std::vector<u8> 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<IRegistrar>( |
|||
[this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> 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<u64>(); |
|||
|
|||
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
|
|||
@ -0,0 +1,43 @@ |
|||
// Copyright 2019 yuzu emulator team |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "core/hle/service/service.h" |
|||
|
|||
namespace Service::Glue { |
|||
|
|||
class ARPManager; |
|||
class IRegistrar; |
|||
|
|||
class ARP_R final : public ServiceFramework<ARP_R> { |
|||
public: |
|||
explicit ARP_R(const Core::System& system, const ARPManager& manager); |
|||
~ARP_R() override; |
|||
|
|||
private: |
|||
void GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx); |
|||
void GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx); |
|||
void GetApplicationControlProperty(Kernel::HLERequestContext& ctx); |
|||
void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx); |
|||
|
|||
const Core::System& system; |
|||
const ARPManager& manager; |
|||
}; |
|||
|
|||
class ARP_W final : public ServiceFramework<ARP_W> { |
|||
public: |
|||
explicit ARP_W(const Core::System& system, ARPManager& manager); |
|||
~ARP_W() override; |
|||
|
|||
private: |
|||
void AcquireRegistrar(Kernel::HLERequestContext& ctx); |
|||
void DeleteProperties(Kernel::HLERequestContext& ctx); |
|||
|
|||
const Core::System& system; |
|||
ARPManager& manager; |
|||
std::shared_ptr<IRegistrar> registrar; |
|||
}; |
|||
|
|||
} // namespace Service::Glue |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue