Catch System.IO.IOException (#932)

This commit is contained in:
Xpl0itR 2020-02-15 20:20:19 +00:00 committed by GitHub
parent 45d86b8f6f
commit d89e90a16e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -85,247 +85,260 @@ namespace Ryujinx.Ui
string saveDataPath = null; string saveDataPath = null;
byte[] applicationIcon = null; byte[] applicationIcon = null;
using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read)) try
{ {
if ((Path.GetExtension(applicationPath).ToLower() == ".nsp") || using (FileStream file = new FileStream(applicationPath, FileMode.Open, FileAccess.Read))
(Path.GetExtension(applicationPath).ToLower() == ".pfs0") ||
(Path.GetExtension(applicationPath).ToLower() == ".xci"))
{ {
try if ((Path.GetExtension(applicationPath).ToLower() == ".nsp") ||
(Path.GetExtension(applicationPath).ToLower() == ".pfs0") ||
(Path.GetExtension(applicationPath).ToLower() == ".xci"))
{ {
PartitionFileSystem pfs; try
bool isExeFs = false;
if (Path.GetExtension(applicationPath).ToLower() == ".xci")
{ {
Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()); PartitionFileSystem pfs;
pfs = xci.OpenPartition(XciPartitionType.Secure); bool isExeFs = false;
}
else
{
pfs = new PartitionFileSystem(file.AsStorage());
// If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application. if (Path.GetExtension(applicationPath).ToLower() == ".xci")
bool hasMainNca = false;
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
{ {
if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca") Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage());
pfs = xci.OpenPartition(XciPartitionType.Secure);
}
else
{
pfs = new PartitionFileSystem(file.AsStorage());
// If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
bool hasMainNca = false;
foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
{ {
pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure(); if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca")
Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{ {
hasMainNca = true; pfs.OpenFile(out IFile ncaFile, fileEntry.FullPath, OpenMode.Read).ThrowIfFailure();
break; Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType == NcaContentType.Program && !nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
hasMainNca = true;
break;
}
}
else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
{
isExeFs = true;
} }
} }
else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main")
if (!hasMainNca && !isExeFs)
{ {
isExeFs = true; numApplicationsFound--;
continue;
} }
} }
if (!hasMainNca && !isExeFs) if (isExeFs)
{ {
numApplicationsFound--; applicationIcon = _nspIcon;
continue;
}
}
if (isExeFs) Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read);
{
applicationIcon = _nspIcon;
Result result = pfs.OpenFile(out IFile npdmFile, "/main.npdm", OpenMode.Read); if (result != ResultFs.PathNotFound)
if (result != ResultFs.PathNotFound)
{
Npdm npdm = new Npdm(npdmFile.AsStream());
titleName = npdm.TitleName;
titleId = npdm.Aci0.TitleId.ToString("x16");
}
}
else
{
// Store the ControlFS in variable called controlFs
GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);
// Creates NACP class from the NACP file
controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure();
Nacp controlData = new Nacp(controlNacpFile.AsStream());
// Get the title name, title ID, developer name and version number from the NACP
version = controlData.DisplayVersion;
GetNameIdDeveloper(controlData, out titleName, out _, out developer);
// Read the icon from the ControlFS and store it as a byte array
try
{
controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure();
using (MemoryStream stream = new MemoryStream())
{ {
icon.AsStream().CopyTo(stream); Npdm npdm = new Npdm(npdmFile.AsStream());
applicationIcon = stream.ToArray();
titleName = npdm.TitleName;
titleId = npdm.Aci0.TitleId.ToString("x16");
} }
} }
catch (HorizonResultException) else
{ {
foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) // Store the ControlFS in variable called controlFs
{ GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId);
if (entry.Name == "control.nacp")
{
continue;
}
controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure(); // Creates NACP class from the NACP file
controlFs.OpenFile(out IFile controlNacpFile, "/control.nacp", OpenMode.Read).ThrowIfFailure();
Nacp controlData = new Nacp(controlNacpFile.AsStream());
// Get the title name, title ID, developer name and version number from the NACP
version = controlData.DisplayVersion;
GetNameIdDeveloper(controlData, out titleName, out _, out developer);
// Read the icon from the ControlFS and store it as a byte array
try
{
controlFs.OpenFile(out IFile icon, $"/icon_{_desiredTitleLanguage}.dat", OpenMode.Read).ThrowIfFailure();
using (MemoryStream stream = new MemoryStream()) using (MemoryStream stream = new MemoryStream())
{ {
icon.AsStream().CopyTo(stream); icon.AsStream().CopyTo(stream);
applicationIcon = stream.ToArray(); applicationIcon = stream.ToArray();
} }
}
if (applicationIcon != null) catch (HorizonResultException)
{
foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*"))
{ {
break; if (entry.Name == "control.nacp")
{
continue;
}
controlFs.OpenFile(out IFile icon, entry.FullPath, OpenMode.Read).ThrowIfFailure();
using (MemoryStream stream = new MemoryStream())
{
icon.AsStream().CopyTo(stream);
applicationIcon = stream.ToArray();
}
if (applicationIcon != null)
{
break;
}
}
if (applicationIcon == null)
{
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
} }
} }
}
}
catch (MissingKeyException exception)
{
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
if (applicationIcon == null) Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
}
catch (InvalidDataException)
{
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
}
catch (Exception exception)
{
Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
Logger.PrintDebug(LogClass.Application, exception.ToString());
numApplicationsFound--;
_loadingError = true;
continue;
}
}
else if (Path.GetExtension(applicationPath).ToLower() == ".nro")
{
BinaryReader reader = new BinaryReader(file);
byte[] Read(long position, int size)
{
file.Seek(position, SeekOrigin.Begin);
return reader.ReadBytes(size);
}
try
{
file.Seek(24, SeekOrigin.Begin);
int assetOffset = reader.ReadInt32();
if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
{
byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
ulong nacpOffset = reader.ReadUInt64();
ulong nacpSize = reader.ReadUInt64();
// Reads and stores game icon as byte array
applicationIcon = Read(assetOffset + iconOffset, (int) iconSize);
// Creates memory stream out of byte array which is the NACP
using (MemoryStream stream = new MemoryStream(Read(assetOffset + (int) nacpOffset, (int) nacpSize)))
{ {
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon; // Creates NACP class from the memory stream
Nacp controlData = new Nacp(stream);
// Get the title name, title ID, developer name and version number from the NACP
version = controlData.DisplayVersion;
GetNameIdDeveloper(controlData, out titleName, out titleId, out developer);
} }
} }
} else
}
catch (MissingKeyException exception)
{
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
Logger.PrintWarning(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}");
}
catch (InvalidDataException)
{
applicationIcon = Path.GetExtension(applicationPath).ToLower() == ".xci" ? _xciIcon : _nspIcon;
Logger.PrintWarning(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}");
}
catch (Exception exception)
{
Logger.PrintError(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
Logger.PrintDebug(LogClass.Application, exception.ToString());
numApplicationsFound--;
_loadingError = true;
continue;
}
}
else if (Path.GetExtension(applicationPath).ToLower() == ".nro")
{
BinaryReader reader = new BinaryReader(file);
byte[] Read(long position, int size)
{
file.Seek(position, SeekOrigin.Begin);
return reader.ReadBytes(size);
}
try
{
file.Seek(24, SeekOrigin.Begin);
int assetOffset = reader.ReadInt32();
if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET")
{
byte[] iconSectionInfo = Read(assetOffset + 8, 0x10);
long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0);
long iconSize = BitConverter.ToInt64(iconSectionInfo, 8);
ulong nacpOffset = reader.ReadUInt64();
ulong nacpSize = reader.ReadUInt64();
// Reads and stores game icon as byte array
applicationIcon = Read(assetOffset + iconOffset, (int) iconSize);
// Creates memory stream out of byte array which is the NACP
using (MemoryStream stream = new MemoryStream(Read(assetOffset + (int) nacpOffset, (int) nacpSize)))
{ {
// Creates NACP class from the memory stream applicationIcon = _nroIcon;
Nacp controlData = new Nacp(stream); titleName = Path.GetFileNameWithoutExtension(applicationPath);
// Get the title name, title ID, developer name and version number from the NACP
version = controlData.DisplayVersion;
GetNameIdDeveloper(controlData, out titleName, out titleId, out developer);
} }
} }
else catch
{ {
applicationIcon = _nroIcon; Logger.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
titleName = Path.GetFileNameWithoutExtension(applicationPath);
}
}
catch
{
Logger.PrintError(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
numApplicationsFound--;
continue;
}
}
else if (Path.GetExtension(applicationPath).ToLower() == ".nca")
{
try
{
Nca nca = new Nca(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
numApplicationsFound--; numApplicationsFound--;
continue; continue;
} }
} }
catch (InvalidDataException) else if (Path.GetExtension(applicationPath).ToLower() == ".nca")
{ {
Logger.PrintWarning(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}"); try
{
Nca nca = new Nca(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
if (nca.Header.ContentType != NcaContentType.Program || nca.Header.GetFsHeader(dataIndex).IsPatchSection())
{
numApplicationsFound--;
continue;
}
}
catch (InvalidDataException)
{
Logger.PrintWarning(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.PrintWarning(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}");
numApplicationsFound--;
_loadingError = true;
continue;
}
applicationIcon = _ncaIcon;
titleName = Path.GetFileNameWithoutExtension(applicationPath);
} }
catch // If its an NSO we just set defaults
else if (Path.GetExtension(applicationPath).ToLower() == ".nso")
{ {
Logger.PrintError(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); applicationIcon = _nsoIcon;
titleName = Path.GetFileNameWithoutExtension(applicationPath);
numApplicationsFound--;
_loadingError = true;
continue;
} }
}
}
catch (IOException exception)
{
Logger.PrintWarning(LogClass.Application, exception.Message);
applicationIcon = _ncaIcon; numApplicationsFound--;
titleName = Path.GetFileNameWithoutExtension(applicationPath); _loadingError = true;
}
// If its an NSO we just set defaults continue;
else if (Path.GetExtension(applicationPath).ToLower() == ".nso")
{
applicationIcon = _nsoIcon;
titleName = Path.GetFileNameWithoutExtension(applicationPath);
}
} }
ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId); ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId);
@ -384,7 +397,7 @@ namespace Ryujinx.Ui
{ {
Gtk.Application.Invoke(delegate Gtk.Application.Invoke(delegate
{ {
GtkDialog.CreateErrorDialog("One or more files encountered were not of a valid type, check logs for more info."); GtkDialog.CreateErrorDialog("One or more files encountered could not be loaded, check logs for more info.");
}); });
} }
} }