?
Solved

NT Administrator accounts listing

Posted on 2003-03-09
15
Medium Priority
?
1,216 Views
Last Modified: 2010-08-05
I need Delphi code for listing the usernames in the machines local Administrators Group.
It would be also usefull if I can list the local 'power users' as well.

Can anyone Help!
cheers!
Darren
0
Comment
Question by:dhnkley
[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
  • 8
  • 6
15 Comments
 
LVL 21

Expert Comment

by:ziolko
ID: 8100995
following code extracts all usernames:

type
  PNET_DISPLAY_USER = ^NET_DISPLAY_USER;
  NET_DISPLAY_USER = record
    usri1_name: LPCWSTR;
    usri1_comment: LPCWSTR;
    usri1_flags: DWORD;
    usri1_full_name: LPCWSTR;
    usri1_user_id: DWORD;
    usri1_next_index: DWORD;
  end;

  PNET_DISPLAY_MACHINE = ^NET_DISPLAY_MACHINE;
  NET_DISPLAY_MACHINE = record
    usri2_name: LPCWSTR;
    usri2_comment: LPCWSTR;
    usri2_flags: DWORD;
    usri2_user_id: DWORD;
    usri2_next_index: DWORD;
  end;

  PNET_DISPLAY_GROUP = ^NET_DISPLAY_GROUP;
  NET_DISPLAY_GROUP = record
    grpi3_name: LPCWSTR;
    grpi3_comment: LPCWSTR;
    grpi3_group_id: DWORD;
    grpi3_attributes: DWORD;
    grpi3_next_index: DWORD;
  end;


const
        LIB_NAME = 'NetAPI32.DLL';
        BUFF_CLEAR = 'NetApiBufferFree';
        NET_QUERY_DISPINFO = 'NetQueryDisplayInformation';

type

  TNetAPIBufferFree = function(Buff: Pointer):Integer;stdcall;

  TNetQueryDisplayInformation = function(ServerName: LPCWSTR;Level,Index,EntriesRequested,PreferredMaximumLength: DWORD;var ReturnedEntryCount: LongWord;SortedBuffer: Pointer):Integer;stdcall;

var      querydispinfo: TNetQueryDisplayInformation;
      buffclear: TNetAPIBufferFree;

function Vaild:Boolean;
begin
     lHandle:=LoadLIbrary(LIB_NAME);
   if lHandle <> 0 then
     begin
       @buffclear:=GetProcAddress(lHandle,BUFF_CLEAR);
       @querydispinfo:=GetProcAddress(lHandle,NET_QUERY_DISPINFO);
     end;
   Result:=(@buffclear <> nil) and (@querydispinfo <> nil);
end;

procedure NetQueryDisplayInformation(Server: string;Level: DWORD;Container: TStrings;var buff: Pointer);
var lpServer: LPCWSTR;
    ret, cnt: Integer;
    idx, entreq, entread: DWORD;
    p1: PNET_DISPLAY_USER;
    p2: PNET_DISPLAY_MACHINE;
    p3: PNET_DISPLAY_GROUP;
begin
  if Valid then
    begin
      GetMem(lpServer,Length(Server)*2+1);
      try
        idx:=0;
        entreq:=100;
        stringtowidechar(Server,lpServer,Length(Server)*2+1);
        repeat
          ret:=querydispinfo(lpServer,Level,idx,entreq,MAX_PREFERRED_LENGTH,entread,@buff);
          if (ret = NERR_Success) or (ret = ERROR_MORE_DATA) then
            begin
              case Level of
                1:    begin
                        p1:=PNET_DISPLAY_USER(buff);
                        for cnt:=0 to entread - 1 do
                          begin
                            Container.Add('Name: '+p1^.usri1_name+'; Comment: '+p1^.usri1_comment+'; FullName: '+p1^.usri1_full_name);
                            idx:=p1^.usri1_next_index;
                            Inc(p1);
                          end;
                      end;
                2:    begin
                        p2:=PNET_DISPLAY_MACHINE(buff);
                        for cnt:=0 to entread - 1 do
                          begin
                            Container.Add('Name: '+p2^.usri2_name+'; Comment: '+p2^.usri2_comment);
                            idx:=p2^.usri2_next_index;
                            Inc(p2);
                          end;
                      end;
                3:    begin
                        p3:=PNET_DISPLAY_GROUP(buff);
                        for cnt:=0 to entread - 1 do
                          begin
                            Container.Add('Name: '+p3^.grpi3_name+'; Comment: '+p3^.grpi3_comment);
                            idx:=p3^.grpi3_next_index;
                            Inc(p3);
                          end;
                      end;
              end;
            end
          else
            begin
              CheckReturn(ret);
              Break;
            end;
        until ret <> ERROR_MORE_DATA;
      finally
        FreeMem(lpserver);
      end;
    end
  else
    raise Exception.Create('Unable to load '+LIB_NAME+' or function "'+NET_QUERY_DISPINFO+'" not supported');
end;


procedure TForm1.Button11Click(Sender: TObject);
var buff: Pointer;
begin
  Screen.Cursor:=crHourGlass;
  Res.LB.Items.Clear;
  try
    NetQueryDisplayInformation(Edit1.Text,LEVEL_DISPLAY_USER,Res.LB.Items,buff);
    Res.Show;
  finally
    NetAPIBufferFree(buff);
    Screen.Cursor:=crDefault;
  end;
end;


ziolko.
0
 

Author Comment

by:dhnkley
ID: 8101080
ziolko,

I was unable to get this to compile, it seems as thoug I'm missing a declaration in the uses clause, that defines these?

[Error] Unit1.pas(103): Undeclared identifier: 'MAX_PREFERRED_LENGTH'

[Error] Unit1.pas(104): Undeclared identifier: 'NERR_Success'

[Error] Unit1.pas(138): Undeclared identifier: 'CheckReturn'

[Error] Unit1.pas(157): Undeclared identifier: 'LEVEL_DISPLAY_USER'

[Error] Unit1.pas(160): Undeclared identifier: 'NetAPIBufferFree'


Darren
0
 

Author Comment

by:dhnkley
ID: 8101118
ziolko,

I was unable to get this to compile, it seems as thoug I'm missing a declaration in the uses clause, that defines these?

[Error] Unit1.pas(103): Undeclared identifier: 'MAX_PREFERRED_LENGTH'

[Error] Unit1.pas(104): Undeclared identifier: 'NERR_Success'

[Error] Unit1.pas(138): Undeclared identifier: 'CheckReturn'

[Error] Unit1.pas(157): Undeclared identifier: 'LEVEL_DISPLAY_USER'

[Error] Unit1.pas(160): Undeclared identifier: 'NetAPIBufferFree'


Darren
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 21

Expert Comment

by:ziolko
ID: 8101120
Ooops sorry I tried to be to fast:-)

const
        MAX_PREFERRED_LENGTH = Cardinal(-1);
        NERR_SUCCESS = 0;
        LEVEL_DISPLAY_USER = 1;
        LEVEL_DISPLAY_MACHINE = 2;
        LEVEL_DISPLAY_GROUP = 3;

procedure NetAPIBufferFree(Buff: Pointer);
begin
  buffclear(Buff);
end;


checkreturn is function that checks error code in my implementation it checks network specific errors and displays error message in Polish.

ziolko.
0
 

Author Comment

by:dhnkley
ID: 8101147
Ok, Got it compiled and working, but this does not give me the list of Accounts in the Administrator s Group
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8101182
if my first comment I said it lists all users.
ziolko.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 8101205
NetGroupGetUsers should do what you're looking for. Found this on google:

http://subscribe.ru/archive/comp.soft.prog.delphint/200207/23073828.html

Regards, Madshi.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8101343
yep Madshi is right, but NetGroupGetUsers will work only for global groups if You need also local groups: NetLocalGroupGetMembers().
I'll have implementation of this function in few minutes.

ziolko.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8101402
LocalGroups:

type
  PLOCALGROUP_MEMBERS_INFO_0 = ^LOCALGROUP_MEMBERS_INFO_0;
  LOCALGROUP_MEMBERS_INFO_0 = record
    lgrmi0_sid: PSID;
  end;

  PLOCALGROUP_MEMBERS_INFO_1 = ^LOCALGROUP_MEMBERS_INFO_1;
  LOCALGROUP_MEMBERS_INFO_1 = record
    lgrmi1_sid: PSID;
    lgrmi1_sidusage: SID_NAME_USE;
    lgrmi1_name: LPWSTR;
  end;

  PLOCALGROUP_MEMBERS_INFO_2 = ^LOCALGROUP_MEMBERS_INFO_2;
  LOCALGROUP_MEMBERS_INFO_2 = record
    lgrmi2_sid: PSID;
    lgrmi2_sidusage: SID_NAME_USE;
    lgrmi2_domainandname: LPWSTR;
  end;

  PLOCALGROUP_MEMBERS_INFO_3 = ^LOCALGROUP_MEMBERS_INFO_3;
  LOCALGROUP_MEMBERS_INFO_3 = record
    lgrmi3_domainandname: LPWSTR;
  end;

  TNetLocalGroupGetMembers = function(ServerName,LocalGroupName: LPCWSTR;level: DWORD;bufptr: Pointer;prefmaxlen: DWORD;var entriesread, totalentries: LongWord;var ResumeHandle: LongWord):Integer;stdcall;

procedure NetLocalGroupGetMembers(Server, GroupName: string;Container: TStrings;var buff: Pointer);
var lpServer, lpGroupName: LPCWSTR;
    ret, cnt: Integer;
    totentr, entread: DWORD;
    p1: PLOCALGROUP_MEMBERS_INFO_3;
    resH: LongWord;
begin
    if Valid then
    begin
      resH:=0;
      GetMem(lpServer,Length(Server)*2+1);
      GetMem(lpGroupName,Length(GroupName)*2+1);
      try
        stringtowidechar(Server,lpServer,Length(Server)*2+1);
        stringtowidechar(GroupName,lpGroupName,Length(GroupName)*2+1);
        repeat
          ret:=getlocalgroupusers(lpServer,lpGroupName,3,@buff,MAX_PREFERRED_LENGTH,entread,totentr,resH);
          if (ret = NERR_Success) or (ret = ERROR_MORE_DATA) then
            begin
              p1:=PLOCALGROUP_MEMBERS_INFO_3(buff);
              for cnt:=0 to entread - 1 do
                begin
                  Container.Add('Name: '+p1^.lgrmi3_domainandname);
                  Inc(p1);
                end;
            end
          else
            CheckReturn(ret);
        until ret <> ERROR_MORE_DATA;
      finally
        FreeMem(lpserver);
      end;
    end
  else
    raise Exception.Create('Unable to load '+LIB_NAME+' or function "'+NET_GROUP_GET_USERS+'" not supported');
end;


ziolko.
0
 

Author Comment

by:dhnkley
ID: 8101678
ziolko
Unable to compile this again

[Error] Unit1.pas(98): Undeclared identifier: 'getlocalgroupusers'

[Error] Unit1.pas(116): Undeclared identifier: 'NET_GROUP_GET_USERS'

0
 

Author Comment

by:dhnkley
ID: 8101763
ziolko
Unable to compile this again

[Error] Unit1.pas(98): Undeclared identifier: 'getlocalgroupusers'

[Error] Unit1.pas(116): Undeclared identifier: 'NET_GROUP_GET_USERS'

0
 
LVL 21

Accepted Solution

by:
ziolko earned 2000 total points
ID: 8102343
full code for global & local groups:

interface
procedure NetAPIBufferFree(Buff: Pointer);
procedure NetGroupGetUsers(Server, GroupName: string;Container: TStrings;var buff: Pointer);
procedure NetLocalGroupGetMembers(Server, GroupName: string;Container: TStrings;var buff: Pointer);

implementation
const
  LIB_NAME = 'NetAPI32.DLL';
  NET_GROUP_GET_USERS_LOCAL  = 'NetLocalGroupGetMembers';
  NET_GROUP_GET_USERS = 'NetGroupGetUsers';
  BUFF_CLEAR = 'NetApiBufferFree';

type

  PGROUP_USERS_INFO_0 = ^GROUP_USERS_INFO_0;
  GROUP_USERS_INFO_0 = record
    grui0_name: LPWSTR;
  end;

  PLOCALGROUP_MEMBERS_INFO_0 = ^LOCALGROUP_MEMBERS_INFO_0;
  LOCALGROUP_MEMBERS_INFO_0 = record
    lgrmi0_sid: PSID;
  end;

  PLOCALGROUP_MEMBERS_INFO_1 = ^LOCALGROUP_MEMBERS_INFO_1;
  LOCALGROUP_MEMBERS_INFO_1 = record
    lgrmi1_sid: PSID;
    lgrmi1_sidusage: SID_NAME_USE;
    lgrmi1_name: LPWSTR;
  end;

  PLOCALGROUP_MEMBERS_INFO_2 = ^LOCALGROUP_MEMBERS_INFO_2;
  LOCALGROUP_MEMBERS_INFO_2 = record
    lgrmi2_sid: PSID;
    lgrmi2_sidusage: SID_NAME_USE;
    lgrmi2_domainandname: LPWSTR;
  end;

  PLOCALGROUP_MEMBERS_INFO_3 = ^LOCALGROUP_MEMBERS_INFO_3;
  LOCALGROUP_MEMBERS_INFO_3 = record
    lgrmi3_domainandname: LPWSTR;
  end;


TNetAPIBufferFree = function(Buff: Pointer):Integer;stdcall;

TNetGroupGetUsers = function(ServerName, GroupName: LPCWSTR;Level: DWORD;bufptr: Pointer;prefmaxlen: DWORD;var entriesread,totalentries: LongWord;var ResumeHandle: LongWord):Integer;stdcall;

TNetLocalGroupGetMembers = function(ServerName,LocalGroupName: LPCWSTR;level: DWORD;bufptr: Pointer;prefmaxlen: DWORD;var entriesread, totalentries: LongWord;var ResumeHandle: LongWord):Integer;stdcall;

var
     lHandle: THandle;
     buffclear: TNetAPIBufferFree;
     getgroupusers: TNetGroupGetUsers;
     getlocalgroupusers: TNetLocalGroupGetMembers;

procedure NetAPIBufferFree(Buff: Pointer);
begin
  if Valid then
    buffclear(Buff);
end;

procedure NetLocalGroupGetMembers(Server, GroupName: string;Container: TStrings;var buff: Pointer);
var lpServer, lpGroupName: LPCWSTR;
    ret, cnt: Integer;
    totentr, entread: DWORD;
    p1: PLOCALGROUP_MEMBERS_INFO_3;
    resH: LongWord;
begin
    if Valid then
    begin
      resH:=0;
      GetMem(lpServer,Length(Server)*2+1);
      GetMem(lpGroupName,Length(GroupName)*2+1);
      try
        stringtowidechar(Server,lpServer,Length(Server)*2+1);
        stringtowidechar(GroupName,lpGroupName,Length(GroupName)*2+1);
        repeat
          ret:=getlocalgroupusers(lpServer,lpGroupName,3,@buff,MAX_PREFERRED_LENGTH,entread,totentr,resH);
          if (ret = NERR_Success) or (ret = ERROR_MORE_DATA) then
            begin
              p1:=PLOCALGROUP_MEMBERS_INFO_3(buff);
              for cnt:=0 to entread - 1 do
                begin
                  Container.Add('Name: '+p1^.lgrmi3_domainandname);
                  Inc(p1);
                end;
            end
          else
            CheckReturn(ret);
        until ret <> ERROR_MORE_DATA;
      finally
        FreeMem(lpserver);
      end;
    end
  else
    raise Exception.Create('Unable to load '+LIB_NAME+' or function "'+NET_GROUP_GET_USERS_LOCAL+'" not supported');
end;

procedure NetGroupGetUsers(Server, GroupName: string;Container: TStrings;var buff: Pointer);
var lpServer, lpGroupName: LPCWSTR;
    ret, cnt: Integer;
    totentr, entread: DWORD;
    p1: PGROUP_USERS_INFO_0;
    resH: LongWord;
begin
    if Valid then
    begin
      resH:=0;
      GetMem(lpServer,Length(Server)*2+1);
      GetMem(lpGroupName,Length(GroupName)*2+1);
      try
        stringtowidechar(Server,lpServer,Length(Server)*2+1);
        stringtowidechar(GroupName,lpGroupName,Length(GroupName)*2+1);
        repeat
          ret:=getgroupusers(lpServer,lpGroupName,0,@buff,MAX_PREFERRED_LENGTH,entread,totentr,resH);
          if (ret = NERR_Success) or (ret = ERROR_MORE_DATA) then
            begin
              p1:=PGROUP_USERS_INFO_0(buff);
              for cnt:=0 to entread - 1 do
                begin
                  Container.Add('Name: '+p1^.grui0_name);
                  Inc(p1);
                end;
            end
          else
            CheckReturn(ret);
        until ret <> ERROR_MORE_DATA;
      finally
        FreeMem(lpserver);
      end;
    end
  else
    raise Exception.Create('Unable to load '+LIB_NAME+' or function "'+NET_GROUP_GET_USERS+'" not supported');
end;

function Valid:Boolean;
begin
   result:=(@buffclear <> nil) and (@getgroupusers <> nil) and (@getlocalgroupusers <> nil);
end;

procedure Load;
begin
   lHandle:=LoadLIbrary(LIB_NAME);
   if lHandle <> 0 then
     begin
       @buffclear:=GetProcAddress(lHandle,BUFF_CLEAR);
       @getgroupusers:=GetProcAddress(lHandle,NET_GROUP_GET_USERS);
       @getlocalgroupusers:=GetProcAddress(lHandle,NET_GROUP_GET_USERS_LOCAL);
     end;
end;

procedure UnLoad;
begin
  if lHandle <> 0 then
    FreeLibrary(lHandle);
end;

ziolko.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8111592
still got some problmes??
ziolko.
0
 

Author Comment

by:dhnkley
ID: 8116806
Ziolko,

Thanks, Have it working, exactly what I wanted.

Darren
0
 
LVL 21

Expert Comment

by:ziolko
ID: 8117217
glad to be helpfull :-)
ziolko.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say 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 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…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
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

770 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