Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

How to get domain \ user name?

Posted on 2006-06-08
7
Medium Priority
?
3,441 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
ID: 16867251
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
ID: 16867265
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
ID: 16867270
ah nevermind, rllibby got there :-)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Author Comment

by:jdthedj
ID: 16867346
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:2266180
ID: 16876190
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 500 total points
ID: 16877559

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
ID: 16882145
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

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Integration Management Part 2
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Suggested Courses

886 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