diff options
Diffstat (limited to 'src/core/hle/kernel/svc')
| -rw-r--r-- | src/core/hle/kernel/svc/svc_port.cpp | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp index 2b7cebde5..2f9bfcb52 100644 --- a/src/core/hle/kernel/svc/svc_port.cpp +++ b/src/core/hle/kernel/svc/svc_port.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/k_client_port.h" | 6 | #include "core/hle/kernel/k_client_port.h" |
| 7 | #include "core/hle/kernel/k_client_session.h" | 7 | #include "core/hle/kernel/k_client_session.h" |
| 8 | #include "core/hle/kernel/k_object_name.h" | ||
| 8 | #include "core/hle/kernel/k_port.h" | 9 | #include "core/hle/kernel/k_port.h" |
| 9 | #include "core/hle/kernel/k_process.h" | 10 | #include "core/hle/kernel/k_process.h" |
| 10 | #include "core/hle/kernel/svc.h" | 11 | #include "core/hle/kernel/svc.h" |
| @@ -74,10 +75,57 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) { | |||
| 74 | R_THROW(ResultNotImplemented); | 75 | R_THROW(ResultNotImplemented); |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name, | 78 | Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name, |
| 78 | int32_t max_sessions) { | 79 | int32_t max_sessions) { |
| 79 | UNIMPLEMENTED(); | 80 | // Copy the provided name from user memory to kernel memory. |
| 80 | R_THROW(ResultNotImplemented); | 81 | std::array<char, KObjectName::NameLengthMax> name{}; |
| 82 | system.Memory().ReadBlock(user_name, name.data(), sizeof(name)); | ||
| 83 | |||
| 84 | // Validate that sessions and name are valid. | ||
| 85 | R_UNLESS(max_sessions >= 0, ResultOutOfRange); | ||
| 86 | R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange); | ||
| 87 | |||
| 88 | if (max_sessions > 0) { | ||
| 89 | // Get the current handle table. | ||
| 90 | auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable(); | ||
| 91 | |||
| 92 | // Create a new port. | ||
| 93 | KPort* port = KPort::Create(system.Kernel()); | ||
| 94 | R_UNLESS(port != nullptr, ResultOutOfResource); | ||
| 95 | |||
| 96 | // Initialize the new port. | ||
| 97 | port->Initialize(max_sessions, false, ""); | ||
| 98 | |||
| 99 | // Register the port. | ||
| 100 | KPort::Register(system.Kernel(), port); | ||
| 101 | |||
| 102 | // Ensure that our only reference to the port is in the handle table when we're done. | ||
| 103 | SCOPE_EXIT({ | ||
| 104 | port->GetClientPort().Close(); | ||
| 105 | port->GetServerPort().Close(); | ||
| 106 | }); | ||
| 107 | |||
| 108 | // Register the handle in the table. | ||
| 109 | R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort()))); | ||
| 110 | ON_RESULT_FAILURE { | ||
| 111 | handle_table.Remove(*out_server_handle); | ||
| 112 | }; | ||
| 113 | |||
| 114 | // Create a new object name. | ||
| 115 | R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()), | ||
| 116 | name.data())); | ||
| 117 | } else /* if (max_sessions == 0) */ { | ||
| 118 | // Ensure that this else case is correct. | ||
| 119 | ASSERT(max_sessions == 0); | ||
| 120 | |||
| 121 | // If we're closing, there's no server handle. | ||
| 122 | *out_server_handle = InvalidHandle; | ||
| 123 | |||
| 124 | // Delete the object. | ||
| 125 | R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data())); | ||
| 126 | } | ||
| 127 | |||
| 128 | R_SUCCEED(); | ||
| 81 | } | 129 | } |
| 82 | 130 | ||
| 83 | Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) { | 131 | Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) { |