2019-01-18 14:26:39 -08:00
|
|
|
using Ryujinx.Common.Logging;
|
|
|
|
using Ryujinx.HLE.HOS.Ipc;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Process;
|
|
|
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
|
|
|
{
|
|
|
|
partial class SvcHandler
|
|
|
|
{
|
|
|
|
private struct HleIpcMessage
|
|
|
|
{
|
|
|
|
public KThread Thread { get; private set; }
|
|
|
|
public KClientSession Session { get; private set; }
|
|
|
|
public IpcMessage Message { get; private set; }
|
|
|
|
public long MessagePtr { get; private set; }
|
|
|
|
|
|
|
|
public HleIpcMessage(
|
|
|
|
KThread thread,
|
|
|
|
KClientSession session,
|
|
|
|
IpcMessage message,
|
|
|
|
long messagePtr)
|
|
|
|
{
|
|
|
|
Thread = thread;
|
|
|
|
Session = session;
|
|
|
|
Message = message;
|
|
|
|
MessagePtr = messagePtr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult ConnectToNamedPort64([R(1)] ulong namePtr, [R(1)] out int handle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return ConnectToNamedPort(namePtr, out handle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult ConnectToNamedPort32([R(1)] uint namePtr, [R(1)] out int handle)
|
|
|
|
{
|
|
|
|
return ConnectToNamedPort(namePtr, out handle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
|
|
|
|
{
|
|
|
|
handle = 0;
|
|
|
|
|
|
|
|
if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name))
|
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name.Length > 11)
|
|
|
|
{
|
|
|
|
return KernelResult.MaximumExceeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
KAutoObject autoObj = KAutoObject.FindNamedObject(_system, name);
|
|
|
|
|
|
|
|
if (!(autoObj is KClientPort clientPort))
|
|
|
|
{
|
|
|
|
return KernelResult.NotFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = clientPort.Connect(out KClientSession clientSession);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CancelHandleReservation(handle);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession);
|
|
|
|
|
|
|
|
clientSession.DecrementReferenceCount();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult SendSyncRequest64([R(0)] int handle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
Add a new JIT compiler for CPU code (#693)
* Start of the ARMeilleure project
* Refactoring around the old IRAdapter, now renamed to PreAllocator
* Optimize the LowestBitSet method
* Add CLZ support and fix CLS implementation
* Add missing Equals and GetHashCode overrides on some structs, misc small tweaks
* Implement the ByteSwap IR instruction, and some refactoring on the assembler
* Implement the DivideUI IR instruction and fix 64-bits IDIV
* Correct constant operand type on CSINC
* Move division instructions implementation to InstEmitDiv
* Fix destination type for the ConditionalSelect IR instruction
* Implement UMULH and SMULH, with new IR instructions
* Fix some issues with shift instructions
* Fix constant types for BFM instructions
* Fix up new tests using the new V128 struct
* Update tests
* Move DIV tests to a separate file
* Add support for calls, and some instructions that depends on them
* Start adding support for SIMD & FP types, along with some of the related ARM instructions
* Fix some typos and the divide instruction with FP operands
* Fix wrong method call on Clz_V
* Implement ARM FP & SIMD move instructions, Saddlv_V, and misc. fixes
* Implement SIMD logical instructions and more misc. fixes
* Fix PSRAD x86 instruction encoding, TRN, UABD and UABDL implementations
* Implement float conversion instruction, merge in LDj3SNuD fixes, and some other misc. fixes
* Implement SIMD shift instruction and fix Dup_V
* Add SCVTF and UCVTF (vector, fixed-point) variants to the opcode table
* Fix check with tolerance on tester
* Implement FP & SIMD comparison instructions, and some fixes
* Update FCVT (Scalar) encoding on the table to support the Half-float variants
* Support passing V128 structs, some cleanup on the register allocator, merge LDj3SNuD fixes
* Use old memory access methods, made a start on SIMD memory insts support, some fixes
* Fix float constant passed to functions, save and restore non-volatile XMM registers, other fixes
* Fix arguments count with struct return values, other fixes
* More instructions
* Misc. fixes and integrate LDj3SNuD fixes
* Update tests
* Add a faster linear scan allocator, unwinding support on windows, and other changes
* Update Ryujinx.HLE
* Update Ryujinx.Graphics
* Fix V128 return pointer passing, RCX is clobbered
* Update Ryujinx.Tests
* Update ITimeZoneService
* Stop using GetFunctionPointer as that can't be called from native code, misc. fixes and tweaks
* Use generic GetFunctionPointerForDelegate method and other tweaks
* Some refactoring on the code generator, assert on invalid operations and use a separate enum for intrinsics
* Remove some unused code on the assembler
* Fix REX.W prefix regression on float conversion instructions, add some sort of profiler
* Add hardware capability detection
* Fix regression on Sha1h and revert Fcm** changes
* Add SSE2-only paths on vector extract and insert, some refactoring on the pre-allocator
* Fix silly mistake introduced on last commit on CpuId
* Generate inline stack probes when the stack allocation is too large
* Initial support for the System-V ABI
* Support multiple destination operands
* Fix SSE2 VectorInsert8 path, and other fixes
* Change placement of XMM callee save and restore code to match other compilers
* Rename Dest to Destination and Inst to Instruction
* Fix a regression related to calls and the V128 type
* Add an extra space on comments to match code style
* Some refactoring
* Fix vector insert FP32 SSE2 path
* Port over the ARM32 instructions
* Avoid memory protection races on JIT Cache
* Another fix on VectorInsert FP32 (thanks to LDj3SNuD
* Float operands don't need to use the same register when VEX is supported
* Add a new register allocator, higher quality code for hot code (tier up), and other tweaks
* Some nits, small improvements on the pre allocator
* CpuThreadState is gone
* Allow changing CPU emulators with a config entry
* Add runtime identifiers on the ARMeilleure project
* Allow switching between CPUs through a config entry (pt. 2)
* Change win10-x64 to win-x64 on projects
* Update the Ryujinx project to use ARMeilleure
* Ensure that the selected register is valid on the hybrid allocator
* Allow exiting on returns to 0 (should fix test regression)
* Remove register assignments for most used variables on the hybrid allocator
* Do not use fixed registers as spill temp
* Add missing namespace and remove unneeded using
* Address PR feedback
* Fix types, etc
* Enable AssumeStrictAbiCompliance by default
* Ensure that Spill and Fill don't load or store any more than necessary
2019-08-08 11:56:22 -07:00
|
|
|
return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle);
|
2019-01-18 14:26:39 -08:00
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult SendSyncRequest32([R(0)] int handle)
|
|
|
|
{
|
|
|
|
return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle);
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong size, [R(2)] int handle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return SendSyncRequest(messagePtr, size, handle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint size, [R(2)] int handle)
|
|
|
|
{
|
|
|
|
return SendSyncRequest(messagePtr, size, handle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle)
|
|
|
|
{
|
2019-02-23 23:24:35 -08:00
|
|
|
byte[] messageData = _process.CpuMemory.ReadBytes((long)messagePtr, (long)size);
|
2019-01-18 14:26:39 -08:00
|
|
|
|
|
|
|
KClientSession clientSession = _process.HandleTable.GetObject<KClientSession>(handle);
|
|
|
|
|
|
|
|
if (clientSession == null || clientSession.Service == null)
|
|
|
|
{
|
|
|
|
return SendSyncRequest_(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clientSession != null)
|
|
|
|
{
|
|
|
|
_system.CriticalSection.Enter();
|
|
|
|
|
|
|
|
KThread currentThread = _system.Scheduler.GetCurrentThread();
|
|
|
|
|
|
|
|
currentThread.SignaledObj = null;
|
|
|
|
currentThread.ObjSyncResult = KernelResult.Success;
|
|
|
|
|
|
|
|
currentThread.Reschedule(ThreadSchedState.Paused);
|
|
|
|
|
|
|
|
IpcMessage message = new IpcMessage(messageData, (long)messagePtr);
|
|
|
|
|
|
|
|
ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
|
|
|
|
currentThread,
|
|
|
|
clientSession,
|
|
|
|
message,
|
|
|
|
(long)messagePtr));
|
|
|
|
|
|
|
|
_system.ThreadCounter.AddCount();
|
|
|
|
|
|
|
|
_system.CriticalSection.Leave();
|
|
|
|
|
|
|
|
return currentThread.ObjSyncResult;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!");
|
|
|
|
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ProcessIpcRequest(object state)
|
|
|
|
{
|
|
|
|
HleIpcMessage ipcMessage = (HleIpcMessage)state;
|
|
|
|
|
|
|
|
ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall(
|
|
|
|
_device,
|
|
|
|
_process,
|
2019-02-23 23:24:35 -08:00
|
|
|
_process.CpuMemory,
|
2019-03-14 20:37:54 -07:00
|
|
|
ipcMessage.Thread,
|
2019-01-18 14:26:39 -08:00
|
|
|
ipcMessage.Session,
|
|
|
|
ipcMessage.Message,
|
|
|
|
ipcMessage.MessagePtr);
|
|
|
|
|
|
|
|
_system.ThreadCounter.Signal();
|
|
|
|
|
|
|
|
ipcMessage.Thread.Reschedule(ThreadSchedState.Running);
|
|
|
|
}
|
|
|
|
|
|
|
|
private KernelResult SendSyncRequest_(int handle)
|
|
|
|
{
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KClientSession session = currentProcess.HandleTable.GetObject<KClientSession>(handle);
|
|
|
|
|
|
|
|
if (session == null)
|
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
return session.SendSyncRequest();
|
|
|
|
}
|
|
|
|
|
|
|
|
public KernelResult CreateSession64(
|
2020-01-12 18:04:28 -08:00
|
|
|
[R(2)] bool isLight,
|
|
|
|
[R(3)] ulong namePtr,
|
|
|
|
[R(1)] out int serverSessionHandle,
|
|
|
|
[R(2)] out int clientSessionHandle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult CreateSession32(
|
|
|
|
[R(2)] bool isLight,
|
|
|
|
[R(3)] uint namePtr,
|
|
|
|
[R(1)] out int serverSessionHandle,
|
|
|
|
[R(2)] out int clientSessionHandle)
|
|
|
|
{
|
|
|
|
return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult CreateSession(
|
|
|
|
bool isLight,
|
|
|
|
ulong namePtr,
|
|
|
|
out int serverSessionHandle,
|
|
|
|
out int clientSessionHandle)
|
|
|
|
{
|
|
|
|
serverSessionHandle = 0;
|
|
|
|
clientSessionHandle = 0;
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KResourceLimit resourceLimit = currentProcess.ResourceLimit;
|
|
|
|
|
|
|
|
KernelResult result = KernelResult.Success;
|
|
|
|
|
|
|
|
if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Session, 1))
|
|
|
|
{
|
|
|
|
return KernelResult.ResLimitExceeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isLight)
|
|
|
|
{
|
|
|
|
KLightSession session = new KLightSession(_system);
|
|
|
|
|
|
|
|
result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
|
|
|
|
|
|
|
|
if (result == KernelResult.Success)
|
|
|
|
{
|
|
|
|
result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CloseHandle(serverSessionHandle);
|
|
|
|
|
|
|
|
serverSessionHandle = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
session.ServerSession.DecrementReferenceCount();
|
|
|
|
session.ClientSession.DecrementReferenceCount();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KSession session = new KSession(_system);
|
|
|
|
|
|
|
|
result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
|
|
|
|
|
|
|
|
if (result == KernelResult.Success)
|
|
|
|
{
|
|
|
|
result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CloseHandle(serverSessionHandle);
|
|
|
|
|
|
|
|
serverSessionHandle = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
session.ServerSession.DecrementReferenceCount();
|
|
|
|
session.ClientSession.DecrementReferenceCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult AcceptSession64([R(1)] int portHandle, [R(1)] out int sessionHandle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return AcceptSession(portHandle, out sessionHandle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult AcceptSession32([R(1)] int portHandle, [R(1)] out int sessionHandle)
|
|
|
|
{
|
|
|
|
return AcceptSession(portHandle, out sessionHandle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult AcceptSession(int portHandle, out int sessionHandle)
|
|
|
|
{
|
|
|
|
sessionHandle = 0;
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KServerPort serverPort = currentProcess.HandleTable.GetObject<KServerPort>(portHandle);
|
|
|
|
|
|
|
|
if (serverPort == null)
|
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
KAutoObject session;
|
|
|
|
|
|
|
|
if (serverPort.IsLight)
|
|
|
|
{
|
|
|
|
session = serverPort.AcceptIncomingLightConnection();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
session = serverPort.AcceptIncomingConnection();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session != null)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.SetReservedHandleObj(handle, session);
|
|
|
|
|
|
|
|
session.DecrementReferenceCount();
|
|
|
|
|
|
|
|
sessionHandle = handle;
|
|
|
|
|
|
|
|
result = KernelResult.Success;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CancelHandleReservation(handle);
|
|
|
|
|
|
|
|
result = KernelResult.NotFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public KernelResult ReplyAndReceive64(
|
2020-01-12 18:04:28 -08:00
|
|
|
[R(1)] ulong handlesPtr,
|
|
|
|
[R(2)] int handlesCount,
|
|
|
|
[R(3)] int replyTargetHandle,
|
|
|
|
[R(4)] long timeout,
|
|
|
|
[R(1)] out int handleIndex)
|
2020-01-19 14:21:53 -08:00
|
|
|
{
|
|
|
|
return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
public KernelResult ReplyAndReceive32(
|
|
|
|
[R(0)] uint timeoutLow,
|
|
|
|
[R(1)] ulong handlesPtr,
|
|
|
|
[R(2)] int handlesCount,
|
|
|
|
[R(3)] int replyTargetHandle,
|
|
|
|
[R(4)] uint timeoutHigh,
|
|
|
|
[R(1)] out int handleIndex)
|
|
|
|
{
|
|
|
|
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
|
|
|
|
|
|
|
|
return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
public KernelResult ReplyAndReceive(
|
|
|
|
ulong handlesPtr,
|
|
|
|
int handlesCount,
|
|
|
|
int replyTargetHandle,
|
|
|
|
long timeout,
|
|
|
|
out int handleIndex)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
handleIndex = 0;
|
|
|
|
|
|
|
|
if ((uint)handlesCount > 0x40)
|
|
|
|
{
|
|
|
|
return KernelResult.MaximumExceeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
ulong copySize = (ulong)((long)handlesCount * 4);
|
|
|
|
|
|
|
|
if (!currentProcess.MemoryManager.InsideAddrSpace(handlesPtr, copySize))
|
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handlesPtr + copySize < handlesPtr)
|
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
int[] handles = new int[handlesCount];
|
|
|
|
|
|
|
|
if (!KernelTransfer.UserToKernelInt32Array(_system, handlesPtr, handles))
|
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount];
|
|
|
|
|
|
|
|
for (int index = 0; index < handlesCount; index++)
|
|
|
|
{
|
|
|
|
KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]);
|
|
|
|
|
|
|
|
if (obj == null)
|
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
syncObjs[index] = obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
KernelResult result;
|
|
|
|
|
|
|
|
if (replyTargetHandle != 0)
|
|
|
|
{
|
|
|
|
KServerSession replyTarget = currentProcess.HandleTable.GetObject<KServerSession>(replyTargetHandle);
|
|
|
|
|
|
|
|
if (replyTarget == null)
|
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = replyTarget.Reply();
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((result = _system.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == KernelResult.Success)
|
|
|
|
{
|
|
|
|
KServerSession session = currentProcess.HandleTable.GetObject<KServerSession>(handles[handleIndex]);
|
|
|
|
|
|
|
|
if (session == null)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((result = session.Receive()) != KernelResult.NotFound)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public KernelResult CreatePort64(
|
2020-01-12 18:04:28 -08:00
|
|
|
[R(2)] int maxSessions,
|
|
|
|
[R(3)] bool isLight,
|
|
|
|
[R(4)] ulong namePtr,
|
|
|
|
[R(1)] out int serverPortHandle,
|
|
|
|
[R(2)] out int clientPortHandle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult CreatePort32(
|
|
|
|
[R(0)] uint namePtr,
|
|
|
|
[R(2)] int maxSessions,
|
|
|
|
[R(3)] bool isLight,
|
|
|
|
[R(1)] out int serverPortHandle,
|
|
|
|
[R(2)] out int clientPortHandle)
|
|
|
|
{
|
|
|
|
return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult CreatePort(
|
|
|
|
int maxSessions,
|
|
|
|
bool isLight,
|
|
|
|
ulong namePtr,
|
|
|
|
out int serverPortHandle,
|
|
|
|
out int clientPortHandle)
|
|
|
|
{
|
|
|
|
serverPortHandle = clientPortHandle = 0;
|
|
|
|
|
|
|
|
if (maxSessions < 1)
|
|
|
|
{
|
|
|
|
return KernelResult.MaximumExceeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
KPort port = new KPort(_system, maxSessions, isLight, (long)namePtr);
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CloseHandle(clientPortHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult ManageNamedPort64([R(1)] ulong namePtr, [R(2)] int maxSessions, [R(1)] out int handle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return ManageNamedPort(namePtr, maxSessions, out handle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult ManageNamedPort32([R(1)] uint namePtr, [R(2)] int maxSessions, [R(1)] out int handle)
|
|
|
|
{
|
|
|
|
return ManageNamedPort(namePtr, maxSessions, out handle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle)
|
|
|
|
{
|
|
|
|
handle = 0;
|
|
|
|
|
|
|
|
if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name))
|
|
|
|
{
|
|
|
|
return KernelResult.UserCopyFailed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxSessions < 0 || name.Length > 11)
|
|
|
|
{
|
|
|
|
return KernelResult.MaximumExceeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxSessions == 0)
|
|
|
|
{
|
|
|
|
return KClientPort.RemoveName(_system, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
KPort port = new KPort(_system, maxSessions, false, 0);
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = port.ClientPort.SetName(name);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CloseHandle(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-12 18:04:28 -08:00
|
|
|
public KernelResult ConnectToPort64([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle)
|
2019-01-18 14:26:39 -08:00
|
|
|
{
|
|
|
|
return ConnectToPort(clientPortHandle, out clientSessionHandle);
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:21:53 -08:00
|
|
|
public KernelResult ConnectToPort32([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle)
|
|
|
|
{
|
|
|
|
return ConnectToPort(clientPortHandle, out clientSessionHandle);
|
|
|
|
}
|
|
|
|
|
2019-01-18 14:26:39 -08:00
|
|
|
private KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle)
|
|
|
|
{
|
|
|
|
clientSessionHandle = 0;
|
|
|
|
|
|
|
|
KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
|
|
|
|
|
|
|
|
KClientPort clientPort = currentProcess.HandleTable.GetObject<KClientPort>(clientPortHandle);
|
|
|
|
|
|
|
|
if (clientPort == null)
|
|
|
|
{
|
|
|
|
return KernelResult.InvalidHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle);
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
KAutoObject session;
|
|
|
|
|
|
|
|
if (clientPort.IsLight)
|
|
|
|
{
|
|
|
|
result = clientPort.ConnectLight(out KLightClientSession clientSession);
|
|
|
|
|
|
|
|
session = clientSession;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = clientPort.Connect(out KClientSession clientSession);
|
|
|
|
|
|
|
|
session = clientSession;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != KernelResult.Success)
|
|
|
|
{
|
|
|
|
currentProcess.HandleTable.CancelHandleReservation(handle);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentProcess.HandleTable.SetReservedHandleObj(handle, session);
|
|
|
|
|
|
|
|
session.DecrementReferenceCount();
|
|
|
|
|
|
|
|
clientSessionHandle = handle;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|