HRESULT是一个可以分成三个域的32位值,
注意:S_FALSE被定义为1而S_OK被定义为0,这一点同C/C++变成原则正好相反。
HRESULT值中16到30这15个比特位包含的时设备代码,设备代码标识的时可以返回HRESULT中返回代码的操作系统部分。当前定义的:
一个函数在各种情况下返回的状态太代码通常包含多个成功代码及多个失败代码。这就是为什么要使用SUCCEEDED及FAILED宏的原因。一般不直接将HRESULT值同某个成功代码(如S_OK)| 失败代码(如S_FAILE)进行比较以决定某个函数是否成功,应使用SECCEEDED及FAILED宏判断
其他人可能会定义新的HRESULT错误代码,客户程序也可能会遇到相应的错误。由于客户使用的组件可能会发生变化,因此组件返回的错误代码也可能会发生变化。
为什么要使用GUID来标识接口而不是用一个长整数呢?问题的实质并不是在于我们可以标识多少个接口,而在于怎样保证每一个接口标识符都是唯一的。
可以使用ObjBase.h中的DEFINE_GUID宏来定义
#ifndefINITGUID
#defineDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID FAR name
#else
#defineDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#endif // INITGUID
在ObjBase.h中所定义的DEFINE_GUID将产生于下列类似的输出:
EXTERN_C const GUID FAR IID_IX
但是,如果在OBjBase.h之后包含INITGUID.H,那么DEFINE_GUID所产生的代码就如下:
//{32bb8320-b41b-11cf-a6bb-0080c7b2d682}
Extern “C” const IID IID_IX =
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6,0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;
在ObjBase.H中定义了一个==操作符,也可以使用IsEqualGUID、IsEqualIID以及IsEqualCLSID。
注册表是一个有许多元素构成的层次结构,每一个元素均被称作是一个关键字。每一个关键字可以包含一系列子关键字。一系列命名的值及/或一个未命名的值。子关键字也可以包含他的子关键字及值,但值却不能有子关键字或值。每一个值都有其相应的类型。注册表结构:
COM只使用了注册表的一个分支:HEKY_CLASSES_ROOT。在此关键字下,可以找到有CLSID关键字。在clsid关键字之下列有系统所有安装的组件的CLSID,注册表CLSID是一个具有如下格式的串:{32bb8320-b41b-11cf-a6bb-0080c7b2d682},对于关键字现在关心的时他的一个子关键字InprocServer32.此关键字的缺省值是组件所在的DLL文件名称
在HKEY_CLASSES_ROOT地开头,列出的将是各种应用程序所注册的文件扩展名。在扩展名之后,可以看到许多其他的名字。此类名字的大多数被称为ProgID,表示是程序员定义的标识符。
ProgID指的时程序员给某个CLSID指定的一个程序员易记的名称。
ProgID具有如下的格式:
<Program>.<Component>.<Version>
比如:Visio.Drawing.4
CLSID clsid;
CLSIDFromProgID(L"Primer.xxx.1",&clsid);
DLL要输出一下两个函数:
#defineSTDAPI EXTERN_C HRESULTSTDAPICALLTYPE
STDAPI DllRegisterServer();
STDAPI DllUnregisterServer();
用户可以使用程序RegSve32.exe来注册某个组件。它实际上通过调用上述那些函数来完成组件的注册的。
通过直接调用注册表函数来完成的。API中有许多想注册表中加入新的关键字及删除某个关键字的函数。
RegOpenKeyEx
RegCreateKeyEx
RegSetValueEx
RegEnumKeyEx
RegDeleteKey
RegCloseKey
组件类实际上就是一个接口集合,该集合将被分配给一个GUID,此GUID此时叫做CATID。对于某个组件而言,若它实现了某个组件类别的所有接口,那么他就可以将其注册成该组件类别的一个成员。客户就可以通过从注册表中选择只属于某个特定组件类别的组件而准备找到他所需要的组件
在使用COM库的其他函数之前,进程必须先调用CoInitialize才初始化COM库函数。当进程不在需要使用COM函数时,必须调用CoUnInitialize
CoTaskMemAlloc()
CoTaskMemFree();
在注册表中包含的CLSID的字符串表示,因此需要一些函数来完成从CLSID到字符串的转换