Skip to content

Commit 58bc654

Browse files
committed
Allow shutdown even if limited admin doesn't have shutdown privilege
Shutdown privilege can be removed from users (in Local Security Policy settings). This will remove it also from limited admin. Thus admin will be unable to shutdown machine (because Explorer runs as limited admin by default). In such case we will attempt to do silent elevation and proceed with shutdown using `SystemSettingsAdminFlows.exe` helper. Fixes #1015
1 parent c541032 commit 58bc654

File tree

1 file changed

+52
-7
lines changed

1 file changed

+52
-7
lines changed

Src/StartMenu/StartMenuDLL/MenuCommands.cpp

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,24 @@ static INT_PTR CALLBACK RenameDlgProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, L
6161
return FALSE;
6262
}
6363

64-
static void SetShutdownPrivileges( void )
64+
static bool SetShutdownPrivileges()
6565
{
66+
bool retval = false;
67+
6668
HANDLE hToken;
67-
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
69+
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
6870
{
6971
TOKEN_PRIVILEGES tp={1};
70-
if (LookupPrivilegeValue(NULL,L"SeShutdownPrivilege",&tp.Privileges[0].Luid))
71-
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
72-
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL);
72+
if (LookupPrivilegeValue(NULL, L"SeShutdownPrivilege", &tp.Privileges[0].Luid))
73+
{
74+
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
75+
if (AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL) && GetLastError() == ERROR_SUCCESS)
76+
retval = true;
77+
}
7378
CloseHandle(hToken);
7479
}
80+
81+
return retval;
7582
}
7683

7784
static void DoSearchSubst( wchar_t *buf, int size, const wchar_t *search )
@@ -658,6 +665,23 @@ class ExitGuard
658665
bool m_bArmed;
659666
};
660667

668+
static TOKEN_ELEVATION_TYPE GetCurrentTokenElevationType()
669+
{
670+
TOKEN_ELEVATION_TYPE retval = TokenElevationTypeDefault;
671+
672+
HANDLE token;
673+
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
674+
{
675+
TOKEN_ELEVATION_TYPE elevationType;
676+
DWORD returnLength;
677+
if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &returnLength) && returnLength == sizeof(elevationType))
678+
retval = elevationType;
679+
680+
CloseHandle(token);
681+
}
682+
683+
return retval;
684+
}
661685

662686
static bool ExecuteShutdownCommand(TMenuID menuCommand)
663687
{
@@ -714,8 +738,29 @@ static bool ExecuteShutdownCommand(TMenuID menuCommand)
714738

715739
if (flags)
716740
{
717-
SetShutdownPrivileges();
718-
InitiateShutdown(NULL, NULL, 0, flags, SHTDN_REASON_FLAG_PLANNED);
741+
if (SetShutdownPrivileges())
742+
{
743+
InitiateShutdown(NULL, NULL, 0, flags, SHTDN_REASON_FLAG_PLANNED);
744+
}
745+
else
746+
{
747+
// we don't have shutdown rights
748+
// lets try silent elevate via SystemSettingsAdminFlows (for limited admin users only)
749+
if (GetCurrentTokenElevationType() == TokenElevationTypeLimited)
750+
{
751+
wchar_t cmdLine[32]{};
752+
Sprintf(cmdLine, _countof(cmdLine), L"Shutdown %d %d", flags, SHTDN_REASON_FLAG_PLANNED);
753+
754+
SHELLEXECUTEINFO sei{};
755+
sei.cbSize = sizeof(sei);
756+
sei.lpFile = L"%systemroot%\\system32\\SystemSettingsAdminFlows.exe";
757+
sei.lpParameters = cmdLine;
758+
sei.lpVerb = L"runas";
759+
sei.fMask = SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI;
760+
761+
ShellExecuteEx(&sei);
762+
}
763+
}
719764

720765
return true;
721766
}

0 commit comments

Comments
 (0)