From 4793541c90be0baee7129bc0c138dbd862bb19b5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 16 Sep 2021 12:13:10 -0500 Subject: [PATCH] Allow reordering tabs when UAC is disabled (#11221) When we're elevated, we disable drag/dropping tabs when elevated, because of a platform limitation that causes the app to _crash_ (see #4874). However, if the user has UAC disabled, this actually works alright. So I'm adding it back in that case. I'm not positive if this is the best way to check if UAC is disabled, but normally, you'll get a [`TokenElevationTypeFull`] when elevated, not `TokenElevationTypeDefault`. If the app is elevated, but there's not a split token, that kinda implies there's no user account separation. If I'm wrong, it's just code, let's replace this with something that does work. ## Validation Steps Performed Booted up a Win10 VM, set `enableLUA` to `0`, rebooted, and checked if this exploded. It didn't. References #4874 References #3581 Work done in pursuit of #11096 Closes #7754 [`TokenElevationTypeFull`]: https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_elevation_type --- src/cascadia/TerminalApp/AppLogic.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index b1b94bc5b..26d7cdb8a 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -10,6 +10,7 @@ #include #include +#include using namespace winrt::Windows::ApplicationModel; using namespace winrt::Windows::ApplicationModel::DataTransfer; @@ -131,17 +132,28 @@ static Documents::Run _BuildErrorRun(const winrt::hstring& text, const ResourceD // Method Description: // - Returns whether the user is either a member of the Administrators group or // is currently elevated. +// - This will return **FALSE** if the user has UAC disabled entirely, because +// there's no separation of power between the user and an admin in that case. // Return Value: // - true if the user is an administrator static bool _isUserAdmin() noexcept try { - SID_IDENTIFIER_AUTHORITY ntAuthority{ SECURITY_NT_AUTHORITY }; - wil::unique_sid adminGroupSid{}; - THROW_IF_WIN32_BOOL_FALSE(AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroupSid)); - BOOL b; - THROW_IF_WIN32_BOOL_FALSE(CheckTokenMembership(NULL, adminGroupSid.get(), &b)); - return !!b; + wil::unique_handle processToken{ GetCurrentProcessToken() }; + const auto elevationType = wil::get_token_information(processToken.get()); + const auto elevationState = wil::get_token_information(processToken.get()); + if (elevationType == TokenElevationTypeDefault && elevationState.TokenIsElevated) + { + // In this case, the user has UAC entirely disabled. This is sort of + // weird, we treat this like the user isn't an admin at all. There's no + // separation of powers, so the things we normally want to gate on + // "having special powers" doesn't apply. + // + // See GH#7754, GH#11096 + return false; + } + + return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS); } catch (...) {