Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (12)


How to retrieve Current User and Domain Names on Windows NTGo to Serhiy Perevoznyk's websiteFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi all versions
Category:
Win API
Skill Level:
Scoring:
Last Update:
04/01/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet Windows NT Domain Username
Times Scored:
5
Visits:
13161
Uploader: Serhiy Perevoznyk
Company: http://users.chello.be/ws36637
Reference: N/A
 
Question/Problem/Abstract:
A program may sometimes need to display the user name and domain name for the current thread. This article demonstrates how to do this on Windows NT by using security functions within the Win32 Application Programming Interface (API).
Answer:



A program may sometimes need to display the user name and domain name for the current thread. This article demonstrates how to do this on Windows NT by using security functions within the Win32 Application Programming Interface (API). Prior to Windows NT, it could be assumed that a thread was running under the account of the interactively logged on user. Windows NT, however, allows threads to run under multiple security contexts, potentially representing multiple users. For instance, in a client/server application, a thread in the server might impersonate a client through the ImpersonateNamedPipeClient function. In this case, it runs under the user context of the client. Another example of a thread running in a different security context is a service thread, which has a domain name of NT AUTHORITY and a user name of SYSTEM, assuming that the service is running in the local system account.
If you need to obtain both the user name and the domain name for the current thread, you must first extract the user's security identifier (SID) from the thread's access token by using the GetTokenInformation function. Then, a call to the LookupAccountSid function can be used to retrieve the account name and domain name associated with the SID.
The following sample code demonstrates how to programmatically retrieve the user name and domain name on Windows NT:

//**********************************************************************
//
//  FUNCTION:     GetCurrentUserAndDomain - This function looks up
//                the user name and domain name for the user account
//                associated with the calling thread.
//
//  PARAMETERS:   szUser - a buffer that receives the user name
//                pcchUser - the size, in characters, of szUser
//                szDomain - a buffer that receives the domain name
//                pcchDomain - the size, in characters, of szDomain
//
//  RETURN VALUE: TRUE if the function succeeds. Otherwise, FALSE and
//                GetLastError() will return the failure reason.
//
//                If either of the supplied buffers are too small,
//                GetLastError() will return ERROR_INSUFFICIENT_BUFFER
//                and pcchUser and pcchDomain will be adjusted to
//                reflect the required buffer sizes.
//
//**********************************************************************

function GetCurrentUserAndDomain(szUser : PChar;   pcchUser : DWORD;
       szDomain : PChar;  pcchDomain: DWORD) : boolean;

var
   fSuccess : boolean;
   hToken   : THandle;
   ptiUser  : PSIDAndAttributes;
   cbti     : DWORD;
   snu      : SID_NAME_USE;

begin
   ptiUser := nil;
   Result := false;

   try
      // Get the calling thread's access token.
      if (not OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
            hToken)) then

       begin
         if (GetLastError() <> ERROR_NO_TOKEN) then
            exit;

         // Retry against process token if no thread token exists.
         if (not OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
               hToken)) then
            exit;
       end;

      // Obtain the size of the user information in the token.
      if (GetTokenInformation(hToken, TokenUser, nil, 0, cbti)) then

         // Call should have failed due to zero-length buffer.
         Exit

       else

         // Call should have failed due to zero-length buffer.
         if (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) then
            Exit;


      // Allocate buffer for user information in the token.
      ptiUser :=  HeapAlloc(GetProcessHeap(), 0, cbti);
      if (ptiUser= nil) then
         Exit;

      // Retrieve the user information from the token.
      if ( not GetTokenInformation(hToken, TokenUser, ptiUser, cbti, cbti)) then
         Exit;

      // Retrieve user name and domain name based on user's SID.
      if ( not LookupAccountSid(nil, ptiUser.Sid, szUser, pcchUser,
            szDomain, pcchDomain, snu)) then
         Exit;

      fSuccess := TRUE;

   finally

      // Free resources.
      if (hToken > 0) then
         CloseHandle(hToken);

      if (ptiUser <> nil) then
         HeapFree(GetProcessHeap(), 0, ptiUser);
   end;

   Result :=  fSuccess;
end;






Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Win NT, Win 2k
    Maarten de Haan (Apr 9 2003 8:53AM)

Do you know the "windows"-version (or Win-API version) of the DOS command: "net user /domain"? This would be a great help for me! Thanks in advance!
Respond

RE: Win NT, Win 2k
Serhiy Perevoznyk (Apr 11 2003 9:12PM)

Function GetUsers(Users : TStringList) : boolean;
type
  PnetResourceArr = ^TNetResource;
Var
  NetResource : TNetResource;
  Buf         : Pointer;
  Count,
  BufSize,
  Res         : DWord;
  Ind         : Integer;
  lphEnum     : THandle;
  Temp        : PNetResourceArr;
Begin
  Result := False;
  GetMem(Buf, 8192);
  Try
    FillChar(NetResource, SizeOf(NetResource), 0);
    NetResource.lpRemoteName := @fServer[1];
    NetResource.dwDisplayType := RESOURCEDISPLAYTYPE_SERVER;
    NetResource.dwUsage := RESOURCEUSAGE_CONTAINER;
    NetResource.dwScope := RESOURCETYPE_DISK;
    Res := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_CONTAINER, @NetResource,lphEnum);
    If Res <> 0 Then Exit;
    While True Do
    Begin
      Count := $FFFFFFFF;
      BufSize := 8192;
      Res := WNetEnumResource(lphEnum, Count, Pointer(Buf), BufSize);
      If Res = ERROR_NO_MORE_ITEMS Then Exit;
      If (Res <> 0) then Exit;
      Temp := PNetResourceArr(Buf);
      For Ind := 0 to Count - 1 do
      Begin
        Users.Add(Temp^.lpRemoteName + 2);
        Inc(Temp);
      End;
    End;
    Res := WNetCloseEnum(lphEnum);
    If Res <> 0 Then Raise Exception(Res);
    Result := True;
  Finally
    FreeMem(Buf);
  End;
End;
Respond

RE: RE: Win NT, Win 2k
Maarten de Haan (Apr 15 2003 10:27AM)

Thanks! But what is fServer? I have declared it as a string, but that gave as only username: "Microsoft Windows Network". I just want to have all the names in my domain. The same what: "NET USER /DOMAIN" does. (At this moment I start a DOS-box, which issues the command: NET USER /DOMAIN>TEMPFILE.TXT and then I wait until the file is ready, and then in windows it reads the (formatted) file in a listbox, which is shown in the program.
Respond

RE: RE: RE: Win NT, Win 2k
anonymus (Apr 15 2003 8:56PM)

Name of the server or domain

You can download a component - it will be more easy to use:
http://users.chello.be/ws36637/download/netusers.zip

Respond

RE: RE: RE: RE: Win NT, Win 2k
Maarten de Haan (Apr 17 2003 8:15AM)

Maybe I am a bit stupid, but how do I get the name of my server? In 'NET USER /DOMAIN' I do not have to fill in a server name. Thanks!
Respond

How to do it step by step
Serhiy Perevoznyk (Apr 17 2003 8:31PM)

First, we will need some API functions:

Const
   NERR_Success = 0;

function NetApiBufferAllocate (ByteCount: DWORD; var Buffer: Pointer): DWORD; stdcall; external 'netapi32.dll';
function NetGetDCName(servername: LPCWSTR; domainname: LPCWSTR;
  bufptr: Pointer): DWORD; stdcall; external 'netapi32.dll';
function NetApiBufferFree (Buffer: Pointer): DWORD ; stdcall; external 'netapi32.dll';
Function NetWkstaGetInfo
        (ServerName : LPWSTR;
         Level      : DWORD;
         BufPtr     : Pointer) : Longint; Stdcall;
                external 'netapi32.dll' Name 'NetWkstaGetInfo';

function NetUserEnum(servername: LPCWSTR; level: DWORD; filter: DWORD;
  var bufptr: Pointer; prefmaxlen: DWORD; var entriesread: DWORD;
  var totalentries: DWORD; resume_handle: PDWORD): DWORD; stdcall; external 'netapi32.dll';

type
  WKSTA_INFO_100   = Record
      wki100_platform_id  : DWORD;
      wki100_computername : LPWSTR;
      wki100_langroup     : LPWSTR;
      wki100_ver_major    : DWORD;
      wki100_ver_minor    : DWORD;
                            End;

   LPWKSTA_INFO_100 = ^WKSTA_INFO_100;

  _USER_INFO_0  = record
    usri0_name: LPWSTR;
  end;
  TUserInfo0 = _USER_INFO_0;

function GetNetParam(AParam : integer) : string;
Var
  PBuf  : LPWKSTA_INFO_100;
  Res   : LongInt;
begin
  result := '';
  Res := NetWkstaGetInfo (Nil, 100, @PBuf);
  If Res = NERR_Success Then
    begin
      case AParam of
       0:   Result := string(PBuf^.wki100_computername);
       1:   Result := string(PBuf^.wki100_langroup);
      end;
    end;
end;

Respond

Computer and domain names
Serhiy Perevoznyk (Apr 17 2003 8:32PM)

function GetComputerName : string;
begin
  Result := GetNetParam(0);
end;

function GetDomainName : string;
begin
  Result := GetNetParam(1);
end;

function GetDomainControllerName(const ADomainName : string) : string;
var
  wDomainName : WideString;
  Controller : PWideChar;
begin
  wDomainName := AdomainName;
  NetGetDCName (Nil, PWideChar (wDomainName), @Controller);
  Result := WideCharToString(controller);
  NetAPIBufferFree (Controller);
end;

Respond

Function to get list of the users
Serhiy Perevoznyk (Apr 17 2003 8:37PM)

procedure GetUsers(Users : TStringList; AServer : string);
type
  TUserInfoArr = array[0..(MaxInt - 4) div SizeOf(TUserInfo0)] of TUserInfo0;
var
  UserInfo: Pointer;
  EntriesRead, TotalEntries, ResumeHandle: DWORD;
  Res: DWORD;
  i: Integer;
  FServer : WideString;
begin
  FServer :=  AServer;
  ResumeHandle := 0;
  repeat
    Res := NetUserEnum(PWideChar(FServer), 0, 0, UserInfo, 64 * SizeOf(TUserInfo0),
      EntriesRead, TotalEntries, @ResumeHandle);
    if (Res = NERR_SUCCESS) or (Res = ERROR_MORE_DATA) then
    begin
      for i := 0 to EntriesRead - 1 do
        Users.Add(TUserInfoArr(UserInfo^)[i].usri0_name);
      NetApiBufferFree(UserInfo);
    end;
  until Res <> ERROR_MORE_DATA;
end;

This function still need the name of the the server.
You can do next:
1. GetUsers(MyList, GetComputerName)
2. Obtain domain name using GetDomainName function
3. Obtain information about primary domain controller for selecting domain using function GetDomainControllerName
4. GetUsers(MyList, DomainController)

5. To add new user:
function NetUserAdd(servername: LPCWSTR; level: DWORD; buf: Pointer;   parm_err: PDWORD): dword; stdcall; external 'netapi32.dll';
6. To delete user:
function NetUserDel(servername: LPCWSTR; username: LPCWSTR): DWORD; stdcall; external 'netapi32.dll';

Respond

Where to find more information
Serhiy Perevoznyk (Apr 17 2003 8:41PM)

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/network_management_functions.asp?frame=true
Respond

RE: Where to find more information
Julien Albrecht (Apr 22 2003 10:40AM)

Good morning from France guys,
All those informations are very interesting and usefull.
but could you plaese do a summary .

Thanks
Respond

RE: RE: Where to find more information
Serhiy Perevoznyk (Apr 22 2003 10:36PM)

http://www.delphi3000.com/articles/article_3637.asp
Respond

RE: RE: RE: RE: Win NT, Win 2k
rainamaji (Sep 15 2004 7:57AM)

domaincontraller niwin nt

Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
S. Kucherov
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)