forked from Mirror/Ryujinx
Make sure TryGetApplicationsFromFile() doesn't throw exceptions anymore (#7046)
* Add docstrings for exceptions to methods near TryGetApplicationsFromFile() * Make sure TryGetApplicationsFromFile() doesn't throw exceptions anymore * Add missing filePath to ApplicationData when loading applications from ExeFS * Fix typo Co-authored-by: riperiperi <rhy3756547@hotmail.com> --------- Co-authored-by: riperiperi <rhy3756547@hotmail.com>
This commit is contained in:
parent
99f04ac1a6
commit
c6dc00815a
8 changed files with 176 additions and 147 deletions
|
@ -15,6 +15,12 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
public ServiceAccessControl ServiceAccessControl { get; private set; }
|
public ServiceAccessControl ServiceAccessControl { get; private set; }
|
||||||
public KernelAccessControl KernelAccessControl { get; private set; }
|
public KernelAccessControl KernelAccessControl { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="InvalidNpdmException">The stream doesn't contain valid ACI0 data.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
|
/// <exception cref="System.NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
|
||||||
public Aci0(Stream stream, int offset)
|
public Aci0(Stream stream, int offset)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
public ServiceAccessControl ServiceAccessControl { get; private set; }
|
public ServiceAccessControl ServiceAccessControl { get; private set; }
|
||||||
public KernelAccessControl KernelAccessControl { get; private set; }
|
public KernelAccessControl KernelAccessControl { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="InvalidNpdmException">The stream doesn't contain valid ACID data.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public Acid(Stream stream, int offset)
|
public Acid(Stream stream, int offset)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -11,6 +11,10 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
public int Unknown3 { get; private set; }
|
public int Unknown3 { get; private set; }
|
||||||
public int Unknown4 { get; private set; }
|
public int Unknown4 { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public FsAccessControl(Stream stream, int offset, int size)
|
public FsAccessControl(Stream stream, int offset, int size)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -9,6 +9,12 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
public int Version { get; private set; }
|
public int Version { get; private set; }
|
||||||
public ulong PermissionsBitmask { get; private set; }
|
public ulong PermissionsBitmask { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="InvalidNpdmException">The stream contains invalid data.</exception>
|
||||||
|
/// <exception cref="NotImplementedException">The ContentOwnerId section is not implemented.</exception>
|
||||||
|
/// <exception cref="ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public FsAccessHeader(Stream stream, int offset, int size)
|
public FsAccessHeader(Stream stream, int offset, int size)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -6,6 +6,10 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
{
|
{
|
||||||
public int[] Capabilities { get; private set; }
|
public int[] Capabilities { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public KernelAccessControl(Stream stream, int offset, int size)
|
public KernelAccessControl(Stream stream, int offset, int size)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -24,6 +24,13 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
public Aci0 Aci0 { get; private set; }
|
public Aci0 Aci0 { get; private set; }
|
||||||
public Acid Acid { get; private set; }
|
public Acid Acid { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="InvalidNpdmException">The stream doesn't contain valid NPDM data.</exception>
|
||||||
|
/// <exception cref="System.NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">An error occured while reading bytes from the stream.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public Npdm(Stream stream)
|
public Npdm(Stream stream)
|
||||||
{
|
{
|
||||||
BinaryReader reader = new(stream);
|
BinaryReader reader = new(stream);
|
||||||
|
|
|
@ -9,6 +9,11 @@ namespace Ryujinx.HLE.Loaders.Npdm
|
||||||
{
|
{
|
||||||
public IReadOnlyDictionary<string, bool> Services { get; private set; }
|
public IReadOnlyDictionary<string, bool> Services { get; private set; }
|
||||||
|
|
||||||
|
/// <exception cref="System.ArgumentException">The stream does not support reading, is <see langword="null"/>, or is already closed.</exception>
|
||||||
|
/// <exception cref="System.ArgumentException">An error occured while reading bytes from the stream.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="System.ObjectDisposedException">The stream is closed.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
public ServiceAccessControl(Stream stream, int offset, int size)
|
public ServiceAccessControl(Stream stream, int offset, int size)
|
||||||
{
|
{
|
||||||
stream.Seek(offset, SeekOrigin.Begin);
|
stream.Seek(offset, SeekOrigin.Begin);
|
||||||
|
|
|
@ -72,17 +72,21 @@ namespace Ryujinx.UI.App.Common
|
||||||
return resourceByteArray;
|
return resourceByteArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>
|
||||||
|
/// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
|
||||||
|
/// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
private ApplicationData GetApplicationFromExeFs(PartitionFileSystem pfs, string filePath)
|
private ApplicationData GetApplicationFromExeFs(PartitionFileSystem pfs, string filePath)
|
||||||
{
|
{
|
||||||
ApplicationData data = new()
|
ApplicationData data = new()
|
||||||
{
|
{
|
||||||
Icon = _nspIcon,
|
Icon = _nspIcon,
|
||||||
|
Path = filePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
using UniqueRef<IFile> npdmFile = new();
|
using UniqueRef<IFile> npdmFile = new();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read);
|
Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read);
|
||||||
|
|
||||||
if (ResultFs.PathNotFound.Includes(result))
|
if (ResultFs.PathNotFound.Includes(result))
|
||||||
|
@ -95,14 +99,16 @@ namespace Ryujinx.UI.App.Common
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{filePath}' Error: {exception.Message}");
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <exception cref="MissingKeyException">The configured key set is missing a key.</exception>
|
||||||
|
/// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception>
|
||||||
|
/// <exception cref="NotSupportedException">The NCA version is not supported.</exception>
|
||||||
|
/// <exception cref="HorizonResultException">An error occured while reading PFS data.</exception>
|
||||||
|
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>
|
||||||
|
/// <exception cref="NotImplementedException">The FsAccessHeader.ContentOwnerId section is not implemented.</exception>
|
||||||
|
/// <exception cref="ArgumentException">An error occured while reading bytes from the stream.</exception>
|
||||||
|
/// <exception cref="EndOfStreamException">The end of the stream is reached.</exception>
|
||||||
|
/// <exception cref="IOException">An I/O error occurred.</exception>
|
||||||
private ApplicationData GetApplicationFromNsp(PartitionFileSystem pfs, string filePath)
|
private ApplicationData GetApplicationFromNsp(PartitionFileSystem pfs, string filePath)
|
||||||
{
|
{
|
||||||
bool isExeFs = false;
|
bool isExeFs = false;
|
||||||
|
@ -170,13 +176,15 @@ namespace Ryujinx.UI.App.Common
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <exception cref="MissingKeyException">The configured key set is missing a key.</exception>
|
||||||
|
/// <exception cref="InvalidDataException">The NCA header could not be decrypted.</exception>
|
||||||
|
/// <exception cref="NotSupportedException">The NCA version is not supported.</exception>
|
||||||
|
/// <exception cref="HorizonResultException">An error occured while reading PFS data.</exception>
|
||||||
private List<ApplicationData> GetApplicationsFromPfs(IFileSystem pfs, string filePath)
|
private List<ApplicationData> GetApplicationsFromPfs(IFileSystem pfs, string filePath)
|
||||||
{
|
{
|
||||||
var applications = new List<ApplicationData>();
|
var applications = new List<ApplicationData>();
|
||||||
string extension = Path.GetExtension(filePath).ToLower();
|
string extension = Path.GetExtension(filePath).ToLower();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach ((ulong titleId, ContentMetaData content) in pfs.GetContentData(ContentMetaType.Application, _virtualFileSystem, _checkLevel))
|
foreach ((ulong titleId, ContentMetaData content) in pfs.GetContentData(ContentMetaType.Application, _virtualFileSystem, _checkLevel))
|
||||||
{
|
{
|
||||||
ApplicationData applicationData = new()
|
ApplicationData applicationData = new()
|
||||||
|
@ -251,19 +259,6 @@ namespace Ryujinx.UI.App.Common
|
||||||
|
|
||||||
applications.Add(applicationData);
|
applications.Add(applicationData);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (MissingKeyException exception)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
|
|
||||||
}
|
|
||||||
catch (InvalidDataException)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {filePath}");
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{filePath}' Error: {exception}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return applications;
|
return applications;
|
||||||
}
|
}
|
||||||
|
@ -319,8 +314,6 @@ namespace Ryujinx.UI.App.Common
|
||||||
BinaryReader reader = new(file);
|
BinaryReader reader = new(file);
|
||||||
ApplicationData application = new();
|
ApplicationData application = new();
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
file.Seek(24, SeekOrigin.Begin);
|
file.Seek(24, SeekOrigin.Begin);
|
||||||
|
|
||||||
int assetOffset = reader.ReadInt32();
|
int assetOffset = reader.ReadInt32();
|
||||||
|
@ -358,13 +351,6 @@ namespace Ryujinx.UI.App.Common
|
||||||
|
|
||||||
application.ControlHolder = controlHolder;
|
application.ControlHolder = controlHolder;
|
||||||
applications.Add(application);
|
applications.Add(application);
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -376,8 +362,6 @@ namespace Ryujinx.UI.App.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ".nca":
|
case ".nca":
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
ApplicationData application = new();
|
ApplicationData application = new();
|
||||||
|
|
||||||
|
@ -393,17 +377,6 @@ namespace Ryujinx.UI.App.Common
|
||||||
application.ControlHolder = controlHolder;
|
application.ControlHolder = controlHolder;
|
||||||
|
|
||||||
applications.Add(application);
|
applications.Add(application);
|
||||||
}
|
|
||||||
catch (InvalidDataException)
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -417,16 +390,35 @@ namespace Ryujinx.UI.App.Common
|
||||||
};
|
};
|
||||||
|
|
||||||
applications.Add(application);
|
applications.Add(application);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (MissingKeyException exception)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (InvalidDataException)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
catch (IOException exception)
|
catch (IOException exception)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Application, exception.Message);
|
Logger.Warning?.Print(LogClass.Application, exception.Message);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var data in applications)
|
foreach (var data in applications)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue