Add functions to ProgramRegistryService

Adds RegisterProgramIndexMapInfo and GetProgramIndexForAccessLog to both FileSystemProxy and ProgramRegistryService
This commit is contained in:
Alex Barney 2020-08-22 01:03:32 -07:00
parent 0b050d2189
commit deaf111ac3
10 changed files with 153 additions and 80 deletions

View file

@ -37,7 +37,7 @@ namespace LibHac.FsSrv
private ProgramRegistryService GetProgramRegistryService()
{
return new ProgramRegistryService(FsProxyCore.Config.ProgramRegistryService, CurrentProcess);
return new ProgramRegistryService(FsProxyCore.Config.ProgramRegistryServiceImpl, CurrentProcess);
}
public Result OpenFileSystemWithId(out IFileSystem fileSystem, ref FsPath path, ulong id, FileSystemProxyType type)
@ -649,6 +649,11 @@ namespace LibHac.FsSrv
throw new NotImplementedException();
}
public Result RegisterProgramIndexMapInfo(ReadOnlySpan<byte> programIndexMapInfoBuffer, int programCount)
{
return GetProgramRegistryService().RegisterProgramIndexMapInfo(programIndexMapInfoBuffer, programCount);
}
public Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path)
{
throw new NotImplementedException();
@ -1087,7 +1092,7 @@ namespace LibHac.FsSrv
public Result GetProgramIndexForAccessLog(out int programIndex, out int programCount)
{
throw new NotImplementedException();
return GetProgramRegistryService().GetProgramIndexForAccessLog(out programIndex, out programCount);
}
public Result OutputAccessLogToSdCard(U8Span logString)
@ -1188,6 +1193,11 @@ namespace LibHac.FsSrv
}
}
private Result GetProgramInfo(out ProgramInfo programInfo)
{
return FsProxyCore.ProgramRegistry.GetProgramInfo(out programInfo, CurrentProcess);
}
private static bool IsSystemSaveDataId(ulong id)
{
return (long)id < 0;

View file

@ -5,6 +5,6 @@ namespace LibHac.FsSrv
public class FileSystemProxyConfiguration
{
public FileSystemCreators FsCreatorInterfaces { get; set; }
public ProgramRegistryServiceImpl ProgramRegistryService { get; set; }
public ProgramRegistryServiceImpl ProgramRegistryServiceImpl { get; set; }
}
}

View file

@ -35,7 +35,7 @@ namespace LibHac.FsSrv
public FileSystemProxyCore(FileSystemProxyConfiguration config, ExternalKeySet externalKeys, IDeviceOperator deviceOperator)
{
Config = config;
ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService);
ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryServiceImpl);
ExternalKeys = externalKeys ?? new ExternalKeySet();
DeviceOperator = deviceOperator;
}

View file

@ -37,7 +37,7 @@ namespace LibHac.FsSrv
var fspConfig = new FileSystemProxyConfiguration
{
FsCreatorInterfaces = config.FsCreators,
ProgramRegistryService = new ProgramRegistryServiceImpl(this)
ProgramRegistryServiceImpl = new ProgramRegistryServiceImpl(this)
};
FsProxyCore = new FileSystemProxyCore(fspConfig, externalKeySet, config.DeviceOperator);

View file

@ -88,6 +88,7 @@ namespace LibHac.FsSrv
Result SetSdCardAccessibility(bool isAccessible);
Result IsSdCardAccessible(out bool isAccessible);
Result RegisterProgramIndexMapInfo(ReadOnlySpan<byte> programIndexMapInfoBuffer, int programCount);
Result SetBisRootForHost(BisPartitionId partitionId, ref FsPath path);
Result SetSaveDataSize(long saveDataSize, long saveDataJournalSize);
Result SetSaveDataRootPath(ref FsPath path);

View file

@ -37,7 +37,7 @@ namespace LibHac.FsSrv.Impl
}
/// <summary>
/// Registers a program with information about the program in the program registry.
/// Registers a program with information about that program in the program registry.
/// </summary>
/// <param name="processId">The process ID of the program.</param>
/// <param name="programId">The <see cref="ProgramId"/> of the program.</param>

View file

@ -5,30 +5,36 @@ using LibHac.Ncm;
namespace LibHac.FsSrv
{
/// <summary>
/// Keeps track of the program IDs and program indexes of each program in a multi-program application.
/// </summary>
public class ProgramIndexMapInfoManager
{
private LinkedList<ProgramIndexMapInfo> MapEntries { get; } = new LinkedList<ProgramIndexMapInfo>();
/// <summary>
/// Clears any existing
/// Unregisters any previously registered program index map info and registers the provided map info.
/// </summary>
/// <param name="entries">The entries </param>
/// <param name="programIndexMapInfo">The program map info entries to register.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.</returns>
public Result Reset(ReadOnlySpan<ProgramIndexMapInfo> entries)
public Result Reset(ReadOnlySpan<ProgramIndexMapInfo> programIndexMapInfo)
{
lock (MapEntries)
{
ClearImpl();
for (int i = 0; i < entries.Length; i++)
for (int i = 0; i < programIndexMapInfo.Length; i++)
{
MapEntries.AddLast(entries[i]);
MapEntries.AddLast(programIndexMapInfo[i]);
}
return Result.Success;
}
}
/// <summary>
/// Unregisters all currently registered program index map info.
/// </summary>
public void Clear()
{
lock (MapEntries)
@ -37,6 +43,12 @@ namespace LibHac.FsSrv
}
}
/// <summary>
/// Gets the <see cref="ProgramIndexMapInfo"/> associated with the specified program ID.
/// </summary>
/// <param name="programId">The program ID of the map info to get.</param>
/// <returns>If the program ID was found, the <see cref="ProgramIndexMapInfo"/> associated
/// with that ID; otherwise, <see langword="null"/>.</returns>
public ProgramIndexMapInfo? Get(ProgramId programId)
{
lock (MapEntries)
@ -72,6 +84,10 @@ namespace LibHac.FsSrv
}
}
/// <summary>
/// Gets the number of currently registered programs,
/// </summary>
/// <returns>The number of registered programs.</returns>
public int GetProgramCount()
{
lock (MapEntries)

View file

@ -8,6 +8,8 @@ namespace LibHac.FsSrv
internal class ProgramRegistryImpl
{
private ulong _processId;
// Note: FS keeps this object as a global variable
private readonly ProgramRegistryServiceImpl _registryService;
public ProgramRegistryImpl(ProgramRegistryServiceImpl registryService)
@ -22,17 +24,10 @@ namespace LibHac.FsSrv
_registryService = registryService;
}
/// <summary>
/// Registers a program with information about the program in the program registry.
/// </summary>
/// <param name="processId">The process ID of the program.</param>
/// <param name="programId">The <see cref="ProgramId"/> of the program.</param>
/// <param name="storageId">The <see cref="StorageId"/> where the program is located.</param>
/// <param name="accessControlData">The FS access control data header located in the program's ACI.</param>
/// <param name="accessControlDescriptor">The FS access control descriptor located in the program's ACID.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.InvalidArgument"/>: The process ID is already registered.<br/>
/// <see cref="ResultFs.PermissionDenied"/>: Insufficient permissions.</returns>
/// <inheritdoc cref="ProgramRegistryManager.RegisterProgram"/>
public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId,
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
{
@ -43,13 +38,10 @@ namespace LibHac.FsSrv
accessControlDescriptor);
}
/// <summary>
/// Unregisters the program with the specified process ID.
/// </summary>
/// <param name="processId">The process ID of the program to unregister.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.InvalidArgument"/>: The process ID is not registered.<br/>
/// <see cref="ResultFs.PermissionDenied"/>: Insufficient permissions.</returns>
/// <inheritdoc cref="ProgramRegistryManager.UnregisterProgram" />
public Result UnregisterProgram(ulong processId)
{
if (!ProgramInfo.IsInitialProgram(_processId))
@ -58,27 +50,13 @@ namespace LibHac.FsSrv
return _registryService.UnregisterProgram(processId);
}
/// <summary>
/// Gets the <see cref="ProgramInfo"/> associated with the specified process ID.
/// </summary>
/// <param name="programInfo">If the method returns successfully, contains the <see cref="ProgramInfo"/>
/// associated with the specified process ID.</param>
/// <param name="processId">The process ID of the <see cref="ProgramInfo"/> to get.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.TargetProgramNotFound"/>: The <see cref="ProgramInfo"/> was not found.</returns>
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfo"/>
public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
return _registryService.GetProgramInfo(out programInfo, processId);
}
/// <summary>
/// Gets the <see cref="ProgramInfo"/> associated with the specified program ID.
/// </summary>
/// <param name="programInfo">If the method returns successfully, contains the <see cref="ProgramInfo"/>
/// associated with the specified program ID.</param>
/// <param name="programId">The program ID of the <see cref="ProgramInfo"/> to get.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.TargetProgramNotFound"/>: The <see cref="ProgramInfo"/> was not found.</returns>
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfoByProgramId"/>
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
{
return _registryService.GetProgramInfoByProgramId(out programInfo, programId);

View file

@ -1,4 +1,10 @@
namespace LibHac.FsSrv
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using LibHac.Fs;
using LibHac.FsSrv.Impl;
namespace LibHac.FsSrv
{
internal readonly struct ProgramRegistryService
{
@ -10,5 +16,78 @@
ServiceImpl = serviceImpl;
ProcessId = processId;
}
/// <summary>
/// Unregisters any previously registered program index map info and registers the provided map info.
/// </summary>
/// <param name="programIndexMapInfo">A buffer containing the program map info to register.</param>
/// <param name="programCount">The number of programs to register. The provided buffer must be
/// large enough to hold this many <see cref="ProgramIndexMapInfo"/> entries.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.PermissionDenied"/>: Insufficient permissions.<br/>
/// <see cref="ResultFs.InvalidSize"/>: The buffer was too small to hold the specified
/// number of <see cref="ProgramIndexMapInfo"/> entries.</returns>
public Result RegisterProgramIndexMapInfo(ReadOnlySpan<byte> 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<ProgramIndexMapInfo>
mapInfo = MemoryMarshal.Cast<byte, ProgramIndexMapInfo>(programIndexMapInfo);
if (mapInfo.Length < programCount)
return ResultFs.InvalidSize.Log();
// Register the map info
return ServiceImpl.RegisterProgramIndexMapInfo(mapInfo.Slice(0, programCount));
}
/// <summary>
/// Gets the multi-program index of the calling process and the number of programs
/// in the current application.
/// </summary>
/// <param name="programIndex">When this method returns successfully, contains the
/// program index of the calling process.</param>
/// <param name="programCount">When this method returns successfully, contains the
/// number of programs in the current application.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.TargetProgramNotFound"/>: The calling program was not found
/// in the program registry. Something's wrong with Loader if this happens.</returns>
public Result GetProgramIndexForAccessLog(out int programIndex, out int programCount)
{
Unsafe.SkipInit(out programIndex);
Unsafe.SkipInit(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
ProgramIndexMapInfo? mapInfo = ServiceImpl.GetProgramIndexMapInfo(programInfo.ProgramId);
// Set the output program index if map info was found
programIndex = mapInfo?.ProgramIndex ?? 0;
// Set the number of programs in the current application
programCount = ServiceImpl.GetProgramIndexMapInfoCount();
return Result.Success;
}
/// <inheritdoc cref="ProgramRegistryServiceImpl.GetProgramInfo"/>
private Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
return ServiceImpl.GetProgramInfo(out programInfo, processId);
}
}
}

View file

@ -5,6 +5,9 @@ using LibHac.Ncm;
namespace LibHac.FsSrv
{
/// <summary>
/// Manages the main program registry and the multi-program registry.
/// </summary>
public class ProgramRegistryServiceImpl
{
private ProgramRegistryManager RegistryManager { get; }
@ -16,16 +19,7 @@ namespace LibHac.FsSrv
ProgramIndexManager = new ProgramIndexMapInfoManager();
}
/// <summary>
/// Registers a program with information about the program in the program registry.
/// </summary>
/// <param name="processId">The process ID of the program.</param>
/// <param name="programId">The <see cref="ProgramId"/> of the program.</param>
/// <param name="storageId">The <see cref="StorageId"/> where the program is located.</param>
/// <param name="accessControlData">The FS access control data header located in the program's ACI.</param>
/// <param name="accessControlDescriptor">The FS access control descriptor located in the program's ACID.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.InvalidArgument"/>: The process ID is already registered.</returns>
/// <inheritdoc cref="ProgramRegistryManager.RegisterProgram"/>
public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId,
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
{
@ -33,54 +27,49 @@ namespace LibHac.FsSrv
accessControlDescriptor);
}
/// <summary>
/// Unregisters the program with the specified process ID.
/// </summary>
/// <param name="processId">The process ID of the program to unregister.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.InvalidArgument"/>: The process ID is not registered.</returns>
/// <inheritdoc cref="ProgramRegistryManager.UnregisterProgram" />
public Result UnregisterProgram(ulong processId)
{
return RegistryManager.UnregisterProgram(processId);
}
/// <summary>
/// Gets the <see cref="ProgramInfo"/> associated with the specified process ID.
/// </summary>
/// <param name="programInfo">If the method returns successfully, contains the <see cref="ProgramInfo"/>
/// associated with the specified process ID.</param>
/// <param name="processId">The process ID of the <see cref="ProgramInfo"/> to get.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.TargetProgramNotFound"/>: The <see cref="ProgramInfo"/> was not found.</returns>
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfo"/>
public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
{
return RegistryManager.GetProgramInfo(out programInfo, processId);
}
/// <summary>
/// Gets the <see cref="ProgramInfo"/> associated with the specified program ID.
/// </summary>
/// <param name="programInfo">If the method returns successfully, contains the <see cref="ProgramInfo"/>
/// associated with the specified program ID.</param>
/// <param name="programId">The program ID of the <see cref="ProgramInfo"/> to get.</param>
/// <returns><see cref="Result.Success"/>: The operation was successful.<br/>
/// <see cref="ResultFs.TargetProgramNotFound"/>: The <see cref="ProgramInfo"/> was not found.</returns>
/// <inheritdoc cref="ProgramRegistryManager.GetProgramInfoByProgramId"/>
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
{
return RegistryManager.GetProgramInfoByProgramId(out programInfo, programId);
}
/// <summary>
/// Gets the <see cref="ProgramId"/> of the program with index <paramref name="programIndex"/> in the
/// multi-program app <paramref name="programId"/> is part of.
/// </summary>
/// <param name="programId">A program ID in the multi-program app to query.</param>
/// <param name="programIndex">The index of the program to get.</param>
/// <returns>If the program exists, the ID of the program with the specified index,
/// otherwise <see cref="ProgramId.InvalidId"/></returns>
/// <inheritdoc cref="ProgramIndexMapInfoManager.GetProgramId"/>
public ProgramId GetProgramId(ProgramId programId, byte programIndex)
{
return ProgramIndexManager.GetProgramId(programId, programIndex);
}
/// <inheritdoc cref="ProgramIndexMapInfoManager.Get"/>
public ProgramIndexMapInfo? GetProgramIndexMapInfo(ProgramId programId)
{
return ProgramIndexManager.Get(programId);
}
/// <summary>
/// Gets the number of programs in the currently registered application.
/// </summary>
/// <returns>The number of programs.</returns>
public int GetProgramIndexMapInfoCount()
{
return ProgramIndexManager.GetProgramCount();
}
/// <inheritdoc cref="ProgramIndexMapInfoManager.Reset"/>
public Result RegisterProgramIndexMapInfo(ReadOnlySpan<ProgramIndexMapInfo> programIndexMapInfo)
{
return ProgramIndexManager.Reset(programIndexMapInfo);
}
}
}