Solved

How to get domain \ user name?

Posted on 2006-06-08
7
3,100 Views
Last Modified: 2010-08-05
Hi

I need to be able to obtain the domain\ user name of the logged in user (not just the current username or machine name) on a local computer.  I have looked at an answer provided by rlibby here:

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20127992.html

but I cannot get it to work because there is a discrepancy between actual and formal var parameters for all the API calls.

Please help!

John
0
Comment
Question by:jdthedj
  • 2
  • 2
  • 2
  • +1
7 Comments
 
LVL 26

Expert Comment

by:Russell Libby
Comment Utility
John,

The code is pretty old, and was written on D3. The errors come from the Integer types changing to DWORD, which is now LongWord in later versions of Delphi. Anyways, cleaned up version that should run fine. Let me know if you have further issues.

Regards,
Russell

Example with function:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1         = class(TForm)
     Button1:    TButton;
     procedure   Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
 SID_AND_ATTRIBUTES   =  packed record
    Sid:           PSID;
    Attributes:    DWORD;
 end;

type
 PTOKEN_USER          =  ^TOKEN_USER;
 TOKEN_USER           =  packed record
    User:          SID_AND_ATTRIBUTES;
 end;

function GetDomainUserName(var UserName: String): Boolean;

var
  Form1: TForm1;

implementation
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var  szUser:     String;
begin

  if GetDomainUserName(szUser) then ShowMessage(szUser);

end;

function GetDomainUserName(var UserName: String): Boolean;
var  hToken:     THandle;
     bSuccess:   Boolean;
     lpInfo:     PTOKEN_USER;
     lpUser:     Array [0..512] of Char;
     cbUser:     DWORD;
     lpDomain:   Array [0..512] of Char;
     cbDomain:   DWORD;
     cbInfo:     DWORD;
     snu:        SID_NAME_USE;
begin

  // Set default result
  result:=True;

  // Clear passed string
  SetLength(UserName, 0);

  // Attempt to open the thread token
  if not(OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True, hToken)) then
  begin
     // Failed, see why it failed
     if (GetLastError = ERROR_NO_TOKEN) then
        result:=OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, hToken)
     else
        result:=False;
  end;

  // Check result
  if result then
  begin
     // Buffer size
     cbInfo:=1024;
     // Allocate memory
     lpInfo:=AllocMem(cbInfo);
     // Resource protection
     try
        // Get token information
        if (GetTokenInformation(hToken, TokenUser, lpInfo, cbInfo, cbInfo)) then
        begin
           // Set buffer var sizes
           cbUser:=SizeOf(lpUser);
           cbDomain:=SizeOf(lpDomain);
           // Lookup account
           if LookupAccountSid(nil, lpInfo^.User.Sid, lpUser, cbUser, lpDomain, cbDomain, snu) then
              UserName:=Format('%s\%s', [lpDomain, lpUser])
           else
              result:=False;
        end
        else
           result:=False;
     finally
        // Free memory
        FreeMem(lpInfo, 1024);
        // Close token handle
        CloseHandle(hToken);
     end;
  end;

end;

end.
0
 
LVL 17

Expert Comment

by:TheRealLoki
Comment Utility
I think you just need to change the types to cardinal

function GetDomainUserName(lpBuff: PChar; var cbBuff: Integer): Integer;
var  hToken:     cardinal;
     bSuccess:   longbool;
     lpInfo:     PTOKEN_USER;
     lpUser:     Array [0..512] of Char;
     cbUser:     cardinal;
     lpDomain:   Array [0..512] of Char;
     cbDomain:   cardinal;
     cbInfo:     cardinal;
     snu:        SID_NAME_USE;
begin
0
 
LVL 17

Expert Comment

by:TheRealLoki
Comment Utility
ah nevermind, rllibby got there :-)
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 3

Author Comment

by:jdthedj
Comment Utility
Thanks Russell.  

Unfortunately I have asked the wrong question.  

What I need is the name from the server under "Active Directory Users and Computers" which also shows on the local computer at the top of the form that appears when you click the Start button.
John
0
 
LVL 28

Expert Comment

by:ciuly
Comment Utility
take a look at this article: http://www.agnisoft.com/white_papers/active_directory.asp
it's about adsi with delphi
I took this snipet from there:
var obj : Variant;
begin
 obj := ADsHlp.GetObject('WinNT://AGNISOFT/Deepak'); // bind to the object
 obj.Put( 'FullName', 'Deepak'); // set properties
 obj.SetInfo;
 obj := NULL; // release the object
end;
and I think that changing it to:

var obj : Variant; fn:variant;
begin
  obj := ADsHlp.GetObject('WinNT://AGNISOFT/Deepak'); // bind to the object
  obj.GetInfo;
  fn := obj.Get( 'FullName'); // set properties
  obj := NULL; // release the object
  showmessage(fn);
end;

it should work. I am not on a domain right here an some of my services are disabled (for security reasons) so I cannot test this. but from the looks of it, it should work.
(you'll have to download the example code from the begining of the article: it contains the helper unit adshlp)
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 125 total points
Comment Utility

Another way of doing it, modified from a paq I worked on (changed from buffer type 1 to buffer type 3). You are interested in the FullName property of the item.

Russell

----

Example first, then source unit:

var  uiItem:        TUserInfoItem;
     dwIndex:       Integer;
begin

  // Create the collection
  with TUserInfo.Create do
  begin
     try
        // Get current user record
        dwIndex:=CurrentUser;
        // Access the item
        uiItem:=Items[dwIndex];
        // Display some info
        ShowMessage(Format('User: "%s"'#13#10'Full name: is "%s"'#13#10'Password was created/modified on %s',
                    [uiItem.Name, uiItem.FullName, FormatDateTime('mmm dd, yy - hh:nn:ss', uiItem.PasswordDate)]));
     finally
        // Free the collection
        Free;
     end;
  end;

end;

---- UserInfo ----

unit UserInfo;
////////////////////////////////////////////////////////////////////////////////
//
//   Unit           :  UserInfo
//   Author         :  rllibby
//   Date           :  07.28.2005
//   Description    :  Implements an object class that can be used to iterate
//                     the local computer users and their related info.
//
////////////////////////////////////////////////////////////////////////////////
interface

////////////////////////////////////////////////////////////////////////////////
//   Include units
////////////////////////////////////////////////////////////////////////////////
uses
  Windows,
  SysUtils,
  Classes;

////////////////////////////////////////////////////////////////////////////////
//   NetApi32 structures
////////////////////////////////////////////////////////////////////////////////
type
  _USER_INFO_3            =  packed record
     usri3_name:          PWideChar;
     usri3_password:      PWideChar;
     usri3_password_age:  DWORD;
     usri3_priv:          DWORD;
     usri3_home_dir:      PWideChar;
     usri3_comment:       PWideChar;
     usri3_flags:         DWORD;
     usri3_script_path:   PWideChar;
     usri3_auth_flags:    DWORD;
     usri3_full_name:     PWideChar;
     usri3_usr_comment:   PWideChar;
     usri3_parms:         PWideChar;
     usri3_workstations:  PWideChar;
     usri3_last_logon:    DWORD;
     usri3_last_logoff:   DWORD;
     usri3_acct_expires:  DWORD;
     usri3_max_storage:   DWORD;
     usri3_units_per_week:DWORD;
     usri3_logon_hours:   Pointer;
     usri3_bad_pw_count:  DWORD;
     usri3_num_logons:    DWORD;
     usri3_logon_server:  PWideChar;
     usri3_country_code:  DWORD;
     usri3_code_page:     DWORD;
     usri3_user_id:       DWORD;
     usri3_pri_group_id:  DWORD;
     usri3_profile:       PWideChar;
     usri3_home_dir_drive:PWideChar;
     usri3_pwd_expired:   DWORD;
  end;
  USER_INFO_3             =  _USER_INFO_3;
  PUSER_INFO_3            =  ^USER_INFO_3;
  LPUSER_INFO_3           =  PUSER_INFO_3;

  _USER_INFO_1            =  packed record
     usri1_name:          PWideChar;
     usri1_password:      PWideChar;
     usri1_password_age:  DWORD;
     usri1_priv:          DWORD;
     usri1_home_dir:      PWideChar;
     usri1_comment:       PWideChar;
     usri1_flags:         DWORD;
     usri1_script_path:   PWideChar;
  end;
  USER_INFO_1             =  _USER_INFO_1;
  PUSER_INFO_1            =  ^USER_INFO_1;
  LPUSER_INFO_1           =  PUSER_INFO_1;

////////////////////////////////////////////////////////////////////////////////
//   NetApi32 helper structures
////////////////////////////////////////////////////////////////////////////////
type
  USER_INFO_1_ARRAY       =  Array [0..Pred(MaxWord)] of USER_INFO_1;
  LPUSER_INFO_1_ARRAY     =  ^USER_INFO_1_ARRAY;
  USER_INFO_3_ARRAY       =  Array [0..Pred(MaxWord)] of USER_INFO_3;
  LPUSER_INFO_3_ARRAY     =  ^USER_INFO_3_ARRAY;

////////////////////////////////////////////////////////////////////////////////
//   NetApi32 constants
////////////////////////////////////////////////////////////////////////////////
const
  FILTER_NORMAL_ACCOUNT   =  $02;
  MAX_PREFERRED_LENGTH    =  DWORD(-1);

////////////////////////////////////////////////////////////////////////////////
//   NetApi32 functions
////////////////////////////////////////////////////////////////////////////////
function   NetApiBufferFree(Buffer: Pointer): Integer; stdcall; external 'netapi32.dll';
function   NetUserEnum(servername: PWideChar; level: DWORD; filter: DWORD; var bufptr: Pointer;
                       prefmaxlen: DWORD; var entriesread: DWORD; var totalentries: DWORD;
                       var resume_handle: DWORD): Integer; stdcall; external 'netapi32.dll' name 'NetUserEnum';

////////////////////////////////////////////////////////////////////////////////
//   UserInfoItem class
////////////////////////////////////////////////////////////////////////////////
type
  TUserInfoItem     =  class(TCollectionItem)
  private
     // Private declarations
     FComment:      String;
     FHomeDirectory:String;
     FPassword:     String;
     FPasswordDate: TDateTime;
     FFullName:     String;
     FName:         String;
  protected
     // Protected declarations
     procedure      LoadInfoBuffer(InfoBuffer: USER_INFO_3);
  public
     // Public declarations
     constructor    Create(Collection: TCollection); override;
     property       Comment: String read FComment;
     property       FullName: String read FFullName;
     property       HomeDirectory: String read FHomeDirectory;
     property       Password: String read FPassword;
     property       PasswordDate: TDateTime read FPasswordDate;
     property       Name: String read FName;
  end;

////////////////////////////////////////////////////////////////////////////////
//   UserInfo class
////////////////////////////////////////////////////////////////////////////////
type
  TUserInfo         =  class(TCollection)
  private
     // Private declarations
     function       GetItem(Index: Integer): TUserInfoItem;
     procedure      SetItem(Index: Integer; Value: TUserInfoItem);
  protected
     // Protected declarations
     procedure      LoadUserInfo;
  public
     // Public declarations
     constructor    Create;
     function       Add: TUserInfoItem;
     function       CurrentUser: Integer;
     procedure      Refresh;
     property       Items[Index: Integer]: TUserInfoItem read GetItem write SetItem; default;
  end;

////////////////////////////////////////////////////////////////////////////////
//   Utility Functions
////////////////////////////////////////////////////////////////////////////////
function   StringFromLPWSTR(Value: PWideChar): String;
function   DateTimeFromOffset(Value: DWORD): TDateTime;

implementation

//// Utility Functions /////////////////////////////////////////////////////////
function StringFromLPWSTR(Value: PWideChar): String;
begin

  if Assigned(Value) then
     result:=WideCharToString(Value)
  else
     SetLength(result, 0);

end;

function DateTimeFromOffset(Value: DWORD): TDateTime;
var  tsOffset:      TTimeStamp;
     dtOffset:      TDateTime;
     wValues:       Array [0..3] of Word;
begin

  // Start with current date time
  result:=Now;

  // Split the seconds into days and milliseconds
  tsOffset:=MSecsToTimeStamp(Value * 1000);

  // Subtract the number of days from today
  result:=result-tsOffset.Date;

  // Split the milliseconds into hours, min, sec, and msecs
  wValues[0]:=tsOffset.Time div 3600000;
  tsOffset.Time:=tsOffset.Time mod 3600000;
  wValues[1]:=tsOffset.Time div 60000;
  tsOffset.Time:=tsOffset.Time mod 60000;
  wValues[2]:=tsOffset.Time div 1000;
  wValues[3]:=tsOffset.Time mod 1000;

  // Encode into a time value
  dtOffset:=EncodeTime(wValues[0], wValues[1], wValues[2], wValues[3]);

  // Subtract from the date
  result:=result-dtOffset;

end;

//// TUserInfoItem /////////////////////////////////////////////////////////////
procedure TUserInfoItem.LoadInfoBuffer(InfoBuffer: USER_INFO_3);
begin

  // Set values from buffer
  FName:=StringFromLPWSTR(InfoBuffer.usri3_name);
  FFullName:=StringFromLPWSTR(InfoBuffer.usri3_full_name);
  FComment:=StringFromLPWSTR(InfoBuffer.usri3_comment);
  FHomeDirectory:=StringFromLPWSTR(InfoBuffer.usri3_home_dir);
  FPassword:=StringFromLPWSTR(InfoBuffer.usri3_password);
  FPasswordDate:=DateTimeFromOffset(InfoBuffer.usri3_password_age);

end;

constructor TUserInfoItem.Create(Collection: TCollection);
begin

  // Perform inherited
  inherited Create(Collection);

  // Set defaults
  SetLength(FComment, 0);
  SetLength(FHomeDirectory, 0);
  SetLength(FPassword, 0);
  SetLength(FName, 0);
  FPasswordDate:=0;

end;

//// TUserInfo /////////////////////////////////////////////////////////////////
procedure TUserInfo.LoadUserInfo;
var  uiItem:        TUserInfoItem;
     pBuf:          LPUSER_INFO_3_ARRAY;
     pTmpBuf:       LPUSER_INFO_3_ARRAY;
     nStatus:       Integer;
     dwPrefMaxLen:  DWORD;
     dwEntriesRead: DWORD;
     dwTotalEntries:DWORD;
     dwResumeHandle:DWORD;
     dwIndex:       Integer;
begin

  // Clear existing items
  Clear;

  // Set defaults
  pBuf:=nil;
  dwPrefMaxLen:=MAX_PREFERRED_LENGTH;
  dwEntriesRead:=0;
  dwTotalEntries:=0;
  dwResumeHandle:=0;

  // Resource protection
  try
     // Repeat until all data is obtained or we error out
     repeat
        nStatus:=NetUserEnum(nil, 3, FILTER_NORMAL_ACCOUNT, Pointer(pBuf), dwPrefMaxLen, dwEntriesRead, dwTotalEntries, dwResumeHandle);
        // If the call succeeds,
        if ((nStatus = 0) or (nStatus = ERROR_MORE_DATA)) then
        begin
           // Save pointer off
           pTmpBuf:=pBuf;
           // Check temp pointer
           if Assigned(pTmpBuf) then
           begin
              // Loop through the entries.
              for dwIndex:=0 to Pred(dwEntriesRead) do
              begin
                 // Create the item and have it load the buffer
                 uiItem:=Add;
                 // Load the buffer
                 uiItem.LoadInfoBuffer(pTmpBuf[dwIndex]);
              end;
           end;
        end;
        // Check buffer
        if Assigned(pBuf) then
        begin
           // Free allocated buffer
           NetApiBufferFree(pBuf);
           // Clear pointer
           pBuf:=nil;
        end;
     // Continue until error or all entries are processed
     until (nStatus <> ERROR_MORE_DATA);
  finally
     // Check buffer for clearing
     if Assigned(pBuf) then NetApiBufferFree(pBuf);
  end;

end;

function TUserInfo.CurrentUser: Integer;
var  lpszUser:      Array [0..128] of Char;
     dwSize:        DWORD;
     dwIndex:       Integer;
begin

  // Set default result
  result:=(-1);

  // Set buffer size
  dwSize:=SizeOf(lpszUser);

  // Get user name
  if GetUserName(lpszUser, dwSize) then
  begin
     // Null terminate
     lpszUser[dwSize]:=#0;
     // Set starting index
     dwIndex:=0;
     // Iterate the user list and find the index of the item
     while (dwIndex < Count) do
     begin
        // Check item against user
        if (CompareText(Items[dwIndex].Name, lpszUser) = 0) then
        begin
           // Set result
           result:=dwIndex;
           // Done processing
           break;
        end;
        // Next item
        Inc(dwIndex);
     end;
  end;

end;

function TUserInfo.Add: TUserInfoItem;
begin

  // Add
  result:=TUserInfoItem(inherited Add);

end;

function TUserInfo.GetItem(Index: Integer): TUserInfoItem;
begin

  // Get the item at index
  result:=TUserInfoItem(inherited GetItem(Index));

end;

procedure TUserInfo.SetItem(Index: Integer; Value: TUserInfoItem);
begin

  // Set the item at index
  inherited SetItem(Index, Value);

end;

procedure TuserInfo.Refresh;
begin

  // Reload the user information
  LoadUserInfo;

end;

constructor TUserInfo.Create;
begin

  // Perfom inherited
  inherited Create(TUserInfoItem);

  // Load the user info
  LoadUserInfo;

end;

end.
0
 
LVL 3

Author Comment

by:jdthedj
Comment Utility
Thanks Russell and Ciuly.

I appreciate the help from both of you.  I have accepted Russell's answer because he also tried to help when I asked the question ambiguously, and also I do not have to download other files to make it work,

John
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now