Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Hallo Cherry!
schau dir mal die Threads an ADSI Stackproblem. vielleicht liegt es bei dir auch an einem Stack-Problem(?) Damit würden sich zumindest einige der Probleme erklären... |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Dezipaitor pointed me to this topic, although I didn't test your code I am sure the problem is the declaration in AdsHlp:
Delphi-Quellcode:
which should be using PWideChar instead of WideString. The declaration in the Jedi Apilib (JwaActiveDs) is correct btw:
function ADsOpenObject(lpszPathName:WideString;
lpszUserName:WideString; lpszPassword:WideString; dwReserved:DWORD; const riid:TGUID; out ppObject):HRESULT; safecall;
Delphi-Quellcode:
function ADsOpenObject(lpszPathName, lpszUserName, lpszPassword: LPCWSTR;
dwReserved: DWORD; const riid: REFIID; out ppObject: Pointer): HRESULT; stdcall; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Nun habe ich ein kleines Folgeproblem... Bis jetzt hat bei mir die Funktion ADsGetObject/ADsOpenObject immer eine EOleException ausgelöst, wenn was nicht i.O. war. Diese konnte ich dann super verwenden. Wenn jetzt z.B eine Authentifizierung mit ADsOpenObject() fehlschlägt, kann ich zwar checken ob SUCCEEDED(HRESULT) oder nicht, jedoch löst es (nachdem die Funktionen korrekt deklariert sind, nochmals Danke Remko) keine eOleExceptions mehr aus... habe jetzt angefangen mir dazu eine Hilfsfunktion zu bauen, nur leider scheints endlos zu sein, jedenfalls der ADsOpenObject Fehlercode wenn ich z.B ein falsches Passwort angebe, habe ich noch nicht rausgekriegt. Oder ist der Ansatzt schon mal falsch?
Delphi-Quellcode:
function ShowEx(hr: HRESULT): String;
resourcestring rsERROR_FILE_NOT_FOUND = 'Objekt nicht gefunden.'; rsERROR_ACCESS_DENIED = 'Zugriff verweigert.'; rsERROR_NOT_ENOUGH_MEMORY = 'System hat zuwenig speicher.'; rsERROR_GEN_FAILURE = 'Unbekannter Fehler.'; rsERROR_DEV_NOT_EXIST = 'Server ist nicht verfügbar.'; rsERROR_BAD_NET_RESP = 'Kommunikation mit dem LDAP-Server kann nicht aufgebaut werden.'; rsERROR_UNEXP_NET_ERR = 'Ver- / Entschlüsselungsfehler ist aufgetreten.'; rsERROR_TOO_MANY_NAMES = 'Limite der verbundenen Administratoren ist erreicht.'; rsERROR_INVALID_PASSWORD = 'Authentifizierung fehlgeschlagen.'; rsERROR_INVALID_PARAMETER = 'Syntax oder Parameter ist nicht korrekt'; rsERROR_OPEN_FAILED = 'Operationsfehler ist aufgetreten.'; rsERROR_INSUFFICIENT_BUFFER = 'Resultat ist zu gross.'; rsERROR_INVALID_NAME = 'Syntaxfehler.'; rsERROR_INVALID_LEVEL = 'Protokollfehler.'; rsERROR_ALREADY_EXISTS = 'Objekt ist bereits vorhanden.'; rsERROR_MORE_DATA = 'Es wurden nicht alle benötigten Informationen erhalten.'; rsERROR_BUSY = 'Server ist beschäftigt.'; rsERROR_CAN_NOT_COMPLETE = 'Server kann die Operation nicht durchführen.'; rsERROR_SERVICE_REQUEST_TIMEOUT = 'Timeout abgelaufen.'; rsERROR_EXTENDED_ERROR = 'Erweiterter Fehler.'; rsERROR_CANCELLED = 'Aktion wurde durch den Benutzer abgebrochen.'; rsERROR_NOT_ENOUGH_QUOTA = 'Zeit- oder Grössenlimit erreicht.'; rsERROR_LOGON_FAILURE = 'Die angegebene Anmeldeinformationen sind ungültig.'; rsERROR_OBJECT_ALREADY_EXISTS = 'Das Objekt ist bereits vorhanden.'; begin if (hr and ERROR_FILE_NOT_FOUND = 0) then result := rsERROR_FILE_NOT_FOUND else if (hr and ERROR_ACCESS_DENIED = 0) then result := rsERROR_ACCESS_DENIED else if (hr and ERROR_NOT_ENOUGH_MEMORY = 0) then result := rsERROR_NOT_ENOUGH_MEMORY else if (hr and ERROR_GEN_FAILURE = 0) then result := rsERROR_GEN_FAILURE else if (hr and ERROR_DEV_NOT_EXIST = 0) then result := rsERROR_DEV_NOT_EXIST else if (hr and ERROR_BAD_NET_RESP = 0) then result := rsERROR_BAD_NET_RESP else if (hr and ERROR_UNEXP_NET_ERR = 0) then result := rsERROR_UNEXP_NET_ERR else if (hr and ERROR_TOO_MANY_NAMES = 0) then result := rsERROR_TOO_MANY_NAMES else if (hr and ERROR_INVALID_PASSWORD = 0) then result := rsERROR_INVALID_PASSWORD else if (hr and ERROR_INVALID_PARAMETER = 0) then result := rsERROR_INVALID_PARAMETER else if (hr and ERROR_OPEN_FAILED = 0) then result := rsERROR_OPEN_FAILED else if (hr and ERROR_INSUFFICIENT_BUFFER = 0) then result := rsERROR_INSUFFICIENT_BUFFER else if (hr and ERROR_INVALID_NAME = 0) then result := rsERROR_INVALID_NAME else if (hr and ERROR_INVALID_LEVEL = 0) then result := rsERROR_INVALID_LEVEL else if (hr and ERROR_ALREADY_EXISTS = 0) then result := rsERROR_ALREADY_EXISTS else if (hr and ERROR_MORE_DATA = 0) then result := rsERROR_MORE_DATA else if (hr and ERROR_BUSY = 0) then result := rsERROR_BUSY else if (hr and ERROR_CAN_NOT_COMPLETE = 0) then result := rsERROR_CAN_NOT_COMPLETE else if (hr and ERROR_SERVICE_REQUEST_TIMEOUT = 0) then result := rsERROR_SERVICE_REQUEST_TIMEOUT else if (hr and ERROR_EXTENDED_ERROR = 0) then result := rsERROR_EXTENDED_ERROR else if (hr and ERROR_CANCELLED = 0) then result := rsERROR_CANCELLED else if (hr and ERROR_NOT_ENOUGH_QUOTA = 0) then result := rsERROR_NOT_ENOUGH_QUOTA else if (hr and ERROR_LOGON_FAILURE = 0) then result := rsERROR_LOGON_FAILURE end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
AdsOpenObject always returns a HRESULT which you can check against known values (case hr of). When you declare a function as safecall in Delphi a wrapper (sometimes called an exception firewall) is added that will raise exceptions for you. If you want you can declare the function as safecall (just replace stdcall with safecall) and use a try..except handler.
PS: the other functions in AdsHlp such as AdsGetObject have the same declaration using WideString so you should change those as well... |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Danke an Remko für den Tipp! :thumb: |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Wenn ich die Funktionen AdsGetObject/AdsOpenObject mit safecall deklariere, werden zwar die exceptions wieder ausgelöst nur verhaltet sich das Ganze wieder ähnlich unstabil wie vorher... Diese Funktion zeigt mir einen Benutzer an und die dazugehörigen Gruppen... Dies funktioniert wenn ich die Funktionen im Wrapper mit stdcall deklariere, nicht aber mit safecall! >> wenn ich das Auflisten der Gruppen auskommentiere gehts... ist doch komisch oder?
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var usr: IADsUser; begin ClearFields; ShowUser(EdLDAP.Text, CBShowUser); sEditedFields.Clear; sOldObjectPath := EdLDAP.Text; if SUCCEEDED(AccessObject(EdLDAP.Text, IADsUser, usr)) then EnumGroupsOfUser(usr, ListBox1.Items); //<-- Access Violation here >> Die Haltepunkte in der Funktion kommen nicht zum Zug!!! end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
I don't understand what you are trying to do with showex and the hr values, you should use the error values as declared in JwaAdsErr.pas such as E_ADS_BAD_PATHNAME and E_ADS_INVALID_DOMAIN_OBJECT.
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
ist euch eigentlich aufgefallen dass die If Bedingungen von cherry falsch sind ?
Zitat:
richtig wäre :
Delphi-Quellcode:
if ((hr and ERROR_FILE_NOT_FOUND)= ERROR_FILE_NOT_FOUND) then
result := rsERROR_FILE_NOT_FOUND |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Ich kann mich nur schon wieder aufregen, dass jeder glaubt so einfach von C nach Delphi WinAPI Header Dateien konvertieren zu können. Der Thread hier ist ein großes Beispiel, dass es oftmals nicht funktioniert.
Ich vermute noch viel mehr Fehler in diesen Units. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Ich hab nicht direkt dich damit gemeint. Aber schön, dass du dich angesprochen fühlst.
Nur meine ich, dass man genau deshalb solche offziellen Bibliotheken, wie die JEDI API verwenden sollte. Und wenn dort ein Fehler drin ist, dann schreibt man eine Mail mit der Vermutung. Wir schauen dann nach und sehen es dann meist auch schon (jahrelange Erfahrung). Aber wenn jemand die Konvertierung selbst macht, dann ist es meist so, dass diese/r nur seinen/ihren Quelltext postet (wenn überhaupt) und man garnicht mitbekommt, dass er/sie die Übersetzung selbst gemacht hat. Das war reiner Zufall, dass ich Remko diesen Thread gezeigt habe und er aus Interesse die Übersetzungen angeschaut hat, da er selbst an einer AD Klasse für JWSCL arbeitet. Aber er/sie hätte sich soviel Arbeit und Zeit erspart, indem er einfach schon die (richtige) Vorlage genommen hätte. Zitat:
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Ok. Ich verwende jetzt die jedi Units und es funktioniert soweit super. Nur habe ich immer noch das Problem, dass ich mit den HRESULT nicht klar komme... Ich nehme nochmals das Besipiel (AdsGetObject) Mit untenstehendem Code ergibt sich folgendes: #1: Ich verwende einen Falschen Benutzername und Passwort -> result = 16 >> S_ADS_ERRORSOCCURRED #2: Ich will auf ein Objekt zugreiffen das nicht existiert -> result = 0 >> Keine Übereinstimmung
Delphi-Quellcode:
Nun mache ich das Selbe, verwende aber die Vergleichsweise die mir Corpsman unterbreitet hat:result := '0'; if (hr and E_ADS_BAD_PATHNAME) = 0 then result := '1' else if (hr and E_ADS_INVALID_DOMAIN_OBJECT) = 0 then result := '2' else if (hr and E_ADS_INVALID_USER_OBJECT) = 0 then result := '3' else if (hr and E_ADS_UNKNOWN_OBJECT) = 0 then result := '4' else if (hr and E_ADS_PROPERTY_NOT_SET) = 0 then result := '5' else if (hr and E_ADS_PROPERTY_NOT_SUPPORTED) = 0 then result := '6' else if (hr and E_ADS_PROPERTY_INVALID) = 0 then result := '7' else if (hr and E_ADS_OBJECT_UNBOUND) = 0 then result := '8' else if (hr and E_ADS_PROPERTY_NOT_MODIFIED) = 0 then result := '9' else if (hr and E_ADS_PROPERTY_MODIFIED) = 0 then result := '10' else if (hr and E_ADS_CANT_CONVERT_DATATYPE) = 0 then result := '11' else if (hr and E_ADS_PROPERTY_NOT_FOUND) = 0 then result := '12' else if (hr and E_ADS_OBJECT_EXISTS) = 0 then result := '13' else if (hr and E_ADS_SCHEMA_VIOLATION) = 0 then result := '14' else if (hr and E_ADS_COLUMN_NOT_SET) = 0 then result := '15' else if (hr and S_ADS_ERRORSOCCURRED) = 0 then result := '16' else if (hr and S_ADS_NOMORE_ROWS) = 0 then result := '17' else if (hr and S_ADS_NOMORE_COLUMNS) = 0 then result := '18' else if (hr and E_ADS_INVALID_FILTER) = 0 then result := '19'; #1: Ich verwende einen Falschen Benutzername und Passwort -> result = 0 >> Keine Übereinstimmung #2: Ich will auf ein Objekt zugreiffen das nicht existiert -> result = 0 >> Keine Übereinstimmung
Delphi-Quellcode:
Ich habe das Ganze Spielchen auch noch mit Case hr of E_ADS_BAD_PATHNAME: usw ... gemacht,result := '0'; if ((hr and E_ADS_BAD_PATHNAME) = E_ADS_BAD_PATHNAME) then result := '1' else if ((hr and E_ADS_INVALID_DOMAIN_OBJECT) = E_ADS_INVALID_DOMAIN_OBJECT) then result := '2' else if ((hr and E_ADS_INVALID_USER_OBJECT) = E_ADS_INVALID_USER_OBJECT) then result := '3' else if ((hr and E_ADS_UNKNOWN_OBJECT) = E_ADS_UNKNOWN_OBJECT) then result := '4' else if ((hr and E_ADS_PROPERTY_NOT_SET) = E_ADS_PROPERTY_NOT_SET) then result := '5' else if ((hr and E_ADS_PROPERTY_NOT_SUPPORTED) = E_ADS_PROPERTY_NOT_SUPPORTED) then result := '6' else if ((hr and E_ADS_PROPERTY_INVALID) = E_ADS_PROPERTY_INVALID) then result := '7' else if ((hr and E_ADS_OBJECT_UNBOUND) = E_ADS_OBJECT_UNBOUND) then result := '8' else if ((hr and E_ADS_PROPERTY_NOT_MODIFIED) = E_ADS_PROPERTY_NOT_MODIFIED) then result := '9' else if ((hr and E_ADS_PROPERTY_MODIFIED) = E_ADS_PROPERTY_MODIFIED) then result := '10' else if ((hr and E_ADS_CANT_CONVERT_DATATYPE) = E_ADS_CANT_CONVERT_DATATYPE) then result := '11' else if ((hr and E_ADS_PROPERTY_NOT_FOUND) = E_ADS_PROPERTY_NOT_FOUND) then result := '12' else if ((hr and E_ADS_OBJECT_EXISTS) = E_ADS_OBJECT_EXISTS) then result := '13' else if ((hr and E_ADS_SCHEMA_VIOLATION) = E_ADS_SCHEMA_VIOLATION) then result := '14' else if ((hr and E_ADS_COLUMN_NOT_SET) = E_ADS_COLUMN_NOT_SET) then result := '15' else if ((hr and S_ADS_ERRORSOCCURRED) = S_ADS_ERRORSOCCURRED) then result := '16' else if ((hr and S_ADS_NOMORE_ROWS) = S_ADS_NOMORE_ROWS) then result := '17' else if ((hr and S_ADS_NOMORE_COLUMNS) = S_ADS_NOMORE_COLUMNS) then result := '18' else if ((hr and E_ADS_INVALID_FILTER) = E_ADS_INVALID_FILTER) then result := '19'; auch hier ergab sich: #1: Ich verwende einen Falschen Benutzername und Passwort -> result = 0 >> Keine Übereinstimmung #2: Ich will auf ein Objekt zugreiffen das nicht existiert -> result = 0 >> Keine Übereinstimmung Ich scheine ja wohl grundsätzlich was falsch zu machen, aber was? |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
D.h. einfach, dass entweder hr = 0 oder ein Wert ist, den du nicht abfängst.
Nimm OleCheck(ADBla()); ,um eine FehlerException zu bekommen. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Und noch das letzte mal das ich eure Nerven in diesem Thread strapaziere bevor ich ihn dann schliesse... Da die Deklaration von ADsGetObject nun einen Pointer erwartet als out Parameter, habe ichs folgendermassen gelöst:
Delphi-Quellcode:
Ist das grundsätzlich richtig? oder würde man das anders machen?function TForm1.AccessObject(const PathName: string; const riid:TGUID; out ppObject: Pointer): HRESULT; var e: EOleSysError; begin if (EdUsername.Text <> '') and (EdPassword.Text <> '') then result := ADsOpenObject(LPCWSTR(PathName), LPCWSTR(EdUsername.Text), LPCWSTR(EdPassword.Text), ADS_USE_ENCRYPTION, riid, ppObject) else result := ADsGetObject(LPCWSTR(PathName), riid, ppObject); if not Succeeded(result) then begin e := EOleSysError.Create('', result, 0); MessageDlg(e.Message, mtError, [mbOK], 0); end; end; procedure TForm1.Button1Click(Sender: TObject); var usr: Pointer; begin ClearFields; ShowUser(EdLDAP.Text, CBShowUser); sEditedFields.Clear; sOldObjectPath := EdLDAP.Text; if SUCCEEDED(AccessObject(EdLDAP.Text, IADsUser, usr)) then EnumGroupsOfUser(IADsUser(usr), ListBox1.Items); end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Just cast the interface to pointer when passing it to AdsGetObject
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
btw: here is a link to the Win32 error codes for Adsi: http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Delphi-Quellcode:
???????? Was ist das?
if not Succeeded(result) then
begin e := EOleSysError.Create('', result, 0); MessageDlg(e.Message, mtError, [mbOK], 0); end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Delphi-Quellcode:
daraus, oder so in der Art.
if not Succeeded(result) then
begin e := EOleSysError.Create('', result, 0); SetLastError(e.Message); end; Ok, jetzt drängt sich aber doch noch was auf: und zwar ExecuteSearch, hast du da vielleicht ein Beispiel dazu... Meine Variante funktioniert natürlich so nicht mehr. Und ich weiss noch wie lange ich damals hatte um die Funktion hinzubekommen. Konkret gibts ne Zugriffsverletzung beim Aufruf von: "hr := search.GetNextRow(Pointer(ptrResult));" Letztes mal, weiss ich noch, wars so, das ich das ganze IDirectorySearch geändert habe. Sprich alle Pointer auf THandle geändert, dann hats geklappt. Nun verwende ich ja aber JwaAdsTLB und da sind die Pointer wieder und ich denke die JEDIS haben das schon richtig gemacht?! Meine Suchfunktion ist etwas "speziell", ich Poste sie trotzdem mal... Wäre jedoch um ein einfaches Beispiel (das mit den JEDI Units funktioniert) sehr dankbar.
Delphi-Quellcode:
{******************************************************************************}
// OBJECT: THIS FUNCTION EXECUTES A SEARCH. // EXPECTED PARAMETERS: searchfilter eg. = (&(|(objectClass=user)(objectClass=group)(objectClass=organizationalUnit))(|(Name=*'+EdSearch.Text+'*)(sAMAccountName=*'+EdSearch.Text+'*))) // CallBackFunction interface: TCallBackResultArray = procedure(data: TResultArray) of object; -> TResultArray is an 2dimensional array of string // OPTIONAL PARAMETERS: Attributes: eg: 'Name;AdsPath;Class;' -> A delimited String to pass which defines the attributes you want to get. default: Name;AdsPath; // LDAPBeginingPath: eg: OU=example,OU=this,DC=domain1,DC=lan -> means the search will be executed on this path. default: search whole AD {******************************************************************************} procedure TEADSObject.DirectorySearch(searchfilter: string; CallBackFunction: TCallBackResultArray; Attributes: string = 'Name;AdsPath;'; LDAPBeginingPath: string = 'ROOTDSE'); var search: IDirectorySearch; ptrResult: THandle; opt: ads_searchpref_info; dwCount: DWORD; hr: HResult; col: ads_search_column; dwErr: DWord; szErr : array[0..255] of WideChar; szName : array[0..255] of WideChar; I: Integer; ArrResult: TStringArray2; ArrResCnt: Integer; AttrArray: array of PWideChar; Attribute: string; empty: Boolean; begin // create an attributes array from the attributes passed by a delimitted string for I := 1 to Length(Attributes) do begin if Attributes[I] = ';' then begin SetLength(AttrArray, Length(AttrArray)+1); getmem(AttrArray[Length(AttrArray)-1], 256); StringToWideChar(Attribute, AttrArray[Length(AttrArray)-1], 256); Attribute := ''; end else Attribute := Attribute + Attributes[I] end; // for faster search set a LDAPBeginingPath to execute the search within this container if LDAPBeginingPath = 'ROOTDSE' then LDAPBeginingPath := AdsMgr.ADSController.LDAPPATH; // get the search object if SUCCEEDED(AccessObject(LDAPBeginingPath, IDirectorySearch, search)) then begin try // set parameters opt.dwSearchPref := ADS_SEARCHPREF_SEARCH_SCOPE OR ADS_SEARCHPREF_SORT_ON; opt.vValue.dwType := ADSTYPE_INTEGER; opt.vValue.__MIDL_0010.Integer := ADS_SCOPE_SUBTREE; // setting search preferences if not SUCCEEDED(search.SetSearchPreference(opt, 1)) then begin ADsGetLastError(dwErr, @szErr[0], 254, @szName[0], 254); ShowMessage(WideCharToString(szErr)); Exit; end; // prepare dwCount := Length(AttrArray); ArrResCnt := 1; // execute the search hr := search.ExecuteSearch(LPCWSTR(searchfilter), @AttrArray[0], dwCount, Pointer(ptrResult)); // handle the result if hr is S_OK if SUCCEEDED(hr) then begin // get first row hr := search.GetNextRow(Pointer(ptrResult)); // <<<<<<<<<< ACCESS VIOLATION // repeat until no more rows while (hr = S_OK) do // (S_NOMORE_ROWS) < JEDI scheints nicht zu kennen begin // redim result array SetLength(ArrResult, ArrResCnt); empty := true; // for each attribute you want to get (defined in AttrArray) for I := 0 to dwCount -1 do begin // get column if Succeeded(search.GetColumn(Pointer(ptrResult), @AttrArray[I], col)) then begin if col.pADsValues <> nil then begin // redim result array (2 dimensional string array) SetLength(ArrResult[ArrResCnt-1], I+1); // fill values into the result array ArrResult[ArrResCnt-1,I] := col.pADsValues^.__MIDL_0010.DNString; //ArrResult[ArrResCnt-1,I] := col.pADsValues^.__MIDL_0010.BackLink.ObjectName; [AHAAA] empty := false; end; search.FreeColumn(col); end; end; hr := search.GetNextRow(Pointer(ptrResult)); // only redim the result array next time, if there was a value found // we dont want empty fields in the result array. if not empty then Inc(ArrResCnt); end; end; //search.CloseSearchHandle(ptrResult); except //search._Release; on e: EOleException do AdsMgr.SetLastError(e.Message); end; end; if Length(ArrResult) > 0 then CallBackFunction(ArrResult); end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
You are doing something VERY wrong!
First you declare ptrResult as THandle:
Delphi-Quellcode:
Later on you cast it to a pointer:
ptrResult: THandle;
Delphi-Quellcode:
You are actually lucky that it works because a pointer is actually a dword therefore it works but the correct way would IMO be:
hr := search.ExecuteSearch(LPCWSTR(searchfilter), @AttrArray[0], dwCount, Pointer(ptrResult));
ptrHandle: PHandle;
Delphi-Quellcode:
If you need to pass it as handle later on use
hr := search.ExecuteSearch(LPCWSTR(searchfilter), @AttrArray[0], dwCount, ptrResult);
Delphi-Quellcode:
to derefence the pointer.
ptrHandle^
/Edit just a remark: I know this is just test code but if you change a variable type ALWAYS change it's name as well as you WILL confuse yourself later on ( or DelphiPraxis members reading your code ;-) ) Also when you post example code, please take the effort of cleaning it up as much as possible. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Danke nochmals für dein Engagement. Leider ändert sich auch dann nichts. Auch wenn ich "ptrResult: Pointer;" habe.
Komisch ist, dass "hr := search.ExecuteSearch(LPCWSTR(searchfilter), @AttrArray[0], dwCount, ptrResult);" = S_OK ist, aber die Zeile weiter unten: "hr := search.GetNextRow(Pointer(ptrResult)); " in einer Zugriffsverletzung endet. Hast du viellecht ein funktionierendes Beispiel, das wäre wohl das einfachste. Ansonsten probiere ich mir hier einen ab. ;-) Danke schon mal. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
First you use ptrResult in ExecuteSearch and then you use Pointer(ptrResult) in search.GetNextRow ??
I suggest you do a good cleanup of your code and post that, stating what is and what is not working. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Vllt. braucht man GetFirstResult zuerst?
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Versuche zunächst mal ganz klein anzufangen:
Delphi-Quellcode:
Und auch ...
procedure TForm1.Button3Click(Sender: TObject);
const ColCount = 3; ColNames : array[0..ColCount-1] of PWideChar = ('Name','Description','ADsPath'); var search: IDirectorySearch; ptrResult: Pointer; hr : HRESULT; begin if SUCCEEDED(ADsGetObject(PWideChar('LDAP://DC=thun,DC=lan'), IDirectorySearch, Pointer(search))) then begin if SUCCEEDED(search.ExecuteSearch('(objectClass=organizationalUnit)',@ColNames,ColCount,ptrResult)) then begin hr := search.GetNextRow(ptrResult); // Zugriffsverletzung end; end; end;
Delphi-Quellcode:
Was mach ich denn falsch?
procedure TForm1.Button3Click(Sender: TObject);
const ColCount = 3; ColNames : array[0..ColCount-1] of PWideChar = ('Name','Description','ADsPath'); var search: IDirectorySearch; ptrResult: Pointer; hr : HRESULT; begin if SUCCEEDED(ADsGetObject(PWideChar('LDAP://DC=thun,DC=lan'), IDirectorySearch, Pointer(search))) then begin if SUCCEEDED(search.ExecuteSearch('(objectClass=organizationalUnit)',@ColNames,ColCount,ptrResult)) then begin hr := search.GetFirstRow(ptrResult); // Zugriffsverletzung end; end; end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Hallo
In diesem Beitrag habe ich damals schon auf ein paar Unstimmigkeiten hingewiesen. Das mit der nicht geschriebenen Mail tut mir leid. |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
Zudem habe ich das Testhalber kurz gemacht und es klappte trotzdem nicht... > Zugriffsverletzung an derselben Stelle! |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
I have seen the problem: delphi creates garbage when importing the TypeLib for Active Directory. I reimported the typelib from c:\windows\system32\activeds.tlb with Delphi 2010 and it's still the same mess. The declaration of IDirectorySearch is totally wrong (and the one in AdsHlp.pas is wrong as well).
This works fine for me:
Delphi-Quellcode:
type
ADS_SEARCH_HANDLE = THandle; PADS_SEARCH_HANDLE = ^ADS_SEARCH_HANDLE; // *********************************************************************// // Interface: IDirectorySearch // Flags: (0) // GUID: {109BA8EC-92F0-11D0-A790-00C04FD8D5A8} // *********************************************************************// IDirectorySearch = interface(IUnknown) ['{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}'] function SetSearchPreference(var pSearchPrefs: ads_searchpref_info; dwNumPrefs: LongWord): HResult; stdcall; function ExecuteSearch(pszSearchFilter: PWideChar; pAttributeNames: PWideChar; dwNumberAttributes: LongWord; var phSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function AbandonSearch(phSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetFirstRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetNextRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetPreviousRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetNextColumnName(hSearchHandle: ADS_SEARCH_HANDLE; out ppszColumnName: PWideChar): HResult; stdcall; function GetColumn(hSearchResult: ADS_SEARCH_HANDLE; szColumnName: PWideChar; out pSearchColumn: ads_search_column): HResult; stdcall; function FreeColumn(var pSearchColumn: ads_search_column): HResult; stdcall; function CloseSearchHandle(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; end; procedure TMainForm.Button1Click(Sender: TObject); var ColCount: DWORD; ColNames: array of PWideChar; DirSearch: IDirectorySearch; SearchHandle: ADS_SEARCH_HANDLE; hr : HRESULT; begin ColCount := 1; SetLength(ColNames, 3); ColNames[0] := 'name'; ColNames[1] := 'description'; ColNames[2] := 'adspath'; hr := ADsGetObject(PWideChar('LDAP://DC=rmi,DC=local'), IID_IDirectorySearch, Pointer(DirSearch)); if failed(hr) then Exit; SearchHandle := 0; hr := DirSearch.ExecuteSearch('(objectClass=organizationalUnit)', @ColNames[0], Length(ColNames), SearchHandle); if failed(hr) then Exit; while DirSearch.GetNextRow(SearchHandle) <> S_ADS_NOMORE_ROWS do begin // Do something with result end; DirSearch.CloseSearchHandle(SearchHandle); DirSearch := nil; end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Some more observations: the attribute names in pAttributeNames MUST BE lowerCASE or you will get empty results.
I made some more corrections to the declaration:
Delphi-Quellcode:
Accessing the search results will currently not work because the declaration of ADS_SEARCH_COLUMN is totally wrong in the typelib, so while this code should be correct the results cannot be displayed because of the wrong declaration:
type
ADS_SEARCH_HANDLE = THandle; PADS_SEARCH_HANDLE = ^ADS_SEARCH_HANDLE; PADS_SEARCH_COLUMN = ^ads_search_column; // *********************************************************************// // Interface: IDirectorySearch // Flags: (0) // GUID: {109BA8EC-92F0-11D0-A790-00C04FD8D5A8} // *********************************************************************// IDirectorySearch = interface(IUnknown) ['{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}'] function SetSearchPreference(var pSearchPrefs: ads_searchpref_info; dwNumPrefs: LongWord): HResult; stdcall; function ExecuteSearch(pszSearchFilter: PWideChar; pAttributeNames: PWideChar; dwNumberAttributes: LongWord; var phSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function AbandonSearch(phSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetFirstRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetNextRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetPreviousRow(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; function GetNextColumnName(hSearchHandle: ADS_SEARCH_HANDLE; out ppszColumnName: PWideChar): HResult; stdcall; function GetColumn(hSearchResult: ADS_SEARCH_HANDLE; szColumnName: PWideChar; var pSearchColumn: ads_search_column): HResult; stdcall; function FreeColumn(var pSearchColumn: ads_search_column): HResult; stdcall; function CloseSearchHandle(hSearchResult: ADS_SEARCH_HANDLE): HResult; stdcall; end;
Delphi-Quellcode:
while DirSearch.GetNextRow(SearchHandle) <> S_ADS_NOMORE_ROWS do
begin for i := 0 to Length(ColNames) - 1 do begin hr := DirSearch.GetColumn(SearchHandle, ColNames[i], col); if succeeded(hr) then begin // note that the typelib doesn't know the proper typed pointer and the anonymous union in it OutputDebugString(col.pADsValues^.__MIDL_0010.CaseIgnoreString); DirSearch.FreeColumn(col); end; end; // Do something with result end; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Liste der Anhänge anzeigen (Anzahl: 1)
Hi
hier mein Änderungen:
Delphi-Quellcode:
Im Anhang der Directorysearcher.
// *********************************************************************//
// Schnittstelle: IDirectorySearch // Flags: (0) // GUID: {109BA8EC-92F0-11D0-A790-00C04FD8D5A8} // *********************************************************************// IDirectorySearch = interface(IUnknown) ['{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}'] function SetSearchPreference(var pSearchPrefs: ads_searchpref_info; dwNumPrefs: LongWord): HResult; stdcall; function ExecuteSearch(pszSearchFilter: PWideChar; pAttributeNames: PWideChar; dwNumberAttributes: LongWord; out phSearchResult: THandle): HResult; stdcall; function AbandonSearch(var phSearchResult: THandle): HResult; stdcall; function GetFirstRow(var hSearchResult: THandle): HResult; stdcall; function GetNextRow(hSearchResult: THandle): HResult; stdcall; function GetPreviousRow(var hSearchResult: THandle): HResult; stdcall; function GetNextColumnName(var hSearchHandle: THandle; out ppszColumnName: PWideChar): HResult; stdcall; function GetColumn(hSearchResult: THandle; szColumnName: PWideChar; out pSearchColumn: ads_search_column): HResult; stdcall; function FreeColumn(var pSearchColumn: ads_search_column): HResult; stdcall; function CloseSearchHandle(var hSearchResult: THandle): HResult; stdcall; end; Alter Mann |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Hey! Vielen Dank euch allen :!:
:dancer2: :witch: :bouncing4: :bounce1: :firejump: :bounce2: :hi: :hello: |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Dann geb ich auch meinen Senf ab:
Die JEDI API&WSCL hat einen geschätzten Wert bei Neuerstellung von 5 Millionen USD. @Alter Mann: Remko erstellt gerade eine AD Klasse für JWSCL. Allerdings hat er gerade mehr Arbeit bekommen und daher wird das länger dauern. Hast du nicht etwas Zeit übrig, um mitzumachen? |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
I have created a new version of JwaAdsTlb by hand because the typelib import from Delphi is unable to produce a good file.
I was hoping that Cherry and/or Alter Mann can test the new unit as the conversion was a lot of (boring) work and it's not unimaginable that I made errors. Please let me know... The problem with the AdsValue record is alignment: I found it in the file IADS.h from the SDK which has the following options:
Delphi-Quellcode:
It means that record will be aligned at 8 byte boundaries and Delphi doesn't have an option for that. I was able to solve it by declaring it with a nested case statement:
/* Compiler settings for ads.odl:
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555
Delphi-Quellcode:
ADSVALUE = packed record
case Byte of // Padding 0: ( dwType: ADSTYPE; case _DoNotUse: ADSTYPE of // Padding ADSTYPE_DN_STRING: (DNString: ADS_DN_STRING); ADSTYPE_CASE_EXACT_STRING: (CaseExactString: ADS_CASE_EXACT_STRING); ADSTYPE_CASE_IGNORE_STRING: (CaseIgnoreString: ADS_CASE_IGNORE_STRING); ADSTYPE_PRINTABLE_STRING: (PrintableString: ADS_PRINTABLE_STRING); ADSTYPE_NUMERIC_STRING: (NumericString: ADS_NUMERIC_STRING); ADSTYPE_BOOLEAN: (Boolean: ADS_BOOLEAN); ADSTYPE_INTEGER: (Integer: ADS_INTEGER); ADSTYPE_OCTET_STRING: (OctetString: ADS_OCTET_STRING); ADSTYPE_UTC_TIME: (UTCTime: ADS_UTC_TIME); ADSTYPE_LARGE_INTEGER: (LargeInteger: ADS_LARGE_INTEGER); ADSTYPE_OBJECT_CLASS: (ClassName: ADS_PROV_SPECIFIC); ADSTYPE_PROV_SPECIFIC: (ProviderSpecific: ADS_PROV_SPECIFIC); ADSTYPE_CASEIGNORE_LIST: (pCaseIgnoreList: PADS_CASEIGNORE_LIST); ADSTYPE_OCTET_LIST: (pOctetList: PADS_OCTET_LIST); ADSTYPE_PATH: (pPath: PADS_PATH); ADSTYPE_POSTALADDRESS: (pPostalAddress: PADS_POSTALADDRESS); ADSTYPE_TIMESTAMP: (Timestamp: ADS_TIMESTAMP); ADSTYPE_BACKLINK: (BackLink: ADS_BACKLINK); ADSTYPE_TYPEDNAME: (pTypedName: PADS_TYPEDNAME); ADSTYPE_HOLD: (Hold: ADS_HOLD); ADSTYPE_NETADDRESS: (pNetAddress: PADS_NETADDRESS); ADSTYPE_REPLICAPOINTER: (pReplicaPointer: PADS_REPLICAPOINTER); ADSTYPE_FAXNUMBER: (pFaxNumber: PADS_FAXNUMBER); ADSTYPE_EMAIL: (Email: ADS_EMAIL); ADSTYPE_NT_SECURITY_DESCRIPTOR: (SecurityDescriptor: ADS_NT_SECURITY_DESCRIPTOR); ADSTYPE_DN_WITH_BINARY: (pDNWithBinary: PADS_DN_WITH_BINARY); ADSTYPE_DN_WITH_STRING: (pDNWithString: PADS_DN_WITH_STRING) ); end; _adsvalue = ADSVALUE; PADSVALUE = ^ADSVALUE; LPADSVALUE = PADSVALUE; |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
So nobody wants to test?
|
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Wer könnte die ADS Header Testen? Wir brauchen wirklich Freiwillige hier. Das Problem ist auch, dass sich nicht jeder so gut mit AD auskennt, geschweige denn eines hat.
Und besonders, da wir dieses große Problem gelöst haben, kann man etwas zurück erwarten. Nicht zuletzt ist das hier alles nur für euch: http://blog.delphi-jedi.net/2010/02/15/reminder-to-you/ |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
@Dezipaitor und @Remko
Sorry das ich mich so lange nicht gemeldet habe. Ich werde das sehr gerne testen und dann auch Feedback abliefern. Nur muss ich bis morgen ein Betarelease des Programms bereit haben und bin daher sehr unter druck. Ich konnte die neue JwaAdsTlb leider noch nicht implementieren, da ich zuwenig Zeit hatte. Ich verspreche aber, dass ich das gleich nächste Woche implementiere! Ich werde dann die Erfahrungen die ich machen werden in diesem Thread posten.. ok?! Danke nochmals für eure Hilfe! |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Lieber spät als nie...
Wo kriege ich deine aktuelle JwaAdsHlp und JwaAdsTLB? Ich hab jetzt endlich Zeit dies auszutesten. Oder hast du "nur" die Änderungen gemacht die du hier auch gepostet hast? Dann kann ichs ja auch selber anpassen. Danke. LG |
Re: Zugriffsverletzung ADSI, so was komisches hab ich noch n
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:27 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