ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

except.c
Go to the documentation of this file.
00001 /*
00002  * msvcrt.dll exception handling
00003  *
00004  * Copyright 2000 Jon Griffiths
00005  * Copyright 2005 Juan Lang
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  *
00021  * FIXME: Incomplete support for nested exceptions/try block cleanup.
00022  */
00023 
00024 #include <precomp.h>
00025 #include "excpt.h"
00026 #include <wine/exception.h>
00027 
00028 void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame);
00029 
00030 typedef void (__cdecl *MSVCRT_security_error_handler)(int, void *);
00031 static MSVCRT_security_error_handler security_error_handler;
00032 
00033 /* VC++ extensions to Win32 SEH */
00034 typedef struct _SCOPETABLE
00035 {
00036   int previousTryLevel;
00037   int (*lpfnFilter)(PEXCEPTION_POINTERS);
00038   int (*lpfnHandler)(void);
00039 } SCOPETABLE, *PSCOPETABLE;
00040 
00041 typedef struct _MSVCRT_EXCEPTION_FRAME
00042 {
00043   EXCEPTION_REGISTRATION_RECORD *prev;
00044   void (*handler)(PEXCEPTION_RECORD, EXCEPTION_REGISTRATION_RECORD*,
00045                   PCONTEXT, PEXCEPTION_RECORD);
00046   PSCOPETABLE scopetable;
00047   int trylevel;
00048   int _ebp;
00049   PEXCEPTION_POINTERS xpointers;
00050 } MSVCRT_EXCEPTION_FRAME;
00051 
00052 typedef struct
00053 {
00054   int   gs_cookie_offset;
00055   ULONG gs_cookie_xor;
00056   int   eh_cookie_offset;
00057   ULONG eh_cookie_xor;
00058   SCOPETABLE entries[1];
00059 } SCOPETABLE_V4;
00060 
00061 #ifdef __i386__
00062 
00063 static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie )
00064 {
00065     return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie);
00066 }
00067 
00068 #if defined(__GNUC__)
00069 static inline void call_finally_block( void *code_block, void *base_ptr )
00070 {
00071     __asm__ __volatile__ ("movl %1,%%ebp; call *%%eax"
00072                           : : "a" (code_block), "g" (base_ptr));
00073 }
00074 
00075 static inline int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp )
00076 {
00077     int ret;
00078     __asm__ __volatile__ ("pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp"
00079                           : "=a" (ret)
00080                           : "0" (func), "r" (ebp), "r" (arg)
00081                           : "ecx", "edx", "memory" );
00082     return ret;
00083 }
00084 static inline int call_unwind_func( int (*func)(void), void *ebp )
00085 {
00086     int ret;
00087     __asm__ __volatile__ ("pushl %%ebp\n\t"
00088                           "pushl %%ebx\n\t"
00089                           "pushl %%esi\n\t"
00090                           "pushl %%edi\n\t"
00091                           "movl %2,%%ebp\n\t"
00092                           "call *%0\n\t"
00093                           "popl %%edi\n\t"
00094                           "popl %%esi\n\t"
00095                           "popl %%ebx\n\t"
00096                           "popl %%ebp"
00097                           : "=a" (ret)
00098                           : "0" (func), "r" (ebp)
00099                           : "ecx", "edx", "memory" );
00100     return ret;
00101 }
00102 #elif defined(_MSC_VER)
00103 #pragma warning(push)
00104 #pragma warning(disable:4731) // Don't complain about changing ebp
00105 void __inline call_finally_block( void *code_block, void *base_ptr )
00106 {
00107     __asm
00108     {
00109         mov eax, code_block
00110         mov ebp, base_ptr
00111         call [eax]
00112     }
00113 }
00114 
00115 int __inline call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *_ebp )
00116 {
00117     int _ret;
00118     __asm
00119     {
00120         push ebp
00121         mov eax, arg
00122         push eax
00123         mov ebp, _ebp
00124         mov eax, func
00125         call [eax]
00126         mov _ret, eax
00127         pop ebp
00128         pop ebp
00129     }
00130     return _ret;
00131 }
00132 int __inline call_unwind_func( int (*func)(void), void *_ebp )
00133 {
00134     int _ret;
00135 
00136     __asm
00137     {
00138         push ebp
00139         push ebx
00140         push esi
00141         push edi
00142         mov ebp, _ebp
00143         call dword ptr [func]
00144         mov _ret, eax
00145         pop edi
00146         pop esi
00147         pop ebx
00148         pop ebp
00149     }
00150     return _ret;
00151 }
00152 #pragma warning(pop)
00153 #endif
00154 
00155 static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
00156                                    EXCEPTION_REGISTRATION_RECORD* frame,
00157                                    PCONTEXT context,
00158                                    EXCEPTION_REGISTRATION_RECORD** dispatch)
00159 {
00160   if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
00161     return ExceptionContinueSearch;
00162   *dispatch = frame;
00163   return ExceptionCollidedUnwind;
00164 }
00165 
00166 void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp )
00167 {
00168     EXCEPTION_REGISTRATION_RECORD reg;
00169     const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie );
00170 
00171     TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel);
00172 
00173     /* Register a handler in case of a nested exception */
00174     reg.Handler = (PEXCEPTION_ROUTINE)MSVCRT_nested_handler;
00175     reg.Prev = NtCurrentTeb()->NtTib.ExceptionList;
00176     __wine_push_frame(&reg);
00177 
00178     while (frame->trylevel != -2 && frame->trylevel != trylevel)
00179     {
00180         int level = frame->trylevel;
00181         frame->trylevel = scopetable->entries[level].previousTryLevel;
00182         if (!scopetable->entries[level].lpfnFilter)
00183         {
00184             TRACE( "__try block cleanup level %d handler %p ebp %p\n",
00185                    level, scopetable->entries[level].lpfnHandler, ebp );
00186             call_unwind_func( scopetable->entries[level].lpfnHandler, ebp );
00187         }
00188     }
00189     __wine_pop_frame(&reg);
00190     TRACE("unwound OK\n");
00191 }
00192 
00193 /*********************************************************************
00194  *      _except_handler4_common (MSVCRT.@)
00195  */
00196 int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void),
00197                                    EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame,
00198                                    CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
00199 {
00200     int retval, trylevel;
00201     EXCEPTION_POINTERS exceptPtrs;
00202     const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie );
00203 
00204     TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n",
00205            rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
00206            frame->handler, context, dispatcher, *cookie, scope_table,
00207            scope_table->gs_cookie_offset, scope_table->gs_cookie_xor,
00208            scope_table->eh_cookie_offset, scope_table->eh_cookie_xor );
00209 
00210     /* FIXME: no cookie validation yet */
00211 
00212     if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
00213     {
00214         /* Unwinding the current frame */
00215         msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp );
00216         TRACE("unwound current frame, returning ExceptionContinueSearch\n");
00217         return ExceptionContinueSearch;
00218     }
00219     else
00220     {
00221         /* Hunting for handler */
00222         exceptPtrs.ExceptionRecord = rec;
00223         exceptPtrs.ContextRecord = context;
00224         *((DWORD *)frame-1) = (DWORD)&exceptPtrs;
00225         trylevel = frame->trylevel;
00226 
00227         while (trylevel != -2)
00228         {
00229             TRACE( "level %d prev %d filter %p\n", trylevel,
00230                    scope_table->entries[trylevel].previousTryLevel,
00231                    scope_table->entries[trylevel].lpfnFilter );
00232             if (scope_table->entries[trylevel].lpfnFilter)
00233             {
00234                 retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp );
00235 
00236                 TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
00237                       "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
00238                       "EXECUTE_HANDLER" : "CONTINUE_SEARCH");
00239 
00240                 if (retval == EXCEPTION_CONTINUE_EXECUTION)
00241                     return ExceptionContinueExecution;
00242 
00243                 if (retval == EXCEPTION_EXECUTE_HANDLER)
00244                 {
00245                     /* Unwind all higher frames, this one will handle the exception */
00246                     _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
00247                     msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
00248 
00249                     /* Set our trylevel to the enclosing block, and call the __finally
00250                      * code, which won't return
00251                      */
00252                     frame->trylevel = scope_table->entries[trylevel].previousTryLevel;
00253                     TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler);
00254                     call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp);
00255                     ERR("Returned from __finally block - expect crash!\n");
00256                 }
00257             }
00258             trylevel = scope_table->entries[trylevel].previousTryLevel;
00259         }
00260     }
00261     TRACE("reached -2, returning ExceptionContinueSearch\n");
00262     return ExceptionContinueSearch;
00263 }
00264 
00265 /*******************************************************************
00266  *      _local_unwind4 (MSVCRT.@)
00267  */
00268 void CDECL _local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel )
00269 {
00270     msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
00271 }
00272 
00273 /*********************************************************************
00274  *      _seh_longjmp_unwind4 (MSVCRT.@)
00275  */
00276 void __stdcall _seh_longjmp_unwind4(struct __JUMP_BUFFER *jmp)
00277 {
00278     msvcrt_local_unwind4( (void *)jmp->Cookie, (MSVCRT_EXCEPTION_FRAME *)jmp->Registration,
00279                           jmp->TryLevel, (void *)jmp->Ebp );
00280 }
00281 
00282 #endif
00283 
00284 /******************************************************************
00285  *      __uncaught_exception
00286  */
00287 BOOL CDECL __uncaught_exception(void)
00288 {
00289     return FALSE;
00290 }
00291 
00292 /* _set_security_error_handler - not exported in native msvcrt, added in msvcr70 */
00293 MSVCRT_security_error_handler CDECL _set_security_error_handler(
00294     MSVCRT_security_error_handler handler )
00295 {
00296     MSVCRT_security_error_handler old = security_error_handler;
00297 
00298     TRACE("(%p)\n", handler);
00299 
00300     security_error_handler = handler;
00301     return old;
00302 }

Generated on Sat May 26 2012 04:22:57 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.