1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
33 #include "path_helper.hxx"
35 #include <osl/diagnose.h>
36 #include <osl/mutex.h>
37 #include <osl/signal.h>
42 #include <systools/win32/uwinapi.h>
44 typedef struct _oslSignalHandlerImpl
46 oslSignalHandlerFunction Handler
;
48 struct _oslSignalHandlerImpl
* pNext
;
49 } oslSignalHandlerImpl
;
51 static sal_Bool bErrorReportingEnabled
= sal_True
;
52 static sal_Bool bInitSignal
= sal_False
;
53 static oslMutex SignalListMutex
;
54 static oslSignalHandlerImpl
* SignalList
;
56 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
);
58 static sal_Bool
InitSignal(void)
62 SignalListMutex
= osl_createMutex();
64 SetUnhandledExceptionFilter(SignalHandlerFunction
);
66 hFaultRep
= LoadLibrary( "faultrep.dll" );
70 typedef BOOL (WINAPI
*pfn_ADDEREXCLUDEDAPPLICATIONW
)(LPCWSTR
);
72 pfn_ADDEREXCLUDEDAPPLICATIONW pfn
= (pfn_ADDEREXCLUDEDAPPLICATIONW
)GetProcAddress( hFaultRep
, "AddERExcludedApplicationW" );
74 pfn( L
"SOFFICE.EXE" );
75 FreeLibrary( hFaultRep
);
81 static sal_Bool
DeInitSignal(void)
83 SetUnhandledExceptionFilter(NULL
);
85 osl_destroyMutex(SignalListMutex
);
90 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
92 oslSignalHandlerImpl
* pHandler
= SignalList
;
93 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
95 while (pHandler
!= NULL
)
97 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
)) != osl_Signal_ActCallNextHdl
)
100 pHandler
= pHandler
->pNext
;
106 /*****************************************************************************/
107 /* SignalHandlerFunction */
108 /*****************************************************************************/
110 #define REPORTENV_PARAM "-crashreportenv:"
111 #define REPORTENV_PARAM2 "/crashreportenv:"
113 static BOOL
ReportCrash( LPEXCEPTION_POINTERS lpEP
)
115 BOOL fSuccess
= FALSE
;
116 BOOL fAutoReport
= FALSE
;
117 TCHAR szBuffer
[1024];
118 ::osl::LongPathBuffer
< sal_Char
> aPath( MAX_LONG_PATH
);
120 PROCESS_INFORMATION ProcessInfo
;
121 STARTUPINFO StartupInfo
;
124 if ( !bErrorReportingEnabled
)
127 /* Check if crash reporter was disabled by command line */
129 for ( argi
= 1; argi
< __argc
; argi
++ )
132 0 == stricmp( __argv
[argi
], "-nocrashreport" ) ||
133 0 == stricmp( __argv
[argi
], "/nocrashreport" )
137 0 == stricmp( __argv
[argi
], "-autocrashreport" ) ||
138 0 == stricmp( __argv
[argi
], "/autocrashreport" )
142 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) ) ||
143 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM2
, strlen(REPORTENV_PARAM2
) )
146 const char *envparam
= __argv
[argi
] + strlen(REPORTENV_PARAM
);
147 const char *delim
= strchr(envparam
, '=' );
153 const char *variable
= envparam
;
154 size_t variable_len
= delim
- envparam
;
155 const char *value
= delim
+ 1;
156 size_t value_len
= strlen(envparam
) - variable_len
- 1;
158 if ( '\"' == *value
)
165 quote
= strchr( value
, '\"' );
167 value_len
= quote
- value
;
170 lpVariable
= reinterpret_cast< CHAR
* >( _alloca( variable_len
+ 1 ) );
171 memcpy( lpVariable
, variable
, variable_len
);
172 lpVariable
[variable_len
] = 0;
174 lpValue
= reinterpret_cast< CHAR
* >( _alloca( value_len
+ 1) );
175 memcpy( lpValue
, value
, value_len
);
176 lpValue
[value_len
] = 0;
178 SetEnvironmentVariable( lpVariable
, lpValue
);
183 if ( SearchPath( NULL
, TEXT( "crashrep.exe" ), NULL
, aPath
.getBufSizeInSymbols(), aPath
, &lpFilePart
) )
185 ZeroMemory( &StartupInfo
, sizeof(StartupInfo
) );
186 StartupInfo
.cb
= sizeof(StartupInfo
.cb
);
189 sntprintf( szBuffer
, elementsof(szBuffer
),
190 _T("%s -p %u -excp 0x%p -t %u%s"),
191 static_cast<sal_Char
*>( aPath
),
192 GetCurrentProcessId(),
194 GetCurrentThreadId(),
195 fAutoReport
? _T(" -noui -send") : _T(" -noui") );
205 CREATE_UNICODE_ENVIRONMENT
,
209 NULL
, NULL
, &StartupInfo
, &ProcessInfo
)
214 WaitForSingleObject( ProcessInfo
.hProcess
, INFINITE
);
215 if ( GetExitCodeProcess( ProcessInfo
.hProcess
, &dwExitCode
) && 0 == dwExitCode
)
225 /*****************************************************************************/
226 /* SignalHandlerFunction */
227 /*****************************************************************************/
229 static BOOL WINAPI
IsWin95A(void)
233 ZeroMemory( &ovi
, sizeof(ovi
) );
234 ovi
.dwOSVersionInfoSize
= sizeof(ovi
);
236 if ( GetVersionEx( &ovi
) )
237 /* See MSDN January 2000 documentation of GetVersionEx */
238 return (ovi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) &&
239 (ovi
.dwMajorVersion
<= 4) &&
240 (ovi
.dwMinorVersion
== 0) &&
241 (ovi
.dwBuildNumber
== 0x040003B6);
243 /* Something wrent wrong. So assume we have an older operating prior Win95 */
248 /* magic Microsoft C++ compiler exception constant */
249 #define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
251 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
)
253 static sal_Bool bNested
= sal_False
;
254 sal_Bool bRaiseCrashReporter
= sal_False
;
256 oslSignalAction Action
;
258 Info
.UserSignal
= lpEP
->ExceptionRecord
->ExceptionCode
;
259 Info
.UserData
= NULL
;
261 switch (lpEP
->ExceptionRecord
->ExceptionCode
)
263 /* Transform unhandled exceptions into access violations.
264 Microsoft C++ compiler (add more for other compilers if necessary).
266 case EXCEPTION_MSC_CPP_EXCEPTION
:
267 case EXCEPTION_ACCESS_VIOLATION
:
268 Info
.Signal
= osl_Signal_AccessViolation
;
269 bRaiseCrashReporter
= sal_True
;
272 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
273 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
274 bRaiseCrashReporter
= sal_True
;
277 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
278 Info
.Signal
= osl_Signal_FloatDivideByZero
;
279 bRaiseCrashReporter
= sal_True
;
282 case EXCEPTION_BREAKPOINT
:
283 Info
.Signal
= osl_Signal_DebugBreak
;
287 Info
.Signal
= osl_Signal_System
;
288 bRaiseCrashReporter
= sal_True
;
296 if ( bRaiseCrashReporter
&& ReportCrash( lpEP
) || IsWin95A() )
298 CallSignalHandler(&Info
);
299 Action
= osl_Signal_ActKillApp
;
302 Action
= CallSignalHandler(&Info
);
305 Action
= osl_Signal_ActKillApp
;
310 case osl_Signal_ActCallNextHdl
:
311 return (EXCEPTION_CONTINUE_SEARCH
);
313 case osl_Signal_ActAbortApp
:
314 return (EXCEPTION_EXECUTE_HANDLER
);
316 case osl_Signal_ActKillApp
:
317 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
324 return (EXCEPTION_CONTINUE_EXECUTION
);
327 /*****************************************************************************/
328 /* osl_addSignalHandler */
329 /*****************************************************************************/
330 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
332 oslSignalHandlerImpl
* pHandler
;
334 OSL_ASSERT(Handler
!= NULL
);
337 bInitSignal
= InitSignal();
339 pHandler
= reinterpret_cast< oslSignalHandlerImpl
* >( calloc( 1, sizeof(oslSignalHandlerImpl
) ) );
341 if (pHandler
!= NULL
)
343 pHandler
->Handler
= Handler
;
344 pHandler
->pData
= pData
;
346 osl_acquireMutex(SignalListMutex
);
348 pHandler
->pNext
= SignalList
;
349 SignalList
= pHandler
;
351 osl_releaseMutex(SignalListMutex
);
359 /*****************************************************************************/
360 /* osl_removeSignalHandler */
361 /*****************************************************************************/
362 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
364 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
366 OSL_ASSERT(Handler
!= NULL
);
369 bInitSignal
= InitSignal();
371 osl_acquireMutex(SignalListMutex
);
373 pHandler
= SignalList
;
375 while (pHandler
!= NULL
)
377 if (pHandler
== Handler
)
380 pPrevious
->pNext
= pHandler
->pNext
;
382 SignalList
= pHandler
->pNext
;
384 osl_releaseMutex(SignalListMutex
);
386 if (SignalList
== NULL
)
387 bInitSignal
= DeInitSignal();
394 pPrevious
= pHandler
;
395 pHandler
= pHandler
->pNext
;
398 osl_releaseMutex(SignalListMutex
);
403 /*****************************************************************************/
404 /* osl_raiseSignal */
405 /*****************************************************************************/
406 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
409 oslSignalAction Action
;
412 bInitSignal
= InitSignal();
414 osl_acquireMutex(SignalListMutex
);
416 Info
.Signal
= osl_Signal_User
;
417 Info
.UserSignal
= UserSignal
;
418 Info
.UserData
= UserData
;
420 Action
= CallSignalHandler(&Info
);
422 osl_releaseMutex(SignalListMutex
);
427 /*****************************************************************************/
428 /* osl_setErrorReporting */
429 /*****************************************************************************/
430 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
432 sal_Bool bOld
= bErrorReportingEnabled
;
433 bErrorReportingEnabled
= bEnable
;