3种错误类型
windows 中有常见的错误返回值,不同的格式类型是不同的,之间可以相互转换,今天介绍下下面3种的返回值的格式,另外提供给大家查找错误码的方法。
HRESULTs,Win32 error code,NTSTATUS
1、HRESULT
HRESULT编号空间具有以下内部结构
|
|
|
|
|
|
|
|
|
| 1 |
|
|
|
|
|
|
|
|
| 2 |
|
|
|
|
|
|
|
|
| 3 |
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
S | R | C | N | X | Facility | Code |
S(1位):严重性。如果设置,表示失败结果。如果清除,则表示成功。
R(1位):保留。如果N位清零,则该位必须设置为0。如果N位被置位,则该位由NTSTATUS编号空间定义。 NTSTATUS 和 HRESULT 的转换映射。
C(1位):客户。该位指定值是客户定义的还是Microsoft定义的。该位设置为客户定义的值,清除为Microsoft定义的值。
N(1位):如果置位,则表明该错误代码是一个NTSTATUS值(如第2.3节中所述),但该位置1。
X(1位): 保留。应该设为0。
Facility(11位):错误来源。具体可以参考下面链接。
Code(2个字节):错误代码。
格式介绍
HRESULT value
2、Win32 error code
所有Win32错误代码都必须在0x0000到0xFFFF范围内
错误代码可以查看链接:
WIN32错误代码可以转换成HRESULT
使用模式0x8007XXXX将Win32错误代码转换为HRESULT,其中XXXX是Win32十六进制值0x0000XXXX的前两个字节。
#define FACILITY_WIN32 0x0007
#define __HRESULT_FROM_WIN32(x)((HRESULT)(x)<= 0?((HRESULT)(x)):((HRESULT)(((x)&0x0000FFFF)|(FACILITY_WIN32 << 16)| 0x80000000)))
示例: ERROR_
0x00000004 ERROR_TOO_MANY_OPEN_FILES
系统无法打开文件。
3、 NTSTATUS
内部格式如下:
|
|
|
|
|
|
|
|
|
| 1 |
|
|
|
|
|
|
|
|
| 2 |
|
|
|
|
|
|
|
|
| 3 |
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Sev | C | N | Facility | Code |
Sev(2位):严重性。严重等级代码如下。
价值 | 意义 |
---|---|
STATUS_SEVERITY_SUCCESS 0x0 | 成功 |
STATUS_SEVERITY_INFORMATIONAL 0x1 | 信息性 |
STATUS_SEVERITY_WARNING 0x2 | 警告 |
STATUS_SEVERITY_ERROR 0x3 | 错误 |
C(1位):客户。这指定值是客户定义的还是Microsoft定义的。此位设置为客户定义的值,清除为Microsoft定义的值。<3>
N(1位):保留。必须将其设置为0,以便可以通过设置该位将NTSTATUS值映射到等效的HRESULT值
Facility(12位):一个值,与C位一起指示用于“代码” 字段的编号空间。
Code(2个字节):错误代码的其余部分。供应商应按其指定的含义重用下表中的值,或使用C位置1定义自己的值。C位清零时选择任何其他值都可能会导致将来发生冲突。
NTSTATUS值
示例:STATUS_* 开始
0xC0000409 STATUS_STACK_BUFFER_OVERRUN
系统在此应用程序中检测到基于堆栈的缓冲区溢出。此超限可能会允许恶意用户控制此应用程序。
查看错误码的方式
1、使用error lookup tool 工具
2、windbg !err <code> 查看错误信息
有些错误没有显示成功~
3、可以在线查找
4、代码查看
使用FormatMessage 格式化错误信息
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
#include <windows.h>
#include <strsafe.h>
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
void main()
{
// Generate an error
if(!GetProcessId(NULL))
ErrorExit(TEXT("GetProcessId"));
}
其他用于错误处理的函数
功能 | 描述 |
---|---|
Beep | 在扬声器上产生简单的音调。 |
CaptureStackbackTrace | 通过在堆栈上走动并记录每一帧的信息来捕获堆栈跟踪。 |
FatalAppExit | 显示消息框,并在关闭消息框时终止应用程序。 |
FlashWindow | 闪烁指定的窗口一次。 |
FlashWindowEx | 闪烁指定的窗口。 |
FormatMessage | 格式化消息字符串。 |
GetErrorMode | 检索当前进程的错误模式。 |
GetLastError | 检索调用线程的最后一个错误代码值。 |
GetThreadErrorMode | 检索调用线程的错误模式。 |
MessageBeep | 播放波形声音。 |
RtlLookupFunctionEntry | 在活动功能表中搜索对应于指定PC值的条目。 |
RtlNtStatusToDosError | 检索与指定的NT错误代码相对应的系统错误代码。 |
RtlPcToFileHeader | 检索包含指定PC值的图像的基地址。 |
RtlUnwind | 启动过程调用帧的展开。 |
RtlUnwind2 | 启动过程调用帧的展开。 |
RtlUnwindEx | 启动过程调用帧的展开。 |
RtlVirtualUnwind | 检索指定函数上下文之前的函数的调用上下文。 |
SetErrorMode | 控制系统是否将处理指定类型的严重错误,或进程是否将处理它们。 |
SetLastError | 设置调用线程的最后错误代码。 |
SetLastErrorEx | 设置调用线程的最后错误代码。 |
SetThreadErrorMode | 控制系统是处理指定类型的严重错误还是调用线程将处理它们。 |