com进程内进程外组件

时间:2022-08-29 18:52:07

COM进程内组件与进程外组件

1.   COM进程内组件

进程内组件以动态链接库的形式存在(后缀名为dll),客户端需要使用进程内组件提供的服务时只需要将dll加载进客户端进程。进程内组件必须提供自注册功能,这样客户端进程才能在需要的从注册表中查找到相应的信息,并加载该组件。

 

进程内组件需要导出四个函数

DllRegisterServer

参数:无

返回值:HRESULT 指示注册操作的错误类型

 

DllUnregisterServer

参数:无

返回值:HRESULT 指示删除注册表中的相应项操作的错误类型

 

DllGetClassObject

参数1CLSID&组件的CLSID(因为一个dll可以作为多个组件的载体)

参数2IID&,要从组件中获取的接口IID

参数3void**,接收获得的接口指针的双重指针

返回值: HRESULT 指示操作结果的错误类型,一般有(E_OUTOFME\

MORY, S_OK,E_NOINTERFACE,CLASS_E_CLASSNOTAVAILABLE);

DllCanUnloadNow

参数:

返回值:HRESULT 指示是否可卸载该组件

说明:COM库每隔一段时间便会自动调用该方法判断是否可以卸载该组件。

 

进程内组件注册表中需要的内容

com进程内进程外组件

位于HKEY_CLASSES_ROOTCLSID项下

其中7F21137D…为组件的CLSID

InprocServer32所对应的值为进程内组件的完整路径

ProgID 所对应的值为组件的易记名称客户端可以通过该名称获得组件的CLSID.

 

2.COM进程外组件

2.1  LPCRPC

COM采用LPC(本地过程调用)和RPC(远程过程调用)的方法进行进程之间的通信,LPC用于在同一机器上的不同进程之间进行通信,而RPC用于在不同机器上的进程之间进行通信

com进程内进程外组件

2.2 存根代理dll

为了提供LPC的处理,com提供了一个非常简便的方法,当组件为进程外组件时,客户将同一个模仿组件的dll进行通信,这个dll可以为客户完成参数调整以及LPC调用,这个dll在客户端称之为代理dll,而在服务器端称作为存根dll。

代理存根dll的生成步骤:

 

1. 编写idl文件

该idl文件包含了所有服务端组件定义的接口,组件标示符CLSID除外

2. 使用MIDL编译该IDL文件

编译后生成的一下几个文件

1) XXX_h.h   包含接口定义的头文件,和所有接口IID的声明

2) XXX_i.c   接口IID的定义

3) XXX_p.c   代理文件

4) Dlldata.c 数据文件

3. 使用以上文件生成存根代理dll

1)  在预处理增加REGISTER_PROXY_DLL

2)  提供输入库rpcrt4.lib   uuid.lib

3)  添加def文件,导出下图五个函数

4)  编译生成dll

生成后的dll会有五个导出函数如下图

 com进程内进程外组件

前面四个和进程内组件意义一致

 

2.3  进程外组件的注册

进程外组件注册需要注册存根代理dll和组件exe文件,其中存根代理dll的注册和进程内组件的注册一致,而exe文件的注册就依靠其命令参数来进行。

组件程序的两个用于注册的入口函数为DllRegisterServerDllUnregisterServer,注册组件使用命令:RegSvr32 *.dll;反注册组件使用命令:RegSvr32 /u *.dll,进程内组件注册使用此命令。进程外组件注册必须支持两个命令行参数/RegServer/UnregServer

CLSID子键下:

com进程内进程外组件

1

 com进程内进程外组件

2

Interface子键下:

com进程内进程外组件

3

com进程内进程外组件

4

 

其中ProxyStubClsid32为该接口的存根代理dllCLSID,图1,这样在查询某接口时com库就知道到哪加载存根代理dll

3 类厂

COM库通过类厂创建COM对象,对应每一个COM类,都有一个类厂专门用于该COM类的对象创建工作。类厂本身也是一个COM对象,它支持接口IClassFactory

com进程内进程外组件

CreateInstance创建对应的COM对象,LockServer控制组件的生存周期。

类厂由函数DllGetClassObject创建。

com进程内进程外组件

DllGetClassObject返回类厂对象的接口指针,再通过CreateInstance创建对应的COM对象。

4.COM库与类厂的交互

创建对象函数:

1)若创建远程对象或希望一次获取对象的多个接口指针,选用CoCreateInstanceEx

com进程内进程外组件

2)若希望获取类厂对象或要调用类厂的某些成员函数,选用CoGetClassObject,通常IID=IID_IclassFactory,进程内组件直接调用DLLCoGetClassObject,若CoGetClassObject创建的类厂对象位于进程外组件,函数启动组件进程,然后等待,直到组件进程把它支持的COM类对象的类厂注册到COM中,返回类厂信息。

3)其他情况下,选用CoCreateInstance创建对象,CoCreateInstance封装类厂创建对象的过程,返回COM对象的接口指针,不能创建远程机器上的对象。

com进程内进程外组件

 

 

com进程内进程外组件
5.COM库

COM库初始化函数:CoInitialize

COM库终止函数:CoUninitialize

COM库内存管理:

COM提供的内存管理器标准,是一个COM接口IMalloc。当组件内存的分配和释放不在同一模块,需要用到内存管理器,COM库封装了三个API函数,用于内存分配和释放

CoTaskMemAlloc

CoTaskMemFree
CoTaskMemRealloc