CoInitialize浅析一

CoInitialize浅析一大家都知道程序中若要使用COM组件则必需要先调用CoInitialize,该函数主要是用来初始化COM执行环境。但这个函数的作用域是以线程为单位还是以进程为单位呢?或许大家已经通过測试程序摸索出答案,

大家好,又见面了,我是你们的朋友全栈君。

大家都知道程序中若要使用COM组件则必需要先调用CoInitialize,该函数主要是用来初始化COM执行环境。但这个函数的作用域是以线程为单位还是以进程为单位呢?或许大家已经通过測试程序摸索出答案,没错,是以线程为单位。今天我们就略微再深入一下,通过分析CoInitialize的详细实现来印证我们的想法。

我们先来看看CoInitialize的汇编

769B2A24                 mov     edi, edi

769B2A26                 push    ebp

769B2A27                 mov     ebp, esp

769B2A29                 push    2               ; dwCoInit

769B2A2B                 push    [ebp+8] ; pvReserved

769B2A2E                 call   _CoInitializeEx@8 ; CoInitializeEx(x,x)

769B2A33                 pop     ebp

769B2A34                 retn    4

能够看到,当中的实现还是比較简单的,它仅仅是简单地调用了CoInitializeEx,将第二个參数设置为2,即COINIT_APARTMENTTHREADED。我们再来看看CoInitializeEx的实现

769AEF5B                 mov     edi, edi

769AEF5D                 push    ebp

769AEF5E                 mov     ebp, esp

769AEF60                 push    ecx

769AEF61                 push    ebx

769AEF62                 mov     ebx, [ebp+0C]

769AEF65                 mov     eax, ebx

769AEF67                 and    eax, 0Eh      ; 检查參数是否正确,眼下第二个參数仅仅用了一个字节

769AEF6A                 cmp     eax, ebx

769AEF6C                 jnz     loc_76A0B8C7

769AEF72                 push    edi

769AEF73                 xor     edi, edi

769AEF75                 cmp     [ebp+8], edi       ; 推断第一个參数是否为NULL

769AEF78                 jnz     loc_76A0B8D1

769AEF7E

769AEF7Eloc_769AEF7E:

769AEF7E                 call    ?IsRunningInRPCSS@@YGHXZ ;IsRunningInRPCSS(void)

769AEF83                 test    eax, eax                                                          ;推断当前进程是否是RPCSS

769AEF85                 jnz     loc_76A0B8ED                                             ;假设是(即返回非0)则返回“灾难性故障”的错误

769AEF8B                 mov     eax, large fs:18h

769AEF91                 mov     eax, [eax+0F80h]

769AEF97                 cmp     eax, edi

769AEF99                 mov     [ebp+8], eax

769AEF9C                 jz      loc_769ADF26                                              ; 推断当前线程中的struct tagSOleTlsData结构体是否分配,若未分配则进行分配

769AEFA2

769AEFA2loc_769AEFA2:

769AEFA2                 push    esi

769AEFA3                 push    edi             ; __int32

769AEFA4                 push    ebx             ; unsigned __int32

769AEFA5                 xor     esi, esi

769AEFA7                 inc     esi

769AEFA8                 push    esi             ; int

769AEFA9                 push    esi             ; int

769AEFAA                 call    ?NotifyInitializeSpies@@YGJHHKJ@Z ;NotifyInitializeSpies(int,int,ulong,long)

769AEFAF                 call    ?IsThreadInNTA@@YGHXZ ; IsThreadInNTA(void)

769AEFB4                 test    eax, eax

769AEFB6                 jnz     loc_769DAFAD                                            ; 假设是 则返回“无法在设置线程模式后对其加以更改。”的错误

769AEFBC                 mov     eax, [ebp+8]

769AEFBF                 mov     ecx, [eax+0Ch]

769AEFC2                 test    ch, 10h                                                          ;推断标识第4位(从第0位開始)是否置位

769AEFC5                 jnz     loc_769D9D20                                              ; server出现意外情况。

769AEFCB                 mov     edx, ebx

769AEFCD                 and     edx, 2

769AEFD0                 mov     [ebp-4], edx                                 

769AEFD3                 jz      short loc_769AEFDE                      ; 非COINIT_APARTMENTTHREADED模式

769AEFD5                 test    ch, 1                                                                    ;推断标识第0位是否置位

769AEFD8                 jnz     loc_769DAFAD                                            ; 返回“无法在设置线程模式后对其加以更改。”的错误

769AEFDE

769AEFDEloc_769AEFDE:

769AEFDE                 cmp     edx, edi                                                            

769AEFE0                 jz      loc_769DAFA5                                             ; 非COINIT_APARTMENTTHREADED模式

769AEFE6

769AEFE6loc_769AEFE6:

769AEFE6                 test    bl, 8

769AEFE9                 jnz     loc_76A0B901                                              ;第二个參数中COINIT_SPEED_OVER_MEMORY标识位被设置,即为单线程套件

769AEFEF

769AEFEFloc_769AEFEF:

769AEFEF                 add     eax, 18h

769AEFF2                 inc     dword ptr [eax]                               ; tagSOleTlsData.dwReserved1[0]++;

769AEFF4                 cmp     [eax], esi                                                    

769AEFF6                 jnz     loc_769ADBF9                                             ; 推断tagSOleTlsData.dwReserved1[0]==1?

769AEFFC                 test    edx, edx

769AEFFE                 mov     ebx, offset?gMTAInitLock@@3VCOleStaticMutexSem@@A ; COleStaticMutexSem gMTAInitLock

769AF003                 jz      loc_769DAFF2                                              ; 第二个參数未设置COINIT_APARTMENTTHREADED标识,即为多线程套件

769AF009

769AF009loc_769AF009:

769AF009                 mov     esi, offset?g_mxsSingleThreadOle@@3VCOleStaticMutexSem@@A ; COleStaticMutexSemg_mxsSingleThreadOle

769AF00E                 mov     ecx, esi

769AF010                 call    ?Request@COleStaticMutexSem@@QAEXXZ ;COleStaticMutexSem::Request(void)

769AF015                 push    [ebp+0C]

769AF018                 lea     eax, [ebp+8]

769AF01B                 push    eax

769AF01C                 call    ?wCoInitializeEx@@YGJAAVCOleTls@@K@Z ;wCoInitializeEx(COleTls &,ulong)  调用wCoInitializeEx

769AF021                 mov     ecx, esi

769AF023                 mov     edi, eax

769AF025                 call    ?Release@COleStaticMutexSem@@QAEXXZ ;COleStaticMutexSem::Release(void)

769AF02A                 test    edi, edi

769AF02C                 jl      loc_76A0B90C

769AF032

769AF032loc_769AF032:

769AF032                 cmp     [ebp-4], 0         

769AF036                 jz      loc_769DB004                   ; 第二个參数未设置COINIT_APARTMENTTHREADED标识,即为多线程套件

769AF03C

769AF03C loc_769AF03C:                           ; CODE XREF:CoInitializeEx(x,x)+2C0B6j

769AF03C                xor     esi, esi

769AF03E                 inc     esi

769AF03F

769AF03F loc_769AF03F:

769AF03F                 push    edi             ; __int32

769AF040                 push    [ebp+0C]  ; unsigned__int32

769AF043                 push    0              ; int

769AF045                 push    esi             ; int

769AF046                 call    ?NotifyInitializeSpies@@YGJHHKJ@Z ;NotifyInitializeSpies(int,int,ulong,long)

769AF04B                 pop     esi

769AF04C

769AF04C loc_769AF04C:

769AF04C                 pop     edi

769AF04D

769AF04Dloc_769AF04D:

769AF04D                 pop     ebx

769AF04E                 leave

769AF04F                 retn    8

当中有几点请注意:

1、在第一个參数为非空时,该函数会推断当前进程是否为EXCEL;

2、该函数也会推断当前进程是否为RPCSS,该进程的用途请大家另行查阅;检查进程是否为RPCSS的方法主要是:先推断当前进程是否有加载Windows文件夹下\\system32\\rpcss.dll,假设未加载则当前进程不是RPCSS;若加载了,则获取该DLL中名为WhichService的导出函数,假设未找到该函数也觉得当前进程是RPCSS;若找到,并该函数的返回值大于等于0,且作为该函数參数的指针所指向的值为2则当前进程不是RPCSS,否则当前进程即为RPCSS。

3、每一个线程的TEB结构向后偏移0x0F80的地方存放struct tagSOleTlsData的指针,该结构的声明例如以下:

typedef structtagSOleTlsData

{

    void *pvReserved0[2];

    DWORD dwReserved0[3];

    void *pvReserved1[1];

    DWORD dwReserved1[3];

    void *pvReserved2[4];

    DWORD dwReserved2[1];

    void *pCurrentCtx;

} SOleTlsData;

该结构中存放了当前线程有关COM的环境信息,这个结构体中各个域的定义微软貌似没有公开。线程启动后,在没有该线程调用CoInitialize或CoInitializeEx之前,该指针为空。第一次调用上述函数后,为该线程从堆上分配该结构的内存并将其指针保存至TEB+0x0F80处。

4、我们注意到,全部对struct tagSOleTlsData内容的改动都未进行相互排斥保护,这是由于全部对该结构的改动操作都在当前线程内部进行,因此也就不存在多线程同步的问题;而对于一些全局信息的改动则都进行了保护。

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/155692.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • gain command of_partitioning

    gain command of_partitioning今天在Centos上进行硬盘分区的时候,分区完成时候需要命令partprobe指令来通知一下内核我刚才进行了系统分区,但是执行的时候发现Centos最小化安装之后没有这个命令,第一时间想到的就是肯定是包含这个指令的rpm包没有装,然后就跑到Centos7上面看一下有没有这条指令,发现有这条指令,然后就查看一下这条指令是来自于哪个安装包[root@zsf~]#whichp…

  • python中取整数的几种方法(python怎么取整)

    一、向零取整:int()python自带的int()取整>>>int(1.2)1>>>int(2.8)2>>>int(-0.1)0>>>int(-5.6)-5总结:int()函数是“向0取整”,取整方向总是让结果比小数的绝对值更小二、向上取整:math.ceil()>>>importmath&gt…

  • 匹配滤波(四种滤波器的幅频特性)

    匹配滤波(matchedfiltering)是最佳滤波的一种。当输入信号具有某一特殊波形时,其输出达到最大。在形式上,一个匹配滤波器由以按时间反序排列的输入信号构成。且滤波器的振幅特性与信号的振幅谱一致。因此,对信号的匹配滤波相当于对信号进行自相关运算。配滤波器是一种非常重要的滤波器,广泛应用与通信、雷达等系统中。从上面的理论推导可以看到,当输出信噪比为最大值的时候,滤波器的传递函数与输入信号的频谱函数满足特定的关系,式2.10就反映了这个关系。满足这种关系的线性滤波器,称之为匹配滤波…

  • Android开发中,怎样调用摄像机拍照以及怎样从本地图库中选取照片

    Android开发中,怎样调用摄像机拍照以及怎样从本地图库中选取照片这是属于我的第一篇博文,首先说明一下,文章属性为原创,其实不能说是原创,我是在学习的过程中根据自己的理解整理的。文章内容大多为书本上的内容,书本是郭霖的《第一行代码》。    正文:现在很多应用程序会调用摄像头的拍照功能,比如哪个程序要上传一张图片作为用户头像,这是启用摄像头拍照会很方便。当然,还有第二种方法,就是在本地图库选取已经被保存的图片。现在,我就根据自己学习的过程,将这部分

  • 平面方程_平面方程一般式的ABCD

    平面方程_平面方程一般式的ABCD参考网址:http://www.lsngo.net/2018/01/07/graphics_plane/这里将点法式展开即可得到:所以上面式子中的D=-n点乘p,n是法向量,p为坐标点,都是三维的,注意负号。这句话又是什么意思?P=<n,D>,就是四维向量。任意一点的齐次坐标为(x,y,z,1),两个点乘,得到Ax+By+Cz+D=0,其实就是P点乘Q。所以平面可以…

    2022年10月23日
  • MySQL 加锁处理分析

    MySQL 加锁处理分析

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号