• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1242
  • Last Modified:

NT Administrator accounts listing

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
dhnkley
Asked:
dhnkley
  • 8
  • 6
1 Solution
 
ziolkoCommented:
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
 
dhnkleyAuthor Commented:
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
 
dhnkleyAuthor Commented:
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
Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

 
ziolkoCommented:
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
 
dhnkleyAuthor Commented:
Ok, Got it compiled and working, but this does not give me the list of Accounts in the Administrator s Group
0
 
ziolkoCommented:
if my first comment I said it lists all users.
ziolko.
0
 
MadshiCommented:
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
 
ziolkoCommented:
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
 
ziolkoCommented:
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
 
dhnkleyAuthor Commented:
ziolko
Unable to compile this again

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

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

0
 
dhnkleyAuthor Commented:
ziolko
Unable to compile this again

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

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

0
 
ziolkoCommented:
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
 
ziolkoCommented:
still got some problmes??
ziolko.
0
 
dhnkleyAuthor Commented:
Ziolko,

Thanks, Have it working, exactly what I wanted.

Darren
0
 
ziolkoCommented:
glad to be helpfull :-)
ziolko.
0

Featured Post

Take Control of Web Hosting For Your Clients

As a web developer or IT admin, successfully managing multiple client accounts can be challenging. In this webinar we will look at the tools provided by Media Temple and Plesk to make managing your clients’ hosting easier.

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