SvcSystem.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. using ChocolArm64.Memory;
  2. using ChocolArm64.State;
  3. using Ryujinx.Common;
  4. using Ryujinx.Common.Logging;
  5. using Ryujinx.HLE.Exceptions;
  6. using Ryujinx.HLE.HOS.Ipc;
  7. using Ryujinx.HLE.HOS.Services;
  8. using System;
  9. using System.Threading;
  10. using static Ryujinx.HLE.HOS.ErrorCode;
  11. namespace Ryujinx.HLE.HOS.Kernel
  12. {
  13. partial class SvcHandler
  14. {
  15. private void SvcExitProcess(CpuThreadState ThreadState)
  16. {
  17. System.Scheduler.GetCurrentProcess().Terminate();
  18. }
  19. private void SignalEvent64(CpuThreadState ThreadState)
  20. {
  21. ThreadState.X0 = (ulong)SignalEvent((int)ThreadState.X0);
  22. }
  23. private KernelResult SignalEvent(int Handle)
  24. {
  25. KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
  26. KernelResult Result;
  27. if (WritableEvent != null)
  28. {
  29. WritableEvent.Signal();
  30. Result = KernelResult.Success;
  31. }
  32. else
  33. {
  34. Result = KernelResult.InvalidHandle;
  35. }
  36. if (Result != KernelResult.Success)
  37. {
  38. Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
  39. }
  40. return Result;
  41. }
  42. private void ClearEvent64(CpuThreadState ThreadState)
  43. {
  44. ThreadState.X0 = (ulong)ClearEvent((int)ThreadState.X0);
  45. }
  46. private KernelResult ClearEvent(int Handle)
  47. {
  48. KernelResult Result;
  49. KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
  50. if (WritableEvent == null)
  51. {
  52. KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle);
  53. Result = ReadableEvent?.Clear() ?? KernelResult.InvalidHandle;
  54. }
  55. else
  56. {
  57. Result = WritableEvent.Clear();
  58. }
  59. if (Result != KernelResult.Success)
  60. {
  61. Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
  62. }
  63. return Result;
  64. }
  65. private void SvcCloseHandle(CpuThreadState ThreadState)
  66. {
  67. int Handle = (int)ThreadState.X0;
  68. object Obj = Process.HandleTable.GetObject<object>(Handle);
  69. Process.HandleTable.CloseHandle(Handle);
  70. if (Obj == null)
  71. {
  72. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
  73. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  74. return;
  75. }
  76. if (Obj is KSession Session)
  77. {
  78. Session.Dispose();
  79. }
  80. else if (Obj is KTransferMemory TransferMemory)
  81. {
  82. Process.MemoryManager.ResetTransferMemory(
  83. TransferMemory.Address,
  84. TransferMemory.Size);
  85. }
  86. ThreadState.X0 = 0;
  87. }
  88. private void ResetSignal64(CpuThreadState ThreadState)
  89. {
  90. ThreadState.X0 = (ulong)ResetSignal((int)ThreadState.X0);
  91. }
  92. private KernelResult ResetSignal(int Handle)
  93. {
  94. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  95. KReadableEvent ReadableEvent = CurrentProcess.HandleTable.GetObject<KReadableEvent>(Handle);
  96. KernelResult Result;
  97. if (ReadableEvent != null)
  98. {
  99. Result = ReadableEvent.ClearIfSignaled();
  100. }
  101. else
  102. {
  103. KProcess Process = CurrentProcess.HandleTable.GetKProcess(Handle);
  104. if (Process != null)
  105. {
  106. Result = Process.ClearIfNotExited();
  107. }
  108. else
  109. {
  110. Result = KernelResult.InvalidHandle;
  111. }
  112. }
  113. if (Result == KernelResult.InvalidState)
  114. {
  115. Logger.PrintDebug(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
  116. }
  117. else if (Result != KernelResult.Success)
  118. {
  119. Logger.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
  120. }
  121. return Result;
  122. }
  123. private void SvcGetSystemTick(CpuThreadState ThreadState)
  124. {
  125. ThreadState.X0 = ThreadState.CntpctEl0;
  126. }
  127. private void SvcConnectToNamedPort(CpuThreadState ThreadState)
  128. {
  129. long StackPtr = (long)ThreadState.X0;
  130. long NamePtr = (long)ThreadState.X1;
  131. string Name = MemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
  132. //TODO: Validate that app has perms to access the service, and that the service
  133. //actually exists, return error codes otherwise.
  134. KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
  135. if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
  136. {
  137. throw new InvalidOperationException("Out of handles!");
  138. }
  139. ThreadState.X0 = 0;
  140. ThreadState.X1 = (uint)Handle;
  141. }
  142. private void SvcSendSyncRequest(CpuThreadState ThreadState)
  143. {
  144. SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0);
  145. }
  146. private void SvcSendSyncRequestWithUserBuffer(CpuThreadState ThreadState)
  147. {
  148. SendSyncRequest(
  149. ThreadState,
  150. (long)ThreadState.X0,
  151. (long)ThreadState.X1,
  152. (int)ThreadState.X2);
  153. }
  154. private void SendSyncRequest(CpuThreadState ThreadState, long MessagePtr, long Size, int Handle)
  155. {
  156. byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
  157. KSession Session = Process.HandleTable.GetObject<KSession>(Handle);
  158. if (Session != null)
  159. {
  160. System.CriticalSection.Enter();
  161. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  162. CurrentThread.SignaledObj = null;
  163. CurrentThread.ObjSyncResult = 0;
  164. CurrentThread.Reschedule(ThreadSchedState.Paused);
  165. IpcMessage Message = new IpcMessage(MessageData, MessagePtr);
  166. ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
  167. CurrentThread,
  168. Session,
  169. Message,
  170. MessagePtr));
  171. System.ThreadCounter.AddCount();
  172. System.CriticalSection.Leave();
  173. ThreadState.X0 = (ulong)CurrentThread.ObjSyncResult;
  174. }
  175. else
  176. {
  177. Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{Handle:x8}!");
  178. ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
  179. }
  180. }
  181. private void ProcessIpcRequest(object State)
  182. {
  183. HleIpcMessage IpcMessage = (HleIpcMessage)State;
  184. IpcMessage.Thread.ObjSyncResult = (int)IpcHandler.IpcCall(
  185. Device,
  186. Process,
  187. Memory,
  188. IpcMessage.Session,
  189. IpcMessage.Message,
  190. IpcMessage.MessagePtr);
  191. System.ThreadCounter.Signal();
  192. IpcMessage.Thread.Reschedule(ThreadSchedState.Running);
  193. }
  194. private void GetProcessId64(CpuThreadState ThreadState)
  195. {
  196. int Handle = (int)ThreadState.X1;
  197. KernelResult Result = GetProcessId(Handle, out long Pid);
  198. ThreadState.X0 = (ulong)Result;
  199. ThreadState.X1 = (ulong)Pid;
  200. }
  201. private KernelResult GetProcessId(int Handle, out long Pid)
  202. {
  203. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  204. KProcess Process = CurrentProcess.HandleTable.GetKProcess(Handle);
  205. if (Process == null)
  206. {
  207. KThread Thread = CurrentProcess.HandleTable.GetKThread(Handle);
  208. if (Thread != null)
  209. {
  210. Process = Thread.Owner;
  211. }
  212. //TODO: KDebugEvent.
  213. }
  214. Pid = Process?.Pid ?? 0;
  215. return Process != null
  216. ? KernelResult.Success
  217. : KernelResult.InvalidHandle;
  218. }
  219. private void SvcBreak(CpuThreadState ThreadState)
  220. {
  221. long Reason = (long)ThreadState.X0;
  222. long Unknown = (long)ThreadState.X1;
  223. long Info = (long)ThreadState.X2;
  224. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  225. if ((Reason & (1 << 31)) == 0)
  226. {
  227. CurrentThread.PrintGuestStackTrace();
  228. throw new GuestBrokeExecutionException();
  229. }
  230. else
  231. {
  232. Logger.PrintInfo(LogClass.KernelSvc, "Debugger triggered.");
  233. CurrentThread.PrintGuestStackTrace();
  234. }
  235. }
  236. private void SvcOutputDebugString(CpuThreadState ThreadState)
  237. {
  238. long Position = (long)ThreadState.X0;
  239. long Size = (long)ThreadState.X1;
  240. string Str = MemoryHelper.ReadAsciiString(Memory, Position, Size);
  241. Logger.PrintWarning(LogClass.KernelSvc, Str);
  242. ThreadState.X0 = 0;
  243. }
  244. private void GetInfo64(CpuThreadState ThreadState)
  245. {
  246. long StackPtr = (long)ThreadState.X0;
  247. uint Id = (uint)ThreadState.X1;
  248. int Handle = (int)ThreadState.X2;
  249. long SubId = (long)ThreadState.X3;
  250. KernelResult Result = GetInfo(Id, Handle, SubId, out long Value);
  251. ThreadState.X0 = (ulong)Result;
  252. ThreadState.X1 = (ulong)Value;
  253. }
  254. private KernelResult GetInfo(uint Id, int Handle, long SubId, out long Value)
  255. {
  256. Value = 0;
  257. switch (Id)
  258. {
  259. case 0:
  260. case 1:
  261. case 2:
  262. case 3:
  263. case 4:
  264. case 5:
  265. case 6:
  266. case 7:
  267. case 12:
  268. case 13:
  269. case 14:
  270. case 15:
  271. case 16:
  272. case 17:
  273. case 18:
  274. case 20:
  275. case 21:
  276. case 22:
  277. {
  278. if (SubId != 0)
  279. {
  280. return KernelResult.InvalidCombination;
  281. }
  282. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  283. KProcess Process = CurrentProcess.HandleTable.GetKProcess(Handle);
  284. if (Process == null)
  285. {
  286. return KernelResult.InvalidHandle;
  287. }
  288. switch (Id)
  289. {
  290. case 0: Value = Process.Capabilities.AllowedCpuCoresMask; break;
  291. case 1: Value = Process.Capabilities.AllowedThreadPriosMask; break;
  292. case 2: Value = (long)Process.MemoryManager.AliasRegionStart; break;
  293. case 3: Value = (long)(Process.MemoryManager.AliasRegionEnd -
  294. Process.MemoryManager.AliasRegionStart); break;
  295. case 4: Value = (long)Process.MemoryManager.HeapRegionStart; break;
  296. case 5: Value = (long)(Process.MemoryManager.HeapRegionEnd -
  297. Process.MemoryManager.HeapRegionStart); break;
  298. case 6: Value = (long)Process.GetMemoryCapacity(); break;
  299. case 7: Value = (long)Process.GetMemoryUsage(); break;
  300. case 12: Value = (long)Process.MemoryManager.GetAddrSpaceBaseAddr(); break;
  301. case 13: Value = (long)Process.MemoryManager.GetAddrSpaceSize(); break;
  302. case 14: Value = (long)Process.MemoryManager.StackRegionStart; break;
  303. case 15: Value = (long)(Process.MemoryManager.StackRegionEnd -
  304. Process.MemoryManager.StackRegionStart); break;
  305. case 16: Value = (long)Process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break;
  306. case 17:
  307. if (Process.PersonalMmHeapPagesCount != 0)
  308. {
  309. Value = Process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize;
  310. }
  311. break;
  312. case 18: Value = Process.TitleId; break;
  313. case 20: Value = (long)Process.UserExceptionContextAddress; break;
  314. case 21: Value = (long)Process.GetMemoryCapacityWithoutPersonalMmHeap(); break;
  315. case 22: Value = (long)Process.GetMemoryUsageWithoutPersonalMmHeap(); break;
  316. }
  317. break;
  318. }
  319. case 8:
  320. {
  321. if (Handle != 0)
  322. {
  323. return KernelResult.InvalidHandle;
  324. }
  325. if (SubId != 0)
  326. {
  327. return KernelResult.InvalidCombination;
  328. }
  329. Value = System.Scheduler.GetCurrentProcess().Debug ? 1 : 0;
  330. break;
  331. }
  332. case 9:
  333. {
  334. if (Handle != 0)
  335. {
  336. return KernelResult.InvalidHandle;
  337. }
  338. if (SubId != 0)
  339. {
  340. return KernelResult.InvalidCombination;
  341. }
  342. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  343. if (CurrentProcess.ResourceLimit != null)
  344. {
  345. KHandleTable HandleTable = CurrentProcess.HandleTable;
  346. KResourceLimit ResourceLimit = CurrentProcess.ResourceLimit;
  347. KernelResult Result = HandleTable.GenerateHandle(ResourceLimit, out int ResLimHandle);
  348. if (Result != KernelResult.Success)
  349. {
  350. return Result;
  351. }
  352. Value = (uint)ResLimHandle;
  353. }
  354. break;
  355. }
  356. case 10:
  357. {
  358. if (Handle != 0)
  359. {
  360. return KernelResult.InvalidHandle;
  361. }
  362. int CurrentCore = System.Scheduler.GetCurrentThread().CurrentCore;
  363. if (SubId != -1 && SubId != CurrentCore)
  364. {
  365. return KernelResult.InvalidCombination;
  366. }
  367. Value = System.Scheduler.CoreContexts[CurrentCore].TotalIdleTimeTicks;
  368. break;
  369. }
  370. case 11:
  371. {
  372. if (Handle != 0)
  373. {
  374. return KernelResult.InvalidHandle;
  375. }
  376. if ((ulong)SubId > 3)
  377. {
  378. return KernelResult.InvalidCombination;
  379. }
  380. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  381. Value = CurrentProcess.RandomEntropy[SubId];
  382. break;
  383. }
  384. case 0xf0000002u:
  385. {
  386. if (SubId < -1 || SubId > 3)
  387. {
  388. return KernelResult.InvalidCombination;
  389. }
  390. KThread Thread = System.Scheduler.GetCurrentProcess().HandleTable.GetKThread(Handle);
  391. if (Thread == null)
  392. {
  393. return KernelResult.InvalidHandle;
  394. }
  395. KThread CurrentThread = System.Scheduler.GetCurrentThread();
  396. int CurrentCore = CurrentThread.CurrentCore;
  397. if (SubId != -1 && SubId != CurrentCore)
  398. {
  399. return KernelResult.Success;
  400. }
  401. KCoreContext CoreContext = System.Scheduler.CoreContexts[CurrentCore];
  402. long TimeDelta = PerformanceCounter.ElapsedMilliseconds - CoreContext.LastContextSwitchTime;
  403. if (SubId != -1)
  404. {
  405. Value = KTimeManager.ConvertMillisecondsToTicks(TimeDelta);
  406. }
  407. else
  408. {
  409. long TotalTimeRunning = Thread.TotalTimeRunning;
  410. if (Thread == CurrentThread)
  411. {
  412. TotalTimeRunning += TimeDelta;
  413. }
  414. Value = KTimeManager.ConvertMillisecondsToTicks(TotalTimeRunning);
  415. }
  416. break;
  417. }
  418. default: return KernelResult.InvalidEnumValue;
  419. }
  420. return KernelResult.Success;
  421. }
  422. private void CreateEvent64(CpuThreadState State)
  423. {
  424. KernelResult Result = CreateEvent(out int WEventHandle, out int REventHandle);
  425. State.X0 = (ulong)Result;
  426. State.X1 = (ulong)WEventHandle;
  427. State.X2 = (ulong)REventHandle;
  428. }
  429. private KernelResult CreateEvent(out int WEventHandle, out int REventHandle)
  430. {
  431. KEvent Event = new KEvent(System);
  432. KernelResult Result = Process.HandleTable.GenerateHandle(Event.WritableEvent, out WEventHandle);
  433. if (Result == KernelResult.Success)
  434. {
  435. Result = Process.HandleTable.GenerateHandle(Event.ReadableEvent, out REventHandle);
  436. if (Result != KernelResult.Success)
  437. {
  438. Process.HandleTable.CloseHandle(WEventHandle);
  439. }
  440. }
  441. else
  442. {
  443. REventHandle = 0;
  444. }
  445. return Result;
  446. }
  447. private void GetProcessList64(CpuThreadState State)
  448. {
  449. ulong Address = State.X1;
  450. int MaxOut = (int)State.X2;
  451. KernelResult Result = GetProcessList(Address, MaxOut, out int Count);
  452. State.X0 = (ulong)Result;
  453. State.X1 = (ulong)Count;
  454. }
  455. private KernelResult GetProcessList(ulong Address, int MaxCount, out int Count)
  456. {
  457. Count = 0;
  458. if ((MaxCount >> 28) != 0)
  459. {
  460. return KernelResult.MaximumExceeded;
  461. }
  462. if (MaxCount != 0)
  463. {
  464. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  465. ulong CopySize = (ulong)MaxCount * 8;
  466. if (Address + CopySize <= Address)
  467. {
  468. return KernelResult.InvalidMemState;
  469. }
  470. if (CurrentProcess.MemoryManager.OutsideAddrSpace(Address, CopySize))
  471. {
  472. return KernelResult.InvalidMemState;
  473. }
  474. }
  475. int CopyCount = 0;
  476. lock (System.Processes)
  477. {
  478. foreach (KProcess Process in System.Processes.Values)
  479. {
  480. if (CopyCount < MaxCount)
  481. {
  482. if (!KernelTransfer.KernelToUserInt64(System, (long)Address + CopyCount * 8, Process.Pid))
  483. {
  484. return KernelResult.UserCopyFailed;
  485. }
  486. }
  487. CopyCount++;
  488. }
  489. }
  490. Count = CopyCount;
  491. return KernelResult.Success;
  492. }
  493. private void GetSystemInfo64(CpuThreadState State)
  494. {
  495. uint Id = (uint)State.X1;
  496. int Handle = (int)State.X2;
  497. long SubId = (long)State.X3;
  498. KernelResult Result = GetSystemInfo(Id, Handle, SubId, out long Value);
  499. State.X0 = (ulong)Result;
  500. State.X1 = (ulong)Value;
  501. }
  502. private KernelResult GetSystemInfo(uint Id, int Handle, long SubId, out long Value)
  503. {
  504. Value = 0;
  505. if (Id > 2)
  506. {
  507. return KernelResult.InvalidEnumValue;
  508. }
  509. if (Handle != 0)
  510. {
  511. return KernelResult.InvalidHandle;
  512. }
  513. if (Id < 2)
  514. {
  515. if ((ulong)SubId > 3)
  516. {
  517. return KernelResult.InvalidCombination;
  518. }
  519. KMemoryRegionManager Region = System.MemoryRegions[SubId];
  520. switch (Id)
  521. {
  522. //Memory region capacity.
  523. case 0: Value = (long)Region.Size; break;
  524. //Memory region free space.
  525. case 1:
  526. {
  527. ulong FreePagesCount = Region.GetFreePages();
  528. Value = (long)(FreePagesCount * KMemoryManager.PageSize);
  529. break;
  530. }
  531. }
  532. }
  533. else /* if (Id == 2) */
  534. {
  535. if ((ulong)SubId > 1)
  536. {
  537. return KernelResult.InvalidCombination;
  538. }
  539. switch (SubId)
  540. {
  541. case 0: Value = System.PrivilegedProcessLowestId; break;
  542. case 1: Value = System.PrivilegedProcessHighestId; break;
  543. }
  544. }
  545. return KernelResult.Success;
  546. }
  547. private void CreatePort64(CpuThreadState State)
  548. {
  549. int MaxSessions = (int)State.X2;
  550. bool IsLight = (State.X3 & 1) != 0;
  551. long NameAddress = (long)State.X4;
  552. KernelResult Result = CreatePort(
  553. MaxSessions,
  554. IsLight,
  555. NameAddress,
  556. out int ServerPortHandle,
  557. out int ClientPortHandle);
  558. State.X0 = (ulong)Result;
  559. State.X1 = (ulong)ServerPortHandle;
  560. State.X2 = (ulong)ClientPortHandle;
  561. }
  562. private KernelResult CreatePort(
  563. int MaxSessions,
  564. bool IsLight,
  565. long NameAddress,
  566. out int ServerPortHandle,
  567. out int ClientPortHandle)
  568. {
  569. ServerPortHandle = ClientPortHandle = 0;
  570. if (MaxSessions < 1)
  571. {
  572. return KernelResult.MaximumExceeded;
  573. }
  574. KPort Port = new KPort(System);
  575. Port.Initialize(MaxSessions, IsLight, NameAddress);
  576. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  577. KernelResult Result = CurrentProcess.HandleTable.GenerateHandle(Port.ClientPort, out ClientPortHandle);
  578. if (Result != KernelResult.Success)
  579. {
  580. return Result;
  581. }
  582. Result = CurrentProcess.HandleTable.GenerateHandle(Port.ServerPort, out ServerPortHandle);
  583. if (Result != KernelResult.Success)
  584. {
  585. CurrentProcess.HandleTable.CloseHandle(ClientPortHandle);
  586. }
  587. return Result;
  588. }
  589. private void ManageNamedPort64(CpuThreadState State)
  590. {
  591. long NameAddress = (long)State.X1;
  592. int MaxSessions = (int)State.X2;
  593. KernelResult Result = ManageNamedPort(NameAddress, MaxSessions, out int Handle);
  594. State.X0 = (ulong)Result;
  595. State.X1 = (ulong)Handle;
  596. }
  597. private KernelResult ManageNamedPort(long NameAddress, int MaxSessions, out int Handle)
  598. {
  599. Handle = 0;
  600. if (!KernelTransfer.UserToKernelString(System, NameAddress, 12, out string Name))
  601. {
  602. return KernelResult.UserCopyFailed;
  603. }
  604. if (MaxSessions < 0 || Name.Length > 11)
  605. {
  606. return KernelResult.MaximumExceeded;
  607. }
  608. if (MaxSessions == 0)
  609. {
  610. return KClientPort.RemoveName(System, Name);
  611. }
  612. KPort Port = new KPort(System);
  613. KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
  614. KernelResult Result = CurrentProcess.HandleTable.GenerateHandle(Port.ServerPort, out Handle);
  615. if (Result != KernelResult.Success)
  616. {
  617. return Result;
  618. }
  619. Port.Initialize(MaxSessions, false, 0);
  620. Result = Port.SetName(Name);
  621. if (Result != KernelResult.Success)
  622. {
  623. CurrentProcess.HandleTable.CloseHandle(Handle);
  624. }
  625. return Result;
  626. }
  627. }
  628. }