在Windows编程中,我们经常接触到的Windows API返回值类型有:

  • BOOL
  • HRESULT
  • LSTATUS

1. 错误码

BOOL类型通常是0表示失败,非0表示成功,在BOOL类型返回失败时,通常还可以通过GetLastError函数获取错误码。错误码与调用线程相关联,每个线程的错误码是独立的,在调用完Windows API后,如下获取错误码,则需要立即获取,否则可能会被后面调用API所设置的错误码所覆盖。

应用程序也可以通过SetLastError函数来设置错误码。

Windows API通常在没有错误发生时,将错误码设置为0,有错误发生时,视具体错误而设置为其他非0值。

微软官方文档:Debug system error codes

常见的错误码

1
2
3
ERROR_SUCCESS = 0  // 成功
ERROR_OUTOFMEMORY // 内存不足
...

2. HRESULT

2.1 HRESULT结构

HRESULT是COM返回的错误码,总共32位,它由三个基本部分组成:

  • 高1位表示成功或失败(0表示成功,1表示失败)。
  • 中间11位编码指示错误来源的设施/设备。
  • 低16位编码错误编号。

0~32位的作用分别如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
S - 严重度 - 表示成功/失败

0 - 成功
1 - 失败 (COERROR)

R - reserved portion of the facility code, corresponds to NT's second severity bit.

C - reserved portion of the facility code, corresponds to NT's C field.

N - reserved portion of the facility code. Used to indicate a mapped NT status value.

r - reserved portion of the facility code. Reserved for internal
use. Used to indicate HRESULT values that are not status
values, but are instead message ids for display strings.

Facility - 设备/设施码

Code - 设备/设施的状态码

在实际开发中,通常不需要关心其每一位的具体作用,我们使用更多的是下面的几个宏:

  • 使用SUCCEEDED(hr)宏判断是否成功(即hr>= 0),FAILED(hr)判断是否失败(即hr< 0)。
  • 使用HRESULT_CODE(hr)宏获取错误码。
  • 使用HRESULT_FACILITY(hr)宏获取设备码。

4字节(32位)整数能表示的最大正整数为7FFF FFFFF(最高位为0),当最高位为1时,则为负数。所以HRESULT能通过是否为负数来判断成功与否。

2.2 常见的HRESULT值

1
2
3
S_OK     // 成功
S_FALSE // 失败
E_FAIL // 失败

2.3 API错误码与HRESULT

我们可以使用HRESULT_FROM_WIN32宏将上一节介绍的“Windows API的错误码”转成HRESULT。

3. LSTATUS

在Windows API中对LSTATUS的定义比较模糊,比如注册表API(如RegCreateEx等)返回的LSTATUS实际就是第一节介绍的Windows错误码。

所以当遇到返回LSTATUS类型的API时,需要参考API的文档说明。