From f4710f5a8114c5d4db7e1289b288ead00853644a Mon Sep 17 00:00:00 2001 From: ThiconZ Date: Sun, 9 Apr 2017 19:58:45 -0400 Subject: [PATCH] Updated to version 1.0.0.3 Properly error handle events when the user does not have access to WAR.exe or the dependency files - Now prompts to restart the launcher as Administrator to gain file access - Now prompts to automatically remove the Read-Only attribute on all files in the game directory to gain write access Added two new launch arguments --CustomDeps and --CheckDepHash details are in the README.md New method of dependency version checking - Now checks by file version number instead of hash Minor code optimizations Launcher version updated to 1.0.0.3 --- README.md | 13 +- RoRLauncher/Client.cs | 25 ++++ RoRLauncher/MainWindow.xaml.cs | 191 ++++++++++++++++++++----- RoRLauncher/Properties/AssemblyInfo.cs | 4 +- RoRLauncher/deps/MYPHandler.dll | Bin 25088 -> 23552 bytes 5 files changed, 189 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index fc887b6..33ba10c 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,22 @@ This project is an attempt to provide a better, open source, alternative to the ![Screenshot](http://i.imgur.com/YTGiy1M.png) -It features the following over the current official one as of Feb 27 2017: +It features the following over the current official launcher as of Apr 9 2017: * Added a minimize button to the main window * On successful game start, the launcher will automatically minimize * On game exit, the launcher will automatically restore to the screen -* Users can start the game multiple times within the same launcher session. +* Users can start the game multiple times within the same launcher session * Ex. if a user launches the game, exits the game, they can click Connect to launch the game again without issues * Greatly improved the error handling * Added better dependency file handling and checks + * By default it will allow the user to have dependency files with a higher file version number than the embedded ones without attempting to replace them with the embedded files. * Added launch arguments * --Debug starts the launcher and begins exporting debug information to 3 files in the current directory, an application configuration file named RoR_Configs.txt, a DxDiag report named RoR_DxDiag.txt, and an MSInfo32 report named RoR_MSInfo.txt. - * --NoErrors will suppress most error popup windows and some error messages, but continue to give short error text messages on the main window for critical messages -* Bug fixes for numerous issues including the Connect button not always working + * --NoErrors will suppress most error popup windows and some error messages, but continue to give short error text messages on the main window for critical messages. + * --CustomDeps disables dependency file checking. This will assume the user has all the required dependency files and that they will work with the launcher. + * --CheckDepHash enables the old method of dependency file hash comparisons instead of file version comparisons to determine if an embedded dependency file needs to replace an external dependency file. This can be helpful if a user wants to make sure their external dependency files are identical to the ones that come embedded. +* Bug fixes and optimizations for numerous issues including the Connect button not always working * Cleaned up the window interfaces from the developer perspective in visual studio (fixes some issues at the same time) +* Uses a new Mythic Patch Handler (MYPHandler) that no longer requires Performance Counters + * This is also open source and can be found [here](https://github.com/ThiconZ/Mythic-Patch-Handler). diff --git a/RoRLauncher/Client.cs b/RoRLauncher/Client.cs index 4b177c2..0a11c4b 100644 --- a/RoRLauncher/Client.cs +++ b/RoRLauncher/Client.cs @@ -474,6 +474,31 @@ public static void Handle(PacketIn packet) // Minimize the launcher once the game process is started MainWindow.mainWindow.ModifyWindowState(System.Windows.WindowState.Minimized); } + catch (System.UnauthorizedAccessException ex) + { + if (MainWindow.mainWindow.NoErrorMode == false) + Client.Popup("Access to WAR.exe is denied. Please obtain access permissions to the Warhammer directory and files and try again: " + Environment.NewLine + ex.ToString()); + else + Client.Print("Error starting game. User lacks file access permissions"); + + // Prompt the user to restart the launcher as admin - this normally fixes this error + if (MainWindow.mainWindow.IsAdministrator() == false) + { + if (System.Windows.MessageBox.Show("Running the launcher as Administrator may resolve this error. Would you like to restart it as Administrator now?", "Restart as Administrator", System.Windows.MessageBoxButton.YesNo) == System.Windows.MessageBoxResult.Yes) + { + MainWindow.mainWindow.RestartAsAdmin(); + } + } + else + { + if (System.Windows.MessageBox.Show("Removing the Read-Only attribute from files in the game directory may resolve this error. Would you like to remove this attribute and restart the application now? Note this will also restart the application as Administrator.", "Remove Read-Only Attribute", System.Windows.MessageBoxButton.YesNo) == System.Windows.MessageBoxResult.Yes) + { + // User must have read/write access to the directory for this to be allowed + MainWindow.mainWindow.RemoveReadOnly(new DirectoryInfo(System.IO.Directory.GetCurrentDirectory())); + MainWindow.mainWindow.RestartAsAdmin(); + } + } + } catch (System.Exception ex) { if (MainWindow.mainWindow.NoErrorMode == false) diff --git a/RoRLauncher/MainWindow.xaml.cs b/RoRLauncher/MainWindow.xaml.cs index c46c215..17173ef 100644 --- a/RoRLauncher/MainWindow.xaml.cs +++ b/RoRLauncher/MainWindow.xaml.cs @@ -7,6 +7,7 @@ using System.Net; using System.Reflection; using System.Security.Cryptography; +using System.Security.Principal; using System.Text; using System.Windows; using System.Windows.Controls; @@ -33,6 +34,10 @@ public partial class MainWindow : Window public bool NoErrorMode = false; + public bool CustomDependencyMode = false; + + public bool CheckDependencyHashes = false; + internal string Error { get @@ -104,18 +109,7 @@ private void worker_DownloadXMLCompleted(object sender, RunWorkerCompletedEventA } else { - XElement arg_170_0; - if (this.doc.Descendants("News").Count() <= 0) - { - arg_170_0 = null; - } - else - { - arg_170_0 = (from n in this.doc.Descendants("News") - orderby (uint)n.Element("Id") descending - select n).First(); - } - XElement xElement2 = arg_170_0; + XElement xElement2 = this.doc.Descendants((XName)"News").Count() > 0 ? this.doc.Descendants((XName)"News").OrderByDescending((Func)(n => (uint)n.Element((XName)"Id"))).First() : (XElement)null; if (xElement2 != null) { this.PatchTitle.Text = (string)xElement2.Element("Date"); @@ -210,19 +204,60 @@ byte[] ComputeDependencyHash(string fileName) } } - private bool CheckForDependency(string fileName) + /// + /// Compares the Internal and External dependecy file versions. + /// + /// Complete file name and extension of the dependency. Must be the same internally and externally. + /// Returns False if Internal version is grater than or equal to External version. + private bool CompareDependencyFileVersion(string fileName) + { + // Load the dependency files in a way that won't lock them from future use + + FileVersionInfo externalFile = FileVersionInfo.GetVersionInfo(Directory.GetCurrentDirectory() + "/" + fileName); + Version externalVersion = new Version(externalFile.FileVersion); + + Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("RoRLauncher.deps." + fileName); + byte[] bytes = new byte[stream.Length]; + stream.Read(bytes, 0, bytes.Length); + stream.Close(); + stream.Dispose(); + Version internalVersion = new Version(Assembly.ReflectionOnlyLoad(bytes).GetName().Version.ToString()); + + // Returns false if internal file version is greater than or equal to the external file + if (internalVersion >= externalVersion) + { + return false; + } + + return true; + } + + /// + /// Check if dependency file already exists. If it does, determine if it should be replaced by the internal dependency file. + /// + /// Complete file name and extension of the dependency. Must be the same internally and externally. + /// The check be done based on file hashes and not file versions. + /// Returns False if the file should be replaced. + private bool CheckForDependency(string fileName, bool hashCheck = false) { // Check if the files we're going to unpack already exist in the current location if (File.Exists(Directory.GetCurrentDirectory() + "/" + fileName) == true) { - // If the files are here, do an md5 check to see if they are the right versions before unpacking new ones - // Could change this to be a file version check instead if we want to allow the user to have a modified version of the file as long as it meets the version number requirements - byte[] externalHash; - byte[] internalHash; - externalHash = ComputeFileHash(Directory.GetCurrentDirectory() + "/" + fileName); - internalHash = ComputeDependencyHash(fileName); + if (hashCheck == false) + { + // If CompareDependencyFileVersion is false then we should replace the external file with the internal one + return CompareDependencyFileVersion(fileName); + } + else + { + // If the files are here, do an md5 check to see if they are the right versions before unpacking new ones + byte[] externalHash; + byte[] internalHash; + externalHash = ComputeFileHash(Directory.GetCurrentDirectory() + "/" + fileName); + internalHash = ComputeDependencyHash(fileName); - return externalHash.SequenceEqual(internalHash); + return externalHash.SequenceEqual(internalHash); + } } else { @@ -234,15 +269,15 @@ private void worker_Unpack(object sender, DoWorkEventArgs e) { // Do safe unpacking of dependencies // If one happens to be locked open in another program and is the right version it will still work this way, previously it would throw an error - if (CheckForDependency("HashDictionary.dll") == false) + if (CheckForDependency("HashDictionary.dll", CheckDependencyHashes) == false) { this.Unpack("HashDictionary.dll"); } - if (CheckForDependency("MYPHandler.dll") == false) + if (CheckForDependency("MYPHandler.dll", CheckDependencyHashes) == false) { this.Unpack("MYPHandler.dll"); } - if (CheckForDependency("ICSharpCode.SharpZipLib.dll") == false) + if (CheckForDependency("ICSharpCode.SharpZipLib.dll", CheckDependencyHashes) == false) { this.Unpack("ICSharpCode.SharpZipLib.dll"); } @@ -300,12 +335,6 @@ public MainWindow() // Pull status/connection information from the server this.ConnectToServers(); - // Unpack required library dependencies to the current directory - // NOTE: these are never cleaned up by the program - maybe it should try to delete them when closed? - BackgroundWorker backgroundWorker2 = new BackgroundWorker(); - backgroundWorker2.DoWork += new DoWorkEventHandler(this.worker_Unpack); - backgroundWorker2.RunWorkerAsync(); - // Make sure the mainWindow is created and visible before moving onto command line options // Without this errors will occur from the Debug mode option mainWindow.Show(); @@ -325,6 +354,25 @@ public MainWindow() { NoErrorMode = true; } + // The user is claiming to be running custom dependency libs so we should not check if internal ones should be unpacked + else if (option.ToLower().Contains("--customdeps") == true) + { + CustomDependencyMode = true; + } + // User wants to have the dependency files checked by hashes and not versions + else if (option.ToLower().Contains("--checkdephash") == true) + { + CheckDependencyHashes = true; + } + } + + // Unpack required library dependencies to the current directory + // NOTE: these are never cleaned up by the program - maybe it should try to delete them when closed? + if(CustomDependencyMode == false) + { + BackgroundWorker backgroundWorker2 = new BackgroundWorker(); + backgroundWorker2.DoWork += new DoWorkEventHandler(this.worker_Unpack); + backgroundWorker2.RunWorkerAsync(); } } @@ -480,11 +528,9 @@ private void PATCH_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { - double num = double.Parse(e.BytesReceived.ToString()); - double num2 = double.Parse(e.TotalBytesToReceive.ToString()); - double num3 = num / num2 * 100.0; - this.ProgressBarFiller.Width = (double)((int)System.Math.Floor(num3 * 469.0 / 100.0)); - this.ProgressText.Text = System.Math.Truncate(num3).ToString() + "%"; + double progress = (double.Parse(e.BytesReceived.ToString()) / double.Parse(e.TotalBytesToReceive.ToString())) * 100.0; + this.ProgressBarFiller.Width = (double)((int)System.Math.Floor(progress * 469.0 / 100.0)); + this.ProgressText.Text = System.Math.Truncate(progress).ToString() + "%"; } private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) @@ -588,8 +634,29 @@ private bool Unpack(string fileName) catch (System.Exception arg) { this.Popup("Error unpacking:" + Environment.NewLine + arg); - bool result = false; - return result; + + if (arg is UnauthorizedAccessException) + { + // Prompt the user to restart the launcher as admin - this normally fixes this error + if (IsAdministrator() == false) + { + if (System.Windows.MessageBox.Show("Running the launcher as Administrator may resolve this error. Would you like to restart it as Administrator now?", "Restart as Administrator", System.Windows.MessageBoxButton.YesNo) == System.Windows.MessageBoxResult.Yes) + { + MainWindow.mainWindow.RestartAsAdmin(); + } + } + else + { + if (System.Windows.MessageBox.Show("Removing the Read-Only attribute from files in the game directory may resolve this error. Would you like to remove this attribute and restart the application now? Note this will also restart the application as Administrator.", "Remove Read-Only Attribute", System.Windows.MessageBoxButton.YesNo) == System.Windows.MessageBoxResult.Yes) + { + // User must have read/write access to the directory for this to be allowed + RemoveReadOnly(new DirectoryInfo(System.IO.Directory.GetCurrentDirectory())); + MainWindow.mainWindow.RestartAsAdmin(); + } + } + } + + return false; } try { @@ -600,8 +667,7 @@ private bool Unpack(string fileName) catch (System.Exception arg2) { this.Popup("Error unpacking 2:" + Environment.NewLine + arg2); - bool result = false; - return result; + return false; } return true; } @@ -678,5 +744,54 @@ private void CreateFullDebugDump() Error = "Error creating dump files. --NoErrors was set on the command-line, remove it and run the launcher again for the full error message."; } } + + public void RestartAsAdmin() + { + // This is required to prevent a critical error that prevents this from finishing + Client._Socket.Shutdown(System.Net.Sockets.SocketShutdown.Send); + + Client._Socket.Close(); + Client._Socket.Dispose(); + Client.Close(); + var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + ProcessStartInfo startInfo = new ProcessStartInfo(exeName); + startInfo.Verb = "runas"; + startInfo.Arguments = Environment.CommandLine; + System.Diagnostics.Process.Start(startInfo); + + // If something stopped Shutdown, force an unclean exit because we don't care anymore + try + { + Application.Current.Shutdown(); + } + catch + { + Process.GetCurrentProcess().Kill(); + } + return; + } + + public bool IsAdministrator() + { + WindowsIdentity identity = WindowsIdentity.GetCurrent(); + WindowsPrincipal principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } + + public void RemoveReadOnly(DirectoryInfo directory) + { + if (directory != null) + { + directory.Attributes = FileAttributes.Normal; + foreach (FileInfo file in directory.GetFiles()) + { + file.Attributes = FileAttributes.Normal; + } + foreach (DirectoryInfo dir in directory.GetDirectories()) + { + RemoveReadOnly(dir); + } + } + } } } diff --git a/RoRLauncher/Properties/AssemblyInfo.cs b/RoRLauncher/Properties/AssemblyInfo.cs index 4a5e3c4..3c8063f 100644 --- a/RoRLauncher/Properties/AssemblyInfo.cs +++ b/RoRLauncher/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.2")] -[assembly: AssemblyFileVersion("1.0.0.2")] +[assembly: AssemblyVersion("1.0.0.3")] +[assembly: AssemblyFileVersion("1.0.0.3")] diff --git a/RoRLauncher/deps/MYPHandler.dll b/RoRLauncher/deps/MYPHandler.dll index d48397e8fa464fd1365133df01b2e1d5712deb39..db07a5a81593fd894aa6d9c66f91d5122e2ccffd 100644 GIT binary patch literal 23552 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 xZ8zVN^X<4%+H}L#e6pCp%