My application needs a function to check if the Current User is allowed to elevate a process (run as Admin). The function IsUserAnAdmin()
does only tell me if the process is already elevated but in my case it is not.
Are there any other options to determine if the User is able to elevate a Process (is an admin)?
for check current elevation status we can query TOKEN_ELEVATION_TYPE
of current process with TokenElevationType
:
TokenElevationTypeFull
- we already run elevated.TokenElevationTypeLimited
- we run under limited token, but haveTokenElevationTypeDefault
- we have no linked token. here exist 2
case:
we already elevated (for check this use
TokenElevation
and
look for TokenIsElevated
from TOKEN_ELEVATION
) this can be if we run under built-in admin account
(DOMAIN_ALIAS_RID_ADMINS
500 ) which is not filtered, or UAC is disabled in system.
we run not under admin account. we can elevate in this case also, but only under another account. for this need know this account password
demo code:
inline ULONG BTE(BOOL f)
{
return f ? 0 : GetLastError();
}
void TryElevate()
{
WCHAR path[MAX_PATH];
if (GetModuleFileNameW(0, path, RTL_NUMBER_OF(path)))
{
SHELLEXECUTEINFOW sei = { sizeof(sei), 0, 0, L"runas", path };
ShellExecuteExW(&sei);
}
}
ULONG CheckElevation()
{
HANDLE hToken;
ULONG err = BTE(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken));
if (!err)
{
ULONG cb = 0, rcb = 0x20;
union {
PTOKEN_USER ptu;
PVOID buf;
};
static volatile UCHAR guz;
PVOID stack = alloca(guz);
PWSTR SzSid = 0;
//++ for display user sid only
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (!(err = BTE(GetTokenInformation(hToken, ::TokenUser, buf, cb, &rcb))))
{
ConvertSidToStringSidW(ptu->User.Sid, &SzSid);
break;
}
} while (err == ERROR_INSUFFICIENT_BUFFER);
// -- for display user sid only
union {
TOKEN_ELEVATION te;
TOKEN_ELEVATION_TYPE tet;
};
if (!(err = BTE(GetTokenInformation(hToken, ::TokenElevationType, &tet, sizeof(tet), &rcb))))
{
switch (tet)
{
case TokenElevationTypeDefault:
if (!(err = BTE(GetTokenInformation(hToken, ::TokenElevation, &te, sizeof(te), &rcb))))
{
if (te.TokenIsElevated)
{
// we are built-in admin or UAC is disabled in system
case TokenElevationTypeFull:
MessageBoxW(HWND_DESKTOP, L"we run elevated", SzSid, MB_ICONINFORMATION);
break;
}
// we can not elevate under same user, but still can elevate under another admin account
// non admin account
TryElevate();
MessageBoxW(HWND_DESKTOP, L"Default", SzSid, MB_ICONINFORMATION);
}
break;
case TokenElevationTypeLimited:
// this mean that we have linked token, which is elevated. we can elevate under same user
TryElevate();
MessageBoxW(HWND_DESKTOP, L"Limited", SzSid, MB_ICONINFORMATION);
break;
default:
MessageBoxW(HWND_DESKTOP, L"unknown elevation type", SzSid, MB_ICONWARNING);
err = ERROR_GEN_FAILURE;
}
}
if (SzSid) LocalFree(SzSid);
CloseHandle(hToken);
}
return err;
}
and result: