Old 19th August 2010, 19:12   #1
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
Playing with COM

I'm attempting to recreate the example posted at: http://en.wikipedia.org/wiki/OLE_Automation#Examples

My code is choking at GetIDsOfNames... Can anyone add some insight?

PHP Code:
    /*
    !define IID_StdOle      '{00020430-0000-0000-C000-000000000046}'
    !define IID_IDispatch   '{00020400-0000-0000-C000-000000000046}'
    !define IID_IUnknown    '{00000000-0000-0000-C000-000000000046}'
    !define IID_NULL        '{00000000-0000-0000-0000-000000000000}'

    !define CLSCTX_SERVER           0x015
    !define LOCALE_SYSTEM_DEFAULT   0x800
    */

    
DetailPrint CLSIDFromProgID
    System
::Call `Ole32::CLSIDFromProgID(w,&g16)i ("Excel.Application",.r0).r2`
    
DetailPrint "ERR=$2"
    
DetailPrint "CLSID=$0"
    
    
    
DetailPrint CoCreateInstance
    System
::Call `Ole32::CoCreateInstance(g r0,i 0,i ${CLSCTX_SERVER},g '${IID_IDispatch}',*i .r1) i .r2`
    
DetailPrint "ERR=$2"
    
    
DetailPrint GetIDsOfNames
    System
::Call `$1->GetIDsOfNames(g ${IID_NULL},w "Visible",i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'(
    DetailPrint "ERR=$2" ; <-- I'
m getting error 0x80004002 (AKA  E_NOINTERFACE)
    
DetailPrint $$3=$
Zinthose is offline   Reply With Quote
Old 19th August 2010, 19:24   #2
Animaether
Major Dude
 
Join Date: Jun 2001
Posts: 1,173
Quote:
Originally Posted by Zinthose View Post
My code is choking at GetIDsOfNames... Can anyone add some insight?

PHP Code:
    System::Call `$1->[B]GetIDsOfNames[/B](g ${IID_NULL},w "Visible",i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'(
    DetailPrint "ERR=$2" ; <-- I'
m getting error 0x80004002 (AKA  E_NOINTERFACE
GetIDsOfNames should be replaced by the numerical entry of that bit in the interface. I don't recall where you can find that, though..
Animaether is offline   Reply With Quote
Old 19th August 2010, 20:24   #3
Afrow UK
Moderator
 
Afrow UK's Avatar
 
Join Date: Nov 2002
Location: Surrey, England
Posts: 8,434
It's the zero-based index of the method as it is listed physically in the interface. This includes methods from interfaces that the interface you are using implements. As IUnknown has 3 methods, your first interface method will typically be #3.

Stu
Afrow UK is offline   Reply With Quote
Old 19th August 2010, 20:32   #4
Animaether
Major Dude
 
Join Date: Jun 2001
Posts: 1,173
Quote:
Originally Posted by Afrow UK View Post
It's the zero-based index of the method as it is listed physically in the interface. This includes methods from interfaces that the interface you are using implements. As IUnknown has 3 methods, your first interface method will typically be #3.
Right - as per the System plugin docs;
Quote:
To find out the index of a member in a COM interface, you need to search for the definition of this COM interface in the header files that come with Visual C/C++ or the Platform SDK. Remember the index is zero based.
What I meant was.. I don't recall where the header files for this interface can be found online (many of us don't actually touch the SDK bits and pieces) - but then I remembered; WINE usually has 'm

http://source.winehq.org/source/include/oleauto.h
Animaether is offline   Reply With Quote
Old 19th August 2010, 20:40   #5
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
Aight... Using the VTable index to lookup the interfaces methods I have now updated with the following..
PHP Code:
    DetailPrint "== CLSIDFromProgID =="
    
System::Call `Ole32::CLSIDFromProgID(w,&g16)i ("Excel.Application",.r0).r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  CLSID=$0"
    
    
DetailPrint "== CoCreateInstance =="
    
System::Call `Ole32::CoCreateInstance(g r0,i 0,i ${CLSCTX_SERVER},g '${IID_IDispatch}',*i .r1) i .r2`
    
DetailPrint "  ERR=$2"
    
    
DetailPrint "== IUnknown::GetTypeInfoCount =="
    
System::Call `$1->3(*i .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== IDispatch::GetTypeInfo =="
    
System::Call `$1->4(i 0,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== IDispatch::GetIDsOfNames =="
    
;System::Call `*(i 7,w "Visible")i .s`
    ;
System::Call `$1->5(g ${IID_NULL},i s,i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'(
    System::Call `$1->5(g ${IID_NULL},w "Visible",i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'
(
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3" 
I think the issue may be with the BSTR. I tried creating it manually but I think I'm doint it wrong too.. :/

UPDATE: I'm convinced it is the BSTR.. Reading up on how to implement them now... http://msdn.microsoft.com/en-us/library/ms221069.aspx

Last edited by Zinthose; 19th August 2010 at 22:00. Reason: Update [BSTR]
Zinthose is offline   Reply With Quote
Old 19th August 2010, 20:48   #6
gringoloco023
Member
 
Join Date: Nov 2009
Posts: 52
Is it index 6 ? See, http://www.clarionopensource.com/Cla...hInterface.htm

I was recently fighting with something similar, ITypeLib
gringoloco023 is offline   Reply With Quote
Old 19th August 2010, 22:12   #7
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
Woot! It was the BSTR!
PHP Code:
    DetailPrint "== CLSIDFromProgID =="
    
System::Call `Ole32::CLSIDFromProgID(w,&g16)i ("Excel.Application",.r0).r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  CLSID=$0"
    
    
DetailPrint "== CoCreateInstance =="
    
System::Call `Ole32::CoCreateInstance(g r0,i 0,i ${CLSCTX_SERVER},g '${IID_IDispatch}',*i .r1) i .r2`
    
DetailPrint "  ERR=$2"
    
    
DetailPrint "== IUnknown::GetTypeInfoCount =="
    
System::Call `$1->3(*i .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== IDispatch::GetTypeInfo =="
    
System::Call `$1->4(i 0,i ${LOCALE_SYSTEM_DEFAULT},*g .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== BSTR =="
    
System::Call `Oleaut32::SysAllocString(w "Visible")i .s`
    
    
DetailPrint "== IDispatch::GetIDsOfNames =="
    
System::Call `$1->5(g ${IID_NULL},*i s,i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'(
    DetailPrint "  ERR=$2"
    DetailPrint "  $$3=$3" 
Now to work out the rest...
Zinthose is offline   Reply With Quote
Old 19th August 2010, 22:23   #8
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
Just a warning... if anyone is playing around with this.. check your TaskManager.. I just found 23 instances of Excel running.....

Here is the updated code with the COM Release at the end.
PHP Code:
    DetailPrint "== CLSIDFromProgID =="
    
System::Call `Ole32::CLSIDFromProgID(w,&g16)i ("Excel.Application",.r0).r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  CLSID=$0"
    
    
DetailPrint "== CoCreateInstance =="
    
System::Call `Ole32::CoCreateInstance(g r0,i 0,i ${CLSCTX_SERVER},g '${IID_IDispatch}',*i .r1) i .r2`
    
DetailPrint "  ERR=$2"
    
    
DetailPrint "== IDispatch::GetTypeInfoCount =="
    
System::Call `$1->3(*i .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== IDispatch::GetTypeInfo =="
    
System::Call `$1->4(i 0,i ${LOCALE_SYSTEM_DEFAULT},*g .r3)i .r2`
    
DetailPrint "  ERR=$2"
    
DetailPrint "  $$3=$3"
    
    
DetailPrint "== Oleaut32::SysAllocString =="
    
System::Call `Oleaut32::SysAllocString(w "Visible")i .r4`
    
DetailPrint "  RC=$4"
    
    
DetailPrint "== IDispatch::GetIDsOfNames =="
    
System::Call `$1->5(g ${IID_NULL},*i r4,i 1,i ${LOCALE_SYSTEM_DEFAULT},*i .r3)i .r2` ;<-- Errors here... :'(
    DetailPrint "  ERR=$2"
    DetailPrint "  $$3=$3"
    
    DetailPrint "== Oleaut32::SysFreeString =="
    System::Call `Oleaut32::SysFreeString(*i r4)`
    
    DetailPrint "== IUnknown::Release =="
    System::Call `$1->2()i .r2`
    DetailPrint "  RefCount=$2" 
Zinthose is offline   Reply With Quote
Old 19th August 2010, 22:58   #9
Animaether
Major Dude
 
Join Date: Jun 2001
Posts: 1,173
heehee

good job

one thing you might want to do, just for readability, is defining the interface bits.. e.g.

!define GetIDsOfNames 5

or even

!define IDispatch->GetIDsOfNames 5

Then later on you can just use..
${IDispatch->GetIDsOfNames} (g ${IID_NULL, etc.
..bit cleaner to read
Animaether is offline   Reply With Quote
Old 19th August 2010, 23:56   #10
Zinthose
Senior Member
 
Join Date: May 2009
Posts: 152
Good idea!!

Here is what I thew together.. needs more optimizations but it's a good start..
PHP Code:
    ## Simplyfy the Evil that is COM
    ## Example:
    ##      ${IDispatch::GetTypeInfo} $1 `(i 0,i ${LOCALE_SYSTEM_DEFAULT},*g .r3)i .r2`
        
!macro _COM_Function _vTableID _ObjectPointer _Parameters
            System
::Call `${_ObjectPointer}->${_vTableID}${_Parameters}`
        !
macroend
        
!define IUnknown::Release           `!insertmacro _COM_Function 2 `
        !
define IDispatch::GetTypeInfoCount `!insertmacro _COM_Function 3 `
        !
define IDispatch::GetTypeInfo      `!insertmacro _COM_Function 4 `
        !
define IDispatch::GetIDsOfNames    `!insertmacro _COM_Function 5 `
        !
define IDispatch::Invoke           `!insertmacro _COM_Function 6 
Zinthose is offline   Reply With Quote
Old 20th August 2010, 17:27   #11
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,442
I have been using some helper macros that are very similar to this (See http://nsis.pastebin.com/BqQFTRv3 ) but I also declare the parameter types in my "_COM_Function" macro so you don't have to specify them when you invoke the method (Can also be used to set default parameter values IIRC) I also use -> and not ::. It might be a good idea to come up with a standard and include it in some header (There is no way we can define all COM interfaces, but some of the shell interfaces would be a good start)

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Tags
system::call ole32 com

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump