HRESULT
COM组件常使用HERESULT来向用户报告接口函数执行的情况。
它是一个结构固定的32位值,分成三部分。
最高位表示函数调用是否成功。低16位包含函数返回值。
常用的HRESULT值
S_OK 函数成功。某些情况下表示函数返回了一个布尔true。S_OK定义为0。
NOERROR 同上。
S_FALSE 函数成功并返回一个布尔false。S_FALSE被定义为1.
E_UNEXPECTED 无法预知的失败。
E_NOIMPLE 成员函数未被实现。
E_NOINTERFACE 组件不支持请求的接口。由QueryInterface函数返回。
E_OUTOFMEMORY 组件无法分配所需内存。
E_FAIL 没有指定的失败。
HRESULT值中16-30位包含的设备代码,标识的是返回代码的操作系统部分。windows中设备代码如下
FACILITY_WINDOWS 8FACILITY_STORAGE 3
FACILITY_SSPI 9
FACILITY_RPC 1
FACILITY_WIN32 7
FACILITY_CONTROL 10
FACILITY_NULL 0
FACILITY_ITF 4
FACILITY_DISPATCH 2
FACILITY_CERT 11
WINERROR.H中包含当前系统产生的所有COM状态代码。大多数该类代码是十六进制形式。
HRESULT使用
因为HRESULT包含多个成功代码及多个失败代码,因此简单的比较不能用来判断成功与失败。
而必须使用宏SUCCEEDED和FAILED。
GUID
GUID,Globally Unique Identifier,全局唯一标识符。IID是一个128比特即16字节的GUID结构。
MSVC++有两个建立GUID的程序,一个UUIDGEN.EXE,命令行方式的。一个GUIDGEN.exe,vc++的对话框应用。
GUID在时间和空间上都是唯一的。生成它,需要一个48位的唯一值,也就是网卡地址,再加一个60位的间戳。
GUID的声明和定义
一种方法,分开定义
.h中
extern "C" const IID IID_IX;
.cpp中
extern "C" const IID IID_IX = {********值******};
另一种,使用宏
细节没太看懂。
由于GUID值占用了16个字节,因此一般不使用值传递。QueryInterface第一个参数就是引用参数。
注册表
CLSID
COM库函数CoCreateInstance用来创建组件,以组件的CLSID为参数。
组件可以用CLSID作为索引在Windows注册表中发布包含它们的DLL文件名称。
CoCreateInstance就是用CLSID作为关键字在注册表中查找需要的文件名称。
COM只使用了注册表的一个分支HKEY_CLASS_ROOT。
在此之下,可以看到CLSID关键字,CLSID之下列出了系统中安装的所有组件的CLSID。
形如{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX},不易辨认,因此它的缺省值都是有意义的,用来表明组件。
对每一个CLSID关键字,InprocServer32关键字的缺省值是组件所在的DLL文件名称。inprocServer32这个名称也就说明了问题。
其他
在HKEY_CLASS_ROOT之下,
首先列出了应用程序所注册的文件扩展名。
在扩展名之后是应用程序的名称,也就是程序员定义的标识符,即ProgID。
ProgID的格式一般遵循:<program>.<component>.<version>
ProgID也主要是用来获取对应的CLSID。COM库函数提供了CLSIDFromProgID和ProgIDFromCLSID。
如何自注册
在DLL中一定要输出如下两个函数:
HRESTUL __stdcall DllRegisterServer();
HRESTUL __stdcall DllUnregisterServer();
所有的win32 API都遵循__stdcall限定符。
DllRegisterServer和DllUnregisterServer的实现需要包含源文件winreg.h或windows.h,并将其同ADVAPI32.lib一块链接。
实现细节暂且不表。
组件类别
为了方便客户调用,根据组件实现的接口的功能大致分类,为它们分配GUID,也就是CATID。
对一个组件来说,要实现了该类组件类别的所有接口,才能被注册为该CATID的一个成员。
组件类别可以由Windows系统附带的一个 Component Category Manager来完成对注册表的处理。它实现了两个主要的COM接口:ICatRegister和ICatInformation。
COM库函数
通过OLE32.DLL,COM定义了一个函数库用来实现COM组件都需要完成的程序化操作。包括
COM的初始化,OleInitialize
内存管理,IMalloc
将字符串转化成GUID,StringFromGUID2