diff options
Diffstat (limited to 'Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs')
-rw-r--r-- | Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs new file mode 100644 index 00000000..ea2ec650 --- /dev/null +++ b/Ryujinx.Horizon/Sdk/Sf/Hipc/HipcManager.cs @@ -0,0 +1,115 @@ +using Ryujinx.Horizon.Common; +using Ryujinx.Horizon.Sdk.Sf.Cmif; +using System; + +namespace Ryujinx.Horizon.Sdk.Sf.Hipc +{ + partial class HipcManager : IServiceObject + { + private readonly ServerDomainSessionManager _manager; + private readonly ServerSession _session; + + public HipcManager(ServerDomainSessionManager manager, ServerSession session) + { + _manager = manager; + _session = session; + } + + [CmifCommand(0)] + public Result ConvertCurrentObjectToDomain(out int objectId) + { + objectId = 0; + + var domain = _manager.Domain.AllocateDomainServiceObject(); + if (domain == null) + { + return HipcResult.OutOfDomains; + } + + bool succeeded = false; + + try + { + Span<int> objectIds = stackalloc int[1]; + + Result result = domain.ReserveIds(objectIds); + + if (result.IsFailure) + { + return result; + } + + objectId = objectIds[0]; + succeeded = true; + } + finally + { + if (!succeeded) + { + ServerDomainManager.DestroyDomainServiceObject(domain); + } + } + + domain.RegisterObject(objectId, _session.ServiceObjectHolder); + _session.ServiceObjectHolder = new ServiceObjectHolder(domain); + + return Result.Success; + } + + [CmifCommand(1)] + public Result CopyFromCurrentDomain([MoveHandle] out int clientHandle, int objectId) + { + clientHandle = 0; + + if (!(_session.ServiceObjectHolder.ServiceObject is DomainServiceObject domain)) + { + return HipcResult.TargetNotDomain; + } + + var obj = domain.GetObject(objectId); + if (obj == null) + { + return HipcResult.DomainObjectNotFound; + } + + Api.CreateSession(out int serverHandle, out clientHandle).AbortOnFailure(); + _manager.RegisterSession(serverHandle, obj).AbortOnFailure(); + + return Result.Success; + } + + [CmifCommand(2)] + public Result CloneCurrentObject([MoveHandle] out int clientHandle) + { + return CloneCurrentObjectImpl(out clientHandle, _manager); + } + + [CmifCommand(3)] + public void QueryPointerBufferSize(out ushort size) + { + size = (ushort)_session.PointerBuffer.Size; + } + + [CmifCommand(4)] + public Result CloneCurrentObjectEx([MoveHandle] out int clientHandle, uint tag) + { + return CloneCurrentObjectImpl(out clientHandle, _manager.GetSessionManagerByTag(tag)); + } + + private Result CloneCurrentObjectImpl(out int clientHandle, ServerSessionManager manager) + { + clientHandle = 0; + + var clone = _session.ServiceObjectHolder.Clone(); + if (clone == null) + { + return HipcResult.DomainObjectNotFound; + } + + Api.CreateSession(out int serverHandle, out clientHandle).AbortOnFailure(); + manager.RegisterSession(serverHandle, clone).AbortOnFailure(); + + return Result.Success; + } + } +} |