![]() |
Freigeben von Pointern von API Funktionen
Ich habe hier folgenden Code und hab eirgendwie ein Brett vorm Kopf:
Delphi-Quellcode:
Da ich mit NetApiBufferFree den Pointer ui3 wieder freigebe, ist logischerweise der Rückgabewert auch verloren. Wie kann ich mein Problem lösen ohne dass ich ein Speicherleck bekomme?
function GetUserInfo(Server, User: string): TUserInfo3;
var ui3: Pointer; NetError: DWORD; begin if User <> '' then begin try NetError := NetUserGetInfo(PWideChar(WideString(Server)), PWideChar(WideString(User)), 3, ui3); if NetError = NERR_SUCCESS then begin result.usri3_name := PUserInfo3(ui3)^.usri3_name; result.usri3_full_name := PUserInfo3(ui3)^.usri3_full_name; result.usri3_comment := PUserInfo3(ui3)^.usri3_comment; result.usri3_home_dir := PUserInfo3(ui3)^.usri3_home_dir; result.usri3_password_age := PUserInfo3(ui3)^.usri3_password_age; result.usri3_last_logon := PUserInfo3(ui3)^.usri3_last_logon; result.usri3_num_logons := PUserInfo3(ui3)^.usri3_num_logons; result.usri3_password_expired := PUserInfo3(ui3)^.usri3_password_expired; result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_PASSWD_CANT_CHANGE = UF_PASSWD_CANT_CHANGE); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_DONT_EXPIRE_PASSWD = UF_DONT_EXPIRE_PASSWD); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_ACCOUNTDISABLE = UF_ACCOUNTDISABLE); end; finally NetApiBufferFree(ui3); end; end; end; |
Re: Freigeben von Pointern von API Funktionen
Gib die Pointer doch einfach bei Beendigung Deines Programmes frei. Das dürfte am einfachsten sein.
mfG mirage228 |
Re: Freigeben von Pointern von API Funktionen
Die Funktion wird mehr mal im Programm aufgerufen. Schlechte Lösung. Würde mir auch so nicht gefallen. ;)
|
Re: Freigeben von Pointern von API Funktionen
Ist der Rückgabewert wirklich verloren? Du dereferenzierst den Pointer ja. Somit hast Du im Result eine normale Kopie der Werte, oder? :gruebel:
Gruss Shaman |
Re: Freigeben von Pointern von API Funktionen
Zitat:
Dann könntest Du die ganzen Dinger eventuell in einer Liste speichern und die einzelnen Items dann am Ende des Programmes freigeben. Oder du hälst eine alle Informationen immer in einem TUserInfo3, die dann angezeigt(ausgewertet?) wird. Bevor neue Informationen reingeholt werden mit Deiner Funktion, ruft Du halt das "NetApiBufferFree" auf. mfG mirage228 |
Re: Freigeben von Pointern von API Funktionen
Ja, er ist weg. Wenn ich NetApiBufferFree aufrufe und den Rückgabewert benutzen will, bekomme ich eine AV. Lasse ich das NetApiBufferFree weg, geht es.
|
Re: Freigeben von Pointern von API Funktionen
:shock:
Das leuchtet mir jetzt aber nicht ein... |
Re: Freigeben von Pointern von API Funktionen
Zitat:
mfG mirage228 |
Re: Freigeben von Pointern von API Funktionen
kopier die daten, anstatt darauf zu pointen
|
Re: Freigeben von Pointern von API Funktionen
Moin!
Doch, bei der darauffolgenden Zuweisung aber - da es dereferenziert ist... Ergo: Der Fehler von Luckie leuchtet mir auch überhaupt nicht ein... MfG Muetze1 |
Re: Freigeben von Pointern von API Funktionen
Also in der Funktion ist der Fehler nicht das muss gehen vieleicht kommt die EV woanders her.
Zeig doch mal wie der Type aufgebaut ist und die auswertung wo die EV kommt. |
Re: Freigeben von Pointern von API Funktionen
Also noch mal alles zusammen:
Delphi-Quellcode:
type
TUserInfo3 = record usri3_name: LPWSTR; usri3_password: LPWSTR; usri3_password_age: DWORD; usri3_priv: DWORD; usri3_home_dir: LPWSTR; usri3_comment: LPWSTR; usri3_flags: DWORD; usri3_script_path: LPWSTR; usri3_auth_flags: DWORD; usri3_full_name: LPWSTR; usri3_usr_comment: LPWSTR; usri3_parms: LPWSTR; usri3_workstations: LPWSTR; usri3_last_logon: DWORD; usri3_last_logoff: DWORD; usri3_acct_expires: DWORD; usri3_max_storage: DWORD; usri3_units_per_week: DWORD; usri3_logon_hours: PBYTE; usri3_bad_pw_count: DWORD; usri3_num_logons: DWORD; usri3_logon_server: LPWSTR; usri3_country_code: DWORD; usri3_code_page: DWORD; usri3_user_id: DWORD; usri3_primary_group_id: DWORD; usri3_profile: LPWSTR; usri3_home_dir_drive: LPWSTR; usri3_password_expired: DWORD; end; PUserInfo3 = ^TUserInfo3;
Delphi-Quellcode:
Und der Aufruf:
function GetUserInfo(Server, User: string): TUserInfo3;
var ui3: Pointer; NetError: DWORD; begin if User <> '' then begin try NetError := NetUserGetInfo(PWideChar(WideString(Server)), PWideChar(WideString(User)), 3, ui3); if NetError = NERR_SUCCESS then begin result.usri3_name := PUserInfo3(ui3)^.usri3_name; result.usri3_full_name := PUserInfo3(ui3)^.usri3_full_name; result.usri3_comment := PUserInfo3(ui3)^.usri3_comment; result.usri3_home_dir := PUserInfo3(ui3)^.usri3_home_dir; result.usri3_password_age := PUserInfo3(ui3)^.usri3_password_age; result.usri3_last_logon := PUserInfo3(ui3)^.usri3_last_logon; result.usri3_num_logons := PUserInfo3(ui3)^.usri3_num_logons; result.usri3_password_expired := PUserInfo3(ui3)^.usri3_password_expired; result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_PASSWD_CANT_CHANGE = UF_PASSWD_CANT_CHANGE); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_DONT_EXPIRE_PASSWD = UF_DONT_EXPIRE_PASSWD); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_ACCOUNTDISABLE = UF_ACCOUNTDISABLE); end; finally //NetApiBufferFree(ui3); end; end; end;
Delphi-Quellcode:
type
TUser = packed record Name: String[255]; UserGroups: string[255]; end; TUsers = array of TUser; [..] function GetUsers(Computer: String): TUsers; var Users: TStringArray; i: Integer; ui3: TUserInfo3; UserGroups: TStringArray; s: PWideChar; begin UserGroups := nil; Users := EnumUsers(Computer, FILTER_NORMAL_ACCOUNT); setlength(result, length(Users)); for i := 0 to length(Users) - 1 do begin ui3 := GetUserInfo(Computer, Users[i]); result[i].Name := String(ui3.usri3_name); end; end; |
Re: Freigeben von Pointern von API Funktionen
Also wenn ich das richtig seh, dann sind zumindest diese Felder
Code:
Strings, weswegen ich den Fehler beim internen String-Handling vermute. Ruf mal für jedes Feld deines Results, das ein String oder WideString is die Funktion UniqueString() auf...
usri3_name
usri3_full_name usri3_comment usri3_home_dir Edit: zu spät.. ich hab mir die Deklaration von TUserInfo3 aus deiner NTUser-Unit angeguckt.. warum hast du denn von den Delphi-Strings auf LPWSTR umgestellt? |
Re: Freigeben von Pointern von API Funktionen
Umgestellt? Die war schon immer so.
|
Re: Freigeben von Pointern von API Funktionen
Hm.. vielleicht hab ich einfach eine alte Version, aber bei mir schaut die so aus:
Delphi-Quellcode:
Bin daher davon ausgegangen, dass es sich um Strings handelt...
type
// See Microsoft documentation for details TUserInfo_3 = record // record for user information, incomplete! Name: string; FullName: string; Comment: string; HomeDir: string; Password: string; PasswordAge: DWORD; // in seconds LastLogon: DWORD; // Specifies a DWORD value that indicates when the last // logon occurred. This value is stored as the // number of seconds that have elapsed since 00:00:00, // January 1, 1970, GMT NumLogons: DWORD; PasswordExpired: DWORD; PasswordCantChange: DWORD; PasswordDontExpire: DWORD; MustChangePW: DWORD; AccountDisable: DWORD; end; |
Re: Freigeben von Pointern von API Funktionen
Wo kommt den die EV
Delphi-Quellcode:
hier => ui3 := GetUserInfo(Computer, Users[i]);
oder hier => result[i].Name := String(ui3.usri3_name); |
Re: Freigeben von Pointern von API Funktionen
Wenn ich NetApiBufferFree aufrufe, dann steht hier nach:
Delphi-Quellcode:
nichts in dem Record drinne. Und die AV kommt dann in der nächsten Zeile.
ui3 := GetUserInfo(Computer, Users[i]);
|
Re: Freigeben von Pointern von API Funktionen
Ist ja auch klar, nachdem du nur den Pointer kopierst, aber nicht dessen Inhalt..
hab mal ein bisschen rumprobiert und mit 2 einfachen Typecasts geht es:
Delphi-Quellcode:
function GetUserInfo(Server, User: string): TUserInfo3;
var ui3: Pointer; NetError: DWORD; begin if User <> '' then begin try NetError := NetUserGetInfo(PWideChar(WideString(Server)), PWideChar(WideString(User)), 3, ui3); if NetError = NERR_SUCCESS then begin result.usri3_name := LPWSTR(WideString(PUserInfo3(ui3)^.usri3_name)); result.usri3_full_name := LPWSTR(WideString(PUserInfo3(ui3)^.usri3_full_name)); result.usri3_comment := LPWSTR(WideString(PUserInfo3(ui3)^.usri3_comment)); result.usri3_home_dir := LPWSTR(WideString(PUserInfo3(ui3)^.usri3_home_dir)); result.usri3_password_age := PUserInfo3(ui3)^.usri3_password_age; result.usri3_last_logon := PUserInfo3(ui3)^.usri3_last_logon; result.usri3_num_logons := PUserInfo3(ui3)^.usri3_num_logons; result.usri3_password_expired := PUserInfo3(ui3)^.usri3_password_expired; result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_PASSWD_CANT_CHANGE = UF_PASSWD_CANT_CHANGE); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_DONT_EXPIRE_PASSWD = UF_DONT_EXPIRE_PASSWD); result.usri3_flags := DWORD(PUserInfo3(ui3)^.usri3_flags and UF_ACCOUNTDISABLE = UF_ACCOUNTDISABLE); end; finally NetApiBufferFree(ui3); end; end; end; |
Re: Freigeben von Pointern von API Funktionen
In dem Record sind es dann Strings oder?
|
Re: Freigeben von Pointern von API Funktionen
Nein, den Record hab ich so lassen wie du ihn deklariert hast...
|
Re: Freigeben von Pointern von API Funktionen
Prima. Geht. Und warum geht es jetzt mit diesem zweifachen Typecast? :gruebel:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:39 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