User permissions, username and domain at login

how can I determine if the current user has administrator or domain Admin user rights on the network. I need a procedure or function that work on win95, win98, WinNT, XP and ME, or alternatively how can I get the username and domain the user is logged onto for a specific computer.

Who is Participating?
Wim ten BrinkConnect With a Mentor Self-employed developerCommented:
win95/98/ME isn't really administrator-aware or domain-aware. User management under these operating systems is nearly non-existant and the little bit it does have is basically sloppy patchwork. Forget about these versions if you need security for your application.
From Windows 2000 there's something called Active Directory that you can easily use by importing the type library from C:\WINNT\system32\activeds.tlb which is probably in your %system% folder somewhere. Through Active Directory you have a good access to the user management of your local system and whatever domain the system is part of. It even allows you to examine other systems on the network if you have proper access rights.

You could also use WMI instead to retrieve the information about users. WMI is available on more systems but not always uptodate. To use WMI into Delphi you have to import the type library C:\WINNT\system32\wbem\wbemdisp.tlb and use that one.

The biggest problem is getting information about the current user, though. Still, all you need access to is the SID of the user. Here's the code:

function GetUserSID: PSID;
  TokenHandle: THandle;
  ReturnLength: DWORD;
  UserToken: PSIDAndAttributes;
  Result := nil;
  if not OpenProcessToken( GetCurrentProcess, TOKEN_ALL_ACCESS, TokenHandle ) then Exception.Create( 'Failed to open token.' );
  ReturnLength := 0;
  UserToken := nil;
  GetTokenInformation( TokenHandle, Tokenuser, UserToken, 0, ReturnLength );
  GetMem( UserToken, ReturnLength );
    if GetTokenInformation( TokenHandle, Tokenuser, UserToken, ReturnLength, ReturnLength ) then begin
      GetMem( Result, GetLengthSid( UserToken.Sid ) );
      CopySid( GetLengthSid( UserToken.Sid ), Result, UserToken.Sid );
    FreeMem( UserToken );

Now, this SID needs to be used properly. (And freed properly! Use FreeSid() fot freeing the SID once you're done with it.) To get the information, use this method:

function SidToUserInfo(const SID: PSID; out UserName, Domain: WideString; out peUse: SID_NAME_USE): Boolean;
  vName, vDomain: array[0..MAX_PATH] of Char;
  cbName, cbDomain: DWORD;
  cbName := SizeOf(vName);
  cbDomain := SizeOf(vDomain);
  if LookupAccountSid(nil, SID, vName, cbName, vDomain, cbDomain, peUse) then begin
    Result := True;
    UserName := string(vName);
    Domain := string(vDomain);
  else begin
    Result := False;
    UserName := SysErrorMessage(GetLastError);
    Domain := '';
    peUse := 0;

Proper usage would be:

  UserName, Domain: WideString;
  peUse: SID_NAME_USE;
  Result := GetComputerName;
  SID := GetUserSID;
  if Assigned(SID) then begin
    if SidToUserInfo(SID, UserName, Domain, peUse) then Result := Domain;

This will provide you the domain name and username of the user that started your process. Still doesn't tell you if the current user is an administrator. Still, you could look him up in WMI or AD. But if you have a SID, you can check if the user is a LOCAL administrator, like this:

function UserIsAdministrator: Boolean;
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  InfoBufferSize: DWORD;
  dwInfoBufferSize: DWORD;
  psidAdministrators: PSID;
  TokenOpen: Boolean;
  Result := False;
  // Get a token.
  TokenOpen := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, hAccessToken);
  if (not TokenOpen) and (GetLastError = ERROR_NO_TOKEN) then begin
    TokenOpen := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hAccessToken);
  if TokenOpen then begin
    // Determine buffer size.
    ptgGroups := nil;
    GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, 0, InfoBufferSize);
    // Allocate memory and retrieve SID.
    GetMem(ptgGroups, InfoBufferSize);
    TokenOpen := GetTokenInformation(hAccessToken, TokenGroups, ptgGroups, InfoBufferSize, dwInfoBufferSize);
    if TokenOpen then begin
      // Create the administrator SID.
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, psidAdministrators);
      {$R-} // No range checking.
      I := 0;
      while (I < ptgGroups.GroupCount) and not EqualSid(psidAdministrators, ptgGroups.Groups[I].Sid) do
      Result := (I < ptgGroups.GroupCount);

But again, this code doesn't work on 95/98/ME since they're not aware of any domain, or SID or whatever...
Try this link:


Download Bill Stewart's 'Windows Admin Script Tools' from

The Readme.txt file contains:

Windows Admin Script Tools
(C) 2001-2004 by Bill Stewart (

These utilities provide a Windows system administrator with several
essential functions that can be particularly useful in logon scripts.

    FVER allows a batch file to perform version checking on a Win32
    executable file, provided it contains version information.

    ISADMIN checks if the currently logged-on user is an administrator
    (Windows NT 4.0 and later). It runs fine on Windows 9x/Me, where the
    current logged on user is always an administrator.

    ISMEMBER can check if the currently logged-on user is a member of one
    or more groups that you can specify on the command line, and it can
    also list group memberships. Requires Windows NT 4.0 or later.

    MINWIN minimizes the topmost window on the screen (useful in logon

    NEEDBOOT determines if there are pending file rename/move/delete
    operations for the next system boot. On Windows 9x/Me, it checks for
    the existence of any entries in the [Rename] section of WININIT.INI; on
    the Windows NT platform, it checks for the existence of the
    PendingFileRenameOperations registry entry. It can also list the
    entries in the [Rename] section or the contents of the registry entry.

    NUPP lets you temporarily map a drive letter, do some things, then
    restore the mapping to its previous value.

    OSVER allows a batch file to perform operating system platform
    checking. It can differentiate between Windows 95, Windows 98, Windows
    Me, Windows NT 4.0, Windows 2000, Windows XP, and Windows Server 2003.
    For NT-based systems, it can also return the system's service pack
    level and role (e.g. workstation, server, or domain controller). For
    Windows NT 4.0 SP6 and later, it can also detect whether the system is
    a Terminal Server (either remote administration mode or application
    server mode).

    RASCONNS allows a batch file to determine if one or more RAS
    connections are active. It can also list active RAS connections and
    determine if a named RAS connection is active.

    Displays a Windows dialog box with a customizable message, buttons and
    icon. A batch file can detect which button was pressed. You can also
    read the dialog box text from a text file and specify a timeout period.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.