Looking for Delphi 7 code to detect if a program is started with administrator rights?
Asked Answered
E

7

10

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.

Eleanoraeleanore answered 7/6, 2011 at 7:24 Comment(3)
The accepted way to do this is to manifest with require admin any program that needs to write to the program files directory.Backstage
As far as i know, administrator rights ARE enough to create/update files in c:\program files!Kristalkristan
@Andreas: not so, you have to have started your program with the 'Run as admin' option. I have full administrator rights on my development pc, but cannot create/update a file in c:\program files... unless I start it with 'Run ad admin'. Because the same program (a web update program by the way) can be run with or without 'Run as admin' I should be able to check this state.Eleanoraeleanore
A
16

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.

Angilaangina answered 12/6, 2011 at 1:15 Comment(0)
F
10
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.
Fudge answered 16/6, 2011 at 4:35 Comment(0)
E
6

Project JEDI's JEDI Code Library has an IsAdministrator function in the JclSecurity unit that will tell you. It still works in Delphi 7.

Eulalie answered 7/6, 2011 at 13:8 Comment(0)
C
3

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

  1. Checks if there are updates available.
  2. Optionally asks the user if he wants to install the updates.
  3. Downloads the updates to a temporary location.
  4. Runs Updater2.exe with ShellExecuteEx and the 'runas' verb.

Updater2.exe

  1. Will get evalated on UAC if the users confirms the prompt or will not be run at all.
  2. Can then copy the files from the temp location to the final location.

This has several advantages:

  • The Updater2 only contains the minimum operations that have to run elevated.
  • The Updater2 can be part of the files that get downloaded.
  • There is no need to check any privileges, UAC takes care of that.

It also works on Windows XP, you get presented with a login dialog if you are not an admin.

Crenelation answered 17/8, 2011 at 10:57 Comment(0)
A
3

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;
Adnopoz answered 20/4, 2014 at 14:7 Comment(0)
C
2

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.

Caryopsis answered 1/12, 2011 at 9:14 Comment(1)
Sorry for replying to old question, not sure how I got here but didn't noticeCaryopsis
R
1

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;
Romaine answered 8/6, 2011 at 17:11 Comment(2)
This code checks if you are a member of the administrators group. Problem with this code is that you can be a member of the administrators group, but not have any administrative rights. Similarly, you can have administrator rights, but not be a member of the administrators group. This function might better be called IsMemberOfAdministratorsGroup, with the understanding that being part of the administrator's group doesn't mean you have the rights of an administrator.Angilaangina
-1, this function gets pasted over and over again by different ppl and as Ian Boyd already said only check if one is a member of the administrator's group.Caryopsis

© 2022 - 2024 — McMap. All rights reserved.