ReactOS  0.4.15-dev-3303-g1ade494
except_i386.c
Go to the documentation of this file.
1 /*
2  * msvcrt C++ exception handling
3  *
4  * Copyright 2000 Jon Griffiths
5  * Copyright 2002 Alexandre Julliard
6  * Copyright 2005 Juan Lang
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  *
22  * NOTES
23  * A good reference is the article "How a C++ compiler implements
24  * exception handling" by Vishal Kochhar, available on
25  * www.thecodeproject.com.
26  */
27 
28 #include "config.h"
29 #include "wine/port.h"
30 
31 #ifdef __i386__
32 
33 #include <stdarg.h>
34 
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winternl.h"
38 #include "msvcrt.h"
39 #include "wine/exception.h"
40 #include "excpt.h"
41 #include "wine/debug.h"
42 
43 #include "cppexcept.h"
44 
46 
47 
48 /* the exception frame used by CxxFrameHandler */
49 typedef struct __cxx_exception_frame
50 {
51  EXCEPTION_REGISTRATION_RECORD frame; /* the standard exception frame */
52  int trylevel;
53  DWORD ebp;
55 
56 /* info about a single catch {} block */
57 typedef struct __catchblock_info
58 {
59  UINT flags; /* flags (see below) */
60  const type_info *type_info; /* C++ type caught by this block */
61  int offset; /* stack offset to copy exception object to */
62  void * (*handler)(void);/* catch block handler code */
64 #define TYPE_FLAG_CONST 1
65 #define TYPE_FLAG_VOLATILE 2
66 #define TYPE_FLAG_REFERENCE 8
67 
68 /* info about a single try {} block */
69 typedef struct __tryblock_info
70 {
71  int start_level; /* start trylevel of that block */
72  int end_level; /* end trylevel of that block */
73  int catch_level; /* initial trylevel of the catch block */
74  int catchblock_count; /* count of catch blocks in array */
75  const catchblock_info *catchblock; /* array of catch blocks */
77 
78 /* info about the unwind handler for a given trylevel */
79 typedef struct __unwind_info
80 {
81  int prev; /* prev trylevel unwind handler, to run after this one */
82  void * (*handler)(void);/* unwind handler */
83 } unwind_info;
84 
85 /* descriptor of all try blocks of a given function */
86 typedef struct __cxx_function_descr
87 {
88  UINT magic; /* must be CXX_FRAME_MAGIC */
89  UINT unwind_count; /* number of unwind handlers */
90  const unwind_info *unwind_table; /* array of unwind handlers */
91  UINT tryblock_count; /* number of try blocks */
92  const tryblock_info *tryblock; /* array of try blocks */
94  const void *ipmap;
95  const void *expect_list; /* expected exceptions list when magic >= VC7 */
96  UINT flags; /* flags when magic >= VC8 */
98 
99 typedef struct
100 {
101  cxx_exception_frame *frame;
102  const cxx_function_descr *descr;
103  EXCEPTION_REGISTRATION_RECORD *nested_frame;
104 } se_translator_ctx;
105 
106 typedef struct _SCOPETABLE
107 {
108  int previousTryLevel;
109  int (*lpfnFilter)(PEXCEPTION_POINTERS);
110  void * (*lpfnHandler)(void);
111 } SCOPETABLE, *PSCOPETABLE;
112 
113 typedef struct _MSVCRT_EXCEPTION_FRAME
114 {
118  PSCOPETABLE scopetable;
119  int trylevel;
120  int _ebp;
121  PEXCEPTION_POINTERS xpointers;
122 } MSVCRT_EXCEPTION_FRAME;
123 
124 typedef struct
125 {
126  int gs_cookie_offset;
127  ULONG gs_cookie_xor;
128  int eh_cookie_offset;
129  ULONG eh_cookie_xor;
130  SCOPETABLE entries[1];
131 } SCOPETABLE_V4;
132 
133 #define TRYLEVEL_END (-1) /* End of trylevel list */
134 
135 DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
137  const cxx_function_descr *descr,
138  EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel ) DECLSPEC_HIDDEN;
139 
140 /* call a copy constructor */
141 extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
142 
143 __ASM_GLOBAL_FUNC( call_copy_ctor,
144  "pushl %ebp\n\t"
145  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
146  __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
147  "movl %esp, %ebp\n\t"
148  __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
149  "pushl $1\n\t"
150  "movl 12(%ebp), %ecx\n\t"
151  "pushl 16(%ebp)\n\t"
152  "call *8(%ebp)\n\t"
153  "leave\n"
154  __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
155  __ASM_CFI(".cfi_same_value %ebp\n\t")
156  "ret" );
157 
158 /* continue execution to the specified address after exception is caught */
159 extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr );
160 
161 __ASM_GLOBAL_FUNC( continue_after_catch,
162  "movl 4(%esp), %edx\n\t"
163  "movl 8(%esp), %eax\n\t"
164  "movl -4(%edx), %esp\n\t"
165  "leal 12(%edx), %ebp\n\t"
166  "jmp *%eax" );
167 
168 extern void DECLSPEC_NORETURN call_finally_block( void *code_block, void *base_ptr );
169 
170 __ASM_GLOBAL_FUNC( call_finally_block,
171  "movl 8(%esp), %ebp\n\t"
172  "jmp *4(%esp)" );
173 
174 extern int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp );
175 
176 __ASM_GLOBAL_FUNC( call_filter,
177  "pushl %ebp\n\t"
178  "pushl 12(%esp)\n\t"
179  "movl 20(%esp), %ebp\n\t"
180  "call *12(%esp)\n\t"
181  "popl %ebp\n\t"
182  "popl %ebp\n\t"
183  "ret" );
184 
185 extern void *call_handler( void * (*func)(void), void *ebp );
186 
187 __ASM_GLOBAL_FUNC( call_handler,
188  "pushl %ebp\n\t"
189  "pushl %ebx\n\t"
190  "pushl %esi\n\t"
191  "pushl %edi\n\t"
192  "movl 24(%esp), %ebp\n\t"
193  "call *20(%esp)\n\t"
194  "popl %edi\n\t"
195  "popl %esi\n\t"
196  "popl %ebx\n\t"
197  "popl %ebp\n\t"
198  "ret" );
199 
200 static inline void dump_type( const cxx_type_info *type )
201 {
202  TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n",
203  type->flags, type->type_info, dbgstr_type_info(type->type_info),
204  type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset,
205  type->size, type->copy_ctor );
206 }
207 
208 static void dump_exception_type( const cxx_exception_type *type )
209 {
210  UINT i;
211 
212  TRACE( "flags %x destr %p handler %p type info %p\n",
213  type->flags, type->destructor, type->custom_handler, type->type_info_table );
214  for (i = 0; i < type->type_info_table->count; i++)
215  {
216  TRACE( " %d: ", i );
217  dump_type( type->type_info_table->info[i] );
218  }
219 }
220 
221 static void dump_function_descr( const cxx_function_descr *descr )
222 {
223  UINT i;
224  int j;
225 
226  TRACE( "magic %x\n", descr->magic );
227  TRACE( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count );
228  for (i = 0; i < descr->unwind_count; i++)
229  {
230  TRACE( " %d: prev %d func %p\n", i,
231  descr->unwind_table[i].prev, descr->unwind_table[i].handler );
232  }
233  TRACE( "try table: %p %d\n", descr->tryblock, descr->tryblock_count );
234  for (i = 0; i < descr->tryblock_count; i++)
235  {
236  TRACE( " %d: start %d end %d catchlevel %d catch %p %d\n", i,
237  descr->tryblock[i].start_level, descr->tryblock[i].end_level,
238  descr->tryblock[i].catch_level, descr->tryblock[i].catchblock,
239  descr->tryblock[i].catchblock_count );
240  for (j = 0; j < descr->tryblock[i].catchblock_count; j++)
241  {
242  const catchblock_info *ptr = &descr->tryblock[i].catchblock[j];
243  TRACE( " %d: flags %x offset %d handler %p type %p %s\n",
244  j, ptr->flags, ptr->offset, ptr->handler,
245  ptr->type_info, dbgstr_type_info( ptr->type_info ) );
246  }
247  }
248  if (descr->magic <= CXX_FRAME_MAGIC_VC6) return;
249  TRACE( "expect list: %p\n", descr->expect_list );
250  if (descr->magic <= CXX_FRAME_MAGIC_VC7) return;
251  TRACE( "flags: %08x\n", descr->flags );
252 }
253 
254 /* check if the exception type is caught by a given catch block, and return the type that matched */
255 static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type,
256  const type_info *catch_ti, UINT catch_flags )
257 {
258  UINT i;
259 
260  for (i = 0; i < exc_type->type_info_table->count; i++)
261  {
262  const cxx_type_info *type = exc_type->type_info_table->info[i];
263 
264  if (!catch_ti) return type; /* catch(...) matches any type */
265  if (catch_ti != type->type_info)
266  {
267  if (strcmp( catch_ti->mangled, type->type_info->mangled )) continue;
268  }
269  /* type is the same, now check the flags */
270  if ((exc_type->flags & TYPE_FLAG_CONST) &&
271  !(catch_flags & TYPE_FLAG_CONST)) continue;
272  if ((exc_type->flags & TYPE_FLAG_VOLATILE) &&
273  !(catch_flags & TYPE_FLAG_VOLATILE)) continue;
274  return type; /* it matched */
275  }
276  return NULL;
277 }
278 
279 
280 /* copy the exception object where the catch block wants it */
281 static void copy_exception( void *object, cxx_exception_frame *frame,
282  const catchblock_info *catchblock, const cxx_type_info *type )
283 {
284  void **dest_ptr;
285 
286  if (!catchblock->type_info || !catchblock->type_info->mangled[0]) return;
287  if (!catchblock->offset) return;
288  dest_ptr = (void **)((char *)&frame->ebp + catchblock->offset);
289 
290  if (catchblock->flags & TYPE_FLAG_REFERENCE)
291  {
292  *dest_ptr = get_this_pointer( &type->offsets, object );
293  }
294  else if (type->flags & CLASS_IS_SIMPLE_TYPE)
295  {
296  memmove( dest_ptr, object, type->size );
297  /* if it is a pointer, adjust it */
298  if (type->size == sizeof(void *)) *dest_ptr = get_this_pointer( &type->offsets, *dest_ptr );
299  }
300  else /* copy the object */
301  {
302  if (type->copy_ctor)
303  call_copy_ctor( type->copy_ctor, dest_ptr, get_this_pointer(&type->offsets,object),
304  (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) );
305  else
306  memmove( dest_ptr, get_this_pointer(&type->offsets,object), type->size );
307  }
308 }
309 
310 /* unwind the local function up to a given trylevel */
311 static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level)
312 {
313  void * (*handler)(void);
314  int trylevel = frame->trylevel;
315 
316  while (trylevel != last_level)
317  {
318  if (trylevel < 0 || trylevel >= descr->unwind_count)
319  {
320  ERR( "invalid trylevel %d\n", trylevel );
322  }
323  handler = descr->unwind_table[trylevel].handler;
324  if (handler)
325  {
326  TRACE( "calling unwind handler %p trylevel %d last %d ebp %p\n",
327  handler, trylevel, last_level, &frame->ebp );
328  call_handler( handler, &frame->ebp );
329  }
330  trylevel = descr->unwind_table[trylevel].prev;
331  }
332  frame->trylevel = last_level;
333 }
334 
335 /* exception frame for nested exceptions in catch block */
336 struct catch_func_nested_frame
337 {
338  EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */
339  cxx_exception_frame *cxx_frame; /* frame of parent exception */
340  const cxx_function_descr *descr; /* descriptor of parent exception */
341  int trylevel; /* current try level */
343 };
344 
345 /* handler for exceptions happening while calling a catch function */
346 static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
348 {
349  struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
350 
352  {
353  __CxxUnregisterExceptionObject(&nested_frame->frame_info, FALSE);
355  }
356 
357  TRACE( "got nested exception in catch function\n" );
358 
359  if(rec->ExceptionCode == CXX_EXCEPTION)
360  {
361  PEXCEPTION_RECORD prev_rec = msvcrt_get_thread_data()->exc_record;
362 
363  if((rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0) ||
364  (prev_rec->ExceptionCode == CXX_EXCEPTION &&
365  rec->ExceptionInformation[1] == prev_rec->ExceptionInformation[1] &&
366  rec->ExceptionInformation[2] == prev_rec->ExceptionInformation[2]))
367  {
368  /* exception was rethrown */
369  *rec = *prev_rec;
370  rec->ExceptionFlags &= ~EH_UNWINDING;
371  if(TRACE_ON(seh)) {
372  TRACE("detect rethrow: exception code: %x\n", rec->ExceptionCode);
373  if(rec->ExceptionCode == CXX_EXCEPTION)
374  TRACE("re-propagate: obj: %lx, type: %lx\n",
375  rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
376  }
377  }
378  else
379  {
380  TRACE("detect threw new exception in catch block\n");
381  }
382  }
383 
384  return cxx_frame_handler( rec, nested_frame->cxx_frame, context,
385  NULL, nested_frame->descr, &nested_frame->frame,
386  nested_frame->trylevel );
387 }
388 
389 /* find and call the appropriate catch block for an exception */
390 /* returns the address to continue execution to after the catch block was called */
391 static inline void call_catch_block( PEXCEPTION_RECORD rec, CONTEXT *context,
392  cxx_exception_frame *frame,
393  const cxx_function_descr *descr, int nested_trylevel,
394  EXCEPTION_REGISTRATION_RECORD *catch_frame,
396 {
397  UINT i;
398  int j;
399  void *addr, *object = (void *)rec->ExceptionInformation[1];
400  struct catch_func_nested_frame nested_frame;
401  int trylevel = frame->trylevel;
402  DWORD save_esp = ((DWORD*)frame)[-1];
404 
405  data->processing_throw++;
406  for (i = 0; i < descr->tryblock_count; i++)
407  {
408  const tryblock_info *tryblock = &descr->tryblock[i];
409 
410  /* only handle try blocks inside current catch block */
411  if (catch_frame && nested_trylevel > tryblock->start_level) continue;
412 
413  if (trylevel < tryblock->start_level) continue;
414  if (trylevel > tryblock->end_level) continue;
415 
416  /* got a try block */
417  for (j = 0; j < tryblock->catchblock_count; j++)
418  {
419  const catchblock_info *catchblock = &tryblock->catchblock[j];
420  if(info)
421  {
422  const cxx_type_info *type = find_caught_type( info,
423  catchblock->type_info, catchblock->flags );
424  if (!type) continue;
425 
426  TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j );
427 
428  /* copy the exception to its destination on the stack */
429  copy_exception( object, frame, catchblock, type );
430  }
431  else
432  {
433  /* no CXX_EXCEPTION only proceed with a catch(...) block*/
434  if(catchblock->type_info)
435  continue;
436  TRACE("found catch(...) block\n");
437  }
438 
439  /* Add frame info here so exception is not freed inside RtlUnwind call */
440  _CreateFrameInfo(&nested_frame.frame_info.frame_info,
441  (void*)rec->ExceptionInformation[1]);
442 
443  /* unwind the stack */
444  RtlUnwind( catch_frame ? catch_frame : &frame->frame, 0, rec, 0 );
445  cxx_local_unwind( frame, descr, tryblock->start_level );
446  frame->trylevel = tryblock->end_level + 1;
447 
448  nested_frame.frame_info.rec = data->exc_record;
449  nested_frame.frame_info.context = data->ctx_record;
450  data->exc_record = rec;
451  data->ctx_record = context;
452  data->processing_throw--;
453 
454  /* call the catch block */
455  TRACE( "calling catch block %p addr %p ebp %p\n",
456  catchblock, catchblock->handler, &frame->ebp );
457 
458  /* setup an exception block for nested exceptions */
459  nested_frame.frame.Handler = catch_function_nested_handler;
460  nested_frame.cxx_frame = frame;
461  nested_frame.descr = descr;
462  nested_frame.trylevel = nested_trylevel + 1;
463 
464  __wine_push_frame( &nested_frame.frame );
465  addr = call_handler( catchblock->handler, &frame->ebp );
466  __wine_pop_frame( &nested_frame.frame );
467 
468  ((DWORD*)frame)[-1] = save_esp;
469  __CxxUnregisterExceptionObject(&nested_frame.frame_info, FALSE);
470  TRACE( "done, continuing at %p\n", addr );
471 
472  continue_after_catch( frame, addr );
473  }
474  }
475  data->processing_throw--;
476 }
477 
478 /*********************************************************************
479  * __CxxExceptionFilter (MSVCRT.@)
480  */
481 int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
482  const type_info *ti, int flags, void **copy)
483 {
484  const cxx_type_info *type;
485  PEXCEPTION_RECORD rec;
486 
487  TRACE( "%p %p %x %p\n", ptrs, ti, flags, copy );
488 
489  if (!ptrs) return EXCEPTION_CONTINUE_SEARCH;
490 
491  /* handle catch(...) */
492  if (!ti) return EXCEPTION_EXECUTE_HANDLER;
493 
494  rec = ptrs->ExceptionRecord;
495  if (rec->ExceptionCode != CXX_EXCEPTION || rec->NumberParameters != 3 ||
499 
500  if (rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0)
501  {
502  rec = msvcrt_get_thread_data()->exc_record;
503  if (!rec) return EXCEPTION_CONTINUE_SEARCH;
504  }
505 
506  type = find_caught_type( (cxx_exception_type*)rec->ExceptionInformation[2], ti, flags );
507  if (!type) return EXCEPTION_CONTINUE_SEARCH;
508 
509  if (copy)
510  {
511  void *object = (void *)rec->ExceptionInformation[1];
512 
514  {
515  *copy = get_this_pointer( &type->offsets, object );
516  }
517  else if (type->flags & CLASS_IS_SIMPLE_TYPE)
518  {
519  memmove( copy, object, type->size );
520  /* if it is a pointer, adjust it */
521  if (type->size == sizeof(void*)) *copy = get_this_pointer( &type->offsets, *copy );
522  }
523  else /* copy the object */
524  {
525  if (type->copy_ctor)
526  call_copy_ctor( type->copy_ctor, copy, get_this_pointer(&type->offsets,object),
527  (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) );
528  else
529  memmove( copy, get_this_pointer(&type->offsets,object), type->size );
530  }
531  }
533 }
534 
535 static LONG CALLBACK se_translation_filter( EXCEPTION_POINTERS *ep, void *c )
536 {
537  se_translator_ctx *ctx = (se_translator_ctx *)c;
539  cxx_exception_type *exc_type;
540 
541  if (rec->ExceptionCode != CXX_EXCEPTION)
542  {
543  TRACE( "non-c++ exception thrown in SEH handler: %x\n", rec->ExceptionCode );
545  }
546 
547  exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
548  call_catch_block( rec, ep->ContextRecord, ctx->frame, ctx->descr,
549  ctx->frame->trylevel, ctx->nested_frame, exc_type );
550 
553 }
554 
555 /*********************************************************************
556  * cxx_frame_handler
557  *
558  * Implementation of __CxxFrameHandler.
559  */
560 DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
562  const cxx_function_descr *descr,
563  EXCEPTION_REGISTRATION_RECORD* nested_frame,
564  int nested_trylevel )
565 {
566  cxx_exception_type *exc_type;
567 
568  if (descr->magic < CXX_FRAME_MAGIC_VC6 || descr->magic > CXX_FRAME_MAGIC_VC8)
569  {
570  ERR( "invalid frame magic %x\n", descr->magic );
572  }
573  if (descr->magic >= CXX_FRAME_MAGIC_VC8 &&
574  (descr->flags & FUNC_DESCR_SYNCHRONOUS) &&
575  (rec->ExceptionCode != CXX_EXCEPTION))
576  return ExceptionContinueSearch; /* handle only c++ exceptions */
577 
579  {
580  if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 );
582  }
583  if (!descr->tryblock_count) return ExceptionContinueSearch;
584 
585  if(rec->ExceptionCode == CXX_EXCEPTION &&
586  rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0)
587  {
588  *rec = *msvcrt_get_thread_data()->exc_record;
589  rec->ExceptionFlags &= ~EH_UNWINDING;
590  if(TRACE_ON(seh)) {
591  TRACE("detect rethrow: exception code: %x\n", rec->ExceptionCode);
592  if(rec->ExceptionCode == CXX_EXCEPTION)
593  TRACE("re-propagate: obj: %lx, type: %lx\n",
594  rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
595  }
596  }
597 
598  if(rec->ExceptionCode == CXX_EXCEPTION)
599  {
600  exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
601 
603  exc_type->custom_handler)
604  {
605  return exc_type->custom_handler( rec, frame, context, dispatch,
606  descr, nested_trylevel, nested_frame, 0 );
607  }
608 
609  if (TRACE_ON(seh))
610  {
611  TRACE("handling C++ exception rec %p frame %p trylevel %d descr %p nested_frame %p\n",
612  rec, frame, frame->trylevel, descr, nested_frame );
613  dump_exception_type( exc_type );
614  dump_function_descr( descr );
615  }
616  }
617  else
618  {
620 
621  exc_type = NULL;
622  TRACE("handling C exception code %x rec %p frame %p trylevel %d descr %p nested_frame %p\n",
623  rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame );
624 
625  if (data->se_translator) {
626  EXCEPTION_POINTERS except_ptrs;
627  se_translator_ctx ctx;
628 
629  ctx.frame = frame;
630  ctx.descr = descr;
631  ctx.nested_frame = nested_frame;
632  __TRY
633  {
634  except_ptrs.ExceptionRecord = rec;
635  except_ptrs.ContextRecord = context;
636  data->se_translator( rec->ExceptionCode, &except_ptrs );
637  }
638  __EXCEPT_CTX(se_translation_filter, &ctx)
639  {
640  }
641  __ENDTRY
642  }
643  }
644 
645  call_catch_block( rec, context, frame, descr,
646  frame->trylevel, nested_frame, exc_type );
648 }
649 
650 
651 /*********************************************************************
652  * __CxxFrameHandler (MSVCRT.@)
653  */
654 extern DWORD CDECL __CxxFrameHandler(PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
656 #ifdef _MSC_VER
657 DWORD _declspec(naked) __CxxFrameHandler(PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
659 {
660  __asm
661  {
662  push 0
663  push 0
664  push eax
665  push[esp + 28]
666  push[esp + 28]
667  push[esp + 28]
668  push[esp + 28]
669  call cxx_frame_handler
670  add esp, 28
671  ret
672  }
673 }
674 #else
675 __ASM_GLOBAL_FUNC(__CxxFrameHandler,
676  "pushl $0\n\t" /* nested_trylevel */
677  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
678  "pushl $0\n\t" /* nested_frame */
679  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
680  "pushl %eax\n\t" /* descr */
681  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
682  "pushl 28(%esp)\n\t" /* dispatch */
683  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
684  "pushl 28(%esp)\n\t" /* context */
685  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
686  "pushl 28(%esp)\n\t" /* frame */
687  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
688  "pushl 28(%esp)\n\t" /* rec */
689  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
690  "call " __ASM_NAME("cxx_frame_handler") "\n\t"
691  "add $28,%esp\n\t"
692  __ASM_CFI(".cfi_adjust_cfa_offset -28\n\t")
693  "ret")
694 #endif
695 
696 
697 /*********************************************************************
698  * __CxxLongjmpUnwind (MSVCRT.@)
699  *
700  * Callback meant to be used as UnwindFunc for setjmp/longjmp.
701  */
702 void __stdcall __CxxLongjmpUnwind( const struct MSVCRT___JUMP_BUFFER *buf )
703 {
704  cxx_exception_frame *frame = (cxx_exception_frame *)buf->Registration;
705  const cxx_function_descr *descr = (const cxx_function_descr *)buf->UnwindData[0];
706 
707  TRACE( "unwinding frame %p descr %p trylevel %ld\n", frame, descr, buf->TryLevel );
708  cxx_local_unwind( frame, descr, buf->TryLevel );
709 }
710 
711 /*********************************************************************
712  * __CppXcptFilter (MSVCRT.@)
713  */
715 {
716  /* only filter c++ exceptions */
718  return _XcptFilter( ex, ptr );
719 }
720 
721 /*********************************************************************
722  * __CxxDetectRethrow (MSVCRT.@)
723  */
724 BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
725 {
726  PEXCEPTION_RECORD rec;
727 
728  if (!ptrs)
729  return FALSE;
730 
731  rec = ptrs->ExceptionRecord;
732 
733  if (rec->ExceptionCode == CXX_EXCEPTION &&
734  rec->NumberParameters == 3 &&
736  rec->ExceptionInformation[2])
737  {
738  ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record;
739  return TRUE;
740  }
741  return (msvcrt_get_thread_data()->exc_record == rec);
742 }
743 
744 /*********************************************************************
745  * __CxxQueryExceptionSize (MSVCRT.@)
746  */
747 unsigned int CDECL __CxxQueryExceptionSize(void)
748 {
749  return sizeof(cxx_exception_type);
750 }
751 
752 
753 /*********************************************************************
754  * _EH_prolog (MSVCRT.@)
755  */
756 
757 /* Provided for VC++ binary compatibility only */
758 __ASM_GLOBAL_FUNC(_EH_prolog,
759  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") /* skip ret addr */
760  "pushl $-1\n\t"
761  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
762  "pushl %eax\n\t"
763  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
764  "pushl %fs:0\n\t"
765  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
766  "movl %esp, %fs:0\n\t"
767  "movl 12(%esp), %eax\n\t"
768  "movl %ebp, 12(%esp)\n\t"
769  "leal 12(%esp), %ebp\n\t"
770  "pushl %eax\n\t"
771  __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
772  "ret")
773 
774 static const SCOPETABLE_V4 *get_scopetable_v4( MSVCRT_EXCEPTION_FRAME *frame, ULONG_PTR cookie )
775 {
776  return (const SCOPETABLE_V4 *)((ULONG_PTR)frame->scopetable ^ cookie);
777 }
778 
779 static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
783 {
784  if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
786  *dispatch = frame;
788 }
789 
790 static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp)
791 {
793 
794  TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel);
795 
796  /* Register a handler in case of a nested exception */
797  reg.Handler = MSVCRT_nested_handler;
798  reg.Prev = NtCurrentTeb()->Tib.ExceptionList;
800 
801  while (frame->trylevel != TRYLEVEL_END && frame->trylevel != trylevel)
802  {
803  int level = frame->trylevel;
804  frame->trylevel = frame->scopetable[level].previousTryLevel;
805  if (!frame->scopetable[level].lpfnFilter)
806  {
807  TRACE( "__try block cleanup level %d handler %p ebp %p\n",
808  level, frame->scopetable[level].lpfnHandler, ebp );
809  call_handler( frame->scopetable[level].lpfnHandler, ebp );
810  }
811  }
813  TRACE("unwound OK\n");
814 }
815 
816 static void msvcrt_local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp )
817 {
819  const SCOPETABLE_V4 *scopetable = get_scopetable_v4( frame, *cookie );
820 
821  TRACE("(%p,%d,%d)\n",frame, frame->trylevel, trylevel);
822 
823  /* Register a handler in case of a nested exception */
824  reg.Handler = MSVCRT_nested_handler;
825  reg.Prev = NtCurrentTeb()->Tib.ExceptionList;
827 
828  while (frame->trylevel != -2 && frame->trylevel != trylevel)
829  {
830  int level = frame->trylevel;
831  frame->trylevel = scopetable->entries[level].previousTryLevel;
832  if (!scopetable->entries[level].lpfnFilter)
833  {
834  TRACE( "__try block cleanup level %d handler %p ebp %p\n",
835  level, scopetable->entries[level].lpfnHandler, ebp );
836  call_handler( scopetable->entries[level].lpfnHandler, ebp );
837  }
838  }
840  TRACE("unwound OK\n");
841 }
842 #ifndef __REACTOS__
843 /*******************************************************************
844  * _local_unwind2 (MSVCRT.@)
845  */
846 void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
847 {
848  msvcrt_local_unwind2( frame, trylevel, &frame->_ebp );
849 }
850 #endif
851 /*******************************************************************
852  * _local_unwind4 (MSVCRT.@)
853  */
854 void CDECL _local_unwind4( ULONG *cookie, MSVCRT_EXCEPTION_FRAME* frame, int trylevel )
855 {
856  msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
857 }
858 
859 #ifndef __REACTOS__
860 /*******************************************************************
861  * _global_unwind2 (MSVCRT.@)
862  */
863 void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame)
864 {
865  TRACE("(%p)\n",frame);
866  RtlUnwind( frame, 0, 0, 0 );
867 }
868 #else
869 void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame);
870 #endif
871 
872 #ifndef __REACTOS__
873 /*********************************************************************
874  * _except_handler2 (MSVCRT.@)
875  */
876 int CDECL _except_handler2(PEXCEPTION_RECORD rec,
879  EXCEPTION_REGISTRATION_RECORD** dispatcher)
880 {
881  FIXME("exception %x flags=%x at %p handler=%p %p %p stub\n",
883  frame->Handler, context, dispatcher);
885 }
886 
887 /*********************************************************************
888  * _except_handler3 (MSVCRT.@)
889  */
890 int CDECL _except_handler3(PEXCEPTION_RECORD rec,
891  MSVCRT_EXCEPTION_FRAME* frame,
892  PCONTEXT context, void* dispatcher)
893 {
894  int retval, trylevel;
895  EXCEPTION_POINTERS exceptPtrs;
896  PSCOPETABLE pScopeTable;
897 
898  TRACE("exception %x flags=%x at %p handler=%p %p %p semi-stub\n",
900  frame->handler, context, dispatcher);
901 
902 #ifdef _MSC_VER
903  __asm{ cld }
904 #else
905  __asm__ __volatile__("cld");
906 #endif
908  {
909  /* Unwinding the current frame */
910  msvcrt_local_unwind2(frame, TRYLEVEL_END, &frame->_ebp);
911  TRACE("unwound current frame, returning ExceptionContinueSearch\n");
913  }
914  else
915  {
916  /* Hunting for handler */
917  exceptPtrs.ExceptionRecord = rec;
918  exceptPtrs.ContextRecord = context;
919  *((DWORD *)frame-1) = (DWORD)&exceptPtrs;
920  trylevel = frame->trylevel;
921  pScopeTable = frame->scopetable;
922 
923  while (trylevel != TRYLEVEL_END)
924  {
925  TRACE( "level %d prev %d filter %p\n", trylevel, pScopeTable[trylevel].previousTryLevel,
926  pScopeTable[trylevel].lpfnFilter );
927  if (pScopeTable[trylevel].lpfnFilter)
928  {
929  retval = call_filter( pScopeTable[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp );
930 
931  TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
932  "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
933  "EXECUTE_HANDLER" : "CONTINUE_SEARCH");
934 
935  if (retval == EXCEPTION_CONTINUE_EXECUTION)
937 
938  if (retval == EXCEPTION_EXECUTE_HANDLER)
939  {
940  /* Unwind all higher frames, this one will handle the exception */
941  _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
942  msvcrt_local_unwind2(frame, trylevel, &frame->_ebp);
943 
944  /* Set our trylevel to the enclosing block, and call the __finally
945  * code, which won't return
946  */
947  frame->trylevel = pScopeTable[trylevel].previousTryLevel;
948  TRACE("__finally block %p\n",pScopeTable[trylevel].lpfnHandler);
949  call_finally_block(pScopeTable[trylevel].lpfnHandler, &frame->_ebp);
950  }
951  }
952  trylevel = pScopeTable[trylevel].previousTryLevel;
953  }
954  }
955  TRACE("reached TRYLEVEL_END, returning ExceptionContinueSearch\n");
957 }
958 #endif /* __REACTOS__ */
959 /*********************************************************************
960  * _except_handler4_common (MSVCRT.@)
961  */
962 int CDECL _except_handler4_common( ULONG *cookie, void (*check_cookie)(void),
963  EXCEPTION_RECORD *rec, MSVCRT_EXCEPTION_FRAME *frame,
965 {
966  int retval, trylevel;
967  EXCEPTION_POINTERS exceptPtrs;
968  const SCOPETABLE_V4 *scope_table = get_scopetable_v4( frame, *cookie );
969 
970  TRACE( "exception %x flags=%x at %p handler=%p %p %p cookie=%x scope table=%p cookies=%d/%x,%d/%x\n",
972  frame->handler, context, dispatcher, *cookie, scope_table,
973  scope_table->gs_cookie_offset, scope_table->gs_cookie_xor,
974  scope_table->eh_cookie_offset, scope_table->eh_cookie_xor );
975 
976  /* FIXME: no cookie validation yet */
977 
979  {
980  /* Unwinding the current frame */
981  msvcrt_local_unwind4( cookie, frame, -2, &frame->_ebp );
982  TRACE("unwound current frame, returning ExceptionContinueSearch\n");
984  }
985  else
986  {
987  /* Hunting for handler */
988  exceptPtrs.ExceptionRecord = rec;
989  exceptPtrs.ContextRecord = context;
990  *((DWORD *)frame-1) = (DWORD)&exceptPtrs;
991  trylevel = frame->trylevel;
992 
993  while (trylevel != -2)
994  {
995  TRACE( "level %d prev %d filter %p\n", trylevel,
996  scope_table->entries[trylevel].previousTryLevel,
997  scope_table->entries[trylevel].lpfnFilter );
998  if (scope_table->entries[trylevel].lpfnFilter)
999  {
1000  retval = call_filter( scope_table->entries[trylevel].lpfnFilter, &exceptPtrs, &frame->_ebp );
1001 
1002  TRACE("filter returned %s\n", retval == EXCEPTION_CONTINUE_EXECUTION ?
1003  "CONTINUE_EXECUTION" : retval == EXCEPTION_EXECUTE_HANDLER ?
1004  "EXECUTE_HANDLER" : "CONTINUE_SEARCH");
1005 
1006  if (retval == EXCEPTION_CONTINUE_EXECUTION)
1008 
1009  if (retval == EXCEPTION_EXECUTE_HANDLER)
1010  {
1012 
1013  /* Unwind all higher frames, this one will handle the exception */
1014  _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
1015  msvcrt_local_unwind4( cookie, frame, trylevel, &frame->_ebp );
1016 
1017  /* Set our trylevel to the enclosing block, and call the __finally
1018  * code, which won't return
1019  */
1020  frame->trylevel = scope_table->entries[trylevel].previousTryLevel;
1021  TRACE("__finally block %p\n",scope_table->entries[trylevel].lpfnHandler);
1022  call_finally_block(scope_table->entries[trylevel].lpfnHandler, &frame->_ebp);
1023  }
1024  }
1025  trylevel = scope_table->entries[trylevel].previousTryLevel;
1026  }
1027  }
1028  TRACE("reached -2, returning ExceptionContinueSearch\n");
1029  return ExceptionContinueSearch;
1030 }
1031 
1032 
1033 /*
1034  * setjmp/longjmp implementation
1035  */
1036 
1037 #define MSVCRT_JMP_MAGIC 0x56433230 /* ID value for new jump structure */
1038 typedef void (__stdcall *MSVCRT_unwind_function)(const struct MSVCRT___JUMP_BUFFER *);
1039 
1040 /* define an entrypoint for setjmp/setjmp3 that stores the registers in the jmp buf */
1041 /* and then jumps to the C backend function */
1042 #define DEFINE_SETJMP_ENTRYPOINT(name) \
1043  __ASM_GLOBAL_FUNC( name, \
1044  "movl 4(%esp),%ecx\n\t" /* jmp_buf */ \
1045  "movl %ebp,0(%ecx)\n\t" /* jmp_buf.Ebp */ \
1046  "movl %ebx,4(%ecx)\n\t" /* jmp_buf.Ebx */ \
1047  "movl %edi,8(%ecx)\n\t" /* jmp_buf.Edi */ \
1048  "movl %esi,12(%ecx)\n\t" /* jmp_buf.Esi */ \
1049  "movl %esp,16(%ecx)\n\t" /* jmp_buf.Esp */ \
1050  "movl 0(%esp),%eax\n\t" \
1051  "movl %eax,20(%ecx)\n\t" /* jmp_buf.Eip */ \
1052  "jmp " __ASM_NAME("__regs_") # name )
1053 
1054 /*******************************************************************
1055  * _setjmp (MSVCRT.@)
1056  */
1057 DEFINE_SETJMP_ENTRYPOINT(MSVCRT__setjmp)
1058 int CDECL DECLSPEC_HIDDEN __regs_MSVCRT__setjmp(struct MSVCRT___JUMP_BUFFER *jmp)
1059 {
1060  jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList;
1061  if (jmp->Registration == ~0UL)
1062  jmp->TryLevel = TRYLEVEL_END;
1063  else
1064  jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
1065 
1066  TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx\n",
1067  jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration );
1068  return 0;
1069 }
1070 
1071 /*******************************************************************
1072  * _setjmp3 (MSVCRT.@)
1073  */
1074 DEFINE_SETJMP_ENTRYPOINT( MSVCRT__setjmp3 )
1075 int WINAPIV DECLSPEC_HIDDEN __regs_MSVCRT__setjmp3(struct MSVCRT___JUMP_BUFFER *jmp, int nb_args, ...)
1076 {
1077  jmp->Cookie = MSVCRT_JMP_MAGIC;
1078  jmp->UnwindFunc = 0;
1079  jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList;
1080  if (jmp->Registration == ~0UL)
1081  {
1082  jmp->TryLevel = TRYLEVEL_END;
1083  }
1084  else
1085  {
1086  int i;
1087  va_list args;
1088 
1089  va_start( args, nb_args );
1090  if (nb_args > 0) jmp->UnwindFunc = va_arg( args, unsigned long );
1091  if (nb_args > 1) jmp->TryLevel = va_arg( args, unsigned long );
1092  else jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
1093  for (i = 0; i < 6 && i < nb_args - 2; i++)
1094  jmp->UnwindData[i] = va_arg( args, unsigned long );
1095  va_end( args );
1096  }
1097 
1098  TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx\n",
1099  jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration );
1100  return 0;
1101 }
1102 
1103 /*********************************************************************
1104  * longjmp (MSVCRT.@)
1105  */
1106 void CDECL MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval)
1107 {
1108  unsigned long cur_frame = 0;
1109 
1110  TRACE("buf=%p ebx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx eip=%08lx frame=%08lx retval=%08x\n",
1111  jmp, jmp->Ebx, jmp->Esi, jmp->Edi, jmp->Ebp, jmp->Esp, jmp->Eip, jmp->Registration, retval );
1112 
1113  cur_frame=(unsigned long)NtCurrentTeb()->Tib.ExceptionList;
1114  TRACE("cur_frame=%lx\n",cur_frame);
1115 
1116  if (cur_frame != jmp->Registration)
1117  _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)jmp->Registration);
1118 
1119  if (jmp->Registration)
1120  {
1121  if (IsBadReadPtr(&jmp->Cookie, sizeof(long)) || jmp->Cookie != MSVCRT_JMP_MAGIC)
1122  {
1123  msvcrt_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration,
1124  jmp->TryLevel, (void *)jmp->Ebp);
1125  }
1126  else if(jmp->UnwindFunc)
1127  {
1128  MSVCRT_unwind_function unwind_func;
1129 
1130  unwind_func=(MSVCRT_unwind_function)jmp->UnwindFunc;
1131  unwind_func(jmp);
1132  }
1133  }
1134 
1135  if (!retval)
1136  retval = 1;
1137 
1138  __wine_longjmp( (__wine_jmp_buf *)jmp, retval );
1139 }
1140 
1141 /*********************************************************************
1142  * _seh_longjmp_unwind (MSVCRT.@)
1143  */
1144 void __stdcall _seh_longjmp_unwind(struct MSVCRT___JUMP_BUFFER *jmp)
1145 {
1146  msvcrt_local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel, (void *)jmp->Ebp );
1147 }
1148 
1149 /*********************************************************************
1150  * _seh_longjmp_unwind4 (MSVCRT.@)
1151  */
1152 void __stdcall _seh_longjmp_unwind4(struct MSVCRT___JUMP_BUFFER *jmp)
1153 {
1154  msvcrt_local_unwind4( (ULONG *)&jmp->Cookie, (MSVCRT_EXCEPTION_FRAME *)jmp->Registration,
1155  jmp->TryLevel, (void *)jmp->Ebp );
1156 }
1157 
1158 /*********************************************************************
1159  * _fpieee_flt (MSVCRT.@)
1160  */
1161 int __cdecl _fpieee_flt(ULONG exception_code, EXCEPTION_POINTERS *ep,
1162  int (__cdecl *handler)(_FPIEEE_RECORD*))
1163 {
1165  _FPIEEE_RECORD rec;
1166  int ret;
1167 
1168  TRACE("(%x %p %p)\n", exception_code, ep, handler);
1169 
1170  switch(exception_code) {
1174  case STATUS_FLOAT_OVERFLOW:
1176  break;
1177  default:
1179  }
1180 
1181  memset(&rec, 0, sizeof(rec));
1182  rec.RoundingMode = ctx->ControlWord >> 10;
1183  switch((ctx->ControlWord >> 8) & 0x3) {
1184  case 0: rec.Precision = 2; break;
1185  case 1: rec.Precision = 3; break;
1186  case 2: rec.Precision = 1; break;
1187  case 3: rec.Precision = 0; break;
1188  }
1189  rec.Status.InvalidOperation = ctx->StatusWord & 0x1;
1190  rec.Status.ZeroDivide = ((ctx->StatusWord & 0x4) != 0);
1191  rec.Status.Overflow = ((ctx->StatusWord & 0x8) != 0);
1192  rec.Status.Underflow = ((ctx->StatusWord & 0x10) != 0);
1193  rec.Status.Inexact = ((ctx->StatusWord & 0x20) != 0);
1194  rec.Enable.InvalidOperation = ((ctx->ControlWord & 0x1) == 0);
1195  rec.Enable.ZeroDivide = ((ctx->ControlWord & 0x4) == 0);
1196  rec.Enable.Overflow = ((ctx->ControlWord & 0x8) == 0);
1197  rec.Enable.Underflow = ((ctx->ControlWord & 0x10) == 0);
1198  rec.Enable.Inexact = ((ctx->ControlWord & 0x20) == 0);
1201  rec.Cause.Overflow = rec.Enable.Overflow & rec.Status.Overflow;
1202  rec.Cause.Underflow = rec.Enable.Underflow & rec.Status.Underflow;
1203  rec.Cause.Inexact = rec.Enable.Inexact & rec.Status.Inexact;
1204 
1205  TRACE("opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset);
1206 
1207  if(*(WORD*)ctx->ErrorOffset == 0x35dc) { /* fdiv m64fp */
1208  if(exception_code==STATUS_FLOAT_DIVIDE_BY_ZERO || exception_code==STATUS_FLOAT_INVALID_OPERATION) {
1209  rec.Operand1.OperandValid = 1;
1210  rec.Result.OperandValid = 0;
1211  } else {
1212  rec.Operand1.OperandValid = 0;
1213  rec.Result.OperandValid = 1;
1214  }
1215  rec.Operand2.OperandValid = 1;
1216  rec.Operation = _FpCodeDivide;
1218  memcpy(&rec.Operand1.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value));
1220  rec.Operand2.Value.Fp64Value = *(double*)ctx->DataOffset;
1221  rec.Result.Format = _FpFormatFp80;
1222  memcpy(&rec.Result.Value.Fp80Value, ctx->RegisterArea, sizeof(rec.Operand1.Value.Fp80Value));
1223 
1224  ret = handler(&rec);
1225 
1227  memcpy(ctx->RegisterArea, &rec.Result.Value.Fp80Value, sizeof(rec.Operand1.Value.Fp80Value));
1228  return ret;
1229  }
1230 
1231  FIXME("unsupported opcode: %x\n", *(ULONG*)ep->ContextRecord->FloatSave.ErrorOffset);
1233 }
1234 
1235 #endif /* __i386__ */
struct _EXCEPTION_RECORD * PEXCEPTION_RECORD
GLenum func
Definition: glext.h:6028
GLint level
Definition: gl.h:1546
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
_CRTIMP int __cdecl _fpieee_flt(unsigned long _ExceptionCode, struct _EXCEPTION_POINTERS *_PtExceptionPtr, int(__cdecl *_Handler)(_FPIEEE_RECORD *))
Definition: comerr.c:44
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
union _FPIEEE_VALUE::@1831 Value
#define args
Definition: format.c:66
#define __cdecl
Definition: accygwin.h:79
#define CXX_FRAME_MAGIC_VC6
Definition: cppexcept.h:24
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx eax jnz xchgl ecx incl TEMP esp ecx subl ebx pushl ecx ecx edx ecx ecx mm0 mm4 mm0 mm4 mm1 mm5 mm1 mm5 mm2 mm6 mm2 mm6 mm3 mm7 mm3 mm7 paddd mm0 paddd mm4 paddd mm0 paddd mm4 paddd mm0 paddd mm4 movq mm1 movq mm5 mm1 mm5 paddd mm0 paddd mm4 mm0 mm4 packssdw mm0 packssdw mm4 mm1 punpckldq mm0 pand mm1 pand mm0 por mm1 movq edi esi edx edi decl ecx jnz popl ecx ecx jecxz mm0 mm0 mm1 mm1 mm2 mm2 mm3 mm3 paddd mm0 paddd mm0 paddd mm0 movq mm1 mm1 paddd mm0 mm0 packssdw mm0 movd eax movw edi esi edx esi ecx mm0 mm4 mm0 mm4 mm1 mm5 mm1 mm5 mm2 mm6 mm2 mm6 mm3 mm7 mm3 mm7 paddd mm0 paddd mm4 paddd mm0 paddd mm4 paddd mm0 paddd mm4 movq mm1 movq mm5 mm1 mm5 paddd mm1 paddd mm5 mm1 mm5 packssdw mm1 packssdw mm5 psubd mm0 psubd mm4 psubsw mm0 psubsw mm4 mm1 punpckldq mm0 pand mm1 pand mm0 por mm1 movq edi esi edx edi decl ecx jnz mm0 mm0 mm1 mm1 mm2 mm2 mm3 mm3 paddd mm0 paddd mm0 paddd mm0 movq mm1 mm1 paddd mm1 mm1 packssdw mm1 psubd mm0 psubsw mm0 movd eax movw edi emms popl ebx popl esi popl edi mov ebp
Definition: synth_sse3d.h:248
_FP80 Fp80Value
Definition: fpieee.h:90
FLOATING_SAVE_AREA FloatSave
Definition: nt_native.h:1446
Definition: http.c:7251
#define TYPE_FLAG_VOLATILE
Definition: cppexcept.h:72
#define TRUE
Definition: types.h:120
struct __cxx_function_descr cxx_function_descr
LONG NTSTATUS
Definition: precomp.h:26
#define CALLBACK
Definition: compat.h:35
#define TYPE_FLAG_REFERENCE
Definition: cppexcept.h:73
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
unsigned int OperandValid
Definition: fpieee.h:104
unsigned int Format
Definition: fpieee.h:105
const unwind_info * unwind_table
Definition: cppexcept.h:97
NTSYSAPI VOID NTAPI RtlUnwind(_In_opt_ PVOID TargetFrame, _In_opt_ PVOID TargetIp, _In_opt_ PEXCEPTION_RECORD ExceptionRecord, _In_ PVOID ReturnValue)
Definition: except.c:47
_FPIEEE_EXCEPTION_FLAGS Cause
Definition: fpieee.h:120
int catchblock_count
Definition: cppexcept.h:81
#define __EXCEPT_CTX(func, ctx)
Definition: exception.h:85
__asm__("\n\t \ NewInt3Handler:\n\t \ pushl $" STR(REASON_INT3) "\n\t \ // call debugger loop\n\t \ jmp NewInt31Handler\n\t \ ")
#define STATUS_FLOAT_DIVIDE_BY_ZERO
Definition: ntstatus.h:378
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define STATUS_FLOAT_INEXACT_RESULT
Definition: ntstatus.h:379
Definition: match.c:390
#define DWORD
Definition: nt_native.h:44
const catchblock_info * catchblock
Definition: cppexcept.h:82
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
PEXCEPTION_ROUTINE Handler
Definition: compat.h:586
PVOID ExceptionAddress
Definition: compat.h:211
unsigned int ZeroDivide
Definition: fpieee.h:112
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define EXCEPTION_CONTINUE_EXECUTION
Definition: excpt.h:87
char mangled[16]
Definition: cpp.c:36
#define STATUS_FLOAT_UNDERFLOW
Definition: ntstatus.h:383
#define __ASM_GLOBAL_FUNC(name, code)
Definition: port.h:201
DWORD ExceptionCode
Definition: compat.h:208
struct _EXCEPTION_POINTERS * PEXCEPTION_POINTERS
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define CXX_FRAME_MAGIC_VC8
Definition: cppexcept.h:26
struct __tryblock_info tryblock_info
void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec)
Definition: except.c:405
_FPIEEE_VALUE Operand2
Definition: fpieee.h:124
#define CLASS_IS_SIMPLE_TYPE
Definition: cppexcept.h:127
#define STATUS_FLOAT_OVERFLOW
Definition: ntstatus.h:381
#define va_end(ap)
Definition: acmsvcex.h:90
static void * get_this_pointer(const this_ptr_offsets *off, void *object)
Definition: cppexcept.h:163
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define TYPE_FLAG_CONST
Definition: cppexcept.h:71
#define __ASM_NAME(name)
Definition: config.h:934
#define FIXME(fmt,...)
Definition: debug.h:111
_FPIEEE_VALUE Result
Definition: fpieee.h:125
static PVOID ptr
Definition: dispmode.c:27
_FPIEEE_EXCEPTION_FLAGS Status
Definition: fpieee.h:122
unsigned int InvalidOperation
Definition: fpieee.h:113
struct _frame_info frame_info
static EXCEPTION_REGISTRATION_RECORD * __wine_push_frame(EXCEPTION_REGISTRATION_RECORD *frame)
Definition: exception.h:104
cxx_exc_custom_handler custom_handler
Definition: cppexcept.h:147
char * va_list
Definition: acmsvcex.h:78
frame_info *CDECL _CreateFrameInfo(frame_info *fi, void *obj)
Definition: except.c:344
#define __TRY
Definition: compat.h:80
#define __ASM_CFI(str)
Definition: asm.h:39
int CDECL __CppXcptFilter(NTSTATUS, PEXCEPTION_POINTERS)
const void * expect_list
Definition: cppexcept.h:102
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
EXCEPTION_REGISTRATION_RECORD frame
Definition: cppexcept.h:58
PCONTEXT ContextRecord
Definition: rtltypes.h:201
#define EH_UNWINDING
Definition: exception.h:17
#define CXX_EXCEPTION
Definition: cppexcept.h:27
#define TRACE(s)
Definition: solgame.cpp:4
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
Definition: compat.h:213
#define FUNC_DESCR_SYNCHRONOUS
Definition: cppexcept.h:106
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl eax
Definition: synth_sse3d.h:85
unsigned int Inexact
Definition: fpieee.h:109
struct __catchblock_info catchblock_info
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define CXX_FRAME_MAGIC_VC7
Definition: cppexcept.h:25
void(* handler)(void)
Definition: cppexcept.h:69
const GLubyte * c
Definition: glext.h:8905
const char * descr
Definition: boot.c:45
_FP64 Fp64Value
Definition: fpieee.h:89
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
const type_info * type_info
Definition: cppexcept.h:67
va_start(ap, x)
#define __stdcall
Definition: typedefs.h:25
static int reg
Definition: i386-dis.c:1283
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
GLbitfield flags
Definition: glext.h:7161
#define __ENDTRY
Definition: compat.h:82
int ret
struct __cxx_exception_frame cxx_exception_frame
GLenum const GLvoid * addr
Definition: glext.h:9621
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum src
Definition: glext.h:6340
struct __unwind_info unwind_info
unsigned int Precision
Definition: fpieee.h:118
unsigned int Underflow
Definition: fpieee.h:110
thread_data_t * msvcrt_get_thread_data(void)
Definition: tls.c:31
void dispatch(HANDLE hStopEvent)
Definition: dispatch.c:70
struct __cxx_exception_type cxx_exception_type
#define WINAPIV
Definition: sdbpapi.h:64
#define EH_EXIT_UNWIND
Definition: exception.h:18
#define ERR(fmt,...)
Definition: debug.h:110
#define va_arg(ap, T)
Definition: acmsvcex.h:89
static const char * dbgstr_type_info(const type_info *info)
Definition: cppexcept.h:155
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define CDECL
Definition: compat.h:29
unsigned int Operation
Definition: fpieee.h:119
const cxx_type_info_table * type_info_table
Definition: cppexcept.h:148
#define long
Definition: qsort.c:33
#define CLASS_HAS_VIRTUAL_BASE_CLASS
Definition: cppexcept.h:128
const void * ipmap
Definition: cppexcept.h:101
Definition: cookie.c:33
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:803
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
unsigned int RoundingMode
Definition: fpieee.h:117
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
static void dump_type(type_t *t)
Definition: write_msft.c:1037
unsigned int Overflow
Definition: fpieee.h:111
_FPIEEE_VALUE Operand1
Definition: fpieee.h:123
unsigned int ULONG
Definition: retypes.h:1
#define const
Definition: zconf.h:230
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ULONG_PTR
Definition: config.h:101
DWORD ExceptionFlags
Definition: compat.h:209
PEXCEPTION_RECORD ExceptionRecord
Definition: rtltypes.h:200
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7786
#define STATUS_FLOAT_INVALID_OPERATION
Definition: ntstatus.h:380
DWORD NumberParameters
Definition: compat.h:212
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE_ON(x)
Definition: compat.h:75
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void CDECL __CxxUnregisterExceptionObject(cxx_frame_info *frame_info, BOOL in_use)
Definition: except.c:464
#define UL
Definition: tui.h:82
CONTEXT * PCONTEXT
Definition: compat.h:558
void __cdecl MSVCRT_terminate(void)
Definition: cpp.c:1277
static EXCEPTION_REGISTRATION_RECORD * __wine_pop_frame(EXCEPTION_REGISTRATION_RECORD *frame)
Definition: exception.h:118
int CDECL _XcptFilter(NTSTATUS, PEXCEPTION_POINTERS)
Definition: except.c:274
const tryblock_info * tryblock
Definition: cppexcept.h:99
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
_FPIEEE_EXCEPTION_FLAGS Enable
Definition: fpieee.h:121
const cxx_type_info * info[3]
Definition: cppexcept.h:134