Reputation: 5058
I am looking for working (obviously) Delphi 7 code so I can check whether my program is started with administrator rights.
Thanks in advance
[--- IMPORTANT UPDATE ---]
Having reviewed the code in the answers so far, I realise that my question maybe is not so clear, or at least is not complete:
I want to know whether my Delphi 7 program is started with the 'Run as admin' check box set.
In other words: I want to know whether it is possible for my Delphi 7 program to create/update files in the c:\Program Files... folders.
Just checking if you have administrator rights is not enough for this.
Upvotes: 10
Views: 12091
Reputation: 256581
The Windows API (used) to have a helper function (IsUserAnAdmin) to tell if you are running with administrative privileges.
OS Account Type UAC IsUserAdmin
============== ============= ============ ===========
Windows XP Standard n/a False
Windows XP Administrator n/a True
Windows Vista Standard Disabled False
Windows Vista Administrator Disabled True
Windows Vista Standard Not Elevated False
Windows Vista Administrator Not Elevated False
Windows Vista Standard Elevated True
Windows Vista Administrator Elevated True
The Shell32 wrapper function is deprecated; which is fine because it was just a wrapper around other code, which you can still call yourself:
function IsUserAdmin: Boolean;
var
b: BOOL;
AdministratorsGroup: PSID;
begin
{
This function returns true if you are currently running with admin privileges.
In Vista and later, if you are non-elevated, this function will return false
(you are not running with administrative privileges).
If you *are* running elevated, then IsUserAdmin will return true, as you are
running with admin privileges.
Windows provides this similar function in Shell32.IsUserAnAdmin.
But the function is deprecated, and this code is lifted
from the docs for CheckTokenMembership:
http://msdn.microsoft.com/en-us/library/aa376389.aspx
}
{
Routine Description: This routine returns TRUE if the callers
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
}
b := AllocateAndInitializeSid(
SECURITY_NT_AUTHORITY,
2, //2 sub-authorities
SECURITY_BUILTIN_DOMAIN_RID, //sub-authority 0
DOMAIN_ALIAS_RID_ADMINS, //sub-authority 1
0, 0, 0, 0, 0, 0, //sub-authorities 2-7 not passed
AdministratorsGroup);
if (b) then
begin
if not CheckTokenMembership(0, AdministratorsGroup, b) then
b := False;
FreeSid(AdministratorsGroup);
end;
Result := b;
end;
In other words: This function gives you the answer you want: Can the user update Program Files.
You need to be weary of code that check if you're a member of the Administrator's group. You can be part of the Administrator's group, but not have any administrative privileges. You can also have administrative privileges, but not be part of the Administrator's group.
Upvotes: 16
Reputation: 1611
I tested this code with Delphi 7, on Windows XP, 7 and 8 (admin and limited accounts):
Function CheckTokenMembership(TokenHandle: THandle; SIdToCheck: PSID; var IsMember: Boolean): Boolean; StdCall; External AdvApi32;
Function IsAdmin: Boolean;
const
DOMAIN_ALIAS_RID_ADMINS = $00000220;
SECURITY_BUILTIN_DOMAIN_RID = $00000020;
SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
var
Admin: Boolean;
AdmGroup: PSID;
Begin
Admin := AllocateAndInitializeSid(SECURITY_NT_AUTHORITY,
2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0, AdmGroup);
If (Admin) Then
Begin
If (not CheckTokenMembership(0, AdmGroup, Admin)) Then
Admin := False;
FreeSid(AdmGroup);
end;
Result := Admin;
end;
Upvotes: 3
Reputation: 7330
Jwscl (The Jedi Windows Security Library) has a function for this: JwCheckAdministratorAccess.
function JwCheckAdministratorAccess: boolean;
usage is very simple:
Uses
JwsclToken;
IsElevated := JwCheckAdministratorAccess;
This function works also in Windows Vista and later if UAC is enabled. If the current process is not elevated the return value is false even if the token contains the administrators group (which is disabled then). This function detects a group membership in the administrator group which means that the user don't need to be in the administrators group directly instead a group can be a member of the administrators group.
Upvotes: 2
Reputation: 14873
The Microsoft recommended way to solve this issue: Split the application into two.
http://msdn.microsoft.com/en-us/library/aa511445.aspx
The first app checks whether it is necessary to run the second one.
The second app contains a "require admin" manifest (like David wrote) and you open it with the ShellExecuteEx 'runas' verb.
In case of a web updater the workflow could be like this:
Updater1.exe
Updater2.exe
This has several advantages:
It also works on Windows XP, you get presented with a login dialog if you are not an admin.
Upvotes: 3
Reputation: 1938
program Project1;
{$APPTYPE CONSOLE}
uses
Windows,
ShellAPI;
// high-level wrapper, see Ian Boyd's answer for details on this function
function IsUserAnAdmin(): BOOL; external shell32;
begin
if IsUserAnAdmin() then
Writeln('TEH R00T OMG')
else
Writeln('rtfmnoobkthx');
Readln;
end.
Upvotes: 10
Reputation: 13454
This code works under D7..XE inc.
function IsWindowsAdministrator: Boolean;
// Returns TRUE if the user has administrator priveleges
// Returns a boolean indicating whether or not user has admin
// privileges. Call only when running under NT. Win9.x will return false!
var
hAccessToken : tHandle;
ptgGroups : pTokenGroups;
dwInfoBufferSize : DWORD;
psidAdministrators : PSID;
int : integer; // counter
blnResult : boolean; // return flag
const
SECURITY_NT_AUTHORITY: SID_IDENTIFIER_AUTHORITY =
(Value: (0,0,0,0,0,5)); // ntifs
SECURITY_BUILTIN_DOMAIN_RID: DWORD = $00000020;
DOMAIN_ALIAS_RID_ADMINS: DWORD = $00000220;
DOMAIN_ALIAS_RID_USERS : DWORD = $00000221;
DOMAIN_ALIAS_RID_GUESTS: DWORD = $00000222;
DOMAIN_ALIAS_RID_POWER_: DWORD = $00000223;
begin
Result := False;
blnResult := OpenThreadToken( GetCurrentThread, TOKEN_QUERY,
True, hAccessToken );
if ( not blnResult ) then
begin
if GetLastError = ERROR_NO_TOKEN then
blnResult := OpenProcessToken( GetCurrentProcess,
TOKEN_QUERY, hAccessToken );
end;
ptgGroups := nil;
if ( blnResult ) then
try
GetMem(ptgGroups, 1024);
blnResult := GetTokenInformation( hAccessToken, TokenGroups,
ptgGroups, 1024,
dwInfoBufferSize );
CloseHandle( hAccessToken );
if ( blnResult ) then
begin
AllocateAndInitializeSid( SECURITY_NT_AUTHORITY, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
psidAdministrators );
{$IFOPT R+}
{$DEFINE RMINUS}
{$R-}
{$ENDIF}
for int := 0 to ptgGroups.GroupCount - 1 do
if EqualSid( psidAdministrators,
ptgGroups.Groups[ int ].Sid ) then
begin
Result := True;
Break;
end;
{$IFDEF IMINUS}
{$R-}
{$UNDEF IMINUS}
{$ENDIF}
FreeSid( psidAdministrators );
end;
finally
If ptgGroups <> nil then
FreeMem( ptgGroups );
end;
end;
Upvotes: 1
Reputation: 125620
Project JEDI's JEDI Code Library has an IsAdministrator function in the JclSecurity unit that will tell you. It still works in Delphi 7.
Upvotes: 6