Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi NetUserEnum die 2. (https://www.delphipraxis.net/2793-netuserenum-die-2-a.html)

daniel8520 19. Nov 2005 09:42

Re: NetUserEnum die 2.
 
Hab's jetzt hinbekommen!

Vielen Dank!

:dp:

//EDIT: Sorry...........falscher Thread!

MiKaEr 20. Apr 2012 20:57

AW: NetUserEnum die 2.
 
ich finde bei mir den fehler leider nicht. es kommt eine unerklärliche AV beim lesen von irgendetwas. es wird der nutzername Administrator in meine ListBox geschrieben mehr aber nicht. das ist erst passiert als ich das record _USER_INFO_0 um password, password_age und home_dir erweitert habe:

Delphi-Quellcode:
unit Unit1;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;

type
 TForm1 = class(TForm)
  ListView1: TListView;
  ListBox1: TListBox;
  procedure FormCreate(Sender: TObject);
 private
  { Private-Deklarationen }
 public
  { Public-Deklarationen }
 end;

var
 Form1: TForm1;

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
  usri1_name: LPWSTR;
  usri1_password: LPWSTR;
  usri1_password_age: DWORD;
  usri1_home_dir: LPWSTR;
 end;

 TUserInfo0 = _USER_INFO_0;

function NetUserChangePassword(Domain: PWideChar; UserName: PWideChar; OldPassword: PWideChar; NewPassword: PWideChar)
 : Longint; stdcall; external 'netapi32.dll' name 'NetUserChangePassword';

implementation

{$R *.dfm}

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;

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;

procedure GetUsers(Users: TStrings; AServer: string);
type
 TUserInfoArr = array [0 .. 3] 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 * 3, 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].usri1_name);
    NetApiBufferFree(UserInfo);
   end;
 until Res <> ERROR_MORE_DATA;
end;

function isPw(const User, Password: string): Boolean;
var
 Err: LongWord;
begin
 Err := NetUserChangePassword(nil, PWideChar(WideString(User)), PWideChar(WideString(Password)),
  PWideChar(WideString(Password)));
 result := Err = 0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 GetUsers(ListBox1.Items, '');
end;

end.

himitsu 20. Apr 2012 21:58

AW: NetUserEnum die 2.
 
Und warum wird schonwieder alles Wichtige unterschlagen?


Wie genau lautet die Fehlermeldung? (der Vorschlag mit Strg+C ist immernoch sehr zu empfehlen)

An welcher Stelle tritt sie auf? (auch wenn meine :glaskugel: schon fast eine Vermutung hat)

Wie kommst du auf die saudämliche Idee diesen Record verändern zu wollen und warum hast du genau diese neuen Felder dort so reingemacht?
Das Format dieser Puffer ist genau definiert und der Aufbau ist über MSDN-Library durchsuchenNetUserEnum zu finden und deinen Aufbau dieser Records kann ich nirgendwo entdecken.

Da du immernoch den Info-Level 0 abfragst, muß es zwangsweise schief gehn, denn dort ist ausschließlich das Feld "name" vorhanden. :roll:

Luckie 20. Apr 2012 22:00

AW: NetUserEnum die 2.
 
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

const
  NERR_Success = 0;
  MAX_PREFERRED_LENGTH = DWORD(-1);

type
  NET_API_STATUS = DWORD;
  TEnumUers = function(Username: string; cntUsers: Integer; Data: Pointer): Boolean;

  TUserInfo1 = record
    usri1_name: LPWSTR;
    usri1_password: LPWSTR;
    usri1_password_age: DWORD;
    usri1_priv: DWORD;
    usri1_home_dir: LPWSTR;
    usri1_comment: LPWSTR;
    usri1_flags: DWORD;
    usri1_script_path: LPWSTR;
  end;
  PUserInfo1 = ^TUserInfo1;

   function NetUserEnum(servername: LPCWSTR; level: DWORD; filter: DWORD; var buf: Pointer; prefmaxlen: DWORD; var
  entriesred: DWORD; var totalentries: DWORD; resumehandle: PDWORD): NET_API_STATUS; stdcall;
 function NetApiBufferFree(Buffer: Pointer): NET_API_STATUS; stdcall;

var
  Form1: TForm1;

implementation

const
  netapi32lib      = 'netapi32.dll';

function NetUserEnum; external netapi32lib name 'NetUserEnum';
function NetApiBufferFree; external netapi32lib name 'NetApiBufferFree';

{$R *.dfm}

function EnumUsersCallback(Username: string; cntUsers: Integer; Data: Pointer): Boolean;
begin
  TListBox(Data).Items.Add(Username);
  Result := True;
end;

function EnumUsers(const Server: WideString; filter: DWORD; Callback: TEnumUers; Data: Pointer): DWORD;
var
  ui1               : Pointer;
  pWork            : Pointer;
  EntriesRead      : DWORD;
  EntriesTotal     : DWORD;
  NetError         : DWORD;
  Loop             : Integer;
begin
  ui1 := nil;
  pWork := nil;
  try
    NetError := NetUserEnum(PWideChar(Server), 0, filter, ui1, MAX_PREFERRED_LENGTH, EntriesRead, EntriesTotal, nil);
    if (NetError = NERR_SUCCESS) and (EntriesRead > 0) then
    begin
      pWork := ui1;
      if Assigned(Callback) then
      begin
        for Loop := 0 to EntriesRead - 1 do
        begin
          if not Callback(PUserInfo1(ui1)^.usri1_name, EntriesRead, Data) then
            break;
          Inc(Integer(ui1), sizeof(Pointer));
        end;
      end;
    end;
  finally
    NetApiBufferFree(pWork);
  end;
  Result := NetError;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Data: Pointer;
begin
  Data := nil;
  EnumUsers('', 0, @EnumUsersCallback, Form1.Listbox1);
end;

end.
Anwendungsbeispiel für meine Unit MpuNTUser: http://michael-puff.de/Programmierung/Delphi/Units/

Wenn du meine Unit benutzt, dann brauchst du natürlich nur die Callback implementieren und die Funktion EnumUsers aufrufen.

himitsu 20. Apr 2012 22:19

AW: NetUserEnum die 2.
 
@Luckie: Ein Level-1-Info-Record, aber ebenfalls Level 0 als Abfrageparameter?

Luckie 21. Apr 2012 00:16

AW: NetUserEnum die 2.
 
Tatsache. Aber es funktioniert - zumindest für den Benutzernamen. Aber wenn ich da 1 einsetze bekomme ich eine AccessViolation. :gruebel: Den ersten Benutzzernamen bekomme ich noch, bei den folgen denn ist das Feld für den Benutzernamen nil. :shock:

himitsu 21. Apr 2012 00:55

AW: NetUserEnum die 2.
 
Du gehst in dem Code auch jeweils einen String weiter (
Delphi-Quellcode:
Inc(Integer(ui1), sizeof(Pointer));
).
Der InfoLevel 0 paßt also zum Inc, weil da ja auch nur die Benutzernamen hintereinanderstehen (was Anderes ließt du in dem Beispiel nicht aus, sonst würde es da wohl auch nicht ganz stimmen).

MiKaEr geht statt Inc über ein Array, was einem
Delphi-Quellcode:
Inc(Integer(...), sizeof(TUserInfo0));
entsprechen würde.
PS: Integer und 64 Bit funktioniet auch nicht mehr, falls man das auch noch ausprobieren will. (wegen em Trottel, welcher den Integer eingefroren hat)

Luckie 21. Apr 2012 00:57

AW: NetUserEnum die 2.
 
OK, wie müsste ich den Code ändern, damit er richtig funktioniert? Ich habe ihn eben mal debuggt, bin aber auf keinen grünen Zweig gekommen.

himitsu 21. Apr 2012 01:09

AW: NetUserEnum die 2.
 
War noch im editieren. :oops:

Du müßtest auch noch das Inc an den Record anpassen. (die Daten/Records liegen wohl hintereinander im Speicher)



Falls eine Pointerarithmetik für den Record vorhanden ist, dann köndest du das INC weglassen und über
Delphi-Quellcode:
PUserInfo1(ui1)[index].usri1_name
drauf zugreifen.
Eventuell kann man auch gleich das ui1 als PUserInfo1 deklarieren. (
Delphi-Quellcode:
ui1[index].usri1_name
)
Womit dann Delphi, direkt beim Aufruf, jeweils ein implizites INC einbaut.

Luckie 21. Apr 2012 01:15

AW: NetUserEnum die 2.
 
Jja, das habe ich auch schon überlegt. Ich habe es jetzt so:
Delphi-Quellcode:
function EnumUsers(const Server: WideString; filter: DWORD; Callback: TEnumUers; Data: Pointer): DWORD;
var
  ui1               : PUserInfo1;
  pWork            : Pointer;
  EntriesRead      : DWORD;
  EntriesTotal     : DWORD;
  NetError         : DWORD;
  Loop             : Integer;
begin
  ui1 := nil;
  pWork := nil;
  try
    NetError := NetUserEnum(PWideChar(Server), 1, filter, ui1, MAX_PREFERRED_LENGTH, EntriesRead, EntriesTotal, nil);
    if (NetError = NERR_SUCCESS) and (EntriesRead > 0) then
    begin
      pWork := ui1;
      if Assigned(Callback) then
      begin
        for Loop := 0 to EntriesRead - 1 do
        begin
          if not Callback(PUserInfo1(ui1)^.usri1_name, EntriesRead, Data) then
            break;
          //Inc(Integer(ui1), sizeof(PUserInfo1));
        end;
      end;
    end;
  finally
    NetApiBufferFree(pWork);
  end;
  Result := NetError;
end;
Aber dann bekomme ich fünf mal den Admin. Das ist das erste Konto von fünf bei mir. Kommentiere ich es nicht aus, bekomme ich nur den ersten Benutzer und die folgenden sind nil. Und dann haut es mir den Code um die Ohren. :(


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:44 Uhr.
Seite 3 von 4     123 4      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz