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