STA 进程内Com组件剖析

来源:互联网 发布:js时间段选择控件 编辑:程序博客网 时间:2024/06/06 03:36

1. 我们知道对单线程套间内Com对象的跨套间访问需要通过向STA套间内的隐藏窗口发送消息来实现的,而隐藏窗口是什么时候创建的呢?是不是每一个STA Com对象都有一个独立的隐藏窗口呢?我于是利用下面的代码做了测试,并在Windbg中对CreateWindowExW下了断点,发现CreateWindow是在初始化Com套间时创建的,而创建Com对象并不会创建窗口。以下为源代码及调用堆栈。

          long lRet;          HRESULT hr;          CoInitializeEx(0,COINIT_APARTMENTTHREADED);          hr =_MyShopStaObj.CreateInstance(__uuidof(InProcLibLib::ShopStaObj));          hr =_MyShopStaObj2.CreateInstance(__uuidof(InProcLibLib::ShopStaObj));

004bf698 770c6417USER32!CreateWindowExW004bf6d0 770c64d4ole32!InitMainThreadWnd+0x3e [d:\w7rtm\com\ole32\com\objact\mainthrd.cxx @ 160]004bf6e8 770c0b49ole32!wCoInitializeEx+0xef [d:\w7rtm\com\ole32\com\class\compobj.cxx @ 2437]004bf708 0032a609ole32!CoInitializeEx+0x29d [d:\w7rtm\com\ole32\com\class\compobj.cxx @ 2110]004bf848 00344989Client!wmain+0x49 [e:\lenovo\comstudy\client\client.cpp @ 34]004bf894 0034484fClient!__tmainCRTStartup+0x129 [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @278]004bf89c 75cc338aClient!wmainCRTStartup+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @189]004bf8a8 77e19a02kernel32!BaseThreadInitThunk+0xe004bf8e8 77e199d5ntdll!__RtlUserThreadStart+0x70004bf900 00000000ntdll!_RtlUserThreadStart+0x1b

因为COM利用消息机制来实现STA,因此STA套间里的线程必须实现消息循环,否则COM将不能实现STA的要求。当在STA套间创建一个STACom对象时,在创建线程得到的是指向Com对象的直接指针,而非代理指针。在其它线程是可以直接使用这个Com指针的,并不会有COM相关的异常,但是这样做违反了COM规范,访问Com对象也变得不再安全。

其实若COM指针为直接指针(STA线程创建STA Com对象或者MTA线程创建MTA Com对象),这个指针其实是可以跨套间使用的,因为使用这种指针进行Com对象访问并不会检查此Com指针为调用线程整理的指针。

但是如果拿到的Com指针为代理指针(STA线程创建MTA Com对象或者MTA线程创建STA Com对象),则使用此指针进行Com对象访问会检查此Com指针为调用线程整理的指针,若不是,则调用错误,或者异常。

 

0 0