Win32 SEH异常深度探索_7 对未处理异常的默认处理

来源:互联网 发布:vb.net高级开发指南 编辑:程序博客网 时间:2024/06/04 04:00

UnhandledExceptions

Earlier in the article, I put off a fulldescription of the UnhandledExceptionFilter API. You normally don't call thisAPI directly (although you can). Most of the time, it's invoked by thefilter-expression code for KERNEL32's default exception callback. I showed thisearlier in the pseudocode for BaseProcessStart.

如果有用户未处理的异常,会调用UnhandledExceptionFilter, 一般由KERNEL32 得默认异常回调函数调用。伪代码如下:

 

 

 

Figure 13 shows my pseudocode forUnhandledExceptionFilter. The API starts out a bit strangely (at least in my opinion).If the fault is an EXCEPTION_ACCESS_ VIOLATION, the code calls_BasepCheckForReadOnlyResource. While I haven't provided pseudocode for thisfunction, I can summarize it. If the exception occurred because a resourcesection (.rsrc) of an EXE or DLL was written to, _BasepCurrentTopLevelFilterchanges the faulting page's attributes from its normal read-only state, therebyallowing the write to occur. If this particular scenario occurs,UnhandledExceptionFilter returns EXCEPTION_ CONTINUE_EXECUTION and executionrestarts at the faulting instruction.

首先,如果是EXCEPTION_ACCESS_ VIOLATION,代码首先调用_BasepCheckForReadOnlyResource 察看是否因为需要写 EXE DLL 中的资源节(.rsrc),如果是,他将改变该页的只读属性让其可写,然后返回EXCEPTION_ CONTINUE_EXECUTION 让代码在异常处继续运行。

 

The next task of UnhandledExceptionFilteris to determine if the process is being run under a Win32 debugger. That is,the process was created with the DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS flag.UnhandledExceptionFilter uses the NtQueryInformationProcess Function that Idescribe in this month's Under the Hood column to tell if the process is beingdebugged. If so, the API returns EXCEPTION_CONTINUE_SEARCH, which tells someother part of the system to wake up the debugger process and tell it that anexception occurred in the debuggee.

接下来调用NtQueryInformationProcess 判断进程是否是运行在 Win32 调试器下,也就是通过DEBUG_PROCESS DEBUG_ONLY_THIS_PROCESS 启动,如果是,返回EXCEPTION_CONTINUE_SEARCH 让系统激活调式器进程并报告异常。

 

Next on UnhandledExceptionFilter's plate isa call to the user-installed unhandled exception filter, if present. Normally,there isn't a user-installed callback, but one can be installed via theSetUnhandledExceptionFilter API. I've also provided pseudocode for this API.The API simply bashes a global variable with the new user callback address, andreturns the value of the old callback.

然后他会调用一个用户定义的未处理异常过滤函数 (用户通过SetUnhandledExceptionFilter设置该函数 )

 

With the preliminaries out of the way,UnhandledExceptionFilter can get down to its primary job: informing you of yourignominious programming blunder with the ever- stylish Application Errordialog. There are two ways that this dialog can be avoided. The first is if theprocess has called SetErrorMode and specified the SEM_NOGPFAULTERRORBOX flag.The other method is to have the Auto value under the AeDebug registry key setto 1. In this case, UnhandledExceptionFilter skips the Application Error dialogand automatically fires up whatever debugger is specified in the Debugger valueof the AeDebug key. If you're familiar with "just in time debugging,"this is where the operating system supports it. More on this later.

在大多数情况下UnhandledExceptionFilter 是做他的主要工作:弹出一个对话框报告有一个程序错误。有两种方法可以避免弹出这个框:

1.调用SetErrorMode并设置SEM_NOGPFAULTERRORBOX 标志;

2. 设置AeDebug 注册表值为1,这时UnhandledExceptionFilter 将自动启动在AeDebug 中设置的调试器。

 

In most cases, neither of these dialogavoidance conditions are true and UnhandledExceptionFilter calls theNtRaiseHardError function in NTDLL.DLL. It's this function that brings up theApplication Error dialog. This dialog waits for you to hit the OK button toterminate the process, or Cancel to debug it. (Maybe it's just me, but hittingCancel to launch a debugger seems a little backward.)

UnhandledExceptionFilter 是通过调用 NTDLL.DLL 中的NtRaiseHardError函数弹出程序错误对话框的,等待用户点击 OK 终止程序,或Cancel 调式程序。

 

If you hit OK in the Application Errordialog box, UnhandledExceptionFilter returns EXCEPTION_EXECUTE_HANDLER. Thecode that called UnhandledExceptionFilter usually responds by terminatingitself (as you saw in the BaseProcessStart code). This brings up an interestingpoint. Most people assume that the system terminates a process with anunhandled exception. It's actually more correct to say that the system sets upthings so that an unhandled exception causes the process to terminate itself.

如果点击OK,UnhandledExceptionFilter 返回 EXCEPTION_EXECUTE_HANDLER,后续代码将终止进程。这里关键的一点:不是由于系统发现进程有未处理异常而去终止进程,而是未处理异常引起进程终止自己,也就是,不是系统终止进程,而是进程终止自己。

 

The truly interesting code inUnhandledExceptionFilter executes if you select Cancel in the Application Errordialog, thereby bringing up a debugger on the faulting process. The code firstcalls CreateEvent to make an event that the debugger will signal after it hasattached to the faulting process. This event handle, along with the currentprocess ID, is passed to sprintf, which formats the command line used to startthe debugger. Once everything is prepared, UnhandledExceptionFilter callsCreateProcess to start the debugger. If CreateProcess succeeds, the code callsNtWaitForSingleObject on the event created earlier. This call blocks until thedebugger process signals the event, indicating that it has attached to thefaulting process successfully. There are other little bits and pieces to theUnhandledExceptionFilter code, but I've covered the important highlights here.

如果点击 CancelUnhandledExceptionFilter首先创建一个 Event,然后启动一个调试器进程,把自己的进程ID和那个 Event句柄作为参数传给调试器,然后等待调试器触发 Event 通知自己,然后代码返回EXCEPTION_CONTINUE_SEARCH

 

 

 

原创粉丝点击