Ludo,
Thank you very much for your most informative posting. I have spent the week trying to implement the msdn examples in pure Pascal and in Pascal-DLL hybrids. Success in non-threaded asynchrosity eludes me though.
Your example (http://www.lazarus.freepascal.org/index.php?topic=18506.15#msg105226) using URLMON's URLDownloadToFile works perfectly. However, the example is synchronous whilst we need asynchronous. Research indicates that URLOpenPullStream is the more relevant function in our case (because we download asynchronously to both memory streams and files, depending on what flags the user sets and can track the progress of the download). The problem is that URLOpenPullStream and URLDownloadToFile (which I am using as an intermediate coding step) both require a variable of a type that implements the IBindStatusCallback interface, which in turn requires declaration of the IBinding interface. I have tried doing so without success; I share my code below.
Is there a way to access the UrlMon.dll's definition of IBindStatus and IBinding so that these interfaces are available within Lazarus? Currently, the only option I see is to define these interfaces myself. Alternatively, is there an example of a Lazarus definition of these interfaces?
FYI, after the program segfaults, the assembler window points within urlmon!ZonesReInit
Thank you for any help you might provide.
Matthew
-------------------------------Top (Global) Level-------------------------------------------------------
INTERFACE
TYPE
PIUnknown = ^IUnknown;
BINDINFO = RECORD
cbSize: ULONGLONG;
szExtraInfo: LPWSTR;
stgmedData: STGMEDIUM;
grfBindInfoF: DWORD;
dwBindVerb: DWORD;
szCustomVerb: LPWSTR;
cbStgmedData: DWORD;
dwOptions: DWORD;
dwOptionsFlags: DWORD;
dwCodePage: DWORD;
securityAttributes: SECURITY_ATTRIBUTES;
iid1: GUID;
pUnk: PIUnknown;
dwReserved: DWORD;
END;
IBinding = INTERFACE (IUnknown)
FUNCTION Abort(): HRESULT;
FUNCTION GetBindResult(VAR pclsidProtocol: CLSID; VAR pdwResult: CLSID;
VAR pszResult: LPOLESTR; VAR pdwReserved: DWORD): HRESULT;
FUNCTION GetPriority(VAR pnPriority: LongInt): HRESULT;
FUNCTION Resume(): HRESULT;
FUNCTION SetPriority(nPriority: LongInt): HRESULT;
FUNCTION Suspend(): HRESULT;
END;
PIBinding = ^IBinding;
IBindStatusCallback = INTERFACE(IUnknown)
{ // IUnknown members }
Function QueryInterface(constref iid: tguid; out obj): longint stdcall; //Object Pascal--needs modification
{ //Function IUnknown.QueryInterface(constref iid: tguid; VAR obj: Object): longint stdcall; //possible modification }
Function _AddRef: longint stdcall;
Function _Release: longint stdcall;
FUNCTION GetBindInfo(VAR grfBINDF: DWORD; VAR bindinfo: BINDINFO): HRESULT; STDCALL;
FUNCTION GetPriority(VAR pnPriority: LongInt): HRESULT; STDCALL;
FUNCTION OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; pformatetc: PFORMATETC; pstgmed: PSTGMEDIUM): HRESULT; STDCALL;
PROCEDURE OnLowResource(); STDCALL;
FUNCTION OnObjectAvailable(riid: REFIID; punk: PIUnknown): HRESULT; STDCALL;
FUNCTION OnProgress(ulProgress: ULONGLONG; ulProgressMax: ULONGLONG; ulStatusCode: ULONGLONG; szStatusText: LPCWSTR): HRESULT; STDCALL;
FUNCTION OnStartBinding(dwReserved: DWORD; pib: PIBinding): HRESULT; STDCALL;
FUNCTION OnStopBinding(hresult1: HRESULT; szError: LPCWSTR): HRESULT; STDCALL;
END;
{----------------------- IBindStatusCallback stuff -----------------------}
TBindStatusCallback = CLASS(IBindStatusCallback)
PUBLIC
{ // IUnknown members }
Function QueryInterface(constref iid: tguid; out obj): longint stdcall; //Object Pascal--needs modification
{ //Function IUnknown.QueryInterface(constref iid: tguid; VAR obj: Object): longint stdcall; //possible modification }
Function _AddRef: longint stdcall;
Function _Release: longint stdcall;
{ IBindStatusCallback members }
FUNCTION GetBindInfo(VAR grfBINDF: DWORD; VAR bindinfo: BINDINFO): HRESULT; STDCALL;
FUNCTION GetPriority(VAR pnPriority: LongInt): HRESULT; STDCALL;
FUNCTION OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; pformatetc: PFORMATETC; pstgmed: PSTGMEDIUM): HRESULT; STDCALL;
PROCEDURE OnLowResource(); STDCALL;
FUNCTION OnObjectAvailable(riid: REFIID; punk: PIUnknown): HRESULT; STDCALL;
FUNCTION OnProgress(ulProgress: ULONGLONG; ulProgressMax: ULONGLONG; ulStatusCode: ULONGLONG; szStatusText: LPCWSTR): HRESULT; STDCALL;
FUNCTION OnStartBinding(dwReserved: DWORD; pib: PIBinding): HRESULT; STDCALL;
FUNCTION OnStopBinding(hresult1: HRESULT; szError: LPCWSTR): HRESULT; STDCALL;
END;
VAR
gBindStatusCallback: TBINDSTATUSCALLBACK; {TBINDSTATUSCALLBACK;}
IMPLEMENTATION
FUNCTION TBindStatusCallback.QueryInterface(constref iid: tguid; out obj): longint stdcall;
BEGIN
QueryInterface := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback._AddRef: longint stdcall;
BEGIN
_AddRef := E_NOTIMPL;
END;
Function TBindStatusCallback._Release: longint stdcall;
BEGIN
_Release := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback.GetBindInfo(VAR grfBINDF: DWORD; VAR bindinfo: BINDINFO): HRESULT; STDCALL;
BEGIN
GetBindInfo := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback.GetPriority(VAR pnPriority: LongInt): HRESULT; STDCALL;
BEGIN
GetPriority := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback.OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; pformatetc: PFORMATETC; pstgmed: PSTGMEDIUM): HRESULT; STDCALL;
VAR
breakpoint: INT;
BEGIN
breakpoint := 4;
END;
PROCEDURE TBindStatusCallback.OnLowResource(); STDCALL;
BEGIN
;
END;
FUNCTION TBindStatusCallback.OnObjectAvailable(riid: REFIID; punk: PIUnknown): HRESULT; STDCALL;
BEGIN
OnObjectAvailable := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback.OnProgress(ulProgress: ULONGLONG; ulProgressMax: ULONGLONG; ulStatusCode: ULONGLONG; szStatusText: LPCWSTR): HRESULT; STDCALL;
VAR
breakpoint: INT;
BEGIN
breakpoint := 5;
END;
FUNCTION TBindStatusCallback.OnStartBinding(dwReserved: DWORD; pib: PIBinding): HRESULT; STDCALL;
BEGIN
OnStartBinding := E_NOTIMPL;
END;
FUNCTION TBindStatusCallback.OnStopBinding(hresult1: HRESULT; szError: LPCWSTR): HRESULT; STDCALL;
BEGIN
OnStopBinding := E_NOTIMPL;
END;
PROCEDURE DownloadURL (theURLString: Str;
outputStream: TMemoryStream;
toFile: TFile;
outputFile, name, pass: Str);
BEGIN
dest:='C:\Windows\temp\data.txt';
IF URLDownloadToFile(NIL, PChar(theURLString), PChar(Dest), 0, @gBindStatusCallback)=0 THEN
END;