只是为了测试,现在只写一个接口的自定义的两个函数

这是接口的定义

[
object,
uuid(C320028D-2E57-46FD-8D80-F24315B58543),
dual,
nonextensible,
pointer_default(unique)
]
interface IDiction : IDispatch{
HRESULT justTest();
HRESULT test_3();
};只有两个成员函数

很简单吧,只是为了测试哈,现在看看调用COM的客户端的源代码

#include


#include


using namespace std;
#import"D:\project\Dic\Debug\Dic.dll" no_namespace
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
IDictionPtr test;
test.CreateInstance(__uuidof(Diction));
test->justTest();
test->test_3();
test.Release();
::CoUninitialize ();
return 0;
}

接连调用IDiction的两个接口而已,现在看看,起反汇编代码:重头戏来了

.text:00401000 ; int __cdecl wmain(int argc, wchar_t **argv)
.text:00401000 _wmain proc near ; CODE XREF: __tmainCRTStartup+11Dp
.text:00401000
.text:00401000 test = _com_ptr_t<_com_IIID

> ptr -10h
.text:00401000 var_C = dword ptr -0Ch
.text:00401000 var_4 = dword ptr -4
.text:00401000 argc = dword ptr 8
.text:00401000 argv = dword ptr 0Ch
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 push 0FFFFFFFFh
.text:00401005 push offset __ehhandler$_wmain
.text:0040100A mov eax, large fs:0
.text:00401010 push eax
.text:00401011 push ecx
.text:00401012 push esi ; dwClsContext
.text:00401013 push edi ; pOuter
.text:00401014 mov eax, ___security_cookie
.text:00401019 xor eax, ebp
.text:0040101B push eax ; rclsid
.text:0040101C lea eax, [ebp+var_C]
.text:0040101F mov large fs:0, eax
.text:00401025 push 0 ; pvReserved
.text:00401027 call ds:CoInitialize(x)
.text:0040102D mov [ebp+test.m_pInterface], 0
.text:00401034 lea edi, [ebp+test]
.text:00401037 mov [ebp+var_4], 0
.text:0040103E call _com_ptr_t<_com_IIID

>::CreateInstance(_GUID const &,IUnknown *,ulong);这是调用的智能接口的CreateInstance
.text:00401043 mov eax, [ebp+test.m_pInterface]
.text:00401046 test eax, eax;检测调用是否成功,如果不成功,则转到错误处理过程
.text:00401048 jnz short $LN30
.text:0040104A push 80004003h ; hr
.text:0040104F call _com_issue_error(long)
.text:00401054 ; ---------------------------------------------------------------------------
.text:00401054
.text:00401054 $LN30: ; CODE XREF: _wmain+48j
.text:00401054 mov ecx, [eax]
.text:00401056 mov edx, [ecx+1Ch];注意这个偏移量,1CH,我想这是justTest的所在,也就是说1CH是,该功能函数在接口中的偏移量
.text:00401059 push eax
.text:0040105A mov esi, eax
.text:0040105C call edx;这是调用过程
.text:0040105E test eax, eax;同上检测函数执行是否成功
.text:00401060 jns short loc_40106E
.text:00401062 push offset __GUID_c320028d_2e57_46fd_8d80_f24315b58543 ; riid这是接口的GUID
.text:00401067 push esi ; punk
.text:00401068 push eax ; hr
.text:00401069 call _com_issue_errorex(long,IUnknown *,_GUID const &)
.text:0040106E ; ---------------------------------------------------------------------------
.text:0040106E
.text:0040106E loc_40106E: ; CODE XREF: _wmain+60j
.text:0040106E mov eax, [ebp+test.m_pInterface]
.text:00401071 test eax, eax
.text:00401073 jnz short $LN31
.text:00401075 push 80004003h ; hr
.text:0040107A call _com_issue_error(long)
.text:0040107F ; ---------------------------------------------------------------------------
.text:0040107F
.text:0040107F $LN31: ; CODE XREF: _wmain+73j
.text:0040107F mov ecx, [eax]
.text:00401081 mov edx, [ecx+20h];20是test_3的偏移量
.text:00401084 push eax
.text:00401085 mov esi, eax
.text:00401087 call edx;这是调用test_3功能的过程
.text:00401089 test eax, eax;同上检测是否成功执行
.text:0040108B jns short loc_401099
.text:0040108D push offset __GUID_c320028d_2e57_46fd_8d80_f24315b58543 ; riid
.text:00401092 push esi ; punk
.text:00401093 push eax ; hr
.text:00401094 call _com_issue_errorex(long,IUnknown *,_GUID const &)
.text:00401099 ; ---------------------------------------------------------------------------
.text:00401099
.text:00401099 loc_401099: ; CODE XREF: _wmain+8Bj
.text:00401099 mov eax, [ebp+test.m_pInterface]
.text:0040109C test eax, eax
.text:0040109E jnz short $LN32
.text:004010A0 push 80004003h ; hr
.text:004010A5 call _com_issue_error(long)
.text:004010AA ; ---------------------------------------------------------------------------
.text:004010AA
.text:004010AA $LN32: ; CODE XREF: _wmain+9Ej
.text:004010AA mov ecx, [eax]
.text:004010AC mov edx, [ecx+8];这个就比较特殊了,经笔者测试,8是一个定值,也就是说Release的偏移量永远是8
.text:004010AF push eax
.text:004010B0 call edx
.text:004010B2 mov [ebp+test.m_pInterface], 0
.text:004010B9 call ds:CoUninitialize()
.text:004010BF mov [ebp+var_4], 0FFFFFFFFh
.text:004010C6 mov eax, [ebp+test.m_pInterface]
.text:004010C9 test eax, eax
.text:004010CB jz short loc_4010D5
.text:004010CD mov ecx, [eax]
.text:004010CF mov edx, [ecx+8]
.text:004010D2 push eax
.text:004010D3 call edx
.text:004010D5
.text:004010D5 loc_4010D5: ; CODE XREF: _wmain+CBj
.text:004010D5 xor eax, eax
.text:004010D7 mov ecx, [ebp+var_C]
.text:004010DA mov large fs:0, ecx
.text:004010E1 pop ecx
.text:004010E2 pop edi
.text:004010E3 pop esi
.text:004010E4 mov esp, ebp
.text:004010E6 pop ebp
.text:004010E7 retn
.text:004010E7 _wmain endp

我们看下,这几个偏移量1C,20,24,之间间隔是4,也就是说每个函数地址的间隔是4,也就是说是虚函数表,他们的接口成员都是放在同一个虚函数表当中的,这下证实了书

中的话。好了,今天就到这儿吧,虽然还是没能知道__imp_baabba什么的是怎么实现的