1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
34 #include "path_helper.hxx"
36 #include <osl/diagnose.h>
37 #include <osl/mutex.h>
38 #include <osl/signal.h>
43 #include <systools/win32/uwinapi.h>
44 #include <sal/macros.h>
46 typedef struct _oslSignalHandlerImpl
48 oslSignalHandlerFunction Handler
;
50 struct _oslSignalHandlerImpl
* pNext
;
51 } oslSignalHandlerImpl
;
53 static sal_Bool bErrorReportingEnabled
= sal_True
;
54 static sal_Bool bInitSignal
= sal_False
;
55 static oslMutex SignalListMutex
;
56 static oslSignalHandlerImpl
* SignalList
;
58 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
);
60 static sal_Bool
InitSignal(void)
64 SignalListMutex
= osl_createMutex();
66 SetUnhandledExceptionFilter(SignalHandlerFunction
);
68 hFaultRep
= LoadLibrary( "faultrep.dll" );
71 pfn_ADDEREXCLUDEDAPPLICATIONW pfn
= (pfn_ADDEREXCLUDEDAPPLICATIONW
)GetProcAddress( hFaultRep
, "AddERExcludedApplicationW" );
73 pfn( L
"SOFFICE.EXE" );
74 FreeLibrary( hFaultRep
);
80 static sal_Bool
DeInitSignal(void)
82 SetUnhandledExceptionFilter(NULL
);
84 osl_destroyMutex(SignalListMutex
);
89 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
91 oslSignalHandlerImpl
* pHandler
= SignalList
;
92 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
94 while (pHandler
!= NULL
)
96 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
)) != osl_Signal_ActCallNextHdl
)
99 pHandler
= pHandler
->pNext
;
105 /*****************************************************************************/
106 /* SignalHandlerFunction */
107 /*****************************************************************************/
109 #define REPORTENV_PARAM "-crashreportenv:"
110 #define REPORTENV_PARAM2 "/crashreportenv:"
112 static BOOL
ReportCrash( LPEXCEPTION_POINTERS lpEP
)
114 BOOL fSuccess
= FALSE
;
115 BOOL fAutoReport
= FALSE
;
116 TCHAR szBuffer
[1024];
117 ::osl::LongPathBuffer
< sal_Char
> aPath( MAX_LONG_PATH
);
119 PROCESS_INFORMATION ProcessInfo
;
120 STARTUPINFO StartupInfo
;
123 if ( !bErrorReportingEnabled
)
126 /* Check if crash reporter was disabled by command line */
128 for ( argi
= 1; argi
< __argc
; argi
++ )
131 0 == stricmp( __argv
[argi
], "--nocrashreport" ) ||
132 0 == stricmp( __argv
[argi
], "/nocrashreport" )
136 0 == stricmp( __argv
[argi
], "--autocrashreport" ) ||
137 0 == stricmp( __argv
[argi
], "/autocrashreport" )
141 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) ) ||
142 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM2
, strlen(REPORTENV_PARAM2
) )
145 const char *envparam
= __argv
[argi
] + strlen(REPORTENV_PARAM
);
146 const char *delim
= strchr(envparam
, '=' );
152 const char *variable
= envparam
;
153 size_t variable_len
= delim
- envparam
;
154 const char *value
= delim
+ 1;
155 size_t value_len
= strlen(envparam
) - variable_len
- 1;
157 if ( '\"' == *value
)
164 quote
= strchr( value
, '\"' );
166 value_len
= quote
- value
;
169 lpVariable
= reinterpret_cast< CHAR
* >( _alloca( variable_len
+ 1 ) );
170 memcpy( lpVariable
, variable
, variable_len
);
171 lpVariable
[variable_len
] = 0;
173 lpValue
= reinterpret_cast< CHAR
* >( _alloca( value_len
+ 1) );
174 memcpy( lpValue
, value
, value_len
);
175 lpValue
[value_len
] = 0;
177 SetEnvironmentVariable( lpVariable
, lpValue
);
182 if ( SearchPath( NULL
, TEXT( "crashrep.exe" ), NULL
, aPath
.getBufSizeInSymbols(), aPath
, &lpFilePart
) )
184 ZeroMemory( &StartupInfo
, sizeof(StartupInfo
) );
185 StartupInfo
.cb
= sizeof(StartupInfo
.cb
);
188 sntprintf( szBuffer
, SAL_N_ELEMENTS(szBuffer
),
189 _T("%s -p %lu -excp 0x%p -t %lu%s"),
190 static_cast<sal_Char
*>( aPath
),
191 GetCurrentProcessId(),
193 GetCurrentThreadId(),
194 fAutoReport
? _T(" -noui -send") : _T(" -noui") );
204 CREATE_UNICODE_ENVIRONMENT
,
208 NULL
, NULL
, &StartupInfo
, &ProcessInfo
)
213 WaitForSingleObject( ProcessInfo
.hProcess
, INFINITE
);
214 if ( GetExitCodeProcess( ProcessInfo
.hProcess
, &dwExitCode
) && 0 == dwExitCode
)
224 /*****************************************************************************/
225 /* SignalHandlerFunction */
226 /*****************************************************************************/
228 /* magic Microsoft C++ compiler exception constant */
229 #define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
231 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
)
233 static sal_Bool bNested
= sal_False
;
234 sal_Bool bRaiseCrashReporter
= sal_False
;
236 oslSignalAction Action
;
238 Info
.UserSignal
= lpEP
->ExceptionRecord
->ExceptionCode
;
239 Info
.UserData
= NULL
;
241 switch (lpEP
->ExceptionRecord
->ExceptionCode
)
243 /* Transform unhandled exceptions into access violations.
244 Microsoft C++ compiler (add more for other compilers if necessary).
246 case EXCEPTION_MSC_CPP_EXCEPTION
:
247 case EXCEPTION_ACCESS_VIOLATION
:
248 Info
.Signal
= osl_Signal_AccessViolation
;
249 bRaiseCrashReporter
= sal_True
;
252 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
253 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
254 bRaiseCrashReporter
= sal_True
;
257 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
258 Info
.Signal
= osl_Signal_FloatDivideByZero
;
259 bRaiseCrashReporter
= sal_True
;
262 case EXCEPTION_BREAKPOINT
:
263 Info
.Signal
= osl_Signal_DebugBreak
;
267 Info
.Signal
= osl_Signal_System
;
268 bRaiseCrashReporter
= sal_True
;
276 if ( bRaiseCrashReporter
&& ReportCrash( lpEP
) )
278 CallSignalHandler(&Info
);
279 Action
= osl_Signal_ActKillApp
;
282 Action
= CallSignalHandler(&Info
);
285 Action
= osl_Signal_ActKillApp
;
290 case osl_Signal_ActCallNextHdl
:
291 return (EXCEPTION_CONTINUE_SEARCH
);
293 case osl_Signal_ActAbortApp
:
294 return (EXCEPTION_EXECUTE_HANDLER
);
296 case osl_Signal_ActKillApp
:
297 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
304 return (EXCEPTION_CONTINUE_EXECUTION
);
307 /*****************************************************************************/
308 /* osl_addSignalHandler */
309 /*****************************************************************************/
310 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
312 oslSignalHandlerImpl
* pHandler
;
314 OSL_ASSERT(Handler
!= NULL
);
317 bInitSignal
= InitSignal();
319 pHandler
= reinterpret_cast< oslSignalHandlerImpl
* >( calloc( 1, sizeof(oslSignalHandlerImpl
) ) );
321 if (pHandler
!= NULL
)
323 pHandler
->Handler
= Handler
;
324 pHandler
->pData
= pData
;
326 osl_acquireMutex(SignalListMutex
);
328 pHandler
->pNext
= SignalList
;
329 SignalList
= pHandler
;
331 osl_releaseMutex(SignalListMutex
);
339 /*****************************************************************************/
340 /* osl_removeSignalHandler */
341 /*****************************************************************************/
342 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
344 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
346 OSL_ASSERT(Handler
!= NULL
);
349 bInitSignal
= InitSignal();
351 osl_acquireMutex(SignalListMutex
);
353 pHandler
= SignalList
;
355 while (pHandler
!= NULL
)
357 if (pHandler
== Handler
)
360 pPrevious
->pNext
= pHandler
->pNext
;
362 SignalList
= pHandler
->pNext
;
364 osl_releaseMutex(SignalListMutex
);
366 if (SignalList
== NULL
)
367 bInitSignal
= DeInitSignal();
374 pPrevious
= pHandler
;
375 pHandler
= pHandler
->pNext
;
378 osl_releaseMutex(SignalListMutex
);
383 /*****************************************************************************/
384 /* osl_raiseSignal */
385 /*****************************************************************************/
386 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
389 oslSignalAction Action
;
392 bInitSignal
= InitSignal();
394 osl_acquireMutex(SignalListMutex
);
396 Info
.Signal
= osl_Signal_User
;
397 Info
.UserSignal
= UserSignal
;
398 Info
.UserData
= UserData
;
400 Action
= CallSignalHandler(&Info
);
402 osl_releaseMutex(SignalListMutex
);
407 /*****************************************************************************/
408 /* osl_setErrorReporting */
409 /*****************************************************************************/
410 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
412 sal_Bool bOld
= bErrorReportingEnabled
;
413 bErrorReportingEnabled
= bEnable
;
418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */