/// <summary>
 /// The constructor needs an expected header identifying the version of the .REG file, as well as import options
 /// </summary>
 /// <param name="expectedHeader">expected header identifying the version of the .REG file</param>
 /// <param name="options">import options</param>
 public RegFileParser(string expectedHeader, RegFileImportOptions options)
 {
     Options = options;
     Result = new RegKeyEntry(null, null);
     HeaderId = expectedHeader;
     NumberOfClosingBracketsExpected = 0;
 }
 /// <summary>
 /// Given the content of a .REG file, identify the proper registry importer
 /// </summary>
 /// <param name="content">File content</param>
 /// <param name="options">Registry import options</param>
 /// <returns>Registry importer suitable for this file</returns>
 public static IRegistryImporter CreateImporterFromString(string content, RegFileImportOptions options)
 {
     if (content.StartsWith(RegFileFormat5Importer.HEADER))
     {
         return new RegFileFormat5Importer(content, options);
     }
     else if (content.StartsWith(RegFileFormat4Importer.HEADER))
     {
         return new RegFileFormat4Importer(content, options);
     }
     throw new BadImageFormatException("Unsupported .REG file format detected");
 }
 /// <summary>
 /// Given a filename, identify the proper registry importer
 /// </summary>
 /// <param name="filename">Filename (including path)</param>
 /// <param name="options">Registry import options</param>
 /// <returns>Registry importer suitable for this file</returns>
 public static IRegistryImporter CreateImporterFromFile(string filename, RegFileImportOptions options)
 {
     return CreateImporterFromString(File.ReadAllText(filename), options);
 }
 /// <summary>
 /// The constructor takes the content of a .REG file, the expected header (=first line of the .REG file) and import options (if any)
 /// </summary>
 /// <param name="content">Content of the .REG file</param>
 /// <param name="expectedHeader">Expected header</param>
 /// <param name="options">Import options</param>
 public RegFileImporter(string content, string expectedHeader, RegFileImportOptions options)
 {
     Parser = new RegFileParser(expectedHeader, options);
     Content = content;
     Result = null;
 }
        private int Run(string[] args)
        {
            Options = RegFileImportOptions.IgnoreWhitespaces;
            Console.OutputEncoding = Encoding.GetEncoding(Encoding.Default.CodePage);

            string processType;
            if (Wow.Is64BitProcess)
            {
                processType = "64-bit";
                CurrentRegistryView = RegistryView.Registry64;
            }
            else if (Wow.Is64BitOperatingSystem)
            {
                processType = "32-bit process on 64-bit OS";
                CurrentRegistryView = RegistryView.Registry32;
            }
            else
            {
                processType = "32-bit";
                CurrentRegistryView = RegistryView.Default;
            }


            Args = new InputArgs(
                "REGDIFF",
                string.Format("Version {0}\r\nFreeware written by Gerson Kurz (http://p-nand-q.com) [{1}]",
                AppVersion.Get(), processType));
            
            Args.Add(InputArgType.RemainingParameters, "FILE {FILE}", null, Presence.Required, "one or more .REG files");
            Args.Add(InputArgType.Parameter, "merge", null, Presence.Optional, "create merged output file");
            Args.Add(InputArgType.Parameter, "diff", null, Presence.Optional, "create diff output file");
            Args.Add(InputArgType.Flag, "registry", false, Presence.Optional, "compare with the current registry value on your local machine");
            Args.Add(InputArgType.Flag, "4", false, Presence.Optional, "use .REG format 4 (non-unicode)");
            Args.Add(InputArgType.Flag, "quiet", false, Presence.Optional, "don't show diff on console");
            Args.Add(InputArgType.Flag, "xml", false, Presence.Optional, "use .XML format");
            Args.Add(InputArgType.Flag, "nocase", false, Presence.Optional, "ignore case (default: case-sensitive)");
            Args.Add(InputArgType.Flag, "write", false, Presence.Optional, "write keys/values to registry");
            Args.Add(InputArgType.Flag, "allaccess", false, Presence.Optional, "grant all access to everyone (when using the /write option)");
            Args.Add(InputArgType.Parameter, "params", null, Presence.Optional, "read value params from file (when using the /write option)");
            Args.Add(InputArgType.MultipleParameters, "alias", null, Presence.Optional, "alias FOO=BAR");
            Args.Add(InputArgType.Flag, "no-empty-keys", false, Presence.Optional, "don't create empty keys");

            if (Wow.Is64BitProcess)
            {
                Args.Add(InputArgType.Flag, "32", false, Presence.Optional, "use 32-bit registry (default for this process: 64-bit)");
            }
            else if (Wow.Is64BitOperatingSystem)
            {
                Args.Add(InputArgType.Flag, "64", false, Presence.Optional, "use 64-bit registry (default for this process: 32-bit)");
            }
            else
            {
                // There is only the 32-bit registry: no need to add this
            }

            if (!Args.Process(args))
                return 10;

            List<string> aliases = Args.GetStringList("alias");
            if (aliases != null)
            {
                foreach(string alias in aliases)
                {
                    string[] tokens = alias.Split('=');
                    if (tokens.Length == 2)
                    {
                        Aliases[tokens[0].ToLower()] = tokens[1];
                        Aliases[tokens[1].ToLower()] = tokens[0];
                    }
                    else
                    {
                        Console.WriteLine("ERROR, the /alias option must be of the form FOO=BAR");
                        return 10;
                    }
                }
            }

            Filenames = Args.GetStringList("FILE {FILE}");
            FileFormat4 = Args.GetFlag("4");
            Quiet = Args.GetFlag("quiet");
            NoEmptyKeys = Args.GetFlag("no-empty-keys");
            FileFormatXML = Args.GetFlag("xml");
            DiffFile = Args.GetString("diff");
            MergeFile = Args.GetString("merge");
            CompareAgainstRegistry = Args.GetFlag("registry");
            WriteToTheRegistry = Args.GetFlag("write");
            AllAccess = Args.GetFlag("allaccess");
            ParamsFilename = Args.GetString("params");
            if (WriteToTheRegistry)
            {
                Options = RegFileImportOptions.AllowSemicolonComments | RegFileImportOptions.AllowHashtagComments | RegFileImportOptions.AllowVariableNamesForNonStringVariables | RegFileImportOptions.IgnoreWhitespaces;
            }

            if (Wow.Is64BitProcess)
            {
                if (Args.GetFlag("32"))
                {
                    CurrentRegistryView = RegistryView.Registry32;
                }
            }
            else if (Wow.Is64BitOperatingSystem)
            {
                if (Args.GetFlag("64"))
                {
                    CurrentRegistryView = RegistryView.Registry64;
                }
            }

            if (CompareAgainstRegistry && (Filenames.Count > 1))
            {
                Console.WriteLine("ERROR, the /registry option supports only a single file");
                return 10;
            }
            if (!ReadInputFiles())
                return 10;

            if (Files.Count == 0)
            {
                Console.WriteLine("You must specify at least one file...");
                return 10;
            }

            if (Files.Count == 1)
            {
                return HandleSingleFile();
            }
            else
            {
                return HandleMultipleFiles();
            }
        }
 /// <summary>
 /// Create an importer from given .REG file format 5 file content
 /// </summary>
 /// <param name="content">Content of a .REG file</param>
 /// <param name="options">Import options</param>
 public RegFileFormat5Importer(string content, RegFileImportOptions options)
     : base(content, HEADER, options)
 {
 }