1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 #include "path_helper.hxx"
27 #include <osl/diagnose.h>
28 #include <osl/mutex.h>
29 #include <osl/signal.h>
34 #include <systools/win32/uwinapi.h>
35 #include <sal/macros.h>
37 typedef struct _oslSignalHandlerImpl
39 oslSignalHandlerFunction Handler
;
41 struct _oslSignalHandlerImpl
* pNext
;
42 } oslSignalHandlerImpl
;
44 static sal_Bool bErrorReportingEnabled
= sal_True
;
45 static sal_Bool bInitSignal
= sal_False
;
46 static oslMutex SignalListMutex
;
47 static oslSignalHandlerImpl
* SignalList
;
49 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
);
51 static sal_Bool
InitSignal(void)
55 SignalListMutex
= osl_createMutex();
57 SetUnhandledExceptionFilter(SignalHandlerFunction
);
59 hFaultRep
= LoadLibrary( "faultrep.dll" );
62 pfn_ADDEREXCLUDEDAPPLICATIONW pfn
= (pfn_ADDEREXCLUDEDAPPLICATIONW
)GetProcAddress( hFaultRep
, "AddERExcludedApplicationW" );
64 pfn( L
"SOFFICE.EXE" );
65 FreeLibrary( hFaultRep
);
71 static sal_Bool
DeInitSignal(void)
73 SetUnhandledExceptionFilter(NULL
);
75 osl_destroyMutex(SignalListMutex
);
80 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
82 oslSignalHandlerImpl
* pHandler
= SignalList
;
83 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
85 while (pHandler
!= NULL
)
87 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
)) != osl_Signal_ActCallNextHdl
)
90 pHandler
= pHandler
->pNext
;
96 /*****************************************************************************/
97 /* SignalHandlerFunction */
98 /*****************************************************************************/
100 #define REPORTENV_PARAM "-crashreportenv:"
101 #define REPORTENV_PARAM2 "/crashreportenv:"
103 static BOOL
ReportCrash( LPEXCEPTION_POINTERS lpEP
)
105 BOOL fSuccess
= FALSE
;
106 BOOL fAutoReport
= FALSE
;
107 TCHAR szBuffer
[1024];
108 ::osl::LongPathBuffer
< sal_Char
> aPath( MAX_LONG_PATH
);
110 PROCESS_INFORMATION ProcessInfo
;
111 STARTUPINFO StartupInfo
;
114 if ( !bErrorReportingEnabled
)
117 /* Check if crash reporter was disabled by command line */
119 for ( argi
= 1; argi
< __argc
; argi
++ )
122 0 == stricmp( __argv
[argi
], "--nocrashreport" ) ||
123 0 == stricmp( __argv
[argi
], "/nocrashreport" )
127 0 == stricmp( __argv
[argi
], "--autocrashreport" ) ||
128 0 == stricmp( __argv
[argi
], "/autocrashreport" )
132 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) ) ||
133 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM2
, strlen(REPORTENV_PARAM2
) )
136 const char *envparam
= __argv
[argi
] + strlen(REPORTENV_PARAM
);
137 const char *delim
= strchr(envparam
, '=' );
143 const char *variable
= envparam
;
144 size_t variable_len
= delim
- envparam
;
145 const char *value
= delim
+ 1;
146 size_t value_len
= strlen(envparam
) - variable_len
- 1;
148 if ( '\"' == *value
)
155 quote
= strchr( value
, '\"' );
157 value_len
= quote
- value
;
160 lpVariable
= reinterpret_cast< CHAR
* >( _alloca( variable_len
+ 1 ) );
161 memcpy( lpVariable
, variable
, variable_len
);
162 lpVariable
[variable_len
] = 0;
164 lpValue
= reinterpret_cast< CHAR
* >( _alloca( value_len
+ 1) );
165 memcpy( lpValue
, value
, value_len
);
166 lpValue
[value_len
] = 0;
168 SetEnvironmentVariable( lpVariable
, lpValue
);
173 if ( SearchPath( NULL
, TEXT( "crashrep.exe" ), NULL
, aPath
.getBufSizeInSymbols(), aPath
, &lpFilePart
) )
175 ZeroMemory( &StartupInfo
, sizeof(StartupInfo
) );
176 StartupInfo
.cb
= sizeof(StartupInfo
.cb
);
179 sntprintf( szBuffer
, SAL_N_ELEMENTS(szBuffer
),
180 _T("%s -p %lu -excp 0x%p -t %lu%s"),
181 static_cast<sal_Char
*>( aPath
),
182 GetCurrentProcessId(),
184 GetCurrentThreadId(),
185 fAutoReport
? _T(" -noui -send") : _T(" -noui") );
195 CREATE_UNICODE_ENVIRONMENT
,
199 NULL
, NULL
, &StartupInfo
, &ProcessInfo
)
204 WaitForSingleObject( ProcessInfo
.hProcess
, INFINITE
);
205 if ( GetExitCodeProcess( ProcessInfo
.hProcess
, &dwExitCode
) && 0 == dwExitCode
)
215 /*****************************************************************************/
216 /* SignalHandlerFunction */
217 /*****************************************************************************/
219 /* magic Microsoft C++ compiler exception constant */
220 #define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
222 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
)
224 static sal_Bool bNested
= sal_False
;
225 sal_Bool bRaiseCrashReporter
= sal_False
;
227 oslSignalAction Action
;
229 Info
.UserSignal
= lpEP
->ExceptionRecord
->ExceptionCode
;
230 Info
.UserData
= NULL
;
232 switch (lpEP
->ExceptionRecord
->ExceptionCode
)
234 /* Transform unhandled exceptions into access violations.
235 Microsoft C++ compiler (add more for other compilers if necessary).
237 case EXCEPTION_MSC_CPP_EXCEPTION
:
238 case EXCEPTION_ACCESS_VIOLATION
:
239 Info
.Signal
= osl_Signal_AccessViolation
;
240 bRaiseCrashReporter
= sal_True
;
243 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
244 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
245 bRaiseCrashReporter
= sal_True
;
248 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
249 Info
.Signal
= osl_Signal_FloatDivideByZero
;
250 bRaiseCrashReporter
= sal_True
;
253 case EXCEPTION_BREAKPOINT
:
254 Info
.Signal
= osl_Signal_DebugBreak
;
258 Info
.Signal
= osl_Signal_System
;
259 bRaiseCrashReporter
= sal_True
;
267 if ( bRaiseCrashReporter
&& ReportCrash( lpEP
) )
269 CallSignalHandler(&Info
);
270 Action
= osl_Signal_ActKillApp
;
273 Action
= CallSignalHandler(&Info
);
276 Action
= osl_Signal_ActKillApp
;
281 case osl_Signal_ActCallNextHdl
:
282 return (EXCEPTION_CONTINUE_SEARCH
);
284 case osl_Signal_ActAbortApp
:
285 return (EXCEPTION_EXECUTE_HANDLER
);
287 case osl_Signal_ActKillApp
:
288 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
295 return (EXCEPTION_CONTINUE_EXECUTION
);
298 /*****************************************************************************/
299 /* osl_addSignalHandler */
300 /*****************************************************************************/
301 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
303 oslSignalHandlerImpl
* pHandler
;
305 OSL_ASSERT(Handler
!= NULL
);
308 bInitSignal
= InitSignal();
310 pHandler
= reinterpret_cast< oslSignalHandlerImpl
* >( calloc( 1, sizeof(oslSignalHandlerImpl
) ) );
312 if (pHandler
!= NULL
)
314 pHandler
->Handler
= Handler
;
315 pHandler
->pData
= pData
;
317 osl_acquireMutex(SignalListMutex
);
319 pHandler
->pNext
= SignalList
;
320 SignalList
= pHandler
;
322 osl_releaseMutex(SignalListMutex
);
330 /*****************************************************************************/
331 /* osl_removeSignalHandler */
332 /*****************************************************************************/
333 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
335 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
337 OSL_ASSERT(Handler
!= NULL
);
340 bInitSignal
= InitSignal();
342 osl_acquireMutex(SignalListMutex
);
344 pHandler
= SignalList
;
346 while (pHandler
!= NULL
)
348 if (pHandler
== Handler
)
351 pPrevious
->pNext
= pHandler
->pNext
;
353 SignalList
= pHandler
->pNext
;
355 osl_releaseMutex(SignalListMutex
);
357 if (SignalList
== NULL
)
358 bInitSignal
= DeInitSignal();
365 pPrevious
= pHandler
;
366 pHandler
= pHandler
->pNext
;
369 osl_releaseMutex(SignalListMutex
);
374 /*****************************************************************************/
375 /* osl_raiseSignal */
376 /*****************************************************************************/
377 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
380 oslSignalAction Action
;
383 bInitSignal
= InitSignal();
385 osl_acquireMutex(SignalListMutex
);
387 Info
.Signal
= osl_Signal_User
;
388 Info
.UserSignal
= UserSignal
;
389 Info
.UserData
= UserData
;
391 Action
= CallSignalHandler(&Info
);
393 osl_releaseMutex(SignalListMutex
);
398 /*****************************************************************************/
399 /* osl_setErrorReporting */
400 /*****************************************************************************/
401 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
403 sal_Bool bOld
= bErrorReportingEnabled
;
404 bErrorReportingEnabled
= bEnable
;
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */