Просмотр исходного кода

IPC services refactoring (#726)

* IPC services refactoring

- Use custom Attributes to handle services.
- Add a way to set the permissions and fix the bsd service to use it.
- Little cleanup.
- C#7.1 is required.

* fix var name

* fix syntax

* Change Permission to Parameter

* Delete BsdServicePermissionLevel.cs

* Fix Linq
Ac_K 6 лет назад
Родитель
Сommit
596b61ce1f
48 измененных файлов с 175 добавлено и 299 удалено
  1. 3 1
      Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs
  2. 2 1
      Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs
  3. 2 1
      Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs
  4. 3 1
      Ryujinx.HLE/HOS/Services/Apm/IManager.cs
  5. 2 1
      Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs
  6. 2 1
      Ryujinx.HLE/HOS/Services/Aud/IAudioRendererManager.cs
  7. 2 1
      Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoderManager.cs
  8. 5 1
      Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs
  9. 7 6
      Ryujinx.HLE/HOS/Services/Bsd/IClient.cs
  10. 2 1
      Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs
  11. 2 1
      Ryujinx.HLE/HOS/Services/Caps/IScreenshotService.cs
  12. 4 5
      Ryujinx.HLE/HOS/Services/Es/IETicketService.cs
  13. 8 3
      Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs
  14. 2 1
      Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs
  15. 5 4
      Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs
  16. 2 1
      Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs
  17. 2 1
      Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs
  18. 2 1
      Ryujinx.HLE/HOS/Services/Lm/ILogService.cs
  19. 2 1
      Ryujinx.HLE/HOS/Services/Lr/ILocationResolverManager.cs
  20. 2 1
      Ryujinx.HLE/HOS/Services/Mm/IRequest.cs
  21. 4 3
      Ryujinx.HLE/HOS/Services/Ncm/IContentManager.cs
  22. 2 1
      Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs
  23. 2 1
      Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs
  24. 2 1
      Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs
  25. 2 1
      Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs
  26. 4 2
      Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs
  27. 2 1
      Ryujinx.HLE/HOS/Services/Ns/ISystemUpdateInterface.cs
  28. 2 1
      Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs
  29. 4 2
      Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs
  30. 5 1
      Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs
  31. 2 1
      Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs
  32. 2 1
      Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs
  33. 3 1
      Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs
  34. 2 1
      Ryujinx.HLE/HOS/Services/Psm/IPsmServer.cs
  35. 17 0
      Ryujinx.HLE/HOS/Services/ServiceAttributes.cs
  36. 7 0
      Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs
  37. 0 236
      Ryujinx.HLE/HOS/Services/ServiceFactory.cs
  38. 2 1
      Ryujinx.HLE/HOS/Services/Set/ISettingsServer.cs
  39. 2 1
      Ryujinx.HLE/HOS/Services/Set/ISystemSettingsServer.cs
  40. 2 1
      Ryujinx.HLE/HOS/Services/Sfdnsres/IResolver.cs
  41. 31 2
      Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
  42. 2 1
      Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs
  43. 2 1
      Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs
  44. 4 1
      Ryujinx.HLE/HOS/Services/Time/IStaticService.cs
  45. 2 1
      Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs
  46. 2 1
      Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs
  47. 2 1
      Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs
  48. 1 0
      Ryujinx.HLE/Ryujinx.HLE.csproj

+ 3 - 1
Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs

@@ -11,6 +11,8 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Acc
 {
+    [Service("acc:u0")]
+    [Service("acc:u1")]
     class IAccountService : IpcService
     {
         private bool _userRegistrationRequestPermitted = false;
@@ -21,7 +23,7 @@ namespace Ryujinx.HLE.HOS.Services.Acc
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAccountService()
+        public IAccountService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Am
 {
+    [Service("appletAE")]
     class IAllSystemAppletProxiesService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAllSystemAppletProxiesService()
+        public IAllSystemAppletProxiesService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Am
 {
+    [Service("appletOE")]
     class IApplicationProxyService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IApplicationProxyService()
+        public IApplicationProxyService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 3 - 1
Ryujinx.HLE/HOS/Services/Apm/IManager.cs

@@ -3,13 +3,15 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Apm
 {
+    [Service("apm")]
+    [Service("apm:p")]
     class IManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IManager()
+        public IManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Aud/IAudioOutManager.cs

@@ -11,6 +11,7 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Aud
 {
+    [Service("audout:u")]
     class IAudioOutManager : IpcService
     {
         private const string DefaultAudioOutput = "DeviceOut";
@@ -23,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAudioOutManager()
+        public IAudioOutManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Aud/IAudioRendererManager.cs

@@ -9,6 +9,7 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Aud
 {
+    [Service("audren:u")]
     class IAudioRendererManager : IpcService
     {
         private const int Rev0Magic = ('R' << 0)  |
@@ -24,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAudioRendererManager()
+        public IAudioRendererManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Aud/IHardwareOpusDecoderManager.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Aud
 {
+    [Service("hwopus")]
     class IHardwareOpusDecoderManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IHardwareOpusDecoderManager()
+        public IHardwareOpusDecoderManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 5 - 1
Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs

@@ -3,13 +3,17 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Bcat
 {
+    [Service("bcat:a")]
+    [Service("bcat:m")]
+    [Service("bcat:u")]
+    [Service("bcat:s")]
     class IServiceCreator : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IServiceCreator()
+        public IServiceCreator(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 7 - 6
Ryujinx.HLE/HOS/Services/Bsd/IClient.cs

@@ -8,9 +8,10 @@ using System.Text;
 
 namespace Ryujinx.HLE.HOS.Services.Bsd
 {
+    [Service("bsd:s", true)]
+    [Service("bsd:u", false)]
     class IClient : IpcService
     {
-
         private static Dictionary<WsaError, LinuxError> _errorMap = new Dictionary<WsaError, LinuxError>
         {
             // WSAEINTR
@@ -95,15 +96,15 @@ namespace Ryujinx.HLE.HOS.Services.Bsd
             {0, 0}
         };
 
-        private Dictionary<int, ServiceProcessRequest> _commands;
-
-        public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
-
         private bool _isPrivileged;
 
         private List<BsdSocket> _sockets = new List<BsdSocket>();
 
-        public IClient(bool isPrivileged)
+        private Dictionary<int, ServiceProcessRequest> _commands;
+
+        public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
+
+        public IClient(ServiceCtx context, bool isPrivileged)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Caps
 {
+    [Service("caps:a")]
     class IAlbumAccessorService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAlbumAccessorService()
+        public IAlbumAccessorService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Caps/IScreenshotService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Caps
 {
+    [Service("caps:ss")]
     class IScreenshotService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IScreenshotService()
+        public IScreenshotService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 4 - 5
Ryujinx.HLE/HOS/Services/Es/IETicketService.cs

@@ -3,20 +3,19 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Es
 {
+    [Service("es")]
     class IeTicketService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        private bool _isInitialized;
-
-        public IeTicketService()
+        public IeTicketService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
-
+                //...
             };
         }
     }
-}
+}

+ 8 - 3
Ryujinx.HLE/HOS/Services/Friend/IServiceCreator.cs

@@ -7,15 +7,20 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Friend
 {
+    [Service("friend:a", FriendServicePermissionLevel.Admin)]
+    [Service("friend:m", FriendServicePermissionLevel.Manager)]
+    [Service("friend:s", FriendServicePermissionLevel.System)]
+    [Service("friend:u", FriendServicePermissionLevel.User)]
+    [Service("friend:v", FriendServicePermissionLevel.Overlay)]
     class IServiceCreator : IpcService
     {
-        private Dictionary<int, ServiceProcessRequest> _commands;
-
         private FriendServicePermissionLevel _permissionLevel;
 
+        private Dictionary<int, ServiceProcessRequest> _commands;
+
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IServiceCreator(FriendServicePermissionLevel permissionLevel)
+        public IServiceCreator(ServiceCtx context, FriendServicePermissionLevel permissionLevel)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs

@@ -15,13 +15,14 @@ using static Ryujinx.HLE.Utilities.StringUtils;
 
 namespace Ryujinx.HLE.HOS.Services.FspSrv
 {
+    [Service("fsp-srv")]
     class IFileSystemProxy : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IFileSystemProxy()
+        public IFileSystemProxy(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 5 - 4
Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs

@@ -8,6 +8,7 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Hid
 {
+    [Service("hid")]
     class IHidServer : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
@@ -40,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IHidServer(Horizon system)
+        public IHidServer(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
@@ -149,9 +150,9 @@ namespace Ryujinx.HLE.HOS.Services.Hid
                 { 1001, GetNpadCommunicationMode                      }
             };
 
-            _npadStyleSetUpdateEvent     = new KEvent(system);
-            _xpadIdEvent                 = new KEvent(system);
-            _palmaOperationCompleteEvent = new KEvent(system);
+            _npadStyleSetUpdateEvent     = new KEvent(context.Device.System);
+            _xpadIdEvent                 = new KEvent(context.Device.System);
+            _palmaOperationCompleteEvent = new KEvent(context.Device.System);
 
             _npadJoyHoldType            = HidNpadJoyHoldType.Vertical;
             _npadStyleSet               = HidNpadStyle.FullKey | HidNpadStyle.Dual | HidNpadStyle.Left | HidNpadStyle.Right | HidNpadStyle.Handheld;

+ 2 - 1
Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs

@@ -7,6 +7,7 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Hid.Irs
 {
+    [Service("irs")]
     class IIrSensorServer : IpcService
     {
         private int _irsensorSharedMemoryHandle = 0;
@@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid.Irs
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IIrSensorServer()
+        public IIrSensorServer(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ldr/IRoInterface.cs

@@ -95,6 +95,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
         }
     }
 
+    [Service("ldr:ro")]
     class IRoInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
@@ -112,7 +113,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldr
 
         private bool _isInitialized;
 
-        public IRoInterface()
+        public IRoInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Lm/ILogService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Lm
 {
+    [Service("lm")]
     class ILogService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ILogService()
+        public ILogService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Lr/ILocationResolverManager.cs

@@ -4,13 +4,14 @@ using Ryujinx.HLE.FileSystem;
 
 namespace Ryujinx.HLE.HOS.Services.Lr
 {
+    [Service("lr")]
     class ILocationResolverManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ILocationResolverManager()
+        public ILocationResolverManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Mm/IRequest.cs

@@ -4,13 +4,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Mm
 {
+    [Service("mm:u")]
     class IRequest : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IRequest()
+        public IRequest(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>()
             {

+ 4 - 3
Ryujinx.HLE/HOS/Services/Ncm/IContentManager.cs

@@ -3,18 +3,19 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ncm
 {
+    [Service("ncm")]
     class IContentManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IContentManager()
+        public IContentManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
-
+                //...
             };
         }
     }
-}
+}

+ 2 - 1
Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
 {
+    [Service("nfp:user")]
     class IUserManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IUserManager()
+        public IUserManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Nifm
 {
+    [Service("nifm:u")]
     class IStaticService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IStaticService()
+        public IStaticService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs

@@ -4,13 +4,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ns
 {
+    [Service("aoc:u")]
     class IAddOnContentManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IAddOnContentManager()
+        public IAddOnContentManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs

@@ -6,13 +6,14 @@ using System.Text;
 
 namespace Ryujinx.HLE.HOS.Services.Ns
 {
+    [Service("ns:am")]
     class IApplicationManagerInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IApplicationManagerInterface()
+        public IApplicationManagerInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 4 - 2
Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs

@@ -3,13 +3,15 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ns
 {
+    [Service("ns:am2")]
+    [Service("ns:ec")]
     class IServiceGetterInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IServiceGetterInterface()
+        public IServiceGetterInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
@@ -19,7 +21,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns
 
         public long GetApplicationManagerInterface(ServiceCtx context)
         {
-            MakeObject(context, new IApplicationManagerInterface());
+            MakeObject(context, new IApplicationManagerInterface(context));
 
             return 0;
         }

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ns/ISystemUpdateInterface.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ns
 {
+    [Service("ns:su")]
     class ISystemUpdateInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISystemUpdateInterface()
+        public ISystemUpdateInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ns
 {
+    [Service("ns:vm")]
     class IVulnerabilityManagerInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IVulnerabilityManagerInterface()
+        public IVulnerabilityManagerInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 4 - 2
Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs

@@ -14,6 +14,8 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Nv
 {
+    [Service("nvdrv")]
+    [Service("nvdrv:a")]
     class INvDrvServices : IpcService
     {
         private delegate int IoctlProcessor(ServiceCtx context, int cmd);
@@ -38,7 +40,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
 
         private KEvent _event;
 
-        public INvDrvServices(Horizon system)
+        public INvDrvServices(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>()
             {
@@ -53,7 +55,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv
                 { 13, FinishInitialize       }
             };
 
-            _event = new KEvent(system);
+            _event = new KEvent(context.Device.System);
         }
 
         static INvDrvServices()

+ 5 - 1
Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs

@@ -3,13 +3,17 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Pctl
 {
+    [Service("pctl")]
+    [Service("pctl:a")]
+    [Service("pctl:r")]
+    [Service("pctl:s")]
     class IParentalControlServiceFactory : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IParentalControlServiceFactory()
+        public IParentalControlServiceFactory(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Pl/ISharedFontManager.cs

@@ -6,13 +6,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Pl
 {
+    [Service("pl:u")]
     class ISharedFontManager : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISharedFontManager()
+        public ISharedFontManager(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Pm
 {
+    [Service("pm:shell")]
     class IShellInterface : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IShellInterface()
+        public IShellInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 3 - 1
Ryujinx.HLE/HOS/Services/Prepo/IPrepoService.cs

@@ -4,13 +4,15 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Prepo
 {
+    [Service("prepo:a")]
+    [Service("prepo:u")]
     class IPrepoService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IPrepoService()
+        public IPrepoService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Psm/IPsmServer.cs

@@ -4,6 +4,7 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Psm
 {
+    [Service("psm")]
     class IPsmServer : IpcService
     {
         enum ChargerType
@@ -17,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Psm
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IPsmServer()
+        public IPsmServer(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 17 - 0
Ryujinx.HLE/HOS/Services/ServiceAttributes.cs

@@ -0,0 +1,17 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services
+{
+    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+    public class ServiceAttribute : Attribute
+    {
+        public readonly string Name;
+        public readonly object Parameter;
+
+        public ServiceAttribute(string name, object parameter = null)
+        {
+            Name      = name;
+            Parameter = parameter;
+        }
+    }
+}

+ 7 - 0
Ryujinx.HLE/HOS/Services/ServiceConfiguration.cs

@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services
+{
+    public static class ServiceConfiguration
+    {
+        public static bool IgnoreMissingServices { get; set; }
+    }
+}

+ 0 - 236
Ryujinx.HLE/HOS/Services/ServiceFactory.cs

@@ -1,236 +0,0 @@
-using Ryujinx.Common.Logging;
-using Ryujinx.HLE.HOS.Services.Acc;
-using Ryujinx.HLE.HOS.Services.Am;
-using Ryujinx.HLE.HOS.Services.Apm;
-using Ryujinx.HLE.HOS.Services.Aud;
-using Ryujinx.HLE.HOS.Services.Bsd;
-using Ryujinx.HLE.HOS.Services.Caps;
-using Ryujinx.HLE.HOS.Services.Es;
-using Ryujinx.HLE.HOS.Services.FspSrv;
-using Ryujinx.HLE.HOS.Services.Hid;
-using Ryujinx.HLE.HOS.Services.Hid.Irs;
-using Ryujinx.HLE.HOS.Services.Ldr;
-using Ryujinx.HLE.HOS.Services.Lm;
-using Ryujinx.HLE.HOS.Services.Mm;
-using Ryujinx.HLE.HOS.Services.Ncm;
-using Ryujinx.HLE.HOS.Services.Nfc.Nfp;
-using Ryujinx.HLE.HOS.Services.Ns;
-using Ryujinx.HLE.HOS.Services.Nv;
-using Ryujinx.HLE.HOS.Services.Pctl;
-using Ryujinx.HLE.HOS.Services.Pl;
-using Ryujinx.HLE.HOS.Services.Pm;
-using Ryujinx.HLE.HOS.Services.Prepo;
-using Ryujinx.HLE.HOS.Services.Psm;
-using Ryujinx.HLE.HOS.Services.Set;
-using Ryujinx.HLE.HOS.Services.Sfdnsres;
-using Ryujinx.HLE.HOS.Services.Sm;
-using Ryujinx.HLE.HOS.Services.Spl;
-using Ryujinx.HLE.HOS.Services.Ssl;
-using Ryujinx.HLE.HOS.Services.Vi;
-using System;
-
-namespace Ryujinx.HLE.HOS.Services
-{
-    public static class ServiceConfiguration
-    {
-        public static bool IgnoreMissingServices { get; set; }
-    }
-
-    static class ServiceFactory
-    {
-        public static IpcService MakeService(Horizon system, string name)
-        {
-            switch (name)
-            {
-                case "acc:u0":
-                    return new IAccountService();
-
-                case "acc:u1":
-                    return new IAccountService();
-
-                case "aoc:u":
-                    return new IAddOnContentManager();
-
-                case "apm":
-                    return new IManager();
-
-                case "apm:p":
-                    return new IManager();
-
-                case "appletAE":
-                    return new IAllSystemAppletProxiesService();
-
-                case "appletOE":
-                    return new IApplicationProxyService();
-
-                case "audout:u":
-                    return new IAudioOutManager();
-
-                case "audren:u":
-                    return new IAudioRendererManager();
-
-                case "bcat:a":
-                    return new Bcat.IServiceCreator();
-
-                case "bcat:m":
-                    return new Bcat.IServiceCreator();
-
-                case "bcat:u":
-                    return new Bcat.IServiceCreator();
-
-                case "bcat:s":
-                    return new Bcat.IServiceCreator();
-
-                case "bsd:s":
-                    return new IClient(true);
-
-                case "bsd:u":
-                    return new IClient(false);
-
-                case "caps:a":
-                    return new IAlbumAccessorService();
-
-                case "caps:ss":
-                    return new IScreenshotService();
-
-                case "csrng":
-                    return new IRandomInterface();
-
-                case "es":
-                    return new IeTicketService();
-
-                case "friend:a":
-                    return new Friend.IServiceCreator(Friend.FriendServicePermissionLevel.Admin);
-
-                case "friend:u":
-                    return new Friend.IServiceCreator(Friend.FriendServicePermissionLevel.User);
-
-                case "friend:v":
-                    return new Friend.IServiceCreator(Friend.FriendServicePermissionLevel.Overlay);
-
-                case "friend:m":
-                    return new Friend.IServiceCreator(Friend.FriendServicePermissionLevel.Manager);
-
-                case "friend:s":
-                    return new Friend.IServiceCreator(Friend.FriendServicePermissionLevel.System);
-
-                case "fsp-srv":
-                    return new IFileSystemProxy();
-
-                case "hid":
-                    return new IHidServer(system);
-
-                case "irs":
-                    return new IIrSensorServer();
-
-                case "ldr:ro":
-                    return new IRoInterface();
-
-                case "hwopus":
-                    return new IHardwareOpusDecoderManager();
-
-                case "lm":
-                    return new ILogService();
-
-                case "mm:u":
-                    return new IRequest();
-
-                case "ncm":
-                    return new IContentManager();
-
-                case "nfp:user":
-                    return new IUserManager();
-
-                case "nifm:u":
-                    return new Nifm.IStaticService();
-
-                case "ns:am":
-                    return new IApplicationManagerInterface();
-
-                case "ns:am2":
-                case "ns:ec":
-                    return new IServiceGetterInterface();
-
-                case "ns:su":
-                    return new ISystemUpdateInterface();
-
-                case "ns:vm":
-                    return new IVulnerabilityManagerInterface();
-
-                case "nvdrv":
-                    return new INvDrvServices(system);
-
-                case "nvdrv:a":
-                    return new INvDrvServices(system);
-
-                case "pctl:s":
-                    return new IParentalControlServiceFactory();
-
-                case "pctl:r":
-                    return new IParentalControlServiceFactory();
-
-                case "pctl:a":
-                    return new IParentalControlServiceFactory();
-
-                case "pctl":
-                    return new IParentalControlServiceFactory();
-
-                case "pl:u":
-                    return new ISharedFontManager();
-
-                case "pm:shell":
-                    return new IShellInterface();
-
-                case "prepo:a":
-                    return new IPrepoService();
-
-                case "prepo:u":
-                    return new IPrepoService();
-
-                case "psm":
-                    return new IPsmServer();
-
-                case "set":
-                    return new ISettingsServer();
-
-                case "set:sys":
-                    return new ISystemSettingsServer();
-
-                case "sfdnsres":
-                    return new IResolver();
-
-                case "sm:":
-                    return new IUserInterface();
-
-                case "ssl":
-                    return new ISslService();
-
-                case "time:a":
-                    return new Time.IStaticService();
-
-                case "time:s":
-                    return new Time.IStaticService();
-
-                case "time:u":
-                    return new Time.IStaticService();
-
-                case "vi:m":
-                    return new IManagerRootService();
-
-                case "vi:s":
-                    return new ISystemRootService();
-
-                case "vi:u":
-                    return new IApplicationRootService();
-            }
-
-            if (ServiceConfiguration.IgnoreMissingServices)
-            {
-                Logger.PrintWarning(LogClass.Service, $"Missing service {name} ignored");
-                return new DummyService(name);
-            }
-
-            throw new NotImplementedException(name);
-        }
-    }
-}

+ 2 - 1
Ryujinx.HLE/HOS/Services/Set/ISettingsServer.cs

@@ -8,13 +8,14 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Set
 {
+    [Service("set")]
     class ISettingsServer : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISettingsServer()
+        public ISettingsServer(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Set/ISystemSettingsServer.cs

@@ -11,13 +11,14 @@ using System.Text;
 
 namespace Ryujinx.HLE.HOS.Services.Set
 {
+    [Service("set:sys")]
     class ISystemSettingsServer : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISystemSettingsServer()
+        public ISystemSettingsServer(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Sfdnsres/IResolver.cs

@@ -10,13 +10,14 @@ using static Ryujinx.HLE.HOS.ErrorCode;
 
 namespace Ryujinx.HLE.HOS.Services.Sfdnsres
 {
+    [Service("sfdnsres")]
     class IResolver : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IResolver()
+        public IResolver(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 31 - 2
Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs

@@ -6,11 +6,16 @@ using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
+using System.Reflection;
 
 namespace Ryujinx.HLE.HOS.Services.Sm
 {
+    [Service("sm:")]
     class IUserInterface : IpcService
     {
+        private Dictionary<string, Type> _services;
+
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
@@ -19,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
 
         private bool _isInitialized;
 
-        public IUserInterface()
+        public IUserInterface(ServiceCtx context = null)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
@@ -30,6 +35,11 @@ namespace Ryujinx.HLE.HOS.Services.Sm
             };
 
             _registeredServices = new ConcurrentDictionary<string, KPort>();
+
+            _services = Assembly.GetExecutingAssembly().GetTypes()
+                .SelectMany(type => type.GetCustomAttributes(typeof(ServiceAttribute), true)
+                .Select(service => (((ServiceAttribute)service).Name, type)))
+                .ToDictionary(service => service.Name, service => service.type);
         }
 
         public static void InitializePort(Horizon system)
@@ -75,7 +85,26 @@ namespace Ryujinx.HLE.HOS.Services.Sm
             }
             else
             {
-                session.ClientSession.Service = ServiceFactory.MakeService(context.Device.System, name);
+                if (_services.TryGetValue(name, out Type type))
+                {
+                    ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
+
+                    session.ClientSession.Service = serviceAttribute.Parameter != null ? (IpcService)Activator.CreateInstance(type, context, serviceAttribute.Parameter)
+                                                                                       : (IpcService)Activator.CreateInstance(type, context);
+                }
+                else
+                {
+                    if (ServiceConfiguration.IgnoreMissingServices)
+                    {
+                        Logger.PrintWarning(LogClass.Service, $"Missing service {name} ignored");
+
+                        session.ClientSession.Service = new DummyService(name);
+                    }
+                    else
+                    {
+                        throw new NotImplementedException(name);
+                    }
+                }
             }
 
             if (context.Process.HandleTable.GenerateHandle(session.ClientSession, out int handle) != KernelResult.Success)

+ 2 - 1
Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs

@@ -5,6 +5,7 @@ using System.Security.Cryptography;
 
 namespace Ryujinx.HLE.HOS.Services.Spl
 {
+    [Service("csrng")]
     class IRandomInterface : IpcService, IDisposable
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
@@ -13,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Spl
 
         private RNGCryptoServiceProvider _rng;
 
-        public IRandomInterface()
+        public IRandomInterface(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs

@@ -4,13 +4,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Ssl
 {
+    [Service("ssl")]
     class ISslService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISslService()
+        public ISslService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 4 - 1
Ryujinx.HLE/HOS/Services/Time/IStaticService.cs

@@ -5,6 +5,9 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Time
 {
+    [Service("time:a")]
+    [Service("time:s")]
+    [Service("time:u")]
     class IStaticService : IpcService
     {
         private int _timeSharedMemoryNativeHandle = 0;
@@ -15,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
 
         private static readonly DateTime StartupDate = DateTime.UtcNow;
 
-        public IStaticService()
+        public IStaticService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Vi
 {
+    [Service("vi:u")]
     class IApplicationRootService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IApplicationRootService()
+        public IApplicationRootService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Vi
 {
+    [Service("vi:m")]
     class IManagerRootService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public IManagerRootService()
+        public IManagerRootService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 2 - 1
Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 
 namespace Ryujinx.HLE.HOS.Services.Vi
 {
+    [Service("vi:s")]
     class ISystemRootService : IpcService
     {
         private Dictionary<int, ServiceProcessRequest> _commands;
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        public ISystemRootService()
+        public ISystemRootService(ServiceCtx context)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {

+ 1 - 0
Ryujinx.HLE/Ryujinx.HLE.csproj

@@ -4,6 +4,7 @@
     <TargetFramework>netcoreapp2.1</TargetFramework>
     <RuntimeIdentifiers>win10-x64;osx-x64;linux-x64</RuntimeIdentifiers>
     <Configurations>Debug;Release;Profile Debug;Profile Release</Configurations>
+    <LangVersion>7.1</LangVersion>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">