1.1.1 状态码
Figure 1. Format of an NTSTATUS code.
在Figure 1中所示的Sev字段指示状态的严重性,必须为系统定义的以下值之一:
STATUS_SEVERITY_SUCCESS:指示状态为成功。
STATUS_SEVERITY_INFORMATIONAL:指示状态为某种信息。
STATUS_SEVERITY_WARNING:指示状态为警告。
STATUS_SEVERITY_ERROR:指示状态为错误。
Facility字段指示该状态码是由哪个系统组件发出的。
Code字段指示详细的状态。
C字段指示该状态是否客户或 Microsoft 定义,若该字段置1,在应用程序中调用GetLastError函数将会返回明确的内核状态码,若该字段置0,则GetLastError函数返回与内核状态码对应的用户状态码。常见的内核状态码及其对应的用户状态码见下表:
Table 1. Correspondence Between Common Kernel-Mode and User-Mode Status Codes
1.1.2 结构化异常处理
A. try-finally块
__try
{
<guarded body>
}
__finally
{
<termination handler>
}
try-finally块的目的是不管保护体中是否发生异常,都会执行结束处理过程,即使在保护体中存在return语句。
Figure 2. Flow of control in a try-finally block.
NTSTATUS TryFinallyTest()
{
__try
{
++counter;
return STATUS_SUCCESS;
}
__finally
{
// 函数返回前必然运行到这里
--counter;
}
}
B. try-except块
__try
{
<guarded body>
}
__except(<filter expression>)
{
<exception handler>
}
当系统检测到保护体中的代码触发了某种异常时,系统根据filter expressions的值判断是否执行异常处理过程。
filter expressions以下三种值:
EXCEPTION_EXECUTE_HANDLER:进行异常处理,处理完后继续执行之后的程序。
EXCEPTION_CONTINUE_SEARCH:表明当前无法处理该异常。系统将查找其他的处理过程,如果找不到任何处理过程,则将系统奔溃。
EXCEPTION_CONTINUE_EXECUTION:指示系统返回引起异常的位置继续执行。
Figure 3. Flow of control in a try-except block.
PVOID p = (PVOID) 1;
__try
{
KdPrint(("About to generate exception\n"));
ProbeForWrite(p, 4, 4);
KdPrint(("You shouldn't see this message\n"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("Exception was caught\n"));
}
KdPrint(("Program kept control after exception\n"));
C. 相关的函数
GetExceptionCode():返回当前的异常值,该值是NTSTATUS类型的值。此函数只在__except表达式和紧接着 __except后的处理过程中有用。
GetExceptionInformation():返回EXCEPTION_POINTERS结构体的地址。此函数只在__except表达式中有用。
D. 主动触发异常
可调用以下函数触发异常:
Table 2. Service Functions for Raising Exceptions
1.1.3 Bug Checks
所谓的bug checks就是常见的电脑蓝屏,可以调用KeBugCheckEx函数引起bug checks。
KeBugCheckEx(bugcode, info1, info2, info3, info4);