自注册进程内组件必须实现DllRegisterServer和DllUnregisterServer,通过regsvr32.exe实现注册表的注册与卸载。

自注册进程外组件必须处理命令行参数/RegServer和/UnregServer,通过它实现注册表的注册与卸载。

进程外组件模型与进程和ntdll.dll的模型类似,只和存根打交道,由存根通过LPC/RPC完成交互。

参数列集:参数及调用等信息打包传递的过程;散集:解包过程。

为什么要用注册表?为了实现组件位置透明!由COM库负责读取并创建组件(对象)。

COM规定,每一个COM对象应该有一个相应的类厂对象。为什么要有类厂这层间接性?

DllGetClassObject(类厂对象标识, IID_IClassFactory, 类厂接口指针)

类厂的LockServer函数引入锁计数是为了防止组件的所有对象都已释放,但仍需保留类厂接口指针用以在不确定的时候再创建对象。

CoGetClassObject(COM库)--->位置透明性--->DllGetClassObject(组件实现并导出)--->创建类厂并获得其指针接口--->

CoGetClassObject(COM库)--->位置透明性--->启动进程外组件进程--->CoRegisterClassObject(自注册类厂)--->返回类厂信息--->

CoCreateInstance是对CoGetClassObject的封装,不需要直接和类厂打交道了,直接获得对象的接口指针。CoCreateInstanceEx用于创建远程机器上的COM对象。

聚合模型不仅需要外包对象的支持,还需要被聚合对象的支持。因为外包对象会直接返回被聚合对象的接口指针给客户,通过该接口指针QueryInterface IUnkown接口及外包对象的接口时必须满足COM的要求。

要实现聚合外包对象需把自己的IUnkown接口指针传递给被聚合对象保存;被聚合对象实现IUnkown(即委托的IUnkown)和非委托的IUnkown两个IUnkown接口,根据是否有外包对象传入的IUnkown接口指针来调用外包对象的接口或自己的非委托IUnkown。

COM线程类型:与UI线程相对应,有消息循环的叫套件线程;与辅助线程对应,没有消息循环的叫自由线程。COM的线程特征是针对COM对象的,而非COM组件。