aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2021-01-02 23:34:28 +0100
committerGitHub <noreply@github.com>2021-01-02 23:34:28 +0100
commitb001040c2f005da21f91713ba1145083a01d0b01 (patch)
tree26a5967abe4ff29bf9c47f0364b87e34d9421ca8
parent4f01c13f5054e3af775fc956584b553da934d476 (diff)
account: Services Refactoring (#1833)
* account: Services Refactoring * Remove extra empty space * Fix IProfile::Get * address gdkchan feedback
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs61
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs47
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs40
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs54
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs (renamed from Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs)33
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ProfileServer.cs117
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/ApplicationServiceServer.cs223
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs127
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs224
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs105
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs82
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountServiceFlag.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Arp/IReader.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/Arp/LibHacIReader.cs29
-rw-r--r--Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs1
17 files changed, 843 insertions, 316 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs
new file mode 100644
index 00000000..4631815b
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs
@@ -0,0 +1,61 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
+{
+ class IManagerForApplication : IpcService
+ {
+ private ManagerServer _managerServer;
+
+ public IManagerForApplication(UserId userId)
+ {
+ _managerServer = new ManagerServer(userId);
+ }
+
+ [Command(0)]
+ // CheckAvailability()
+ public ResultCode CheckAvailability(ServiceCtx context)
+ {
+ return _managerServer.CheckAvailability(context);
+ }
+
+ [Command(1)]
+ // GetAccountId() -> nn::account::NetworkServiceAccountId
+ public ResultCode GetAccountId(ServiceCtx context)
+ {
+ return _managerServer.GetAccountId(context);
+ }
+
+ [Command(2)]
+ // EnsureIdTokenCacheAsync() -> object<nn::account::detail::IAsyncContext>
+ public ResultCode EnsureIdTokenCacheAsync(ServiceCtx context)
+ {
+ ResultCode resultCode = _managerServer.EnsureIdTokenCacheAsync(context, out IAsyncContext asyncContext);
+
+ if (resultCode == ResultCode.Success)
+ {
+ MakeObject(context, asyncContext);
+ }
+
+ return resultCode;
+ }
+
+ [Command(3)]
+ // LoadIdTokenCache() -> (u32 id_token_cache_size, buffer<bytes, 6>)
+ public ResultCode LoadIdTokenCache(ServiceCtx context)
+ {
+ return _managerServer.LoadIdTokenCache(context);
+ }
+
+ [Command(130)]
+ // GetNintendoAccountUserResourceCacheForApplication() -> (nn::account::NintendoAccountId, nn::account::nas::NasUserBaseForApplication, buffer<bytes, 6>)
+ public ResultCode GetNintendoAccountUserResourceCacheForApplication(ServiceCtx context)
+ {
+ return _managerServer.GetNintendoAccountUserResourceCacheForApplication(context);
+ }
+
+ [Command(160)] // 5.0.0+
+ // StoreOpenContext()
+ public ResultCode StoreOpenContext(ServiceCtx context)
+ {
+ return _managerServer.StoreOpenContext(context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs
new file mode 100644
index 00000000..57a46666
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs
@@ -0,0 +1,47 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
+{
+ class IManagerForSystemService : IpcService
+ {
+ private ManagerServer _managerServer;
+
+ public IManagerForSystemService(UserId userId)
+ {
+ _managerServer = new ManagerServer(userId);
+ }
+
+ [Command(0)]
+ // CheckAvailability()
+ public ResultCode CheckAvailability(ServiceCtx context)
+ {
+ return _managerServer.CheckAvailability(context);
+ }
+
+ [Command(1)]
+ // GetAccountId() -> nn::account::NetworkServiceAccountId
+ public ResultCode GetAccountId(ServiceCtx context)
+ {
+ return _managerServer.GetAccountId(context);
+ }
+
+ [Command(2)]
+ // EnsureIdTokenCacheAsync() -> object<nn::account::detail::IAsyncContext>
+ public ResultCode EnsureIdTokenCacheAsync(ServiceCtx context)
+ {
+ ResultCode resultCode = _managerServer.EnsureIdTokenCacheAsync(context, out IAsyncContext asyncContext);
+
+ if (resultCode == ResultCode.Success)
+ {
+ MakeObject(context, asyncContext);
+ }
+
+ return resultCode;
+ }
+
+ [Command(3)]
+ // LoadIdTokenCache() -> (u32 id_token_cache_size, buffer<bytes, 6>)
+ public ResultCode LoadIdTokenCache(ServiceCtx context)
+ {
+ return _managerServer.LoadIdTokenCache(context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs
new file mode 100644
index 00000000..c07d90ad
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs
@@ -0,0 +1,40 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
+{
+ class IProfile : IpcService
+ {
+ private ProfileServer _profileServer;
+
+ public IProfile(UserProfile profile)
+ {
+ _profileServer = new ProfileServer(profile);
+ }
+
+ [Command(0)]
+ // Get() -> (nn::account::profile::ProfileBase, buffer<nn::account::profile::UserData, 0x1a>)
+ public ResultCode Get(ServiceCtx context)
+ {
+ return _profileServer.Get(context);
+ }
+
+ [Command(1)]
+ // GetBase() -> nn::account::profile::ProfileBase
+ public ResultCode GetBase(ServiceCtx context)
+ {
+ return _profileServer.GetBase(context);
+ }
+
+ [Command(10)]
+ // GetImageSize() -> u32
+ public ResultCode GetImageSize(ServiceCtx context)
+ {
+ return _profileServer.GetImageSize(context);
+ }
+
+ [Command(11)]
+ // LoadImage() -> (u32, buffer<bytes, 6>)
+ public ResultCode LoadImage(ServiceCtx context)
+ {
+ return _profileServer.LoadImage(context);
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs
new file mode 100644
index 00000000..33fef3e1
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs
@@ -0,0 +1,54 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
+{
+ class IProfileEditor : IpcService
+ {
+ private ProfileServer _profileServer;
+
+ public IProfileEditor(UserProfile profile)
+ {
+ _profileServer = new ProfileServer(profile);
+ }
+
+ [Command(0)]
+ // Get() -> (nn::account::profile::ProfileBase, buffer<nn::account::profile::UserData, 0x1a>)
+ public ResultCode Get(ServiceCtx context)
+ {
+ return _profileServer.Get(context);
+ }
+
+ [Command(1)]
+ // GetBase() -> nn::account::profile::ProfileBase
+ public ResultCode GetBase(ServiceCtx context)
+ {
+ return _profileServer.GetBase(context);
+ }
+
+ [Command(10)]
+ // GetImageSize() -> u32
+ public ResultCode GetImageSize(ServiceCtx context)
+ {
+ return _profileServer.GetImageSize(context);
+ }
+
+ [Command(11)]
+ // LoadImage() -> (u32, buffer<bytes, 6>)
+ public ResultCode LoadImage(ServiceCtx context)
+ {
+ return _profileServer.LoadImage(context);
+ }
+
+ [Command(100)]
+ // Store(nn::account::profile::ProfileBase, buffer<nn::account::profile::UserData, 0x19>)
+ public ResultCode Store(ServiceCtx context)
+ {
+ return _profileServer.Store(context);
+ }
+
+ [Command(101)]
+ // StoreWithImage(nn::account::profile::ProfileBase, buffer<nn::account::profile::UserData, 0x19>, buffer<bytes, 5>)
+ public ResultCode StoreWithImage(ServiceCtx context)
+ {
+ return _profileServer.StoreWithImage(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/AccountService/ManagerServer.cs
index 746f8f46..c7efe778 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IManagerForApplication.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ManagerServer.cs
@@ -1,31 +1,24 @@
-using Ryujinx.Common.Logging;
+using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
-using Ryujinx.HLE.HOS.Services.Arp;
-using System;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
-namespace Ryujinx.HLE.HOS.Services.Account.Acc
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
{
- class IManagerForApplication : IpcService
+ class ManagerServer
{
// TODO: Determine where and how NetworkServiceAccountId is set.
private const long NetworkServiceAccountId = 0xcafe;
- private UserId _userId;
- private ApplicationLaunchProperty _applicationLaunchProperty;
+ private UserId _userId;
- public IManagerForApplication(UserId userId, ApplicationLaunchProperty applicationLaunchProperty)
+ public ManagerServer(UserId userId)
{
- _userId = userId;
- _applicationLaunchProperty = applicationLaunchProperty;
+ _userId = userId;
}
- [Command(0)]
- // CheckAvailability()
public ResultCode CheckAvailability(ServiceCtx context)
{
// NOTE: This opens the file at "su/baas/USERID_IN_UUID_STRING.dat" where USERID_IN_UUID_STRING is formatted as "%08x-%04x-%04x-%02x%02x-%08x%04x".
@@ -37,8 +30,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
- [Command(1)]
- // GetAccountId() -> nn::account::NetworkServiceAccountId
public ResultCode GetAccountId(ServiceCtx context)
{
// NOTE: This opens the file at "su/baas/USERID_IN_UUID_STRING.dat" (where USERID_IN_UUID_STRING is formatted
@@ -52,16 +43,14 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
- [Command(2)]
- // EnsureIdTokenCacheAsync() -> object<nn::account::detail::IAsyncContext>
- public ResultCode EnsureIdTokenCacheAsync(ServiceCtx context)
+ public ResultCode EnsureIdTokenCacheAsync(ServiceCtx context, out IAsyncContext asyncContext)
{
KEvent asyncEvent = new KEvent(context.Device.System.KernelContext);
AsyncExecution asyncExecution = new AsyncExecution(asyncEvent);
asyncExecution.Initialize(1000, EnsureIdTokenCacheAsyncImpl);
- MakeObject(context, new IAsyncContext(asyncExecution));
+ asyncContext = new IAsyncContext(asyncExecution);
// return ResultCode.NullObject if the IAsyncContext pointer is null. Doesn't occur in our case.
@@ -82,8 +71,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
await Task.CompletedTask;
}
- [Command(3)]
- // LoadIdTokenCache() -> (u32 id_token_cache_size, buffer<bytes, 6>)
public ResultCode LoadIdTokenCache(ServiceCtx context)
{
long bufferPosition = context.Request.ReceiveBuff[0].Position;
@@ -114,8 +101,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
- [Command(130)]
- // GetNintendoAccountUserResourceCacheForApplication() -> (nn::account::NintendoAccountId, nn::account::nas::NasUserBaseForApplication, buffer<bytes, 6>)
public ResultCode GetNintendoAccountUserResourceCacheForApplication(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { NetworkServiceAccountId });
@@ -127,8 +112,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
- [Command(160)] // 5.0.0+
- // StoreOpenContext()
public ResultCode StoreOpenContext(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceAcc);
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ProfileServer.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ProfileServer.cs
new file mode 100644
index 00000000..c6e0508f
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/ProfileServer.cs
@@ -0,0 +1,117 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.Cpu;
+using Ryujinx.HLE.Utilities;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
+{
+ class ProfileServer
+ {
+ private UserProfile _profile;
+ private Stream _profilePictureStream;
+
+ public ProfileServer(UserProfile profile)
+ {
+ _profile = profile;
+ _profilePictureStream = Assembly.GetCallingAssembly().GetManifestResourceStream("Ryujinx.HLE.RyujinxProfileImage.jpg");
+ }
+
+ public ResultCode Get(ServiceCtx context)
+ {
+ context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(0x80L);
+
+ long bufferPosition = context.Request.RecvListBuff[0].Position;
+
+ MemoryHelper.FillWithZeros(context.Memory, bufferPosition, 0x80);
+
+ // TODO: Determine the struct.
+ context.Memory.Write((ulong)bufferPosition, 0); // Unknown
+ context.Memory.Write((ulong)bufferPosition + 4, 1); // Icon ID. 0 = Mii, the rest are character icon IDs.
+ context.Memory.Write((ulong)bufferPosition + 8, (byte)1); // Profile icon background color ID
+ // 0x07 bytes - Unknown
+ // 0x10 bytes - Some ID related to the Mii? All zeros when a character icon is used.
+ // 0x60 bytes - Usually zeros?
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+
+ return GetBase(context);
+ }
+
+ 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;
+ }
+
+ public ResultCode GetImageSize(ServiceCtx context)
+ {
+ context.ResponseData.Write(_profilePictureStream.Length);
+
+ return ResultCode.Success;
+ }
+
+ 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.Write((ulong)bufferPosition, profilePictureData);
+
+ context.ResponseData.Write(_profilePictureStream.Length);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode Store(ServiceCtx context)
+ {
+ long userDataPosition = context.Request.PtrBuff[0].Position;
+ long userDataSize = context.Request.PtrBuff[0].Size;
+
+ byte[] userData = new byte[userDataSize];
+
+ context.Memory.Read((ulong)userDataPosition, userData);
+
+ // TODO: Read the nn::account::profile::ProfileBase and store everything in the savedata.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { userDataSize });
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode StoreWithImage(ServiceCtx context)
+ {
+ long userDataPosition = context.Request.PtrBuff[0].Position;
+ long userDataSize = context.Request.PtrBuff[0].Size;
+
+ byte[] userData = new byte[userDataSize];
+
+ context.Memory.Read((ulong)userDataPosition, userData);
+
+ long profilePicturePosition = context.Request.SendBuff[0].Position;
+ long profilePictureSize = context.Request.SendBuff[0].Size;
+
+ byte[] profilePictureData = new byte[profilePictureSize];
+
+ context.Memory.Read((ulong)profilePicturePosition, profilePictureData);
+
+ // TODO: Read the nn::account::profile::ProfileBase and store everything in the savedata.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { userDataSize, profilePictureSize });
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/ApplicationServiceServer.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/ApplicationServiceServer.cs
new file mode 100644
index 00000000..4931866c
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/ApplicationServiceServer.cs
@@ -0,0 +1,223 @@
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ class ApplicationServiceServer
+ {
+ readonly AccountServiceFlag _serviceFlag;
+
+ public ApplicationServiceServer(AccountServiceFlag serviceFlag)
+ {
+ _serviceFlag = serviceFlag;
+ }
+
+ public ResultCode GetUserCountImpl(ServiceCtx context)
+ {
+ context.ResponseData.Write(context.Device.System.State.Account.GetUserCount());
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode GetUserExistenceImpl(ServiceCtx context)
+ {
+ ResultCode resultCode = CheckUserId(context, out UserId userId);
+
+ if (resultCode != ResultCode.Success)
+ {
+ return resultCode;
+ }
+
+ context.ResponseData.Write(context.Device.System.State.Account.TryGetUser(userId, out _));
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode ListAllUsers(ServiceCtx context)
+ {
+ return WriteUserList(context, context.Device.System.State.Account.GetAllUsers());
+ }
+
+ 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;
+
+ MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
+
+ ulong offset = 0;
+
+ foreach (UserProfile userProfile in profiles)
+ {
+ if (offset + 0x10 > (ulong)outputSize)
+ {
+ break;
+ }
+
+ context.Memory.Write((ulong)outputPosition + offset, userProfile.UserId.High);
+ context.Memory.Write((ulong)outputPosition + offset + 8, userProfile.UserId.Low);
+
+ offset += 0x10;
+ }
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode GetLastOpenedUser(ServiceCtx context)
+ {
+ context.Device.System.State.Account.LastOpenedUser.UserId.Write(context.ResponseData);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode GetProfile(ServiceCtx context, out IProfile profile)
+ {
+ profile = default;
+
+ ResultCode resultCode = CheckUserId(context, out UserId userId);
+
+ if (resultCode != ResultCode.Success)
+ {
+ return resultCode;
+ }
+
+ if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile))
+ {
+ Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!");
+
+ return ResultCode.UserNotFound;
+ }
+
+ profile = new IProfile(userProfile);
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode IsUserRegistrationRequestPermitted(ServiceCtx context)
+ {
+ context.ResponseData.Write(_serviceFlag != AccountServiceFlag.Application);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
+ {
+ if (context.Device.System.State.Account.GetUserCount() != 1)
+ {
+ // Invalid UserId.
+ UserId.Null.Write(context.ResponseData);
+
+ return ResultCode.UserNotFound;
+ }
+
+ bool isNetworkServiceAccountRequired = context.RequestData.ReadBoolean();
+
+ if (isNetworkServiceAccountRequired)
+ {
+ // NOTE: 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.Stub?.PrintStub(LogClass.ServiceAcc, new { isNetworkServiceAccountRequired });
+ }
+
+ // NOTE: 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;
+ }
+
+ public ResultCode StoreSaveDataThumbnail(ServiceCtx context)
+ {
+ ResultCode resultCode = CheckUserId(context, out UserId userId);
+
+ if (resultCode != ResultCode.Success)
+ {
+ return resultCode;
+ }
+
+ 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 = new byte[inputSize];
+
+ context.Memory.Read((ulong)inputPosition, thumbnailBuffer);
+
+ // NOTE: Account service call nn::fs::WriteSaveDataThumbnailFile().
+ // TODO: Store thumbnailBuffer somewhere, in save data 0x8000000000000010 ?
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode ClearSaveDataThumbnail(ServiceCtx context)
+ {
+ ResultCode resultCode = CheckUserId(context, out UserId userId);
+
+ if (resultCode != ResultCode.Success)
+ {
+ return resultCode;
+ }
+
+ /*
+ // NOTE: Doesn't occur in our case.
+ if (userId == null)
+ {
+ return ResultCode.InvalidArgument;
+ }
+ */
+
+ // NOTE: Account service call nn::fs::WriteSaveDataThumbnailFileHeader();
+ // TODO: Clear the Thumbnail somewhere, in save data 0x8000000000000010 ?
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc);
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode ListQualifiedUsers(ServiceCtx context)
+ {
+ // TODO: Determine how users are "qualified". We assume all users are "qualified" for now.
+
+ return WriteUserList(context, context.Device.System.State.Account.GetAllUsers());
+ }
+
+ public ResultCode CheckUserId(ServiceCtx context, out UserId userId)
+ {
+ userId = context.RequestData.ReadStruct<UserId>();
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ return ResultCode.Success;
+ }
+ }
+} \ 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
index 9fb3fb9b..90091b08 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs
@@ -1,8 +1,129 @@
-namespace Ryujinx.HLE.HOS.Services.Account.Acc
+using Ryujinx.Common;
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
- [Service("acc:su")]
+ [Service("acc:su", AccountServiceFlag.Administrator)] // Max Sessions: 8
class IAccountServiceForAdministrator : IpcService
{
- public IAccountServiceForAdministrator(ServiceCtx context) { }
+ private ApplicationServiceServer _applicationServiceServer;
+
+ public IAccountServiceForAdministrator(ServiceCtx context, AccountServiceFlag serviceFlag)
+ {
+ _applicationServiceServer = new ApplicationServiceServer(serviceFlag);
+ }
+
+ [Command(0)]
+ // GetUserCount() -> i32
+ public ResultCode GetUserCount(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetUserCountImpl(context);
+ }
+
+ [Command(1)]
+ // GetUserExistence(nn::account::Uid) -> bool
+ public ResultCode GetUserExistence(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetUserExistenceImpl(context);
+ }
+
+ [Command(2)]
+ // ListAllUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListAllUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListAllUsers(context);
+ }
+
+ [Command(3)]
+ // ListOpenUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListOpenUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListOpenUsers(context);
+ }
+
+ [Command(4)]
+ // GetLastOpenedUser() -> nn::account::Uid
+ public ResultCode GetLastOpenedUser(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetLastOpenedUser(context);
+ }
+
+ [Command(5)]
+ // GetProfile(nn::account::Uid) -> object<nn::account::profile::IProfile>
+ public ResultCode GetProfile(ServiceCtx context)
+ {
+ ResultCode resultCode = _applicationServiceServer.GetProfile(context, out IProfile iProfile);
+
+ if (resultCode == ResultCode.Success)
+ {
+ MakeObject(context, iProfile);
+ }
+
+ return resultCode;
+ }
+
+ [Command(50)]
+ // IsUserRegistrationRequestPermitted(pid) -> bool
+ public ResultCode IsUserRegistrationRequestPermitted(ServiceCtx context)
+ {
+ // NOTE: pid is unused.
+
+ return _applicationServiceServer.IsUserRegistrationRequestPermitted(context);
+ }
+
+ [Command(51)]
+ // TrySelectUserWithoutInteraction(bool) -> nn::account::Uid
+ public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
+ {
+ return _applicationServiceServer.TrySelectUserWithoutInteraction(context);
+ }
+
+ [Command(102)]
+ // GetBaasAccountManagerForSystemService(nn::account::Uid) -> object<nn::account::baas::IManagerForApplication>
+ public ResultCode GetBaasAccountManagerForSystemService(ServiceCtx context)
+ {
+ ResultCode resultCode = _applicationServiceServer.CheckUserId(context, out UserId userId);
+
+ if (resultCode != ResultCode.Success)
+ {
+ return resultCode;
+ }
+
+ MakeObject(context, new IManagerForSystemService(userId));
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
+
+ [Command(140)] // 6.0.0+
+ // ListQualifiedUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListQualifiedUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListQualifiedUsers(context);
+ }
+
+ [Command(205)]
+ // GetProfileEditor(nn::account::Uid) -> object<nn::account::profile::IProfileEditor>
+ public ResultCode GetProfileEditor(ServiceCtx context)
+ {
+ UserId userId = context.RequestData.ReadStruct<UserId>();
+
+ if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile))
+ {
+ Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!");
+
+ return ResultCode.UserNotFound;
+ }
+
+ MakeObject(context, new IProfileEditor(userProfile));
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
}
} \ 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
index 6382a4ba..d2385594 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs
@@ -1,188 +1,106 @@
-using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
using Ryujinx.HLE.HOS.Services.Arp;
-using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
- [Service("acc:u0")]
+ [Service("acc:u0", AccountServiceFlag.Application)] // Max Sessions: 4
class IAccountServiceForApplication : IpcService
{
- private bool _userRegistrationRequestPermitted = false;
+ private ApplicationServiceServer _applicationServiceServer;
- private ApplicationLaunchProperty _applicationLaunchProperty;
-
- public IAccountServiceForApplication(ServiceCtx context) { }
+ public IAccountServiceForApplication(ServiceCtx context, AccountServiceFlag serviceFlag)
+ {
+ _applicationServiceServer = new ApplicationServiceServer(serviceFlag);
+ }
[Command(0)]
// GetUserCount() -> i32
public ResultCode GetUserCount(ServiceCtx context)
{
- context.ResponseData.Write(context.Device.System.State.Account.GetUserCount());
-
- return ResultCode.Success;
+ return _applicationServiceServer.GetUserCountImpl(context);
}
[Command(1)]
// GetUserExistence(nn::account::Uid) -> bool
public ResultCode GetUserExistence(ServiceCtx context)
{
- UserId userId = context.RequestData.ReadStruct<UserId>();
-
- if (userId.IsNull)
- {
- return ResultCode.NullArgument;
- }
-
- context.ResponseData.Write(context.Device.System.State.Account.TryGetUser(userId, out _));
-
- return ResultCode.Success;
+ return _applicationServiceServer.GetUserExistenceImpl(context);
}
[Command(2)]
// ListAllUsers() -> array<nn::account::Uid, 0xa>
public ResultCode ListAllUsers(ServiceCtx context)
{
- return WriteUserList(context, context.Device.System.State.Account.GetAllUsers());
+ return _applicationServiceServer.ListAllUsers(context);
}
[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;
-
- MemoryHelper.FillWithZeros(context.Memory, outputPosition, (int)outputSize);
-
- ulong offset = 0;
-
- foreach (UserProfile userProfile in profiles)
- {
- if (offset + 0x10 > (ulong)outputSize)
- {
- break;
- }
-
- context.Memory.Write((ulong)outputPosition + offset, userProfile.UserId.High);
- context.Memory.Write((ulong)outputPosition + offset + 8, userProfile.UserId.Low);
-
- offset += 0x10;
- }
-
- return ResultCode.Success;
+ return _applicationServiceServer.ListOpenUsers(context);
}
[Command(4)]
// GetLastOpenedUser() -> nn::account::Uid
public ResultCode GetLastOpenedUser(ServiceCtx context)
{
- context.Device.System.State.Account.LastOpenedUser.UserId.Write(context.ResponseData);
-
- return ResultCode.Success;
+ return _applicationServiceServer.GetLastOpenedUser(context);
}
[Command(5)]
// GetProfile(nn::account::Uid) -> object<nn::account::profile::IProfile>
public ResultCode GetProfile(ServiceCtx context)
{
- UserId userId = context.RequestData.ReadStruct<UserId>();
+ ResultCode resultCode = _applicationServiceServer.GetProfile(context, out IProfile iProfile);
- if (!context.Device.System.State.Account.TryGetUser(userId, out UserProfile userProfile))
+ if (resultCode == ResultCode.Success)
{
- Logger.Warning?.Print(LogClass.ServiceAcc, $"User 0x{userId} not found!");
-
- return ResultCode.UserNotFound;
+ MakeObject(context, iProfile);
}
- MakeObject(context, new IProfile(userProfile));
-
- // Doesn't occur in our case.
- // return ResultCode.NullObject;
-
- return ResultCode.Success;
+ return resultCode;
}
[Command(50)]
- // IsUserRegistrationRequestPermitted(u64, pid) -> bool
+ // IsUserRegistrationRequestPermitted(pid) -> bool
public ResultCode IsUserRegistrationRequestPermitted(ServiceCtx context)
{
- // The u64 argument seems to be unused by account.
- context.ResponseData.Write(_userRegistrationRequestPermitted);
-
- return ResultCode.Success;
+ // NOTE: pid is unused.
+ return _applicationServiceServer.IsUserRegistrationRequestPermitted(context);
}
[Command(51)]
// TrySelectUserWithoutInteraction(bool) -> nn::account::Uid
public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
{
- if (context.Device.System.State.Account.GetUserCount() != 1)
- {
- // Invalid UserId.
- new UserId(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.Stub?.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;
+ return _applicationServiceServer.TrySelectUserWithoutInteraction(context);
}
[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?
+ // InitializeApplicationInfo(u64 pid_placeholder, pid)
public ResultCode InitializeApplicationInfo(ServiceCtx context)
{
- if (_applicationLaunchProperty != null)
- {
- return ResultCode.Unknown41;
- }
+ // NOTE: In call 100, account service use the pid_placeholder instead of the real pid, which is wrong, call 140 fix that.
- // 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
+ if (nn::arp::detail::IReader::GetApplicationLaunchProperty() == 0xCC9D) // ResultCode.InvalidProcessId
{
- _applicationLaunchProperty = ApplicationLaunchProperty.Default;
-
return ResultCode.InvalidArgument;
}
- else
+
*/
- {
- _applicationLaunchProperty = ApplicationLaunchProperty.GetByPid(context);
- }
- Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { unknown });
+ // TODO: Determine where ApplicationLaunchProperty is used.
+ ApplicationLaunchProperty applicationLaunchProperty = ApplicationLaunchProperty.GetByPid(context);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAcc, new { applicationLaunchProperty.TitleId });
return ResultCode.Success;
}
@@ -191,19 +109,14 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// GetBaasAccountManagerForApplication(nn::account::Uid) -> object<nn::account::baas::IManagerForApplication>
public ResultCode GetBaasAccountManagerForApplication(ServiceCtx context)
{
- UserId userId = context.RequestData.ReadStruct<UserId>();
-
- if (userId.IsNull)
- {
- return ResultCode.NullArgument;
- }
+ ResultCode resultCode = _applicationServiceServer.CheckUserId(context, out UserId userId);
- if (_applicationLaunchProperty == null)
+ if (resultCode != ResultCode.Success)
{
- return ResultCode.InvalidArgument;
+ return resultCode;
}
- MakeObject(context, new IManagerForApplication(userId, _applicationLaunchProperty));
+ MakeObject(context, new IManagerForApplication(userId));
// Doesn't occur in our case.
// return ResultCode.NullObject;
@@ -215,63 +128,14 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// StoreSaveDataThumbnail(nn::account::Uid, buffer<bytes, 5>)
public ResultCode StoreSaveDataThumbnail(ServiceCtx context)
{
- if (_applicationLaunchProperty == null)
- {
- return ResultCode.InvalidArgument;
- }
-
- UserId userId = context.RequestData.ReadStruct<UserId>();
-
- 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 = new byte[inputSize];
-
- context.Memory.Read((ulong)inputPosition, thumbnailBuffer);
-
- // TODO: Store thumbnailBuffer somewhere, in save data 0x8000000000000010 ?
-
- Logger.Stub?.PrintStub(LogClass.ServiceAcc);
-
- return ResultCode.Success;
+ return _applicationServiceServer.StoreSaveDataThumbnail(context);
}
[Command(111)]
// ClearSaveDataThumbnail(nn::account::Uid)
public ResultCode ClearSaveDataThumbnail(ServiceCtx context)
{
- if (_applicationLaunchProperty == null)
- {
- return ResultCode.InvalidArgument;
- }
-
- UserId userId = context.RequestData.ReadStruct<UserId>();
-
- if (userId.IsNull)
- {
- return ResultCode.NullArgument;
- }
-
- // TODO: Clear the Thumbnail somewhere, in save data 0x8000000000000010 ?
-
- Logger.Stub?.PrintStub(LogClass.ServiceAcc);
-
- return ResultCode.Success;
+ return _applicationServiceServer.ClearSaveDataThumbnail(context);
}
[Command(131)] // 6.0.0+
@@ -294,25 +158,15 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
// ListQualifiedUsers() -> array<nn::account::Uid, 0xa>
public ResultCode ListQualifiedUsers(ServiceCtx context)
{
- // TODO: Determine how users are "qualified". We assume all users are "qualified" for now.
-
- return WriteUserList(context, context.Device.System.State.Account.GetAllUsers());
+ return _applicationServiceServer.ListQualifiedUsers(context);
}
[Command(150)] // 6.0.0+
// IsUserAccountSwitchLocked() -> bool
public ResultCode IsUserAccountSwitchLocked(ServiceCtx context)
{
- // TODO : Validate the following check.
- /*
- if (_applicationLaunchProperty != null)
- {
- return ResultCode.Unknown41;
- }
- */
-
- // 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.
+ // TODO: 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.Application.ControlData.Value.UserAccountSwitchLock);
@@ -321,4 +175,4 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
return ResultCode.Success;
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs
index f1972f63..d61e0744 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs
@@ -1,8 +1,107 @@
-namespace Ryujinx.HLE.HOS.Services.Account.Acc
+using Ryujinx.Common;
+using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
+
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
- [Service("acc:u1")]
+ [Service("acc:u1", AccountServiceFlag.SystemService)] // Max Sessions: 16
class IAccountServiceForSystemService : IpcService
{
- public IAccountServiceForSystemService(ServiceCtx context) { }
+ private ApplicationServiceServer _applicationServiceServer;
+
+ public IAccountServiceForSystemService(ServiceCtx context, AccountServiceFlag serviceFlag)
+ {
+ _applicationServiceServer = new ApplicationServiceServer(serviceFlag);
+ }
+
+ [Command(0)]
+ // GetUserCount() -> i32
+ public ResultCode GetUserCount(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetUserCountImpl(context);
+ }
+
+ [Command(1)]
+ // GetUserExistence(nn::account::Uid) -> bool
+ public ResultCode GetUserExistence(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetUserExistenceImpl(context);
+ }
+
+ [Command(2)]
+ // ListAllUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListAllUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListAllUsers(context);
+ }
+
+ [Command(3)]
+ // ListOpenUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListOpenUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListOpenUsers(context);
+ }
+
+ [Command(4)]
+ // GetLastOpenedUser() -> nn::account::Uid
+ public ResultCode GetLastOpenedUser(ServiceCtx context)
+ {
+ return _applicationServiceServer.GetLastOpenedUser(context);
+ }
+
+ [Command(5)]
+ // GetProfile(nn::account::Uid) -> object<nn::account::profile::IProfile>
+ public ResultCode GetProfile(ServiceCtx context)
+ {
+ ResultCode resultCode = _applicationServiceServer.GetProfile(context, out IProfile iProfile);
+
+ if (resultCode == ResultCode.Success)
+ {
+ MakeObject(context, iProfile);
+ }
+
+ return resultCode;
+ }
+
+ [Command(50)]
+ // IsUserRegistrationRequestPermitted(pid) -> bool
+ public ResultCode IsUserRegistrationRequestPermitted(ServiceCtx context)
+ {
+ // NOTE: pid is unused.
+
+ return _applicationServiceServer.IsUserRegistrationRequestPermitted(context);
+ }
+
+ [Command(51)]
+ // TrySelectUserWithoutInteraction(bool) -> nn::account::Uid
+ public ResultCode TrySelectUserWithoutInteraction(ServiceCtx context)
+ {
+ return _applicationServiceServer.TrySelectUserWithoutInteraction(context);
+ }
+
+ [Command(102)]
+ // GetBaasAccountManagerForSystemService(nn::account::Uid) -> object<nn::account::baas::IManagerForApplication>
+ public ResultCode GetBaasAccountManagerForSystemService(ServiceCtx context)
+ {
+ UserId userId = context.RequestData.ReadStruct<UserId>();
+
+ if (userId.IsNull)
+ {
+ return ResultCode.NullArgument;
+ }
+
+ MakeObject(context, new IManagerForSystemService(userId));
+
+ // Doesn't occur in our case.
+ // return ResultCode.NullObject;
+
+ return ResultCode.Success;
+ }
+
+ [Command(140)] // 6.0.0+
+ // ListQualifiedUsers() -> array<nn::account::Uid, 0xa>
+ public ResultCode ListQualifiedUsers(ServiceCtx context)
+ {
+ return _applicationServiceServer.ListQualifiedUsers(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
index d28ea275..223be2f5 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs
@@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
- [Service("acc:aa")]
+ [Service("acc:aa", AccountServiceFlag.BaasAccessTokenAccessor)] // Max Sessions: 4
class IBaasAccessTokenAccessor : IpcService
{
public IBaasAccessTokenAccessor(ServiceCtx context) { }
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs
deleted file mode 100644
index 4b134c6f..00000000
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/IProfile.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using Ryujinx.Common.Logging;
-using Ryujinx.Cpu;
-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.Stub?.PrintStub(LogClass.ServiceAcc);
-
- context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(0x80L);
-
- long position = context.Request.ReceiveBuff[0].Position;
-
- MemoryHelper.FillWithZeros(context.Memory, position, 0x80);
-
- context.Memory.Write((ulong)position, 0);
- context.Memory.Write((ulong)position + 4, 1);
- context.Memory.Write((ulong)position + 8, 1L);
-
- 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.Write((ulong)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/AccountServiceFlag.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountServiceFlag.cs
new file mode 100644
index 00000000..a991f977
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/AccountServiceFlag.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.HLE.HOS.Services.Account.Acc
+{
+ enum AccountServiceFlag
+ {
+ Administrator = 100,
+ SystemService = 101,
+ Application = 102,
+ BaasAccessTokenAccessor = 200
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
index 75915c02..85ddb439 100644
--- a/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
+++ b/Ryujinx.HLE/HOS/Services/Account/Acc/Types/UserId.cs
@@ -15,6 +15,8 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
public bool IsNull => (Low | High) == 0;
+ public static UserId Null => new UserId(0, 0);
+
public UserId(long low, long high)
{
Low = low;
diff --git a/Ryujinx.HLE/HOS/Services/Arp/IReader.cs b/Ryujinx.HLE/HOS/Services/Arp/IReader.cs
index 5d1e2fff..35a2de0c 100644
--- a/Ryujinx.HLE/HOS/Services/Arp/IReader.cs
+++ b/Ryujinx.HLE/HOS/Services/Arp/IReader.cs
@@ -1,4 +1,4 @@
-namespace Ryujinx.HLE.HOS.Services.Hid
+namespace Ryujinx.HLE.HOS.Services.Arp
{
[Service("arp:r")]
class IReader : IpcService
diff --git a/Ryujinx.HLE/HOS/Services/Arp/LibHacIReader.cs b/Ryujinx.HLE/HOS/Services/Arp/LibHacIReader.cs
index 44d674a4..dc8ed2e6 100644
--- a/Ryujinx.HLE/HOS/Services/Arp/LibHacIReader.cs
+++ b/Ryujinx.HLE/HOS/Services/Arp/LibHacIReader.cs
@@ -1,5 +1,4 @@
using LibHac;
-using LibHac.Arp.Impl;
using LibHac.Ncm;
using LibHac.Ns;
using System;
@@ -8,7 +7,7 @@ using ApplicationId = LibHac.ApplicationId;
namespace Ryujinx.HLE.HOS.Services.Arp
{
- class LibHacIReader : IReader
+ class LibHacIReader : LibHac.Arp.Impl.IReader
{
private Horizon System { get; }
@@ -19,21 +18,22 @@ namespace Ryujinx.HLE.HOS.Services.Arp
public Result GetApplicationLaunchProperty(out LibHac.Arp.ApplicationLaunchProperty launchProperty, ulong processId)
{
- launchProperty = new LibHac.Arp.ApplicationLaunchProperty();
-
- launchProperty.BaseStorageId = StorageId.BuiltInUser;
- launchProperty.ApplicationId = new ApplicationId(System.Device.Application.TitleId);
+ launchProperty = new LibHac.Arp.ApplicationLaunchProperty
+ {
+ BaseStorageId = StorageId.BuiltInUser,
+ ApplicationId = new ApplicationId(System.Device.Application.TitleId)
+ };
return Result.Success;
}
- public Result GetApplicationLaunchPropertyWithApplicationId(out LibHac.Arp.ApplicationLaunchProperty launchProperty,
- ApplicationId applicationId)
+ public Result GetApplicationLaunchPropertyWithApplicationId(out LibHac.Arp.ApplicationLaunchProperty launchProperty, ApplicationId applicationId)
{
- launchProperty = new LibHac.Arp.ApplicationLaunchProperty();
-
- launchProperty.BaseStorageId = StorageId.BuiltInUser;
- launchProperty.ApplicationId = applicationId;
+ launchProperty = new LibHac.Arp.ApplicationLaunchProperty
+ {
+ BaseStorageId = StorageId.BuiltInUser,
+ ApplicationId = applicationId
+ };
return Result.Success;
}
@@ -43,10 +43,9 @@ namespace Ryujinx.HLE.HOS.Services.Arp
throw new NotImplementedException();
}
- public Result GetApplicationControlPropertyWithApplicationId(out ApplicationControlProperty controlProperty,
- ApplicationId applicationId)
+ public Result GetApplicationControlPropertyWithApplicationId(out ApplicationControlProperty controlProperty, ApplicationId applicationId)
{
throw new NotImplementedException();
}
}
-}
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs b/Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs
index 4324f13e..ea200f3d 100644
--- a/Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs
+++ b/Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs
@@ -1,7 +1,6 @@
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator;
-using Ryujinx.HLE.Utilities;
namespace Ryujinx.HLE.HOS.Services.Friend
{