Пример #1
0
        /// <summary>Sends an ATA command in 48-bit format</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="ptId">Platform ID for executing the command</param>
        /// <param name="fd">File handle</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if ATA returned non-OK status</param>
        /// <param name="registers">Registers to send to the device</param>
        /// <param name="errorRegisters">Registers returned by the device</param>
        /// <param name="protocol">ATA protocol to use</param>
        /// <param name="transferRegister">What register contains the transfer length</param>
        /// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersLba48 registers,
                                           out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
                                           AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
                                           bool transferBlocks, out double duration, out bool sense)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
            {
                // No check for Windows version. A 48-bit ATA disk simply does not work on earlier systems
                return(Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol,
                                                      ref buffer, timeout, out duration, out sense));
            }

            case PlatformID.Linux:
            {
                return(Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol,
                                                    transferRegister, ref buffer, timeout, transferBlocks,
                                                    out duration, out sense));
            }

            case PlatformID.FreeBSD:
            {
                return(FreeBSD.Command.SendAtaCommand((IntPtr)fd, registers, out errorRegisters, protocol,
                                                      ref buffer, timeout, out duration, out sense));
            }

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #2
0
        /// <summary>Sends a SCSI command</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="fd">File handle</param>
        /// <param name="cdb">SCSI CDB</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="senseBuffer">Buffer with the SCSI sense</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="direction">SCSI command transfer direction</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense">
        ///     <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
        ///     sense
        /// </param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendScsiCommand(object fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer,
                                            uint timeout, ScsiDirection direction, out double duration, out bool sense)
        {
            PlatformID ptId = DetectOS.GetRealPlatformID();

            return(SendScsiCommand(ptId, fd, cdb, ref buffer, out senseBuffer, timeout, direction, out duration,
                                   out sense));
        }
Пример #3
0
        /// <summary>Sends a MMC/SD command</summary>
        /// <returns>The result of the command.</returns>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendMmcCommand(object fd, MmcCommands command, bool write, bool isApplication,
                                           MmcFlags flags, uint argument, uint blockSize, uint blocks,
                                           ref byte[] buffer, out uint[] response, out double duration, out bool sense,
                                           uint timeout = 0)
        {
            PlatformID ptId = DetectOS.GetRealPlatformID();

            return(SendMmcCommand(ptId, (int)fd, command, write, isApplication, flags, argument, blockSize, blocks,
                                  ref buffer, out response, out duration, out sense, timeout));
        }
Пример #4
0
        /// <summary>Sends an ATA command in 48-bit LBA format</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="fd">File handle</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if ATA returned non-OK status</param>
        /// <param name="registers">Registers to send to the device</param>
        /// <param name="errorRegisters">Registers returned by the device</param>
        /// <param name="protocol">ATA protocol to use</param>
        /// <param name="transferRegister">What register contains the transfer length</param>
        /// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendAtaCommand(object fd, AtaRegistersLba48 registers,
                                           out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
                                           AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
                                           bool transferBlocks, out double duration, out bool sense)
        {
            PlatformID ptId = DetectOS.GetRealPlatformID();

            return(SendAtaCommand(ptId, fd, registers, out errorRegisters, protocol, transferRegister, ref buffer,
                                  timeout, transferBlocks, out duration, out sense));
        }
Пример #5
0
        internal static int ReOpen(PlatformID ptId, string devicePath, object fd, out object newFd)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT: return(Windows.Command.ReOpen(devicePath, (SafeFileHandle)fd, out newFd));

            case PlatformID.Linux:   return(Linux.Command.ReOpen(devicePath, (int)fd, out newFd));

            default:                 throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #6
0
        internal static int BufferedOsRead(PlatformID ptId, object fd, out byte[] buffer, long offset, uint length,
                                           out double duration)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
                return(Windows.Command.BufferedOsRead((SafeFileHandle)fd, out buffer, offset, length, out duration));

            case PlatformID.Linux:
                return(Linux.Command.BufferedOsRead((int)fd, out buffer, offset, length, out duration));

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #7
0
        internal static int SendMultipleMmcCommands(PlatformID ptId, object fd, Device.MmcSingleCommand[] commands,
                                                    out double duration, out bool sense, uint timeout = 0)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
                return(Windows.Command.SendMultipleMmcCommands((SafeFileHandle)fd, commands, out duration,
                                                               out sense, timeout));

            case PlatformID.Linux:
                return(Linux.Command.SendMultipleMmcCommands((int)fd, commands, out duration, out sense, timeout));

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #8
0
        /// <summary>Sends an ATA command in 28-bit LBA format</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="ptId">Platform ID for executing the command</param>
        /// <param name="fd">File handle</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if ATA returned non-OK status</param>
        /// <param name="registers">Registers to send to the device</param>
        /// <param name="errorRegisters">Registers returned by the device</param>
        /// <param name="protocol">ATA protocol to use</param>
        /// <param name="transferRegister">What register contains the transfer length</param>
        /// <param name="transferBlocks">Set to <c>true</c> if the transfer length is in block, otherwise it is in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendAtaCommand(PlatformID ptId, object fd, AtaRegistersLba28 registers,
                                           out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
                                           AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
                                           bool transferBlocks, out double duration, out bool sense)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
            {
                if ((Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1 &&
                     (Environment.OSVersion.ServicePack == "Service Pack 1" ||
                      Environment.OSVersion.ServicePack == "")) ||
                    (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0))
                {
                    throw new InvalidOperationException("Windows XP or earlier is not supported.");
                }

                // Windows NT 4 or earlier, requires special ATA pass thru SCSI. But Aaru cannot run there (or can it?)
                if (Environment.OSVersion.Version.Major <= 4)
                {
                    throw new InvalidOperationException("Windows NT 4.0 or earlier is not supported.");
                }

                return(Windows.Command.SendAtaCommand((SafeFileHandle)fd, registers, out errorRegisters, protocol,
                                                      ref buffer, timeout, out duration, out sense));
            }

            case PlatformID.Linux:
            {
                return(Linux.Command.SendAtaCommand((int)fd, registers, out errorRegisters, protocol,
                                                    transferRegister, ref buffer, timeout, transferBlocks,
                                                    out duration, out sense));
            }

            case PlatformID.FreeBSD:
            {
                return(FreeBSD.Command.SendAtaCommand((IntPtr)fd, registers, out errorRegisters, protocol,
                                                      ref buffer, timeout, out duration, out sense));
            }

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #9
0
        /// <summary>Sends a MMC/SD command</summary>
        /// <returns>The result of the command.</returns>
        /// <param name="ptId">Platform ID for executing the command</param>
        /// <param name="fd">File handle</param>
        /// <param name="command">MMC/SD opcode</param>
        /// <param name="buffer">Buffer for MMC/SD command response</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense"><c>True</c> if MMC/SD returned non-OK status</param>
        /// <param name="write"><c>True</c> if data is sent from host to card</param>
        /// <param name="isApplication"><c>True</c> if command should be preceded with CMD55</param>
        /// <param name="flags">Flags indicating kind and place of response</param>
        /// <param name="blocks">How many blocks to transfer</param>
        /// <param name="argument">Command argument</param>
        /// <param name="response">Response registers</param>
        /// <param name="blockSize">Size of block in bytes</param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendMmcCommand(PlatformID ptId, object fd, MmcCommands command, bool write,
                                           bool isApplication, MmcFlags flags, uint argument, uint blockSize,
                                           uint blocks, ref byte[] buffer, out uint[] response, out double duration,
                                           out bool sense, uint timeout = 0)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
                return(Windows.Command.SendMmcCommand((SafeFileHandle)fd, command, write, isApplication, flags,
                                                      argument, blockSize, blocks, ref buffer, out response,
                                                      out duration, out sense, timeout));

            case PlatformID.Linux:
                return(Linux.Command.SendMmcCommand((int)fd, command, write, isApplication, flags, argument,
                                                    blockSize, blocks, ref buffer, out response, out duration,
                                                    out sense, timeout));

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #10
0
        /// <summary>Sends a SCSI command</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="ptId">Platform ID for executing the command</param>
        /// <param name="fd">File handle</param>
        /// <param name="cdb">SCSI CDB</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="senseBuffer">Buffer with the SCSI sense</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="direction">SCSI command transfer direction</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense">
        ///     <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
        ///     sense
        /// </param>
        /// <exception cref="InvalidOperationException">If the specified platform is not supported</exception>
        internal static int SendScsiCommand(PlatformID ptId, object fd, byte[] cdb, ref byte[] buffer,
                                            out byte[] senseBuffer, uint timeout, ScsiDirection direction,
                                            out double duration, out bool sense)
        {
            switch (ptId)
            {
            case PlatformID.Win32NT:
            {
                ScsiIoctlDirection dir;

                switch (direction)
                {
                case ScsiDirection.In:
                    dir = ScsiIoctlDirection.In;

                    break;

                case ScsiDirection.Out:
                    dir = ScsiIoctlDirection.Out;

                    break;

                default:
                    dir = ScsiIoctlDirection.Unspecified;

                    break;
                }

                return(Windows.Command.SendScsiCommand((SafeFileHandle)fd, cdb, ref buffer, out senseBuffer,
                                                       timeout, dir, out duration, out sense));
            }

            case PlatformID.Linux:
            {
                Linux.ScsiIoctlDirection dir;

                switch (direction)
                {
                case ScsiDirection.In:
                    dir = Linux.ScsiIoctlDirection.In;

                    break;

                case ScsiDirection.Out:
                    dir = Linux.ScsiIoctlDirection.Out;

                    break;

                case ScsiDirection.Bidirectional:
                    dir = Linux.ScsiIoctlDirection.Unspecified;

                    break;

                case ScsiDirection.None:
                    dir = Linux.ScsiIoctlDirection.None;

                    break;

                default:
                    dir = Linux.ScsiIoctlDirection.Unknown;

                    break;
                }

                return(Linux.Command.SendScsiCommand((int)fd, cdb, ref buffer, out senseBuffer, timeout, dir,
                                                     out duration, out sense));
            }

            case PlatformID.FreeBSD:
            {
                CcbFlags flags = 0;

                switch (direction)
                {
                case ScsiDirection.In:
                    flags = CcbFlags.CamDirIn;

                    break;

                case ScsiDirection.Out:
                    flags = CcbFlags.CamDirOut;

                    break;

                case ScsiDirection.Bidirectional:
                    flags = CcbFlags.CamDirBoth;

                    break;

                case ScsiDirection.None:
                    flags = CcbFlags.CamDirNone;

                    break;
                }

                return(IntPtr.Size == 8
                               ? FreeBSD.Command.SendScsiCommand64((IntPtr)fd, cdb, ref buffer, out senseBuffer,
                                                                   timeout, flags, out duration, out sense)
                               : FreeBSD.Command.SendScsiCommand((IntPtr)fd, cdb, ref buffer, out senseBuffer, timeout,
                                                                 flags, out duration, out sense));
            }

            default: throw new InvalidOperationException($"Platform {ptId} not yet supported.");
            }
        }
Пример #11
0
        /// <summary>Initializes the dump log</summary>
        /// <param name="outputFile">Output log file</param>
        /// <param name="dev">Device</param>
        /// <param name="private">Disable saving paths or serial numbers in log</param>
        public DumpLog(string outputFile, Device dev, bool @private)
        {
            if (string.IsNullOrEmpty(outputFile))
            {
                return;
            }

            _logSw = new StreamWriter(outputFile, true);

            _logSw.WriteLine("Start logging at {0}", DateTime.Now);

            PlatformID platId  = DetectOS.GetRealPlatformID();
            string     platVer = DetectOS.GetVersion();

            var assemblyVersion =
                Attribute.GetCustomAttribute(typeof(DumpLog).Assembly, typeof(AssemblyInformationalVersionAttribute)) as
                AssemblyInformationalVersionAttribute;

            _logSw.WriteLine("################# System information #################");

            _logSw.WriteLine("{0} {1} ({2}-bit)", DetectOS.GetPlatformName(platId, platVer), platVer,
                             Environment.Is64BitOperatingSystem ? 64 : 32);

            if (DetectOS.IsMono)
            {
                _logSw.WriteLine("Mono {0}", Version.GetMonoVersion());
            }
            else if (DetectOS.IsNetCore)
            {
                _logSw.WriteLine(".NET Core {0}", Version.GetNetCoreVersion());
            }
            else
            {
                _logSw.WriteLine(RuntimeInformation.FrameworkDescription);
            }

            _logSw.WriteLine();

            _logSw.WriteLine("################# Program information ################");
            _logSw.WriteLine("Aaru {0}", assemblyVersion?.InformationalVersion);
            _logSw.WriteLine("Running in {0}-bit", Environment.Is64BitProcess ? 64 : 32);
            _logSw.WriteLine("Running as superuser: {0}", DetectOS.IsAdmin ? "Yes" : "No");
        #if DEBUG
            _logSw.WriteLine("DEBUG version");
        #endif
            if (@private)
            {
                string[] args = Environment.GetCommandLineArgs();

                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i].StartsWith("/dev", StringComparison.OrdinalIgnoreCase) ||
                        args[i].StartsWith("aaru://", StringComparison.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    try
                    {
                        args[i] = Path.GetFileName(args[i]);
                    }
                    catch
                    {
                        // Do nothing
                    }
                }

                _logSw.WriteLine("Command line: {0}", string.Join(" ", args));
            }
            else
            {
                _logSw.WriteLine("Command line: {0}", Environment.CommandLine);
            }

            _logSw.WriteLine();

            if (dev.IsRemote)
            {
                _logSw.WriteLine("################# Remote information #################");
                _logSw.WriteLine("Server: {0}", dev.RemoteApplication);
                _logSw.WriteLine("Version: {0}", dev.RemoteVersion);

                _logSw.WriteLine("Operating system: {0} {1}", dev.RemoteOperatingSystem,
                                 dev.RemoteOperatingSystemVersion);

                _logSw.WriteLine("Architecture: {0}", dev.RemoteArchitecture);
                _logSw.WriteLine("Protocol version: {0}", dev.RemoteProtocolVersion);
                _logSw.WriteLine("Running as superuser: {0}", dev.IsRemoteAdmin ? "Yes" : "No");
                _logSw.WriteLine("######################################################");
            }

            _logSw.WriteLine("################# Device information #################");
            _logSw.WriteLine("Manufacturer: {0}", dev.Manufacturer);
            _logSw.WriteLine("Model: {0}", dev.Model);
            _logSw.WriteLine("Firmware revision: {0}", dev.FirmwareRevision);

            if (!@private)
            {
                _logSw.WriteLine("Serial number: {0}", dev.Serial);
            }

            _logSw.WriteLine("Removable device: {0}", dev.IsRemovable);
            _logSw.WriteLine("Device type: {0}", dev.Type);
            _logSw.WriteLine("CompactFlash device: {0}", dev.IsCompactFlash);
            _logSw.WriteLine("PCMCIA device: {0}", dev.IsPcmcia);
            _logSw.WriteLine("USB device: {0}", dev.IsUsb);

            if (dev.IsUsb)
            {
                _logSw.WriteLine("USB manufacturer: {0}", dev.UsbManufacturerString);
                _logSw.WriteLine("USB product: {0}", dev.UsbProductString);

                if (!@private)
                {
                    _logSw.WriteLine("USB serial: {0}", dev.UsbSerialString);
                }

                _logSw.WriteLine("USB vendor ID: {0:X4}h", dev.UsbVendorId);
                _logSw.WriteLine("USB product ID: {0:X4}h", dev.UsbProductId);
            }

            _logSw.WriteLine("FireWire device: {0}", dev.IsFireWire);

            if (dev.IsFireWire)
            {
                _logSw.WriteLine("FireWire vendor: {0}", dev.FireWireVendorName);
                _logSw.WriteLine("FireWire model: {0}", dev.FireWireModelName);

                if (!@private)
                {
                    _logSw.WriteLine("FireWire GUID: 0x{0:X16}", dev.FireWireGuid);
                }

                _logSw.WriteLine("FireWire vendor ID: 0x{0:X8}", dev.FireWireVendor);
                _logSw.WriteLine("FireWire product ID: 0x{0:X8}", dev.FireWireModel);
            }

            _logSw.WriteLine("######################################################");

            _logSw.WriteLine();
            _logSw.WriteLine("################ Dumping progress log ################");
            _logSw.Flush();
        }
Пример #12
0
        protected void OnBtnSaveClicked(object sender, EventArgs e)
        {
            var dlgSave = new SaveFileDialog
            {
                CheckFileExists = true
            };

            dlgSave.Filters.Add(new FileFilter
            {
                Extensions = new[]
                {
                    "log"
                },
                Name = "Log files"
            });

            DialogResult result = dlgSave.ShowDialog(this);

            if (result != DialogResult.Ok)
            {
                return;
            }

            try
            {
                var logFs = new FileStream(dlgSave.FileName, FileMode.Create, FileAccess.ReadWrite);
                var logSw = new StreamWriter(logFs);

                logSw.WriteLine("Log saved at {0}", DateTime.Now);

                PlatformID platId  = DetectOS.GetRealPlatformID();
                string     platVer = DetectOS.GetVersion();

                var assemblyVersion =
                    Attribute.GetCustomAttribute(typeof(AaruConsole).Assembly,
                                                 typeof(AssemblyInformationalVersionAttribute)) as
                    AssemblyInformationalVersionAttribute;

                logSw.WriteLine("################# System information #################");

                logSw.WriteLine("{0} {1} ({2}-bit)", DetectOS.GetPlatformName(platId, platVer), platVer,
                                Environment.Is64BitOperatingSystem ? 64 : 32);

                if (DetectOS.IsMono)
                {
                    logSw.WriteLine("Mono {0}", Version.GetMonoVersion());
                }
                else if (DetectOS.IsNetCore)
                {
                    logSw.WriteLine(".NET Core {0}", Version.GetNetCoreVersion());
                }
                else
                {
                    logSw.WriteLine(RuntimeInformation.FrameworkDescription);
                }

                logSw.WriteLine();

                logSw.WriteLine("################# Program information ################");
                logSw.WriteLine("Aaru {0}", assemblyVersion?.InformationalVersion);
                logSw.WriteLine("Running in {0}-bit", Environment.Is64BitProcess ? 64 : 32);
                logSw.WriteLine("Running GUI mode using {0}", Application.Instance.Platform.ID);
            #if DEBUG
                logSw.WriteLine("DEBUG version");
            #endif
                logSw.WriteLine("Command line: {0}", Environment.CommandLine);
                logSw.WriteLine();

                logSw.WriteLine("################# Console ################");

                foreach (LogEntry entry in ConsoleHandler.Entries)
                {
                    if (entry.Type != "Info")
                    {
                        logSw.WriteLine("{0}: ({1}) {2}", entry.Timestamp, entry.Type.ToLower(), entry.Message);
                    }
                    else
                    {
                        logSw.WriteLine("{0}: {1}", entry.Timestamp, entry.Message);
                    }
                }

                logSw.Close();
                logFs.Close();
            }
            catch (Exception exception)
            {
                MessageBox.Show("Exception {0} trying to save logfile, details has been sent to console.",
                                exception.Message);

                AaruConsole.ErrorWriteLine("Console", exception.Message);
                AaruConsole.ErrorWriteLine("Console", exception.StackTrace);
            }
        }
Пример #13
0
        public static void SaveSettings()
        {
            try
            {
                PlatformID ptId = DetectOS.GetRealPlatformID();

                switch (ptId)
                {
                // In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.aaru.plist
                case PlatformID.MacOSX:
                case PlatformID.iOS:
                {
                    var root = new NSDictionary
                    {
                        {
                            "SaveReportsGlobally", Current.SaveReportsGlobally
                        },
                        {
                            "ShareReports", Current.ShareReports
                        },
                        {
                            "GdprCompliance", Current.GdprCompliance
                        },
                        {
                            "EnableDecryption", Current.EnableDecryption
                        }
                    };

                    if (Current.Stats != null)
                    {
                        var stats = new NSDictionary
                        {
                            {
                                "ShareStats", Current.Stats.ShareStats
                            },
                            {
                                "CommandStats", Current.Stats.CommandStats
                            },
                            {
                                "DeviceStats", Current.Stats.DeviceStats
                            },
                            {
                                "FilesystemStats", Current.Stats.FilesystemStats
                            },
                            {
                                "FilterStats", Current.Stats.FilterStats
                            },
                            {
                                "MediaImageStats", Current.Stats.MediaImageStats
                            },
                            {
                                "MediaScanStats", Current.Stats.MediaScanStats
                            },
                            {
                                "PartitionStats", Current.Stats.PartitionStats
                            },
                            {
                                "MediaStats", Current.Stats.MediaStats
                            },
                            {
                                "VerifyStats", Current.Stats.VerifyStats
                            }
                        };

                        root.Add("Stats", stats);
                    }

                    string preferencesPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
                                     "Preferences");

                    string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.aaru.plist");

                    var fs = new FileStream(preferencesFilePath, FileMode.Create);
                    BinaryPropertyListWriter.Write(fs, root);
                    fs.Close();
                }

                break;

                #if !NETSTANDARD2_0
                // In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/Aaru
                case PlatformID.Win32NT:
                case PlatformID.Win32S:
                case PlatformID.Win32Windows:
                case PlatformID.WinCE:
                case PlatformID.WindowsPhone:
                {
                    RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE", true)?.
                                            CreateSubKey("Claunia.com");

                    RegistryKey key = parentKey?.CreateSubKey("Aaru");

                    if (key != null)
                    {
                        key.SetValue("SaveReportsGlobally", Current.SaveReportsGlobally);
                        key.SetValue("ShareReports", Current.ShareReports);
                        key.SetValue("GdprCompliance", Current.GdprCompliance);
                        key.SetValue("EnableDecryption", Current.EnableDecryption);

                        if (Current.Stats != null)
                        {
                            key.SetValue("Statistics", true);
                            key.SetValue("ShareStats", Current.Stats.ShareStats);
                            key.SetValue("CommandStats", Current.Stats.CommandStats);
                            key.SetValue("DeviceStats", Current.Stats.DeviceStats);
                            key.SetValue("FilesystemStats", Current.Stats.FilesystemStats);
                            key.SetValue("FilterStats", Current.Stats.FilterStats);
                            key.SetValue("MediaImageStats", Current.Stats.MediaImageStats);
                            key.SetValue("MediaScanStats", Current.Stats.MediaScanStats);
                            key.SetValue("PartitionStats", Current.Stats.PartitionStats);
                            key.SetValue("MediaStats", Current.Stats.MediaStats);
                            key.SetValue("VerifyStats", Current.Stats.VerifyStats);
                        }
                        else
                        {
                            key.SetValue("Statistics", true);
                            key.DeleteValue("ShareStats", false);
                            key.DeleteValue("CommandStats", false);
                            key.DeleteValue("DeviceStats", false);
                            key.DeleteValue("FilesystemStats", false);
                            key.DeleteValue("MediaImageStats", false);
                            key.DeleteValue("MediaScanStats", false);
                            key.DeleteValue("PartitionStats", false);
                            key.DeleteValue("MediaStats", false);
                            key.DeleteValue("VerifyStats", false);
                        }
                    }
                }

                break;
                #endif

                // Otherwise, settings will be saved in ~/.config/Aaru.xml
                default:
                {
                    string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

                    string xdgConfigPath =
                        Path.Combine(homePath,
                                     Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
                                     XDG_CONFIG_HOME_RESOLVED);

                    string settingsPath = Path.Combine(xdgConfigPath, "Aaru.xml");

                    if (!Directory.Exists(xdgConfigPath))
                    {
                        Directory.CreateDirectory(xdgConfigPath);
                    }

                    var fs = new FileStream(settingsPath, FileMode.Create);
                    var xs = new XmlSerializer(Current.GetType());
                    xs.Serialize(fs, Current);
                    fs.Close();
                }

                break;
                }
            }
            #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
            catch
            {
                // ignored
            }
            #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
        }
Пример #14
0
        /// <summary>Loads settings</summary>
        public static void LoadSettings()
        {
            Current = new DicSettings();
            PlatformID ptId     = DetectOS.GetRealPlatformID();
            string     homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

            LocalDbPath = "local.db";
            string oldMainDbPath = "master.db";

            MainDbPath = "main.db";

            try
            {
                switch (ptId)
                {
                // In case of macOS or iOS statistics and reports will be saved in ~/Library/Application Support/Claunia.com/Aaru
                case PlatformID.MacOSX:
                case PlatformID.iOS:
                {
                    string appSupportPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
                                     "Application Support", "Claunia.com");

                    if (!Directory.Exists(appSupportPath))
                    {
                        Directory.CreateDirectory(appSupportPath);
                    }

                    string dicPath  = Path.Combine(appSupportPath, "DiscImageChef");
                    string aaruPath = Path.Combine(appSupportPath, "Aaru");

                    if (Directory.Exists(dicPath) &&
                        !Directory.Exists(aaruPath))
                    {
                        Directory.Move(dicPath, aaruPath);
                    }

                    if (!Directory.Exists(aaruPath))
                    {
                        Directory.CreateDirectory(aaruPath);
                    }

                    LocalDbPath   = Path.Combine(aaruPath, LocalDbPath);
                    MainDbPath    = Path.Combine(aaruPath, MainDbPath);
                    oldMainDbPath = Path.Combine(aaruPath, oldMainDbPath);

                    ReportsPath = Path.Combine(aaruPath, "Reports");

                    if (!Directory.Exists(ReportsPath))
                    {
                        Directory.CreateDirectory(ReportsPath);
                    }

                    StatsPath = Path.Combine(aaruPath, "Statistics");

                    if (!Directory.Exists(StatsPath))
                    {
                        Directory.CreateDirectory(StatsPath);
                    }
                }

                break;

                // In case of Windows statistics and reports will be saved in %APPDATA%\Claunia.com\Aaru
                case PlatformID.Win32NT:
                case PlatformID.Win32S:
                case PlatformID.Win32Windows:
                case PlatformID.WinCE:
                case PlatformID.WindowsPhone:
                {
                    string appSupportPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                     "Claunia.com");

                    if (!Directory.Exists(appSupportPath))
                    {
                        Directory.CreateDirectory(appSupportPath);
                    }

                    string dicPath  = Path.Combine(appSupportPath, "DiscImageChef");
                    string aaruPath = Path.Combine(appSupportPath, "Aaru");

                    if (Directory.Exists(dicPath) &&
                        !Directory.Exists(aaruPath))
                    {
                        Directory.Move(dicPath, aaruPath);
                    }

                    if (!Directory.Exists(aaruPath))
                    {
                        Directory.CreateDirectory(aaruPath);
                    }

                    LocalDbPath   = Path.Combine(aaruPath, LocalDbPath);
                    MainDbPath    = Path.Combine(aaruPath, MainDbPath);
                    oldMainDbPath = Path.Combine(aaruPath, oldMainDbPath);

                    ReportsPath = Path.Combine(aaruPath, "Reports");

                    if (!Directory.Exists(ReportsPath))
                    {
                        Directory.CreateDirectory(ReportsPath);
                    }

                    StatsPath = Path.Combine(aaruPath, "Statistics");

                    if (!Directory.Exists(StatsPath))
                    {
                        Directory.CreateDirectory(StatsPath);
                    }
                }

                break;

                // Otherwise, statistics and reports will be saved in ~/.claunia.com/Aaru
                default:
                {
                    string xdgDataPath =
                        Path.Combine(homePath,
                                     Environment.GetEnvironmentVariable(XDG_DATA_HOME) ?? XDG_DATA_HOME_RESOLVED);

                    string oldDicPath = Path.Combine(homePath, ".claunia.com", "DiscImageChef");
                    string dicPath    = Path.Combine(xdgDataPath, "DiscImageChef");
                    string aaruPath   = Path.Combine(xdgDataPath, "Aaru");

                    if (Directory.Exists(oldDicPath) &&
                        !Directory.Exists(aaruPath))
                    {
                        Directory.Move(oldDicPath, aaruPath);
                        Directory.Delete(Path.Combine(homePath, ".claunia.com"));
                    }

                    if (Directory.Exists(dicPath) &&
                        !Directory.Exists(aaruPath))
                    {
                        Directory.Move(dicPath, aaruPath);
                    }

                    if (!Directory.Exists(aaruPath))
                    {
                        Directory.CreateDirectory(aaruPath);
                    }

                    LocalDbPath   = Path.Combine(aaruPath, LocalDbPath);
                    MainDbPath    = Path.Combine(aaruPath, MainDbPath);
                    oldMainDbPath = Path.Combine(aaruPath, oldMainDbPath);

                    ReportsPath = Path.Combine(aaruPath, "Reports");

                    if (!Directory.Exists(ReportsPath))
                    {
                        Directory.CreateDirectory(ReportsPath);
                    }

                    StatsPath = Path.Combine(aaruPath, "Statistics");

                    if (!Directory.Exists(StatsPath))
                    {
                        Directory.CreateDirectory(StatsPath);
                    }
                }

                break;
                }

                if (File.Exists(oldMainDbPath))
                {
                    File.Move(oldMainDbPath, MainDbPath);
                }
            }
            catch
            {
                ReportsPath = null;
            }

            FileStream   prefsFs = null;
            StreamReader prefsSr = null;

            try
            {
                switch (ptId)
                {
                // In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.aaru.plist
                case PlatformID.MacOSX:
                case PlatformID.iOS:
                {
                    string preferencesPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
                                     "Preferences");

                    string dicPreferencesFilePath =
                        Path.Combine(preferencesPath, "com.claunia.discimagechef.plist");

                    string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.aaru.plist");

                    if (File.Exists(dicPreferencesFilePath))
                    {
                        File.Move(dicPreferencesFilePath, preferencesFilePath);
                    }

                    if (!File.Exists(preferencesFilePath))
                    {
                        SetDefaultSettings();
                        SaveSettings();
                    }

                    prefsFs = new FileStream(preferencesFilePath, FileMode.Open, FileAccess.Read);

                    var parsedPreferences = (NSDictionary)BinaryPropertyListParser.Parse(prefsFs);

                    if (parsedPreferences != null)
                    {
                        Current.SaveReportsGlobally =
                            parsedPreferences.TryGetValue("SaveReportsGlobally", out NSObject obj) &&
                            ((NSNumber)obj).ToBool();

                        Current.ShareReports = parsedPreferences.TryGetValue("ShareReports", out obj) &&
                                               ((NSNumber)obj).ToBool();

                        Current.EnableDecryption = parsedPreferences.TryGetValue("EnableDecryption", out obj) &&
                                                   ((NSNumber)obj).ToBool();

                        if (parsedPreferences.TryGetValue("Stats", out obj))
                        {
                            var stats = (NSDictionary)obj;

                            if (stats != null)
                            {
                                Current.Stats = new StatsSettings
                                {
                                    ShareStats = stats.TryGetValue("ShareStats", out NSObject obj2) &&
                                                 ((NSNumber)obj2).ToBool(),
                                    CommandStats = stats.TryGetValue("CommandStats", out obj2) &&
                                                   ((NSNumber)obj2).ToBool(),
                                    DeviceStats = stats.TryGetValue("DeviceStats", out obj2) &&
                                                  ((NSNumber)obj2).ToBool(),
                                    FilesystemStats =
                                        stats.TryGetValue("FilesystemStats", out obj2) && ((NSNumber)obj2).ToBool(),
                                    FilterStats = stats.TryGetValue("FilterStats", out obj2) &&
                                                  ((NSNumber)obj2).ToBool(),
                                    MediaImageStats =
                                        stats.TryGetValue("MediaImageStats", out obj2) && ((NSNumber)obj2).ToBool(),
                                    MediaScanStats =
                                        stats.TryGetValue("MediaScanStats", out obj2) && ((NSNumber)obj2).ToBool(),
                                    PartitionStats =
                                        stats.TryGetValue("PartitionStats", out obj2) && ((NSNumber)obj2).ToBool(),
                                    MediaStats = stats.TryGetValue("MediaStats", out obj2) &&
                                                 ((NSNumber)obj2).ToBool(),
                                    VerifyStats = stats.TryGetValue("VerifyStats", out obj2) &&
                                                  ((NSNumber)obj2).ToBool()
                                }
                            }
                            ;
                        }
                        else
                        {
                            Current.Stats = null;
                        }

                        Current.GdprCompliance = parsedPreferences.TryGetValue("GdprCompliance", out obj)
                                                         ? (ulong)((NSNumber)obj).ToLong() : 0;

                        prefsFs.Close();
                    }
                    else
                    {
                        prefsFs.Close();

                        SetDefaultSettings();
                        SaveSettings();
                    }
                }

                break;

                #if !NETSTANDARD2_0
                // In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/Aaru
                case PlatformID.Win32NT:
                case PlatformID.Win32S:
                case PlatformID.Win32Windows:
                case PlatformID.WinCE:
                case PlatformID.WindowsPhone:
                {
                    RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("Claunia.com");

                    if (parentKey == null)
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    RegistryKey dicKey = parentKey.OpenSubKey("DiscImageChef");
                    RegistryKey key    = parentKey.OpenSubKey("Aaru");
                    bool        stats;

                    if (dicKey != null &&
                        key == null)
                    {
                        Current.SaveReportsGlobally = Convert.ToBoolean(dicKey.GetValue("SaveReportsGlobally"));
                        Current.ShareReports        = Convert.ToBoolean(dicKey.GetValue("ShareReports"));
                        Current.GdprCompliance      = Convert.ToUInt64(dicKey.GetValue("GdprCompliance"));
                        Current.EnableDecryption    = Convert.ToBoolean(dicKey.GetValue("EnableDecryption"));

                        stats = Convert.ToBoolean(dicKey.GetValue("Statistics"));

                        if (stats)
                        {
                            Current.Stats = new StatsSettings
                            {
                                ShareStats      = Convert.ToBoolean(dicKey.GetValue("ShareStats")),
                                CommandStats    = Convert.ToBoolean(dicKey.GetValue("CommandStats")),
                                DeviceStats     = Convert.ToBoolean(dicKey.GetValue("DeviceStats")),
                                FilesystemStats = Convert.ToBoolean(dicKey.GetValue("FilesystemStats")),
                                FilterStats     = Convert.ToBoolean(dicKey.GetValue("FilterStats")),
                                MediaImageStats = Convert.ToBoolean(dicKey.GetValue("MediaImageStats")),
                                MediaScanStats  = Convert.ToBoolean(dicKey.GetValue("MediaScanStats")),
                                PartitionStats  = Convert.ToBoolean(dicKey.GetValue("PartitionStats")),
                                MediaStats      = Convert.ToBoolean(dicKey.GetValue("MediaStats")),
                                VerifyStats     = Convert.ToBoolean(dicKey.GetValue("VerifyStats"))
                            }
                        }
                        ;

                        SaveSettings();

                        parentKey.DeleteSubKeyTree("DiscImageChef");

                        return;
                    }

                    if (key == null)
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    Current.SaveReportsGlobally = Convert.ToBoolean(key.GetValue("SaveReportsGlobally"));
                    Current.ShareReports        = Convert.ToBoolean(key.GetValue("ShareReports"));
                    Current.GdprCompliance      = Convert.ToUInt64(key.GetValue("GdprCompliance"));
                    Current.EnableDecryption    = Convert.ToBoolean(key.GetValue("EnableDecryption"));

                    stats = Convert.ToBoolean(key.GetValue("Statistics"));

                    if (stats)
                    {
                        Current.Stats = new StatsSettings
                        {
                            ShareStats      = Convert.ToBoolean(key.GetValue("ShareStats")),
                            CommandStats    = Convert.ToBoolean(key.GetValue("CommandStats")),
                            DeviceStats     = Convert.ToBoolean(key.GetValue("DeviceStats")),
                            FilesystemStats = Convert.ToBoolean(key.GetValue("FilesystemStats")),
                            FilterStats     = Convert.ToBoolean(key.GetValue("FilterStats")),
                            MediaImageStats = Convert.ToBoolean(key.GetValue("MediaImageStats")),
                            MediaScanStats  = Convert.ToBoolean(key.GetValue("MediaScanStats")),
                            PartitionStats  = Convert.ToBoolean(key.GetValue("PartitionStats")),
                            MediaStats      = Convert.ToBoolean(key.GetValue("MediaStats")),
                            VerifyStats     = Convert.ToBoolean(key.GetValue("VerifyStats"))
                        }
                    }
                    ;
                }

                break;
                #endif

                // Otherwise, settings will be saved in ~/.config/Aaru.xml
                default:
                {
                    string oldConfigPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config");

                    string oldSettingsPath = Path.Combine(oldConfigPath, "DiscImageChef.xml");

                    string xdgConfigPath =
                        Path.Combine(homePath,
                                     Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
                                     XDG_CONFIG_HOME_RESOLVED);

                    string dicSettingsPath = Path.Combine(xdgConfigPath, "DiscImageChef.xml");
                    string settingsPath    = Path.Combine(xdgConfigPath, "Aaru.xml");

                    if (File.Exists(oldSettingsPath) &&
                        !File.Exists(settingsPath))
                    {
                        if (!Directory.Exists(xdgConfigPath))
                        {
                            Directory.CreateDirectory(xdgConfigPath);
                        }

                        File.Move(oldSettingsPath, settingsPath);
                    }

                    if (File.Exists(dicSettingsPath) &&
                        !File.Exists(settingsPath))
                    {
                        File.Move(dicSettingsPath, settingsPath);
                    }

                    if (!File.Exists(settingsPath))
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    var xs = new XmlSerializer(Current.GetType());
                    prefsSr = new StreamReader(settingsPath);
                    Current = (DicSettings)xs.Deserialize(prefsSr);
                }

                break;
                }
            }
            catch
            {
                prefsFs?.Close();
                prefsSr?.Close();
                SetDefaultSettings();
                SaveSettings();
            }
        }
Пример #15
0
        /// <summary>Loads settings</summary>
        public static void LoadSettings()
        {
            Current = new SetSettings();
            PlatformID ptId     = DetectOS.GetRealPlatformID();
            string     homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

            FileStream   prefsFs = null;
            StreamReader prefsSr = null;

            try
            {
                switch (ptId)
                {
                // In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
                case PlatformID.MacOSX:
                case PlatformID.iOS:
                {
                    string preferencesPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
                                     "Preferences");

                    string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");

                    if (!File.Exists(preferencesFilePath))
                    {
                        SetDefaultSettings();
                        SaveSettings();
                    }

                    prefsFs = new FileStream(preferencesFilePath, FileMode.Open, FileAccess.Read);

                    var parsedPreferences = (NSDictionary)BinaryPropertyListParser.Parse(prefsFs);

                    if (parsedPreferences != null)
                    {
                        NSObject obj;

                        Current.DatabasePath = parsedPreferences.TryGetValue("DatabasePath", out obj)
                                                       ? ((NSString)obj).ToString() : null;

                        Current.RepositoryPath = parsedPreferences.TryGetValue("RepositoryPath", out obj)
                                                         ? ((NSString)obj).ToString() : null;

                        Current.TemporaryFolder = parsedPreferences.TryGetValue("TemporaryFolder", out obj)
                                                          ? ((NSString)obj).ToString() : null;

                        Current.UnArchiverPath = parsedPreferences.TryGetValue("UnArchiverPath", out obj)
                                                         ? ((NSString)obj).ToString() : null;

                        prefsFs.Close();
                    }
                    else
                    {
                        prefsFs.Close();

                        SetDefaultSettings();
                        SaveSettings();
                    }
                }

                break;

                #if !NETSTANDARD2_0
                // In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
                case PlatformID.Win32NT when OperatingSystem.IsWindows():
                case PlatformID.Win32S when OperatingSystem.IsWindows():
                case PlatformID.Win32Windows when OperatingSystem.IsWindows():
                case PlatformID.WinCE when OperatingSystem.IsWindows():
                case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
                {
                    RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE")?.OpenSubKey("Claunia.com");

                    if (parentKey == null)
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    RegistryKey key = parentKey.OpenSubKey("RomRepoMgr");

                    if (key == null)
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    Current.DatabasePath    = key.GetValue("DatabasePath") as string;
                    Current.RepositoryPath  = key.GetValue("RepositoryPath") as string;
                    Current.TemporaryFolder = key.GetValue("TemporaryFolder") as string;
                    Current.UnArchiverPath  = key.GetValue("UnArchiverPath") as string;
                }

                break;
                #endif

                // Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
                default:
                {
                    string xdgConfigPath =
                        Path.Combine(homePath,
                                     Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
                                     XDG_CONFIG_HOME_RESOLVED);

                    string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");

                    if (!File.Exists(settingsPath))
                    {
                        SetDefaultSettings();
                        SaveSettings();

                        return;
                    }

                    prefsSr = new StreamReader(settingsPath);

                    Current = JsonSerializer.Deserialize <SetSettings>(prefsSr.ReadToEnd(), new JsonSerializerOptions
                        {
                            AllowTrailingCommas         = true,
                            PropertyNameCaseInsensitive = true,
                            ReadCommentHandling         = JsonCommentHandling.Skip,
                            WriteIndented = true
                        });
                }

                break;
                }
            }
            catch
            {
                prefsFs?.Close();
                prefsSr?.Close();
                SetDefaultSettings();
                SaveSettings();
            }
        }
Пример #16
0
        public static void SaveSettings()
        {
            try
            {
                PlatformID ptId = DetectOS.GetRealPlatformID();

                switch (ptId)
                {
                // In case of macOS or iOS settings will be saved in ~/Library/Preferences/com.claunia.romrepomgr.plist
                case PlatformID.MacOSX:
                case PlatformID.iOS:
                {
                    var root = new NSDictionary
                    {
                        {
                            "DatabasePath", Current.DatabasePath
                        },
                        {
                            "RepositoryPath", Current.RepositoryPath
                        },
                        {
                            "TemporaryFolder", Current.TemporaryFolder
                        },
                        {
                            "UnArchiverPath", Current.UnArchiverPath
                        }
                    };

                    string preferencesPath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library",
                                     "Preferences");

                    string preferencesFilePath = Path.Combine(preferencesPath, "com.claunia.romrepomgr.plist");

                    var fs = new FileStream(preferencesFilePath, FileMode.Create);
                    BinaryPropertyListWriter.Write(fs, root);
                    fs.Close();
                }

                break;

                #if !NETSTANDARD2_0
                // In case of Windows settings will be saved in the registry: HKLM/SOFTWARE/Claunia.com/RomRepoMgr
                case PlatformID.Win32NT when OperatingSystem.IsWindows():
                case PlatformID.Win32S when OperatingSystem.IsWindows():
                case PlatformID.Win32Windows when OperatingSystem.IsWindows():
                case PlatformID.WinCE when OperatingSystem.IsWindows():
                case PlatformID.WindowsPhone when OperatingSystem.IsWindows():
                {
                    RegistryKey parentKey = Registry.CurrentUser.OpenSubKey("SOFTWARE", true)?.
                                            CreateSubKey("Claunia.com");

                    RegistryKey key = parentKey?.CreateSubKey("RomRepoMgr");

                    key?.SetValue("DatabasePath", Current.DatabasePath);
                    key?.SetValue("RepositoryPath", Current.RepositoryPath);
                    key?.SetValue("TemporaryFolder", Current.TemporaryFolder);
                    key?.SetValue("UnArchiverPath", Current.UnArchiverPath);
                }

                break;
                #endif

                // Otherwise, settings will be saved in ~/.config/RomRepoMgr.json
                default:
                {
                    string homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

                    string xdgConfigPath =
                        Path.Combine(homePath,
                                     Environment.GetEnvironmentVariable(XDG_CONFIG_HOME) ??
                                     XDG_CONFIG_HOME_RESOLVED);

                    string settingsPath = Path.Combine(xdgConfigPath, "RomRepoMgr.json");

                    if (!Directory.Exists(xdgConfigPath))
                    {
                        Directory.CreateDirectory(xdgConfigPath);
                    }

                    var prefsSr = new StreamWriter(settingsPath);

                    prefsSr.Write(JsonSerializer.Serialize(Current, new JsonSerializerOptions
                        {
                            AllowTrailingCommas         = true,
                            PropertyNameCaseInsensitive = true,
                            ReadCommentHandling         = JsonCommentHandling.Skip,
                            WriteIndented = true
                        }));

                    prefsSr.Close();
                }

                break;
                }
            }
            #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
            catch
            {
                // ignored
            }
            #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
        }