COM技术内幕第六章笔记HRESULT、GUID、注册表及其他

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          8
FACILITY_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包含多个成功代码及多个失败代码,因此简单的比较不能用来判断成功与失败。

而必须使用宏SUCCEEDEDFAILED

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库函数提供了CLSIDFromProgIDProgIDFromCLSID

如何自注册

在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接口:ICatRegisterICatInformation

COM库函数

通过OLE32.DLL,COM定义了一个函数库用来实现COM组件都需要完成的程序化操作。包括

COM的初始化,OleInitialize
内存管理,IMalloc
将字符串转化成GUID,StringFromGUID2

原文地址:https://www.cnblogs.com/mumuliang/p/1873486.html