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