diff options
Diffstat (limited to 'src/core/hle/service/sm/sm.cpp')
-rw-r--r-- | src/core/hle/service/sm/sm.cpp | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index a0a7206bb..88909504d 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -36,10 +36,11 @@ static ResultCode ValidateServiceName(const std::string& name) { return RESULT_SUCCESS; } -void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self) { +void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, + Kernel::KernelCore& kernel) { ASSERT(self->sm_interface.expired()); - auto sm = std::make_shared<SM>(self); + auto sm = std::make_shared<SM>(self, kernel); sm->InstallAsNamedPort(); self->sm_interface = sm; self->controller_interface = std::make_unique<Controller>(); @@ -114,8 +115,6 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { std::string name(name_buf.begin(), end); - // TODO(yuriks): Permission checks go here - auto client_port = service_manager->GetServicePort(name); if (client_port.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; @@ -127,14 +126,22 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { return; } - auto session = client_port.Unwrap()->Connect(); - ASSERT(session.Succeeded()); - if (session.Succeeded()) { - LOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId()); - IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; - rb.Push(session.Code()); - rb.PushMoveObjects(std::move(session).Unwrap()); + auto [client, server] = Kernel::Session::Create(kernel, name); + + const auto& server_port = client_port.Unwrap()->GetServerPort(); + if (server_port->GetHLEHandler()) { + server_port->GetHLEHandler()->ClientConnected(server); + } else { + server_port->AppendPendingSession(server); } + + // Wake the threads waiting on the ServerPort + server_port->WakeupAllWaitingThreads(); + + LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId()); + IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; + rb.Push(RESULT_SUCCESS); + rb.PushMoveObjects(std::move(client)); } void SM::RegisterService(Kernel::HLERequestContext& ctx) { @@ -178,8 +185,8 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) { rb.Push(service_manager->UnregisterService(name)); } -SM::SM(std::shared_ptr<ServiceManager> service_manager) - : ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) { +SM::SM(std::shared_ptr<ServiceManager> service_manager, Kernel::KernelCore& kernel) + : ServiceFramework{"sm:", 4}, service_manager{std::move(service_manager)}, kernel{kernel} { static const FunctionInfo functions[] = { {0x00000000, &SM::Initialize, "Initialize"}, {0x00000001, &SM::GetService, "GetService"}, |