![]() |
Re: NetUserEnum die 2.
Hab's jetzt hinbekommen!
Vielen Dank! :dp: //EDIT: Sorry...........falscher Thread! |
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. |
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 ![]() Da du immernoch den Info-Level 0 abfragst, muß es zwangsweise schief gehn, denn dort ist ausschließlich das Feld "name" vorhanden. :roll: |
AW: NetUserEnum die 2.
Delphi-Quellcode:
Anwendungsbeispiel für meine Unit MpuNTUser:
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. ![]() Wenn du meine Unit benutzt, dann brauchst du natürlich nur die Callback implementieren und die Funktion EnumUsers aufrufen. |
AW: NetUserEnum die 2.
@Luckie: Ein Level-1-Info-Record, aber ebenfalls Level 0 als Abfrageparameter?
|
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:
|
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:
entsprechen würde.
Inc(Integer(...), sizeof(TUserInfo0));
PS: Integer und 64 Bit funktioniet auch nicht mehr, falls man das auch noch ausprobieren will. (wegen em Trottel, welcher den Integer eingefroren hat) |
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.
|
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:
drauf zugreifen.
PUserInfo1(ui1)[index].usri1_name
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. |
AW: NetUserEnum die 2.
Jja, das habe ich auch schon überlegt. Ich habe es jetzt so:
Delphi-Quellcode:
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. :(
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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:35 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz