News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

DISP_E_UNKNOWNINTERFACE

Started by GoneFishing, January 11, 2014, 07:10:48 AM

Previous topic - Next topic

GoneFishing

It's my first try with IDispatch . I call GetIDsOfNames and ALWAYS get HRESULT 80020001
DISP_E_UNKNOWNINTERFACE :
QuoteA return value that indicates that the interface identifier passed in riid is not equal to IID_NULL.

include \masm32\include\masm32rt.inc

__UNICODE__ EQU

.data
     IID_IDispatch GUID <00020400h,0000h,0000h,<0C0h,0h,0h,0h,0h,0h,0h,46h>>
     IID_NULL      GUID <00000000h,0000h,0000h,<0h,0h,0h,0h,0h,0h,0h,0h>>
.data?
     lpszProgID    dd ?
     lpszMember    dd ?
     DISPID        dd ?
     pclsid        dd ?
     ppv           dd ?
.code
     start:
     cls
     call main
     inkey
     exit

main proc
     mov eax,uc$("Shell.Application")
     invoke SysAllocString,eax
     mov lpszProgID,eax
     invoke CLSIDFromProgID,eax,addr pclsid
            .if eax != S_OK
                print LastError$(),13,10,0
                ret
            .endif
     print "CLSIDFromProgID : SUCCESS",13,10,0 
     invoke CoInitialize,NULL
     invoke CoCreateInstance,addr pclsid,
                             NULL,
                             CLSCTX_INPROC_SERVER,
                             addr IID_IDispatch,
                             addr ppv
            .if eax != S_OK
                fnx MessageBox,0,hex$(eax),"HRESULT: ",MB_OK 
                print LastError$(),13,10,0
                ret
            .endif
     print "CoCreateInstance: SUCCESS",13,10,0
     mov eax,uc$("NameSpace")
     invoke SysAllocString,eax
     mov lpszMember, eax
   ; ------------------------------------------------------------------------;
   ; invoke IDispatch_GetIDsOfNames, riid, rgszNames, cNames, lcid, rgDispId ;
   ; ------------------------------------------------------------------------;
     push 0                   ;  program terminates abnormally without it :-\ 
     push offset DISPID       ;  rgDispId
     push 800h                ;  lcid
     push 1                   ;  cNames
     push eax                 ;  rgszNames
     push offset IID_NULL     ;  riid
     mov  edx, dword ptr [ppv];  pointer to IDispatch
     mov  eax, [edx]
     mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
     call edx
          .if  eax != S_OK
               fnx MessageBox,0,hex$(eax),"HRESULT: ",MB_OK
               print "GetIDsOfNames   : FAILED ",13,10,0
               jmp _exit
          .endif
     print "GetIDsOfNames   : SUCCESS",13,10,0
_exit:
     invoke SysFreeString , addr lpszProgID
     invoke SysFreeString , addr lpszMember
     invoke CoUninitialize
     ret
main endp

end  start


Awaiting the enlightment from COM gurus  ;)

dedndave

     push 0                   ;  program terminates abnormally without it :-\ 
     push offset DISPID       ;  rgDispId
     push 800h                ;  lcid
     push 1                   ;  cNames
     push eax                 ;  rgszNames
     push offset IID_NULL     ;  riid
     mov  edx, dword ptr [ppv];  pointer to IDispatch
     mov  eax, [edx]
     mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
     call edx


not good   :P

give me a few minutes...

dedndave

something like  this should may work
;###############################################################################################

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM

;###############################################################################################

;IDispatch interface

IDispatch STRUCT
  METHOD(QueryInterface,         _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,                 _this:LPVOID)
  METHOD(Release,                _this:LPVOID)
  METHOD(GetTypeInfoCount,       _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,            _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,          _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:DWORD)
  METHOD(Invoke,                 _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS

;###############################################################################################


;
;
;
    mov     edx,ppv
    mov     ecx,[edx]
    INVOKE  [ecx].IDispatch.GetIDsOfNames,edx,riid,rgszNames,cNames,lcid,rgDispId
;
;
;


EDIT: updated the INVOKE line
edited again - had ECX and EDX swapped

GoneFishing

Thank you , Dave
but still no luck
it crashes

jj2007

With Dave's/qWord's code on top, this builds fine (provided you comment out/complete the UNICODE line):
   ; ------------------------------------------------------------------------;
   ; invoke IDispatch_GetIDsOfNames, riid, rgszNames, cNames, lcid, rgDispId ;
   ; ------------------------------------------------------------------------;
  if 1
rgDispId equ <DISPID>
lcid equ 800h
cNames equ 1
rgszNames equ eax
riid equ <offset IID_NULL>
mov edx,ppv
mov ecx, [edx]
INVOKE  [ecx].IDispatch.GetIDsOfNames,edx,riid,rgszNames,cNames,lcid,rgDispId
  else
     push 0                   ;  program terminates abnormally without it :-\ 
     push offset DISPID       ;  rgDispId
     push 800h                ;  lcid
     push 1                   ;  cNames
     push eax                 ;  rgszNames
     push offset IID_NULL     ;  riid
     mov  edx, dword ptr [ppv];  pointer to IDispatch
     mov  eax, [edx]
     mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
     call edx
  endif
          .if  eax != S_OK
               ; fnx MessageBox,0,hex$(eax),"HRESULT: ",MB_OK
               print "GetIDsOfNames   : FAILED ",13,10,0
               jmp _exit
          .endif
     print "GetIDsOfNames   : SUCCESS",13,10,0
_exit:

dedndave

i have found a few issues

first, if you are going to define the __UNICODE__ symbol, do so before the include files
next, in the IDispatch interface, the function named "Invoke" must be named something else   :P
you have an LCID of 800h - not sure how critical this is, but i replaced it with 409h
the DISPID variable must be an array of DWORDS - if i understand correctly, at least 2 DWORDS


i think we have one more issue
that is that we are passing the pointer to a dynamic string (BSTR)
i seem to recall that dynamic string arrays have the array count in the first element
we should be able to use Hutch's array allocation macro(s)

dedndave

here is what i have so far
__UNICODE__ EQU 1

include \masm32\include\masm32rt.inc

;###############################################################################################

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM

;###############################################################################################

;IDispatch interface

IDispatch STRUCT
  METHOD(QueryInterface,         _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,                 _this:LPVOID)
  METHOD(Release,                _this:LPVOID)
  METHOD(GetTypeInfoCount,       _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,            _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,          _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,                _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS

;###############################################################################################

.data
     IID_IDispatch GUID <00020400h,0000h,0000h,<0C0h,0h,0h,0h,0h,0h,0h,46h>>
     IID_NULL      GUID <00000000h,0000h,0000h,<0h,0h,0h,0h,0h,0h,0h,0h>>
.data?
     lpszProgID    dd ?
     lpszMember    dd ?
     DISPID        dd ?,?
     pclsid        dd ?
     ppv           dd ?
.code
     start:
     cls
     call main
     inkey
     exit

main proc
     mov eax,uc$("Shell.Application")
     invoke SysAllocString,eax
     mov lpszProgID,eax
     invoke CLSIDFromProgID,eax,addr pclsid
            .if eax != S_OK
                print LastError$(),13,10,0
                ret
            .endif
     print "CLSIDFromProgID : SUCCESS",13,10,0 
     invoke CoInitialize,NULL
     invoke CoCreateInstance,addr pclsid,
                             NULL,
                             1, ;CLSCTX_INPROC_SERVER,
                             addr IID_IDispatch,
                             addr ppv
            .if eax != S_OK
                fnx MessageBox,0,hex$(eax),"HRESULT: ",MB_OK 
                print LastError$(),13,10,0
                ret
            .endif
     print "CoCreateInstance: SUCCESS",13,10,0
     mov eax,uc$("NameSpace")
     invoke SysAllocString,eax
     mov lpszMember, eax

   ; ------------------------------------------------------------------------;
   ; invoke IDispatch_GetIDsOfNames, riid, rgszNames, cNames, lcid, rgDispId ;
   ; ------------------------------------------------------------------------;
;    push 0                   ;  program terminates abnormally without it :-\ 
;    push offset DISPID       ;  rgDispId
;    push 800h                ;  lcid
;    push 1                   ;  cNames
;    push eax                 ;  rgszNames
;    push offset IID_NULL     ;  riid
;    mov  edx, dword ptr [ppv];  pointer to IDispatch
;    mov  eax, [edx]
;    mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
;    call edx

    mov     edx,ppv
    mov     ecx,[edx]
    INVOKE  [ecx].IDispatch.GetIDsOfNames,edx,offset IID_NULL,eax,1,409h,offset DISPID

          .if  eax != S_OK
               fnx MessageBox,0,hex$(eax),"HRESULT: ",MB_OK
               print "GetIDsOfNames   : FAILED ",13,10,0
               jmp _exit
          .endif
     print "GetIDsOfNames   : SUCCESS",13,10,0
_exit:
     invoke SysFreeString , addr lpszProgID
     invoke SysFreeString , addr lpszMember
     invoke CoUninitialize
     ret
main endp

end  start

jj2007

Even with a proper BSTR, I get "The requested lookup key was not found in any active activation context" aka 80070057h...

japheth

Quote from: jj2007 on January 11, 2014, 05:54:45 PM
Even with a proper BSTR, I get "The requested lookup key was not found in any active activation context" aka 80070057h...

The functions called so far don't require BSTRs, just wide strings.

I get error 80020006, which means that name "NameSpace" is unknown ( sounds plausible):


include \masm32\include\masm32rt.inc

includelib msvcrt.lib
printf proto c :vararg

;###############################################################################################

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM

L macro parms:VARARG
local wstr
    wstr textequ <>
    for parm,<parms>
      ifidn <">,@SubStr(parm,1,1)
%       forc chr$, <@SubStr(parm,2,@SizeStr(parm)-2)>
          ifnb wstr
             wstr CatStr wstr,<,>
          endif
          wstr CatStr wstr,<'&chr$'>
        endm
      else
        ifnb wstr
           wstr CatStr wstr,<,>
        endif
        wstr CatStr wstr,<parm>
      endif
    endm
    exitm <wstr>
endm

CStr macro text:vararg
local xxx
.const
xxx db text,0
.code
exitm <offset xxx>
endm

;###############################################################################################

;IDispatch interface

IDispatch STRUCT
  METHOD(QueryInterface,         _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,                 _this:LPVOID)
  METHOD(Release,                _this:LPVOID)
  METHOD(GetTypeInfoCount,       _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,            _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,          _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,                _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS

;###############################################################################################

.data
     IID_IDispatch GUID <00020400h,0000h,0000h,<0C0h,0h,0h,0h,0h,0h,0h,46h>>
     IID_NULL      GUID <00000000h,0000h,0000h,<0h,0h,0h,0h,0h,0h,0h,0h>>

wszCls dw L("Shell.Application"),0
wszNS  dw L("NameSpace"),0

.data?
;     lpszProgID    dd ?
;     lpszMember    dd ?
     DISPID        dd ?,?
     pclsid        dd ?
     ppv           dd ?
.code
     start:
     cls
     call main
     inkey
     exit

main proc
     invoke CLSIDFromProgID,addr wszCls,addr pclsid
            .if eax != S_OK
                invoke printf, CStr("CLSIDFromProgID FAILED, eax=%X",10), eax
                ret
            .endif
     print "CLSIDFromProgID : SUCCESS",13,10,0 
     invoke CoInitialize,NULL
     invoke CoCreateInstance,addr pclsid,
                             NULL,
                             1, ;CLSCTX_INPROC_SERVER,
                             addr IID_IDispatch,
                             addr ppv
            .if eax != S_OK
                invoke printf, CStr("CoCreateInstance FAILED, eax=%X",10), eax
                ret
            .endif
     invoke printf, CStr( "CoCreateInstance: SUCCESS",10 )

   ; ------------------------------------------------------------------------;
   ; invoke IDispatch_GetIDsOfNames, riid, rgszNames, cNames, lcid, rgDispId ;
   ; ------------------------------------------------------------------------;
;    push 0                   ;  program terminates abnormally without it :-\ 
;    push offset DISPID       ;  rgDispId
;    push 800h                ;  lcid
;    push 1                   ;  cNames
;    push eax                 ;  rgszNames
;    push offset IID_NULL     ;  riid
;    mov  edx, dword ptr [ppv];  pointer to IDispatch
;    mov  eax, [edx]
;    mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
;    call edx

    mov     edx,ppv
    mov     ecx,[edx]
    INVOKE  [ecx].IDispatch.GetIDsOfNames,edx,offset IID_NULL,addr wszNS,1,409h,offset DISPID
    .if  eax != S_OK
         invoke printf, CStr("GetIDsOfNames FAILED, eax=%X",10), eax
         jmp _exit
    .endif
     print "GetIDsOfNames   : SUCCESS",13,10,0
_exit:
;     invoke SysFreeString , addr lpszProgID
;     invoke SysFreeString , addr lpszMember
     invoke CoUninitialize
     ret
main endp

end  start


GoneFishing

Quote from: japheth on January 11, 2014, 07:57:16 PM
The functions called so far don't require BSTRs, just wide strings.

I get error 80020006, which means that name "NameSpace" is unknown ( sounds plausible):
...
I removed those unnecessary calls - SysAllocString, SysFreeString
As to "NameSpace" member of Shell.Application object - it does exist.
I've got the following CPP code working on XP SP3:

#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <Objbase.h>
#pragma comment (lib,"Ole32.lib")
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{   
    CoInitialize(NULL);

    // Get clsid from name
    CLSID clsid;
    CLSIDFromProgID(L"shell.application",&clsid);

    // Create instance
    IDispatch *obj=NULL;
    CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IDispatch),(void**)&obj);

    HRESULT hresult;
    OLECHAR FAR* szMember = (OLECHAR*)L"NameSpace";       
    DISPID dispid;
    hresult = obj->GetIDsOfNames(IID_NULL, &szMember, 1,LOCALE_SYSTEM_DEFAULT, &dispid) ;
    return 0;
}


My results for posted fixes:
@dedndave : crash         (i.e. I'm seeing WerFault.exe's dialog)
@Japheth   :  80020006  (DISP_E_UNKNOWNNAME)
@jj2007     :  80070057  (declared in windows.inc as E_INVALIDARG )

I debugged my code and discovered that shell32 compares its own _GUID_NULL not with IID_NULL but with rgszNames string or even with part of "Press any key to continue ..." string . It makes me think that the problem is in parameters and stack balance .
Having working CPP code makes the task much simpler .
I'll report my results 
Thank you all  :t

japheth

Quote from: vertograd on January 11, 2014, 10:15:19 PM
I've got the following CPP code working on XP SP3:

Ok, your C++ sample reveals what's wrong in the assembly source - an incorrect "level of indirection".

This should work:



include \masm32\include\masm32rt.inc

includelib \wininc\lib\msvcrt.lib
printf proto c :vararg

;###############################################################################################

;METHOD macro by qWord

METHOD  MACRO   name,args:VARARG
        LOCAL   _type1,_type2
        _type1  TYPEDEF PROTO args
        _type2  TYPEDEF PTR _type1
        EXITM   <name _type2 ?>
        ENDM

L macro parms:VARARG
local wstr
    wstr textequ <>
    for parm,<parms>
      ifidn <">,@SubStr(parm,1,1)
%       forc chr$, <@SubStr(parm,2,@SizeStr(parm)-2)>
          ifnb wstr
             wstr CatStr wstr,<,>
          endif
          wstr CatStr wstr,<'&chr$'>
        endm
      else
        ifnb wstr
           wstr CatStr wstr,<,>
        endif
        wstr CatStr wstr,<parm>
      endif
    endm
    exitm <wstr>
endm

CStr macro text:vararg
local xxx
.const
xxx db text,0
.code
exitm <offset xxx>
endm

;###############################################################################################

;IDispatch interface

IDispatch STRUCT
  METHOD(QueryInterface,         _this:LPVOID,riid:LPVOID,ppvObj:LPVOID)
  METHOD(AddRef,                 _this:LPVOID)
  METHOD(Release,                _this:LPVOID)
  METHOD(GetTypeInfoCount,       _this:LPVOID,pctinfo:UINT)
  METHOD(GetTypeInfo,            _this:LPVOID,iTInfo:UINT,lcid:LCID,ppTInfo:LPVOID)
  METHOD(GetIDsOfNames,          _this:LPVOID,riid:LPVOID,rgszNames:LPOLESTR,cNames:UINT,lcid:LCID,rgDispId:LPVOID)
  METHOD(dInvoke,                _this:LPVOID,dispIdMember:DWORD,riid:LPVOID,lcid:LCID,wFlags:DWORD,pDispParams:LPVOID,pVarResult:LPVOID,pExcepInfo:LPVOID,puArgErr:UINT)
IDispatch ENDS

;###############################################################################################

.data
     IID_IDispatch GUID <00020400h,0000h,0000h,<0C0h,0h,0h,0h,0h,0h,0h,46h>>
     IID_NULL      GUID <00000000h,0000h,0000h,<0h,0h,0h,0h,0h,0h,0h,0h>>

wszCls dw L("Shell.Application"),0
wszNS  dw L("NameSpace"),0

itemtab label ptr
dd wszNS
dd 0

.data?
;     lpszProgID    dd ?
;     lpszMember    dd ?
     DISPID        dd ?,?
     pclsid        dd ?
     ppv           dd ?
.code
     start:
;     cls
     call main
;     inkey
     exit

main proc
     invoke CLSIDFromProgID,addr wszCls,addr pclsid
            .if eax != S_OK
                invoke printf, CStr("CLSIDFromProgID FAILED, eax=%X",10), eax
                ret
            .endif
     print "CLSIDFromProgID : SUCCESS",13,10,0 
     invoke CoInitialize,NULL
     invoke CoCreateInstance,addr pclsid,
                             NULL,
                             1, ;CLSCTX_INPROC_SERVER,
                             addr IID_IDispatch,
                             addr ppv
            .if eax != S_OK
                invoke printf, CStr("CoCreateInstance FAILED, eax=%X",10), eax
                ret
            .endif
     invoke printf, CStr( "CoCreateInstance: SUCCESS",10 )

   ; ------------------------------------------------------------------------;
   ; invoke IDispatch_GetIDsOfNames, riid, rgszNames, cNames, lcid, rgDispId ;
   ; ------------------------------------------------------------------------;
;    push 0                   ;  program terminates abnormally without it :-\ 
;    push offset DISPID       ;  rgDispId
;    push 800h                ;  lcid
;    push 1                   ;  cNames
;    push eax                 ;  rgszNames
;    push offset IID_NULL     ;  riid
;    mov  edx, dword ptr [ppv];  pointer to IDispatch
;    mov  eax, [edx]
;    mov  edx, dword ptr [eax+20] ; offset of GetIDsOfNames
;    call edx

    mov     edx,ppv
    mov     ecx,[edx]
    INVOKE  [ecx].IDispatch.GetIDsOfNames,edx,offset IID_NULL,addr itemtab,1,800h,offset DISPID
    .if  eax != S_OK
         invoke printf, CStr("GetIDsOfNames FAILED, eax=%X",10), eax
         jmp _exit
    .endif
     print "GetIDsOfNames   : SUCCESS",13,10,0
_exit:
;     invoke SysFreeString , addr lpszProgID
;     invoke SysFreeString , addr lpszMember
     invoke CoUninitialize
     ret
main endp

end  start


jj2007

Quote from: japheth on January 11, 2014, 10:40:17 PM
This should work:

Replace all printf with crt_printf, and comment out the printf PROTO, and it works on Masm32.

GoneFishing

Japheth and Jochen !
Thank you both  :t
Now it works fine and I'm to do the next step - IDispatch_Invoke  :biggrin:

dedndave

Quote from: vertograd on January 11, 2014, 11:06:03 PM
Japheth and Jochen !
Thank you both  :t
Now it works fine and I'm to do the next step - IDispatch_Invoke  :biggrin:

so, i'm chopped liver ?

GoneFishing

Quote from: dedndave on January 12, 2014, 12:01:06 AM
Quote from: vertograd on January 11, 2014, 11:06:03 PM
Japheth and Jochen !
Thank you both  :t
Now it works fine and I'm to do the next step - IDispatch_Invoke  :biggrin:

so, i'm chopped liver ?

Dave, certainly not!
Quote from: vertograd on January 11, 2014, 10:15:19 PM
Thank you all  :t


I'm greatly appreciate your help
Thank you, Dave  :t