One of the things promised, which are on the Internet somewhere, but sometimes hard to find, was a code snippet which reliably returns, whether the program is started in administrative mode or not. This piece of code is similar to old known solutions, however under Vista the old version returned the user level, rather than the token under which the program was started. The following code works well under Windows Vista and older systems.
const
SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
DOMAIN_ALIAS_RID_ADMINS = $00000220;
SE_GROUP_ENABLED = $00000004;
function IsAdmin: Boolean;
var
hAccessToken: THandle;
ptgGroups: PTokenGroups;
dwInfoBufferSize: DWORD;
psidAdministrators: PSID;
x: Integer;
bSuccess: BOOL;
begin
Result := False;
bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, hAccessToken);
if not bSuccess then
if GetLastError = ERROR_NO_TOKEN then
bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
if bSuccess then
begin
GetTokenInformation(hAccessToken, TokenGroups, nil, 0, dwInfoBufferSize);
ptgGroups := GetMemory(dwInfoBufferSize);
bSuccess := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, dwInfoBufferSize, dwInfoBufferSize);
CloseHandle(hAccessToken);
if bSuccess then
begin
AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdministrators);
for x := 0 to ptgGroups.GroupCount - 1 do
begin
if (SE_GROUP_ENABLED = (ptgGroups.Groups[x].Attributes and SE_GROUP_ENABLED)) and EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then
begin
Result := True;
Break;
end;
end;
FreeSid(psidAdministrators);
end;
FreeMem(ptgGroups);
end;
end;
Thanks to Olaf for pointing out the insufficient memory problem. Fixed in this sample.