mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Add the program registry
This commit is contained in:
parent
76d21263da
commit
004e46cacc
@ -40,11 +40,12 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary
|
||||
2,3005,,OutOfRange,
|
||||
|
||||
2,3200,3499,AllocationMemoryFailed,
|
||||
2,3312,,AesXtsFileFileStorageAllocationError,
|
||||
2,3313,,AesXtsFileXtsStorageAllocationError,
|
||||
2,3314,,AesXtsFileAlignmentStorageAllocationError,
|
||||
2,3315,,AesXtsFileStorageFileAllocationError,
|
||||
2,3383,,AesXtsFileSubStorageAllocationError,
|
||||
2,3258,,AllocationFailureInProgramRegistryManagerA,In RegisterProgram allocating ProgramInfoNode
|
||||
2,3312,,AllocationFailureInAesXtsFileA,In Initialize allocating FileStorage
|
||||
2,3313,,AllocationFailureInAesXtsFileB,In Initialize allocating AesXtsStorage
|
||||
2,3314,,AllocationFailureInAesXtsFileC,In Initialize allocating AlignmentMatchingStoragePooledBuffer
|
||||
2,3315,,AllocationFailureInAesXtsFileD,In Initialize allocating StorageFile
|
||||
2,3383,,AllocationFailureInAesXtsFileE,In Initialize allocating SubStorage
|
||||
|
||||
2,3500,3999,MmcAccessFailed,
|
||||
|
||||
@ -234,6 +235,7 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary
|
||||
2,6465,,UserNotExist,
|
||||
|
||||
2,6600,6699,EntryNotFound,
|
||||
2,6605,,TargetProgramNotFound,Specified program is not found in the program registry.
|
||||
2,6606,,TargetProgramIndexNotFound,Specified program index is not found
|
||||
|
||||
2,6700,6799,OutOfResource,
|
||||
|
Can't render this file because it has a wrong number of fields in line 154.
|
@ -96,16 +96,18 @@ namespace LibHac.Fs
|
||||
|
||||
/// <summary>Error code: 2002-3200; Range: 3200-3499; Inner value: 0x190002</summary>
|
||||
public static Result.Base AllocationMemoryFailed { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 3200, 3499); }
|
||||
/// <summary>Error code: 2002-3312; Inner value: 0x19e002</summary>
|
||||
public static Result.Base AesXtsFileFileStorageAllocationError => new Result.Base(ModuleFs, 3312);
|
||||
/// <summary>Error code: 2002-3313; Inner value: 0x19e202</summary>
|
||||
public static Result.Base AesXtsFileXtsStorageAllocationError => new Result.Base(ModuleFs, 3313);
|
||||
/// <summary>Error code: 2002-3314; Inner value: 0x19e402</summary>
|
||||
public static Result.Base AesXtsFileAlignmentStorageAllocationError => new Result.Base(ModuleFs, 3314);
|
||||
/// <summary>Error code: 2002-3315; Inner value: 0x19e602</summary>
|
||||
public static Result.Base AesXtsFileStorageFileAllocationError => new Result.Base(ModuleFs, 3315);
|
||||
/// <summary>Error code: 2002-3383; Inner value: 0x1a6e02</summary>
|
||||
public static Result.Base AesXtsFileSubStorageAllocationError => new Result.Base(ModuleFs, 3383);
|
||||
/// <summary>In RegisterProgram allocating ProgramInfoNode<br/>Error code: 2002-3258; Inner value: 0x197402</summary>
|
||||
public static Result.Base AllocationFailureInProgramRegistryManagerA => new Result.Base(ModuleFs, 3258);
|
||||
/// <summary>In Initialize allocating FileStorage<br/>Error code: 2002-3312; Inner value: 0x19e002</summary>
|
||||
public static Result.Base AllocationFailureInAesXtsFileA => new Result.Base(ModuleFs, 3312);
|
||||
/// <summary>In Initialize allocating AesXtsStorage<br/>Error code: 2002-3313; Inner value: 0x19e202</summary>
|
||||
public static Result.Base AllocationFailureInAesXtsFileB => new Result.Base(ModuleFs, 3313);
|
||||
/// <summary>In Initialize allocating AlignmentMatchingStoragePooledBuffer<br/>Error code: 2002-3314; Inner value: 0x19e402</summary>
|
||||
public static Result.Base AllocationFailureInAesXtsFileC => new Result.Base(ModuleFs, 3314);
|
||||
/// <summary>In Initialize allocating StorageFile<br/>Error code: 2002-3315; Inner value: 0x19e602</summary>
|
||||
public static Result.Base AllocationFailureInAesXtsFileD => new Result.Base(ModuleFs, 3315);
|
||||
/// <summary>In Initialize allocating SubStorage<br/>Error code: 2002-3383; Inner value: 0x1a6e02</summary>
|
||||
public static Result.Base AllocationFailureInAesXtsFileE => new Result.Base(ModuleFs, 3383);
|
||||
|
||||
/// <summary>Error code: 2002-3500; Range: 3500-3999; Inner value: 0x1b5802</summary>
|
||||
public static Result.Base MmcAccessFailed { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 3500, 3999); }
|
||||
@ -452,6 +454,8 @@ namespace LibHac.Fs
|
||||
|
||||
/// <summary>Error code: 2002-6600; Range: 6600-6699; Inner value: 0x339002</summary>
|
||||
public static Result.Base EntryNotFound { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6600, 6699); }
|
||||
/// <summary>Specified program is not found in the program registry.<br/>Error code: 2002-6605; Inner value: 0x339a02</summary>
|
||||
public static Result.Base TargetProgramNotFound => new Result.Base(ModuleFs, 6605);
|
||||
/// <summary>Specified program index is not found<br/>Error code: 2002-6606; Inner value: 0x339c02</summary>
|
||||
public static Result.Base TargetProgramIndexNotFound => new Result.Base(ModuleFs, 6606);
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace LibHac.FsSrv
|
||||
private FileSystemProxyCore FsProxyCore { get; }
|
||||
internal FileSystemServer FsServer { get; }
|
||||
|
||||
public long CurrentProcess { get; private set; }
|
||||
public ulong CurrentProcess { get; private set; }
|
||||
|
||||
public long SaveDataSize { get; private set; }
|
||||
public long SaveDataJournalSize { get; private set; }
|
||||
@ -29,12 +29,17 @@ namespace LibHac.FsSrv
|
||||
FsProxyCore = fsProxyCore;
|
||||
FsServer = fsServer;
|
||||
|
||||
CurrentProcess = -1;
|
||||
CurrentProcess = ulong.MaxValue;
|
||||
SaveDataSize = 0x2000000;
|
||||
SaveDataJournalSize = 0x1000000;
|
||||
AutoCreateSaveData = true;
|
||||
}
|
||||
|
||||
private ProgramRegistryService GetProgramRegistryService()
|
||||
{
|
||||
return new ProgramRegistryService(FsProxyCore.Config.ProgramRegistryService, CurrentProcess);
|
||||
}
|
||||
|
||||
public Result OpenFileSystemWithId(out IFileSystem fileSystem, ref FsPath path, ulong id, FileSystemProxyType type)
|
||||
{
|
||||
fileSystem = default;
|
||||
@ -66,7 +71,7 @@ namespace LibHac.FsSrv
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Result SetCurrentProcess(long processId)
|
||||
public Result SetCurrentProcess(ulong processId)
|
||||
{
|
||||
CurrentProcess = processId;
|
||||
|
||||
|
10
src/LibHac/FsSrv/FileSystemProxyConfiguration.cs
Normal file
10
src/LibHac/FsSrv/FileSystemProxyConfiguration.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using LibHac.FsSrv.Creators;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
public class FileSystemProxyConfiguration
|
||||
{
|
||||
public FileSystemCreators FsCreatorInterfaces { get; set; }
|
||||
public ProgramRegistryServiceImpl ProgramRegistryService { get; set; }
|
||||
}
|
||||
}
|
@ -15,7 +15,10 @@ namespace LibHac.FsSrv
|
||||
{
|
||||
public class FileSystemProxyCore
|
||||
{
|
||||
private FileSystemCreators FsCreators { get; }
|
||||
internal FileSystemProxyConfiguration Config { get; }
|
||||
private FileSystemCreators FsCreators => Config.FsCreatorInterfaces;
|
||||
internal ProgramRegistryImpl ProgramRegistry { get; }
|
||||
|
||||
private ExternalKeySet ExternalKeys { get; }
|
||||
private IDeviceOperator DeviceOperator { get; }
|
||||
|
||||
@ -29,9 +32,10 @@ namespace LibHac.FsSrv
|
||||
|
||||
internal ISaveDataIndexerManager SaveDataIndexerManager { get; private set; }
|
||||
|
||||
public FileSystemProxyCore(FileSystemCreators fsCreators, ExternalKeySet externalKeys, IDeviceOperator deviceOperator)
|
||||
public FileSystemProxyCore(FileSystemProxyConfiguration config, ExternalKeySet externalKeys, IDeviceOperator deviceOperator)
|
||||
{
|
||||
FsCreators = fsCreators;
|
||||
Config = config;
|
||||
ProgramRegistry = new ProgramRegistryImpl(Config.ProgramRegistryService);
|
||||
ExternalKeys = externalKeys ?? new ExternalKeySet();
|
||||
DeviceOperator = deviceOperator;
|
||||
}
|
||||
|
@ -34,7 +34,13 @@ namespace LibHac.FsSrv
|
||||
ExternalKeySet externalKeySet = config.ExternalKeySet ?? new ExternalKeySet();
|
||||
Timer = config.TimeSpanGenerator ?? new StopWatchTimeSpanGenerator();
|
||||
|
||||
FsProxyCore = new FileSystemProxyCore(config.FsCreators, externalKeySet, config.DeviceOperator);
|
||||
var fspConfig = new FileSystemProxyConfiguration
|
||||
{
|
||||
FsCreatorInterfaces = config.FsCreators,
|
||||
ProgramRegistryService = new ProgramRegistryServiceImpl(this)
|
||||
};
|
||||
|
||||
FsProxyCore = new FileSystemProxyCore(fspConfig, externalKeySet, config.DeviceOperator);
|
||||
var fsProxy = new FileSystemProxy(FsProxyCore, this);
|
||||
FsClient = new FileSystemClient(this, fsProxy, Timer);
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace LibHac.FsSrv
|
||||
{
|
||||
public interface IFileSystemProxy
|
||||
{
|
||||
Result SetCurrentProcess(long processId);
|
||||
Result SetCurrentProcess(ulong processId);
|
||||
Result OpenDataFileSystemByCurrentProcess(out IFileSystem fileSystem);
|
||||
Result OpenFileSystemWithPatch(out IFileSystem fileSystem, ProgramId programId, FileSystemProxyType type);
|
||||
Result OpenFileSystemWithId(out IFileSystem fileSystem, ref FsPath path, ulong id, FileSystemProxyType type);
|
||||
|
211
src/LibHac/FsSrv/Impl/ProgramRegistryManager.cs
Normal file
211
src/LibHac/FsSrv/Impl/ProgramRegistryManager.cs
Normal file
@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Ncm;
|
||||
|
||||
namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
internal class ProgramRegistryManager
|
||||
{
|
||||
// Note: FS keeps each ProgramInfo in a shared_ptr, but there aren't any non-memory resources
|
||||
// that need to be freed, so we use plain ProgramInfos
|
||||
private LinkedList<ProgramInfo> ProgramInfoList { get; }
|
||||
private FileSystemServer FsServer { get; }
|
||||
|
||||
// Note: This variable is global in FS. It's moved to ProgramRegistryManager here because it
|
||||
// relies on some state kept in FileSystemServer, and it's only used by ProgramRegistryManager
|
||||
private ProgramInfo _programInfoForInitialProcess;
|
||||
private readonly object _programInfoForInitialProcessGuard = new object();
|
||||
|
||||
public ProgramRegistryManager(FileSystemServer fsServer)
|
||||
{
|
||||
ProgramInfoList = new LinkedList<ProgramInfo>();
|
||||
FsServer = fsServer;
|
||||
}
|
||||
|
||||
private ProgramInfo GetProgramInfoForInitialProcess()
|
||||
{
|
||||
if (_programInfoForInitialProcess == null)
|
||||
{
|
||||
lock (_programInfoForInitialProcessGuard)
|
||||
{
|
||||
_programInfoForInitialProcess ??= ProgramInfo.CreateProgramInfoForInitialProcess(FsServer);
|
||||
}
|
||||
}
|
||||
|
||||
return _programInfoForInitialProcess;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId,
|
||||
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
var programInfo = new ProgramInfo(FsServer, processId, programId, storageId, accessControlData,
|
||||
accessControlDescriptor);
|
||||
|
||||
lock (ProgramInfoList)
|
||||
{
|
||||
foreach (ProgramInfo info in ProgramInfoList)
|
||||
{
|
||||
if (info.Contains(processId))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
ProgramInfoList.AddLast(programInfo);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Result UnregisterProgram(ulong processId)
|
||||
{
|
||||
lock (ProgramInfoList)
|
||||
{
|
||||
for (LinkedListNode<ProgramInfo> node = ProgramInfoList.First; node != null; node = node.Next)
|
||||
{
|
||||
if (node.Value.Contains(processId))
|
||||
{
|
||||
ProgramInfoList.Remove(node);
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Result GetProgramInfo(out ProgramInfo programInfo, ulong processId)
|
||||
{
|
||||
lock (ProgramInfoList)
|
||||
{
|
||||
if(ProgramInfo.IsInitialProgram(processId))
|
||||
{
|
||||
programInfo = GetProgramInfoForInitialProcess();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
foreach (ProgramInfo info in ProgramInfoList)
|
||||
{
|
||||
if (info.Contains(processId))
|
||||
{
|
||||
programInfo = info;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
programInfo = default;
|
||||
return ResultFs.TargetProgramNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
|
||||
{
|
||||
lock (ProgramInfoList)
|
||||
{
|
||||
foreach (ProgramInfo info in ProgramInfoList)
|
||||
{
|
||||
if (info.ProgramId.Value == programId)
|
||||
{
|
||||
programInfo = info;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
programInfo = default;
|
||||
return ResultFs.TargetProgramNotFound.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProgramInfo
|
||||
{
|
||||
private ulong ProcessId { get; }
|
||||
public ProgramId ProgramId { get; }
|
||||
public StorageId StorageId { get; }
|
||||
public AccessControl AccessControl { get; }
|
||||
|
||||
public ProgramInfo(FileSystemServer fsServer, ulong processId, ProgramId programId, StorageId storageId,
|
||||
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
ProcessId = processId;
|
||||
AccessControl = new AccessControl(fsServer, accessControlData, accessControlDescriptor);
|
||||
ProgramId = programId;
|
||||
StorageId = storageId;
|
||||
}
|
||||
|
||||
private ProgramInfo(FileSystemServer fsServer, ReadOnlySpan<byte> accessControlData,
|
||||
ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
ProcessId = 0;
|
||||
AccessControl = new AccessControl(fsServer, accessControlData, accessControlDescriptor);
|
||||
ProgramId = default;
|
||||
StorageId = 0;
|
||||
}
|
||||
|
||||
public bool Contains(ulong processId) => ProcessId == processId;
|
||||
|
||||
public static bool IsInitialProgram(ulong processId)
|
||||
{
|
||||
// Todo: We have no kernel to call into, so use hardcoded values for now
|
||||
const int initialProcessIdLowerBound = 1;
|
||||
const int initialProcessIdUpperBound = 10;
|
||||
|
||||
return initialProcessIdLowerBound >= processId && processId <= initialProcessIdUpperBound;
|
||||
}
|
||||
|
||||
public static bool IsCurrentProcess(ulong processId)
|
||||
{
|
||||
// Todo: Don't use hardcoded value
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static ProgramInfo CreateProgramInfoForInitialProcess(FileSystemServer fsServer)
|
||||
{
|
||||
return new ProgramInfo(fsServer, InitialProcessAccessControlDataHeader,
|
||||
InitialProcessAccessControlDescriptor);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> InitialProcessAccessControlDataHeader => new byte[]
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1C, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> InitialProcessAccessControlDescriptor => new byte[]
|
||||
{
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
}
|
||||
}
|
98
src/LibHac/FsSrv/ProgramRegistryImpl.cs
Normal file
98
src/LibHac/FsSrv/ProgramRegistryImpl.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Impl;
|
||||
using LibHac.Ncm;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
internal class ProgramRegistryImpl
|
||||
{
|
||||
private ulong _processId;
|
||||
private readonly ProgramRegistryServiceImpl _registryService;
|
||||
|
||||
public ProgramRegistryImpl(ProgramRegistryServiceImpl registryService)
|
||||
{
|
||||
_processId = ulong.MaxValue;
|
||||
_registryService = registryService;
|
||||
}
|
||||
|
||||
public ProgramRegistryImpl(ProgramRegistryServiceImpl registryService, ulong processId)
|
||||
{
|
||||
_processId = processId;
|
||||
_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>
|
||||
public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId,
|
||||
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
if (!ProgramInfo.IsInitialProgram(_processId))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
return _registryService.RegisterProgram(processId, programId, storageId, accessControlData,
|
||||
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>
|
||||
public Result UnregisterProgram(ulong processId)
|
||||
{
|
||||
if (!ProgramInfo.IsInitialProgram(_processId))
|
||||
return ResultFs.PermissionDenied.Log();
|
||||
|
||||
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>
|
||||
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>
|
||||
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
|
||||
{
|
||||
return _registryService.GetProgramInfoByProgramId(out programInfo, programId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the process ID of the process that will use this service via IPC.
|
||||
/// </summary>
|
||||
/// <param name="processId">The process ID to set.</param>
|
||||
/// <returns><see cref="Result.Success"/>: The operation was successful.</returns>
|
||||
public Result SetCurrentProcess(ulong processId)
|
||||
{
|
||||
_processId = processId;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
14
src/LibHac/FsSrv/ProgramRegistryService.cs
Normal file
14
src/LibHac/FsSrv/ProgramRegistryService.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
internal readonly struct ProgramRegistryService
|
||||
{
|
||||
private ProgramRegistryServiceImpl ServiceImpl { get; }
|
||||
private ulong ProcessId { get; }
|
||||
|
||||
public ProgramRegistryService(ProgramRegistryServiceImpl serviceImpl, ulong processId)
|
||||
{
|
||||
ServiceImpl = serviceImpl;
|
||||
ProcessId = processId;
|
||||
}
|
||||
}
|
||||
}
|
71
src/LibHac/FsSrv/ProgramRegistryServiceImpl.cs
Normal file
71
src/LibHac/FsSrv/ProgramRegistryServiceImpl.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Impl;
|
||||
using LibHac.Ncm;
|
||||
|
||||
namespace LibHac.FsSrv
|
||||
{
|
||||
public class ProgramRegistryServiceImpl
|
||||
{
|
||||
private ProgramRegistryManager RegistryManager { get; }
|
||||
|
||||
public ProgramRegistryServiceImpl(FileSystemServer fsServer)
|
||||
{
|
||||
RegistryManager = new ProgramRegistryManager(fsServer);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public Result RegisterProgram(ulong processId, ProgramId programId, StorageId storageId,
|
||||
ReadOnlySpan<byte> accessControlData, ReadOnlySpan<byte> accessControlDescriptor)
|
||||
{
|
||||
return RegistryManager.RegisterProgram(processId, programId, storageId, accessControlData,
|
||||
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>
|
||||
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>
|
||||
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>
|
||||
public Result GetProgramInfoByProgramId(out ProgramInfo programInfo, ulong programId)
|
||||
{
|
||||
return RegistryManager.GetProgramInfoByProgramId(out programInfo, programId);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user