Skip to content
Snippets Groups Projects
Commit 5f308d3c authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard
Browse files

Added some exception handling functions.

parent e884cc2b
No related branches found
No related tags found
No related merge requests found
......@@ -6,10 +6,10 @@
* See http://www.microsoft.com/msj/0197/exception/exception.htm,
* but don't believe all of it.
*
* FIXME: Incomplete, no support for nested exceptions or try block cleanup.
* FIXME: Incomplete support for nested exceptions/try block cleanup.
*/
#include <setjmp.h>
#include "ntddk.h"
#include "wine/exception.h"
#include "thread.h"
#include "msvcrt.h"
......@@ -21,28 +21,41 @@ typedef void (*MSVCRT_sig_handler_func)(void);
typedef struct _SCOPETABLE
{
DWORD previousTryLevel;
int (__cdecl *lpfnFilter)(int, PEXCEPTION_POINTERS);
int (__cdecl *lpfnHandler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_FRAME *);
int (__cdecl *lpfnFilter)(PEXCEPTION_POINTERS);
int (__cdecl *lpfnHandler)(void);
} SCOPETABLE, *PSCOPETABLE;
typedef struct _MSVCRT_EXCEPTION_REGISTRATION
typedef struct _MSVCRT_EXCEPTION_FRAME
{
struct _EXCEPTION_REGISTRATION *prev;
EXCEPTION_FRAME *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_RECORD);
PSCOPETABLE scopetable;
int trylevel;
DWORD trylevel;
int _ebp;
PEXCEPTION_POINTERS xpointers;
} MSVCRT_EXCEPTION_REGISTRATION;
} MSVCRT_EXCEPTION_FRAME;
typedef struct _EXCEPTION_REGISTRATION
#define TRYLEVEL_END 0xff /* End of trylevel list */
#if defined(__GNUC__) && defined(__i386__)
#define CALL_FINALLY_BLOCK(code_block, base_ptr) \
__asm__ __volatile__ ("movl %0,%%eax; movl %1,%%ebp; call *%%eax" \
: : "g" (code_block), "g" (base_ptr))
static DWORD __cdecl MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
struct __EXCEPTION_FRAME *frame,
PCONTEXT context WINE_UNUSED,
struct __EXCEPTION_FRAME **dispatch)
{
struct _EXCEPTION_REGISTRATION *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_RECORD);
} EXCEPTION_REGISTRATION;
if (rec->ExceptionFlags & 0x6)
return ExceptionContinueSearch;
*dispatch = frame;
return ExceptionCollidedUnwind;
}
#endif
/*********************************************************************
* _XcptFilter (MSVCRT.@)
......@@ -75,22 +88,42 @@ __ASM_GLOBAL_FUNC(MSVCRT__EH_prolog,
*/
void __cdecl MSVCRT__global_unwind2(PEXCEPTION_FRAME frame)
{
#if defined(__GNUC__) && defined(__i386__)
TRACE("(%p)\n",frame);
if (0)
unwind_label: return;
RtlUnwind( frame, &&unwind_label, 0, 0 );
#else
FIXME("(%p) stub\n",frame);
#endif
TRACE("(%p)\n",frame);
RtlUnwind( frame, 0, 0, 0 );
}
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void __cdecl MSVCRT__local_unwind2(MSVCRT_EXCEPTION_REGISTRATION *endframe, DWORD nr )
void __cdecl MSVCRT__local_unwind2(MSVCRT_EXCEPTION_FRAME *frame,
DWORD trylevel)
{
FIXME("(%p,%ld) stub\n",endframe,nr);
MSVCRT_EXCEPTION_FRAME *curframe = frame;
DWORD curtrylevel = 0xfe;
EXCEPTION_FRAME reg;
TRACE("(%p,%ld,%ld)\n",frame, frame->trylevel, trylevel);
/* Register a handler in case of a nested exception */
reg.Handler = (PEXCEPTION_HANDLER)MSVCRT_nested_handler;
reg.Prev = NtCurrentTeb()->except;
__wine_push_frame(&reg);
while (frame->trylevel != TRYLEVEL_END && frame->trylevel != trylevel)
{
curtrylevel = frame->scopetable[frame->trylevel].previousTryLevel;
curframe = frame;
curframe->trylevel = curtrylevel;
if (!frame->scopetable[curtrylevel].lpfnFilter)
{
ERR("__try block cleanup not implemented - expect crash!\n");
/* FIXME: Remove current frame, set ebp, call
* frame->scopetable[curtrylevel].lpfnHandler()
*/
}
}
__wine_pop_frame(&reg);
TRACE("unwound OK\n");
}
/*********************************************************************
......@@ -98,7 +131,8 @@ void __cdecl MSVCRT__local_unwind2(MSVCRT_EXCEPTION_REGISTRATION *endframe, DWOR
*/
int __cdecl MSVCRT__except_handler2(PEXCEPTION_RECORD rec,
PEXCEPTION_FRAME frame,
PCONTEXT context, PEXCEPTION_FRAME *dispatcher)
PCONTEXT context,
PEXCEPTION_FRAME *dispatcher)
{
FIXME("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
......@@ -110,12 +144,73 @@ int __cdecl MSVCRT__except_handler2(PEXCEPTION_RECORD rec,
* _except_handler3 (MSVCRT.@)
*/
int __cdecl MSVCRT__except_handler3(PEXCEPTION_RECORD rec,
MSVCRT_EXCEPTION_REGISTRATION *frame,
MSVCRT_EXCEPTION_FRAME *frame,
PCONTEXT context,void *dispatcher)
{
FIXME("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
#if defined(__GNUC__) && defined(__i386__)
long retval, trylevel;
EXCEPTION_POINTERS exceptPtrs;
PSCOPETABLE pScopeTable;
TRACE("exception %lx flags=%lx at %p handler=%p %p %p semi-stub\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
frame->handler, context, dispatcher);
__asm__ __volatile__ ("cld");
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{
/* Unwinding the current frame */
MSVCRT__local_unwind2(frame, TRYLEVEL_END);
return ExceptionContinueSearch;
}
else
{
/* Hunting for handler */
exceptPtrs.ExceptionRecord = rec;
exceptPtrs.ContextRecord = context;
*((DWORD *)frame-1) = (DWORD)&exceptPtrs;
trylevel = frame->trylevel;
pScopeTable = frame->scopetable;
while (trylevel != TRYLEVEL_END)
{
if (pScopeTable[trylevel].lpfnFilter)
{
TRACE("filter = %p\n", pScopeTable[trylevel].lpfnFilter);
retval = pScopeTable[trylevel].lpfnFilter(&exceptPtrs);
TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
"CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
"EXECUTE_HANDLER" : "CONTINUE_SEARCH");
if (retval == EXCEPTION_CONTINUE_EXECUTION)
return ExceptionContinueExecution;
if (retval == EXCEPTION_EXECUTE_HANDLER)
{
/* Unwind all higher frames, this one will handle the exception */
MSVCRT__global_unwind2((PEXCEPTION_FRAME)frame);
MSVCRT__local_unwind2(frame, trylevel);
/* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return
*/
frame->trylevel = pScopeTable->previousTryLevel;
TRACE("__finally block %p\n",pScopeTable[trylevel].lpfnHandler);
CALL_FINALLY_BLOCK(pScopeTable[trylevel].lpfnHandler, frame->_ebp);
ERR("Returned from __finally block - expect crash!\n");
}
}
trylevel = pScopeTable->previousTryLevel;
}
}
#else
TRACE("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
frame->handler, context, dispatcher);
#endif
return ExceptionContinueSearch;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment