diff --git a/App.xaml.cs b/App.xaml.cs index 55457ea..4588b3b 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -1,14 +1,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Configuration; -using System.Data; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; -using System.Threading.Tasks; using System.Windows; using Microsoft.Win32; using ISBoxerEVELauncher.Extensions; @@ -17,722 +14,751 @@ using ISBoxerEVELauncher.Games.EVE; using ISBoxerEVELauncher.Interface; using System.Net; +using CefSharp.WinForms; using ISBoxerEVELauncher.Windows; namespace ISBoxerEVELauncher { - /// - /// Interaction logic for App.xaml - /// - public partial class App : Application - { - public static bool HasInnerSpace { get; set; } - public static LoginBrowser myLB = new LoginBrowser(); - public static string strUserName {get; set; } - - - public static string AppVersion - { - get - { - return Assembly.GetExecutingAssembly().GetName().Version.ToString(); - } - } - - - public static void ReloadGameConfiguration() - { - try - { - GameConfiguration = InnerSpaceSettings.Load(ISPath + @"\GameConfiguration.XML"); - } - catch - { - GameConfiguration = null; - } - } - - public static string DetectedEVESharedCachePath - { - get - { - RegistryKey hkcu = Registry.CurrentUser; - RegistryKey PathKey = hkcu.OpenSubKey(@"SOFTWARE\CCP\EVEONLINE"); - if (PathKey != null) - { - string value = PathKey.GetValue("CACHEFOLDER", Environment.SpecialFolder.CommonApplicationData + @"\CCP\EVE\SharedCache\") as string; - return value; + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + public static bool HasInnerSpace + { + get; set; + } + public static LoginBrowser myLB = new LoginBrowser(); + public static string strUserName + { + get; set; + } + public static string strPassword + { + get; set; + } + + + public static string AppVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); } - return null; - } - - } - - public static string[] CommandLine; - public static bool ExitAfterLaunch; - public static bool searchCharactersOnly; - - static Settings _Settings; - public static Settings Settings - { - get - { - if (_Settings == null) - { - try - { - _Settings = Settings.Load(); - if (EVEAccount.ShouldUgradeCookieStorage) - { - _Settings.Store(); - } - } - catch (System.IO.FileNotFoundException) - { - _Settings = new Settings(); - _Settings.Store(); - } - } - return _Settings; - } - } - - public static string ISBoxerEVELauncherPath - { - get - { - return System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - } - } - - public static string ISExecutable - { - get - { - return ISPath + "\\InnerSpace.exe"; - } - } - - public static string BaseDirectory - { - get - { - return System.AppDomain.CurrentDomain.BaseDirectory; - } - } - - static string _ISPath = string.Empty; - /// - /// Path to Inner Space, which should either be in the registry, or the current folder. Otherwise, the user likely doesn't care about Inner Space integration. - /// - public static string ISPath - { - get - { - // already detected? - if (!string.IsNullOrEmpty(_ISPath)) - return _ISPath; - - // nope. - - // we're expected to be installed into the IS/ISBoxer folder.... - if (System.IO.File.Exists(BaseDirectory + @"\InnerSpace.exe")) - { - _ISPath = BaseDirectory; - return _ISPath; - } - - // oh well... the path SHOULD be in the registry... - { - RegistryKey hklm = Registry.LocalMachine; - RegistryKey ISPathKey = hklm.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\InnerSpace.exe"); - if (ISPathKey != null) - { - string reg_path = ISPathKey.GetValue("Path", Environment.SpecialFolder.ProgramFiles + @"\InnerSpace") as string; - if (System.IO.File.Exists(reg_path + "\\InnerSpace.exe")) - { - _ISPath = reg_path; - return _ISPath; - } - } - } - - // didn't find it. maybe not even installed. - return BaseDirectory; - } - set - { - _ISPath = value; - } - } - - static void ReloadGameProfiles() - { - InnerSpaceGameProfile gpSingularity = Settings.SingularityGameProfile; - InnerSpaceGameProfile gpTranquility = Settings.TranquilityGameProfile; - - if (_GameProfiles == null) - { - _GameProfiles = new ObservableCollection(); - } - else - _GameProfiles.Clear(); - - if (GameConfiguration != null) - { - if (GameConfiguration.Sets != null) - { - foreach (Set gameSet in GameConfiguration.Sets) - { - Set profilesSet = gameSet.FindSet("Profiles"); - if (profilesSet == null || profilesSet.Sets == null) - continue; - - foreach (Set gameProfileSet in profilesSet.Sets) - { - InnerSpaceGameProfile gp = new InnerSpaceGameProfile() { Game = gameSet.Name, GameProfile = gameProfileSet.Name }; - _GameProfiles.Add(gp); - } - } - } - } - - Settings.SingularityGameProfile = App.FindGlobalGameProfile(gpSingularity); - Settings.TranquilityGameProfile = App.FindGlobalGameProfile(gpTranquility); - } - - public static Set FindGameProfileSet(string gameName, string gameProfileName) - { - if (string.IsNullOrWhiteSpace(gameName) || string.IsNullOrWhiteSpace(gameProfileName)) - return null; + } - if (GameConfiguration == null || GameConfiguration.Sets == null) - return null; - Set gameSet = GameConfiguration.FindSet(gameName); - if (gameSet == null) - return null; + public static void ReloadGameConfiguration() + { + try + { + GameConfiguration = InnerSpaceSettings.Load(ISPath + @"\GameConfiguration.XML"); + } + catch + { + GameConfiguration = null; + } + } - Set profilesSet = gameSet.FindSet("Profiles"); - if (profilesSet == null || profilesSet.Sets == null) - return null; + public static string DetectedEVESharedCachePath + { + get + { + RegistryKey hkcu = Registry.CurrentUser; + RegistryKey PathKey = hkcu.OpenSubKey(@"SOFTWARE\CCP\EVEONLINE"); + if (PathKey != null) + { + string value = PathKey.GetValue("CACHEFOLDER", Environment.SpecialFolder.CommonApplicationData + @"\CCP\EVE\SharedCache\") as string; + return value; + } + return null; + } + + } + + public static string[] CommandLine; + public static bool ExitAfterLaunch; + public static bool searchCharactersOnly; + + static Settings _Settings; + public static Settings Settings + { + get + { + if (_Settings == null) + { + try + { + _Settings = Settings.Load(); + if (EVEAccount.ShouldUgradeCookieStorage) + { + _Settings.Store(); + } + } + catch (System.IO.FileNotFoundException) + { + _Settings = new Settings(); + _Settings.Store(); + } + } + return _Settings; + } + } - return profilesSet.FindSet(gameProfileName); - } + public static string ISBoxerEVELauncherPath + { + get + { + return System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + } + } + + public static string ISExecutable + { + get + { + return ISPath + "\\InnerSpace.exe"; + } + } + + public static string BaseDirectory + { + get + { + return System.AppDomain.CurrentDomain.BaseDirectory; + } + } + + static string _ISPath = string.Empty; + /// + /// Path to Inner Space, which should either be in the registry, or the current folder. Otherwise, the user likely doesn't care about Inner Space integration. + /// + public static string ISPath + { + get + { + // already detected? + if (!string.IsNullOrEmpty(_ISPath)) + return _ISPath; + + // nope. + + // we're expected to be installed into the IS/ISBoxer folder.... + if (System.IO.File.Exists(BaseDirectory + @"\InnerSpace.exe")) + { + _ISPath = BaseDirectory; + return _ISPath; + } + + // oh well... the path SHOULD be in the registry... + { + RegistryKey hklm = Registry.LocalMachine; + RegistryKey ISPathKey = hklm.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\InnerSpace.exe"); + if (ISPathKey != null) + { + string reg_path = ISPathKey.GetValue("Path", Environment.SpecialFolder.ProgramFiles + @"\InnerSpace") as string; + if (System.IO.File.Exists(reg_path + "\\InnerSpace.exe")) + { + _ISPath = reg_path; + return _ISPath; + } + } + } + + // didn't find it. maybe not even installed. + return BaseDirectory; + } + set + { + _ISPath = value; + } + } + + static void ReloadGameProfiles() + { + InnerSpaceGameProfile gpSingularity = Settings.SingularityGameProfile; + InnerSpaceGameProfile gpTranquility = Settings.TranquilityGameProfile; - static Set _GameConfiguration; - public static Set GameConfiguration { get { return _GameConfiguration; } private set { _GameConfiguration = value; ReloadGameProfiles(); } } - static ObservableCollection _GameProfiles; - public static ObservableCollection GameProfiles - { - get - { if (_GameProfiles == null) { - _GameProfiles = new ObservableCollection(); - ReloadGameProfiles(); - } - return _GameProfiles; - } - private set - { - _GameProfiles = value; - } - } - - public static InnerSpaceGameProfile FindGlobalGameProfile(InnerSpaceGameProfile likeThis) - { - if (GameProfiles == null || likeThis == null) - return likeThis; - - InnerSpaceGameProfile found = GameProfiles.FirstOrDefault(q => q.Game.Equals(likeThis.Game, StringComparison.InvariantCultureIgnoreCase) && q.GameProfile.Equals(likeThis.GameProfile, StringComparison.InvariantCultureIgnoreCase)); - if (found == null) - return likeThis; - - return found; - } - - static bool AddGameToXML(string gameName, string gameProfileName, string executablePath, string executableName, string parameters) - { - // not running, just edit the XML - if (GameConfiguration == null) - { - // no existing XML. - return false; - } - - Set gameSet = GameConfiguration.FindSet(gameName); - if (gameSet == null) - { - gameSet = new Set(gameName); - GameConfiguration.Add(gameSet); - gameSet.Add(new Setting("OpenGL", "1")); - gameSet.Add(new Setting("Direct3D8", "1")); - gameSet.Add(new Setting("Direct3D9", "1")); - gameSet.Add(new Setting("Win32I Keyboard", "1")); - gameSet.Add(new Setting("Win32I Mouse", "1")); - gameSet.Add(new Setting("DirectInput8 Keyboard", "1")); - gameSet.Add(new Setting("DirectInput8 Mouse", "1")); - gameSet.Add(new Setting("modules", "auto")); - gameSet.Add(new Setting("Background Mouse", "1")); - gameSet.Add(new Setting("Keystroke Delay", "1")); - } - - Set gameProfilesSet = gameSet.FindSet("Profiles"); - if (gameProfilesSet == null) - { - gameProfilesSet = new Set("Profiles"); - gameSet.Add(gameProfilesSet); - } - - Set gameProfileSet = gameSet.FindSet(gameProfileName); - if (gameProfileSet == null) - { - gameProfileSet = new Set(gameProfileName); - gameProfilesSet.Add(gameProfileSet); - } - - Setting setting = gameProfileSet.FindSetting("Executable"); - if (setting == null) - gameProfileSet.Add(new Setting("Executable", executableName)); - else - setting.Value = executableName; - - setting = gameProfileSet.FindSetting("Path"); - if (setting == null) - gameProfileSet.Add(new Setting("Path", executablePath)); - else - setting.Value = executablePath; - - setting = gameProfileSet.FindSetting("Parameters"); - if (setting == null) - { - if (!string.IsNullOrEmpty(parameters)) - gameProfileSet.Add(new Setting("Parameters", parameters)); - } - else - { - if (string.IsNullOrEmpty(parameters)) - gameProfileSet.Settings.Remove(setting); + _GameProfiles = new ObservableCollection(); + } else - setting.Value = parameters; - } - - if (GameProfiles.FirstOrDefault(q => q.GameProfile.Equals(gameProfileName)) == null) - { - GameProfiles.Add(new InnerSpaceGameProfile() { Game = gameName, GameProfile = gameProfileName }); - } - - GameConfiguration.Store(ISPath + @"\GameConfiguration.XML"); - return true; - } - /// - /// Add a Game/Game Profile to Inner Space - /// - /// - /// - /// - /// - /// - /// - public static bool AddGame(string gameName, string gameProfileName, string executablePath, string executableName, string parameters) - { - string isboxerFilename = System.IO.Path.Combine(ISPath, "ISBoxer Toolkit.exe"); - while (true) - { - System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("InnerSpace"); - if (processes.Length == 0) - { - if (!AddGameToXML(gameName, gameProfileName, executablePath, executableName, parameters)) - { - MessageBox.Show("In order to Add Game for you, ISBoxer EVE Launcher requires that GameConfiguration.XML exist in the Inner Space folder -- looking for: " + isboxerFilename); - return false; - } - return true; - } - - if (!System.IO.File.Exists(isboxerFilename)) - { - switch (MessageBox.Show("ISBoxer EVE Launcher has determined that Inner Space is running. Please Exit Inner Space and click OK to try again, otherwise click Cancel.", "Adding a Game this way requires Inner Space to be closed", MessageBoxButton.OKCancel)) - { - case MessageBoxResult.OK: - continue; - case MessageBoxResult.Cancel: - return false; - } + _GameProfiles.Clear(); + + if (GameConfiguration != null) + { + if (GameConfiguration.Sets != null) + { + foreach (Set gameSet in GameConfiguration.Sets) + { + Set profilesSet = gameSet.FindSet("Profiles"); + if (profilesSet == null || profilesSet.Sets == null) + continue; + + foreach (Set gameProfileSet in profilesSet.Sets) + { + InnerSpaceGameProfile gp = new InnerSpaceGameProfile() { Game = gameSet.Name, GameProfile = gameProfileSet.Name }; + _GameProfiles.Add(gp); + } + } + } } + + Settings.SingularityGameProfile = App.FindGlobalGameProfile(gpSingularity); + Settings.TranquilityGameProfile = App.FindGlobalGameProfile(gpTranquility); + } + + public static Set FindGameProfileSet(string gameName, string gameProfileName) + { + if (string.IsNullOrWhiteSpace(gameName) || string.IsNullOrWhiteSpace(gameProfileName)) + return null; + + if (GameConfiguration == null || GameConfiguration.Sets == null) + return null; + + Set gameSet = GameConfiguration.FindSet(gameName); + if (gameSet == null) + return null; + + Set profilesSet = gameSet.FindSet("Profiles"); + if (profilesSet == null || profilesSet.Sets == null) + return null; + + return profilesSet.FindSet(gameProfileName); + } + + static Set _GameConfiguration; + public static Set GameConfiguration + { + get + { + return _GameConfiguration; + } + private set + { + _GameConfiguration = value; + ReloadGameProfiles(); + } + } + static ObservableCollection _GameProfiles; + public static ObservableCollection GameProfiles + { + get + { + if (_GameProfiles == null) + { + _GameProfiles = new ObservableCollection(); + ReloadGameProfiles(); + } + return _GameProfiles; + } + private set + { + _GameProfiles = value; + } + } + + public static InnerSpaceGameProfile FindGlobalGameProfile(InnerSpaceGameProfile likeThis) + { + if (GameProfiles == null || likeThis == null) + return likeThis; + + InnerSpaceGameProfile found = GameProfiles.FirstOrDefault(q => q.Game.Equals(likeThis.Game, StringComparison.InvariantCultureIgnoreCase) && q.GameProfile.Equals(likeThis.GameProfile, StringComparison.InvariantCultureIgnoreCase)); + if (found == null) + return likeThis; + + return found; + } + + static bool AddGameToXML(string gameName, string gameProfileName, string executablePath, string executableName, string parameters) + { + // not running, just edit the XML + if (GameConfiguration == null) + { + // no existing XML. + return false; + } + + Set gameSet = GameConfiguration.FindSet(gameName); + if (gameSet == null) + { + gameSet = new Set(gameName); + GameConfiguration.Add(gameSet); + gameSet.Add(new Setting("OpenGL", "1")); + gameSet.Add(new Setting("Direct3D8", "1")); + gameSet.Add(new Setting("Direct3D9", "1")); + gameSet.Add(new Setting("Win32I Keyboard", "1")); + gameSet.Add(new Setting("Win32I Mouse", "1")); + gameSet.Add(new Setting("DirectInput8 Keyboard", "1")); + gameSet.Add(new Setting("DirectInput8 Mouse", "1")); + gameSet.Add(new Setting("modules", "auto")); + gameSet.Add(new Setting("Background Mouse", "1")); + gameSet.Add(new Setting("Keystroke Delay", "1")); + } + + Set gameProfilesSet = gameSet.FindSet("Profiles"); + if (gameProfilesSet == null) + { + gameProfilesSet = new Set("Profiles"); + gameSet.Add(gameProfilesSet); + } + + Set gameProfileSet = gameSet.FindSet(gameProfileName); + if (gameProfileSet == null) + { + gameProfileSet = new Set(gameProfileName); + gameProfilesSet.Add(gameProfileSet); + } + + Setting setting = gameProfileSet.FindSetting("Executable"); + if (setting == null) + gameProfileSet.Add(new Setting("Executable", executableName)); else + setting.Value = executableName; + + setting = gameProfileSet.FindSetting("Path"); + if (setting == null) + gameProfileSet.Add(new Setting("Path", executablePath)); + else + setting.Value = executablePath; + + setting = gameProfileSet.FindSetting("Parameters"); + if (setting == null) { - FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(isboxerFilename); - if (fvi.ProductMajorPart < 42) - { - switch (MessageBox.Show("ISBoxer EVE Launcher has determined that Inner Space is running. Please Exit Inner Space and click OK to try again, otherwise click Cancel.", "Adding a Game this way requires Inner Space to be closed", MessageBoxButton.OKCancel)) - { - case MessageBoxResult.OK: - continue; - case MessageBoxResult.Cancel: + if (!string.IsNullOrEmpty(parameters)) + gameProfileSet.Add(new Setting("Parameters", parameters)); + } + else + { + if (string.IsNullOrEmpty(parameters)) + gameProfileSet.Settings.Remove(setting); + else + setting.Value = parameters; + } + + if (GameProfiles.FirstOrDefault(q => q.GameProfile.Equals(gameProfileName)) == null) + { + GameProfiles.Add(new InnerSpaceGameProfile() { Game = gameName, GameProfile = gameProfileName }); + } + + GameConfiguration.Store(ISPath + @"\GameConfiguration.XML"); + return true; + } + /// + /// Add a Game/Game Profile to Inner Space + /// + /// + /// + /// + /// + /// + /// + public static bool AddGame(string gameName, string gameProfileName, string executablePath, string executableName, string parameters) + { + string isboxerFilename = System.IO.Path.Combine(ISPath, "ISBoxer Toolkit.exe"); + while (true) + { + System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("InnerSpace"); + if (processes.Length == 0) + { + if (!AddGameToXML(gameName, gameProfileName, executablePath, executableName, parameters)) + { + MessageBox.Show("In order to Add Game for you, ISBoxer EVE Launcher requires that GameConfiguration.XML exist in the Inner Space folder -- looking for: " + isboxerFilename); return false; - } - } + } + return true; + } + + if (!System.IO.File.Exists(isboxerFilename)) + { + switch (MessageBox.Show("ISBoxer EVE Launcher has determined that Inner Space is running. Please Exit Inner Space and click OK to try again, otherwise click Cancel.", "Adding a Game this way requires Inner Space to be closed", MessageBoxButton.OKCancel)) + { + case MessageBoxResult.OK: + continue; + case MessageBoxResult.Cancel: + return false; + } + } + else + { + FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(isboxerFilename); + if (fvi.ProductMajorPart < 42) + { + switch (MessageBox.Show("ISBoxer EVE Launcher has determined that Inner Space is running. Please Exit Inner Space and click OK to try again, otherwise click Cancel.", "Adding a Game this way requires Inner Space to be closed", MessageBoxButton.OKCancel)) + { + case MessageBoxResult.OK: + continue; + case MessageBoxResult.Cancel: + return false; + } + } + } + + + string cmdLine = "run isboxer -inituplink;isboxeraddgame \"" + gameName.Replace("\"", "\\\"") + "\" \"" + gameProfileName.Replace("\"", "\\\"") + "\" \"" + executablePath.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\" \"" + executableName.Replace("\"", "\\\"") + "\" \"" + parameters.Replace("\"", "\\\"") + "\""; + System.Diagnostics.Process.Start(ISExecutable, cmdLine); + return true; + } + } + + /// + /// Have Inner Space launch EVE via a specified Game and Game Profile + /// + /// + /// + /// + /// + /// + /// + static public bool Launch(string gameName, string gameProfileName, bool sisi, DirectXVersion dxVersion, long characterID, EVEAccount.Token token) + { + //if (ssoToken == null) + // throw new ArgumentNullException("ssoToken"); + if (gameName == null) + throw new ArgumentNullException("gameName"); + if (gameProfileName == null) + throw new ArgumentNullException("gameProfileName"); + + string cmdLine = "open \"" + gameName + "\" \"" + gameProfileName + "\" -addparam \"/noconsole\" -addparam \"/ssoToken=" + token.TokenString + "\""; + if (dxVersion != DirectXVersion.Default) + { + cmdLine += " -addparam \"/triPlatform=" + dxVersion.ToString() + "\""; } + if (characterID != 0) + { + cmdLine += " -addparam \"/character=" + characterID + "\""; + } - string cmdLine = "run isboxer -inituplink;isboxeraddgame \"" + gameName.Replace("\"", "\\\"") + "\" \"" + gameProfileName.Replace("\"", "\\\"") + "\" \"" + executablePath.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\" \"" + executableName.Replace("\"", "\\\"") + "\" \"" + parameters.Replace("\"", "\\\"") + "\""; - System.Diagnostics.Process.Start(ISExecutable, cmdLine); + if (sisi) + { + cmdLine += " -addparam \"/server:Singularity\""; + } + else + { + cmdLine += " -addparam \"/server:tranquility\""; + } + + cmdLine += " -addparam \"settingsprofile=ISBEL\" -addparam \"/machineHash=" + App.Settings.MachineHash + "\" \"\""; + + try + { + System.Diagnostics.Process.Start(App.ISExecutable, cmdLine); + } + catch (Exception e) + { + MessageBox.Show("Launch failed. executable=" + App.ISExecutable + "; args=" + cmdLine + System.Environment.NewLine + e.ToString()); + return false; + } return true; - } - } - - /// - /// Have Inner Space launch EVE via a specified Game and Game Profile - /// - /// - /// - /// - /// - /// - /// - static public bool Launch(string gameName, string gameProfileName, bool sisi, DirectXVersion dxVersion, long characterID, EVEAccount.Token token) - { - //if (ssoToken == null) - // throw new ArgumentNullException("ssoToken"); - if (gameName == null) - throw new ArgumentNullException("gameName"); - if (gameProfileName == null) - throw new ArgumentNullException("gameProfileName"); - - string cmdLine = "open \"" + gameName + "\" \"" + gameProfileName + "\" -addparam \"/noconsole\" -addparam \"/ssoToken=" + token.TokenString + "\""; - if (dxVersion != DirectXVersion.Default) - { - cmdLine += " -addparam \"/triPlatform=" + dxVersion.ToString() + "\""; - } - - if (characterID != 0) - { - cmdLine += " -addparam \"/character=" + characterID + "\""; - } - - if (sisi) - { - cmdLine += " -addparam \"/server:Singularity\""; - } - else - { - cmdLine += " -addparam \"/server:tranquility\""; - } - - cmdLine += " -addparam \"settingsprofile=ISBEL\" -addparam \"/machineHash=" + App.Settings.MachineHash + "\" \"\""; - - try - { - System.Diagnostics.Process.Start(App.ISExecutable, cmdLine); - } - catch (Exception e) - { - MessageBox.Show("Launch failed. executable=" + App.ISExecutable + "; args=" + cmdLine + System.Environment.NewLine + e.ToString()); - return false; - } - return true; - } - - /// - /// Launch EVE directly - /// - /// - /// - /// - /// - /// - static public bool Launch(string sharedCachePath, bool sisi, DirectXVersion dxVersion, long characterID, EVEAccount.Token token) - { - //if (ssoToken == null) - // throw new ArgumentNullException("ssoToken"); - if (sharedCachePath == null) - throw new ArgumentNullException("sharedCachePath"); - - string args = "/noconsole /ssoToken=" + token.TokenString; - if (dxVersion != DirectXVersion.Default) - { - args += " /triPlatform=" + dxVersion.ToString(); - } - - if (sisi) - { - args += " /server:Singularity"; - } - else - { - args += " /server:tranquility"; - } - - if (characterID != 0) - { - args += " /character=" + characterID; - } - - args += " /settingsprofile=ISBEL /machineHash=" + App.Settings.MachineHash + " \"\""; - - string executable; - if (sisi) - executable = App.Settings.GetSingularityEXE(); - else - executable = App.Settings.GetTranquilityEXE(); - - if (!System.IO.File.Exists(executable)) - { - MessageBox.Show("Cannot find exefile.exe for launch -- looking at: " + executable); - return false; - } - - try - { - System.Diagnostics.Process.Start(executable, args); - } - catch (Exception e) - { - MessageBox.Show("Launch failed. executable=" + executable + "; args=" + args + System.Environment.NewLine + e.ToString()); - return false; - } - return true; - } - - public static void ProcessCommandLine(string Args) - { - ProcessCommandLine(Args.SplitCommandLine()); - } - - public static void ProcessCommandLine(IEnumerable Args) - { - - if (Args == null || Args.Count() == 0) - { - ProfileManager.MigrateSettingsToISBEL(); - return; - } - - List LaunchAccountNames = new List(); - - bool useInnerSpace = false; - foreach (string s in Args) - { - switch (s.ToLowerInvariant()) - { - case "-dx9": - Settings.UseDirectXVersion = DirectXVersion.dx9; - break; - case "-dx11": - Settings.UseDirectXVersion = DirectXVersion.dx11; - break; - case "-singularity": - Settings.UseSingularity = true; - break; - case "-tranquility": - Settings.UseSingularity = false; - break; - case "-innerspace": - useInnerSpace = true; - break; - case "-eve": - useInnerSpace = false; - break; - case "-multiinstance": - break; - case "-exit": - ExitAfterLaunch = true; - break; - case "-c": - searchCharactersOnly = true; - break; - case "null": - // ignore - break; - default: - LaunchAccountNames.Add(s); - break; - } - } - - if (LaunchAccountNames.Count == 0) - { - - return; - } - - List LaunchAccounts = new List(); - - foreach (string name in LaunchAccountNames) - { - - if (!searchCharactersOnly) - { - EVEAccount acct = Settings.Accounts.FirstOrDefault(q => q.Username.Equals(name, StringComparison.InvariantCultureIgnoreCase)); - if (acct != null) - { - LaunchAccounts.Add(acct); - continue; - } - } - EVECharacter ec = Settings.Characters.FirstOrDefault(q => q.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)); - if (ec != null) - { - LaunchAccounts.Add(ec); - continue; - } - - MessageBox.Show("Unrecognized EVE Account or Character name '" + name + "' -- if this is correct, please use Add Account/Character to enable it before launching."); - return; - } - - ILauncher launcher; - if (useInnerSpace) - { - InnerSpaceGameProfile gp; - if (Settings.UseSingularity) - { - gp = Settings.SingularityGameProfile; + } + + /// + /// Launch EVE directly + /// + /// + /// + /// + /// + /// + static public bool Launch(string sharedCachePath, bool sisi, DirectXVersion dxVersion, long characterID, EVEAccount.Token token) + { + //if (ssoToken == null) + // throw new ArgumentNullException("ssoToken"); + if (sharedCachePath == null) + throw new ArgumentNullException("sharedCachePath"); + + string args = "/noconsole /ssoToken=" + token.TokenString; + if (dxVersion != DirectXVersion.Default) + { + args += " /triPlatform=" + dxVersion.ToString(); + } + + if (sisi) + { + args += " /server:Singularity"; } else { - gp = Settings.TranquilityGameProfile; + args += " /server:tranquility"; } - if (gp == null || string.IsNullOrEmpty(gp.Game) || string.IsNullOrEmpty(gp.GameProfile)) + if (characterID != 0) { - MessageBox.Show("Please select a Game Profile first!"); - return; + args += " /character=" + characterID; } - launcher = new Launchers.InnerSpace(gp, Settings.UseDirectXVersion, Settings.UseSingularity); - } - else - { - launcher = new Launchers.Direct(Settings.EVESharedCachePath, Settings.UseDirectXVersion, Settings.UseSingularity); - } - Windows.LaunchProgressWindow lpw = new Windows.LaunchProgressWindow(LaunchAccounts, launcher); - lpw.ShowDialog(); + args += " /settingsprofile=ISBEL /machineHash=" + App.Settings.MachineHash + " \"\""; - if (ExitAfterLaunch) - { - App.Current.Shutdown(); - } - } + string executable; + if (sisi) + executable = App.Settings.GetSingularityEXE(); + else + executable = App.Settings.GetTranquilityEXE(); - /// - /// Gets what we think is the "master" ISBoxer EVE Launcher instance - /// - /// true if we should be more secure about it (e.g. Master Key transfer), false if we're just passing command-line around - /// - static public Process GetMasterInstance(bool ensureMainModule) - { - Process currentProcess = Process.GetCurrentProcess(); + if (!System.IO.File.Exists(executable)) + { + MessageBox.Show("Cannot find exefile.exe for launch -- looking at: " + executable); + return false; + } - //Note: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.mainwindowhandle?view=netframework-4.7 - //When the Main window is hidden, it will return a MainWindowHandle of 0. This makes the following code fail when trying to find the master window that is minimized to the system tray: - IEnumerable processList = Process.GetProcesses().Where(q => q.NameMatches(currentProcess) && (q.MainWindowHandle != IntPtr.Zero || q.Id == currentProcess.Id)); + try + { + System.Diagnostics.Process.Start(executable, args); + } + catch (Exception e) + { + MessageBox.Show("Launch failed. executable=" + executable + "; args=" + args + System.Environment.NewLine + e.ToString()); + return false; + } + return true; + } - if (processList == null) - return null; + public static void ProcessCommandLine(string Args) + { + ProcessCommandLine(Args.SplitCommandLine()); + } - Process[] processes = processList.ToArray(); - Array.Sort(processes, (a, b) => a.StartTime > b.StartTime ? 1 : -1); - if (processes.Length > 1) - { - for (int i = 0; i < processes.Length; i++) - { - if (processes[i].Id == currentProcess.Id) - continue; - - // ensure that the Master Instance is indeed this app by checking the module list? (note: if the other process is Administrator, this one also needs to be Administrator) - if (!ensureMainModule) - return processes[i]; - - try - { - - if (processes[i].MainModuleNameMatches(currentProcess)) - return processes[i]; - } - catch (System.ComponentModel.Win32Exception we) - { - if (we.NativeErrorCode == 5) - { - // this might be the right instance, but since it's Administrator and we're not, we can't use it. - continue; - } - throw; - } - } - } - return null; - } - - /// - /// Transmit the command-line to an already-running Master instance, if one is available - /// - /// - public bool TransmitCommandLine() - { - // check if it's already running. - - System.Diagnostics.Process masterInstance = GetMasterInstance(false); - - if (masterInstance != null) - { - string joinedCommandLine = string.Empty; - foreach (string s in CommandLine) - { - // if it's another process, don't exit - switch (s.ToLowerInvariant()) - { - case "null": - // ignore... - break; - case "-exit": - // the -exit is intended for THIS process, not the other one. - break; - case "-multiinstance": - return false; - } - - if (!s.Equals("-exit", StringComparison.InvariantCultureIgnoreCase)) - joinedCommandLine += "\"" + s.Replace("\"", "\\\"") + "\" "; - } - joinedCommandLine.TrimEnd(); + public static void ProcessCommandLine(IEnumerable Args) + { - byte[] buff = Encoding.Unicode.GetBytes(joinedCommandLine); + if (Args == null || Args.Count() == 0) + { + ProfileManager.MigrateSettingsToISBEL(); + return; + } - Windows.COPYDATASTRUCT cds = new Windows.COPYDATASTRUCT(); - cds.cbData = buff.Length; - cds.lpData = Marshal.AllocHGlobal(buff.Length); - Marshal.Copy(buff, 0, cds.lpData, buff.Length); - cds.dwData = IntPtr.Zero; - cds.cbData = buff.Length; - var ret = ISBoxerEVELauncher.Windows.MainWindow.SendMessage(masterInstance.MainWindowHandle, ISBoxerEVELauncher.Windows.MainWindow.WM_COPYDATA, IntPtr.Zero, ref cds); - Marshal.FreeHGlobal(cds.lpData); + List LaunchAccountNames = new List(); - Shutdown(); - return true; - } - return false; - } + bool useInnerSpace = false; + foreach (string s in Args) + { + switch (s.ToLowerInvariant()) + { + case "-dx9": + Settings.UseDirectXVersion = DirectXVersion.dx9; + break; + case "-dx11": + Settings.UseDirectXVersion = DirectXVersion.dx11; + break; + case "-singularity": + Settings.UseSingularity = true; + break; + case "-tranquility": + Settings.UseSingularity = false; + break; + case "-innerspace": + useInnerSpace = true; + break; + case "-eve": + useInnerSpace = false; + break; + case "-multiinstance": + break; + case "-exit": + ExitAfterLaunch = true; + break; + case "-c": + searchCharactersOnly = true; + break; + case "null": + // ignore + break; + default: + LaunchAccountNames.Add(s); + break; + } + } + + if (LaunchAccountNames.Count == 0) + { + + return; + } + + List LaunchAccounts = new List(); + + foreach (string name in LaunchAccountNames) + { + + if (!searchCharactersOnly) + { + EVEAccount acct = Settings.Accounts.FirstOrDefault(q => q.Username.Equals(name, StringComparison.InvariantCultureIgnoreCase)); + if (acct != null) + { + LaunchAccounts.Add(acct); + continue; + } + } + EVECharacter ec = Settings.Characters.FirstOrDefault(q => q.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)); + if (ec != null) + { + LaunchAccounts.Add(ec); + continue; + } + + MessageBox.Show("Unrecognized EVE Account or Character name '" + name + "' -- if this is correct, please use Add Account/Character to enable it before launching."); + return; + } + + ILauncher launcher; + if (useInnerSpace) + { + InnerSpaceGameProfile gp; + if (Settings.UseSingularity) + { + gp = Settings.SingularityGameProfile; + } + else + { + gp = Settings.TranquilityGameProfile; + } + + if (gp == null || string.IsNullOrEmpty(gp.Game) || string.IsNullOrEmpty(gp.GameProfile)) + { + MessageBox.Show("Please select a Game Profile first!"); + return; + } + + launcher = new Launchers.InnerSpace(gp, Settings.UseDirectXVersion, Settings.UseSingularity); + } + else + { + launcher = new Launchers.Direct(Settings.EVESharedCachePath, Settings.UseDirectXVersion, Settings.UseSingularity); + } + Windows.LaunchProgressWindow lpw = new Windows.LaunchProgressWindow(LaunchAccounts, launcher); + lpw.ShowDialog(); + + if (ExitAfterLaunch) + { + App.Current.Shutdown(); + } + } + + /// + /// Gets what we think is the "master" ISBoxer EVE Launcher instance + /// + /// true if we should be more secure about it (e.g. Master Key transfer), false if we're just passing command-line around + /// + static public Process GetMasterInstance(bool ensureMainModule) + { + Process currentProcess = Process.GetCurrentProcess(); + + //Note: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.mainwindowhandle?view=netframework-4.7 + //When the Main window is hidden, it will return a MainWindowHandle of 0. This makes the following code fail when trying to find the master window that is minimized to the system tray: + IEnumerable processList = Process.GetProcesses().Where(q => q.NameMatches(currentProcess) && (q.MainWindowHandle != IntPtr.Zero || q.Id == currentProcess.Id)); + + if (processList == null) + return null; + + Process[] processes = processList.ToArray(); + Array.Sort(processes, (a, b) => a.StartTime > b.StartTime ? 1 : -1); + if (processes.Length > 1) + { + for (int i = 0; i < processes.Length; i++) + { + if (processes[i].Id == currentProcess.Id) + continue; - private void ApplicationStart(object sender, StartupEventArgs e) - { - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - // Allows the operating system to choose the best protocol to use, and to block protocols that are not secure. Unless your app has a specific reason not to, you should use this value. - ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault; + // ensure that the Master Instance is indeed this app by checking the module list? (note: if the other process is Administrator, this one also needs to be Administrator) + if (!ensureMainModule) + return processes[i]; + + try + { + + if (processes[i].MainModuleNameMatches(currentProcess)) + return processes[i]; + } + catch (System.ComponentModel.Win32Exception we) + { + if (we.NativeErrorCode == 5) + { + // this might be the right instance, but since it's Administrator and we're not, we can't use it. + continue; + } + throw; + } + } + } + return null; + } - CommandLine = e.Args; + /// + /// Transmit the command-line to an already-running Master instance, if one is available + /// + /// + public bool TransmitCommandLine() + { + // check if it's already running. - if (!TransmitCommandLine()) - { - ReloadGameConfiguration(); + System.Diagnostics.Process masterInstance = GetMasterInstance(false); - if (GameConfiguration != null || System.IO.File.Exists(ISExecutable)) + if (masterInstance != null) { - HasInnerSpace = true; + string joinedCommandLine = string.Empty; + foreach (string s in CommandLine) + { + // if it's another process, don't exit + switch (s.ToLowerInvariant()) + { + case "null": + // ignore... + break; + case "-exit": + // the -exit is intended for THIS process, not the other one. + break; + case "-multiinstance": + return false; + } + + if (!s.Equals("-exit", StringComparison.InvariantCultureIgnoreCase)) + joinedCommandLine += "\"" + s.Replace("\"", "\\\"") + "\" "; + } + joinedCommandLine.TrimEnd(); + + byte[] buff = Encoding.Unicode.GetBytes(joinedCommandLine); + + Windows.COPYDATASTRUCT cds = new Windows.COPYDATASTRUCT(); + cds.cbData = buff.Length; + cds.lpData = Marshal.AllocHGlobal(buff.Length); + Marshal.Copy(buff, 0, cds.lpData, buff.Length); + cds.dwData = IntPtr.Zero; + cds.cbData = buff.Length; + var ret = ISBoxerEVELauncher.Windows.MainWindow.SendMessage(masterInstance.MainWindowHandle, ISBoxerEVELauncher.Windows.MainWindow.WM_COPYDATA, IntPtr.Zero, ref cds); + Marshal.FreeHGlobal(cds.lpData); + + Shutdown(); + return true; } + return false; + } + + private void ApplicationStart(object sender, StartupEventArgs e) + { + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + // Allows the operating system to choose the best protocol to use, and to block protocols that are not secure. Unless your app has a specific reason not to, you should use this value. + ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault; + + CommandLine = e.Args; + + if (!TransmitCommandLine()) + { + ReloadGameConfiguration(); + + if (GameConfiguration != null || System.IO.File.Exists(ISExecutable)) + { + HasInnerSpace = true; + } + + CefSettings settings = new CefSettings(); + settings.CachePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CEF"; + + CefSharp.Cef.Initialize(settings); + + var mainWindow = new Windows.MainWindow(); //Re-enable normal shutdown mode. @@ -741,13 +767,13 @@ private void ApplicationStart(object sender, StartupEventArgs e) mainWindow.Show(); ProcessCommandLine(CommandLine); - } - } + } + } - void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - MessageBox.Show("Exception unhandled by ISBoxer EVE Launcher: " + e.ExceptionObject.ToString()); - } + void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + MessageBox.Show("Exception unhandled by ISBoxer EVE Launcher: " + e.ExceptionObject.ToString()); + } - } + } } diff --git a/Games/EVE/EVEAccount.cs b/Games/EVE/EVEAccount.cs index 17040ec..7ccbdbf 100644 --- a/Games/EVE/EVEAccount.cs +++ b/Games/EVE/EVEAccount.cs @@ -1309,6 +1309,7 @@ public LoginResult GetAccessToken(bool sisi, out Token accessToken) } App.strUserName = Username; + App.strPassword = new System.Net.NetworkCredential(string.Empty, SecurePassword).Password; var uri = RequestResponse.GetLoginUri(sisi, state.ToString(), challengeHash); diff --git a/Windows/LoginBrowser.Designer.cs b/Windows/LoginBrowser.Designer.cs index 6402c2f..7f350bd 100644 --- a/Windows/LoginBrowser.Designer.cs +++ b/Windows/LoginBrowser.Designer.cs @@ -74,7 +74,7 @@ private void InitializeComponent() this.toolStripButton_Refresh.ImageTransparentColor = System.Drawing.Color.Magenta; this.toolStripButton_Refresh.Name = "toolStripButton_Refresh"; this.toolStripButton_Refresh.Size = new System.Drawing.Size(36, 36); - this.toolStripButton_Refresh.Text = "toolStripButton1"; + this.toolStripButton_Refresh.Text = "Refresh"; this.toolStripButton_Refresh.Click += new System.EventHandler(this.toolStripButton_Refresh_Click); // // LoginBrowser diff --git a/Windows/LoginBrowser.cs b/Windows/LoginBrowser.cs index 99873d9..01fcfe9 100644 --- a/Windows/LoginBrowser.cs +++ b/Windows/LoginBrowser.cs @@ -82,7 +82,14 @@ private void chromiumWebBrowser_FrameLoadEnd(object sender, CefSharp.FrameLoadEn strURL_RequestVerificationToken = strCurrentAddress; } - if (taskHtml.Result.Contains("Be sure to click the prompt above to login to the EVE Online launcher")) + if (taskHtml.Result.Contains("Log in to your account") && !taskHtml.Result.Contains("Invalid username / password")) + { + this.chromiumWebBrowser.EvaluateScriptAsync("document.getElementById('UserName').value = '" + App.strUserName + "';"); + this.chromiumWebBrowser.EvaluateScriptAsync("document.getElementById('Password').value = '" + App.strPassword + "';"); + this.chromiumWebBrowser.EvaluateScriptAsync("document.getElementById('RememberMe').click();"); + this.chromiumWebBrowser.EvaluateScriptAsync("document.forms['loginForm'].submit();"); + } + else if (taskHtml.Result.Contains("Be sure to click the prompt above to login to the EVE Online launcher")) { strHTML_Result = taskHtml.Result; strURL_Result = strCurrentAddress; @@ -98,6 +105,7 @@ private void chromiumWebBrowser_FrameLoadEnd(object sender, CefSharp.FrameLoadEn } }); + } private void LoginBrowser_Resize(object sender, EventArgs e) diff --git a/Windows/LoginBrowser.resx b/Windows/LoginBrowser.resx index cc81fe5..527e628 100644 --- a/Windows/LoginBrowser.resx +++ b/Windows/LoginBrowser.resx @@ -124,38 +124,38 @@ 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 \ No newline at end of file