diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs index 5b91e235e..9fd002a21 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs @@ -26,8 +26,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { long size = context.RequestData.ReadInt64(); + if (size <= 0) + { + return ResultCode.ObjectInvalid; + } + MakeObject(context, new IStorage(new byte[size])); + // NOTE: Returns ResultCode.MemoryAllocationFailed if IStorage is null, it doesn't occur in our case. + return ResultCode.Success; } @@ -35,20 +42,44 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys // CreateTransferMemoryStorage(b8, u64, handle) -> object public ResultCode CreateTransferMemoryStorage(ServiceCtx context) { - bool unknown = context.RequestData.ReadBoolean(); - long size = context.RequestData.ReadInt64(); - int handle = context.Request.HandleDesc.ToCopy[0]; + bool isReadOnly = context.RequestData.ReadBoolean(); + long size = context.RequestData.ReadInt64(); + int handle = context.Request.HandleDesc.ToCopy[0]; KTransferMemory transferMem = context.Process.HandleTable.GetObject(handle); - if (transferMem == null) + if (size <= 0) { - Logger.Warning?.Print(LogClass.ServiceAm, $"Invalid TransferMemory Handle: {handle:X}"); - - return ResultCode.Success; // TODO: Find correct error code + return ResultCode.ObjectInvalid; } - var data = new byte[transferMem.Size]; + byte[] data = new byte[transferMem.Size]; + + transferMem.Creator.CpuMemory.Read(transferMem.Address, data); + + context.Device.System.KernelContext.Syscall.CloseHandle(handle); + + MakeObject(context, new IStorage(data, isReadOnly)); + + return ResultCode.Success; + } + + [Command(12)] // 2.0.0+ + // CreateHandleStorage(u64, handle) -> object + public ResultCode CreateHandleStorage(ServiceCtx context) + { + long size = context.RequestData.ReadInt64(); + int handle = context.Request.HandleDesc.ToCopy[0]; + + KTransferMemory transferMem = context.Process.HandleTable.GetObject(handle); + + if (size <= 0) + { + return ResultCode.ObjectInvalid; + } + + byte[] data = new byte[transferMem.Size]; + transferMem.Creator.CpuMemory.Read(transferMem.Address, data); context.Device.System.KernelContext.Syscall.CloseHandle(handle); diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs index 37514275d..e4b7d1984 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs @@ -2,11 +2,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE { class IStorage : IpcService { - public byte[] Data { get; private set; } + public bool IsReadOnly { get; private set; } + public byte[] Data { get; private set; } - public IStorage(byte[] data) + public IStorage(byte[] data, bool isReadOnly = false) { - Data = data; + IsReadOnly = isReadOnly; + Data = data; } [Command(0)] diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs index ddd97a4c0..721cf1f9d 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs @@ -24,6 +24,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE // Write(u64, buffer) public ResultCode Write(ServiceCtx context) { + if (_storage.IsReadOnly) + { + return ResultCode.ObjectInvalid; + } + long writePosition = context.RequestData.ReadInt64(); if (writePosition > _storage.Data.Length)