Bug in der Typelib zum DWebBrowserEvents2 interface
Symptom: FileDownload() wird zwar aufgerufen, jedoch kann ein Download nicht verhindert werden, was durch Setzen des ersten Parameters auf TRUE möglich sein müßte.
Problem: Die Signatur der FileDownload()-Methode in der Typelib von MS ist fehlerhaft!
Achtung: wenn man aus der Typelib des
DWebBrowserEvents2 (enthalten in shdocvw.dll) bzw dem Interface, enthalten in exdisp.h/exdispid.h automatisch eine
Unit erzeugen läßt um das Interface zu implementieren, dann wird ein Fehler in diese Implementation eingebaut. Gleiches gilt, wenn man den Dokumentationen bis inklusive "Platform
SDK Release: February 2003" folgt, denn dort wird als Prototyp dies angegeben:
Code:
void FileDownload(VARIANT_BOOL *&Cancel);
Korrekt wäre jedoch:
Code:
void FileDownload(
VARIANT_BOOL *ActiveDocument,
VARIANT_BOOL *Cancel
);
Es handelt sich dabei um DISPID_FILEDOWNLOAD == 270 ("Fired to indicate the File Download dialog is opening") und exakter ausgedrückt, wie
hier zu finden, um folgende Ereignis-Methode (entnommen aus obiger Quelle - TWebBrowserEvents implementiert das Interface):
procedure DoFileDownload(var Cancel: WordBool); safecall;
Hier aus der Invoke-Methode des Dispatchers die Behandlung dieser speziellen DISPID:
Delphi-Quellcode:
270: begin
DoFileDownload (dps.rgvarg^ [pDispIds^ [0]].pbool^);
Result := S_OK;
end;
Delphi-Quellcode:
procedure TWebBrowserEvents.DoFileDownload(var Cancel: WordBool);
begin
if not Assigned (FileDownload) then System.Exit;
FileDownload (Self, Cancel);
end;
Delphi-Quellcode:
TFileDownloadEvent = procedure(Sender: TObject;
var Cancel: WordBool) of object;
Microsoft selbst
räumt ein, daß in der Typelib eine falsche Signatur der FileDownload-Methode vorgegeben wird. Allerdings ist nun das Problem, daß die Methode zwar beim entsprechenden Event aufgerufen wird, jedoch die Parameterübergabe komplett im Eimer ist, weil die Signatur der Methode nicht stimmt. Es wird nämlich statt TRUE an den eigentlichen Cancel-Parameter zu übergeben, das TRUE an den ActiveDocument-Parameter übergeben. Dumme Sache
An obigen Quellen müssen folgende Änderungen vorgenommen werden:
procedure DoFileDownload(var ActiveDocument: WordBool; var Cancel: WordBool); safecall;
Delphi-Quellcode:
270: begin
DoFileDownload(dps.rgvarg^ [pDispIds^ [0]].pbool^, dps.rgvarg^ [pDispIds^ [1]].pbool^);
Result := S_OK;
end;
Delphi-Quellcode:
procedure TWebBrowserEvents.DoFileDownload(var ActiveDocument: WordBool; var Cancel: WordBool);
begin
if not Assigned (FileDownload) then System.Exit;
FileDownload (Self, ActiveDocument, Cancel);
end;
Delphi-Quellcode:
TFileDownloadEvent = procedure(Sender: TObject;
var ActiveDocument: WordBool; var Cancel: WordBool) of object;
So, das sollte es auch schon gewesen sein. Gefunden habe ich das Ganze durch Probleme in einer C++-Implementation dieses Interfaces. Durch einen
KB-Artikel bin ich dann auf das Problem mit der fehlerhaften Signatur aufmerksam geworden.
Da es mich viel Zeit gekostet hat, dachte ich die Codelib sei für diese Sache genau der richtige Platz! So müssen sich andere nicht auch wie ich mühsam auf die Suche nach dem Problem machen
Ich hoffe, daß ich nix übersehen habe, da ich wie gesagt, das Ganze nur in C++ benutze.