0024304: Eliminate GCC compiler warning about exceeding maximum value for type in...
[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 _WIN32
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 static 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  // provide message to the user with possibility to stop
231  int idx = lstrlen ( buffer );
232  if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
233      // reset FP operations before message box, otherwise it may fail to show up
234     _fpreset();
235     _clearfp();
236
237     MessageBeep ( MB_ICONHAND );
238     int aChoice = ::MessageBox (0, buffer, "OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
239     if (aChoice == IDRETRY)
240     {
241       _osd_debug();
242       DebugBreak();
243     } 
244     else if (aChoice == IDABORT)
245       exit(0xFFFF);
246  }
247
248  // reset FPE state
249  if ( flterr ) {
250    if ( !fFltExceptions )
251      return EXCEPTION_EXECUTE_HANDLER;
252    _fpreset () ;
253    _clearfp() ;
254    _controlfp ( 0, _OSD_FPX ) ;          // JR add :
255 //     cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
256  }
257  return _osd_raise ( dwExceptionCode, buffer );
258 #else
259  return 0;
260 #endif
261 }
262
263 //=======================================================================
264 //function : SIGWntHandler
265 //purpose  : Will only be used if user calls ::raise() function with
266 //           signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
267 //           (the latter will likely be removed in the future)
268 //=======================================================================
269 static void SIGWntHandler (int signum, int sub_code)
270 {
271 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
272     Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
273     switch( signum ) {
274     case SIGFPE :
275       if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
276           cout << "signal error" << endl ;
277       switch( sub_code ) {
278       case _FPE_INVALID :
279         CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
280         break ;
281       case _FPE_DENORMAL :
282         CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
283         break ;
284       case _FPE_ZERODIVIDE :
285         CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
286         break ;
287       case _FPE_OVERFLOW :
288         CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
289         break ;
290       case _FPE_UNDERFLOW :
291         CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
292         break ;
293       case _FPE_INEXACT :
294         CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
295         break ;
296       default:
297         cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");" << endl;
298         Standard_NumericError::Raise("Floating Point Error");
299         break ;
300       }
301       break ;
302     case SIGSEGV :
303       if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
304         cout << "signal error" << endl ;
305       CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
306       break ;
307     case SIGILL :
308       if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
309         cout << "signal error" << endl ;
310       CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
311       break ;
312     default:
313       cout << "SIGWntHandler unexpected signal : " << signum << endl ;
314       break ;
315     }
316  DebugBreak ();
317 #endif
318 }
319
320 //=======================================================================
321 //function : TranslateSE
322 //purpose  : Translate Structural Exceptions into C++ exceptions
323 //           Will be used when user's code is compiled with /EHa option
324 //=======================================================================
325 #ifdef _MSC_VER
326
327 // If this file compiled with the default MSVC options for exception
328 // handling (/GX or /EHsc) then the following warning is issued:
329 //   warning C4535: calling _set_se_translator() requires /EHa
330 // However it is correctly inserted and used when user's code compiled with /EHa.
331 // So, here we disable the warning.
332 #pragma warning (disable:4535)
333
334 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
335 {
336   Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
337   ptrdiff_t info1 = 0, info0 = 0;
338   if ( theExcPtr ) {
339     info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
340     info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
341   }
342   CallHandler(theCode, info1, info0);
343 }
344 #endif
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 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
352 {
353   DWORD                dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
354
355   return CallHandler (dwExceptionCode,
356                       lpXP->ExceptionRecord->ExceptionInformation[1],
357                       lpXP->ExceptionRecord->ExceptionInformation[0]);
358 }
359 //=======================================================================
360 //function : SetSignal
361 //purpose  :
362 //=======================================================================
363 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
364 {
365 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
366   Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
367   LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
368
369   OSD_Environment env (TEXT("CSF_DEBUG_MODE"));
370   TCollection_AsciiString val = env.Value();
371   if (!env.Failed())
372   {
373     cout << "Environment variable CSF_DEBUG_MODE setted.\n";
374     fMsgBox = Standard_True;
375   }
376   else
377   {
378     fMsgBox = Standard_False;
379   }
380
381   // Set exception handler (ignored when running under debugger). It will be used in most cases
382   // when user's code is compiled with /EHs
383   // Replaces the existing top-level exception filter for all existing and all future threads
384   // in the calling process
385   aPreviousFilter = ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
386
387   // Signal handlers will only be used when the method ::raise() will be used
388   // Handlers must be set for every thread
389   if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
390     cout << "signal(OSD::SetSignal) error\n";
391   if (signal (SIGFPE,  (void(*)(int))SIGWntHandler) == SIG_ERR)
392     cout << "signal(OSD::SetSignal) error\n";
393   if (signal (SIGILL,  (void(*)(int))SIGWntHandler) == SIG_ERR)
394     cout << "signal(OSD::SetSignal) error\n";
395
396   // Set Ctrl-C and Ctrl-Break handler
397   fCtrlBrk = Standard_False;
398   SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
399
400 #ifdef _MSC_VER
401 //  _se_translator_function pOldSeFunc = 
402     _set_se_translator (TranslateSE);
403 #endif
404
405   fFltExceptions = theFloatingSignal;
406   if (theFloatingSignal)
407   {
408     _controlfp (0, _OSD_FPX);        // JR add :
409   }
410   else {
411     _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
412   }
413 #endif
414 }  // end OSD :: SetSignal
415
416 //============================================================================
417 //==== ControlBreak 
418 //============================================================================
419
420 void OSD :: ControlBreak () {
421
422  if ( fCtrlBrk ) {
423  
424   fCtrlBrk = Standard_False;
425   OSD_Exception_CTRL_BREAK :: Raise (  TEXT( "*** INTERRUPT ***" )  );
426  
427  }  // end if
428
429 }  // end OSD :: ControlBreak
430
431 //============================================================================
432 //==== _osd_ctrl_break_handler 
433 //============================================================================
434
435 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
436
437  if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
438
439   MessageBeep ( MB_ICONEXCLAMATION );
440   fCtrlBrk = Standard_True;
441
442  } else
443
444   exit ( 254 );
445
446  return TRUE;
447
448 }  // end _osd_ctrl_break_handler
449
450 //============================================================================
451 //==== _osd_raise 
452 //============================================================================
453
454 static LONG __fastcall _osd_raise ( DWORD dwCode, LPTSTR msg ) 
455 {
456   if (msg[0] == TEXT('\x03')) ++msg;
457
458   switch (dwCode)
459   {
460     case EXCEPTION_ACCESS_VIOLATION:
461       OSD_Exception_ACCESS_VIOLATION::Raise (msg);
462       break;
463     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
464       OSD_Exception_ARRAY_BOUNDS_EXCEEDED::Raise (msg);
465       break;
466     case EXCEPTION_DATATYPE_MISALIGNMENT:
467       Standard_ProgramError::Raise (msg);
468       break;
469     case EXCEPTION_ILLEGAL_INSTRUCTION:
470       OSD_Exception_ILLEGAL_INSTRUCTION::Raise (msg);
471       break;
472     case EXCEPTION_IN_PAGE_ERROR:
473       OSD_Exception_IN_PAGE_ERROR::Raise (msg);
474       break;
475     case EXCEPTION_INT_DIVIDE_BY_ZERO:
476       Standard_DivideByZero::Raise (msg);
477       break;
478     case EXCEPTION_INT_OVERFLOW:
479       OSD_Exception_INT_OVERFLOW::Raise (msg);
480       break;
481     case EXCEPTION_INVALID_DISPOSITION:
482       OSD_Exception_INVALID_DISPOSITION::Raise (msg);
483       break;
484     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
485       OSD_Exception_NONCONTINUABLE_EXCEPTION::Raise (msg);
486       break;
487     case EXCEPTION_PRIV_INSTRUCTION:
488       OSD_Exception_PRIV_INSTRUCTION::Raise (msg);
489       break;
490     case EXCEPTION_STACK_OVERFLOW:
491       OSD_Exception_STACK_OVERFLOW::Raise (msg);
492       break;
493     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
494       Standard_DivideByZero::Raise (msg);
495       break;
496     case EXCEPTION_FLT_STACK_CHECK:
497     case EXCEPTION_FLT_OVERFLOW:
498       Standard_Overflow::Raise (msg);
499       break;
500     case EXCEPTION_FLT_UNDERFLOW:
501       Standard_Underflow::Raise (msg);
502       break;
503     case EXCEPTION_FLT_INVALID_OPERATION:
504     case EXCEPTION_FLT_DENORMAL_OPERAND:
505     case EXCEPTION_FLT_INEXACT_RESULT:
506     case STATUS_FLOAT_MULTIPLE_TRAPS:
507     case STATUS_FLOAT_MULTIPLE_FAULTS:
508       Standard_NumericError::Raise (msg);
509       break;
510     default:
511       break;
512   }  // end switch
513   return EXCEPTION_EXECUTE_HANDLER;
514 }  // end _osd_raise
515
516 //============================================================================
517 //==== _osd_debug 
518 //============================================================================
519
520 #if defined(__CYGWIN32__) || defined(__MINGW32__)
521 #define __try
522 #define __finally
523 #define __leave return 0
524 #endif
525
526 LONG _osd_debug ( void ) {
527
528  LONG action ;
529
530  if ( !fDbgLoaded ) {
531  
532   HKEY                hKey = NULL;
533   HANDLE              hEvent = INVALID_HANDLE_VALUE;
534   DWORD               dwKeyType;
535   DWORD               dwValueLen;
536   TCHAR               keyValue[ MAX_PATH ];
537   TCHAR               cmdLine[ MAX_PATH ];
538   SECURITY_ATTRIBUTES sa;
539   PROCESS_INFORMATION pi;
540   STARTUPINFO         si;
541
542   __try {
543   
544    if (  RegOpenKey (
545           HKEY_LOCAL_MACHINE,
546           TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
547           &hKey
548          ) != ERROR_SUCCESS
549    ) __leave;
550
551    dwValueLen = sizeof ( keyValue );
552   
553    if (  RegQueryValueEx (
554           hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
555          ) != ERROR_SUCCESS
556    ) __leave;
557
558    sa.nLength              = sizeof ( SECURITY_ATTRIBUTES );
559    sa.lpSecurityDescriptor = NULL;
560    sa.bInheritHandle       = TRUE;
561
562    if (   (  hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL )  ) == NULL   ) __leave;
563
564    wsprintf (  cmdLine, keyValue, GetCurrentProcessId (), hEvent  );
565
566    ZeroMemory (  &si, sizeof ( STARTUPINFO )  );
567
568    si.cb      = sizeof ( STARTUPINFO );
569    si.dwFlags = STARTF_FORCEONFEEDBACK;
570
571 //   cout << "_osd_debug -> CreateProcess" << endl ;
572    if (  !CreateProcess (
573            NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
574            NULL, NULL, &si, &pi
575           )
576    ) __leave;
577
578 //   cout << "_osd_debug -> WaitForSingleObject " << endl ;
579    WaitForSingleObject ( hEvent, INFINITE );
580 //   cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
581
582    CloseHandle ( pi.hProcess );
583    CloseHandle ( pi.hThread  );
584
585 //   cout << "_osd_debug fDbgLoaded  " << endl ;
586    fDbgLoaded = TRUE;
587   
588   }  // end __try
589
590   __finally {
591   
592 //   cout << "_osd_debug -> CloseHandle(hKey) " << endl ;
593    if ( hKey   != INVALID_HANDLE_VALUE ) CloseHandle ( hKey   );
594 //   cout << "_osd_debug -> CloseHandle(hEvent) " << endl ;
595    if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
596 //   cout << "_osd_debug end __finally " << endl ;
597   
598   }  // end __finally
599
600  }  /* end if */
601
602  action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
603 // cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
604 //      << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
605  return action ;
606
607 }  // end _osd_debug
608
609 #if defined(__CYGWIN32__) || defined(__MINGW32__)
610 #undef __try
611 #undef __finally
612 #undef __leave
613 #endif
614 #endif // WNT