"Always run as administrator" and "Restart as ..." only for administrator account (#1318)

This commit is contained in:
Yevhenii Holovachov 2020-02-18 21:56:34 +02:00 committed by GitHub
parent e177c5c94c
commit 607a297c4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 5 deletions

View File

@ -6,6 +6,8 @@
#include <sddl.h>
#include "version.h"
#pragma comment(lib, "advapi32.lib")
namespace localized_strings
{
const wchar_t LAST_ERROR_FORMAT_STRING[] = L"%s failed with error %d: %s";
@ -539,3 +541,72 @@ std::wstring get_module_folderpath(HMODULE mod)
PathRemoveFileSpecW(buffer);
return { buffer, (UINT)lstrlenW(buffer) };
}
// The function returns true in case of error since we want to return false
// only in case of a positive verification that the user is not an admin.
bool check_user_is_admin()
{
auto freeMemory = [](PSID pSID, PTOKEN_GROUPS pGroupInfo) {
if (pSID)
{
FreeSid(pSID);
}
if (pGroupInfo)
{
GlobalFree(pGroupInfo);
}
};
HANDLE hToken;
DWORD dwSize = 0, dwResult = 0;
PTOKEN_GROUPS pGroupInfo;
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
PSID pSID = NULL;
// Open a handle to the access token for the calling process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
return true;
}
// Call GetTokenInformation to get the buffer size.
if (!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize))
{
dwResult = GetLastError();
if (dwResult != ERROR_INSUFFICIENT_BUFFER)
{
return true;
}
}
// Allocate the buffer.
pGroupInfo = (PTOKEN_GROUPS)GlobalAlloc(GPTR, dwSize);
// Call GetTokenInformation again to get the group information.
if (!GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize))
{
freeMemory(pSID, pGroupInfo);
return true;
}
// Create a SID for the BUILTIN\Administrators group.
if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID))
{
freeMemory(pSID, pGroupInfo);
return true;
}
// Loop through the group SIDs looking for the administrator SID.
for (DWORD i = 0; i < pGroupInfo->GroupCount; ++i)
{
if (EqualSid(pSID, pGroupInfo->Groups[i].Sid))
{
freeMemory(pSID, pGroupInfo);
return true;
}
}
freeMemory(pSID, pGroupInfo);
return false;
}

View File

@ -71,6 +71,9 @@ bool run_non_elevated(const std::wstring& file, const std::wstring& params);
// Run command with the same elevation, returns true if succedded
bool run_same_elevation(const std::wstring& file, const std::wstring& params);
// Returns true if the current process is running from administrator account
bool check_user_is_admin();
// Get the executable path or module name for modern apps
std::wstring get_process_path(DWORD pid) noexcept;
// Get the executable path or module name for modern apps

View File

@ -40,6 +40,7 @@ json::JsonObject GeneralSettings::to_json()
result.SetNamedValue(L"is_elevated", json::value(isElevated));
result.SetNamedValue(L"run_elevated", json::value(isRunElevated));
result.SetNamedValue(L"is_admin", json::value(isAdmin));
result.SetNamedValue(L"theme", json::value(theme));
result.SetNamedValue(L"system_theme", json::value(systemTheme));
result.SetNamedValue(L"powertoys_version", json::value(powerToysVersion));
@ -65,6 +66,7 @@ GeneralSettings get_settings()
.isPackaged = winstore::running_as_packaged(),
.isElevated = is_process_elevated(),
.isRunElevated = run_as_elevated,
.isAdmin = check_user_is_admin(),
.theme = settings_theme,
.systemTheme = WindowsColors::is_dark_mode() ? L"dark" : L"light",
.powerToysVersion = get_product_version(),

View File

@ -10,6 +10,7 @@ struct GeneralSettings
std::unordered_map<std::wstring, bool> isModulesEnabledMap;
bool isElevated;
bool isRunElevated;
bool isAdmin;
std::wstring theme;
std::wstring systemTheme;
std::wstring powerToysVersion;

View File

@ -133,12 +133,15 @@ export class GeneralSettings extends React.Component <any, any> {
ref={(input) => {this.startup_reference=input;}}
/>
</Stack>
<BoolToggleSettingsControl
{this.state.settings.general.is_admin &&
(<BoolToggleSettingsControl
setting={{display_name: 'Always run as administrator', value: this.state.settings.general.run_elevated}}
on_change={this.parent_on_change}
ref={(input) => {this.elevated_reference=input;}}
/>
<CustomActionSettingsControl
/>)
}
{this.state.settings.general.is_admin &&
(<CustomActionSettingsControl
setting={{
display_name: '',
value: this.state.settings.general.is_elevated ?
@ -160,7 +163,8 @@ export class GeneralSettings extends React.Component <any, any> {
}));
}}
ref={(input) => {this.restart_reference=input;}}
/>
/>)
}
<ChoiceGroupSettingsControl
setting={{display_name: 'Chose Settings color',
value: this.state.settings.general.theme,

File diff suppressed because one or more lines are too long