在本章中,我们将会讨论关于前面所未能细说的一些细节问题。
首先就是HRESULT。关于它我们在第3章中讨论QueryInterface时曾有所提及。第二个是GUID。传递给Qnerylnterface的IID结构就是GUID的一个例子。之后,我们将讨论组件如何在Windows的注册表中发布其位置信息,以便客户能够找到并创建它们。最后我们将介绍COM库中的一些有用的函数及实用程序。
HRESULT
COM使用HRESUTL来向其用户报告各种情况。例如 QueryInterface 返回的就是一个HRESULT值。在后面的章节中我们将会看到,许多COM接口函数所返问的均是HRESULT值。
HRESULT这种类型的值并不是一个指向某个结果的句柄。HRESULT值实际上是一个可分成三个域的32位值。图6-1显示了这三个部分的含义。这个名称的形成是有其历史原因的,读者不要将它想成是“结果的句柄”(Handle to RESULT),而应将其当成是“这就是结果”(Here’s the RESULT)。
系统所生成的HRESULT值在Win32的头文件WINERROR.H中有定义。在此文件的前面列出的是Win32的错误代码。HRESULT值同Win32的错误代码有些类似,但读者不应将它们等同起来,也不要将其混淆。
图6-1所示的HRESULT值中最重要的比特位表示函数调用是否成功。这种设计使得函数可以返回多个成功代码及失败代码。HRESULT的低16位包含的就是函数的返回代码,其余的15位包含的是此类型及返回值起源的更详细的信息。
表6-1列出了那些最常用的错误代码。其中表示成功返回的代码在其名称前都有一个S_前缀,而表示失败返回的代码其名称前的前缀则是E_。
表6-1 常用HRESULT值
名称 | 含义 |
---|---|
S_OK | 函数成功。在某些情况下,它还表示函数返回了一个布尔真值。S_OK被定义为0。 |
NOERROR | 同S_OK相同。 |
S_ FALSE | 函数成功并返回一个布尔假值。S_FALSE被定义为1。 |
E_ UNEXPECTED | 无法预知的失败。 |
E_ NOIMPLE | 成员函数未被实现。 |
E_ NOINTERFACE | 组件不支持所请求的接口。此值将由QueryInterface函数返回。 |
E. OUTOFMEMORY | 组件无法分配所需的内存。 |
E_ FAIL | 没有指定的失败。 |
注意S_FALSE被定义成1而S_OK被定义成0,这点同C/C++编程原则正好是相反的。因此在使用HRESULT值时,应将返回的值直接同S_FAISE或S_OK进行比较。
HRESULT值中16到30这15个比特位包含的是设备代码。设备代码标识的是可以返回HRESULT中返回代码的操作系统部分。由于Windows操作系统是由Microsoft开发的,因此它保留有定义设备代码的权力。当前所定义的设备代码如表6-2所列。
表6-2 当前所定义的内设备代码
FACILITY_WINDOWS | 8 |
FACILITY_STORAGE | 3 |
FACILITY_SSPI | 9 |
FACILITY_RPC | 1 |
FACILITY_WTN32 | 7 |
FACTLITY_CONTROL | 10 |
FACILITY_NULL | 0 |
FACILITY_ITF | 4 |
FACILITY_DISPATCH | 2 |
FACILITY_CERT | 11 |