AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Falsche Speicherbereiche

Ein Thema von Luckie · begonnen am 21. Okt 2004 · letzter Beitrag vom 22. Okt 2004
Antwort Antwort
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

Falsche Speicherbereiche

  Alt 21. Okt 2004, 22:23
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:
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;
Diese fülle ich wie folgt:
Delphi-Quellcode:
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;
Dann die eigentliche Funktion:
Delphi-Quellcode:
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;
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.

Ich habe keinen blassen Schimmer, was da passiert und warum.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 05:20
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von fkerber
fkerber
(CodeLib-Manager)

Registriert seit: 9. Jul 2003
Ort: Ensdorf
6.723 Beiträge
 
Delphi XE Professional
 
#3

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 09:13
Hi!

Auch wenn ich eigentlich davon gar nix verstehe , mal eine Frage dazu:

Heißt das, dass da ein Fehler in Delphi/Compiler ist oder was anderes?


Ciao Frederic
Frederic Kerber
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 09:16
Da musst du mal auf Motzi warten, der kann dir das wohl besser erklären.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von fkerber
fkerber
(CodeLib-Manager)

Registriert seit: 9. Jul 2003
Ort: Ensdorf
6.723 Beiträge
 
Delphi XE Professional
 
#5

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 09:18
Hi!

Ok, dann warte ich mal gespannt

Ciao Frederic
Frederic Kerber
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 09:30
Moin!

Zitat von Luckie:
..., 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.

Ich habe keinen blassen Schimmer, was da passiert und warum.
Für mich ist das denn eindeutig, dass der Speicherbereich auf den ui3 zeigt nicht ordentlich alloziiert wurde. Und daher würde ich vor allem erstmal in die Richtung forschen. Vor allem ist in der o.g. Funktion bisher auch noch keine Alloziierung zu erkennen (kann natürlich in den Sub-Routinen geschehen - sieht man aber nicht)...

MfG
Muetze1
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 09:41
Obacht !
Sobald die Funktion SetDetails verlassen wird, zeigt result.usri3_name ins Nirvana (ungültiger Speicherbereich).
Delphi-Quellcode:
function SetDetails: TUserInfo3;
begin
  ZeroMemory(@result, sizeof(result));
  result.usri3_name := PWideChar(WideString(GetText(ID_EDT_USER)));
Mag sein, dass result.usri3_name noch auf sinnvolle Daten zeigt;
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 http://www.delphipraxis.net/internal...ct.php?t=31191 siehst wie das gemeint ist.

Ü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.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 10:19
Zitat von shmia:
Obacht !
Sobald die Funktion SetDetails verlassen wird, zeigt result.usri3_name ins Nirvana (ungültiger Speicherbereich).
Nein. Das hat schon alles gestimmt. Nach verlassen der Prozedur, war noch alles da. Nur eine Interne Funktion zum Anfordern von Speicher für den String beim Cast hat den Speicher innerhalb des Speichers von ui3 reserviert.

Zitat:
It is recommended that you use the USER_INFO_4 structure instead.
Oh, das muss ich mir mal ankucken.

Hm, beim ir steht da aber auch:
Zitat:
Specifies level two information and additional attributes about the user account. This level is valid only on servers. The buf parameter points to a USER_INFO_4 structure.

Windows 2000/NT: This level is not supported.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 10:54
Moin!

Zitat von Luckie:
Zitat von shmia:
Obacht !
Sobald die Funktion SetDetails verlassen wird, zeigt result.usri3_name ins Nirvana (ungültiger Speicherbereich).
Nein. Das hat schon alles gestimmt. Nach verlassen der Prozedur, war noch alles da. Nur eine Interne Funktion zum Anfordern von Speicher für den String beim Cast hat den Speicher innerhalb des Speichers von ui3 reserviert.
Nein, shmia hat Recht, der Speicherbereich ist wieder frei verfügbar und genaus deshalb wird der Speicher für den String auch in dem Bereich alloziiert, weil der Bereich frei ist.

MfG
Muetze1
  Mit Zitat antworten Zitat
Benutzerbild von Motzi
Motzi

Registriert seit: 6. Aug 2002
Ort: Wien
598 Beiträge
 
Delphi XE2 Professional
 
#10

Re: Falsche Speicherbereiche

  Alt 22. Okt 2004, 11:17
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.
Manuel Pöter
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:49 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