- Reapply 35812:

- RtlDispatchException: Call vectored exception handlers before doing anything else
- KiUserExceptionDispatcher: Call RtlDispatchException directly as it now takes care of vectored handling
- Rename RtlpExecuteVectoredExceptionHandlers to RtlCallVectoredExceptionHandlers, and fix return type
- References: "New Vectored Exception Handling in Windows XP" by Matt Pietrek
- New in this revision: Only call vectored handlers in user mode, as there is no such thing in kernel mode

svn path=/trunk/; revision=37137
This commit is contained in:
Stefan Ginsberg 2008-11-01 19:48:52 +00:00
parent ed9780429d
commit ae24c33a4f
5 changed files with 32 additions and 57 deletions

View file

@ -15,10 +15,6 @@
typedef NTSTATUS (NTAPI *USER_CALL)(PVOID Argument, ULONG ArgumentLength);
EXCEPTION_DISPOSITION NTAPI
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context);
/* FUNCTIONS ****************************************************************/
/*
@ -32,26 +28,16 @@ KiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord,
EXCEPTION_RECORD NestedExceptionRecord;
NTSTATUS Status;
/* call the vectored exception handlers */
if(RtlpExecuteVectoredExceptionHandlers(ExceptionRecord,
Context) != ExceptionContinueExecution)
/* Dispatch the exception and check the result */
if (RtlDispatchException(ExceptionRecord, Context))
{
goto ContinueExecution;
/* Continue executing */
Status = NtContinue(Context, FALSE);
}
else
{
/* Dispatch the exception and check the result */
if(RtlDispatchException(ExceptionRecord, Context))
{
ContinueExecution:
/* Continue executing */
Status = NtContinue(Context, FALSE);
}
else
{
/* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
/* Raise an exception */
Status = NtRaiseException(ExceptionRecord, Context, FALSE);
}
/* Setup the Exception record */

View file

@ -183,52 +183,22 @@ _KiRaiseUserExceptionDispatcher@0:
.globl _KiUserExceptionDispatcher@8
_KiUserExceptionDispatcher@8:
/* clear the direct flag
* text from bug 2279
* if it not clear it means that if an exception occurs while
* the direction flag is set (typically inside memmove), the
* exception handlers will be called with the direction flag still
* set. The Windows x86-32 and x86-64 ABI requires that the
* direction flag be Calling memset() with a compile-time constant
* size on both GCC and MSVC will result in inlining a "rep stosd"
* instruction. Because of the ABI, they will assume that the
* direction flag is clear and not emit a "cld" instruction.
* Using memset() in an exception handler therefore will
* corrupt memory if the exception occurred during a reverse copy
* such as a forward overlapping memmove().
*
* For reliability and ease of debugging, please add "cld" to the beginning of
* KiUserExceptionDispatcher. Note that the same will be true of x86-64 whenever
* that happens. This does not affect continuing execution; the CONTEXT of the
* exception has the direction flag set and will be restored upon NtContinue.
* KiUserApcDispatcher and KiUserCallbackDispatcher need to be evaluated for this
* issue.
*/
/* Clear direction flag */
cld
/* Save the Context and Exception Records */
mov ecx, [esp+4]
mov ebx, [esp]
/* Call the vectored exception handler */
/* Dispatch the exception */
push ecx
push ebx
call _RtlpExecuteVectoredExceptionHandlers@8
/* Check for success */
or al, al
jnz ContinueExecution
/* Dispatch the exception */
sub esp, 8
call _RtlDispatchException@8
/* Check for success */
or al, al
jz RaiseException
ContinueExecution:
/* Pop off the records */
pop ebx
pop ecx

View file

@ -74,6 +74,17 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
/* Perform vectored exception handling if we are in user mode */
if (RtlpGetMode() != KernelMode)
{
/* Call any registered vectored handlers */
if (RtlCallVectoredExceptionHandlers(ExceptionRecord, Context))
{
/* Exception handled, continue execution */
return TRUE;
}
}
/* Get the current stack limits and registration frame */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame = RtlpGetExceptionList();

View file

@ -37,6 +37,13 @@ VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
BOOLEAN
NTAPI
RtlCallVectoredExceptionHandlers(
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context
);
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;

View file

@ -28,9 +28,10 @@ typedef struct _RTL_VECTORED_EXCEPTION_HANDLER
/* FUNCTIONS ***************************************************************/
EXCEPTION_DISPOSITION NTAPI
RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
BOOLEAN
NTAPI
RtlCallVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PLIST_ENTRY CurrentEntry;
PRTL_VECTORED_EXCEPTION_HANDLER veh;
@ -55,7 +56,7 @@ RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
if(VectoredHandler(&ExceptionInfo) == EXCEPTION_CONTINUE_EXECUTION)
{
return ExceptionContinueSearch;
return TRUE;
}
RtlEnterCriticalSection(&RtlpVectoredExceptionLock);
@ -63,7 +64,7 @@ RtlpExecuteVectoredExceptionHandlers(IN PEXCEPTION_RECORD ExceptionRecord,
RtlLeaveCriticalSection(&RtlpVectoredExceptionLock);
}
return ExceptionContinueExecution;
return FALSE;
}
VOID