diff --git a/src/LibHac/Fs/Shim/ProgramRegistry.cs b/src/LibHac/Fs/Shim/ProgramRegistry.cs index 79b61fd7..844103a3 100644 --- a/src/LibHac/Fs/Shim/ProgramRegistry.cs +++ b/src/LibHac/Fs/Shim/ProgramRegistry.cs @@ -20,7 +20,7 @@ public static class ProgramRegistry if (rc.IsFailure()) return rc.Miss(); rc = programRegistry.Get.RegisterProgram(processId, programId, storageId, new InBuffer(accessControlData), - new InBuffer(accessControlDescriptor)); + accessControlData.Length, new InBuffer(accessControlDescriptor), accessControlDescriptor.Length); fs.Impl.AbortIfNeeded(rc); if (rc.IsFailure()) return rc.Miss(); @@ -41,4 +41,4 @@ public static class ProgramRegistry return Result.Success; } -} +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/FileSystemProxyImpl.cs b/src/LibHac/FsSrv/FileSystemProxyImpl.cs index 35e54fa0..615e1dbc 100644 --- a/src/LibHac/FsSrv/FileSystemProxyImpl.cs +++ b/src/LibHac/FsSrv/FileSystemProxyImpl.cs @@ -138,7 +138,7 @@ public class FileSystemProxyImpl : IFileSystemProxy, IFileSystemProxyForLoader private ProgramIndexRegistryService GetProgramIndexRegistryService() { - return new ProgramIndexRegistryService(Globals.ProgramRegistryServiceImpl, _currentProcess); + return new ProgramIndexRegistryService(_fsServer, Globals.ProgramRegistryServiceImpl, _currentProcess); } private AccessLogService GetAccessLogService() @@ -1151,4 +1151,4 @@ public class FileSystemProxyImpl : IFileSystemProxy, IFileSystemProxyForLoader { return GetBaseFileSystemService().OpenBisWiper(ref outBisWiper, transferMemoryHandle, transferMemorySize); } -} +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/FileSystemServerInitializer.cs b/src/LibHac/FsSrv/FileSystemServerInitializer.cs index 93cd083c..8210b936 100644 --- a/src/LibHac/FsSrv/FileSystemServerInitializer.cs +++ b/src/LibHac/FsSrv/FileSystemServerInitializer.cs @@ -82,7 +82,7 @@ public static class FileSystemServerInitializer var programRegistryService = new ProgramRegistryServiceImpl(in programRegistryConfig); - server.InitializeProgramRegistryImpl(programRegistryService); + ProgramRegistryImpl.Initialize(server, programRegistryService); var baseStorageConfig = new BaseStorageServiceImpl.Configuration(); baseStorageConfig.BisStorageCreator = config.FsCreators.BuiltInStorageCreator; @@ -272,4 +272,4 @@ public class FileSystemServerConfig /// If null, an empty set will be created. /// public ExternalKeySet ExternalKeySet { get; set; } -} +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/FileSystemProxyServiceObject.cs b/src/LibHac/FsSrv/Impl/FileSystemProxyServiceObject.cs index 7c5f4933..595cd5f7 100644 --- a/src/LibHac/FsSrv/Impl/FileSystemProxyServiceObject.cs +++ b/src/LibHac/FsSrv/Impl/FileSystemProxyServiceObject.cs @@ -66,7 +66,8 @@ public static class FileSystemProxyServiceObject public void Dispose() { } public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId, - InBuffer accessControlData, InBuffer accessControlDescriptor) + InBuffer accessControlData, long accessControlDataSize, InBuffer accessControlDescriptor, + long accessControlDescriptorSize) { return ResultFs.PortAcceptableCountLimited.Log(); } @@ -81,4 +82,4 @@ public static class FileSystemProxyServiceObject return ResultFs.PortAcceptableCountLimited.Log(); } } -} +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/Impl/MultiCommitManager.cs b/src/LibHac/FsSrv/Impl/MultiCommitManager.cs index a147c4d0..0e0ca117 100644 --- a/src/LibHac/FsSrv/Impl/MultiCommitManager.cs +++ b/src/LibHac/FsSrv/Impl/MultiCommitManager.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using LibHac.Common; using LibHac.Diag; using LibHac.Fs; diff --git a/src/LibHac/FsSrv/ProgramIndexRegistryService.cs b/src/LibHac/FsSrv/ProgramIndexRegistryService.cs deleted file mode 100644 index 5bba7d95..00000000 --- a/src/LibHac/FsSrv/ProgramIndexRegistryService.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using LibHac.Common; -using LibHac.Fs; -using LibHac.FsSrv.Impl; -using LibHac.Sf; -using LibHac.Util; - -namespace LibHac.FsSrv; - -/// -/// Used to perform operations on the program index registry. -/// -/// Appropriate methods calls on IFileSystemProxy are forwarded to this class -/// which then checks the calling process' permissions and performs the requested operation. -///
Based on FS 10.0.0 (nnSdk 10.4.0)
-internal readonly struct ProgramIndexRegistryService -{ - private ProgramRegistryServiceImpl ServiceImpl { get; } - private ulong ProcessId { get; } - - public ProgramIndexRegistryService(ProgramRegistryServiceImpl serviceImpl, ulong processId) - { - ServiceImpl = serviceImpl; - ProcessId = processId; - } - - /// - /// Unregisters any previously registered program index map info and registers the provided map info. - /// - /// A buffer containing the program map info to register. - /// The number of programs to register. The provided buffer must be - /// large enough to hold this many entries. - /// : The operation was successful.
- /// : Insufficient permissions.
- /// : The buffer was too small to hold the specified - /// number of entries.
- public Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfo, int programCount) - { - // Verify the caller's permissions - Result rc = GetProgramInfo(out ProgramInfo programInfo, ProcessId); - if (rc.IsFailure()) return rc; - - if (!programInfo.AccessControl.CanCall(OperationType.RegisterProgramIndexMapInfo)) - return ResultFs.PermissionDenied.Log(); - - // Return early if the program count is 0 so we leave any previously - // registered entries as they were - if (programCount == 0) - return Result.Success; - - // Verify that the provided buffer is large enough to hold "programCount" entries - ReadOnlySpan - mapInfo = MemoryMarshal.Cast(programIndexMapInfo.Buffer); - - if (mapInfo.Length < programCount) - return ResultFs.InvalidSize.Log(); - - // Register the map info - return ServiceImpl.RegisterProgramIndexMapInfo(mapInfo.Slice(0, programCount)); - } - - /// - /// Gets the multi-program index of the calling process and the number of programs - /// in the current application. - /// - /// When this method returns successfully, contains the - /// program index of the calling process. - /// When this method returns successfully, contains the - /// number of programs in the current application. - /// : The operation was successful.
- /// : The calling program was not found - /// in the program registry. Something's wrong with Loader if this happens.
- public Result GetProgramIndex(out int programIndex, out int programCount) - { - UnsafeHelpers.SkipParamInit(out programIndex, out programCount); - - // No permissions are needed to call this method - Result rc = GetProgramInfo(out ProgramInfo programInfo, ProcessId); - if (rc.IsFailure()) return rc; - - // Try to get map info for this process - Optional mapInfo = ServiceImpl.GetProgramIndexMapInfo(programInfo.ProgramId); - - // Set the output program index if map info was found - programIndex = mapInfo.HasValue ? mapInfo.ValueRo.ProgramIndex : 0; - - // Set the number of programs in the current application - programCount = ServiceImpl.GetProgramIndexMapInfoCount(); - - return Result.Success; - } - - /// - private Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) - { - return ServiceImpl.GetProgramInfo(out programInfo, processId); - } -} diff --git a/src/LibHac/FsSrv/ProgramRegistryImpl.cs b/src/LibHac/FsSrv/ProgramRegistryImpl.cs index fc7c3633..9fdfcf26 100644 --- a/src/LibHac/FsSrv/ProgramRegistryImpl.cs +++ b/src/LibHac/FsSrv/ProgramRegistryImpl.cs @@ -1,4 +1,5 @@ -using LibHac.Fs; +using LibHac.Diag; +using LibHac.Fs; using LibHac.FsSrv.Impl; using LibHac.FsSrv.Sf; using LibHac.Ncm; @@ -6,15 +7,6 @@ using LibHac.Sf; namespace LibHac.FsSrv; -public static class ProgramRegistryImplGlobalMethods -{ - public static void InitializeProgramRegistryImpl(this FileSystemServer fsSrv, - ProgramRegistryServiceImpl serviceImpl) - { - fsSrv.Globals.ProgramRegistryImpl.ServiceImpl = serviceImpl; - } -} - internal struct ProgramRegistryImplGlobals { public ProgramRegistryServiceImpl ServiceImpl; @@ -27,12 +19,14 @@ internal struct ProgramRegistryImplGlobals /// is stored in a and includes the process' process ID, program ID, /// storage location and file system permissions. This allows FS to resolve the program ID and /// verify the permissions of any process calling it. -///
Based on FS 10.0.0 (nnSdk 10.4.0) +/// Based on FS 13.1.0 (nnSdk 13.4.0) public class ProgramRegistryImpl : IProgramRegistry { - private FileSystemServer _fsServer; private ulong _processId; + // LibHac addition + private FileSystemServer _fsServer; + private ref ProgramRegistryImplGlobals Globals => ref _fsServer.Globals.ProgramRegistryImpl; public ProgramRegistryImpl(FileSystemServer server) @@ -47,12 +41,20 @@ public class ProgramRegistryImpl : IProgramRegistry /// : The process ID is already registered.
/// : Insufficient permissions. /// - public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId, - InBuffer accessControlData, InBuffer accessControlDescriptor) + public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId, InBuffer accessControlData, + long accessControlDataSize, InBuffer accessControlDescriptor, long accessControlDescriptorSize) { + Assert.SdkRequiresNotNull(Globals.ServiceImpl); + if (!_fsServer.IsInitialProgram(_processId)) return ResultFs.PermissionDenied.Log(); + if (accessControlDataSize > accessControlData.Size) + return ResultFs.InvalidSize.Log(); + + if (accessControlDescriptorSize > accessControlDescriptor.Size) + return ResultFs.InvalidSize.Log(); + return Globals.ServiceImpl.RegisterProgramInfo(processId, programId, storageId, accessControlData.Buffer, accessControlDescriptor.Buffer); } @@ -63,6 +65,8 @@ public class ProgramRegistryImpl : IProgramRegistry /// public Result UnregisterProgram(ulong processId) { + Assert.SdkRequiresNotNull(Globals.ServiceImpl); + if (!_fsServer.IsInitialProgram(_processId)) return ResultFs.PermissionDenied.Log(); @@ -72,12 +76,16 @@ public class ProgramRegistryImpl : IProgramRegistry /// public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) { + Assert.SdkRequiresNotNull(Globals.ServiceImpl); + return Globals.ServiceImpl.GetProgramInfo(out programInfo, processId); } /// public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId) { + Assert.SdkRequiresNotNull(Globals.ServiceImpl); + return Globals.ServiceImpl.GetProgramInfoByProgramId(out programInfo, programId); } @@ -91,4 +99,22 @@ public class ProgramRegistryImpl : IProgramRegistry _processId = processId; return Result.Success; } + + /// + /// Sets the used by the provided . + /// This function must be called before calling functions on a . + /// This function must not be called more than once. + /// + /// The to initialize. + /// The + /// that will use. + public static void Initialize(FileSystemServer fsServer, ProgramRegistryServiceImpl serviceImpl) + { + ref ProgramRegistryImplGlobals globals = ref fsServer.Globals.ProgramRegistryImpl; + + Assert.SdkRequiresNotNull(serviceImpl); + Assert.SdkRequiresNull(globals.ServiceImpl); + + globals.ServiceImpl = serviceImpl; + } } \ No newline at end of file diff --git a/src/LibHac/FsSrv/ProgramRegistryService.cs b/src/LibHac/FsSrv/ProgramRegistryService.cs new file mode 100644 index 00000000..6295036d --- /dev/null +++ b/src/LibHac/FsSrv/ProgramRegistryService.cs @@ -0,0 +1,193 @@ +using System; +using System.Runtime.InteropServices; +using LibHac.Common; +using LibHac.Fs; +using LibHac.FsSrv.Impl; +using LibHac.Ncm; +using LibHac.Sf; +using LibHac.Util; + +namespace LibHac.FsSrv; + +/// +/// Used to perform operations on the program index registry. +/// +/// Appropriate methods calls on IFileSystemProxy are forwarded to this class +/// which then checks the calling process' permissions and performs the requested operation. +/// Based on FS 13.1.0 (nnSdk 13.4.0) +internal readonly struct ProgramIndexRegistryService +{ + private readonly ProgramRegistryServiceImpl _serviceImpl; + private readonly ulong _processId; + + // LibHac addition + private readonly FileSystemServer _fsServer; + + public ProgramIndexRegistryService(FileSystemServer fsServer, ProgramRegistryServiceImpl serviceImpl, + ulong processId) + { + _serviceImpl = serviceImpl; + _processId = processId; + _fsServer = fsServer; + } + + /// + /// Unregisters any previously registered program index map info and registers the provided map info. + /// + /// A buffer containing the program map info to register. + /// The number of programs to register. The provided buffer must be + /// large enough to hold this many entries. + /// : The operation was successful.
+ /// : Insufficient permissions.
+ /// : The buffer was too small to hold the specified + /// number of entries.
+ public Result RegisterProgramIndexMapInfo(InBuffer programIndexMapInfo, int programCount) + { + // Verify the caller's permissions + using (var programRegistry = new ProgramRegistryImpl(_fsServer)) + { + Result rc = programRegistry.GetProgramInfo(out ProgramInfo programInfo, _processId); + if (rc.IsFailure()) return rc; + + if (!programInfo.AccessControl.CanCall(OperationType.RegisterProgramIndexMapInfo)) + return ResultFs.PermissionDenied.Log(); + } + + // Return early if the program count is 0 so we leave any previously + // registered entries as they were + if (programCount == 0) + return Result.Success; + + // Verify that the provided buffer is large enough to hold "programCount" entries + ReadOnlySpan + mapInfo = MemoryMarshal.Cast(programIndexMapInfo.Buffer); + + if (mapInfo.Length < programCount) + return ResultFs.InvalidSize.Log(); + + // Register the map info + return _serviceImpl.ResetProgramIndexMapInfo(mapInfo.Slice(0, programCount)); + } + + /// + /// Gets the multi-program index of the calling process and the number of programs + /// in the current application. + /// + /// When this method returns successfully, contains the + /// program index of the calling process. + /// When this method returns successfully, contains the + /// number of programs in the current application. + /// : The operation was successful.
+ /// : The calling program was not found + /// in the program registry. Something's wrong with Loader if this happens.
+ public Result GetProgramIndex(out int programIndex, out int programCount) + { + UnsafeHelpers.SkipParamInit(out programIndex, out programCount); + + // No permissions are needed to call this method + Result rc = GetProgramInfo(out ProgramInfo programInfo, _processId); + if (rc.IsFailure()) return rc; + + // Try to get map info for this process + Optional mapInfo = _serviceImpl.GetProgramIndexMapInfo(programInfo.ProgramId); + + // Set the output program index if map info was found + programIndex = mapInfo.HasValue ? mapInfo.ValueRo.ProgramIndex : 0; + + // Set the number of programs in the current application + programCount = _serviceImpl.GetProgramIndexMapInfoCount(); + + return Result.Success; + } + + /// + private Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) + { + using var programRegistry = new ProgramRegistryImpl(_fsServer); + return programRegistry.GetProgramInfo(out programInfo, processId); + } +} + +/// +/// Manages the main program registry and the multi-program registry. +/// +/// Based on FS 13.1.0 (nnSdk 13.4.0) +public class ProgramRegistryServiceImpl : IDisposable +{ + // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable + private Configuration _config; + private ProgramRegistryManager _registryManager; + private ProgramIndexMapInfoManager _programIndexManager; + + public struct Configuration + { + // LibHac addition + public FileSystemServer FsServer; + } + + public ProgramRegistryServiceImpl(in Configuration config) + { + _config = config; + _registryManager = new ProgramRegistryManager(_config.FsServer); + _programIndexManager = new ProgramIndexMapInfoManager(); + } + + public void Dispose() + { + _registryManager?.Dispose(); + _programIndexManager?.Dispose(); + } + + /// + public Result RegisterProgramInfo(ulong processId, ProgramId programId, StorageId storageId, + ReadOnlySpan accessControlData, ReadOnlySpan accessControlDescriptor) + { + return _registryManager.RegisterProgram(processId, programId, storageId, accessControlData, + accessControlDescriptor); + } + + /// + public Result UnregisterProgramInfo(ulong processId) + { + return _registryManager.UnregisterProgram(processId); + } + + /// + public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) + { + return _registryManager.GetProgramInfo(out programInfo, processId); + } + + /// + public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId) + { + return _registryManager.GetProgramInfoByProgramId(out programInfo, programId); + } + + /// + public Result ResetProgramIndexMapInfo(ReadOnlySpan programIndexMapInfo) + { + return _programIndexManager.Reset(programIndexMapInfo); + } + + /// + public ProgramId GetProgramIdByIndex(ProgramId programId, byte programIndex) + { + return _programIndexManager.GetProgramId(programId, programIndex); + } + + /// + public Optional GetProgramIndexMapInfo(ProgramId programId) + { + return _programIndexManager.Get(programId); + } + + /// + /// Gets the number of programs in the currently registered application. + /// + /// The number of programs. + public int GetProgramIndexMapInfoCount() + { + return _programIndexManager.GetProgramCount(); + } +} \ No newline at end of file diff --git a/src/LibHac/FsSrv/ProgramRegistryServiceImpl.cs b/src/LibHac/FsSrv/ProgramRegistryServiceImpl.cs deleted file mode 100644 index 9d5a52b7..00000000 --- a/src/LibHac/FsSrv/ProgramRegistryServiceImpl.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using LibHac.Fs; -using LibHac.FsSrv.Impl; -using LibHac.Ncm; -using LibHac.Util; - -namespace LibHac.FsSrv; - -/// -/// Manages the main program registry and the multi-program registry. -/// -/// Based on FS 10.0.0 (nnSdk 10.4.0) -public class ProgramRegistryServiceImpl -{ - // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable - private Configuration _config; - private ProgramRegistryManager _registryManager; - private ProgramIndexMapInfoManager _programIndexManager; - - public ProgramRegistryServiceImpl(in Configuration config) - { - _config = config; - _registryManager = new ProgramRegistryManager(_config.FsServer); - _programIndexManager = new ProgramIndexMapInfoManager(); - } - - public struct Configuration - { - // LibHac addition - public FileSystemServer FsServer; - } - - /// - public Result RegisterProgramInfo(ulong processId, ProgramId programId, StorageId storageId, - ReadOnlySpan accessControlData, ReadOnlySpan accessControlDescriptor) - { - return _registryManager.RegisterProgram(processId, programId, storageId, accessControlData, - accessControlDescriptor); - } - - /// - public Result UnregisterProgramInfo(ulong processId) - { - return _registryManager.UnregisterProgram(processId); - } - - /// - public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId) - { - return _registryManager.GetProgramInfo(out programInfo, processId); - } - - /// - public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId) - { - return _registryManager.GetProgramInfoByProgramId(out programInfo, programId); - } - - /// - public ProgramId GetProgramIdByIndex(ProgramId programId, byte programIndex) - { - return _programIndexManager.GetProgramId(programId, programIndex); - } - - /// - public Optional GetProgramIndexMapInfo(ProgramId programId) - { - return _programIndexManager.Get(programId); - } - - /// - /// Gets the number of programs in the currently registered application. - /// - /// The number of programs. - public int GetProgramIndexMapInfoCount() - { - return _programIndexManager.GetProgramCount(); - } - - /// - public Result RegisterProgramIndexMapInfo(ReadOnlySpan programIndexMapInfo) - { - return _programIndexManager.Reset(programIndexMapInfo); - } -} diff --git a/src/LibHac/FsSrv/Sf/IProgramRegistry.cs b/src/LibHac/FsSrv/Sf/IProgramRegistry.cs index 00a8cfb5..d0cb7705 100644 --- a/src/LibHac/FsSrv/Sf/IProgramRegistry.cs +++ b/src/LibHac/FsSrv/Sf/IProgramRegistry.cs @@ -6,9 +6,9 @@ namespace LibHac.FsSrv.Sf; public interface IProgramRegistry : IDisposable { - Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId, - InBuffer accessControlData, InBuffer accessControlDescriptor); + Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId, InBuffer accessControlData, + long accessControlDataSize, InBuffer accessControlDescriptor, long accessControlDescriptorSize); Result UnregisterProgram(ulong processId); Result SetCurrentProcess(ulong processId); -} +} \ No newline at end of file