Exemple #1
0
        private static bool Solve2009Version(LoaderOptions options, ref CryptoInfo cryptoInfo)
        {
            Log.Trace("Trying to solve outdated version.");
            var destDirName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Character Builder");

            if (Directory.Exists(destDirName))
            {
                options.CBPath = destDirName;
                cryptoInfo     = new CryptoInfo(options);
                Log.Trace($"Using pre-patched {destDirName}");
                return(true);
            }

            var defaultPath = @"C:\Program Files\Wizards of the Coast\Character Builder".Replace('\\', Path.DirectorySeparatorChar);

            Log.Trace($"  - Looking in {defaultPath}");
            if (Directory.Exists(defaultPath))
            {
                Log.Trace($"  - Applying patch");
                var path = Patch(options.CBPath, defaultPath);
                if (!string.IsNullOrEmpty(path))
                {
                    Log.Trace($"  - Patch works. Moving to {destDirName}");
                    Utils.CopyAll(path, destDirName);
                    new DirectoryInfo(path).Delete(true);
                    options.CBPath = destDirName;
                    cryptoInfo     = new CryptoInfo(options);
                    Log.Trace($"Patch successful");
                    var baseconfigpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.cbconfig");
                    if (File.Exists(baseconfigpath)) // Point the config file at this for future launches
                    {
                        var doc = System.Xml.Linq.XDocument.Load(baseconfigpath);
                        doc.Root.Add(new System.Xml.Linq.XElement("CharacterBuilderPath", options.CBPath));
                        doc.Save(baseconfigpath);
                    }
                    Log.Warn("CBLoader has manually reapplied a failed April2010 patch install.");
                    return(true);
                }
            }

            return(false);
        }
        public static Thread StartProcess(LoaderOptions options, string[] args, string redirectPath, string changelog)
        {
            Log.Info("Preparing to start CharacterBuilder.exe");
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            redirectPath = Path.GetFullPath(redirectPath);

            Log.Debug(" - Creating application domain.");
            var setup = new AppDomainSetup
            {
                ApplicationBase         = AppDomain.CurrentDomain.BaseDirectory,
                ApplicationName         = "D&D 4E Character Builder",
                DisallowCodeDownload    = true,
                DisallowPublisherPolicy = true
            };

            // For some reason, unless we set PrivateBinPathProbe, D20RulesEngine.dll bypasses ResolveAssembly
            setup.PrivateBinPath      = setup.ApplicationBase;
            setup.PrivateBinPathProbe = "true";
            var appDomain = AppDomain.CreateDomain("D&D 4E Character Builder", null, setup, FULL_TRUST);

            Log.Debug(" - Creating remote callback.");
            var callbackObj = appDomain.CreateInstance("CBLoader", typeof(TargetDomainCallback).FullName);
            var callback    = (TargetDomainCallback)callbackObj.Unwrap();

            // Seal the AppDomain by setting the private path to an invalid path.
            // For some reason, we must *also* do this to stop D20RulesEngine.dll from bypassing.
#pragma warning disable CS0618
            appDomain.ClearPrivatePath();
            appDomain.AppendPrivatePath("<|>");
#pragma warning restore CS0618

            callback.Init(options.CBPath, Log.RemoteReceiver, Path.GetFullPath(redirectPath), Path.GetFullPath(changelog));

            Log.Debug(" - Patching CharacterBuilder.exe");
            PatchApplication(callback, options.CBPath, changelog);

            Log.Debug(" - Patching ApplicationUpdate.Client.dll");
            PatchApplicationUpdate(callback, options.CBPath);

            Log.Debug(" - Setting up environment.");
            Environment.CurrentDirectory = options.CBPath;

            stopwatch.Stop();
            Log.Debug($"Finished in {stopwatch.ElapsedMilliseconds} ms");
            Log.Debug();

            Log.Info("Launching CharacterBuilder.exe");
            var thread = new Thread(() => {
                var hideLog = !Log.VerboseMode;
                if (hideLog)
                {
                    ConsoleWindow.SetConsoleShown(false);
                }
                appDomain.ExecuteAssemblyByName("CharacterBuilder", null, args);
                Log.Debug("CharacterBuilder.exe terminated.");
                if (hideLog && Log.ErrorLogged)
                {
                    ConsoleWindow.SetConsoleShown(true);
                }
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            return(thread);
        }
Exemple #3
0
        private static LoaderOptions ProcessOptions(string[] args)
        {
            var options = new LoaderOptions();

            var showHelp = false;
            var noConfig = false;

            string configFile = null;
            string keyFile    = null;
            string cbPath     = null;
            string cachePath  = null;

            bool?writeKeyFile           = null;
            bool?verboseMode            = null;
            bool?forceUpdate            = null;
            bool?forceRemerge           = null;
            bool?launchBuilder          = null;
            bool?checkForUpdates        = null;
            bool?updateFirst            = null;
            bool?setFileAssociations    = null;
            bool?dumpTemporaryFiles     = null;
            bool?createUpdateIndexFiles = null;

            var opts = new OptionSet()
            {
                "Usage: CBLoader [-c <config file>]",
                "A homebrew rules loader for the D&D Insider Character Builder",
                "",
                { "h|?|help", "Shows this help message.",
                  value => showHelp = true },
                { "v|verbose", "Enables additional debugging output.",
                  value => verboseMode = true },
                { "c|config=", "A config file to use rather than the default.",
                  value => SetUniqueString(ref configFile, "-c", value) },
                { "no-config", "Do not use a configuration file.",
                  value => noConfig = true },
                { "a|set-assocations", "Associate .dnd4e and .cbconfig with CBLoader.",
                  value => setFileAssociations = false },
                "",
                "Path management:",
                { "u|cache-path=", "Sets where to write temporary files.",
                  value => SetUniqueString(ref cachePath, "-u", value) },
                { "cb-path=", "Sets where character builder is installed.",
                  value => SetUniqueString(ref cbPath, "--cb-path", value) },
                { "f|folder=", "Adds a directory to search for custom rules in.",
                  value => options.AddPath(value) },
                { "ignore-part=", "Adds a part file to ignore.",
                  value => options.IgnoreParts.Add(value) },
                "",
                "Keyfile options:",
                { "k|key-file=", "Uses the given keyfile.",
                  value => SetUniqueString(ref keyFile, "-k", value) },
                { "r=", "Updates a keyfile at the given path. Implies -k.",
                  value => {
                      SetUniqueString(ref keyFile, "-r", value);
                      writeKeyFile = true;
                  } },
                "",
                "Execution options:",
                { "update-first", "Update before merging, rather than after.",
                  value => updateFirst = true },
                { "force-update", "Redownload parts files.",
                  value => forceUpdate = true },
                { "e|force-remerge", "Always regenerate merged rules file.",
                  value => forceRemerge = true },
                { "d|no-update", "Do not check for updates.",
                  value => checkForUpdates = false },
                "",
                "Development options:",
                { "n|no-run", "Do not actually launch the character builder.",
                  value => launchBuilder = false },
                { "dump-temporary", "Dumps raw rules data to disk.",
                  value => dumpTemporaryFiles = true },
                { "create-update-indexes", "Create update version indexes.",
                  value => createUpdateIndexFiles = true },
            };

            var execArgs = opts.Parse(args);

            if (showHelp)
            {
                opts.WriteOptionDescriptions(Console.Out);
                return(null);
            }

            // Load a configation file.
            if (!noConfig)
            {
                if (configFile == null)
                {
                    options.AddOptionFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.cbconfig"));
                }
                else
                {
                    options.AddOptionFile(configFile);
                }
            }

            // Copy configuration options from console.
            if (keyFile != null)
            {
                options.KeyFile = keyFile;
            }
            if (cbPath != null)
            {
                options.CBPath = cbPath;
            }
            if (cachePath != null)
            {
                options.CachePath = cachePath;
            }

            if (writeKeyFile != null)
            {
                options.WriteKeyFile = (bool)writeKeyFile;
            }
            if (verboseMode != null)
            {
                options.VerboseMode = (bool)verboseMode;
            }
            if (forceUpdate != null)
            {
                options.ForceUpdate = (bool)forceUpdate;
            }
            if (forceRemerge != null)
            {
                options.ForceRemerge = (bool)forceRemerge;
            }
            if (launchBuilder != null)
            {
                options.LaunchBuilder = (bool)launchBuilder;
            }
            if (checkForUpdates != null)
            {
                options.CheckForUpdates = (bool)checkForUpdates;
            }
            if (updateFirst != null)
            {
                options.UpdateFirst = (bool)updateFirst;
            }
            if (setFileAssociations != null)
            {
                options.SetFileAssociations = (bool)setFileAssociations;
            }
            if (dumpTemporaryFiles != null)
            {
                options.DumpTemporaryFiles = (bool)dumpTemporaryFiles;
            }
            if (createUpdateIndexFiles != null)
            {
                options.CreateUpdateIndexFiles = (bool)createUpdateIndexFiles;
            }

            if (options.CBPath == null && (options.CBPath = Utils.GetInstallPath()) == null)
            {
                throw new CBLoaderException(
                          "CBLoader could not find an installation of Character Builder.\n" +
                          "Please specify its path with <CBPath>path/to/builder</CBPath> in the configuration " +
                          "or reinstall Character Builder.");
            }

            // Default cache Path
            if (options.CachePath == null)
            {
                options.CachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Cache");
            }

            // Default keyfile location.
            if (options.KeyFile == null)
            {
                options.KeyFile = Path.Combine(options.CachePath, "cbloader.keyfile");
            }

            // Default part directory.
            if (options.MergeDirectories.Count == 0 && options.UpdateDirectories.Count == 0)
            {
                options.AddPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Custom"));
            }
            options.AddPath(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ddi"), "CBLoader"));

            // Update first anyway if LaunchBuilder isn't set -- we don't need this optimization.
            if (!options.LaunchBuilder)
            {
                options.UpdateFirst = true;
            }

            // Check configuration option consistancy.
            options.FinalOptionsCheck();
            return(options);
        }