欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

masm32开发com组件介绍[一][二][三]

程序员文章站 2022-03-19 11:27:25
作 者: combojiang时 间: 2007-12-10,14:09链 接: http://bbs.pediy.com/showthread.php?t=56328 声明:本贴参考网站:...

作 者: combojiang
时 间: 2007-12-10,14:09
链 接: http://bbs.pediy.com/showthread.php?t=56328

声明:本贴参考网站:http://ourworld.compuserve.com/

[一]基础知识篇
组件对象模型(Com)在windows操作系统中应用越来越广泛。com因为大量的技术细节显得很复杂,但是正是这种复杂才使com组件的调用显得十分简单。 com和使用程序采用server/client架构。下面我们将在后续的两篇中介绍com组件的编写与调用。

com编程时当前程序开发的热点,各种编程语言都为组件编写提供了很好的支持,但是汇编语言例外,汇编语言开发组件没有优势。但是透过汇编开发的了解,可以使我们了解com组件的工作原理。好了,闲话少说,开始介绍:)

所有的inc头文件都要满足如下特点:
 
1) masm32松散的类型定义约定将继续使用。就是说参数可以被定义为他们的基本类型,代表性的如:DWORD

2) 里面不能创建任何的代码,仅仅包含定义信息,头文件里面需要包含代码,则必须定义为宏。
 
3) 结构体应该参照他们的C原形来定义。

4) GUID 结构定义在windows.inc文件中,GUID的值应该通过textequ宏来定义,这样不会直接产生任何代码。

5) 接口定义分为两步:
   1.一个通用的宏产生一个通用的接口结构。
   2.使用接口名字来修饰结构自身的方法名字。
   这种方式可以有效地避免namespace冲突,并且方便接口定义结构继承。
 
6)COM接口函数调用使用coinvoke宏。

 


GUIDS
EXAMPLE:

sIID_IUnknown  TEXTEQU  <{000000000H, 00000H, 00000H,
                            {0C0H, 000H, 000H, 000H, 000H, 000H, 000H, 046H}}

可以被用来定义
IID_IUnknown   GUID    sIID_IUnknown

 

 
接口:
由于MASM32原形约定松散的类型检查,主要检查编译时函数的参数的个数。因此可以非常简单的定义接口函数,如下所示,用下表值来表示函数参数的个数。

comethod1Proto   typedef proto :DWORD
comethod2Proto   typedef proto :DWORD, :DWORD
comethod3Proto   typedef proto :DWORD, :DWORD, :DWORD
comethod4Proto   typedef proto :DWORD, :DWORD, :DWORD, :DWORD
comethod4Proto   typedef proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD

函数指针如下:
comethod1        typedef ptr comethod1Proto
comethod2        typedef ptr comethod2Proto
comethod3        typedef ptr comethod3Proto
comethod4        typedef ptr comethod4Proto
comethod5        typedef ptr comethod4Proto


IUnknown接口: IUnknown接口是基本接口,其他所有接口都是派生于它。函数原形定义如上,其定义如下:

_vtIUnknown MACRO CastName:REQ
    ; IUnknown methods
    &CastName&_QueryInterface comethod3  ?
    &CastName&_AddRef         comethod1  ?
    &CastName&_Release        comethod1  ?
ENDM

IUnknown                        STRUCT
    _vtIUnknown IUnknown
IUnknown                        ENDS

其展开如下:

IUnknown                        STRUCT
    IUnknown_QueryInterface comethod3    ?
    IUnknown_AddRef         comethod1    ?
    IUnknown_Release        comethod1    ?
IUnknown                        ENDS


IClassFactory 接口
IClassFactory派生于 IUnknown.它的结构开始是 IUnknown 的方法, 后面添加了 2个自己的方法.

_vtIClassFactory MACRO CastName:REQ
    ; IUnknown methods 
    _vtIUnknown CastName
    ; IClassFactory methods
    &CastName&_CreateInstance comethod4 ?
    &CastName&_LockServer     comethod2 ?
ENDM
 
IClassFactory                   STRUCT
    _vtIClassFactory IClassFactory
IClassFactory                   ENDS

展开如下:

IClassFactory                   STRUCT
    IClassFactory_QueryInterface comethod3 ?
    IClassFactory_AddRef         comethod1 ?
    IClassFactory_Release        comethod1 ?
    IClassFactory_CreateInstance comethod4 ?
    IClassFactory_LockServer     comethod2 ?
IClassFactory                   ENDS


Coinvoke宏

;---------------------------------------------------------------------
; coinvoke MACRO
; pInterface    pointer to a specific interface instance
; Interface     the Interfaces struct typedef
; Function      which function or method of the interface to perform
; args          all required arguments
;                   (type, kind and count determined by the function)
;
coinvoke MACRO pInterface:REQ, Interface:REQ, Function:REQ, args:VARARG
    LOCAL istatement, arg
    FOR arg, <args>     ;; run thru args to see if edx is lurking in there
        IFIDNI <&arg>, <edx>
            .ERR <edx is not allowed as a coinvoke parameter>
        ENDIF
    ENDM
    istatement CATSTR <invoke (Interface PTR[edx]).&Interface>,<_>,<&Function, pInterface>
    IFNB <args>     ;; add the list of parameter arguments if any
        istatement CATSTR istatement, <, >, <&args>
    ENDIF
    mov edx, pInterface
    mov edx, [edx]
    istatement
ENDM
;---------------------------------------------------------------------
例如:QueryInterface方法调用如下:

coinvoke ppv ,IUnknown, QueryInterface, ADDR IID_SomeOtherInterface,
ADDR ppnew


HRESULTS
任何一个com接口函数的返回值类型都是一个hResult, 4个字节长。返回值在eax寄存器中。可以用这个值来判断函数调用是否成功。

.IF !SIGN?
; function passed
.ELSE
; function failed
.ENDIF
接下来,我们定义了宏来简化它:
.IF SUCCEEDED   ; TRUE if SIGN bit not set
.IF FAILED   &n