Hi all.
For some time now i have been working on a more complete example app for the URLDownloadToFile API (http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/moniker/reference/functions/urldownloadtofile.asp). I would like to use the callback facilities it provides, but that requires the implementation of a class, which as we all know, MASM does not natively provide for.
I have constructed this basic template in c++ and tried to link the resulting object file with the one from my project, but it seems that classes are not as easy to integrate as a simple function.
public class cIBindStatusCallback : IBindStatusCallback
{
public:
STDMETHODIMP QueryInterface(REFIID riid ,void ** ppvObject)
{ return E_NOINTERFACE;}
STDMETHODIMP_(ULONG) AddRef()
{ return 0; }
STDMETHODIMP_(ULONG) Release()
{ return 0;}
STDMETHODIMP OnStartBinding(DWORD grfBSCOption, IBinding* pbinding)
{ return 0; }
STDMETHODIMP GetPriority(LONG* pnPriority)
{ return 0; }
STDMETHODIMP OnLowResource(DWORD dwReserved)
{ return 0; }
STDMETHOD(OnProgress)(ULONG ulProgress,ULONG ulProgressMax,ULONG ulStatusCode,LPCWSTR szStatusText)
{ return 0; }
STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError)
{ return 0; }
STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo)
{ return 0; }
STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize,FORMATETC *pfmtetc,STGMEDIUM* pstgmed)
{ return 0; }
STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk)
{ return 0; }
};
Despite my best efforts over the past few days, i have been unable to recreate this construct in objasm, in fact I've been unable to create much at all in objasm...it would seem i don't have enough experience in hlls...the only class I've ever constructed was the one above and a few in php, which is similar in theory, but not nearly as complex as one in cpp :(
Anyway, to get to the point, I'm hoping someone will be able to help me make use of the callback function, either by utilizing objasm, or if there is some way of manually constructing a class in asm itself. Any help would be appreciated, my ultimate goal is to recreate the C++ class in asm, and be able to pass it as the callback arg for URLDownloadToFile.
Thanks, Ehtyar.
Hi Ehtyar
What you need is an object that provides the interface you need to pass to the URLDownloadToFile function. In our case, the interface pointer is the same as the object instance pointer!
I attached the skeleton of the object and you have to provide the functionality for the callback, filling the methods with your code.
Some of the methods expect BSTRs, so dont forget to include support for them.
Regards,
Biterider
PS: take a look at this link http://www.com.it-berater.org/COM/webbrowser/Interfaces/IBindStatusCallback.htm
[attachment deleted by admin]
Hello,
Best way to use the IBindStatusCallback interface is to translate Urlmon.h with the translator (in the masm32-windows.inc subforum).This provide tou the full set of definitions.
The question is what tasks do you want to made with the class ?.Some soluces are offered by masm.
ToutEnMasm
Quote
STIBindStatusCallback STRUCT
QueryInterface comethod3 ?
AddRef comethod1 ?
Release comethod1 ?
OnStartBinding comethod3 ?
GetPriority comethod2 ?
OnLowResource comethod2 ?
OnProgress comethod5 ?
OnStopBinding comethod3 ?
GetBindInfo comethod3 ?
OnDataAvailable comethod5 ?
OnObjectAvailable comethod3 ?
STIBindStatusCallback ENDS
IBindStatusCallback MACRO Function:REQ, args:VARARG
; definition de la macro locale InvokeInterface
LOCAL InvokeInterface, arg
FOR arg, <args> ;verifier que edx n'est pas dans la liste d'arguments args
IFIDNI <&arg>, <edx> ;
.ERR <edx is not allowed as a coinvoke parameter>
ENDIF
ENDM
IFIDNI <&pInterface>, <edx>
.ERR <edx is not allowed as a coinvoke parameter>
ENDIF
;InvokeInterface = concatene ...CATSTR(concatene) MACRO instruction MASM32
;---------- on doit mettre ppv en premier argument -----------------------------------
InvokeInterface CATSTR <invoke (STIBindStatusCallback PTR[edx]).>,<&Function,ppvIBindStatusCallback>
IFNB <args> ; add the list of parameter arguments if any
InvokeInterface CATSTR InvokeInterface, <, >, <&args>
ENDIF
; forme les lignes de codes
mov edx, ppvIBindStatusCallback
mov edx, [edx]
InvokeInterface
ENDM
Thank you both very much for your help, especially in such a short time.
Firstly to Biterider.
The example you gave me makes a lot of sense, and i have to admit that ObjAsm can make for some very nice looking code, but i am at a complete loss as to how to include it. The project as it stands is created using only standard MASM functionality, and a few macros from macros.asm. So, i replaced my includes with the startup code for ObjAsm, and then based on trial and error, uncommented the includes that were not automatically included by ObjAsm. Seems no matter what i do, i end up with a ton of errors. They seem to consist mostly of syntax errors, undefined/redefined symbols and conflicting parameters either from the IBindStatusCallback.inc, or the ObjAsm macro includes. Errors are also reported about invalid structures at the line numbers of my .DATA and .DATA? sections...
ToutEnMasm, it had occurred to me when i started this project that one could use STRUCTs to define the class, but as evidenced by this post, i don't know enough about this sort of thing to implement it myself. Basically the code you provided in your post is complete voodoo to me, i have absolutely no idea what it's doing or what i should do with it, other than the STRUCT itself.
Now this may be asking a bit much from you both, considering the effort you have both apparently already gone to, and if it is, just say so, and ill drop it. The only way i see me understanding how these are supposed to work, is by having a practical example to adapt to my own needs. Ideally, i would need to either be told or shown exactly how to implement your examples, then provide the functionality myself. For example, if you were to show me a file that invoked the URLDownloadToFile API only, utilizing the callback, with no functionality in itself, i can then add the code you supply to my existing project, and add the functionality i need to the base that you provided. I realise this is asking for a lot, but i am at a loss as to how i am to use these examples. If i am indeed asking too much, please just say so, so that I'm not anxiously awaiting a reply :S
Thanks so much for your help so far, Ehtyar.
Hi Ehtyar
A quick solution for your task is to use the structure ToutEnMasm has pointed you before and fill it with the pointers to your method implementations. Finally pass a pointer to a pointer to this structure to the URLDownloadToFile API.
Use the link I posted above to get an idea about what the methods expect to return.
Regards,
Biterider
Biterider, thanks a lot for your suggestion, i have implemented it as i presumed you meant, but unfortunately it crashes. I have attached my implementation (a very basic version of my project) for you to look at (the full source of the complete project will be posted when it is released). Please take a look at it for me and help me track down my error. Hope i haven't made too big a screw-up of it :S
Thanks again, Ehtyar.
[attachment deleted by admin]
Hi Ehtyar
The error was that what I pointed out with a pointer to a pointer to the interface. I added the missing indirection and the interfacing works as expected. You code still crash because you need to add the code for each interface method. You can see that the methods are called since the int 3 stops the execution and you can use a debugger to inspect what is happening.
Attached you can find the modifications.
Regards,
Biterider
Thank you once again BitRider, but i'm afraid it didn't do the trick. Whilst i was awaiting a reply from here, i came across this nice little example here (http://www.codeproject.com/internet/urldownload.asp) of how one might implement this bleeping API. I have implemented my functions in accordance with those in said example (it's creator also only required use of the OnProgress method) and i am afraid to say it still bleeping crashes. While his example does not seem to operate properly, it does not crash, therefore it would seem i am still doing something incorrectly. If you could please take another look at this revised code, i would be most appreciative.
Thank you once again, Ehtyar.
[attachment deleted by admin]
Hi again
Over night I found the problem. COM passes the instance pointer silently, so you will never find it in any definition, but using MASM you have to include it in your callback procedures. I called it Self and added it to each method of the Interface. Now it works and you can add your code.
Regards,
Biterider
PS: I found another bug in your Interface definition. I uploaded an working version I adapted for the debugging with OA32. You can strip out what you don't need.
[attachment deleted by admin]
Hello,
This is a little explain on how to use what I posted
Quote
pcomethod1 TYPEDEF PROTO :DWORD
pcomethod2 TYPEDEF PROTO :DWORD, :DWORD
// and so on
comethod1 TYPEDEF PTR pcomethod1
comethod2 TYPEDEF PTR pcomethod2
To use the interface you have to got the pointer on the IBindStatusCallback,put in in
ppvIBindStatusCallback (made it by :ppvIBindStatusCallback dd 0).
When it's made you have just to call the macro (instead of invoke) followed by the arguments.
the IBindStatusCallback replace invoke and you use the function exactly as api.
You can use this system to create your own interface (adding a structure) that can be use as a class.
Prompt me if you want i explain it to you.
When you want to provide an interface for an api (a callback ),you have to define each proc (and put code in it),feel the structure with the offset of proc and pass the adress of the structure to the api.
TouEnMasm
I have tested the sample and just made a crash .
It's because THIS_ is missing in the prototypes.
I have also simplify the write of the callback.
ToutEnMasm
[attachment deleted by admin]
Ehtyar,
This might be slightly off-topic but it is a useful extension of your project. The attached file shows you how to download the zip and then it unzips it into a directory called 'install' :8)
Paul
[attachment deleted by admin]
Sorry for the late reply guys, had a bit of a hectic past few days. I have successfully integrated the work of ToutEnMasm and Bitrider into my project :D Thank you both very much for your help, you're each mentioned in the about box. The source will be released after i have tidied up the code and added a few comments, but i may post the executable sometime today.
Paul, it's funny you should be posting in this topic, this project was somewhat inspired by you and is my first GeneSys-only project :). Thanks for the example, but since i managed to avoid C bloat in this project thus far, i might just leave it as it is.
Ehtyar.
Ehtyar,
I love inspiring people and as for your first GeneSys project, I can't wait to see it!
Paul
I hope you're impressed Paul :D It will be up soon.
Ehtyar.