![]() |
Falsche Speicherbereiche
Ich stehe vor einem Rätsel. Mit der API NetUserSetInfo versuche ich Details für einen Benutzer Account zu setzen. NetUserSetInfo erwartet unter anderem folgende Struktur:
Delphi-Quellcode:
Diese fülle ich wie folgt:
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:
Dann die eigentliche Funktion:
function SetDetails: TUserInfo3;
begin ZeroMemory(@result, sizeof(result)); result.usri3_name := PWideChar(WideString(GetText(ID_EDT_USER))); result.usri3_full_name := PWideChar(WideString(GetText(ID_EDT_FULLNAME))); result.usri3_comment := PWideChar(WideString(GetText(ID_EDT_DESCRIPTION))); result.usri3_home_dir := PWideChar(WideString(GetText(ID_EDT_HOMEDIR))); result.usri3_script_path := PWideChar(WideString(GetText(ID_EDT_SCRIPT_PATH))); if GetCheck(ID_CHK_MUST_CHANGE_PW) then result.usri3_password_expired := 1 else result.usri3_password_expired := 0; if GetCheck(ID_CHK_CANT_CHANGE_PW) then result.usri3_flags := result.usri3_flags or UF_PASSWD_CANT_CHANGE; if GetCheck(ID_CHK_PW_DONT_EXPIRE) then result.usri3_flags := result.usri3_flags or UF_DONT_EXPIRE_PASSWD; if GetCheck(ID_CHK_ACCOUNT_DISABLED) then result.usri3_flags := result.usri3_flags or UF_ACCOUNTDISABLE; end;
Delphi-Quellcode:
Es kommt alles richtig an. Stoppe ich hier: PUserInfo3(ui3)^.usri3_name := UserInfo.usri3_name; und schaue mir die Werte der felder der Struktur an, stimmen sie alle. Aber so bald der full_name zugewiesen wurde, stimmen die Werte der anderen Felder nicht mehr. Teilweise steht Schrott drinne teilweise sachen im Klartext, die irgendwo anders im Programm auftauchen, wie der Computername zum Beispiel.
function SetUserInfo(Server, User: string; UserInfo: TUserInfo3):
NET_API_STATUS; var ui3: Pointer; begin ui3 := nil; result := NERR_BASE; if User <> '' then begin if NetUserGetInfo(PWideChar(WideString(Server)), PWideChar(WideString(User)), 3, ui3) = NERR_SUCCESS then begin PUserInfo3(ui3)^.usri3_name := UserInfo.usri3_name; PUserInfo3(ui3)^.usri3_full_name := UserInfo.usri3_full_name; PUserInfo3(ui3)^.usri3_password := UserInfo.usri3_password; PUserInfo3(ui3)^.usri3_home_dir := UserInfo.usri3_home_dir; PUserInfo3(ui3)^.usri3_comment := UserInfo.usri3_comment; PUserInfo3(ui3)^.usri3_usr_comment := UserInfo.usri3_comment; PUserInfo3(ui3)^.usri3_priv := UserInfo.usri3_priv; PUserInfo3(ui3)^.usri3_script_path := UserInfo.usri3_script_path; PUserInfo3(ui3)^.usri3_auth_flags := UserInfo.usri3_auth_flags; PUserInfo3(ui3)^.usri3_parms := UserInfo.usri3_parms; PUserInfo3(ui3)^.usri3_workstations := UserInfo.usri3_workstations; PUserInfo3(ui3)^.usri3_acct_expires := UserInfo.usri3_acct_expires; PUserInfo3(ui3)^.usri3_max_storage := UserInfo.usri3_max_storage; PUserInfo3(ui3)^.usri3_home_dir_drive := UserInfo.usri3_home_dir_drive; PUserInfo3(ui3)^.usri3_profile := UserInfo.usri3_profile; PUserInfo3(ui3)^.usri3_password_expired := UserInfo.usri3_password_expired; PUserInfo3(ui3)^.usri3_flags := UserInfo.usri3_flags; result := NetUserSetInfo(PWideChar(WideString(Server)), PWideChar(WideString(User)), 3, ui3, nil); end; end; end; Ich habe keinen blassen Schimmer, was da passiert und warum. :evil: |
Re: Falsche Speicherbereiche
So. Motzi hat das ganze mal analysiert und festgestellt, das es bei den Casts von Server und User teilweise der Speicherbereich auf den der Pointer ui3 zeigt überschrieben wird. Lösung sieht so aus, dass man praktisch von Hand selber castet.
|
Re: Falsche Speicherbereiche
Hi!
Auch wenn ich eigentlich davon gar nix verstehe :drunken: , mal eine Frage dazu: Heißt das, dass da ein Fehler in Delphi/Compiler ist oder was anderes? Ciao Frederic |
Re: Falsche Speicherbereiche
Da musst du mal auf Motzi warten, der kann dir das wohl besser erklären.
|
Re: Falsche Speicherbereiche
Hi!
Ok, dann warte ich mal gespannt :cyclops: Ciao Frederic |
Re: Falsche Speicherbereiche
Moin!
Zitat:
MfG Muetze1 |
Re: Falsche Speicherbereiche
Obacht !
Sobald die Funktion SetDetails verlassen wird, zeigt result.usri3_name ins Nirvana (ungültiger Speicherbereich).
Delphi-Quellcode:
Mag sein, dass result.usri3_name noch auf sinnvolle Daten zeigt;
function SetDetails: TUserInfo3;
begin ZeroMemory(@result, sizeof(result)); result.usri3_name := PWideChar(WideString(GetText(ID_EDT_USER))); aber die Daten können jederzeit durch andere Daten überschrieben werden. Du brauchst 2 Strukturen: eine mit zeigerlosen Delphi-Datentypen und eine passend zu USER_INFO_3. Im Betrag ![]() Übrigens: die MSDE sagt du sollst USER_INFO_4 nehmen: The USER_INFO_3 structure contains information about a user account, including the account name, password data, privilege level, the path to the user's home directory, relative identifiers (RIDs), and other user-related network statistics. It is recommended that you use the USER_INFO_4 structure instead. |
Re: Falsche Speicherbereiche
Zitat:
Zitat:
Hm, beim ir steht da aber auch: Zitat:
|
Re: Falsche Speicherbereiche
Moin!
Zitat:
MfG Muetze1 |
Re: Falsche Speicherbereiche
Nein, shmia hat nicht recht, der Compiler nimmt da alle nötigen Zwischenschritte vor.. ich hab am Anfang auch das als Fehlerursache im Aug gehabt und einiges entsprechend umgestellt, der Fehler blieb aber.
Inzwischen hab ich festgestellt, dass der Fehler wirklich bei den Typecasts lag, allerdings nicht auf Delphi-Seite, sondern auf API-Seite. In dem Prog wird recht oft von String auf WideString und PWideString gecastet. Bei jedem dieser Casts werden intern vom Compiler entsprechende Zwischenschritte durchgeführt die mit den APIs SysAllocStringLen und SysFreeString arbeiten. Ganz erklären kann ich es nicht, aber offensichtlich kommt mit den vielen Typecasts und damit verbundenem Speicher allozieren/deallozieren der Memory-Manager dieser APIs durcheinander, jedenfalls liefert beim 2ten Typecast die API-Funktion SysAllocStringLen als Ergebnis einen Zeiger auf dieselbe Adresse zurück auf die auch ein Feld von UserInfo zeigt. An genau dieser Stelle wurde zuvor bereits ein andrer WideString durch einen entsprechenden Typecast und Aufruf von SysAllocStringLen abgelegt. Offensichtlich versucht der Memory-Manager den Speicher wiederzuverwenden, nur dass in diesem Fall eben an dieser Stelle noch ein andrer String liegt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:04 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