我正在Win32 + WTL中进行一些编程,我对可用的错误类型感到困惑。
一般情况下,我想检查错误,并将其提供给AtlGetErrorDescription(调用FormatMessage)。
我的问题是:
有什么区别:
DWORD
,由GetLastError
返回。HRESULT
,由例如CAtlFile
包装器,使用HRESULT_FROM_WIN32
转换DWORD
。LSTATUS
,由例如RegCreateKeyEx
。我可以向FormatMessage
提供哪些类型的错误?它的签名表示它接受HRESULT
,但有很多示例将GetLastError
的返回值直接传递给FormatMessage
。
答案 0 :(得分:22)
它们只反映了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和媒体基金会,否则没有强烈暗示他们为什么喜欢这种方式。获取此类错误代码的字符串需要使用FormatMessage和FORMAT_MESSAGE_FROM_HMODULE选项。