Commit 3b3ff2bb authored by Alexandre Julliard's avatar Alexandre Julliard

Added macros and definitions for using exception inside Wine or

Winelib code.
parent 89fae7eb
......@@ -8,7 +8,7 @@
#include "debugtools.h"
#include "winnt.h"
#include "ntddk.h"
#include "except.h"
#include "wine/exception.h"
#include "stackframe.h"
DEFAULT_DEBUG_CHANNEL(seh)
......@@ -248,7 +248,7 @@ REGS_ENTRYPOINT(NtRaiseException)
first = (BOOL)STACK32_POP(context);
STACK32_PUSH(context,ret); /* restore return addr */
EXC_RaiseException( rec, context );
EXC_RaiseException( rec, ctx );
*context = *ctx;
}
......@@ -276,9 +276,6 @@ REGS_ENTRYPOINT(RtlRaiseException)
/*******************************************************************
* RtlUnwind (KERNEL32.590) (NTDLL.518)
*
* This function is undocumented. This is the general idea of
* RtlUnwind, though. Note that error handling is not yet implemented.
*
* The real prototype is:
* void WINAPI RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
* PEXCEPTION_RECORD pRecord, DWORD returnEax );
......
......@@ -19,7 +19,6 @@
#include "selectors.h"
#include "syslevel.h"
#include "task.h"
#include "except.h"
#include "win.h"
#include "flatthunk.h"
#include "mouse.h"
......
/*
* except.h
* Copyright (c) 1996 Onno Hovers (onno@stack.urc.tue.nl)
* Copyright (c) 1999 Alexandre Julliard
*/
#ifndef __WINE_EXCEPT_H
#define __WINE_EXCEPT_H
#include <setjmp.h>
#include "winnt.h"
#include "thread.h"
static inline EXCEPTION_FRAME *EXC_push_frame( EXCEPTION_FRAME *frame )
{
TEB * teb = NtCurrentTeb();
frame->Prev = teb->except;
teb->except = frame;
return frame;
}
static inline EXCEPTION_FRAME *EXC_pop_frame( EXCEPTION_FRAME *frame )
{
NtCurrentTeb()->except = frame->Prev;
return frame->Prev;
}
#endif /* __WINE_EXCEPT_H */
/*
* Wine exception handling
*
* Copyright (c) 1999 Alexandre Julliard
*/
#ifndef __WINE_WINE_EXCEPTION_H
#define __WINE_WINE_EXCEPTION_H
#include <setjmp.h>
#include "winnt.h"
#include "thread.h"
/* The following definitions allow using exceptions in Wine and Winelib code
*
* They should be used like this:
*
* __TRY()
* {
* do some stuff that can raise an exception
* }
* __EXCEPT(filter_func,param)
* {
* handle the exception here
* }
* __ENDTRY()
*
* or
*
* __TRY()
* {
* do some stuff that can raise an exception
* }
* __FINALLY(finally_func,param)
*
* The filter_func must be defined with the WINE_EXCEPTION_FILTER
* macro, and return one of the EXCEPTION_* code; it can use
* GetExceptionInformation and GetExceptionCode to retrieve the
* exception info.
*
* The finally_func must be defined with the WINE_FINALLY_FUNC macro.
*
* Warning: you cannot use return, break, or continue inside a __TRY
* or __EXCEPT block.
*
* -- AJ
*/
#define __TRY() \
do { __WINE_FRAME __f; int __state = -1; \
while (__state != 2) switch(__state) \
{ case 0: /* try */
#define __EXCEPT(func,arg) \
__state = 2; break; \
case -1: /* init */ \
__f.frame.Handler = (PEXCEPTION_HANDLER)WINE_exception_handler; \
__f.u.e.filter = (func); \
__f.u.e.param = (LPVOID)(arg); \
EXC_push_frame( &__f.frame ); \
__state = setjmp( __f.u.e.jmp); \
break; \
case 1: /* except */
#define __ENDTRY() \
__state++; break; \
} \
EXC_pop_frame( &__f.frame ); \
} while (0);
#define __FINALLY(func,arg) \
__state = 2; break; \
case -1: /* init */ \
__f.frame.Handler = (PEXCEPTION_HANDLER)WINE_finally_handler; \
__f.u.f.finally_func = (func); \
__f.u.f.param = (LPVOID)(arg); \
EXC_push_frame( &__f.frame ); \
__ENDTRY()
#define WINE_EXCEPTION_FILTER(func,arg) DWORD WINAPI func( EXCEPTION_POINTERS *__eptr, LPVOID arg )
#define WINE_FINALLY_FUNC(func,arg) void WINAPI func( LPVOID arg )
#define GetExceptionInformation() (__eptr)
#define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode)
typedef DWORD (*CALLBACK __WINE_FILTER)(PEXCEPTION_POINTERS,LPVOID);
typedef void (*CALLBACK __WINE_FINALLY)(LPVOID);
typedef struct
{
EXCEPTION_FRAME frame;
union
{
struct /* exception data */
{
__WINE_FILTER filter;
LPVOID param;
jmp_buf jmp;
} e;
struct /* finally data */
{
__WINE_FINALLY finally_func;
LPVOID param;
} f;
} u;
} __WINE_FRAME;
extern DWORD WINAPI WINE_exception_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher );
extern DWORD WINAPI WINE_finally_handler( PEXCEPTION_RECORD record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher );
static inline EXCEPTION_FRAME *EXC_push_frame( EXCEPTION_FRAME *frame )
{
TEB * teb = NtCurrentTeb();
frame->Prev = teb->except;
teb->except = frame;
return frame;
}
static inline EXCEPTION_FRAME *EXC_pop_frame( EXCEPTION_FRAME *frame )
{
NtCurrentTeb()->except = frame->Prev;
return frame->Prev;
}
#endif /* __WINE_WINE_EXCEPTION_H */
......@@ -20,27 +20,18 @@
* But exception handling is so basic to Win32 that it should be
* documented!
*
* Fixmes:
* -Most functions need better parameter checking.
* -I do not know how to handle exceptions within an exception handler.
* or what is done when ExceptionNestedException is returned from an
* exception handler
* -Real exceptions are not yet implemented. only the exception functions
* are implemented. A real implementation needs some new code in
* loader/signal.c. There would also be a need for showing debugging
* information in UnhandledExceptionFilter.
*
*/
#include <assert.h>
#include "winuser.h"
#include "winerror.h"
#include "ntddk.h"
#include "wine/exception.h"
#include "ldt.h"
#include "process.h"
#include "thread.h"
#include "debugtools.h"
#include "except.h"
#include "stackframe.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(seh)
......@@ -107,3 +98,55 @@ LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
pdb->top_filter = filter;
return old;
}
/*************************************************************
* WINE_exception_handler
*
* Exception handler for exception blocks declared in Wine code.
*/
DWORD WINAPI WINE_exception_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher )
{
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
return ExceptionContinueSearch;
if (wine_frame->u.e.filter)
{
EXCEPTION_POINTERS ptrs;
ptrs.ExceptionRecord = record;
ptrs.ContextRecord = context;
switch(wine_frame->u.e.filter( &ptrs, wine_frame->u.e.param ))
{
case EXCEPTION_CONTINUE_SEARCH:
return ExceptionContinueSearch;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
case EXCEPTION_EXECUTE_HANDLER:
break;
default:
/* FIXME: should probably raise a nested exception here */
return ExceptionContinueSearch;
}
}
RtlUnwind( frame, 0, record, 0 );
longjmp( wine_frame->u.e.jmp, 1 );
}
/*************************************************************
* WINE_finally_handler
*
* Exception handler for try/finally blocks declared in Wine code.
*/
DWORD WINAPI WINE_finally_handler( EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
CONTEXT *context, LPVOID pdispatcher )
{
__WINE_FRAME *wine_frame = (__WINE_FRAME *)frame;
if (!(record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
return ExceptionContinueSearch;
wine_frame->u.f.finally_func( wine_frame->u.f.param );
return ExceptionContinueSearch;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment