News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Classes in ASM

Started by Ehtyar, November 19, 2006, 05:52:39 AM

Previous topic - Next topic

Ehtyar

Hi all.
For some time now i have been working on a more complete example app for the URLDownloadToFile API. 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.

Biterider

#1
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]

ToutEnMasm

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      


Ehtyar

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.

Biterider

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

Ehtyar

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]

Biterider

#6
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

Ehtyar

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 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]

Biterider

#8
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]

ToutEnMasm

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








ToutEnMasm


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]

PBrennick

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]
The GeneSys Project is available from:
The Repository or My crappy website

Ehtyar

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.

PBrennick

Ehtyar,
I love inspiring people and as for your first GeneSys project, I can't wait to see it!

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Ehtyar

I hope you're impressed Paul :D It will be up soon.

Ehtyar.