aboutsummaryrefslogblamecommitdiff
path: root/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs
blob: 55b49bcecdeaee227e19092aabcac7c66d4731d5 (plain) (tree)
1
2
3
4
5
6
7
8
                                     
                             
                  
                                               
                                                                 

                                        
                                     
 
                                                     
         
                                   
         
                        
                                          
                                                                
         
                                                             
 
                                                                      
             
                                          

                
                                                               
             
         
                        
                                           
                                                                 
         
                                                             
 
                                                                      
 
                                      
         
                        
                                                     
                                                                           
         
                                                             
 
                                                                      
             
                                          

                
                                               
             
         
                        
                                                          
                                                                                
         
                                                             
 
                                                                     
             
                                          

                
                                               
             
         
                        
                                       
                                                             
         
                                                             
 
                                                                                                                               
             
                                          

                
                                               
             
         
                        
                                                      
                                                                            
         
                                                             
 
                                                                      
 
                                      
         
                        
                                                           
                                                                                 
         
                                                             
 
                                                                     
 
                                      
         
                        
                                                              
                                                                                    
         
                                                             
 
                                                                     
             
                                          

                
                                               

             
                        
                                                               
                                                                                     
         
                                                             
 
                                                                     
 
                                      
         
                        
                    
                                                     
         
                                                                               
 
                                      
         
                         
                                          
                                                                
         
                                                             
 
                                                                      
 
                                      
         
                         
                                   
                                                                    
         
                                                                               
 
                                      
         
                         
                                            
                                                                  
         
                                                             
 
                                                                        
 
                                      
         
                         
                                            
                                                                  
         
                                                             
 
                                                                        
 
                                      
         
                         
                                            
                                                                  
         
                                                             
 
                                                                       
 
                                      
         
                         
                                             
                                                                   
         
                                                             
 
                                                                       
 
                                      
         
                                                                                                          
         
                                                                                                   
 
                                                                                           
         
                                                                                               
         
                                                                                 
                                                                                                                                
 
                                                        
             
                                                                          
 
                                                                               
 
                                                                  







                             
                                                                                                     
         
                                                                                 
                                                                                                                               
 
                                                                                  

         
using LibHac.Ncm;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.HLE.FileSystem;
using System.Text;

using static Ryujinx.HLE.Utilities.StringUtils;

namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager
{
    class ILocationResolver : IpcService
    {
        private StorageId _storageId;

        public ILocationResolver(StorageId storageId)
        {
            _storageId = storageId;
        }

        [CommandCmif(0)]
        // ResolveProgramPath(u64 titleId)
        public ResultCode ResolveProgramPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            if (ResolvePath(context, titleId, NcaContentType.Program))
            {
                return ResultCode.Success;
            }
            else
            {
                return ResultCode.ProgramLocationEntryNotFound;
            }
        }

        [CommandCmif(1)]
        // RedirectProgramPath(u64 titleId)
        public ResultCode RedirectProgramPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            RedirectPath(context, titleId, 0, NcaContentType.Program);

            return ResultCode.Success;
        }

        [CommandCmif(2)]
        // ResolveApplicationControlPath(u64 titleId)
        public ResultCode ResolveApplicationControlPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            if (ResolvePath(context, titleId, NcaContentType.Control))
            {
                return ResultCode.Success;
            }
            else
            {
                return ResultCode.AccessDenied;
            }
        }

        [CommandCmif(3)]
        // ResolveApplicationHtmlDocumentPath(u64 titleId)
        public ResultCode ResolveApplicationHtmlDocumentPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            if (ResolvePath(context, titleId, NcaContentType.Manual))
            {
                return ResultCode.Success;
            }
            else
            {
                return ResultCode.AccessDenied;
            }
        }

        [CommandCmif(4)]
        // ResolveDataPath(u64 titleId)
        public ResultCode ResolveDataPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            if (ResolvePath(context, titleId, NcaContentType.Data) || ResolvePath(context, titleId, NcaContentType.PublicData))
            {
                return ResultCode.Success;
            }
            else
            {
                return ResultCode.AccessDenied;
            }
        }

        [CommandCmif(5)]
        // RedirectApplicationControlPath(u64 titleId)
        public ResultCode RedirectApplicationControlPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            RedirectPath(context, titleId, 1, NcaContentType.Control);

            return ResultCode.Success;
        }

        [CommandCmif(6)]
        // RedirectApplicationHtmlDocumentPath(u64 titleId)
        public ResultCode RedirectApplicationHtmlDocumentPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            RedirectPath(context, titleId, 1, NcaContentType.Manual);

            return ResultCode.Success;
        }

        [CommandCmif(7)]
        // ResolveApplicationLegalInformationPath(u64 titleId)
        public ResultCode ResolveApplicationLegalInformationPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            if (ResolvePath(context, titleId, NcaContentType.Manual))
            {
                return ResultCode.Success;
            }
            else
            {
                return ResultCode.AccessDenied;
            }
        }

        [CommandCmif(8)]
        // RedirectApplicationLegalInformationPath(u64 titleId)
        public ResultCode RedirectApplicationLegalInformationPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            RedirectPath(context, titleId, 1, NcaContentType.Manual);

            return ResultCode.Success;
        }

        [CommandCmif(9)]
        // Refresh()
        public ResultCode Refresh(ServiceCtx context)
        {
            context.Device.System.ContentManager.RefreshEntries(_storageId, 1);

            return ResultCode.Success;
        }

        [CommandCmif(10)]
        // SetProgramNcaPath2(u64 titleId)
        public ResultCode SetProgramNcaPath2(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            RedirectPath(context, titleId, 1, NcaContentType.Program);

            return ResultCode.Success;
        }

        [CommandCmif(11)]
        // ClearLocationResolver2()
        public ResultCode ClearLocationResolver2(ServiceCtx context)
        {
            context.Device.System.ContentManager.RefreshEntries(_storageId, 1);

            return ResultCode.Success;
        }

        [CommandCmif(12)]
        // DeleteProgramNcaPath(u64 titleId)
        public ResultCode DeleteProgramNcaPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            DeleteContentPath(context, titleId, NcaContentType.Program);

            return ResultCode.Success;
        }

        [CommandCmif(13)]
        // DeleteControlNcaPath(u64 titleId)
        public ResultCode DeleteControlNcaPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            DeleteContentPath(context, titleId, NcaContentType.Control);

            return ResultCode.Success;
        }

        [CommandCmif(14)]
        // DeleteDocHtmlNcaPath(u64 titleId)
        public ResultCode DeleteDocHtmlNcaPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            DeleteContentPath(context, titleId, NcaContentType.Manual);

            return ResultCode.Success;
        }

        [CommandCmif(15)]
        // DeleteInfoHtmlNcaPath(u64 titleId)
        public ResultCode DeleteInfoHtmlNcaPath(ServiceCtx context)
        {
            ulong titleId = context.RequestData.ReadUInt64();

            DeleteContentPath(context, titleId, NcaContentType.Manual);

            return ResultCode.Success;
        }

        private void RedirectPath(ServiceCtx context, ulong titleId, int flag, NcaContentType contentType)
        {
            string        contentPath = ReadUtf8String(context);
            LocationEntry newLocation = new LocationEntry(contentPath, flag, titleId, contentType);

            context.Device.System.ContentManager.RedirectLocation(newLocation, _storageId);
        }

        private bool ResolvePath(ServiceCtx context, ulong titleId, NcaContentType contentType)
        {
            ContentManager contentManager = context.Device.System.ContentManager;
            string         contentPath    = contentManager.GetInstalledContentPath(titleId, _storageId, NcaContentType.Program);

            if (!string.IsNullOrWhiteSpace(contentPath))
            {
                ulong position = context.Request.RecvListBuff[0].Position;
                ulong size     = context.Request.RecvListBuff[0].Size;

                byte[] contentPathBuffer = Encoding.UTF8.GetBytes(contentPath);

                context.Memory.Write(position, contentPathBuffer);
            }
            else
            {
                return false;
            }

            return true;
        }

        private void DeleteContentPath(ServiceCtx context, ulong titleId, NcaContentType contentType)
        {
            ContentManager contentManager = context.Device.System.ContentManager;
            string         contentPath    = contentManager.GetInstalledContentPath(titleId, _storageId, NcaContentType.Manual);

            contentManager.ClearEntry(titleId, NcaContentType.Manual, _storageId);
        }
    }
}