diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-12-15 16:52:30 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-12-15 16:52:30 +0200 |
| commit | 66be0fdd579050375421ad54dc25cf35bac0845c (patch) | |
| tree | 429ebbf390862a2cc1dcad40aecb96a1399c7ab0 /Software/Visual_Studio/PPC/Tango.PPC.Updater | |
| parent | 97513f619e9778e8409831db04b29b0dcf53f1b9 (diff) | |
| download | Tango-66be0fdd579050375421ad54dc25cf35bac0845c.tar.gz Tango-66be0fdd579050375421ad54dc25cf35bac0845c.zip | |
Implemented several fallbacks to PPC update failure !
Diffstat (limited to 'Software/Visual_Studio/PPC/Tango.PPC.Updater')
3 files changed, 171 insertions, 13 deletions
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Updater/IdentityUtils.cs b/Software/Visual_Studio/PPC/Tango.PPC.Updater/IdentityUtils.cs new file mode 100644 index 000000000..3a43be6f9 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Updater/IdentityUtils.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Updater +{ + public static class IdentityUtils + { + [DllImport("advapi32.dll", SetLastError = true)] + static extern bool GetTokenInformation(IntPtr tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength); + + /// <summary> + /// Passed to <see cref="GetTokenInformation"/> to specify what + /// information about the token to return. + /// </summary> + enum TokenInformationClass + { + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics, + TokenRestrictedSids, + TokenSessionId, + TokenGroupsAndPrivileges, + TokenSessionReference, + TokenSandBoxInert, + TokenAuditPolicy, + TokenOrigin, + TokenElevationType, + TokenLinkedToken, + TokenElevation, + TokenHasRestrictions, + TokenAccessInformation, + TokenVirtualizationAllowed, + TokenVirtualizationEnabled, + TokenIntegrityLevel, + TokenUiAccess, + TokenMandatoryPolicy, + TokenLogonSid, + MaxTokenInfoClass + } + + /// <summary> + /// The elevation type for a user token. + /// </summary> + enum TokenElevationType + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + + public static bool IsElevated() + { + var identity = WindowsIdentity.GetCurrent(); + if (identity == null) throw new InvalidOperationException("Couldn't get the current user identity"); + var principal = new WindowsPrincipal(identity); + + // Check if this user has the Administrator role. If they do, return immediately. + // If UAC is on, and the process is not elevated, then this will actually return false. + //if (principal.IsInRole(WindowsBuiltInRole.Administrator)) return true; + + //// If we're not running in Vista onwards, we don't have to worry about checking for UAC. + //if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major < 6) + //{ + // // Operating system does not support UAC; skipping elevation check. + // return false; + //} + + int tokenInfLength = Marshal.SizeOf(typeof(int)); + IntPtr tokenInformation = Marshal.AllocHGlobal(tokenInfLength); + + try + { + var token = identity.Token; + var result = GetTokenInformation(token, TokenInformationClass.TokenElevationType, tokenInformation, tokenInfLength, out tokenInfLength); + + if (!result) + { + var exception = Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); + throw new InvalidOperationException("Couldn't get token information", exception); + } + + var elevationType = (TokenElevationType)Marshal.ReadInt32(tokenInformation); + + switch (elevationType) + { + case TokenElevationType.TokenElevationTypeDefault: + // TokenElevationTypeDefault - User is not using a split token, so they cannot elevate. + return false; + case TokenElevationType.TokenElevationTypeFull: + // TokenElevationTypeFull - User has a split token, and the process is running elevated. Assuming they're an administrator. + return true; + case TokenElevationType.TokenElevationTypeLimited: + // TokenElevationTypeLimited - User has a split token, but the process is not running elevated. Assuming they're an administrator. + return false; + default: + // Unknown token elevation type. + return false; + } + } + finally + { + if (tokenInformation != IntPtr.Zero) Marshal.FreeHGlobal(tokenInformation); + } + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs index 6615ededf..b821b332b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Updater/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -69,6 +70,22 @@ namespace Tango.PPC.Updater { try { + if (!IdentityUtils.IsElevated()) + { + ShowError("The updater utility is not running under elevated permissions and cannot perform.\nThe process will restart."); + var exeName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + ProcessStartInfo startInfo = new ProcessStartInfo(exeName); + startInfo.Arguments = String.Join(" ", App.StartupArgs); + startInfo.Verb = "runas"; + Process.Start(startInfo); + Environment.Exit(0); + return; + } + } + catch { } + + try + { Init(); EnsureTangoIsDown(); RemoveOldDLLFiles(); @@ -78,30 +95,42 @@ namespace Tango.PPC.Updater DoEvents(); Thread.Sleep(1000); StartTango(true); + Exit(); } catch (Exception ex) { - ShowError($"Update failed.\n{ex.Message}"); - StartTango(false); + if (ShowErrorRetry($"Update failed.\n{ex.Message}")) + { + Update(); + } + else + { + txtStatus.Text = "Update failed. Restoring previous application state..."; + DoEvents(); + Thread.Sleep(1000); + StartTango(false); + Exit(); + } } - finally + } + + private void Exit() + { + try { - try + foreach (var file in Directory.GetFiles(_sourceFolder, "*.*", SearchOption.AllDirectories)) { - foreach (var file in Directory.GetFiles(_sourceFolder, "*.*", SearchOption.AllDirectories)) + try { - try - { - File.Delete(file); - } - catch { } + File.Delete(file); } + catch { } } - catch { } + } + catch { } - Environment.Exit(0); - } + Environment.Exit(0); } private void Init() @@ -137,6 +166,10 @@ namespace Tango.PPC.Updater { p.StartInfo.Arguments = "-update_ok"; } + else + { + p.StartInfo.Arguments = "-update_failed"; + } p.Start(); } @@ -248,5 +281,11 @@ namespace Tango.PPC.Updater { MessageBox.Show(error, "Tango Update", MessageBoxButton.OK, MessageBoxImage.Error); } + + private bool ShowErrorRetry(String error) + { + var result = MessageBox.Show(error + "\n" + "Press yes to retry.", "Tango Update", MessageBoxButton.YesNo, MessageBoxImage.Error); + return result == MessageBoxResult.Yes; + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Updater/Tango.PPC.Updater.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Updater/Tango.PPC.Updater.csproj index 3f232c4d2..ec40d5887 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Updater/Tango.PPC.Updater.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Updater/Tango.PPC.Updater.csproj @@ -67,6 +67,7 @@ <DependentUpon>App.xaml</DependentUpon> <SubType>Code</SubType> </Compile> + <Compile Include="IdentityUtils.cs" /> <Compile Include="MainWindow.xaml.cs"> <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> |
