Procházet zdrojové kódy

Update to LibHac 0.5.0 (#725)

* Update to libhac 0.5

* Catch HorizonResultException in IFileSystemProxy

* Changes based on feedback
Alex Barney před 6 roky
rodič
revize
f723f6f39a

+ 1 - 2
Ryujinx.HLE/HOS/Services/Acc/IAccountService.cs

@@ -321,8 +321,7 @@ namespace Ryujinx.HLE.HOS.Services.Acc
             // Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current PID and store the result (NACP File) internally.
             // But since we use LibHac and we load one Application at a time, it's not necessary.
 
-            // TODO : Use "context.Device.System.ControlData.UserAccountSwitchLock" when LibHac is updated.
-            context.ResponseData.Write(false);
+            context.ResponseData.Write(context.Device.System.ControlData.UserAccountSwitchLock);
 
             Logger.PrintStub(LogClass.ServiceAcc);
 

+ 23 - 28
Ryujinx.HLE/HOS/Services/FspSrv/IDirectory.cs

@@ -1,11 +1,11 @@
+using LibHac;
 using Ryujinx.HLE.HOS.Ipc;
-using System;
 using System.Collections.Generic;
 using System.Text;
 
 namespace Ryujinx.HLE.HOS.Services.FspSrv
 {
-    class IDirectory : IpcService, IDisposable
+    class IDirectory : IpcService
     {
         private const int DirectoryEntrySize = 0x310;
 
@@ -15,11 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
         private IEnumerator<LibHac.Fs.DirectoryEntry> _enumerator;
 
-        public event EventHandler<EventArgs> Disposed;
-
-        public string Path { get; }
-
-        private LibHac.Fs.IDirectory _provider;
+        private LibHac.Fs.IDirectory _baseDirectory;
 
         public IDirectory(LibHac.Fs.IDirectory directory)
         {
@@ -29,9 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
                 { 1, GetEntryCount }
             };
 
-            _provider = directory;
-
-            Path = directory.FullPath;
+            _baseDirectory = directory;
 
             _enumerator = directory.Read().GetEnumerator();
         }
@@ -45,13 +39,20 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             int maxReadCount = (int)(bufferLen / DirectoryEntrySize);
             int readCount    = 0;
 
-            while (readCount < maxReadCount && _enumerator.MoveNext())
+            try
             {
-                long position = bufferPosition + readCount * DirectoryEntrySize;
+                while (readCount < maxReadCount && _enumerator.MoveNext())
+                {
+                    long position = bufferPosition + readCount * DirectoryEntrySize;
 
-                WriteDirectoryEntry(context, position, _enumerator.Current);
+                    WriteDirectoryEntry(context, position, _enumerator.Current);
 
-                readCount++;
+                    readCount++;
+                }
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
             }
 
             context.ResponseData.Write((long)readCount);
@@ -78,22 +79,16 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // GetEntryCount() -> u64
         public long GetEntryCount(ServiceCtx context)
         {
-            context.ResponseData.Write((long)_provider.GetEntryCount());
-
-            return 0;
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (disposing)
+            try
             {
-                Disposed?.Invoke(this, EventArgs.Empty);
+                context.ResponseData.Write((long)_baseDirectory.GetEntryCount());
             }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
+
+            return 0;
         }
     }
 }

+ 46 - 16
Ryujinx.HLE/HOS/Services/FspSrv/IFile.cs

@@ -1,3 +1,4 @@
+using LibHac;
 using LibHac.Fs;
 using Ryujinx.HLE.HOS.Ipc;
 using System;
@@ -13,11 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
         private LibHac.Fs.IFile _baseFile;
 
-        public event EventHandler<EventArgs> Disposed;
-
-        public string Path { get; private set; }
-
-        public IFile(LibHac.Fs.IFile baseFile, string path)
+        public IFile(LibHac.Fs.IFile baseFile)
         {
             _commands = new Dictionary<int, ServiceProcessRequest>
             {
@@ -29,7 +26,6 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             };
 
             _baseFile = baseFile;
-            Path      = PathTools.Normalize(path);
         }
 
         // Read(u32 readOption, u64 offset, u64 size) -> (u64 out_size, buffer<u8, 0x46, 0> out_buf)
@@ -44,8 +40,16 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             long size   = context.RequestData.ReadInt64();
 
             byte[] data = new byte[size];
+            int readSize;
 
-            int readSize = _baseFile.Read(data, offset, readOption);
+            try
+            {
+                readSize = _baseFile.Read(data, offset, readOption);
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             context.Memory.WriteBytes(position, data);
 
@@ -67,7 +71,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
             byte[] data = context.Memory.ReadBytes(position, size);
 
-            _baseFile.Write(data, offset, writeOption);
+            try
+            {
+                _baseFile.Write(data, offset, writeOption);
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -75,7 +86,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // Flush()
         public long Flush(ServiceCtx context)
         {
-            _baseFile.Flush();
+            try
+            {
+                _baseFile.Flush();
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -83,9 +101,16 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // SetSize(u64 size)
         public long SetSize(ServiceCtx context)
         {
-            long size = context.RequestData.ReadInt64();
+            try
+            {
+                long size = context.RequestData.ReadInt64();
 
-            _baseFile.SetSize(size);
+                _baseFile.SetSize(size);
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -93,7 +118,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // GetSize() -> u64 fileSize
         public long GetSize(ServiceCtx context)
         {
-            context.ResponseData.Write(_baseFile.GetSize());
+            try
+            {
+                context.ResponseData.Write(_baseFile.GetSize());
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -105,11 +137,9 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
         protected virtual void Dispose(bool disposing)
         {
-            if (disposing && _baseFile != null)
+            if (disposing)
             {
-                _baseFile.Dispose();
-
-                Disposed?.Invoke(this, EventArgs.Empty);
+                _baseFile?.Dispose();
             }
         }
     }

+ 78 - 269
Ryujinx.HLE/HOS/Services/FspSrv/IFileSystem.cs

@@ -1,9 +1,8 @@
+using LibHac;
 using LibHac.Fs;
 using Ryujinx.HLE.HOS.Ipc;
-using System;
 using System.Collections.Generic;
-using System.IO;
-using Ryujinx.Common.Logging;
+
 using static Ryujinx.HLE.HOS.ErrorCode;
 using static Ryujinx.HLE.Utilities.StringUtils;
 
@@ -15,9 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
         public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
 
-        private HashSet<string> _openPaths;
-
-        private LibHac.Fs.IFileSystem _provider;
+        private LibHac.Fs.IFileSystem _fileSystem;
 
         public IFileSystem(LibHac.Fs.IFileSystem provider)
         {
@@ -40,9 +37,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
                 { 14, GetFileTimeStampRaw        }
             };
 
-            _openPaths = new HashSet<string>();
-
-            _provider = provider;
+            _fileSystem = provider;
         }
 
         // CreateFile(u32 createOption, u64 size, buffer<bytes<0x301>, 0x19, 0x301> path)
@@ -55,34 +50,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
             long size = context.RequestData.ReadInt64();
 
-            if (name == null)
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (_provider.FileExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.CreateFile(name, size, createOption);
+                _fileSystem.CreateFile(name, size, createOption);
             }
-            catch (DirectoryNotFoundException)
+            catch (HorizonResultException ex)
             {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -93,29 +67,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (!_provider.FileExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.DeleteFile(name);
+                _fileSystem.DeleteFile(name);
             }
-            catch (FileNotFoundException)
+            catch (HorizonResultException ex)
             {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -126,34 +84,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (name == null)
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (_provider.DirectoryExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.CreateDirectory(name);
-            }
-            catch (DirectoryNotFoundException)
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
+                _fileSystem.CreateDirectory(name);
             }
-            catch (UnauthorizedAccessException)
+            catch (HorizonResultException ex)
             {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -164,29 +101,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (!_provider.DirectoryExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.DeleteDirectory(name);
-            }
-            catch (DirectoryNotFoundException)
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
+                _fileSystem.DeleteDirectory(name);
             }
-            catch (UnauthorizedAccessException)
+            catch (HorizonResultException ex)
             {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -197,25 +118,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (!_provider.DirectoryExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.DeleteDirectoryRecursively(name);
+                _fileSystem.DeleteDirectoryRecursively(name);
             }
-            catch (UnauthorizedAccessException)
+            catch (HorizonResultException ex)
             {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -227,34 +136,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             string oldName = ReadUtf8String(context, 0);
             string newName = ReadUtf8String(context, 1);
 
-            if (_provider.FileExists(oldName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (_provider.FileExists(newName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
-            }
-
-            if (IsPathAlreadyInUse(oldName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.RenameFile(oldName, newName);
-            }
-            catch (FileNotFoundException)
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
+                _fileSystem.RenameFile(oldName, newName);
             }
-            catch (UnauthorizedAccessException)
+            catch (HorizonResultException ex)
             {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {oldName} or {newName}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -266,34 +154,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             string oldName = ReadUtf8String(context, 0);
             string newName = ReadUtf8String(context, 1);
 
-            if (!_provider.DirectoryExists(oldName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (!_provider.DirectoryExists(newName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
-            }
-
-            if (IsPathAlreadyInUse(oldName))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.RenameFile(oldName, newName);
+                _fileSystem.RenameDirectory(oldName, newName);
             }
-            catch (DirectoryNotFoundException)
+            catch (HorizonResultException ex)
             {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {oldName} or {newName}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -306,15 +173,20 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
             try
             {
-                DirectoryEntryType entryType = _provider.GetEntryType(name);
+                DirectoryEntryType entryType = _fileSystem.GetEntryType(name);
 
-                context.ResponseData.Write((int)entryType);
+                if (entryType == DirectoryEntryType.Directory || entryType == DirectoryEntryType.File)
+                {
+                    context.ResponseData.Write((int)entryType);
+                }
+                else
+                {
+                    return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
+                }
             }
-            catch (FileNotFoundException)
+            catch (HorizonResultException ex)
             {
-                context.ResponseData.Write(0);
-
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -327,40 +199,19 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
             string name = ReadUtf8String(context);
 
-            if (!_provider.FileExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
-            IFile fileInterface;
-
             try
             {
-                LibHac.Fs.IFile file = _provider.OpenFile(name, mode);
+                LibHac.Fs.IFile file = _fileSystem.OpenFile(name, mode);
 
-                fileInterface = new IFile(file, name);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
+                IFile fileInterface = new IFile(file);
 
-                throw;
+                MakeObject(context, fileInterface);
             }
-
-            fileInterface.Disposed += RemoveFileInUse;
-
-            lock (_openPaths)
+            catch (HorizonResultException ex)
             {
-                _openPaths.Add(fileInterface.Path);
+                return ex.ResultValue.Value;
             }
 
-            MakeObject(context, fileInterface);
-
             return 0;
         }
 
@@ -371,47 +222,33 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
             string name = ReadUtf8String(context);
 
-            if (!_provider.DirectoryExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
-            IDirectory dirInterface;
-
             try
             {
-                LibHac.Fs.IDirectory dir = _provider.OpenDirectory(name, mode);
+                LibHac.Fs.IDirectory dir = _fileSystem.OpenDirectory(name, mode);
 
-                dirInterface = new IDirectory(dir);
-            }
-            catch (UnauthorizedAccessException)
-            {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
+                IDirectory dirInterface = new IDirectory(dir);
 
-                throw;
+                MakeObject(context, dirInterface);
             }
-
-            dirInterface.Disposed += RemoveDirectoryInUse;
-
-            lock (_openPaths)
+            catch (HorizonResultException ex)
             {
-                _openPaths.Add(dirInterface.Path);
+                return ex.ResultValue.Value;
             }
 
-            MakeObject(context, dirInterface);
-
             return 0;
         }
 
         // Commit()
         public long Commit(ServiceCtx context)
         {
-            _provider.Commit();
+            try
+            {
+                _fileSystem.Commit();
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -421,7 +258,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            context.ResponseData.Write(_provider.GetFreeSpaceSize(name));
+            try
+            {
+                context.ResponseData.Write(_fileSystem.GetFreeSpaceSize(name));
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -431,7 +275,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            context.ResponseData.Write(_provider.GetTotalSpaceSize(name));
+            try
+            {
+                context.ResponseData.Write(_fileSystem.GetTotalSpaceSize(name));
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -441,25 +292,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (!_provider.DirectoryExists(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-            }
-
-            if (IsPathAlreadyInUse(name))
-            {
-                return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse);
-            }
-
             try
             {
-                _provider.CleanDirectoryRecursively(name);
+                _fileSystem.CleanDirectoryRecursively(name);
             }
-            catch (UnauthorizedAccessException)
+            catch (HorizonResultException ex)
             {
-                Logger.PrintError(LogClass.ServiceFs, $"Unable to access {name}");
-
-                throw;
+                return ex.ResultValue.Value;
             }
 
             return 0;
@@ -470,9 +309,9 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         {
             string name = ReadUtf8String(context);
 
-            if (_provider.FileExists(name) || _provider.DirectoryExists(name))
+            try
             {
-                FileTimeStampRaw timestamp = _provider.GetFileTimeStampRaw(name);
+                FileTimeStampRaw timestamp = _fileSystem.GetFileTimeStampRaw(name);
 
                 context.ResponseData.Write(timestamp.Created);
                 context.ResponseData.Write(timestamp.Modified);
@@ -484,43 +323,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
                 data[0] = 1;
 
                 context.ResponseData.Write(data);
-
-                return 0;
             }
-
-            return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
-        }
-
-        private bool IsPathAlreadyInUse(string path)
-        {
-            lock (_openPaths)
+            catch (HorizonResultException ex)
             {
-                return _openPaths.Contains(path);
+                return ex.ResultValue.Value;
             }
-        }
 
-        private void RemoveFileInUse(object sender, EventArgs e)
-        {
-            IFile fileInterface = (IFile)sender;
-
-            lock (_openPaths)
-            {
-                fileInterface.Disposed -= RemoveFileInUse;
-
-                _openPaths.Remove(fileInterface.Path);
-            }
-        }
-
-        private void RemoveDirectoryInUse(object sender, EventArgs e)
-        {
-            IDirectory dirInterface = (IDirectory)sender;
-
-            lock (_openPaths)
-            {
-                dirInterface.Disposed -= RemoveDirectoryInUse;
-
-                _openPaths.Remove(dirInterface.Path);
-            }
+            return 0;
         }
     }
 }

+ 67 - 34
Ryujinx.HLE/HOS/Services/FspSrv/IFileSystemProxy.cs

@@ -127,17 +127,13 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs
         public long OpenSaveDataFileSystem(ServiceCtx context)
         {
-            LoadSaveDataFileSystem(context);
-
-            return 0;
+            return LoadSaveDataFileSystem(context);
         }
 
         // OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs
         public long OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context)
         {
-            LoadSaveDataFileSystem(context);
-
-            return 0;
+            return LoadSaveDataFileSystem(context);
         }
 
         // OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
@@ -179,11 +175,18 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
                     if (File.Exists(ncaPath))
                     {
-                        LibHac.Fs.IStorage ncaStorage   = new LocalStorage(ncaPath, FileAccess.Read, FileMode.Open);
-                        Nca                nca          = new Nca(context.Device.System.KeySet, ncaStorage);
-                        LibHac.Fs.IStorage romfsStorage = nca.OpenStorage(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
-
-                        MakeObject(context, new IStorage(romfsStorage));
+                        try
+                        {
+                            LibHac.Fs.IStorage ncaStorage   = new LocalStorage(ncaPath, FileAccess.Read, FileMode.Open);
+                            Nca                nca          = new Nca(context.Device.System.KeySet, ncaStorage);
+                            LibHac.Fs.IStorage romfsStorage = nca.OpenStorage(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
+
+                            MakeObject(context, new IStorage(romfsStorage));
+                        }
+                        catch (HorizonResultException ex)
+                        {
+                            return ex.ResultValue.Value;
+                        }
 
                         return 0;
                     }
@@ -230,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             return 0;
         }
 
-        public void LoadSaveDataFileSystem(ServiceCtx context)
+        public long LoadSaveDataFileSystem(ServiceCtx context)
         {
             SaveSpaceId saveSpaceId = (SaveSpaceId)context.RequestData.ReadInt64();
 
@@ -242,39 +245,62 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
             SaveDataType    saveDataType = (SaveDataType)context.RequestData.ReadByte();
             SaveInfo        saveInfo     = new SaveInfo(titleId, saveId, saveDataType, userId, saveSpaceId);
             string          savePath     = context.Device.FileSystem.GetGameSavePath(saveInfo, context);
-            LocalFileSystem fileSystem   = new LocalFileSystem(savePath);
 
-            DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem);
+            try
+            {
+                LocalFileSystem             fileSystem     = new LocalFileSystem(savePath);
+                DirectorySaveDataFileSystem saveFileSystem = new DirectorySaveDataFileSystem(fileSystem);
+
+                MakeObject(context, new IFileSystem(saveFileSystem));
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
-            MakeObject(context, new IFileSystem(saveFileSystem));
+            return 0;
         }
 
         private long OpenNsp(ServiceCtx context, string pfsPath)
         {
-            LocalStorage        storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open);
-            PartitionFileSystem nsp     = new PartitionFileSystem(storage);
+            try
+            {
+                LocalStorage        storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open);
+                PartitionFileSystem nsp     = new PartitionFileSystem(storage);
 
-            ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
-            
-            IFileSystem nspFileSystem = new IFileSystem(nsp);
+                ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
+                
+                IFileSystem nspFileSystem = new IFileSystem(nsp);
 
-            MakeObject(context, nspFileSystem);
+                MakeObject(context, nspFileSystem);
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
 
         private long OpenNcaFs(ServiceCtx context, string ncaPath, LibHac.Fs.IStorage ncaStorage)
         {
-            Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);
-
-            if (!nca.SectionExists(NcaSectionType.Data))
+            try
             {
-                return MakeError(ErrorModule.Fs, FsErr.PartitionNotFound);
-            }
+                Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);
+
+                if (!nca.SectionExists(NcaSectionType.Data))
+                {
+                    return MakeError(ErrorModule.Fs, FsErr.PartitionNotFound);
+                }
 
-            LibHac.Fs.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
+                LibHac.Fs.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
 
-            MakeObject(context, new IFileSystem(fileSystem));
+                MakeObject(context, new IFileSystem(fileSystem));
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }
@@ -295,15 +321,22 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
                     FileMode.Open,
                     FileAccess.Read);
 
-                PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());
+                try
+                {
+                    PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());
 
-                ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
-                
-                string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');
+                    ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
+                    
+                    string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');
 
-                if (nsp.FileExists(filename))
+                    if (nsp.FileExists(filename))
+                    {
+                        return OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage());
+                    }
+                }
+                catch (HorizonResultException ex)
                 {
-                    return OpenNcaFs(context, fullPath, nsp.OpenFile(filename, OpenMode.Read).AsStorage());
+                    return ex.ResultValue.Value;
                 }
             }
 

+ 17 - 2
Ryujinx.HLE/HOS/Services/FspSrv/IStorage.cs

@@ -1,3 +1,4 @@
+using LibHac;
 using Ryujinx.HLE.HOS.Ipc;
 using System.Collections.Generic;
 
@@ -40,7 +41,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
 
                 byte[] data = new byte[size];
 
-                _baseStorage.Read(data, offset);
+                try
+                {
+                    _baseStorage.Read(data, offset);
+                }
+                catch (HorizonResultException ex)
+                {
+                    return ex.ResultValue.Value;
+                }
 
                 context.Memory.WriteBytes(buffDesc.Position, data);
             }
@@ -51,7 +59,14 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
         // GetSize() -> u64 size
         public long GetSize(ServiceCtx context)
         {
-            context.ResponseData.Write(_baseStorage.GetSize());
+            try
+            {
+                context.ResponseData.Write(_baseStorage.GetSize());
+            }
+            catch (HorizonResultException ex)
+            {
+                return ex.ResultValue.Value;
+            }
 
             return 0;
         }

+ 1 - 1
Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs

@@ -65,7 +65,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns
             position += isbn.Length;
 
             context.Memory.WriteByte(position++, nacp.StartupUserAccount);
-            context.Memory.WriteByte(position++, nacp.TouchScreenUsageMode);
+            context.Memory.WriteByte(position++, nacp.UserAccountSwitchLock);
             context.Memory.WriteByte(position++, nacp.AocRegistrationType);
 
             context.Memory.WriteInt32(position, nacp.AttributeFlag);

+ 1 - 1
Ryujinx.HLE/Ryujinx.HLE.csproj

@@ -47,7 +47,7 @@
 
   <ItemGroup>
     <PackageReference Include="Concentus" Version="1.1.7" />
-    <PackageReference Include="LibHac" Version="0.4.1" />
+    <PackageReference Include="LibHac" Version="0.5.0" />
     <PackageReference Include="TimeZoneConverter.Posix" Version="2.1.0" />
   </ItemGroup>