News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

CoInvoke

Started by jj2007, September 08, 2012, 10:27:18 AM

Previous topic - Next topic

jj2007

I have added a CoInvoke macro to the MasmBasic library, usage (for example, more below):

   CoInvoke pInterface, IWebBrowserVtbl.get_HWND, addr hWin

There is a somewhat "unfinished" thread in the old forum, and I have a suspicion that the macro shown there might not work correctly. Below is my version (from MasmBasic.inc):

CoInvoke MACRO pInterface:REQ,Method:REQ,args:VARARG
LOCAL is, ct, ciPush$, tmp$, tmpAddr$, errEdx$
  ct=0
  ciPush$ equ <>
  FOR arg, <args>
   ct=ct+1
   ciPush$ CATSTR <arg>, <#>, ciPush$
  ENDM
  ciPush$ CATSTR ciPush$, < >
  WHILE ct
     ct=ct-1
   is INSTR ciPush$, <#>
   tmp$ SUBSTR ciPush$, 1, is-1
   tmpAddr$ CATSTR tmp$, <123>   ; addr
   tmpAddr$ SUBSTR tmpAddr$, 1, 4
   ifidni tmpAddr$, <addr>
      % errEdx$ equ tmp$
      tmp$ SUBSTR ciPush$, 5, is-5
      lea edx, tmp$
      push edx
   else
      ifidni tmp$, <edx>
         ifdef errEdx$
            % echo ### edx overwritten by errEdx$ ###
            .err
         endif
      endif
      push tmp$
   endif
   ciPush$ SUBSTR ciPush$, is+1
  ENDM
  ifdifi <pInterface>, <eax>
   mov eax, pInterface
  endif
  push eax
  mov eax, [eax]
  mov edx, [eax+Method]
  call dword ptr [eax+Method]   ; Method=4, 8, ...
ENDM

One question: In some very old posts by Ernie Murphy (e.g. here) and Japheth, you can find statements like:

.ERR <edx is not allowed as a coinvoke parameter>

Is there any good reason not to allow edx? My version throws an error if edx gets overwritten by an addr xyz, but otherwise I just can't see why edx should not work with CoInvoke... ::)

Just for fun, below a short COM app that launches MSIE (will not assemble with JWasm 2.08):

include \masm32\MasmBasic\MasmBasic.inc   ; download (version 8 Sept 2012 required)
.data?
WebInterface   dd ?   ; will be loaded by CoCreateInstance

.code
CLSID_InternetExplorer   GuidFromString("0002DF01-0000-0000-C000-000000000046")
IID_IWebBrowser2   GuidFromString(D30C1661-CDAF-11D0-8A3E-00C04FC9E26E)

MyBrowser proc url
LOCAL vEmpty:VARIANT, hWin
  ClearLocalVariables uses edi
  mov edi, offset WebInterface
  .if !dword ptr [edi]
   invoke CoCreateInstance, addr CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, addr IID_IWebBrowser2, edi
   cmp eax, S_OK
   jne cci_failed
   CoInvoke [edi], IWebBrowserVtbl.put_StatusBar, VARIANT_FALSE   ; OK, now configure the browser
   CoInvoke [edi], IWebBrowserVtbl.put_MenuBar, VARIANT_FALSE
   CoInvoke [edi], IWebBrowserVtbl.put_Visible, VARIANT_TRUE
   CoInvoke [edi], IWebBrowserVtbl.get_HWND, addr hWin
   invoke ShowWindow, hWin, SW_MINIMIZE   ; MSIE has the bad habit of showing by default a restored window
   invoke ShowWindow, hWin, SW_MAXIMIZE   ; the author likes it maximised ;-)
  .endif
  lea edx, vEmpty
  CoInvoke [edi], IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx   ; COM needs a BSTR, so the ANSI URL needs to be converted
cci_failed:
  PopUses
  ret
MyBrowser endp

   Init
      invoke OleInitialize, NULL
   .if eax==S_OK
      invoke MyBrowser, Chr$("http://masmforum.com/~masm32/board/index.php")
   .endif
      invoke OleUninitialize
   Exit
end start

Source & exe attached below.

Ryan

#1
(Nothing relevant)

My apologies if the original content of this post shifted the focus of the topic.

jj2007

Ok, but at that stage edx could have been used, without any risk, for one of the pushed args...
I have tested passing args with edx with my macros, and as expected, there are no problems.

Ryan

Yeah, it appears my response doesn't really apply.  I was reading through that tutorial from CP.  I was just looking at Japheth's vf macro, and I was asking myself the same question.

japheth


> Ok, but at that stage edx could have been used, without any risk, for one of the pushed args...
> I have tested passing args with edx with my macros, and as expected, there are no problems.

The problem is that expansion is done from left to right - even if the arguments of invoke are pushed from right to left. That means, the code that's using edx to dereference the vtable is created BEFORE the arguments of the function are being pushed.

Ryan

Makes sense now.

Thanks for the explanation  :t

jj2007

Then why can...

  lea edx, vEmpty
  CoInvoke [edi], IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx   ; COM needs a BSTR, so the ANSI URL needs to be converted

... work smoothly, Japheth? Can you show an example where the left-to-right expansion matters in this context?
Thanks, JJ

japheth

Quote from: jj2007 on September 08, 2012, 03:39:58 PM
Then why can...

  lea edx, vEmpty
  CoInvoke [edi], IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx   ; COM needs a BSTR, so the ANSI URL needs to be converted
... work smoothly, Japheth?

Perhaps because your version of CoInvoke has little to do with the CoInvoke macro of Ernest Murphi?


TouEnMasm


edx is not allowed as parameter because he is used as the pointer of interface.
This macro is a modify of the original coinvoke.
Quote
;add: DECLARE_pointeur TEXTEQU <STInterFace>
;where pointeur is
; pointeur dd     ;all name who get the com pointer
; USAGE:
; COM pointeur,Release  ;usefull with duplicate pointer
COM MACRO ppv:REQ,fonction:REQ,args:VARARG
   local InvokeInterface
   computeoffset CATSTR <DECLARE_>,<ppv>
   ;---------- controle les arguments
    FOR arg, <args>     ; edx couldn't be used as parameter
        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
   ;------------ fin de controle --------------------------------
   ;InvokeInterface = concatene ...CATSTR(concatene) MACRO instruction MASM32   
   ;--- ppv is the first arg in STANDARD COM PROTOTYPE ------------
                ;--- the virtual proto need ecx with ppv
    InvokeInterface CATSTR <invoke (computeoffset ptr  [edx]).>,<&fonction,ppv>
    IFNB <args>     ; add the list of parameter arguments if any
        InvokeInterface CATSTR InvokeInterface, <, >, <&args>
    ENDIF
   ; -- charge le pointeur ---------------------
    mov edx, ppv
    mov edx, [edx]
    InvokeInterface      
ENDM

Fa is a musical note to play with CL

jj2007

Quote from: ToutEnMasm on September 08, 2012, 04:52:45 PM
edx is not allowed as parameter because he is used as the pointer of interface.

By often repeating something, it does not become more true. AFAIK there is no valid reason not to use edx in a CoInvoke macro. If you can't believe it, launch Olly to see this:
Original source:
  lea edx, vEmpty
  CoInvoke [edi], IWebBrowserVtbl.Navigate, Ole$(url), edx, edx, edx, edx
Disassembly:
004010D2      .  8D55 F2                 lea edx, [ebp-0E]
004010D5      .  52                      push edx
... get Ole$(URL) in eax ...
004010FE      .  5A                      pop edx
004010FF      .  52                      push edx
00401100      .  52                      push edx
00401101      .  52                      push edx
00401102      .  52                      push edx
00401103      .  50                      push eax <<< push URL
00401104      .  8B07                    mov eax, [edi]
00401106      .  50                      push eax
00401107      .  8B00                    mov eax, [eax]
0040110C      .  FF50 2C                 call near [eax+2C]

TouEnMasm


No need of olly,i have made enough control.
When masm translate the macro , he put the load of edx at the first place.
So if you use edx as argument,he is overwritten.
A simple listing is enough to show how it work.
Fa is a musical note to play with CL

TouEnMasm


Proof is here with the  listing of a macro.
   .LISTALL
   ITextServices TxDraw,DVASPECT_DOCPRINT,0,NULL,NULL,hdcDraw,NULL,prc,\
      NULL,   NULL,NULL,NULL,NULL ;TXTVIEW_INACTIVE
   .NOLIST

Quote
              1C    ;   forme les lignes de codes
0000028D  55         *       push   ebp
0000028E  8B EC      *       mov    ebp, esp
00000290  8B 15 00000244 R  1C     mov edx, ppvITextServices
00000296  8B 12        1C     mov edx, [edx]
00000298  8B 0D 00000244 R  1C     mov ecx,ppvITextServices   
0000029E  6A 00      *       push   +000000000h
000002A0  6A 00      *       push   +000000000h
000002A2  6A 00      *       push   +000000000h
000002A4  6A 00      *       push   +000000000h
000002A6  6A 00      *       push   +000000000h
000002A8  FF 75 0C      *       push   dword  ptr ss:[ebp]+00000000Ch
000002AB  6A 00      *       push   +000000000h
000002AD  FF 75 08      *       push   dword  ptr ss:[ebp]+000000008h
000002B0  6A 00      *       push   +000000000h
000002B2  6A 00      *       push   +000000000h
000002B4  6A 00      *       push   +000000000h
000002B6  6A 08      *       push   +000000008h
000002B8  FF 52 10      *       call   dword  ptr [edx]+000000010h

Fa is a musical note to play with CL

jj2007

Sorry, I can't see your point. My macro works.

japheth

Quote from: jj2007 on September 08, 2012, 05:21:31 PM
Sorry, I can't see your point. My macro works.

Noone has claimed that it is IMPOSSIBLE to write a CoInvoke macro that allows to used register EDX. Both ToutEnMasm and me were very clearly referring to the CoInvoke macro of Ernest Murphy, not yours.

JJ, deliberately misunderstanding people is an indication of a TROLL. Are you a TROLL?

Ryan

I'm curious.  The second last line in the macro has
mov edx, [eax+Method]

What is the point of this?  edx is not used in the last line of the macro, so is this necessary?