STA 进程内Com组件剖析

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!CreateWindowExW
004bf6d0 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+0xe
004bf8e8 77e199d5ntdll!__RtlUserThreadStart+0x70
004bf900 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指针为调用线程整理的指针,若不是,则调用错误,或者异常。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值