diff --git a/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs b/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs index 283128fe8..5454e9327 100644 --- a/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs +++ b/Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs @@ -5,16 +5,25 @@ using Ryujinx.Common.Logging; using Ryujinx.Common.Utilities; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.Utilities; +using System; using System.Text; namespace Ryujinx.HLE.HOS.Services.Prepo { - [Service("prepo:a")] - [Service("prepo:a2")] - [Service("prepo:u")] + [Service("prepo:a", PrepoServicePermissionLevel.Admin)] // 1.0.0-5.1.0 + [Service("prepo:a2", PrepoServicePermissionLevel.Admin)] // 6.0.0+ + [Service("prepo:m", PrepoServicePermissionLevel.Manager)] + [Service("prepo:u", PrepoServicePermissionLevel.User)] + [Service("prepo:s", PrepoServicePermissionLevel.System)] class IPrepoService : IpcService { - public IPrepoService(ServiceCtx context) { } + private PrepoServicePermissionLevel _permission; + private ulong _systemSessionId; + + public IPrepoService(ServiceCtx context, PrepoServicePermissionLevel permission) + { + _permission = permission; + } [Command(10100)] // 1.0.0-5.1.0 [Command(10102)] // 6.0.0-9.2.0 @@ -22,6 +31,11 @@ namespace Ryujinx.HLE.HOS.Services.Prepo // SaveReport(u64, pid, buffer, buffer) public ResultCode SaveReport(ServiceCtx context) { + if (((int)_permission & 1) == 0) + { + return ResultCode.PermissionDenied; + } + // We don't care about the differences since we don't use the play report. return ProcessReport(context, withUserID: false); } @@ -32,6 +46,11 @@ namespace Ryujinx.HLE.HOS.Services.Prepo // SaveReportWithUser(nn::account::Uid, u64, pid, buffer, buffer) public ResultCode SaveReportWithUser(ServiceCtx context) { + if (((int)_permission & 1) == 0) + { + return ResultCode.PermissionDenied; + } + // We don't care about the differences since we don't use the play report. return ProcessReport(context, withUserID: true); } @@ -57,6 +76,29 @@ namespace Ryujinx.HLE.HOS.Services.Prepo return ResultCode.Success; } + [Command(10400)] // 9.0.0+ + // GetSystemSessionId() -> u64 + public ResultCode GetSystemSessionId(ServiceCtx context) + { + if (((int)_permission & 1) == 0) + { + return ResultCode.PermissionDenied; + } + + if (_systemSessionId == 0) + { + byte[] randomBuffer = new byte[8]; + + new Random().NextBytes(randomBuffer); + + _systemSessionId = BitConverter.ToUInt64(randomBuffer, 0); + } + + context.ResponseData.Write(_systemSessionId); + + return ResultCode.Success; + } + private ResultCode ProcessReport(ServiceCtx context, bool withUserID) { UserId userId = withUserID ? context.RequestData.ReadStruct() : new UserId(); diff --git a/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs index 1e110ea68..3199e2705 100644 --- a/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs +++ b/Ryujinx.HLE/HOS/Services/Prepo/ResultCode.cs @@ -7,9 +7,9 @@ namespace Ryujinx.HLE.HOS.Services.Prepo Success = 0, - InvalidArgument = (1 << ErrorCodeShift) | ModuleId, - InvalidState = (5 << ErrorCodeShift) | ModuleId, - InvalidBufferSize = (9 << ErrorCodeShift) | ModuleId, - Unknown1 = (90 << ErrorCodeShift) | ModuleId + InvalidArgument = (1 << ErrorCodeShift) | ModuleId, + InvalidState = (5 << ErrorCodeShift) | ModuleId, + InvalidBufferSize = (9 << ErrorCodeShift) | ModuleId, + PermissionDenied = (90 << ErrorCodeShift) | ModuleId } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs b/Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs new file mode 100644 index 000000000..624c3fde3 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Prepo/Types/PrepoServicePermissionLevel.cs @@ -0,0 +1,12 @@ +using System; + +namespace Ryujinx.HLE.HOS.Services.Prepo +{ + enum PrepoServicePermissionLevel + { + Admin = -1, + User = 1, + System = 2, + Manager = 6 + } +} \ No newline at end of file