summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/acc/acc.cpp34
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp25
-rw-r--r--src/core/hle/service/acc/profile_manager.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp6
-rw-r--r--src/core/hle/service/service.cpp21
-rw-r--r--src/core/hle/service/service.h4
-rw-r--r--src/core/hle/service/sm/sm.cpp43
-rw-r--r--src/core/hle/service/sm/sm.h2
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp41
11 files changed, 117 insertions, 65 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index bb838e285..85a3f0802 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -512,10 +512,11 @@ protected:
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
- explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_)
+ explicit IManagerForApplication(Core::System& system_,
+ const std::shared_ptr<ProfileManager>& profile_manager_)
: ServiceFramework{system_, "IManagerForApplication"},
ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
- user_id{user_id_} {
+ profile_manager{profile_manager_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
@@ -545,7 +546,7 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.PushRaw<u64>(user_id.Hash());
+ rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
}
void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
@@ -575,17 +576,20 @@ private:
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.PushRaw<u64>(user_id.Hash());
+ rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
}
void StoreOpenContext(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_ACC, "(STUBBED) called");
+ LOG_DEBUG(Service_ACC, "called");
+
+ profile_manager->StoreOpenedUsers();
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
- Common::UUID user_id{};
+ std::shared_ptr<ProfileManager> profile_manager;
};
// 6.0.0+
@@ -790,7 +794,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
- rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser());
+ rb.PushIpcInterface<IManagerForApplication>(system, profile_manager);
}
void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) {
@@ -849,22 +853,10 @@ void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
-void Module::Interface::LoadOpenContext(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_ACC, "(STUBBED) called");
-
- // This is similar to GetBaasAccountManagerForApplication
- // This command is used concurrently with ListOpenContextStoredUsers
- // TODO: Find the differences between this and GetBaasAccountManagerForApplication
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser());
-}
-
void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_ACC, "(STUBBED) called");
+ LOG_DEBUG(Service_ACC, "called");
- // TODO(ogniK): Handle open contexts
- ctx.WriteBuffer(profile_manager->GetOpenUsers());
+ ctx.WriteBuffer(profile_manager->GetStoredOpenedUsers());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 1621e7c0a..9411b0b92 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -35,7 +35,6 @@ public:
void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx);
void GetProfileEditor(Kernel::HLERequestContext& ctx);
void ListQualifiedUsers(Kernel::HLERequestContext& ctx);
- void LoadOpenContext(Kernel::HLERequestContext& ctx);
void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx);
void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx);
void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 65023b8c2..54844bfe7 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -28,7 +28,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
{110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
{111, nullptr, "ClearSaveDataThumbnail"},
{120, nullptr, "CreateGuestLoginRequest"},
- {130, &ACC_U0::LoadOpenContext, "LoadOpenContext"}, // 5.0.0+
+ {130, nullptr, "LoadOpenContext"}, // 5.0.0+
{131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index a58da4d5f..481e0d141 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -261,6 +261,31 @@ UUID ProfileManager::GetLastOpenedUser() const {
return last_opened_user;
}
+/// Gets the list of stored opened users.
+UserIDArray ProfileManager::GetStoredOpenedUsers() const {
+ UserIDArray output{};
+ std::ranges::transform(stored_opened_profiles, output.begin(), [](const ProfileInfo& p) {
+ if (p.is_open)
+ return p.user_uuid;
+ return Common::InvalidUUID;
+ });
+ std::stable_partition(output.begin(), output.end(),
+ [](const UUID& uuid) { return uuid.IsValid(); });
+ return output;
+}
+
+/// Captures the opened users, which can be queried across process launches with
+/// ListOpenContextStoredUsers.
+void ProfileManager::StoreOpenedUsers() {
+ size_t profile_index{};
+ stored_opened_profiles = {};
+ std::for_each(profiles.begin(), profiles.end(), [&](const auto& profile) {
+ if (profile.is_open) {
+ stored_opened_profiles[profile_index++] = profile;
+ }
+ });
+}
+
/// Return the users profile base and the unknown arbitary data.
bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
UserData& data) const {
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 135f7d0d5..993a5a57a 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -86,6 +86,8 @@ public:
UserIDArray GetOpenUsers() const;
UserIDArray GetAllUsers() const;
Common::UUID GetLastOpenedUser() const;
+ UserIDArray GetStoredOpenedUsers() const;
+ void StoreOpenedUsers();
bool CanSystemRegisterUser() const;
@@ -101,6 +103,7 @@ private:
bool RemoveProfileAtIndex(std::size_t index);
std::array<ProfileInfo, MAX_USERS> profiles{};
+ std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{};
std::size_t user_count{};
Common::UUID last_opened_user{};
};
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 44388655d..fa29db758 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -126,10 +126,12 @@ NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output)
LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle);
return result;
}
+ bool is_out_io{};
ASSERT(system.CurrentProcess()
->PageTable()
- .LockForMapDeviceAddressSpace(handle_description->address, handle_description->size,
- Kernel::KMemoryPermission::None, true)
+ .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
+ handle_description->size,
+ Kernel::KMemoryPermission::None, true, false)
.IsSuccess());
std::memcpy(output.data(), &params, sizeof(params));
return result;
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 5db6588e4..5ab41c0c4 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -99,6 +99,12 @@ ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* se
ServiceFrameworkBase::~ServiceFrameworkBase() {
// Wait for other threads to release access before destroying
const auto guard = LockService();
+
+ if (named_port != nullptr) {
+ named_port->GetClientPort().Close();
+ named_port->GetServerPort().Close();
+ named_port = nullptr;
+ }
}
void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
@@ -113,15 +119,16 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
Kernel::KClientPort& ServiceFrameworkBase::CreatePort() {
const auto guard = LockService();
- ASSERT(!service_registered);
+ if (named_port == nullptr) {
+ ASSERT(!service_registered);
- auto* port = Kernel::KPort::Create(kernel);
- port->Initialize(max_sessions, false, service_name);
- port->GetServerPort().SetSessionHandler(shared_from_this());
+ named_port = Kernel::KPort::Create(kernel);
+ named_port->Initialize(max_sessions, false, service_name);
- service_registered = true;
+ service_registered = true;
+ }
- return port->GetClientPort();
+ return named_port->GetClientPort();
}
void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) {
@@ -199,7 +206,6 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
switch (ctx.GetCommandType()) {
case IPC::CommandType::Close:
case IPC::CommandType::TIPC_Close: {
- session.Close();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
result = IPC::ERR_REMOTE_PROCESS_DEAD;
@@ -244,6 +250,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory);
+ system.Kernel().RegisterInterfaceForNamedService("sm:", SM::ServiceManager::SessionHandler);
Account::InstallInterfaces(system);
AM::InstallInterfaces(*sm, *nv_flinger, system);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index ec9deeee4..22e2119d7 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -20,6 +20,7 @@ class System;
namespace Kernel {
class HLERequestContext;
class KClientPort;
+class KPort;
class KServerSession;
class ServiceThread;
} // namespace Kernel
@@ -98,6 +99,9 @@ protected:
/// Identifier string used to connect to the service.
std::string service_name;
+ /// Port used by ManageNamedPort.
+ Kernel::KPort* named_port{};
+
private:
template <typename T>
friend class ServiceFramework;
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index e2b8d8720..84720094f 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -23,7 +23,13 @@ constexpr Result ERR_INVALID_NAME(ErrorModule::SM, 6);
constexpr Result ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {}
-ServiceManager::~ServiceManager() = default;
+
+ServiceManager::~ServiceManager() {
+ for (auto& [name, port] : service_ports) {
+ port->GetClientPort().Close();
+ port->GetServerPort().Close();
+ }
+}
void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
controller_interface->InvokeRequest(context);
@@ -43,6 +49,10 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core
return self.sm_interface->CreatePort();
}
+void ServiceManager::SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port) {
+ self.sm_interface->AcceptSession(server_port);
+}
+
Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
Kernel::SessionRequestHandlerPtr handler) {
@@ -53,7 +63,11 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
return ERR_ALREADY_REGISTERED;
}
- registered_services.emplace(std::move(name), handler);
+ auto* port = Kernel::KPort::Create(kernel);
+ port->Initialize(ServerSessionCountMax, false, name);
+
+ service_ports.emplace(name, port);
+ registered_services.emplace(name, handler);
return ResultSuccess;
}
@@ -68,24 +82,20 @@ Result ServiceManager::UnregisterService(const std::string& name) {
}
registered_services.erase(iter);
+ service_ports.erase(name);
+
return ResultSuccess;
}
ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
CASCADE_CODE(ValidateServiceName(name));
- auto it = registered_services.find(name);
- if (it == registered_services.end()) {
+ auto it = service_ports.find(name);
+ if (it == service_ports.end()) {
LOG_ERROR(Service_SM, "Server is not registered! service={}", name);
return ERR_SERVICE_NOT_REGISTERED;
}
- auto* port = Kernel::KPort::Create(kernel);
-
- port->Initialize(ServerSessionCountMax, false, name);
- auto handler = it->second;
- port->GetServerPort().SetSessionHandler(std::move(handler));
-
- return port;
+ return it->second;
}
/**
@@ -144,23 +154,20 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
// Find the named port.
auto port_result = service_manager.GetServicePort(name);
- if (port_result.Failed()) {
+ auto service = service_manager.GetService<Kernel::SessionRequestHandler>(name);
+ if (port_result.Failed() || !service) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw);
return port_result.Code();
}
auto& port = port_result.Unwrap();
- SCOPE_EXIT({ port->GetClientPort().Close(); });
-
- kernel.RegisterServerObject(&port->GetServerPort());
// Create a new session.
Kernel::KClientSession* session{};
- if (const auto result = port->GetClientPort().CreateSession(
- std::addressof(session), std::make_shared<Kernel::SessionRequestManager>(kernel));
- result.IsError()) {
+ if (const auto result = port->GetClientPort().CreateSession(&session); result.IsError()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
return result;
}
+ service->AcceptSession(&port->GetServerPort());
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 878decc6f..02a5dde9e 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -51,6 +51,7 @@ private:
class ServiceManager {
public:
static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system);
+ static void SessionHandler(ServiceManager& self, Kernel::KServerPort* server_port);
explicit ServiceManager(Kernel::KernelCore& kernel_);
~ServiceManager();
@@ -78,6 +79,7 @@ private:
/// Map of registered services, retrieved using GetServicePort.
std::unordered_map<std::string, Kernel::SessionRequestHandlerPtr> registered_services;
+ std::unordered_map<std::string, Kernel::KPort*> service_ports;
/// Kernel context
Kernel::KernelCore& kernel;
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 273f79568..69e0fe808 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -15,10 +15,9 @@
namespace Service::SM {
void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
- ASSERT_MSG(!ctx.Session()->GetSessionRequestManager()->IsDomain(),
- "Session is already a domain");
+ ASSERT_MSG(!ctx.GetManager()->IsDomain(), "Session is already a domain");
LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId());
- ctx.Session()->GetSessionRequestManager()->ConvertToDomainOnRequestEnd();
+ ctx.GetManager()->ConvertToDomainOnRequestEnd();
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@@ -28,23 +27,35 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service, "called");
- auto& parent_session = *ctx.Session()->GetParent();
- auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort();
- auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
+ auto& process = *ctx.GetThread().GetOwnerProcess();
+ auto session_manager = ctx.GetManager();
- // Create a session.
- Kernel::KClientSession* session{};
- const Result result = parent_port.CreateSession(std::addressof(session), session_manager);
- if (result.IsError()) {
- LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
+ // FIXME: this is duplicated from the SVC, it should just call it instead
+ // once this is a proper process
+
+ // Reserve a new session from the process resource limit.
+ Kernel::KScopedResourceReservation session_reservation(&process,
+ Kernel::LimitableResource::Sessions);
+ ASSERT(session_reservation.Succeeded());
+
+ // Create the session.
+ Kernel::KSession* session = Kernel::KSession::Create(system.Kernel());
+ ASSERT(session != nullptr);
+
+ // Initialize the session.
+ session->Initialize(nullptr, "");
+
+ // Commit the session reservation.
+ session_reservation.Commit();
+
+ // Register with manager.
+ session_manager->SessionHandler().RegisterSession(&session->GetServerSession(),
+ session_manager);
// We succeeded.
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(ResultSuccess);
- rb.PushMoveObjects(session);
+ rb.PushMoveObjects(session->GetClientSession());
}
void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {