Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How to get domain \ user name?

Posted on 2006-06-08
7
Medium Priority
?
3,362 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

688 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