early-access version 3408

This commit is contained in:
pineappleEA
2023-02-19 05:22:05 +01:00
parent 08eaaa3b39
commit 3da7802d0a
143 changed files with 1669 additions and 916 deletions

View File

@@ -126,6 +126,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
*result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
return ResultSuccess;
case InfoType::IsApplication:
LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
*result = true;
return ResultSuccess;
case InfoType::FreeThreadCount:
*result = process->GetFreeThreadCount();
return ResultSuccess;

View File

@@ -5,62 +5,47 @@
#include "core/core.h"
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {
/// Connect to an OS service given the port name, returns the handle to the port to out
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
auto& memory = system.Memory();
if (!memory.IsValidVirtualAddress(port_name_address)) {
LOG_ERROR(Kernel_SVC,
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
port_name_address);
return ResultNotFound;
}
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) {
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
static constexpr std::size_t PortNameMaxLength = 11;
// Read 1 char beyond the max allowed port name to detect names that are too long.
const std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
if (port_name.size() > PortNameMaxLength) {
LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
port_name.size());
return ResultOutOfRange;
}
std::array<char, KObjectName::NameLengthMax> name{};
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
// Validate that the name is valid.
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
// Get the current handle table.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Find the client port.
auto port = kernel.CreateNamedServicePort(port_name);
if (!port) {
LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ResultNotFound;
}
auto port = KObjectName::Find<KClientPort>(system.Kernel(), name.data());
R_UNLESS(port.IsNotNull(), ResultNotFound);
// Reserve a handle for the port.
// NOTE: Nintendo really does write directly to the output handle here.
R_TRY(handle_table.Reserve(out));
auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); });
ON_RESULT_FAILURE {
handle_table.Unreserve(*out);
};
// Create a session.
KClientSession* session{};
KClientSession* session;
R_TRY(port->CreateSession(std::addressof(session)));
kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
// Register the session in the table, close the extra reference.
handle_table.Register(*out, session);
session->Close();
// We succeeded.
handle_guard.Cancel();
return ResultSuccess;
R_SUCCEED();
}
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
@@ -74,10 +59,60 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
R_THROW(ResultNotImplemented);
}
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name,
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
int32_t max_sessions) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
// Copy the provided name from user memory to kernel memory.
std::array<char, KObjectName::NameLengthMax> name{};
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
// Validate that sessions and name are valid.
R_UNLESS(max_sessions >= 0, ResultOutOfRange);
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
if (max_sessions > 0) {
// Get the current handle table.
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Create a new port.
KPort* port = KPort::Create(system.Kernel());
R_UNLESS(port != nullptr, ResultOutOfResource);
// Initialize the new port.
port->Initialize(max_sessions, false, "");
// Register the port.
KPort::Register(system.Kernel(), port);
// Ensure that our only reference to the port is in the handle table when we're done.
SCOPE_EXIT({
port->GetClientPort().Close();
port->GetServerPort().Close();
});
// Register the handle in the table.
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
ON_RESULT_FAILURE {
handle_table.Remove(*out_server_handle);
};
// Create a new object name.
R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
name.data()));
} else /* if (max_sessions == 0) */ {
// Ensure that this else case is correct.
ASSERT(max_sessions == 0);
// If we're closing, there's no server handle.
*out_server_handle = InvalidHandle;
// Delete the object.
R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
}
R_SUCCEED();
}
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {