Hab's gefunden. Danke euch für die Unterstützung. Letztlich liegt der Fehler bei
Indy. Kann man das irgendwo melden, in der Hoffnung, dass das gefixt wird? Macht das bei
QC Sinn, weil ja Teil von Delphi, oder kann man sowas auch direkt ans
Indy-Team melden?
Folgendes Beispielprojekt (für Interessierte auch als Paket im Anhang):
Delphi-Quellcode:
unit main;
interface
uses
Winapi.Windows,
Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs, IdSSLOpenSSLHeaders,
Vcl.StdCtrls;
type
TForm2 =
class(TForm)
MemoStatus: TMemo;
ButtonLoadLib: TButton;
ButtonLoadLibOwn: TButton;
procedure ButtonLoadLibClick(Sender: TObject);
procedure ButtonLoadLibOwnClick(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
class var _PEM_read_bio_RSA_PUBKEY:
function(bp: PBIO; x: PPRSA; cb: ppem_password_cb; u: Pointer): PRSA
cdecl;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.ButtonLoadLibClick(Sender: TObject);
begin
MemoStatus.Clear;
if IdSSLOpenSSLHeaders.Load
then begin
MemoStatus.Lines.Add('
OpenSSL loaded');
MemoStatus.Lines.Add('
Handle: '+GetCryptLibHandle.ToString);
if GetCryptLibHandle <> 0
then
begin
_PEM_read_bio_RSA_PUBKEY := GetProcAddress(GetCryptLibHandle, '
PEM_read_bio_RSA_PUBKEY');
if @_PEM_read_bio_RSA_PUBKEY =
nil then
MemoStatus.Lines.Add('
Function not found')
else
MemoStatus.Lines.Add('
Success! Function found!');
end else
MemoStatus.Lines.Add('
Crypo handle invalid')
end else
MemoStatus.Lines.Add('
Failed loading OpenSSL');
end;
procedure TForm2.ButtonLoadLibOwnClick(Sender: TObject);
var
crypHandle: HMODULE;
begin
MemoStatus.Clear;
crypHandle:=SafeLoadLibrary('
libeay32.dll');
if crypHandle<>0
then begin
MemoStatus.Lines.Add('
OpenSSL loaded');
MemoStatus.Lines.Add('
Handle: '+crypHandle.ToString);
_PEM_read_bio_RSA_PUBKEY := GetProcAddress(crypHandle, '
PEM_read_bio_RSA_PUBKEY');
if @_PEM_read_bio_RSA_PUBKEY =
nil then
MemoStatus.Lines.Add('
Function not found')
else
MemoStatus.Lines.Add('
Success! Function found!');
end else
MemoStatus.Lines.Add('
Failed loading OpenSSL');
end;
end.
Der erste Aufruf,
ButtonLoadLibClick
ist angelehnt an das, wie es auch in der von mir genutzten Bibliotheke JOSE.Signing.RSA gemacht werden soll. Hier läuft es auch genauso: unter 32-Bit funktioniert es super, unter 64-Bit findet er die Funktion nicht.
Der zweite Button mit dem Aufruf
ButtonLoadLibClick
kümmert sich selbst nochmal um das Laden der Bibliothek. Das Suchen der gewünschten Funktion klappt dann problemlos sowohl unter
Win32 und Win64.
Und warum behaupte ich nun, das
Indy "schuld" ist?
In der
Unit IdSSLOpenSSLHeaders wird das
Handle auf die libeay32.dll in der globalen Variable hIdCrypto gespeichert und diese ist auch vom Typ HModule. Unter
Win32 wird HModule zu "Cardinal", unter Win64 aber zu UInt64. Die Variable ist aber nur im Implementation-Bereich definiert, also können wir nicht von außen auf sie zugreifen. Nach außen verfügbar macht die
Unit diese Variable über die oben auch genutzte Funktion
GetCryptLibHandle
. Diese Funktion liefert aber nicht HModule zurück, sondern ein Integer. Dadurch wird in der Rückgabe also das
Handle zerschossen - sieht man ganz gut, wenn man mein Testprogramm ausführt und die beiden Handles vergleicht. Dass das nicht passt, ist offensichtlich, denke ich mal.
Ich sag mal so: Aaaaaargh!
Jemand eine Idee für einen Workaround, ohne dass ich die IdSSLOpenSSLHeaders patchen muss?