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 ADSI, Stackproblem (https://www.delphipraxis.net/140090-adsi-stackproblem.html)

Alex O. 11. Sep 2009 14:25


ADSI, Stackproblem
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo!

Ich arbeite an einem Replikationsdienst, der peropdisch Mitarbeiterstammdaten (Telefonnr, usw) aus meiner Mitarbeiterdatenbank ins ActiveDirectory schreiben soll.
In einer Testumgebung habe ich das mittels der ADSI-Bibliotheken die ich mir von agnisoft geholt habe schon mal hinbekommen.

Jetzt baue ich das ganze in meinen Dienst ein, und habe jetzt plötzlich ein Problem mit dem Stack, wenn ich die Funktion ADsOpenObject (eine in der Windows-DDL activeds.dll definierte Funktion, die über die Unit adshlp.pas definiert wird).
Soweit ich das sehe wird der Stack nach dem Funktionsaufruf nicht richtig zurückgesetzt (?)

so schaut mein Funktionsaufruf aus:
Delphi-Quellcode:
var
  i: Integer;
  DHR: TDHI_HRAnagraphic;
begin
  ...
  ...
  DHR:=ExpGod.HRAnagraphics.GetItem(qWork.FieldByName('HRID').asInteger);
  ...
  ...
  if DHR.ADUser.asBoolean then
  begin
    i:=$123;
    Res:=HRtoAD(DHR);
    Showmessage(IntToStr(i));
  end;
  ...
  ...
end;
folgendes wird dabei aufgerufen:
Delphi-Quellcode:
function THRReplSrv.HRtoAD(AHR: TDHI_HRAnagraphic): Boolean;
var
  DNameTranslator: TNameTranslator;
  DStr: String;
  DADUser: IADsUser;
  HRes: HREsult;
begin
  Result:=False;

  CoInitialize(nil);
  DNameTranslator:=TNameTranslator.Create;
  try
    DStr:=DNameTranslator.Translate_NT_2_DN(AHr.ADLink.asString);

    if DStr = '' then begin
      exit;
    end
    else begin
      if DADUser <> nil then
        DADUser._Release;

      ADsOpenObject('LDAP://' + DStr, FConfig.AD_Username, FConfig.AD_UserPassword, 0, IADsUser, DADUser);

      if Failed(HRes) then begin
        //LogErrorMessage(...);
        exit;
      end;

      if not(Assigned(DADUser)) then begin
        //LogErrorMessage(...);
        exit;
      end;

      //*** get all the ADSI-Fields...
      DADUser.GetInfo;
      ...
      //*** hier werden die Mitarbeiterstammdaten in die entsprechenden Attribute des AD geschrieben
      ...
      DADUser.SetInfo;
      ...
    Result:=True;
  finally
    if DADUser <> nil then
      DADUser._Release;

    DNameTranslator.Free;
    CoUninitialize;
  end;
end;
(das Unwichtige hab ich mal weggelassen, damit die Übersicht nicht leidet; das Objekt DHR speichert mir meine Mitarbeiterstammdaten)

Ich habe bereits versucht:
- alles unwichtige auszukommentieren (Fehler trat trotzdem auf)
- alles bis auf den Aufruf von ADSOpenObject auszukommentieren (Fehler trat trotzdem auf)
- alles auszuführen, nur der Aufruf von ADSOpenObject wird auskommentiert (Fehler trat NICHT auf)
- den Aufruf von ADSOpenObject mit einem leeren LDAP-String auszuführen (Fehler trat NICHT auf)

das Ergebnis war immer: Wenn der Aufruf von ADSOpenObject erfolgreich gemacht wurde, war der Stack in der oben deklarierten Funktion "zerschossen".
Sprich:
- der Stackpointer im Register ESP war vor dem Aufruf der Funktion HRtoAD = 0012FD94
- nach der Rückkehr aus der Funktion HRtoAD war der plötzlich = 0012F894
sollte der nicht identisch sein?? (Siehe auch die angehängten Screenshots des CPU-Fensters)

ich habe deshalb auch mal extra die (lokal deklarierte) Variable i eingebaut, der ja extra vor dem Aufruf der Funktion ein Wert zugewiesen wird, unmittelbar danach wird aber nicht der erwartete Wert, sondern ein komplett anderer Wert in der Messagebox angezeigt (was ja auch nicht weiter verwunderlich ist, wenn der Stackpointer komplett daneben liegt...)

Hat jemand eine Idee, was da die Ursache sein könnte?
Ich habe zwar betreffend ADSI / Delphi einiges im Gooooogle gefunden, aber nie wurde irgend ein ähnliches Problem berichtet.
das einzige was annähernd mein Problem beschreibt habe ich hier gefunden

Alex O. 12. Sep 2009 11:24

Re: ADSI, Stackproblem
 
mit etwas Glück konnte ich def Fehler selbst finden :-)

für die Nachwelt, hier meine Lösung:

das DADUser._Release darf nicht (!) aufgerufen werden - statt dessen direkt NIL zuweisen, und schon geht's besser (Zumindest kommt der Stack nicht mehr durcheinander)

Delphi-Quellcode:
finally
  //if DADUser <> nil then
  //  DADUser._Release;
  DADUser:=nil;
  ...
end;
Ausserdem musste meine Function so aufrufen
Delphi-Quellcode:
asm
  push ESI;
  push EDI;
end;
  Res:=HRtoAD(DHR);
asm
  pop EDI;
  pop ESI;
end;
die Register ESI und EDI werden anscheinend durch den Aufruf von ADsOpenObject umgebogen und nicht korrekt wiederhergestellt.
Folge war, dass der erste Aufruf der Funktion zwar geklappt hatte, daraufhin aber einige Variablen, nicht mehr erreichbar waren.

vielleicht kann das ja mal jemandem helfen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:45 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