コード例 #1
0
        public void Initialize(Switch device)
        {
            lock (_lock)
            {
                _certificates          = new Dictionary <CaCertificateId, CertStoreEntry>();
                _initialized           = false;
                _contentManager        = device.System.ContentManager;
                _virtualFileSystem     = device.FileSystem;
                _fsIntegrityCheckLevel = device.System.FsIntegrityCheckLevel;

                if (HasCertStoreTitle())
                {
                    using LocalStorage ncaFile = new LocalStorage(_virtualFileSystem.SwitchPathToSystemPath(GetCertStoreTitleContentPath()), FileAccess.Read, FileMode.Open);

                    Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile);

                    IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _fsIntegrityCheckLevel);

                    using var trustedCertsFileRef = new UniqueRef <IFile>();

                    Result result = romfs.OpenFile(ref trustedCertsFileRef.Ref(), "/ssl_TrustedCerts.bdf".ToU8Span(), OpenMode.Read);

                    if (!result.IsSuccess())
                    {
                        // [1.0.0 - 2.3.0]
                        if (ResultFs.PathNotFound.Includes(result))
                        {
                            result = romfs.OpenFile(ref trustedCertsFileRef.Ref(), "/ssl_TrustedCerts.tcf".ToU8Span(), OpenMode.Read);
                        }

                        if (result.IsFailure())
                        {
                            Logger.Error?.Print(LogClass.ServiceSsl, CertStoreTitleMissingErrorMessage);

                            return;
                        }
                    }

                    using IFile trustedCertsFile = trustedCertsFileRef.Release();

                    trustedCertsFile.GetSize(out long fileSize).ThrowIfFailure();

                    Span <byte> trustedCertsRaw = new byte[fileSize];

                    trustedCertsFile.Read(out _, 0, trustedCertsRaw).ThrowIfFailure();

                    CertStoreFileHeader header = MemoryMarshal.Read <CertStoreFileHeader>(trustedCertsRaw);

                    if (!header.IsValid())
                    {
                        Logger.Error?.Print(LogClass.ServiceSsl, "Invalid CertStore data found, skipping!");

                        return;
                    }

                    ReadOnlySpan <byte> trustedCertsData = trustedCertsRaw[Unsafe.SizeOf <CertStoreFileHeader>()..];
コード例 #2
0
        public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, PartitionFileSystem pfs, int programIndex)
        {
            Nca mainNca    = null;
            Nca patchNca   = null;
            Nca controlNca = null;

            fileSystem.ImportTickets(pfs);

            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
            {
                using var ncaFile = new UniqueRef <IFile>();

                pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage());

                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);

                if (ncaProgramIndex != programIndex)
                {
                    continue;
                }

                if (nca.Header.ContentType == NcaContentType.Program)
                {
                    int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);

                    if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())
                    {
                        patchNca = nca;
                    }
                    else
                    {
                        mainNca = nca;
                    }
                }
                else if (nca.Header.ContentType == NcaContentType.Control)
                {
                    controlNca = nca;
                }
            }

            return(mainNca, patchNca, controlNca);
        }
コード例 #3
0
        public static ResultCode OpenFileSystemFromInternalFile(ServiceCtx context, string fullPath, out IFileSystem openedFileSystem)
        {
            openedFileSystem = null;

            DirectoryInfo archivePath = new DirectoryInfo(fullPath).Parent;

            while (string.IsNullOrWhiteSpace(archivePath.Extension))
            {
                archivePath = archivePath.Parent;
            }

            if (archivePath.Extension == ".nsp" && File.Exists(archivePath.FullName))
            {
                FileStream pfsFile = new FileStream(
                    archivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
                    FileMode.Open,
                    FileAccess.Read);

                try
                {
                    PartitionFileSystem nsp = new PartitionFileSystem(pfsFile.AsStorage());

                    ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);

                    string filename = fullPath.Replace(archivePath.FullName, string.Empty).TrimStart('\\');

                    using var ncaFile = new UniqueRef <LibHac.Fs.Fsa.IFile>();

                    Result result = nsp.OpenFile(ref ncaFile.Ref(), filename.ToU8Span(), OpenMode.Read);
                    if (result.IsFailure())
                    {
                        return((ResultCode)result.Value);
                    }

                    return(OpenNcaFs(context, fullPath, ncaFile.Release().AsStorage(), out openedFileSystem));
                }
                catch (HorizonResultException ex)
                {
                    return((ResultCode)ex.ResultValue.Value);
                }
            }

            return(ResultCode.PathDoesNotExist);
        }
コード例 #4
0
            private byte[]? LoadExpectedIcon(SectionItem sectionItem, NacpLanguage nacpLanguage)
            {
                var languageName = nacpLanguage.ToString();

                var expectedFileName = $"icon_{languageName}.dat";

                var iconItem = sectionItem.ChildItems.FirstOrDefault(item => string.Equals(item.Name, expectedFileName, StringComparison.OrdinalIgnoreCase));

                if (iconItem == null)
                {
                    var message = LocalizationManager.Instance.Current.Keys.LoadingError_IconMissing.SafeFormat(expectedFileName);
                    sectionItem.Errors.Add(message);
                    _logger.LogError(message);
                    return(null);
                }

                var fileSystem = sectionItem.FileSystem;

                if (fileSystem == null)
                {
                    return(null);
                }

                try
                {
                    using var uniqueRefFile = new UniqueRef <IFile>();

                    fileSystem.OpenFile(ref uniqueRefFile.Ref(), iconItem.Path.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                    var file = uniqueRefFile.Release();

                    file.GetSize(out var fileSize).ThrowIfFailure();
                    var bytes = new byte[fileSize];
                    file.AsStream().Read(bytes);
                    return(bytes);
                }
                catch (Exception ex)
                {
                    var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadIcon.SafeFormat(ex.Message);
                    iconItem.Errors.Add(message);
                    _logger.LogError(ex, message);
                    return(null);
                }
            }
コード例 #5
0
        public static (Nca patch, Nca control) GetGameUpdateDataFromPartition(VirtualFileSystem fileSystem, PartitionFileSystem pfs, string titleId, int programIndex)
        {
            Nca patchNca   = null;
            Nca controlNca = null;

            fileSystem.ImportTickets(pfs);

            foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
            {
                using var ncaFile = new UniqueRef <IFile>();

                pfs.OpenFile(ref ncaFile.Ref(), fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();

                Nca nca = new Nca(fileSystem.KeySet, ncaFile.Release().AsStorage());

                int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF);

                if (ncaProgramIndex != programIndex)
                {
                    continue;
                }

                if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId)
コード例 #6
0
        private void BuildChildItems(SectionItem parentItem)
        {
            try
            {
                const string?ROOT_PATH = "/";

                var fileSystem = parentItem.FileSystem;
                if (fileSystem == null)
                {
                    return;
                }

                var directoryEntries = SafeGetDirectoryEntries(fileSystem, ROOT_PATH, parentItem);

                foreach (var directoryEntry in directoryEntries)
                {
                    var entryName = directoryEntry.Name;
                    var entryPath = directoryEntry.FullPath;

                    // NACP File
                    if (parentItem.ParentItem.ContentType == NcaContentType.Control && string.Equals(entryName, NacpItem.NacpFileName, StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile nacpFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nacpFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenNacpFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        ApplicationControlProperty nacp;
                        try
                        {
                            var blitStruct = new BlitStruct <ApplicationControlProperty>(1);
                            nacpFile.Read(out _, 0, blitStruct.ByteSpan).ThrowIfFailure();

                            nacp = blitStruct.Value;
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadNacpFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        parentItem.ChildItems.Add(new NacpItem(nacp, parentItem, directoryEntry));
                    }
                    // CNMT File
                    else if (parentItem.ParentItem.ContentType == NcaContentType.Meta && entryName.EndsWith(".cnmt", StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile cnmtFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            cnmtFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenCnmtFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        Cnmt cnmt;
                        try
                        {
                            cnmt = new Cnmt(cnmtFile.AsStream());
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadCnmtFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }
                        parentItem.ChildItems.Add(new CnmtItem(cnmt, parentItem, directoryEntry));
                    }
                    // MAIN file
                    else if (parentItem.ParentItem.ContentType == NcaContentType.Program && string.Equals(entryName, "main", StringComparison.OrdinalIgnoreCase) && directoryEntry.Type == DirectoryEntryType.File)
                    {
                        IFile nsoFile;
                        try
                        {
                            using var uniqueRefFile = new UniqueRef <IFile>();
                            fileSystem.OpenFile(ref uniqueRefFile.Ref(), entryPath.ToU8Span(), OpenMode.Read).ThrowIfFailure();
                            nsoFile = uniqueRefFile.Release();
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToOpenMainFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        NsoHeader?nsoHeader;
                        try
                        {
                            var nsoReader = new NsoReader();
                            nsoReader.Initialize(nsoFile).ThrowIfFailure();
                            nsoHeader = nsoReader.Header;
                        }
                        catch (Exception ex)
                        {
                            OnLoadingException(ex, parentItem);

                            var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadMainFile.SafeFormat(ex.Message);
                            parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                            _logger.LogError(ex, message);
                            continue;
                        }

                        parentItem.ChildItems.Add(new MainItem(nsoHeader.Value, parentItem, directoryEntry));
                    }
                    else
                    {
                        var directoryEntryItem = new DirectoryEntryItem(parentItem, directoryEntry);
                        BuildChildItems(directoryEntryItem);
                        parentItem.ChildItems.Add(directoryEntryItem);
                    }
                }
            }
            catch (Exception ex)
            {
                OnLoadingException(ex, parentItem);

                var message = LocalizationManager.Instance.Current.Keys.LoadingError_FailedToLoadSectionContent.SafeFormat(ex.Message);
                parentItem.Errors.Add(TREE_LOADING_CATEGORY, message);
                _logger.LogError(ex, message);
            }
        }