aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Account
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2019-09-19 02:45:11 +0200
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-09-19 10:45:11 +1000
commita0720b5681852f3d786d77bd3793b0359dea321c (patch)
tree9d8f61e540d1d1d827999902dad95e5c0c1e076e /Ryujinx.HLE/HOS/Services/Account
parent4af3101b22e6957d6aa48a2768566d658699f4ed (diff)
Refactoring HOS folder structure (#771)
* Refactoring HOS folder structure Refactoring HOS folder structure: - Added some subfolders when needed (Following structure decided in private). - Added some `Types` folders when needed. - Little cleanup here and there. - Add services placeholders for every HOS services (close #766 and #753). * Remove Types namespaces
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Account')
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/AccountUtils.cs67
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs294
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs40
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs80
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountState.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserProfile.cs37
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Dauth/IService.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/ResultCode.cs20
11 files changed, 578 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/AccountUtils.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/AccountUtils.cs
new file mode 100644
index 00000000..7a70025a
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/AccountUtils.cs
@@ -0,0 +1,67 @@
+using Ryujinx.HLE.Utilities;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ public class AccountUtils
+ {
+ private ConcurrentDictionary<string, UserProfile> _profiles;
+
+ internal UserProfile LastOpenedUser { get; private set; }
+
+ public AccountUtils()
+ {
+ _profiles = new ConcurrentDictionary<string, UserProfile>();
+ }
+
+ public void AddUser(UInt128 userId, string name)
+ {
+ UserProfile profile = new UserProfile(userId, name);
+
+ _profiles.AddOrUpdate(userId.ToString(), profile, (key, old) => profile);
+ }
+
+ public void OpenUser(UInt128 userId)
+ {
+ if (_profiles.TryGetValue(userId.ToString(), out UserProfile profile))
+ {
+ (LastOpenedUser = profile).AccountState = AccountState.Open;
+ }
+ }
+
+ public void CloseUser(UInt128 userId)
+ {
+ if (_profiles.TryGetValue(userId.ToString(), out UserProfile profile))
+ {
+ profile.AccountState = AccountState.Closed;
+ }
+ }
+
+ public int GetUserCount()
+ {
+ return _profiles.Count;
+ }
+
+ internal bool TryGetUser(UInt128 userId, out UserProfile profile)
+ {
+ return _profiles.TryGetValue(userId.ToString(), out profile);
+ }
+
+ internal IEnumerable<UserProfile> GetAllUsers()
+ {
+ return _profiles.Values;
+ }
+
+ internal IEnumerable<UserProfile> GetOpenedUsers()
+ {
+ return _profiles.Values.Where(x => x.AccountState == AccountState.Open);
+ }
+
+ internal UserProfile GetFirst()
+ {
+ return _profiles.First().Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs
new file mode 100644
index 00000000..9fb3fb9b
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ [Service("acc:su")]
+ class IAccountServiceForAdministrator : IpcService
+ {
+ public IAccountServiceForAdministrator(ServiceCtx context) { }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
new file mode 100644
index 00000000..84239539
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
@@ -0,0 +1,294 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Services.Arp;
+using Ryujinx.HLE.Utilities;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ [Service("acc:u0")]
+ class IAccountServiceForApplication : IpcService
+ {
+ private bool _userRegistrationRequestPermitted = false;
+
+ private ApplicationLaunchProperty _applicationLaunchProperty;
+
+ public IAccountServiceForApplication(ServiceCtx context) { }
+
+ [Command(0)]
+ // GetUserCount() -> i32
+ public ResultCode GetUserCount(ServiceCtx context)
+ {
+ context.ResponseData.Write(context.Device.System.State.Account.GetUserCount());
+
+ return ResultCode.Success;
+ }
+
+ [Command(1)]
+ // GetUserExistence(nn::account::Uid) -> bool
+ public ResultCode GetUserExistence(ServiceCtx context)
+ {
+ UInt128 userId = new UInt128(context.RequestData.ReadBytes(0x10));
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ context.ResponseData.Write(context.Device.System.State.Account.TryGetUser(userId, out _));
+
+ return ResultCode.Success;
+ }
+
+ [Command(2)]
+ // ListAllUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListAllUsers(ServiceCtx context)
+ {
+ return WriteUserList(context, context.Device.System.State.Account.GetAllUsers());
+ }
+
+ [Command(3)]
+ // ListOpenUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListOpenUsers(ServiceCtx context)
+ {
+ return WriteUserList(context, context.Device.System.State.Account.GetOpenedUsers());
+ }
+
+ private ResultCode WriteUserList(ServiceCtx context, IEnumerable<UserProfile> profiles)
+ {
+ if (context.Request.RecvListBuff.Count == 0)
+ {
+ return ResultCode.InvalidInputBuffer;
+ }
+
+ long outputPosition = context.Request.RecvListBuff[0].Position;
+ long outputSize = context.Request.RecvListBuff[0].Size;
+
+ ulong offset = 0;
+
+ foreach (UserProfile userProfile in profiles)
+ {
+ if (offset + 0x10 > (ulong)outputSize)
+ {
+ break;
+ }
+
+ context.Memory.WriteInt64(outputPosition + (long)offset, userProfile.UserId.Low);
+ context.Memory.WriteInt64(outputPosition + (long)offset + 8, userProfile.UserId.High);
+
+ offset += 0x10;
+ }
+
+ return ResultCode.Success;
+ }
+
+ [Command(4)]
+ // GetLastOpenedUser() -> nn::account::Uid
+ public ResultCode GetLastOpenedUser(ServiceCtx context)
+ {
+ context.Device.System.State.Account.LastOpenedUser.UserId.Write(context.ResponseData);
+
+ return ResultCode.Success;
+ }
+
+ [Command(5)]
+ // GetProfile(nn::account::Uid) -> object<nn::account::profile::IProfile>
+ public ResultCode GetProfile(ServiceCtx context)
+ {
+ UInt128 userId = new UInt128(context.RequestData.ReadBytes(0x10));
+
+ if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile))
+ {
+ Logger.PrintWarning(LogClass.ServiceAcc, $"User 0x{userId} not found!");
+
+ return ResultCode.UserNotFound;
+ }
+
+ MakeObject(context, new IProfile(userProfile));
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
+
+ [Command(50)]
+ // IsUserRegistrationRequestPermitted(u64, pid) -> bool
+ public ResultCode IsUserRegistrationRequestPermitted(ServiceCtx context)
+ {
+ // The u64 argument seems to be unused by account.
+ context.ResponseData.Write(_userRegistrationRequestPermitted);
+
+ return ResultCode.Success;
+ }
+
+ [Command(51)]
+ // TrySelectUserWithoutInteraction(bool) -> nn::account::Uid
+ public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
+ {
+ if (context.Device.System.State.Account.GetUserCount() != 1)
+ {
+ // Invalid UserId.
+ new UInt128(0, 0).Write(context.ResponseData);
+
+ return 0;
+ }
+
+ bool baasCheck = context.RequestData.ReadBoolean();
+
+ if (baasCheck)
+ {
+ // This checks something related to baas (online), and then return an invalid UserId if the check in baas returns an error code.
+ // In our case, we can just log it for now.
+
+ Logger.PrintStub(LogClass.ServiceAcc, new { baasCheck });
+ }
+
+ // As we returned an invalid UserId if there is more than one user earlier, now we can return only the first one.
+ context.Device.System.State.Account.GetFirst().UserId.Write(context.ResponseData);
+
+ return ResultCode.Success;
+ }
+
+ [Command(100)]
+ [Command(140)] // 6.0.0+
+ // InitializeApplicationInfo(u64, pid)
+ // Both calls (100, 140) use the same submethod, maybe there's something different further along when arp:r is called?
+ public ResultCode InitializeApplicationInfo(ServiceCtx context)
+ {
+ if (_applicationLaunchProperty != null)
+ {
+ return ResultCode.ApplicationLaunchPropertyAlreadyInit;
+ }
+
+ // The u64 argument seems to be unused by account.
+ long unknown = context.RequestData.ReadInt64();
+
+ // TODO: Account actually calls nn::arp::detail::IReader::GetApplicationLaunchProperty() with the current PID and store the result (ApplicationLaunchProperty) internally.
+ // For now we can hardcode values, and fix it after GetApplicationLaunchProperty is implemented.
+
+ /*
+ if (nn::arp::detail::IReader::GetApplicationLaunchProperty() == 0xCC9D) // InvalidProcessId
+ {
+ _applicationLaunchProperty = ApplicationLaunchProperty.Default;
+
+ return ResultCode.InvalidArgument;
+ }
+ else
+ */
+ {
+ _applicationLaunchProperty = ApplicationLaunchProperty.GetByPid(context);
+ }
+
+ Logger.PrintStub(LogClass.ServiceAcc, new { unknown });
+
+ return ResultCode.Success;
+ }
+
+ [Command(101)]
+ // GetBaasAccountManagerForApplication(nn::account::Uid) -> object<nn::account::baas::IManagerForApplication>
+ public ResultCode GetBaasAccountManagerForApplication(ServiceCtx context)
+ {
+ UInt128 userId = new UInt128(context.RequestData.ReadBytes(0x10));
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ if (_applicationLaunchProperty == null)
+ {
+ return ResultCode.InvalidArgument;
+ }
+
+ MakeObject(context, new IManagerForApplication(userId, _applicationLaunchProperty));
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
+
+ [Command(110)]
+ // StoreSaveDataThumbnail(nn::account::Uid, buffer<bytes, 5>)
+ public ResultCode StoreSaveDataThumbnail(ServiceCtx context)
+ {
+ if (_applicationLaunchProperty == null)
+ {
+ return ResultCode.InvalidArgument;
+ }
+
+ UInt128 userId = new UInt128(context.RequestData.ReadBytes(0x10));
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ if (context.Request.SendBuff.Count == 0)
+ {
+ return ResultCode.InvalidInputBuffer;
+ }
+
+ long inputPosition = context.Request.SendBuff[0].Position;
+ long inputSize = context.Request.SendBuff[0].Size;
+
+ if (inputSize != 0x24000)
+ {
+ return ResultCode.InvalidInputBufferSize;
+ }
+
+ byte[] thumbnailBuffer = context.Memory.ReadBytes(inputPosition, inputSize);
+
+ // TODO: Store thumbnailBuffer somewhere, in save data 0x8000000000000010 ?
+
+ Logger.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+
+ [Command(111)]
+ // ClearSaveDataThumbnail(nn::account::Uid)
+ public ResultCode ClearSaveDataThumbnail(ServiceCtx context)
+ {
+ if (_applicationLaunchProperty == null)
+ {
+ return ResultCode.InvalidArgument;
+ }
+
+ UInt128 userId = new UInt128(context.RequestData.ReadBytes(0x10));
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ // TODO: Clear the Thumbnail somewhere, in save data 0x8000000000000010 ?
+
+ Logger.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+
+ [Command(150)] // 6.0.0+
+ // IsUserAccountSwitchLocked() -> bool
+ public ResultCode IsUserAccountSwitchLocked(ServiceCtx context)
+ {
+ // TODO : Validate the following check.
+ /*
+ if (_applicationLaunchProperty != null)
+ {
+ return ResultCode.ApplicationLaunchPropertyAlreadyInit;
+ }
+ */
+
+ // Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current PID and store the result (NACP File) internally.
+ // But since we use LibHac and we load one Application at a time, it's not necessary.
+
+ context.ResponseData.Write(context.Device.System.ControlData.UserAccountSwitchLock);
+
+ Logger.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs
new file mode 100644
index 00000000..f1972f63
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ [Service("acc:u1")]
+ class IAccountServiceForSystemService : IpcService
+ {
+ public IAccountServiceForSystemService(ServiceCtx context) { }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs
new file mode 100644
index 00000000..d28ea275
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ [Service("acc:aa")]
+ class IBaasAccessTokenAccessor : IpcService
+ {
+ public IBaasAccessTokenAccessor(ServiceCtx context) { }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
new file mode 100644
index 00000000..aa9e07bd
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
@@ -0,0 +1,40 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Services.Arp;
+using Ryujinx.HLE.Utilities;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ class IManagerForApplication : IpcService
+ {
+ private UInt128 _userId;
+ private ApplicationLaunchProperty _applicationLaunchProperty;
+
+ public IManagerForApplication(UInt128 userId, ApplicationLaunchProperty applicationLaunchProperty)
+ {
+ _userId = userId;
+ _applicationLaunchProperty = applicationLaunchProperty;
+ }
+
+ [Command(0)]
+ // CheckAvailability()
+ public ResultCode CheckAvailability(ServiceCtx context)
+ {
+ Logger.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+
+ [Command(1)]
+ // GetAccountId() -> nn::account::NetworkServiceAccountId
+ public ResultCode GetAccountId(ServiceCtx context)
+ {
+ long networkServiceAccountId = 0xcafe;
+
+ Logger.PrintStub(LogClass.ServiceAcc, new { networkServiceAccountId });
+
+ context.ResponseData.Write(networkServiceAccountId);
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs
new file mode 100644
index 00000000..0470832b
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs
@@ -0,0 +1,80 @@
+using ARMeilleure.Memory;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.Utilities;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ class IProfile : IpcService
+ {
+ private UserProfile _profile;
+ private Stream _profilePictureStream;
+
+ public IProfile(UserProfile profile)
+ {
+ _profile = profile;
+ _profilePictureStream = Assembly.GetCallingAssembly().GetManifestResourceStream("Ryujinx.HLE.RyujinxProfileImage.jpg");
+ }
+
+ [Command(0)]
+ // Get() -> (nn::account::profile::ProfileBase, buffer<nn::account::profile::UserData, 0x1a>)
+ public ResultCode Get(ServiceCtx context)
+ {
+ Logger.PrintStub(LogClass.ServiceAcc);
+
+ long position = context.Request.ReceiveBuff[0].Position;
+
+ MemoryHelper.FillWithZeros(context.Memory, position, 0x80);
+
+ context.Memory.WriteInt32(position, 0);
+ context.Memory.WriteInt32(position + 4, 1);
+ context.Memory.WriteInt64(position + 8, 1);
+
+ return GetBase(context);
+ }
+
+ [Command(1)]
+ // GetBase() -> nn::account::profile::ProfileBase
+ public ResultCode GetBase(ServiceCtx context)
+ {
+ _profile.UserId.Write(context.ResponseData);
+
+ context.ResponseData.Write(_profile.LastModifiedTimestamp);
+
+ byte[] username = StringUtils.GetFixedLengthBytes(_profile.Name, 0x20, Encoding.UTF8);
+
+ context.ResponseData.Write(username);
+
+ return ResultCode.Success;
+ }
+
+ [Command(10)]
+ // GetImageSize() -> u32
+ public ResultCode GetImageSize(ServiceCtx context)
+ {
+ context.ResponseData.Write(_profilePictureStream.Length);
+
+ return ResultCode.Success;
+ }
+
+ [Command(11)]
+ // LoadImage() -> (u32, buffer<bytes, 6>)
+ public ResultCode LoadImage(ServiceCtx context)
+ {
+ long bufferPosition = context.Request.ReceiveBuff[0].Position;
+ long bufferLen = context.Request.ReceiveBuff[0].Size;
+
+ byte[] profilePictureData = new byte[bufferLen];
+
+ _profilePictureStream.Read(profilePictureData, 0, profilePictureData.Length);
+
+ context.Memory.WriteBytes(bufferPosition, profilePictureData);
+
+ context.ResponseData.Write(_profilePictureStream.Length);
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountState.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountState.cs
new file mode 100644
index 00000000..2382a255
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ public enum AccountState
+ {
+ Closed,
+ Open
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserProfile.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserProfile.cs
new file mode 100644
index 00000000..25004c24
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserProfile.cs
@@ -0,0 +1,37 @@
+using Ryujinx.HLE.Utilities;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ class UserProfile
+ {
+ private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+ public UInt128 UserId { get; private set; }
+
+ public string Name { get; private set; }
+
+ public long LastModifiedTimestamp { get; private set; }
+
+ public AccountState AccountState { get; set; }
+ public AccountState OnlinePlayState { get; set; }
+
+ public UserProfile(UInt128 userId, string name)
+ {
+ UserId = userId;
+ Name = name;
+
+ LastModifiedTimestamp = 0;
+
+ AccountState = AccountState.Closed;
+ OnlinePlayState = AccountState.Closed;
+
+ UpdateTimestamp();
+ }
+
+ private void UpdateTimestamp()
+ {
+ LastModifiedTimestamp = (long)(DateTime.Now - Epoch).TotalSeconds;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Dauth/IService.cs b/Ryujinx.HLE/HOS/Services/Account/Dauth/IService.cs
new file mode 100644
index 00000000..72301349
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Dauth/IService.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Dauth
+{
+ [Service("dauth:0")] // 5.0.0+
+ class IService : IpcService
+ {
+ public IService(ServiceCtx context) { }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs
new file mode 100644
index 00000000..e56732ab
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/ResultCode.cs
@@ -0,0 +1,20 @@
+namespace Ryujinx.HLE.HOS.Services.Account
+{
+ enum ResultCode
+ {
+ ModuleId = 124,
+ ErrorCodeShift = 9,
+
+ Success = 0,
+
+ NullArgument = (20 << ErrorCodeShift) | ModuleId,
+ InvalidArgument = (22 << ErrorCodeShift) | ModuleId,
+ NullInputBuffer = (30 << ErrorCodeShift) | ModuleId,
+ InvalidInputBufferSize = (31 << ErrorCodeShift) | ModuleId,
+ InvalidInputBuffer = (32 << ErrorCodeShift) | ModuleId,
+ ApplicationLaunchPropertyAlreadyInit = (41 << ErrorCodeShift) | ModuleId,
+ UserNotFound = (100 << ErrorCodeShift) | ModuleId,
+ NullObject = (302 << ErrorCodeShift) | ModuleId,
+ UnknownError1 = (341 << ErrorCodeShift) | ModuleId
+ }
+} \ No newline at end of file