Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1039
  • Last Modified:

A list of users, currently logged in users, and administrator status

Hi

This is for XP/NT .

For the local machine (not the network), I want to get a list of all users, whether they are running or not, which is the current user, and whether a given user is an administrator.

deep in the api no doubt, but where?

thanks

0
Mutley2003
Asked:
Mutley2003
  • 3
1 Solution
 
mikelittlewoodCommented:
This example uses 2 listboxes, 2 buttons and an edit box.
It will return the list of users on your PC (put computer name in edit box like "\\computername"
If you then select a user from the list generated it will then give you a list of groups they belong to.

Still working on the other bits  :0)

unit Unit1;

interface

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

const
  netapi32 = 'netapi32.dll';

function NetApiBufferFree(Buffer: Pointer): Integer; stdcall; external netapi32 name 'NetApiBufferFree';

const
  MAX_PREFERRED_LENGTH = Cardinal(-1);

type
  PNetDisplayUser = ^TNetDisplayUser;
  TNetDisplayUser = record
    usri1_name: PWideChar;
    usri1_comment: PWideChar;
    usri1_flags: Cardinal;
    usri1_full_name: PWideChar;
    usri1_user_id: Cardinal;
    usri1_next_index: Cardinal;
  end;
  PGroupUsersInfo = ^TGroupUsersInfo;
  TGroupUsersInfo = record
    grui0_name: PWideChar;
  end;

type
  TMainForm = class(TForm)
    ListBoxUsers: TListBox;
    ListBoxGroups: TListBox;
    ButtonUsers: TButton;
    ButtonUserGroups: TButton;
    EditComputer: TEdit;
    procedure ButtonUsersClick(Sender: TObject);
    procedure ButtonUserGroupsClick(Sender: TObject);
  private
    { Private declarations }
  public

  end;

      function NetQueryDisplayInformation(ServerName: PWideChar; Level, Index, EntriesRequested,
      PreferredMaximumLength: Cardinal; var ReturnedEntryCount: Cardinal; var SortedBuffer: Pointer): Integer; stdcall;
      external netapi32 name 'NetQueryDisplayInformation';
    function NetUserGetGroups(servername, username: PWideChar; level: Cardinal; var bufptr: Pointer;
      prefmaxlen: Cardinal; var entriesread, totalentries: Cardinal): Integer; stdcall;
      external netapi32 name 'NetUserGetGroups';

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

procedure GetUsers(const ServerName: string; Users: TStrings);
var
  NetResult: Integer;
  ServerNameW: WideString;
  Index: Integer;
  Returned: Cardinal;
  Buffer: Pointer;
begin
  Users.BeginUpdate;
  try
    Users.Clear;
    ServerNameW := ServerName;
    Returned := 1;
    Index := 0;
    while True do
    begin
      NetResult := NetQueryDisplayInformation(PWideChar(ServerNameW), 1, Index, 1, 1024, Returned, Buffer);
      case NetResult of
        ERROR_SUCCESS, ERROR_MORE_DATA:
          begin
            try
              if Returned = 0 then
                Break;
                with PNetDisplayUser(Buffer)^ do
                begin
                  Index := usri1_next_index;
                  Users.Add(usri1_name);
                end;
            finally
              NetApiBufferFree(Buffer);
            end;
          end;
        else
          raise Exception.CreateFmt('NetQueryDisplayInformation error: %d', [NetResult]);
      end;
    end;
  finally
    Users.EndUpdate;
  end;
end;

procedure GetUserGroups(const ServerName, UserName: string; Groups: TStrings);
var
  ServerNameW, UserNameW: WideString;
  Buffer: Pointer;
  NetResult: Integer;
  Read, Total: Cardinal;
  I: Integer;
  P: PGroupUsersInfo;
begin
  Groups.BeginUpdate;
  try
    Groups.Clear;
    ServerNameW := ServerName;
    UserNameW := UserName;
    NetResult := NetUserGetGroups(PWideChar(ServerNameW), PWideChar(UserNameW), 0, Buffer,
      MAX_PREFERRED_LENGTH, Read, Total);
    case NetResult of
      ERROR_SUCCESS, ERROR_MORE_DATA:
        begin
          try
            P := Buffer;
            for I := 0 to Read - 1 do
              with P^ do
              begin
                Groups.Add(grui0_name);
                Inc(P);
              end;
          finally
            NetApiBufferFree(Buffer);
          end;
        end;
      else
        raise Exception.CreateFmt('NetUserGetGroups error: %d', [NetResult]);
    end;
  finally
    Groups.EndUpdate;
  end;
end;

procedure TMainForm.ButtonUsersClick(Sender: TObject);
begin
  GetUsers(EditComputer.Text, ListBoxUsers.Items);
end;

procedure TMainForm.ButtonUserGroupsClick(Sender: TObject);
begin
  ListBoxGroups.Clear;
  if ListBoxUsers.ItemIndex = -1 then
    Exit;
  GetUserGroups(EditComputer.Text, ListBoxUsers.Items[ListBoxUsers.ItemIndex], ListBoxGroups.Items);
end;

end.
0
 
mikelittlewoodCommented:
Put another listbox and button onto the form and this function will return the current logged on user

procedure TMainForm.GetCurrentUserClick(Sender: TObject);
var
  name: string;
  i: cardinal;
begin
  i := 255;
  SetLength(name,i);
  GetUserName(PChar(name), i);
  SetLength(name,i-1);
  ListBoxCurrUser.Items.Add(name)
end;
0
 
Mutley2003Author Commented:
Thanks Mike

the code works, but with a few interesting issues

1. I get a 1722 if I give it the name of a win 98 machine on the network, this is maybe unsurprising, but since I don't have another xp machine on this network I cannot tell if all is OK XP to XP etc

2. for the local machine (\\virgo), I get "users" as

Administrator  
ASPNET  
Guest  
HelpAssistant  
IUSR_VIRGO  
IWAM_VIRGO  
John Aitchison  
SUPPORT_388945a0  
Tricia Aitchison  

the same thing happens if I call with nil as the first param ie
NetResult := NetQueryDisplayInformation(nil, 1, Index, 1, 1024, Returned, Buffer);
which according to MSDN should give the users from the local machine.

This is very curious. Of these only two are "real" users
ie
John Aitchison  
Tricia Aitchison  
so where did all those other ones come from????


I had an idea so i printed out the flag and comment details and got

Administrator comment= Built-in account for administering the computer/domain flags=66049  
ASPNET comment= Account used for running the ASP.NET worker process (aspnet_wp.exe) flags=66081  
Guest comment= Built-in account for guest access to the computer/domain flags=66081  
HelpAssistant comment= Account for Providing Remote Assistance flags=66051  
IUSR_VIRGO comment= Built-in account for anonymous access to Internet Information Services flags=66081  
IWAM_VIRGO comment= Built-in account for Internet Information Services to start out of process applications flags=66081  
John Aitchison comment= Account upgraded from Windows 98 flags=66081  
SUPPORT_388945a0 comment= This is a vendor's account for the Help and Support Service flags=66051  
Tricia Aitchison comment=  flags=66049  

hmm, it looks like flags of 66049 correspond to  the only "real" users, but that does include Administrator .. that doesn't seem to me to be a "real" user since logging in as  Administrator is not an option at login time and folders like
C:\Documents and Settings\Administrator\FavoritesC:\Documents and Settings\Administrator\Favorites are empty.

3. Any idea how I can detect whether a user is running (aka logged in) or not?

Lots of thanks for your help. I will leave the question open for a little bit to see if there is any more feedback, but  what you have done has been really great.

0
 
mikelittlewoodCommented:
1) Im not sure sorry, not up to date with OS compatibility.
2) Yeah I get a list of other users as well as proper people. Some are system ones like you said, others are ones I havent heard of before.
3) Im not sure how you check if a particular user is logged onto a PC somewhere on the network, only what user is currently on a PC you are looking at.

Hopefully someone else might be able to give you a few more clues.
Glad some of what I gave you is useful.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now