21

我正在用 Win32 + WTL 进行一些编程,但我对可用的错误类型感到困惑。

通常,我想检查错误,并将其提供给 AtlGetErrorDescription(调用 FormatMessage)。

我的问题是:

  1. 有什么区别:

    • DWORD, 由GetLastError.返回
    • HRESULT,由例如CAtlFile包装器返回,用于HRESULT_FROM_WIN32从 转换DWORD
    • LSTATUS,由例如返回RegCreateKeyEx
  2. 我可以提供哪些类型的错误FormatMessage?它的签名表明它接受HRESULT,但是有很多示例将 的返回值GetLastError直接传递给FormatMessage

4

1 回答 1

29

它们只是反映了 Windows 中使用的不同 API:

  • GetLastError() 返回一个 winapi 错误代码。一个从 1 开始的简单数字。它们通常映射自底层的原生 api 错误代码。像 ERROR_FILE_NOT_FOUND 是从 STATUS_OBJECT_NAME_NOT_FOUND 文件系统驱动程序错误代码映射的。Winapi 错误代码在 WinError.h SDK 头文件中声明。您可以使用 FORMAT_MESSAGE_FROM_SYSTEM 选项从 FormatMessage() 获取描述性字符串。

  • HRESULT 是 COM 错误代码。它由三个基本部分组成,高位表示严重性,中位编码指示错误来源的设施,低 16 位编码错误编号。HRESULT_FROM_WIN32() 宏是一个辅助宏,用于将 winapi 错误代码映射到 COM 错误代码。它只是将严重性设置为“失败”,将设备代码设置为 7(winapi)并将错误代码复制到低位。有很多可能的 COM 错误代码,只有少数可以通过 FormatMessage() 转换为字符串。您应该使用 ISupportErrorInfo 接口询问 COM 服务器是否可以通过 IErrorInfo 提供错误描述。

  • LSTATUS 晦涩难懂,RegCreateEx 实际上返回 LONG,只是 winapi 错误码。它确实会在一些 shell 包装函数中弹出,例如 SHGetValue()。我常常很不清楚为什么 shell 团队会这样做。

  • 您的问题中未提及但值得注意的是本机 api 生成的错误代码。它们记录在 ntstatus.h SDK 标头中。winapi 应该包装原生 api,但这些错误代码有时会在边缘窥视,特别是在异常情况下。大多数程序员都见过 0xc0000005 (STATUS_ACCESS_VIOLATION) 异常代码。0xc00000fd 匹配此站点的名称。FormatMessage() 可以将常见的转换为字符串,只要它不是驱动程序生成的自定义错误代码。有几个 API 使用这些类型的错误代码,即使它们在用户模式下运行。常见的例子是 WIC 和媒体基金会,否则没有强烈暗示他们为什么喜欢这种方式。获取此类错误代码的字符串需要使用带有 FORMAT_MESSAGE_FROM_HMODULE 选项的 FormatMessage。

于 2013-10-23T17:37:18.893 回答