diff --git a/common/Helpers/RuntimeHelper.cs b/common/Helpers/RuntimeHelper.cs index 1e81bd1529..d08bb5dd87 100644 --- a/common/Helpers/RuntimeHelper.cs +++ b/common/Helpers/RuntimeHelper.cs @@ -2,9 +2,13 @@ // Licensed under the MIT License. using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Security.Principal; using Windows.Win32; using Windows.Win32.Foundation; +using Windows.Win32.Security; +using static DevHome.Common.Helpers.RuntimeHelper; namespace DevHome.Common.Helpers; @@ -35,6 +39,35 @@ public static bool IsCurrentProcessRunningAsAdmin() return identity.Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) ?? false; } + // Determine whether the current process is running elevated in a split token session + // will not return true if UAC is disabled and the user is running as administrator by default + public static unsafe bool IsCurrentProcessRunningElevated() + { + HANDLE tokenHandle; + if (!PInvoke.OpenProcessToken(PInvoke.GetCurrentProcess(), TOKEN_ACCESS_MASK.TOKEN_QUERY, &tokenHandle)) + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + + try + { + TOKEN_ELEVATION_TYPE elevationType; + uint elevationTypeSize = (uint)Unsafe.SizeOf(); + uint returnLength; + + if (!PInvoke.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, &elevationType, elevationTypeSize, &returnLength)) + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + + return elevationType == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; + } + finally + { + PInvoke.CloseHandle(tokenHandle); + } + } + public static void VerifyCurrentProcessRunningAsAdmin() { if (!IsCurrentProcessRunningAsAdmin()) diff --git a/common/NativeMethods.txt b/common/NativeMethods.txt index acddcf3dab..342d739925 100644 --- a/common/NativeMethods.txt +++ b/common/NativeMethods.txt @@ -11,6 +11,9 @@ GetWindowLong WINDOW_EX_STYLE SHLoadIndirectString StrFormatByteSizeEx +OpenProcessToken +GetTokenInformation +GetCurrentProcess SFBS_FLAGS MAX_PATH GetDpiForWindow @@ -18,4 +21,5 @@ GetWindowRect GetMonitorInfo SetWindowPos MonitorFromWindow -E_INVALIDARG \ No newline at end of file +E_INVALIDARG +TOKEN_ELEVATION_TYPE \ No newline at end of file diff --git a/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs b/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs index 1525cfcdfd..09e8bfa5e1 100644 --- a/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs +++ b/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs @@ -46,8 +46,8 @@ public Visibility GetNoWidgetMessageVisibility(int widgetCount, bool isLoading) return (widgetCount == 0 && !isLoading && HasWidgetServiceInitialized) ? Visibility.Visible : Visibility.Collapsed; } - public bool IsRunningAsAdmin() + public bool IsRunningElevated() { - return RuntimeHelper.IsCurrentProcessRunningAsAdmin(); + return RuntimeHelper.IsCurrentProcessRunningElevated(); } } diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs index f30eeb6c4a..378e8968bb 100644 --- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs +++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs @@ -195,8 +195,8 @@ private void UnsubscribeFromWidgets() private async Task ValidateDashboardState() { - // Ensure we're not running as admin. Display an error and don't allow using the Dashboard if we are. - if (ViewModel.IsRunningAsAdmin()) + // Ensure we're not running elevated. Display an error and don't allow using the Dashboard if we are. + if (ViewModel.IsRunningElevated()) { _log.Error($"Dev Home is running as admin, can't show Dashboard"); RunningAsAdminMessageStackPanel.Visibility = Visibility.Visible;