作 者: 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 Interface's 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 ; TRUE is SIGN bit set
結論:
以上這些是你用彙編開發com需要用到的,這些適用於activex的開發。