Entwickler-Ecke

Windows API - Schutzverletzung in PathRelativePathToA


jaenicke - Sa 10.10.09 18:27
Titel: Schutzverletzung in PathRelativePathToA
Hallo!

Ich möchte ausgehend von einem Pfad die relative Verzeichnisangabe zu einem zweiten Pfad bekommen. (Dabei geht es um die Angabe des Unitpfads bei der automatischen Anpassung einer Delphiprojektdatei.)

Dafür gibt es die Funktion PathRelativePathTo [http://msdn.microsoft.com/en-us/library/bb773740.aspx], die in Delphi 2006 nicht deklariert ist. Daher wollte ich diese dynamisch einbinden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function PathRelativePathToDynA(pszPath: PAnsiChar; const pszFrom: PAnsiChar;
  dwAttrFrom: DWORD; const pszTo: PAnsiChar; dwAttrTo: DWORD): BOOL;
var
  DllHandle: THandle;
  PathRelativePathToFunc: TPathRelativePathToFunc;
begin
  Result := False;
  DllHandle := LoadLibrary('shlwapi.dll');
  if DllHandle <> 0 then
  begin
    @PathRelativePathToFunc := GetProcAddress(DllHandle, 'PathRelativePathToA');
    if Assigned(PathRelativePathToFunc) then
      Result := PathRelativePathToFunc(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo);
    FreeLibrary(DllHandle);
  end;
end;
Leider gibt es beim Aufruf eine Schutzverletzung beim Schreiben an Adresse 80 in der DLL. Der Aufruf sieht so aus (extrahiert und direkt so lauffähig):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
  TargetDir, AProjectFile, ADirectory: string;
begin
  AProjectFile := 'c:\a\b\path';
  ADirectory := 'c:\a\x\y\file';
  SetLength(TargetDir, MAX_PATH);
  if PathRelativePathToDynA(PAnsiChar(TargetDir),
    PAnsiChar(AProjectFile), FILE_ATTRIBUTE_DIRECTORY,
    PAnsiChar(ADirectory), FILE_ATTRIBUTE_NORMAL) then
    SetLength(TargetDir, StrLen(PChar(TargetDir)))
  else
    TargetDir := ADirectory;
  ShowMessage(TargetDir);
Sieht vielleicht jemand wo das Problem liegt? Die Pfade usw. entstammen direkt dem Beispiel aus der Dokumentation.

Vielen Dank schon einmal, schönen Gruß,
Sebastian


BenBE - Sa 10.10.09 19:15

Kannst Du bitte die Deklaration deeines Funktionsprototypen für den dynamischen Aufruf angeben?

Ferner: das MSDN sagt für den ersten Parameter out an, d.h. dieser muss auch in Delphi Writeable sein, also zumindest var, da IMHO aber irgendwo Speicher reserviert werden muss, dürfte auch out eine mögliche Option sein.


Xentar - Sa 10.10.09 19:23

Hab das grad auch mal ausprobiert.. Scheint an der Deklaration von dem Typ zu liegen.

Delphi-Quelltext
1:
  TPathRelativePathToFunc = function(pszPath: PAnsiChar; const pszFrom: PAnsiChar; dwAttrFrom: DWORD; const pszTo: PAnsiChar; dwAttrTo: DWORD): BOOL;                    

geht nicht.


Delphi-Quelltext
1:
  TPathRelativePathToFunc = function(pszPath: PAnsiChar; const pszFrom: PAnsiChar; dwAttrFrom: DWORD; const pszTo: PAnsiChar; dwAttrTo: DWORD): BOOL; stdcall;                    

geht.


jaenicke - Sa 10.10.09 19:25

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Kannst Du bitte die Deklaration deeines Funktionsprototypen für den dynamischen Aufruf angeben?
:oops:

Delphi-Quelltext
1:
2:
  TPathRelativePathToFunc = function(pszPath: PAnsiChar; const pszFrom: PAnsiChar;
    dwAttrFrom: DWORD; const pszTo: PAnsiChar; dwAttrTo: DWORD): BOOL;


Ich wollte gerade noch etwas dazu schreiben, aber da sehe ich schon in orange... so ein blöder Fehler...
Vielen Dank und tut mir leid, das hätte ich eigentlich sehen müssen. :autsch:


Delete - Sa 10.10.09 21:17

Wo ist die Aufrufkonvention?


jaenicke - Sa 10.10.09 21:22

Danke, ja, genau das war der Fehler, das meinte ich mit orange. Das hätte ich wohl klarer dazuschreiben sollen. :oops:
user profile iconXentars Antwort wurde gerade (in orange) via AJAX angezeigt während ich noch die Antwort geschrieben habe, so dass ich nicht weiterschreiben brauchte. ;-)