COM原理
+ -

COM对象的创建

2022-02-07 45 1

在COM库中有3个可用于创建COM对象的函数,分别是CoGetClassObject和CoCreateInstnace/Ex。
通常情况下,客户程序调用其中之一完成对象的创建,并返回对象的初始接口指针。
COM库与类厂也通过这3个函数进行交互。

CoGetClassObject

HRESULT CoGetClassObject(
  [in]           REFCLSID rclsid,
  [in]           DWORD    dwClsContext,
  [in, optional] LPVOID   pvReserved,
  [in]           REFIID   riid,
  [out]          LPVOID   *ppv
);

CoGetClassObject先找到由clsid指定的COM类的类厂,然后连接到类厂对象,如果需要的话,CoGetClassObject装入组件代码。如果是进程内组件对象,则CoGetClassObject调用DLL模块的DllGetClassObject导出函数,把参数clsid、iid和ppv传递给DllGetClassObject,并返回类厂对象的接口指针。通常情况下iid为IClassFactory的标识符IID_IClassFactory。

如果类厂对象还支持其它可用于创建操作的接口,也可使用其它的接口标识符。例如,可请求IClassFactory2接口,以便在创建时,验证用户的许可证情况。IClassFactory2接口是对IClassFactory的扩展,它加强了组件创建的安全性。

参数dwClsContext指定组件类别,可指定为进程内组件、进程外组件或进程内控制对象(类似于进程外组件的代理对象,主要用于OLE技术);参数iid和ppv分别对应于DllGetClassObject的参数,用于指定接口IID和存放类对象的接口指针;参数pServerInfo用于创建远程对象时指定服务器信息,在创建进程内组件对象或本地进程外组件时,设置NULL。

如果CoGetClassObject创建的类厂对象位于进程外组件,情形则要复杂得多。首先CoGetClassObject启动组件进程,然后一直等待,直到组件进程把它支持的COM类对象的类厂注册到COM中。于是CoGetClassObject把COM中相应的类厂信息返回。因此,组件外进程被COM库启动时(带命令行参数/Embedding),必须把所支持的COM类的类厂对象通过 CoRegisterClassObject注册到COM中,以便COM库创建COM对象使用。当进程退出时,必须调用CoRevokeClassObject以便通知COM它所注册的类厂对象不再有效。组件程序调用CoRegisterClassObject和CoRevokeClassObject必须配对。

CoCreateInstance/Ex函数

CoCreateInstance是一个被包装过的函数,在它的内部实际上也调用了CoGetClassObject。CoCreateInstance参数clsid和dwClsContext含义与CoGetClassObject中的一致,(CoCreateInstance的iid和ppv参数与CoGetClassObject不同,一个是表示对象的接口信息,一个是表示类厂的接口信息)。参数pUnknownOuter与类厂接口的CreateInstance中对应的参数一致,主要用于对象被聚合的情况。CoCreateInstance把通过类厂创建对象的过程封装起来,客户程序只要指定对象类的CLSID和待输出的接口指针及接口ID,客户程序可不与类厂打交道。

CoCreateInstance可用下面的代码实现:

HRESULT CoCreateInstance(clsid,IUnknown *pUnknownOuter,DWORD dwClsContext,const IID& iid,void *ppv)
{
    IClassFactory *pCF;
    HRESULT hr = CoGetClassObject(clsid,dwClsContext,NULL,IID_IClassFactory,(void *)pCF);
    if (FAILED(hr))
    return hr;

    hr = pCF->CreateInstance(pUnknownOuter,iid,(void *)ppv);
    pFC->Release();
    return hr;
}

从这段代码可看出,CoCreateInstance首先利用CoGetClassObject创建类厂对象,然后用得到的类厂对象的接口指针创建真正的COM对象,最后把类厂对象释放掉并返回,这样就把类厂屏蔽起来。
但是,用CoCreateInstance并不能创建远程机上的对象,因为在调用CoGetClassObject时,把第三个用于指定服务器信息的参数设置为NULL。

HRESULT CoCreateInstanceEx(
  [in]      REFCLSID     Clsid,
  [in]      IUnknown     *punkOuter,
  [in]      DWORD        dwClsCtx,
  [in]      COSERVERINFO *pServerInfo,
  [in]      DWORD        dwCount,
  [in, out] MULTI_QI     *pResults
);

要创建远程对象,可使用CoCreateInstanceEx函数。前三个参数与CoCreateInstance一样,pServerInfo与CoGetClassOjbect的参数一样,用于指定服务器信息,最后两个参数dwCount和rgMultiQI指定了一个结构数组,可用于保存多个对象接口指针,其目的在于一次获得多个接口指针,以便减少客户程序与组件程序之间的频繁交互,这对于网络环境下的远程对象是很有意义的。

0 篇笔记 写笔记

COM对象的创建
在COM库中有3个可用于创建COM对象的函数,分别是CoGetClassObject和CoCreateInstnace/Ex。通常情况下,客户程序调用其中之一完成对象的创建,并返回对象的初始接口指针。COM库与类厂也通过这3个函数进行交互。CoGetClassObjectHRESULT CoGet......
COM组件的安装与卸载
(1)进程内组件的安装客户调用COM库的CoCreateInstanceCoGetClassObject创建COM对象时,在CoGetClassObject中,COM库根据注册表中的信息,找到类标识符CLSID对应的组件程序(DLL)的全路径并调用CoLoadLibrary,再调用组件程序的Dll......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!