Delphi-PRAXiS

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)

CalganX 7. Feb 2003 13:27


NetUserEnum die 2.
 
Hi,
entweder ich bin blöd, oder der Kompiler ist kaputt. Also, ersteinmal meine Definition der NetUserEnum aus JwaLM:
Delphi-Quellcode:
function NetUserEnum(
  const servername: LPCWSTR;
  const level: DWORD;
  const filter: DWORD;
  const bufptr: Pointer;
  const prefmaxlen: DWORD;
  var entriesread: DWORD;
  var totalentries: DWORD;
  const resume_handle: PDWORD
 ): NET_API_STATUS; stdcall;
Ich habe mir bereits Christian's Definition aus dem Ursprungsthread angesehen. Allerdings kann ich damit nix anfangen. Darum bitte ich euch mir hier nochmal zu helfen, denn ich steige nicht mehr durch.
Nun aber mein Source (nachdem ich alles in eine Funktion schreiben wollte, ging nix mehr):
Delphi-Quellcode:
procedure ListAllUsers(hTreeView: DWORD; hMasterParent: Cardinal; var iEntriesRead: Cardinal);
type
  PUSER_INFO_0  = ^_USER_INFO_0;
//  PUSER_INFO_11 = ^_USER_INFO_11; <= für später...
var
  aTempIStruct: TTVInsertStruct;
  aUserBuffer, aWorkBuffer: PUSER_INFO_0;
  dwEntriesRead: Cardinal;
  i: integer;
  sTemp: string;
begin
  if NetUserEnum(nil, 0, FILTER_NORMAL_ACCOUNT, @aUserBuffer, MAX_PREFERRED_LENGTH,
                 dwEntriesRead, dwEntriesRead, nil) = NERR_SUCCESS then begin
    aWorkBuffer := aUserBuffer;
    for i:=1 to dwEntriesRead do begin
      aTempIStruct.hParent := Pointer(hMasterParent);
      sTemp := aWorkBuffer.usri0_name;
      aTempIStruct.item.pszText := @sTemp[1];
      SendMessage(hTreeView, TVM_INSERTITEM, 0, integer(@aTempIStruct));

      inc(aWorkBuffer, sizeOf(PUSER_INFO_0));
    end;
  end;
  NetAPIBufferFree(aUserBuffer);
end;
So, wenn ich nun ausführe: Es gibt ne saftige AccessViolation mit folgendem Inhalt:
Code:
---------------------------
Application Error
---------------------------
Exception EAccessViolation in module OSInfo.exe at 000037C3.
Access violation at address 004037C3 in module 'OSInfo.exe'. Read of address BAADF00D.
---------------------------
OK  
---------------------------
Dann wird das Programm zurückgesetzt und Ende.

Was mache ich nur falsch. :cry::cry::cry::cry::cry:

Chris

Luckie 7. Feb 2003 13:30

Code:
for i:=1 to dwEntriesRead do begin
Du läufst 2 Stellen zu weit. Du mußt die Schleife von 0 bis dwEntriesRead-1 laufen lassen.

CalganX 7. Feb 2003 13:32

Wie bereits per ICQ mitgeteilt: hat nix gebracht...

Chris

CalganX 7. Feb 2003 13:58

Nach ein paar Unterredungen in ICQ ist folgendes herausgekommen:
Delphi-Quellcode:
procedure ListAllUsers(hTreeView: DWORD; hMasterParent: Cardinal; var iEntriesRead: Cardinal);
{type
  PUSER_INFO_0  = ^_USER_INFO_0;
  PUSER_INFO_11 = ^_USER_INFO_11;}
var
  aTempIStruct: TTVInsertStruct;
  aUserBuffer, aWorkBuffer: Pointer; //PUSER_INFO_0;
  dwEntriesRead: Cardinal;
  i: integer;
  sTemp: string;
begin
  aTempIStruct.item.mask := TVIF_TEXT;
  if NetUserEnum(nil, 0, FILTER_NORMAL_ACCOUNT, aUserBuffer, MAX_PREFERRED_LENGTH,
                 dwEntriesRead, dwEntriesRead, nil) = NERR_SUCCESS then begin
    aWorkBuffer := aUserBuffer;
    for i:=0 to dwEntriesRead-1 do begin
      aTempIStruct.hParent := Pointer(hMasterParent);
      sTemp := PUserInfo0(aWorkBuffer)^.usri0_name;
      aTempIStruct.item.pszText := @sTemp[1];
      SendMessage(hTreeView, TVM_INSERTITEM, 0, integer(@aTempIStruct));

      inc(Integer(aWorkBuffer), sizeOf(aWorkBuffer));
    end;
  end;
  NetAPIBufferFree(aUserBuffer);
end;
Allerdings ist hier die ursprüngliche Deklaration von NetUserEnum bei zubehalten. Ich hatte sie geändert, da Christian das so gepostet hat (oder ich habe ihn missverstanden).
Nochmal danke @ Luckie..

Chris

Christian Seehase 7. Feb 2003 14:03

Moin Chris,

das hier ist schlicht falsch:

Delphi-Quellcode:
 inc(aWorkBuffer, sizeOf(PUSER_INFO_0));
Es muss schlicht

Delphi-Quellcode:
 inc(aWorkBuffer);
heissen.

Da aWorkBuffer typisiert ist (eben PUSER_INFO_O), zählt der Compiler bei einem inc(aWorkBuffer) automatisch um SizeOf(PUSER_INFO_0) hoch.
Nur wenn der Typ Pointer ist, muss man sich um die Grösse der Struktur selber Gedanken machen.
Das kannst Du auch in meinen Beiträgen zu dem Ursprungsthread auch schon sehen (auch wenn ich es dort wohl nicht explizit dazugeschrieben hatte. ;-)

@Luckie:
Da man mit i hier nicht direkt einen Tabelleneintrag indiziert spielt es keine Rolle, ob man i nun von 0 bis dwEntriesRead-1, von 1 bis dwEntriesRead oder von 278 bis dwEntriesRead+277 laufen lässt. Hauptsache die Gesamtzahl der Schleifendurchläuft ist korrekt.

CalganX 7. Feb 2003 14:05

Hi Christian,
habe das gerade noch geändert... Lese mir aber gleich nochmal alle Threads zu diesem Thema durch...

Chris

Luckie 7. Feb 2003 14:06

Stimmt hast recht, Aber bei solchen for-Schleifen hab eich mir das imme rangewöhnt, dann vergist man es an anderer Stelle nicht. :wink:

Christian Seehase 7. Feb 2003 14:07

Moin Chris,

die Lösung, die Du gepostet hast, während ich meinen Beitrag geschrieben habe funktioniert natürlich auch.
Ich würde diese allerdings in die Rubrik: "Warum einfach, wenn's umständlich geht" einsortieren ;-)

CalganX 7. Feb 2003 14:07

Oops: Es muss wohl eher
Delphi-Quellcode:
inc(integer(aWorkBuffer));
heißen, da sonst:
Zitat:

[Error] UserInfo.pas(29): Ordinal type required
Chris

Luckie 7. Feb 2003 14:09

Dafür kann man aber bei meiner Lösung die Jedi-Header-Übersetzungen in Ruhe lassen. :wink:

CalganX 7. Feb 2003 14:11

Ätsch, Bätsch ausgetrickst. Wenn ich
Delphi-Quellcode:
inc(integer(aWorkBuffer), sizeOf(PUSERINFO0));
mache gibts kein Problem, aber nachdem ich nun einfach
Delphi-Quellcode:
inc(aWorkBuffer); {oder} inc(integer(aWorkBuffer));
mache, dann gibts ne' AccessViolation...

Chris

Christian Seehase 7. Feb 2003 14:12

Moin Chris,

nein, muss es nicht.

So hab' ich das gemacht

Delphi-Quellcode:
function NetUserEnum(
  const servername: LPCWSTR;
  const level: DWORD;
  const filter: DWORD;
  const bufptr: Pointer;
  const prefmaxlen: DWORD;
  var entriesread: DWORD;
  var totalentries: DWORD;
  const resume_handle: PDWORD
): NET_API_STATUS; stdcall; external 'netapi32.dll';

function NetApiBufferFree(const pBuffer : Pointer): NET_API_STATUS; stdcall; external 'netapi32.dll';


procedure TfrmMAIN.miFileOpenClick(Sender: TObject);

var
  rui0Work : PUSER_INFO_0;
  rui0Save : PUSER_INFO_0;
  dwEntriesRead : DWORD;
  i            : integer;
begin
  if NetUserEnum(nil, 0, FILTER_NORMAL_ACCOUNT, @rui0Work, MAX_PREFERRED_LENGTH,
                 dwEntriesRead, dwEntriesRead, nil) = NERR_SUCCESS then begin
    rui0Save := rui0Work;
    for i:=1 to dwEntriesRead do
    begin
      ListBox1.Items.Add(rui0Work.usri0_name);
      [color=red]inc(rui0Work);[/color]
    end;
  end;
  NetAPIBufferFree(rui0Save);
end;
und es funktioniert einwandfrei.

(Ich hab' sogar mal die Funktionsdeklarationen benutzt, wie es die Jedis machen)

CalganX 7. Feb 2003 14:16

HILFE!!!! Ich drehe hier noch durch. Also, wenn ich das mache, was du gemacht hast, dann kommt:
Zitat:

[Error] UserInfo.pas(20): Types of actual and formal var parameters must be identical
Allerdings ist bei mir bufptr mit var versehen und so steht es auch bei den Jedis...

Chris

Christian Seehase 7. Feb 2003 14:17

Moin Luckie,

dann nimm meinetwegen die Jedi Units:

Delphi-Quellcode:
procedure TfrmMAIN.miFileOpenClick(Sender: TObject);

type
  PUserInfo0 = ^TUserInfo0;
  _USER_INFO_0  = record
    usri0_name: LPWSTR;
  end;
  TUserInfo0 = _USER_INFO_0;
  USER_INFO_0 = _USER_INFO_0;

var
  rui0Work : PUserInfo0;
  rui0Save : PUserInfo0;
  dwEntriesRead : DWORD;
  i            : integer;
begin
  if NetUserEnum(nil, 0, FILTER_NORMAL_ACCOUNT, @rui0Work, MAX_PREFERRED_LENGTH,
                 dwEntriesRead, dwEntriesRead, nil) = NERR_SUCCESS then begin
    rui0Save := rui0Work;
    for i:=1 to dwEntriesRead do
    begin
      ListBox1.Items.Add(rui0Work.usri0_name);
      inc(rui0Work);
    end;
  end;
  NetAPIBufferFree(rui0Save);
end;
Mein Methode funktioniert trotzdem ;-)
(Auch ohne die Jedi Deklarationen anzufassen)

CalganX 7. Feb 2003 14:22

Also, nochmal *wimmer*:
Delphi-Quellcode:
procedure ListAllUsers(hTreeView: DWORD; hMasterParent: Cardinal; var iEntriesRead: Cardinal);
var
  aTempIStruct: TTVInsertStruct;
  aUserBuffer, aWorkBuffer: PUSERINFO0;
  dwEntriesRead: Cardinal;
  i: integer;
  sTemp: string;
begin
  aTempIStruct.item.mask := TVIF_TEXT;
{27 =>}  if NetUserEnum(nil, 0, FILTER_NORMAL_ACCOUNT, @aUserBuffer{<=}, MAX_PREFERRED_LENGTH,
                 dwEntriesRead, dwEntriesRead, nil) = NERR_SUCCESS then begin
    aWorkBuffer := aUserBuffer;
    for i:=0 to dwEntriesRead-1 do begin
      aTempIStruct.hParent := Pointer(hMasterParent);
      sTemp := {PUserInfo0(}aWorkBuffer{)^}.usri0_name;
      aTempIStruct.item.pszText := @sTemp[1];
      SendMessage(hTreeView, TVM_INSERTITEM, 0, integer(@aTempIStruct));

      inc({integer(}aWorkBuffer{), sizeOf(PUSERINFO0)});
    end;
  end;
  NetAPIBufferFree(aUserBuffer);
end;
Kommentare deswegen, dass ich alles schnell wiederrückgängig machen kann. ;)
Nun, wenn ich das so mache (die Typen-deklarationen sind bereits in den Units drin; das gleiche, wenn ich sie reinschreibe), dann gibts den Fehler:
Zitat:

[Error] UserInfo.pas(27): Types of actual and formal var parameters must be identical
Chris

Christian Seehase 7. Feb 2003 14:30

Moin Chris,

könntest Du bitte auch noch mal markieren, was denn Zeile 27 ist?

CalganX 7. Feb 2003 14:32

Das ist die Zeile in der @aUserBuffer steht. Und an der Stelle steht auch der Cursor... Markieren kann ich auch nochmal machen

Chris

Christian Seehase 7. Feb 2003 14:47

Moin Chris,

ich dachte die weiter oben gepostete Funktionsdeklaration stamme aus den Jedi Headern, aber die sieht ja so aus:

Delphi-Quellcode:
function NetUserEnum(servername: LPCWSTR; level: DWORD; filter: DWORD;
 var {<=== VAR statt CONST} bufptr: Pointer; prefmaxlen: DWORD; var entriesread: DWORD;
  var totalentries: DWORD; resume_handle: PDWORD): NET_API_STATUS; stdcall;
Wenn hier das var weggelassen würde, würde es auch gehen.

Ersatzweise musst Du für @aUserBuffer Pointer(aUserBuffer) schreiben, dann geht's.

CalganX 7. Feb 2003 16:50

OK. Aber es wäre theoretisch möglich, die Methode von Luckie (2. Source, der anfängt mit "Nach ein paar Unterredungen in ICQ ist folgendes herausgekommen:") zu nutzen, richtig? Denn dann würde ich doch diese Methode nehmen, da diese diejenige ist, dir mir derzeit am ehesten zusagt.

Chris

Christian Seehase 7. Feb 2003 17:35

Moin Chris,

den hab' ich jetzt zwar nicht ausprobiert, bin aber der Meinung, dass der natürlich auch gehen würde.
Wann man den Typecast nun macht spielt ja keine Rolle.
Ich find's halt nur einfacher und übersichtlicher den nur einmal zu machen, statt öfter.

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. :(

himitsu 21. Apr 2012 01:34

AW: NetUserEnum die 2.
 
Delphi-Quellcode:
        for Loop := 0 to EntriesRead - 1 do
          if not Callback(PUserInfo1(ui1)[Loop].usri1_name, EntriesRead, Data) then
            break;
oder
Delphi-Quellcode:
        for Loop := 0 to EntriesRead - 1 do
        begin
          if not Callback(PUserInfo1(ui1)^.usri1_name, EntriesRead, Data) then
            break;
          Inc(NativeUInt(ui1), sizeof(TUserInfo1)); // T statt P und Integer, falls NativeUInt noch nicht geht
        end;
PS: Ich würde den Callback noch so anpassen, daß man dort das ganze TUserInfo1 anstatt nur des Usermames übergibt. (damit nichts umsonst ausgelesen wird)

Luckie 21. Apr 2012 01:40

AW: NetUserEnum die 2.
 
Perfekt. Die zweite Möglichkeit funktioniert. Hm, dafür habe ich andere Funktionen. Und davon mal abgesehen, verwend eich im Usermanager andere Routinen. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:47 Uhr.

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