Example #1
0
        static void Main(string[] args)
        {
            Settings.Load();
            Settings.Save();
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);

            logger.WriteLine("Made by FailedShack");
            SetConsoleVisibility(false);
            Application.EnableVisualStyles();

            if (Settings.ShowUpdateNag)
            {
                Task.Run(async() =>
                {
                    JObject release;
                    try
                    {
                        release = await GithubUtil.GetRelease("FailedShack", "USBHelperLauncher", "latest");
                    }
                    catch
                    {
                        return;
                    }
                    string newVersion = (string)release["tag_name"];
                    string version    = GetVersion();
                    if (newVersion.CompareTo(version) > 0)
                    {
                        var updateNag       = new CheckboxDialog("New version found: " + newVersion + "\nCurrent version: " + version + "\nDo you want to open the download site?", "Do not show this again.", "Update Checker", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        DialogResult result = updateNag.ShowDialog();
                        if (result == DialogResult.Yes)
                        {
                            Process.Start((string)release["html_url"]);
                        }
                        Settings.ShowUpdateNag = !updateNag.Checked;
                        Settings.Save();
                    }
                });
            }

            string hostsFile = GetHostsFile();

            if (File.Exists(hostsFile))
            {
                try
                {
                    Hosts = Hosts.Load(hostsFile);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Could not load hosts file: " + e.Message, "Malformed hosts file", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                Hosts = new Hosts();
                if (Settings.ShowHostsWarning)
                {
                    var hostsWarning = new CheckboxDialog(
                        "It appears you don't currently have a hosts redirector file. This file may be required to route obsolete hostnames to their correct destination.\n" +
                        "If you intended to use this feature, make sure a file named 'hosts.json' is located in the same directory as this executable.\n" +
                        "You may also use the built-in editor located in the Advanced section in the tray icon's context menu.", "Do not show this again.", "Hosts file missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    hostsWarning.ShowDialog();
                    Settings.ShowHostsWarning = !hostsWarning.Checked;
                    Settings.Save();
                }
            }

            try
            {
                database.LoadFromDir(Path.Combine(GetLauncherPath(), "data"));
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show(e.Message + "\nMake sure this file is under the data directory.", "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            if (!File.Exists("ver") || !File.Exists("WiiU_USB_Helper.exe"))
            {
                MessageBox.Show("Could not find Wii U USB Helper, please make sure this executable is in the correct folder.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }
            helperVersion = File.ReadAllLines("ver")[0];
            int revision = Int32.Parse(helperVersion.Substring(helperVersion.LastIndexOf('.') + 1));

            if (helperVersion.StartsWith("0.6.1"))
            {
                // Workaround to allow it to launch
                if (revision >= 653)
                {
                    string installPath = GetInstallPath();
                    string lastTitles  = Path.Combine(installPath, "lasttitles");
                    if (revision > 653)
                    {
                        string installConfPath = GetInstallConfPath();
                        Directory.CreateDirectory(installConfPath);
                        File.Create(Path.Combine(installConfPath, "user.config")).Close();
                    }
                    if (!File.Exists(lastTitles))
                    {
                        Directory.CreateDirectory(installPath);
                        StringBuilder sb = new StringBuilder();
                        // Rev. 653 minimums: 3 lines, single character each
                        // Revs. 654 & 655 minimums: 25 lines, 16 chars each
                        for (int lines = 0; lines != 25; lines++)
                        {
                            sb.Append('0', 16).AppendLine();
                        }
                        File.WriteAllText(lastTitles, sb.ToString());
                    }
                }
            }
            if (!CertMaker.rootCertExists() && !CertMaker.createRootCert())
            {
                MessageBox.Show("Creation of the interception certificate failed.", "Unable to generate certificate.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            string executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper.exe");

            var running = Process.GetProcessesByName("Patched").FirstOrDefault(p => p.GetMainModuleFileName().StartsWith(GetLauncherPath(), StringComparison.OrdinalIgnoreCase));

            if (running != default(Process))
            {
                DialogResult result = MessageBox.Show("An instance of Wii U USB Helper is already running.\nWould you like to close it?", "Already running", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (result == DialogResult.No)
                {
                    Environment.Exit(0);
                }
                running.Kill();
            }

            proxy.Start();

            // Patching
            for (int i = 0; i < args.Length; i++)
            {
                var group = Regex.Match(args[i], "[-]{1,2}(.*)").Groups[1];
                if (group.Success)
                {
                    switch (group.Value)
                    {
                    case "nopatch":
                        patch = false;
                        logger.WriteLine("Patching has been disabled.");
                        break;

                    case "verbose":
                        Verbose = true;
                        logger.WriteLine("Verbose logging enabled.");
                        break;
                    }
                }
            }

            ProgressDialog dialog = new ProgressDialog();

            dialog.SetStyle(ProgressBarStyle.Marquee);
            dialog.GetProgressBar().MarqueeAnimationSpeed = 30;
            dialog.SetHeader("Injecting...");
            new Thread(() => {
                dialog.ShowDialog();
            }).Start();
            var injector = new ModuleInitInjector(executable);

            executable = Path.Combine(GetLauncherPath(), "Patched.exe");
            injector.Inject(executable);
            logger.WriteLine("Injected module initializer.");
            if (patch)
            {
                dialog.Invoke(new Action(() => dialog.SetHeader("Patching...")));
                RSAPatcher patcher           = new RSAPatcher(executable);
                RSACryptoServiceProvider rsa = GetRSA();
                string xml = rsa.ToXmlString(false);
                rsa.Dispose();
                var builder  = new StringBuilder();
                var element  = XElement.Parse(xml);
                var settings = new XmlWriterSettings
                {
                    OmitXmlDeclaration = true,
                    Indent             = true
                };
                using (var xmlWriter = XmlWriter.Create(builder, settings))
                {
                    element.Save(xmlWriter);
                }
                patcher.SetPublicKey(builder.ToString());
                logger.WriteLine("Patched public key.");
            }
            dialog.Invoke(new Action(() => dialog.Close()));

            // Time to launch Wii U USB Helper
            sessionStart = DateTime.UtcNow;
            process      = StartProcess(executable, helperVersion);

            if (Settings.DisableOptionalPatches)
            {
                logger.WriteLine("Optional patches have been disabled.");
            }

            new Thread(() =>
            {
                logger.WriteLine("Sending information to injector...");
                var client  = new PipeClient();
                var packets = new List <ActionPacket>();
                if (patch)
                {
                    packets.Add(new DonationKeyPacket()
                    {
                        DonationKey = GenerateDonationKey()
                    });
                }
                packets.AddRange(new List <ActionPacket>()
                {
                    new CertificateAuthorityPacket()
                    {
                        CaCert = CertMaker.GetRootCertificate()
                    },
                    new ProxyPacket()
                    {
                        Proxy = proxy.GetWebProxy()
                    },
                    new DownloaderSettingsPacket()
                    {
                        MaxRetries          = Settings.MaxRetries,
                        DelayBetweenRetries = Settings.DelayBetweenRetries
                    },
                    new OptionalPatchesPacket()
                    {
                        DisableOptionalPatches = Settings.DisableOptionalPatches
                    },
                    new TerminationPacket()
                });
                foreach (ActionPacket packet in packets)
                {
                    if (!client.SendPacket(packet))
                    {
                        logger.WriteLine(string.Format("Could not send IPC packet of type {0}", packet.GetType().Name));
                    }
                }
            }).Start();

            ContextMenu trayMenu   = new ContextMenu();
            MenuItem    dlEmulator = new MenuItem("Download Emulator");

            foreach (EmulatorConfiguration.Emulator emulator in Enum.GetValues(typeof(EmulatorConfiguration.Emulator)))
            {
                EmulatorConfiguration config = EmulatorConfiguration.GetConfiguration(emulator);
                dlEmulator.MenuItems.Add(config.GetName(), (sender, e) => OnDownloadEmulator(config));
            }
            MenuItem advanced = new MenuItem("Advanced");

            advanced.MenuItems.Add("Toggle Console", OnVisibilityChange);
            advanced.MenuItems.Add("Clear Install", OnClearInstall);
            advanced.MenuItems.Add("Generate Donation Key", OnGenerateKey).Enabled = patch;
            advanced.MenuItems.Add("Hosts Editor", OnOpenHostsEditor);
            trayMenu.MenuItems.Add("Exit", OnExit);
            trayMenu.MenuItems.Add("Check for Updates", OnUpdateCheck);
            trayMenu.MenuItems.Add("Report Issue", OnDebugMessage);
            trayMenu.MenuItems.Add(dlEmulator);
            trayMenu.MenuItems.Add(advanced);
            trayIcon.Text        = "Wii U USB Helper Launcher";
            trayIcon.Icon        = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
            trayIcon.ContextMenu = trayMenu;
            trayIcon.Visible     = true;
            backgroundThread     = new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (!process.HasExited)
                {
                    try
                    {
                        Thread.Sleep(30);
                    }
                    catch (ThreadInterruptedException) { }
                }
                Cleanup();
                Application.Exit();
            });
            backgroundThread.Start();
            Application.Run();
        }
Example #2
0
        static void Main(string[] args)
        {
            Settings.Load();
            Settings.Save();
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);

            for (int i = 0; i < args.Length; i++)
            {
                var group = Regex.Match(args[i], "[-]{1,2}(.*)").Groups[1];
                if (group.Success)
                {
                    switch (group.Value)
                    {
                    case "nokey":
                        OverridePublicKey = false;
                        break;

                    case "showconsole":
                        showConsole = true;
                        break;
                    }
                }
            }

            Logger.WriteLine("Made by FailedShack");
            SetConsoleVisibility(showConsole);
            Application.EnableVisualStyles();

            if (Settings.ShowUpdateNag)
            {
                Task.Run(async() =>
                {
                    JObject release;
                    try
                    {
                        release = await GithubUtil.GetRelease("FailedShack", "USBHelperLauncher", "latest");
                    }
                    catch
                    {
                        return;
                    }
                    string newVersion = (string)release["tag_name"];
                    string version    = GetVersion();
                    if (newVersion.CompareTo(version) > 0)
                    {
                        var updateNag       = new CheckboxDialog("New version found: " + newVersion + "\nCurrent version: " + version + "\nDo you want to open the download site?", "Do not show this again.", "Update Checker", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        DialogResult result = updateNag.ShowDialog();
                        if (result == DialogResult.Yes)
                        {
                            Process.Start((string)release["html_url"]);
                        }
                        Settings.ShowUpdateNag = !updateNag.Checked;
                        Settings.Save();
                    }
                }).Wait();
            }

            if (Settings.ShowTranslateNag && Locale.ChosenLocale != LocaleProvider.DefaultLocale)
            {
                var localeInfo   = Locale.KnownLocales[Locale.ChosenLocale];
                var translateNag = MessageBox.Show(
                    string.Format("We are currently looking for volunteers to translate Wii U USB Helper to other languages. " +
                                  "You may be able to contribute by submitting translations for {0} on Crowdin.\nWould you like to open the site?", localeInfo.Name),
                    "Appeal to Translate", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                if (translateNag == DialogResult.Yes)
                {
                    Process.Start("https://crowdin.com/project/wii-u-usb-helper");
                }
                Settings.ShowTranslateNag = false;
                Settings.Save();
            }

            var certs = new DirectoryInfo("certs");

            if (certs.Exists)
            {
                foreach (var file in certs.EnumerateFiles().Where(x => x.Length > 0))
                {
                    try
                    {
                        Proxy.CertificateStore.Import(file.FullName);
                    }
                    catch (CryptographicException)
                    {
                        MessageBox.Show(string.Format("{0} is not a valid certificate file.", file.Name, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error));
                        Environment.Exit(-1);
                    }
                }
            }

            string hostsFile = GetHostsFile();

            if (File.Exists(hostsFile))
            {
                try
                {
                    Hosts = Hosts.Load(hostsFile);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Could not load hosts file: " + e.Message, "Malformed hosts file", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Hosts = new Hosts();
                }

                var conflicting = Proxy.GetConflictingHosts();
                if (!Settings.HostsExpert && conflicting.Count > 0)
                {
                    var hostsConflictWarning = new CheckboxDialog(
                        "The following hostnames specified in the hosts file are normally handled by USBHelperLauncher:\n\n" + string.Join("\n", conflicting) +
                        "\n\nIf you override them the program may not function properly." +
                        "\nDo you want to exclude them?", "Do not show this again.", "Conflicting hosts", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    DialogResult result = hostsConflictWarning.ShowDialog();
                    if (result == DialogResult.Yes)
                    {
                        Hosts.hosts = Hosts.hosts.Where(x => !conflicting.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value);
                    }
                    Settings.HostsExpert = hostsConflictWarning.Checked;
                    Settings.Save();
                }
            }
            else
            {
                Hosts = new Hosts();
                if (Settings.ShowHostsWarning)
                {
                    var hostsWarning = new CheckboxDialog(
                        "It appears you don't currently have a hosts redirector file. This file may be required to route obsolete hostnames to their correct destination.\n" +
                        "If you intended to use this feature, make sure a file named 'hosts.json' is located in the same directory as this executable.\n" +
                        "You may also use the built-in editor located in the Advanced section in the tray icon's context menu.", "Do not show this again.", "Hosts file missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    hostsWarning.ShowDialog();
                    Settings.ShowHostsWarning = !hostsWarning.Checked;
                    Settings.Save();
                }
            }

            try
            {
                Database.LoadFromDir(Path.Combine(GetLauncherPath(), "data"));
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show(e.Message + "\nMake sure this file is under the data directory.", "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(-1);
            }

            if (!File.Exists("ver") || !File.Exists("WiiU_USB_Helper.exe"))
            {
                MessageBox.Show("Could not find Wii U USB Helper, please make sure this executable is in the correct folder.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(-1);
            }
            HelperVersion = File.ReadAllLines("ver")[0];

            // Ensure that the cached title key JSON files are valid
            string[] toCheck = { "3FFFD23A80F800ABFCC436A5EC8F7F0B94C728A4", "9C6DD14B8E3530B701BC4F1B77345DADB0C32020" };
            foreach (string file in toCheck)
            {
                string path = Path.Combine(GetInstallPath(), file);
                if (File.Exists(path))
                {
                    try
                    {
                        JToken.Parse(File.ReadAllText(path));
                    }
                    catch (JsonReaderException)
                    {
                        File.Delete(path);
                        Logger.WriteLine(string.Format("Removed bad cache file: {0}", file));
                    }
                }
            }

            // Make sure that FiddlerCore's key container can be accessed
            string keyContainer = FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.KeyContainerName", "FiddlerBCKey");

            if (WinUtil.CSP.TryAcquire(keyContainer) == WinUtil.CSP.NTE_BAD_KEY_STATE)
            {
                WinUtil.CSP.Delete(keyContainer);
                Logger.WriteLine("Removed broken key container: {0}", keyContainer);
            }

            CertMaker.oCertProvider = new BCCertMaker.BCCertMaker(); // Don't try to load CertMaker.dll
            if (!Settings.ForceHttp && !CertMaker.rootCertExists() && !CertMaker.createRootCert())
            {
                MessageBox.Show("Creation of the interception certificate failed.", "Unable to generate certificate.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(-1);
            }

            string executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper.exe");

            var running = Process.GetProcessesByName("Patched").FirstOrDefault(p => p.GetMainModuleFileName().StartsWith(GetLauncherPath(), StringComparison.OrdinalIgnoreCase));

            if (running != default(Process))
            {
                DialogResult result = MessageBox.Show("An instance of Wii U USB Helper is already running.\nWould you like to close it?", "Already running", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (result == DialogResult.No)
                {
                    Environment.Exit(0);
                }
                running.Kill();
            }

            Proxy.Start();

            // Update translations
            var dialog = new ProgressDialog();
            var worker = dialog.GetWorker();

            dialog.SetHeader("Updating translations...");
            new Thread(() => dialog.ShowDialog()).Start();
            Task.Run(async() =>
            {
                try
                {
                    if (await Locale.UpdateIfNeeded(dialog))
                    {
                        Logger.WriteLine("Updated translations: {0}", Settings.TranslationsBuild);
                    }
                    else
                    {
                        Logger.WriteLine("Translations were up to date.");
                    }
                }
                catch (Exception e)
                {
                    Logger.WriteLine("Could not update translations: {0}", e.Message);
                }
            }).Wait();

            ServiceHost host = new ServiceHost(typeof(LauncherService), new Uri("net.pipe://localhost/LauncherService"));

            host.AddServiceEndpoint(typeof(ILauncherService), new NetNamedPipeBinding(), "");
            host.Open();

            // Patching
            dialog.Invoke(new Action(() =>
            {
                dialog.SetStyle(ProgressBarStyle.Marquee);
                dialog.GetProgressBar().MarqueeAnimationSpeed = 30;
                dialog.SetHeader("Injecting...");
            }));
            var injector = new ModuleInitInjector(executable);

            executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper_.exe");
            injector.Inject(executable);
            Logger.WriteLine("Injected module initializer.");
            dialog.Invoke(new Action(() => dialog.Close()));

            if (OverridePublicKey)
            {
                // Generate an RSA key pair for our donation keys
                using (var rsa = new RSACryptoServiceProvider(2048))
                {
                    rsaParams = rsa.ExportParameters(true);
                    PublicKey = rsa.ToXmlString(false);
                }
            }

            // Time to launch Wii U USB Helper
            SessionStart = DateTime.UtcNow;
            var startInfo = new ProcessStartInfo()
            {
                FileName              = executable,
                Arguments             = HelperVersion,
                UseShellExecute       = false,
                RedirectStandardError = true,
                StandardErrorEncoding = Encoding.Default
            };
            var process = new Process()
            {
                StartInfo = startInfo
            };

            process.EnableRaisingEvents = true;
            process.Exited += async(sender, e) =>
            {
                if (killed)
                {
                    return;
                }
                if (process.ExitCode != 0)
                {
                    Logger.WriteLine("Wii U USB Helper returned non-zero exit code 0x{0:x}:\n{1}", process.ExitCode, process.StandardError.ReadToEnd().Trim());;
                    var result = MessageBox.Show(string.Format("Uh-oh. Wii U USB Helper has crashed unexpectedly.\nDo you want to generate a debug log?\n\nError code: 0x{0:x}", process.ExitCode), "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                    if (result == DialogResult.Yes)
                    {
                        await GenerateDebugLog();
                    }
                }
                Cleanup();
                Application.Exit();
            };
            process.Start();
            HelperProcess = process;

            if (Settings.DisableOptionalPatches)
            {
                Logger.WriteLine("Optional patches have been disabled.");
            }

            if (Settings.ForceHttp)
            {
                Logger.WriteLine("Requests will be proxied over plain HTTP.");
            }

            ContextMenu trayMenu   = new ContextMenu();
            MenuItem    dlEmulator = new MenuItem("Download Emulator");

            foreach (EmulatorConfiguration.Emulator emulator in Enum.GetValues(typeof(EmulatorConfiguration.Emulator)))
            {
                EmulatorConfiguration config = EmulatorConfiguration.GetConfiguration(emulator);
                dlEmulator.MenuItems.Add(config.GetName(), (sender, e) => OnDownloadEmulator(config));
            }
            MenuItem language = new MenuItem("Language")
            {
                RadioCheck = true
            };

            foreach (var lang in Locale.AvailableLocales)
            {
                language.MenuItems.Add(lang.Value.Native, (sender, e) =>
                {
                    Settings.Locale = lang.Key;
                    Settings.Save();
                    MessageBox.Show("Your language choice has been saved.\nPlease restart USBHelperLauncher for changes to take effect.", "Restart required", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }).Checked = lang.Key == Locale.ChosenLocale;
            }
            if (language.MenuItems.Count == 0)
            {
                language.MenuItems.Add("No translations found").Enabled = false;
            }
            MenuItem advanced = new MenuItem("Advanced");

            advanced.MenuItems.Add("Toggle Console", OnVisibilityChange);
            advanced.MenuItems.Add("Clear Install", OnClearInstall);
            advanced.MenuItems.Add("Generate Donation Key", OnGenerateKey).Enabled = OverridePublicKey;
            advanced.MenuItems.Add("Hosts Editor", OnOpenHostsEditor);
            advanced.MenuItems.Add("Export Sessions", OnExportSessions);
            trayMenu.MenuItems.Add("Exit", OnExit);
            trayMenu.MenuItems.Add("Check for Updates", OnUpdateCheck);
            trayMenu.MenuItems.Add("Report Issue", async(sender, e) => await GenerateDebugLog());
            trayMenu.MenuItems.Add(dlEmulator);
            trayMenu.MenuItems.Add(language);
            trayMenu.MenuItems.Add(advanced);
            trayIcon = new NotifyIcon
            {
                Text        = "Wii U USB Helper Launcher",
                Icon        = Icon.ExtractAssociatedIcon(Application.ExecutablePath),
                ContextMenu = trayMenu,
                Visible     = true
            };
            Application.Run();
        }
Example #3
0
        static void Main(string[] args)
        {
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);

            logger.WriteLine("Made by FailedShack");
            SetConsoleVisibility(false);
            Application.EnableVisualStyles();

            try
            {
                database.LoadFromDir(Path.Combine(GetLauncherPath(), "data"));
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show(e.Message + "\nMake sure this file is under the data directory.", "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            if (!File.Exists("ver") || !File.Exists("WiiU_USB_Helper.exe"))
            {
                MessageBox.Show("Could not find Wii U USB Helper, please make sure this executable is in the correct folder.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }
            helperVersion = File.ReadAllLines("ver")[0];
            int revision = Int32.Parse(helperVersion.Substring(helperVersion.LastIndexOf('.') + 1));

            if (helperVersion.StartsWith("0.6.1"))
            {
                // Workaround to allow it to launch
                if (revision >= 653)
                {
                    string installPath = GetInstallPath();
                    string lastTitles  = Path.Combine(installPath, "lasttitles");
                    if (revision > 653)
                    {
                        string installConfPath = GetInstallConfPath();
                        Directory.CreateDirectory(installConfPath);
                        File.Create(Path.Combine(installConfPath, "user.config")).Close();
                    }
                    if (!File.Exists(lastTitles))
                    {
                        Directory.CreateDirectory(installPath);
                        StringBuilder sb = new StringBuilder();
                        // Rev. 653 minimums: 3 lines, single character each
                        // Revs. 654 & 655 minimums: 25 lines, 16 chars each
                        for (int lines = 0; lines != 25; lines++)
                        {
                            sb.Append('0', 16).AppendLine();
                        }
                        File.WriteAllText(lastTitles, sb.ToString());
                    }
                }
            }
            if (!CertMaker.rootCertExists() || !CertMaker.rootCertIsTrusted())
            {
                MessageBox.Show(
                    "You will now be prompted to install an SSL certificate, this is required to allow other programs to make HTTPS requests while Wii U USB Helper is open.\n" +
                    "This is part of the initial setup process.\n", "First run - Read carefully!", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
                while (true)
                {
                    if (!CertMaker.createRootCert() || !CertMaker.trustRootCert())
                    {
                        DialogResult result = MessageBox.Show("The setup process cannot continue without an SSL certificate.\nAre you sure you want to cancel?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                        if (result == DialogResult.Yes)
                        {
                            Environment.Exit(0);
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                string firefox = GetFirefoxExecutable();
                if (firefox != null)
                {
                    logger.WriteLine("Firefox: " + firefox);
                    MessageBox.Show("You will now also be prompted to install the certificate on Firefox.\nMake sure to check 'Trust this CA to identify websites'.", "First run", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    proxy.Start();
                    while (!FiddlerApplication.IsStarted())
                    {
                        Thread.Sleep(30);
                    }
                    StartProcess(firefox, "http://www.wiiuusbhelper.com/certificate");
                }
            }
            logger.WriteLine("Found trusted SSL Certificate.");

            if (!FiddlerApplication.IsStarted())
            {
                proxy.Start();
            }

            string executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper.exe");

            // Patching
            if (args.Length == 1)
            {
                var group = Regex.Match(args[0], "[-]{1,2}(.*)").Groups[1];
                if (group.Success && group.Value == "nopatch")
                {
                    patch = false;
                    logger.WriteLine("Patching has been disabled.");
                }
            }
            if (patch)
            {
                ProgressDialog dialog = new ProgressDialog();
                dialog.SetHeader("Patching...");
                dialog.SetStyle(ProgressBarStyle.Marquee);
                dialog.GetProgressBar().MarqueeAnimationSpeed = 30;
                new Thread(() => {
                    dialog.ShowDialog();
                }).Start();
                RSAPatcher patcher           = new RSAPatcher(executable);
                RSACryptoServiceProvider rsa = GetRSA();
                string xml = rsa.ToXmlString(false);
                rsa.Dispose();
                var builder  = new StringBuilder();
                var element  = XElement.Parse(xml);
                var settings = new XmlWriterSettings
                {
                    OmitXmlDeclaration = true,
                    Indent             = true
                };
                using (var xmlWriter = XmlWriter.Create(builder, settings))
                {
                    element.Save(xmlWriter);
                }
                executable = Path.Combine(GetLauncherPath(), "Patched.exe");
                patcher.SetPublicKey(builder.ToString(), executable);
                dialog.Invoke(new Action(() => dialog.Close()));
                logger.WriteLine("Patched public key.");
            }

            // Time to launch Wii U USB Helper
            sessionStart = DateTime.UtcNow;
            process      = StartProcess(executable, helperVersion);
            ContextMenu trayMenu   = new ContextMenu();
            MenuItem    dlEmulator = new MenuItem("Download Emulator");

            foreach (EmulatorConfiguration.Emulator emulator in Enum.GetValues(typeof(EmulatorConfiguration.Emulator)))
            {
                EmulatorConfiguration config = EmulatorConfiguration.GetConfiguration(emulator);
                dlEmulator.MenuItems.Add(config.GetName(), (sender, e) => OnDownloadEmulator(config));
            }
            MenuItem advanced = new MenuItem("Advanced");

            advanced.MenuItems.Add("Toggle Console", OnVisibilityChange);
            advanced.MenuItems.Add("Clear Install", OnClearInstall);
            advanced.MenuItems.Add("Remove Certificate", OnRemoveCertificate);
            trayMenu.MenuItems.Add("Exit", OnExit);
            trayMenu.MenuItems.Add("Check for Updates", OnUpdateCheck);
            trayMenu.MenuItems.Add("Report Issue", OnDebugMessage);
            trayMenu.MenuItems.Add("Generate Donation Key", OnGenerateKey).Enabled = patch;
            trayMenu.MenuItems.Add(dlEmulator);
            trayMenu.MenuItems.Add(advanced);
            trayIcon.Text        = "Wii U USB Helper Launcher";
            trayIcon.Icon        = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
            trayIcon.ContextMenu = trayMenu;
            trayIcon.Visible     = true;
            backgroundThread     = new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (!process.HasExited)
                {
                    try
                    {
                        Thread.Sleep(30);
                    }
                    catch (ThreadInterruptedException) { }
                }
                Cleanup();
                Application.Exit();
            });
            backgroundThread.Start();
            Application.Run();
        }
Example #4
0
        static void Main(string[] args)
        {
            Settings.Load();
            Settings.Save();
            proxy     = new Net.Proxy(8877);
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);

            for (int i = 0; i < args.Length; i++)
            {
                var group = Regex.Match(args[i], "[-]{1,2}(.*)").Groups[1];
                if (group.Success)
                {
                    switch (group.Value)
                    {
                    case "nokey":
                        OverridePublicKey = false;
                        break;

                    case "showconsole":
                        showConsole = true;
                        break;
                    }
                }
            }

            logger.WriteLine("Made by FailedShack");
            SetConsoleVisibility(showConsole);
            Application.EnableVisualStyles();

            if (Settings.ShowUpdateNag)
            {
                Task.Run(async() =>
                {
                    JObject release;
                    try
                    {
                        release = await GithubUtil.GetRelease("FailedShack", "USBHelperLauncher", "latest");
                    }
                    catch
                    {
                        return;
                    }
                    string newVersion = (string)release["tag_name"];
                    string version    = GetVersion();
                    if (newVersion.CompareTo(version) > 0)
                    {
                        var updateNag       = new CheckboxDialog("New version found: " + newVersion + "\nCurrent version: " + version + "\nDo you want to open the download site?", "Do not show this again.", "Update Checker", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        DialogResult result = updateNag.ShowDialog();
                        if (result == DialogResult.Yes)
                        {
                            Process.Start((string)release["html_url"]);
                        }
                        Settings.ShowUpdateNag = !updateNag.Checked;
                        Settings.Save();
                    }
                });
            }

            string hostsFile = GetHostsFile();

            if (File.Exists(hostsFile))
            {
                try
                {
                    Hosts = Hosts.Load(hostsFile);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Could not load hosts file: " + e.Message, "Malformed hosts file", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Hosts = new Hosts();
                }

                var conflicting = proxy.GetConflictingHosts();
                if (!Settings.HostsExpert && conflicting.Count > 0)
                {
                    var hostsConflictWarning = new CheckboxDialog(
                        "The following hostnames specified in the hosts file are normally handled by USBHelperLauncher:\n\n" + string.Join("\n", conflicting) +
                        "\n\nIf you override them the program may not function properly." +
                        "\nDo you want to exclude them?", "Do not show this again.", "Conflicting hosts", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    DialogResult result = hostsConflictWarning.ShowDialog();
                    if (result == DialogResult.Yes)
                    {
                        Hosts.hosts = Hosts.hosts.Where(x => !conflicting.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value);
                    }
                    Settings.HostsExpert = hostsConflictWarning.Checked;
                    Settings.Save();
                }
            }
            else
            {
                Hosts = new Hosts();
                if (Settings.ShowHostsWarning)
                {
                    var hostsWarning = new CheckboxDialog(
                        "It appears you don't currently have a hosts redirector file. This file may be required to route obsolete hostnames to their correct destination.\n" +
                        "If you intended to use this feature, make sure a file named 'hosts.json' is located in the same directory as this executable.\n" +
                        "You may also use the built-in editor located in the Advanced section in the tray icon's context menu.", "Do not show this again.", "Hosts file missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    hostsWarning.ShowDialog();
                    Settings.ShowHostsWarning = !hostsWarning.Checked;
                    Settings.Save();
                }
            }

            try
            {
                database.LoadFromDir(Path.Combine(GetLauncherPath(), "data"));
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show(e.Message + "\nMake sure this file is under the data directory.", "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            if (!File.Exists("ver") || !File.Exists("WiiU_USB_Helper.exe"))
            {
                MessageBox.Show("Could not find Wii U USB Helper, please make sure this executable is in the correct folder.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }
            helperVersion = File.ReadAllLines("ver")[0];

            // Ensure that the cached title key JSON files are valid
            string[] toCheck = { "3FFFD23A80F800ABFCC436A5EC8F7F0B94C728A4", "9C6DD14B8E3530B701BC4F1B77345DADB0C32020" };
            foreach (string file in toCheck)
            {
                string path = Path.Combine(GetInstallPath(), file);
                if (File.Exists(path))
                {
                    try
                    {
                        JToken.Parse(File.ReadAllText(path));
                    }
                    catch (JsonReaderException)
                    {
                        File.Delete(path);
                        logger.WriteLine(string.Format("Removed bad cache file: {0}", file));
                    }
                }
            }

            // Make sure that FiddlerCore's key container can be accessed
            string keyContainer = FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.KeyContainerName", "FiddlerBCKey");

            if (WinUtil.CSP.TryAcquire(keyContainer) == WinUtil.CSP.NTE_BAD_KEY_STATE)
            {
                WinUtil.CSP.Delete(keyContainer);
                logger.WriteLine("Removed broken key container: {0}", keyContainer);
            }

            if (!CertMaker.rootCertExists() && !CertMaker.createRootCert())
            {
                MessageBox.Show("Creation of the interception certificate failed.", "Unable to generate certificate.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            string executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper.exe");

            var running = Process.GetProcessesByName("Patched").FirstOrDefault(p => p.GetMainModuleFileName().StartsWith(GetLauncherPath(), StringComparison.OrdinalIgnoreCase));

            if (running != default(Process))
            {
                DialogResult result = MessageBox.Show("An instance of Wii U USB Helper is already running.\nWould you like to close it?", "Already running", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (result == DialogResult.No)
                {
                    Environment.Exit(0);
                }
                running.Kill();
            }

            proxy.Start();
            ServiceHost host = new ServiceHost(typeof(LauncherService), new Uri("net.pipe://localhost/LauncherService"));

            host.AddServiceEndpoint(typeof(ILauncherService), new NetNamedPipeBinding(), "");
            host.Open();

            // Patching
            ProgressDialog dialog = new ProgressDialog();

            dialog.SetStyle(ProgressBarStyle.Marquee);
            dialog.GetProgressBar().MarqueeAnimationSpeed = 30;
            dialog.SetHeader("Injecting...");
            new Thread(() => {
                dialog.ShowDialog();
            }).Start();
            var injector = new ModuleInitInjector(executable);

            executable = Path.Combine(GetLauncherPath(), "Patched.exe");
            injector.Inject(executable);
            logger.WriteLine("Injected module initializer.");
            dialog.Invoke(new Action(() => dialog.Close()));

            if (OverridePublicKey)
            {
                // Generate an RSA key pair for our donation keys
                using (var rsa = new RSACryptoServiceProvider(2048))
                {
                    rsaParams = rsa.ExportParameters(true);
                    PublicKey = rsa.ToXmlString(false);
                }
            }

            // Time to launch Wii U USB Helper
            sessionStart = DateTime.UtcNow;
            process      = StartProcess(executable, helperVersion);

            if (Settings.DisableOptionalPatches)
            {
                logger.WriteLine("Optional patches have been disabled.");
            }

            ContextMenu trayMenu   = new ContextMenu();
            MenuItem    dlEmulator = new MenuItem("Download Emulator");

            foreach (EmulatorConfiguration.Emulator emulator in Enum.GetValues(typeof(EmulatorConfiguration.Emulator)))
            {
                EmulatorConfiguration config = EmulatorConfiguration.GetConfiguration(emulator);
                dlEmulator.MenuItems.Add(config.GetName(), (sender, e) => OnDownloadEmulator(config));
            }
            MenuItem advanced = new MenuItem("Advanced");

            advanced.MenuItems.Add("Toggle Console", OnVisibilityChange);
            advanced.MenuItems.Add("Clear Install", OnClearInstall);
            advanced.MenuItems.Add("Generate Donation Key", OnGenerateKey).Enabled = OverridePublicKey;
            advanced.MenuItems.Add("Hosts Editor", OnOpenHostsEditor);
            advanced.MenuItems.Add("Export Sessions", OnExportSessions);
            trayMenu.MenuItems.Add("Exit", OnExit);
            trayMenu.MenuItems.Add("Check for Updates", OnUpdateCheck);
            trayMenu.MenuItems.Add("Report Issue", OnDebugMessage);
            trayMenu.MenuItems.Add(dlEmulator);
            trayMenu.MenuItems.Add(advanced);
            trayIcon = new NotifyIcon
            {
                Text        = "Wii U USB Helper Launcher",
                Icon        = Icon.ExtractAssociatedIcon(Application.ExecutablePath),
                ContextMenu = trayMenu,
                Visible     = true
            };
            backgroundThread = new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (!process.HasExited)
                {
                    try
                    {
                        Thread.Sleep(30);
                    }
                    catch (ThreadInterruptedException) { }
                }
                Cleanup();
                Application.Exit();
            });
            backgroundThread.Start();
            Application.Run();
        }
Example #5
0
        static void Main(string[] args)
        {
            Settings.Load();
            Settings.Save();
            proxy     = new Net.Proxy(8877);
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);

            for (int i = 0; i < args.Length; i++)
            {
                var group = Regex.Match(args[i], "[-]{1,2}(.*)").Groups[1];
                if (group.Success)
                {
                    switch (group.Value)
                    {
                    case "nopatch":
                        PatchPublicKey = false;
                        break;

                    case "showconsole":
                        showConsole = true;
                        break;
                    }
                }
            }

            logger.WriteLine("Made by FailedShack");
            SetConsoleVisibility(showConsole);
            Application.EnableVisualStyles();

            if (Settings.ShowUpdateNag)
            {
                Task.Run(async() =>
                {
                    JObject release;
                    try
                    {
                        release = await GithubUtil.GetRelease("FailedShack", "USBHelperLauncher", "latest");
                    }
                    catch
                    {
                        return;
                    }
                    string newVersion = (string)release["tag_name"];
                    string version    = GetVersion();
                    if (newVersion.CompareTo(version) > 0)
                    {
                        var updateNag       = new CheckboxDialog("New version found: " + newVersion + "\nCurrent version: " + version + "\nDo you want to open the download site?", "Do not show this again.", "Update Checker", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                        DialogResult result = updateNag.ShowDialog();
                        if (result == DialogResult.Yes)
                        {
                            Process.Start((string)release["html_url"]);
                        }
                        Settings.ShowUpdateNag = !updateNag.Checked;
                        Settings.Save();
                    }
                });
            }

            string hostsFile = GetHostsFile();

            if (File.Exists(hostsFile))
            {
                try
                {
                    Hosts = Hosts.Load(hostsFile);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Could not load hosts file: " + e.Message, "Malformed hosts file", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                Hosts = new Hosts();
                if (Settings.ShowHostsWarning)
                {
                    var hostsWarning = new CheckboxDialog(
                        "It appears you don't currently have a hosts redirector file. This file may be required to route obsolete hostnames to their correct destination.\n" +
                        "If you intended to use this feature, make sure a file named 'hosts.json' is located in the same directory as this executable.\n" +
                        "You may also use the built-in editor located in the Advanced section in the tray icon's context menu.", "Do not show this again.", "Hosts file missing", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    hostsWarning.ShowDialog();
                    Settings.ShowHostsWarning = !hostsWarning.Checked;
                    Settings.Save();
                }
            }

            try
            {
                database.LoadFromDir(Path.Combine(GetLauncherPath(), "data"));
            }
            catch (FileNotFoundException e)
            {
                MessageBox.Show(e.Message + "\nMake sure this file is under the data directory.", "Initialization error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            if (!File.Exists("ver") || !File.Exists("WiiU_USB_Helper.exe"))
            {
                MessageBox.Show("Could not find Wii U USB Helper, please make sure this executable is in the correct folder.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }
            helperVersion = File.ReadAllLines("ver")[0];
            int revision = int.Parse(helperVersion.Substring(helperVersion.LastIndexOf('.') + 1));

            if (helperVersion.StartsWith("0.6.1"))
            {
                // Workaround to allow it to launch
                if (revision >= 653)
                {
                    string installPath = GetInstallPath();
                    string lastTitles  = Path.Combine(installPath, "lasttitles");
                    if (revision > 653)
                    {
                        string installConfPath = GetInstallConfPath();
                        Directory.CreateDirectory(installConfPath);
                        File.Create(Path.Combine(installConfPath, "user.config")).Close();
                    }
                    if (!File.Exists(lastTitles))
                    {
                        Directory.CreateDirectory(installPath);
                        StringBuilder sb = new StringBuilder();
                        // Rev. 653 minimums: 3 lines, single character each
                        // Revs. 654 & 655 minimums: 25 lines, 16 chars each
                        for (int lines = 0; lines != 25; lines++)
                        {
                            sb.Append('0', 16).AppendLine();
                        }
                        File.WriteAllText(lastTitles, sb.ToString());
                    }
                }
            }

            // Ensure that the cached title key JSON files are valid
            string[] toCheck = { "3FFFD23A80F800ABFCC436A5EC8F7F0B94C728A4", "9C6DD14B8E3530B701BC4F1B77345DADB0C32020" };
            foreach (string file in toCheck)
            {
                string path = Path.Combine(GetInstallPath(), file);
                if (File.Exists(path))
                {
                    try
                    {
                        JToken.Parse(File.ReadAllText(path));
                    }
                    catch (JsonReaderException)
                    {
                        File.Delete(path);
                        logger.WriteLine(string.Format("Removed bad cache file: {0}", file));
                    }
                }
            }

            // Make sure that FiddlerCore's key container can be accessed
            string keyContainerName = FiddlerApplication.Prefs.GetStringPref("fiddler.certmaker.bc.KeyContainerName", "FiddlerBCKey");

            try
            {
                CspParameters cspParams = new CspParameters {
                    KeyContainerName = keyContainerName
                };
                var _ = new CspKeyContainerInfo(cspParams).UniqueKeyContainerName; // this will throw an exception if the container cannot be accessed
            }
            catch (CryptographicException)
            {
                byte[] hash;
                using (MD5 md5 = MD5.Create())
                {
                    hash = md5.ComputeHash(Encoding.ASCII.GetBytes(keyContainerName.ToLower() + "\0"));
                }
                var reader = new BinaryReader(new MemoryStream(hash));
                var sb     = new StringBuilder();
                for (int i = 0; i < 4; i++)
                {
                    sb.AppendFormat("{0:x8}", reader.ReadInt32());
                }

                string hashString   = sb.ToString();
                string userSID      = WindowsIdentity.GetCurrent().User.ToString();
                string rsaPath      = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft", "Crypto", "RSA", userSID);
                string keyContainer = Directory.GetFiles(rsaPath).Where(n => Path.GetFileName(n).ToLower().StartsWith(hashString)).FirstOrDefault();

                if (keyContainer != null)
                {
                    File.Delete(keyContainer);
                    logger.WriteLine(string.Format("Removed broken key container (Name: \"{0}\", Hash: {1}).", keyContainerName, hashString));
                }
            }

            if (!CertMaker.rootCertExists() && !CertMaker.createRootCert())
            {
                MessageBox.Show("Creation of the interception certificate failed.", "Unable to generate certificate.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }

            string executable = Path.Combine(GetLauncherPath(), "WiiU_USB_Helper.exe");

            var running = Process.GetProcessesByName("Patched").FirstOrDefault(p => p.GetMainModuleFileName().StartsWith(GetLauncherPath(), StringComparison.OrdinalIgnoreCase));

            if (running != default(Process))
            {
                DialogResult result = MessageBox.Show("An instance of Wii U USB Helper is already running.\nWould you like to close it?", "Already running", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (result == DialogResult.No)
                {
                    Environment.Exit(0);
                }
                running.Kill();
            }

            proxy.Start();
            ServiceHost host = new ServiceHost(typeof(LauncherService), new Uri("net.pipe://localhost/LauncherService"));

            host.AddServiceEndpoint(typeof(ILauncherService), new NetNamedPipeBinding(), "");
            host.Open();

            // Patching
            ProgressDialog dialog = new ProgressDialog();

            dialog.SetStyle(ProgressBarStyle.Marquee);
            dialog.GetProgressBar().MarqueeAnimationSpeed = 30;
            dialog.SetHeader("Injecting...");
            new Thread(() => {
                dialog.ShowDialog();
            }).Start();
            var injector = new ModuleInitInjector(executable);

            executable = Path.Combine(GetLauncherPath(), "Patched.exe");
            injector.Inject(executable);
            logger.WriteLine("Injected module initializer.");
            if (PatchPublicKey)
            {
                dialog.Invoke(new Action(() => dialog.SetHeader("Patching...")));
                RSAPatcher patcher = new RSAPatcher(executable);
                string     xml;
                using (var rsa = new RSACryptoServiceProvider(2048))
                {
                    rsaParams = rsa.ExportParameters(true);
                    xml       = rsa.ToXmlString(false);
                }
                var builder  = new StringBuilder();
                var element  = XElement.Parse(xml);
                var settings = new XmlWriterSettings
                {
                    OmitXmlDeclaration = true,
                    Indent             = true
                };
                using (var xmlWriter = XmlWriter.Create(builder, settings))
                {
                    element.Save(xmlWriter);
                }
                patcher.SetPublicKey(builder.ToString());
                logger.WriteLine("Patched public key.");
            }
            else
            {
                logger.WriteLine("Patching has been disabled.");
            }
            dialog.Invoke(new Action(() => dialog.Close()));

            // Time to launch Wii U USB Helper
            sessionStart = DateTime.UtcNow;
            process      = StartProcess(executable, helperVersion);

            if (Settings.DisableOptionalPatches)
            {
                logger.WriteLine("Optional patches have been disabled.");
            }

            ContextMenu trayMenu   = new ContextMenu();
            MenuItem    dlEmulator = new MenuItem("Download Emulator");

            foreach (EmulatorConfiguration.Emulator emulator in Enum.GetValues(typeof(EmulatorConfiguration.Emulator)))
            {
                EmulatorConfiguration config = EmulatorConfiguration.GetConfiguration(emulator);
                dlEmulator.MenuItems.Add(config.GetName(), (sender, e) => OnDownloadEmulator(config));
            }
            MenuItem advanced = new MenuItem("Advanced");

            advanced.MenuItems.Add("Toggle Console", OnVisibilityChange);
            advanced.MenuItems.Add("Clear Install", OnClearInstall);
            advanced.MenuItems.Add("Generate Donation Key", OnGenerateKey).Enabled = PatchPublicKey;
            advanced.MenuItems.Add("Hosts Editor", OnOpenHostsEditor);
            advanced.MenuItems.Add("Export Sessions", OnExportSessions);
            trayMenu.MenuItems.Add("Exit", OnExit);
            trayMenu.MenuItems.Add("Check for Updates", OnUpdateCheck);
            trayMenu.MenuItems.Add("Report Issue", OnDebugMessage);
            trayMenu.MenuItems.Add(dlEmulator);
            trayMenu.MenuItems.Add(advanced);
            trayIcon = new NotifyIcon
            {
                Text        = "Wii U USB Helper Launcher",
                Icon        = Icon.ExtractAssociatedIcon(Application.ExecutablePath),
                ContextMenu = trayMenu,
                Visible     = true
            };
            backgroundThread = new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (!process.HasExited)
                {
                    try
                    {
                        Thread.Sleep(30);
                    }
                    catch (ThreadInterruptedException) { }
                }
                Cleanup();
                Application.Exit();
            });
            backgroundThread.Start();
            Application.Run();
        }