0022545: Improved exception handling
[occt.git] / src / OSD / OSD_signal_WNT.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18
19 #include <OSD.ixx>
20
21 #ifdef WNT
22
23 //---------------------------- Windows NT System --------------------------------
24
25 #define STRICT
26 #ifdef NOUSER
27 #undef NOUSER
28 #endif
29 #include <windows.h>
30
31 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
32 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
33 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
34 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
35 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
36 #include <OSD_Exception_INT_OVERFLOW.hxx>
37 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
38 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
39 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
40 #include <OSD_Exception_STACK_OVERFLOW.hxx>
41 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
42 #include <OSD_Exception_CTRL_BREAK.hxx>
43
44 #include <OSD_Environment.hxx>
45 #include <Standard_Underflow.hxx>
46 #include <Standard_DivideByZero.hxx>
47 #include <Standard_Overflow.hxx>
48 #include <Standard_ProgramError.hxx>
49 #include <Standard_Mutex.hxx>
50
51 #include <OSD_WNT_1.hxx>
52
53 #ifdef _MSC_VER
54 #include <eh.h>
55 #include <malloc.h>
56 #endif
57
58 #include <process.h>
59 #include <signal.h>
60 #include <float.h>
61
62 static Standard_Boolean fMsgBox;
63 static Standard_Boolean fFltExceptions;
64 static Standard_Boolean fDbgLoaded;
65 static Standard_Boolean fCtrlBrk;
66
67 // used to forbid simultaneous execution of setting / executing handlers
68 static Standard_Mutex THE_SIGNAL_MUTEX;
69
70 static LONG __fastcall _osd_raise ( DWORD, LPTSTR );
71 static BOOL WINAPI     _osd_ctrl_break_handler ( DWORD );
72
73 extern "C" Standard_EXPORT LONG _osd_debug   ( void );
74
75 MB_DESC fatalErrorDesc[] = {
76
77                  { MBT_ICON,   ( int )IDI_HAND              },
78                  { MBT_BUTTON, IDYES,    TEXT( "Continue" ) },
79                  { MBT_BUTTON, IDNO,     TEXT( "Debugger" ) },
80                  { MBT_BUTTON, IDCANCEL, TEXT( "Stop"     ) }
81
82 };
83
84 //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
85 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
86
87 //=======================================================================
88 //function : CallHandler
89 //purpose  :
90 //=======================================================================
91 static LONG CallHandler (DWORD dwExceptionCode,
92                          ptrdiff_t ExceptionInformation1,
93                          ptrdiff_t ExceptionInformation0)
94 {
95
96 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
97
98  Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
99  static TCHAR         buffer[ 2048 ];
100  int                  flterr = 0;
101
102  buffer[0] = '\0' ;
103
104 // cout << "CallHandler " << dwExceptionCode << endl ;
105  switch ( dwExceptionCode ) {
106  
107   case EXCEPTION_FLT_DENORMAL_OPERAND:
108 //      cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << endl ;
109       lstrcpy (  buffer, TEXT( "FLT DENORMAL OPERAND" )  );
110       flterr = 1 ;
111       break ;
112   case EXCEPTION_FLT_DIVIDE_BY_ZERO:
113 //      cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << endl ;
114       lstrcpy (  buffer, TEXT( "FLT DIVIDE BY ZERO" )  );
115       flterr = 1 ;
116       break ;
117   case EXCEPTION_FLT_INEXACT_RESULT:
118 //      cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << endl ;
119       lstrcpy (  buffer, TEXT( "FLT INEXACT RESULT" )  );
120       flterr = 1 ;
121       break ;
122   case EXCEPTION_FLT_INVALID_OPERATION:
123 //      cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << endl ;
124       lstrcpy (  buffer, TEXT( "FLT INVALID OPERATION" )  );
125       flterr = 1 ;
126       break ;
127   case EXCEPTION_FLT_OVERFLOW:
128 //      cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << endl ;
129       lstrcpy (  buffer, TEXT( "FLT OVERFLOW" )  );
130       flterr = 1 ;
131       break ;
132   case EXCEPTION_FLT_STACK_CHECK:
133 //      cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << endl ;
134       lstrcpy (  buffer, TEXT( "FLT STACK CHECK" )  );
135       flterr = 1 ;
136       break ;
137   case EXCEPTION_FLT_UNDERFLOW:
138 //      cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
139       lstrcpy (  buffer, TEXT( "FLT UNDERFLOW" )  );
140       flterr = 1 ;
141       break ;
142   case STATUS_FLOAT_MULTIPLE_TRAPS:
143 //      cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
144       lstrcpy (  buffer, TEXT( "FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)" )  );
145       flterr = 1 ;
146       break ;
147   case STATUS_FLOAT_MULTIPLE_FAULTS:
148 //      cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
149       lstrcpy (  buffer, TEXT( "FLT MULTIPLE FAULTS" )  );
150       flterr = 1 ;
151       break ;
152
153   case STATUS_NO_MEMORY:
154 //      cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
155       OSD_Exception_STATUS_NO_MEMORY ::
156       Raise (  TEXT( "MEMORY ALLOCATION ERROR ( no room in the process heap )" )  );
157
158   case EXCEPTION_ACCESS_VIOLATION:
159 //      cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
160       wsprintf ( buffer, TEXT( "%s%s%s0x%.8p%s%s%s" ), TEXT( "ACCESS VIOLATION" ),
161                  fMsgBox ? "\n" : " ", TEXT( "at address " ),
162                  ExceptionInformation1 ,
163                  TEXT( " during '" ),
164                  ExceptionInformation0 ? TEXT( "WRITE" ) : TEXT( "READ" ),
165                  TEXT( "' operation" ));
166   break;
167
168   case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
169 //      cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << endl ;
170       lstrcpy (  buffer, TEXT( "ARRAY BOUNDS EXCEEDED" )  );
171   break;
172
173   case EXCEPTION_DATATYPE_MISALIGNMENT:
174 //      cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << endl ;
175       lstrcpy (  buffer, TEXT( "DATATYPE MISALIGNMENT" )  );
176   break;
177
178   case EXCEPTION_ILLEGAL_INSTRUCTION:
179 //      cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << endl ;
180       lstrcpy (  buffer, TEXT( "ILLEGAL INSTRUCTION" )  );
181   break;
182
183   case EXCEPTION_IN_PAGE_ERROR:
184 //      cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << endl ;
185       lstrcpy (  buffer, TEXT( "IN_PAGE ERROR" )  );
186   break;
187
188   case EXCEPTION_INT_DIVIDE_BY_ZERO:
189 //      cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << endl ;
190       lstrcpy (  buffer, TEXT( "INTEGER DIVISION BY ZERO" )  );
191   break;
192
193   case EXCEPTION_INT_OVERFLOW:
194 //      cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << endl ;
195       lstrcpy (  buffer, TEXT( "INTEGER OVERFLOW" )  );
196   break;
197
198   case EXCEPTION_INVALID_DISPOSITION:
199 //      cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << endl ;
200       lstrcpy (  buffer, TEXT( "INVALID DISPOSITION" )  );
201   break;
202
203   case EXCEPTION_NONCONTINUABLE_EXCEPTION:
204 //      cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << endl ;
205       lstrcpy (  buffer, TEXT( "NONCONTINUABLE EXCEPTION" )  );
206   break;
207
208   case EXCEPTION_PRIV_INSTRUCTION:
209 //      cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << endl ;
210       lstrcpy (  buffer, TEXT( "PRIVELEGED INSTRUCTION ENCOUNTERED" )  );
211   break;
212
213   case EXCEPTION_STACK_OVERFLOW:
214 //      cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << endl ;
215 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
216     // try recovering from stack overflow: available in MS VC++ 7.0
217     if (!_resetstkoflw())
218       lstrcpy (  buffer, TEXT( "Unrecoverable STACK OVERFLOW" )  );
219     else
220 #endif
221       lstrcpy (  buffer, TEXT( "STACK OVERFLOW" )  );
222   break;
223  
224   default:
225     wsprintf( buffer, TEXT("unknown exception code 0x%x, params 0x%p 0x%p"),
226               dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
227
228  }  // end switch
229
230  int idx = lstrlen ( buffer );
231
232
233  if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
234      // reset FP operations before message box, otherwise it may fail to show up
235     _fpreset();
236     _clearfp();
237
238   MessageBeep ( MB_ICONHAND );
239   int msgID = MsgBox ( NULL, buffer, TEXT( "Error detected" ), 4, fatalErrorDesc );
240 //  cout << "flterr" << flterr << " fFltExceptions " << fFltExceptions << endl ;
241   if ( flterr ) {
242     if ( !fFltExceptions )
243       return EXCEPTION_EXECUTE_HANDLER;
244     _fpreset () ;
245     _clearfp() ;
246     _controlfp ( 0, _OSD_FPX ) ;          // JR add :
247 //    cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
248   }
249   buffer[ idx ] = 0;
250   switch ( msgID ) {
251    case IDYES: {
252     PTCHAR ptr = _tcschr (  buffer, TEXT( '\n' )  );
253     if ( ptr != NULL )
254       *ptr = TEXT( ' ' );
255 //    cout << "CallHandler " << dwExceptionCode << endl ;
256     _osd_raise ( dwExceptionCode, buffer );
257    }  // IDYES
258    case IDNO:
259     LONG action ;
260     action = _osd_debug ();
261 //    cout << "return from CallHandler -> DebugBreak " << endl ;
262     DebugBreak ();
263     _osd_raise ( dwExceptionCode, buffer );
264 //    cout << "CallHandler return : " << action << endl ;
265     return action ;
266    case IDCANCEL:
267     exit ( 0xFFFF );
268    }  // end switch
269  }
270  else {
271    if ( flterr ) {
272      if ( !fFltExceptions )
273        return EXCEPTION_EXECUTE_HANDLER;
274      _fpreset () ;
275      _clearfp() ;
276      _controlfp ( 0, _OSD_FPX ) ;          // JR add :
277 //     cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
278    }
279  }
280  return _osd_raise ( dwExceptionCode, buffer );
281 #else
282  return 0;
283 #endif
284 }
285
286 //=======================================================================
287 //function : SIGWntHandler
288 //purpose  : Will only be used if user calls ::raise() function with
289 //           signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
290 //           (the latter will likely be removed in the future)
291 //=======================================================================
292 static void SIGWntHandler (int signum, int sub_code)
293 {
294 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
295     Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
296     switch( signum ) {
297     case SIGFPE :
298       if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
299             cout << "signal error" << endl ;
300           switch( sub_code ) {
301           case _FPE_INVALID :
302             CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
303             break ;
304           case _FPE_DENORMAL :
305             CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
306             break ;
307           case _FPE_ZERODIVIDE :
308             CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
309             break ;
310           case _FPE_OVERFLOW :
311             CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
312             break ;
313           case _FPE_UNDERFLOW :
314             CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
315             break ;
316           case _FPE_INEXACT :
317             CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
318             break ;
319           default:
320             cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");"
321                  << endl ;
322             Standard_NumericError::Raise("Floating Point Error");
323             break ;
324           }
325           break ;
326         case SIGSEGV :
327       if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
328             cout << "signal error" << endl ;
329           CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
330           break ;
331     case SIGILL :
332       if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
333             cout << "signal error" << endl ;
334           CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
335           break ;
336         default:
337           cout << "SIGWntHandler unexpected signal : "
338                << signum << endl ;
339           break ;
340         }
341  DebugBreak ();
342 #endif
343 }
344
345 //=======================================================================
346 //function : WntHandler
347 //purpose  : Will be used when user's code is compiled with /EHs
348 //           option and unless user sets his own exception handler with 
349 //           ::SetUnhandledExceptionFilter().
350 //=======================================================================
351 Standard_Integer OSD::WntHandler (const Standard_Address theExceptionInfo)
352 {
353   LPEXCEPTION_POINTERS lpXP = (LPEXCEPTION_POINTERS )theExceptionInfo;
354   DWORD                dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
355
356   return CallHandler (dwExceptionCode,
357                       lpXP->ExceptionRecord->ExceptionInformation[1],
358                       lpXP->ExceptionRecord->ExceptionInformation[0]);
359 }
360
361 //=======================================================================
362 //function : TranslateSE
363 //purpose  : Translate Structural Exceptions into C++ exceptions
364 //           Will be used when user's code is compiled with /EHa option
365 //=======================================================================
366 #ifdef _MSC_VER
367
368 // If this file compiled with the default MSVC options for exception
369 // handling (/GX or /EHsc) then the following warning is issued:
370 //   warning C4535: calling _set_se_translator() requires /EHa
371 // However it is correctly inserted and used when user's code compiled with /EHa.
372 // So, here we disable the warning.
373 #pragma warning (disable:4535)
374
375 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
376 {
377   Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
378   ptrdiff_t info1 = 0, info0 = 0;
379   if ( theExcPtr ) {
380     info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
381     info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
382   }
383   CallHandler(theCode, info1, info0);
384 }
385 #endif
386
387 //=======================================================================
388 //function : SetSignal
389 //purpose  :
390 //=======================================================================
391 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
392 {
393 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
394   Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
395   LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
396
397   OSD_Environment env (TEXT("CSF_DEBUG_MODE"));
398   TCollection_AsciiString val = env.Value();
399   if (!env.Failed())
400   {
401     cout << "Environment variable CSF_DEBUG_MODE setted.\n";
402     fMsgBox = Standard_True;
403   }
404   else
405   {
406     fMsgBox = Standard_False;
407   }
408
409   // Set exception handler (ignored when running under debugger). It will be used in most cases
410   // when user's code is compiled with /EHs
411   // Replaces the existing top-level exception filter for all existing and all future threads
412   // in the calling process
413   aPreviousFilter = ::SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER )&OSD::WntHandler);
414
415   // Signal handlers will only be used when the method ::raise() will be used
416   // Handlers must be set for every thread
417   if (signal (SIGSEGV, (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
418     cout << "signal(OSD::SetSignal) error\n";
419   if (signal (SIGFPE,  (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
420     cout << "signal(OSD::SetSignal) error\n";
421   if (signal (SIGILL,  (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
422     cout << "signal(OSD::SetSignal) error\n";
423
424   // Set Ctrl-C and Ctrl-Break handler
425   fCtrlBrk = Standard_False;
426   SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
427
428 #ifdef _MSC_VER
429   _se_translator_function pOldSeFunc = _set_se_translator (TranslateSE);
430 #endif
431
432   fFltExceptions = theFloatingSignal;
433   if (theFloatingSignal)
434   {
435     _controlfp (0, _OSD_FPX);        // JR add :
436   }
437   else {
438     _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
439   }
440 #endif
441 }  // end OSD :: SetSignal
442
443 //============================================================================
444 //==== ControlBreak 
445 //============================================================================
446
447 void OSD :: ControlBreak () {
448
449  if ( fCtrlBrk ) {
450  
451   fCtrlBrk = Standard_False;
452   OSD_Exception_CTRL_BREAK :: Raise (  TEXT( "*** INTERRUPT ***" )  );
453  
454  }  // end if
455
456 }  // end OSD :: ControlBreak
457
458 //============================================================================
459 //==== _osd_ctrl_break_handler 
460 //============================================================================
461
462 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
463
464  if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
465
466   MessageBeep ( MB_ICONEXCLAMATION );
467   fCtrlBrk = Standard_True;
468
469  } else
470
471   exit ( 254 );
472
473  return TRUE;
474
475 }  // end _osd_ctrl_break_handler
476
477 //============================================================================
478 //==== _osd_raise 
479 //============================================================================
480
481 static LONG __fastcall _osd_raise ( DWORD dwCode, LPTSTR msg ) 
482 {
483   if (msg[0] == TEXT('\x03')) ++msg;
484
485   switch (dwCode)
486   {
487     case EXCEPTION_ACCESS_VIOLATION:
488       OSD_Exception_ACCESS_VIOLATION::Raise (msg);
489       break;
490     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
491       OSD_Exception_ARRAY_BOUNDS_EXCEEDED::Raise (msg);
492       break;
493     case EXCEPTION_DATATYPE_MISALIGNMENT:
494       Standard_ProgramError::Raise (msg);
495       break;
496     case EXCEPTION_ILLEGAL_INSTRUCTION:
497       OSD_Exception_ILLEGAL_INSTRUCTION::Raise (msg);
498       break;
499     case EXCEPTION_IN_PAGE_ERROR:
500       OSD_Exception_IN_PAGE_ERROR::Raise (msg);
501       break;
502     case EXCEPTION_INT_DIVIDE_BY_ZERO:
503       Standard_DivideByZero::Raise (msg);
504       break;
505     case EXCEPTION_INT_OVERFLOW:
506       OSD_Exception_INT_OVERFLOW::Raise (msg);
507       break;
508     case EXCEPTION_INVALID_DISPOSITION:
509       OSD_Exception_INVALID_DISPOSITION::Raise (msg);
510       break;
511     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
512       OSD_Exception_NONCONTINUABLE_EXCEPTION::Raise (msg);
513       break;
514     case EXCEPTION_PRIV_INSTRUCTION:
515       OSD_Exception_PRIV_INSTRUCTION::Raise (msg);
516       break;
517     case EXCEPTION_STACK_OVERFLOW:
518       OSD_Exception_STACK_OVERFLOW::Raise (msg);
519       break;
520     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
521       Standard_DivideByZero::Raise (msg);
522       break;
523     case EXCEPTION_FLT_STACK_CHECK:
524     case EXCEPTION_FLT_OVERFLOW:
525       Standard_Overflow::Raise (msg);
526       break;
527     case EXCEPTION_FLT_UNDERFLOW:
528       Standard_Underflow::Raise (msg);
529       break;
530     case EXCEPTION_FLT_INVALID_OPERATION:
531     case EXCEPTION_FLT_DENORMAL_OPERAND:
532     case EXCEPTION_FLT_INEXACT_RESULT:
533     case STATUS_FLOAT_MULTIPLE_TRAPS:
534     case STATUS_FLOAT_MULTIPLE_FAULTS:
535       Standard_NumericError::Raise (msg);
536       break;
537     default:
538       break;
539   }  // end switch
540   return EXCEPTION_EXECUTE_HANDLER;
541 }  // end _osd_raise
542
543 //============================================================================
544 //==== _osd_debug 
545 //============================================================================
546
547 #if defined(__CYGWIN32__) || defined(__MINGW32__)
548 #define __try
549 #define __finally
550 #define __leave return 0
551 #endif
552
553 LONG _osd_debug ( void ) {
554
555  LONG action ;
556
557  if ( !fDbgLoaded ) {
558  
559   HKEY                hKey;
560   HANDLE              hEvent = INVALID_HANDLE_VALUE;
561   DWORD               dwKeyType;
562   DWORD               dwValueLen;
563   TCHAR               keyValue[ MAX_PATH ];
564   TCHAR               cmdLine[ MAX_PATH ];
565   SECURITY_ATTRIBUTES sa;
566   PROCESS_INFORMATION pi;
567   STARTUPINFO         si;
568
569   __try {
570   
571    if (  RegOpenKey (
572           HKEY_LOCAL_MACHINE,
573           TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
574           &hKey
575          ) != ERROR_SUCCESS
576    ) __leave;
577
578    dwValueLen = sizeof ( keyValue );
579   
580    if (  RegQueryValueEx (
581           hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
582          ) != ERROR_SUCCESS
583    ) __leave;
584
585    sa.nLength              = sizeof ( SECURITY_ATTRIBUTES );
586    sa.lpSecurityDescriptor = NULL;
587    sa.bInheritHandle       = TRUE;
588
589    if (   (  hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL )  ) == NULL   ) __leave;
590
591    wsprintf (  cmdLine, keyValue, GetCurrentProcessId (), hEvent  );
592
593    ZeroMemory (  &si, sizeof ( STARTUPINFO )  );
594
595    si.cb      = sizeof ( STARTUPINFO );
596    si.dwFlags = STARTF_FORCEONFEEDBACK;
597
598 //   cout << "_osd_debug -> CreateProcess" << endl ;
599    if (  !CreateProcess (
600            NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
601            NULL, NULL, &si, &pi
602           )
603    ) __leave;
604
605 //   cout << "_osd_debug -> WaitForSingleObject " << endl ;
606    WaitForSingleObject ( hEvent, INFINITE );
607 //   cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
608
609    CloseHandle ( pi.hProcess );
610    CloseHandle ( pi.hThread  );
611
612 //   cout << "_osd_debug fDbgLoaded  " << endl ;
613    fDbgLoaded = TRUE;
614   
615   }  // end __try
616
617   __finally {
618   
619 //   cout << "_osd_debug -> CloseHandle(hKey) " << endl ;
620    if ( hKey   != INVALID_HANDLE_VALUE ) CloseHandle ( hKey   );
621 //   cout << "_osd_debug -> CloseHandle(hEvent) " << endl ;
622    if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
623 //   cout << "_osd_debug end __finally " << endl ;
624   
625   }  // end __finally
626
627  }  /* end if */
628
629  action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
630 // cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
631 //      << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
632  return action ;
633
634 }  // end _osd_debug
635
636 #if defined(__CYGWIN32__) || defined(__MINGW32__)
637 #undef __try
638 #undef __finally
639 #undef __leave
640 #endif
641
642 // Must be there for compatibility with UNIX system code ----------------------
643
644 //void OSD::Handler(const OSD_Signals aSig,
645 //                  const OSD_Signals aCode){}
646 void OSD::Handler(const OSD_Signals theSignal,
647                   const Standard_Address theSigInfo,
648                   const Standard_Address theContext) {}
649
650 void OSD::SegvHandler(const OSD_Signals aSig,
651                       const Standard_Address code,
652                       const Standard_Address scp){}
653
654 #endif // WNT