merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / w32 / signal.c
blob0a4ecc3442a73c74915137056bee29c8004fa89a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: signal.c,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 /* system headers */
32 #include "system.h"
33 #include <tchar.h>
35 #include <osl/diagnose.h>
36 #include <osl/mutex.h>
37 #include <osl/signal.h>
38 #ifndef __MINGW32__
39 #include <DbgHelp.h>
40 #endif
41 #include <ErrorRep.h>
42 #include <systools/win32/uwinapi.h>
44 typedef struct _oslSignalHandlerImpl
46 oslSignalHandlerFunction Handler;
47 void* pData;
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)
60 HMODULE hFaultRep;
62 SignalListMutex = osl_createMutex();
64 SetUnhandledExceptionFilter(SignalHandlerFunction);
66 hFaultRep = LoadLibrary( "faultrep.dll" );
67 if ( hFaultRep )
69 #ifdef __MINGW32__
70 typedef BOOL (WINAPI *pfn_ADDEREXCLUDEDAPPLICATIONW)(LPCWSTR);
71 #endif
72 pfn_ADDEREXCLUDEDAPPLICATIONW pfn = (pfn_ADDEREXCLUDEDAPPLICATIONW)GetProcAddress( hFaultRep, "AddERExcludedApplicationW" );
73 if ( pfn )
74 pfn( L"SOFFICE.EXE" );
75 FreeLibrary( hFaultRep );
78 return sal_True;
81 static sal_Bool DeInitSignal(void)
83 SetUnhandledExceptionFilter(NULL);
85 osl_destroyMutex(SignalListMutex);
87 return sal_False;
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)
98 break;
100 pHandler = pHandler->pNext;
103 return Action;
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 TCHAR szPath[MAX_PATH];
119 LPTSTR lpFilePart;
120 PROCESS_INFORMATION ProcessInfo;
121 STARTUPINFO StartupInfo;
122 int argi;
124 if ( !bErrorReportingEnabled )
125 return FALSE;
127 /* Check if crash reporter was disabled by command line */
129 for ( argi = 1; argi < __argc; argi++ )
131 if (
132 0 == stricmp( __argv[argi], "-nocrashreport" ) ||
133 0 == stricmp( __argv[argi], "/nocrashreport" )
135 return FALSE;
136 else if (
137 0 == stricmp( __argv[argi], "-autocrashreport" ) ||
138 0 == stricmp( __argv[argi], "/autocrashreport" )
140 fAutoReport = TRUE;
141 else if (
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, '=' );
149 if ( delim )
151 CHAR *lpVariable;
152 CHAR *lpValue;
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 )
160 const char *quote;
162 value++;
163 value_len--;
165 quote = strchr( value, '\"' );
166 if ( quote )
167 value_len = quote - value;
170 lpVariable = _alloca( variable_len + 1 );
171 memcpy( lpVariable, variable, variable_len );
172 lpVariable[variable_len] = 0;
174 lpValue = _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, MAX_PATH, szPath, &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 szPath,
192 GetCurrentProcessId(),
193 lpEP,
194 GetCurrentThreadId(),
195 fAutoReport ? _T(" -noui -send") : _T(" -noui") );
197 if (
198 CreateProcess(
199 NULL,
200 szBuffer,
201 NULL,
202 NULL,
203 FALSE,
204 #ifdef UNICODE
205 CREATE_UNICODE_ENVIRONMENT,
206 #else
208 #endif
209 NULL, NULL, &StartupInfo, &ProcessInfo )
212 DWORD dwExitCode;
214 WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
215 if ( GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) && 0 == dwExitCode )
217 fSuccess = TRUE;
222 return fSuccess;
225 /*****************************************************************************/
226 /* SignalHandlerFunction */
227 /*****************************************************************************/
229 static BOOL WINAPI IsWin95A(void)
231 OSVERSIONINFO ovi;
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 */
245 return TRUE;
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;
255 oslSignalInfo Info;
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;
270 break;
272 case EXCEPTION_INT_DIVIDE_BY_ZERO:
273 Info.Signal = osl_Signal_IntegerDivideByZero;
274 bRaiseCrashReporter = sal_True;
275 break;
277 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
278 Info.Signal = osl_Signal_FloatDivideByZero;
279 bRaiseCrashReporter = sal_True;
280 break;
282 case EXCEPTION_BREAKPOINT:
283 Info.Signal = osl_Signal_DebugBreak;
284 break;
286 default:
287 Info.Signal = osl_Signal_System;
288 bRaiseCrashReporter = sal_True;
289 break;
292 if ( !bNested )
294 bNested = sal_True;
296 if ( bRaiseCrashReporter && ReportCrash( lpEP ) || IsWin95A() )
298 CallSignalHandler(&Info);
299 Action = osl_Signal_ActKillApp;
301 else
302 Action = CallSignalHandler(&Info);
304 else
305 Action = osl_Signal_ActKillApp;
308 switch ( Action )
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);
318 exit(255);
319 break;
322 return (EXCEPTION_CONTINUE_EXECUTION);
325 /*****************************************************************************/
326 /* osl_addSignalHandler */
327 /*****************************************************************************/
328 oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
330 oslSignalHandlerImpl* pHandler;
332 OSL_ASSERT(Handler != NULL);
334 if (! bInitSignal)
335 bInitSignal = InitSignal();
337 pHandler = calloc(1, sizeof(oslSignalHandlerImpl));
339 if (pHandler != NULL)
341 pHandler->Handler = Handler;
342 pHandler->pData = pData;
344 osl_acquireMutex(SignalListMutex);
346 pHandler->pNext = SignalList;
347 SignalList = pHandler;
349 osl_releaseMutex(SignalListMutex);
351 return (pHandler);
354 return (NULL);
357 /*****************************************************************************/
358 /* osl_removeSignalHandler */
359 /*****************************************************************************/
360 sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
362 oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
364 OSL_ASSERT(Handler != NULL);
366 if (! bInitSignal)
367 bInitSignal = InitSignal();
369 osl_acquireMutex(SignalListMutex);
371 pHandler = SignalList;
373 while (pHandler != NULL)
375 if (pHandler == Handler)
377 if (pPrevious)
378 pPrevious->pNext = pHandler->pNext;
379 else
380 SignalList = pHandler->pNext;
382 osl_releaseMutex(SignalListMutex);
384 if (SignalList == NULL)
385 bInitSignal = DeInitSignal();
387 free(pHandler);
389 return (sal_True);
392 pPrevious = pHandler;
393 pHandler = pHandler->pNext;
396 osl_releaseMutex(SignalListMutex);
398 return (sal_False);
401 /*****************************************************************************/
402 /* osl_raiseSignal */
403 /*****************************************************************************/
404 oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
406 oslSignalInfo Info;
407 oslSignalAction Action;
409 if (! bInitSignal)
410 bInitSignal = InitSignal();
412 osl_acquireMutex(SignalListMutex);
414 Info.Signal = osl_Signal_User;
415 Info.UserSignal = UserSignal;
416 Info.UserData = UserData;
418 Action = CallSignalHandler(&Info);
420 osl_releaseMutex(SignalListMutex);
422 return (Action);
425 /*****************************************************************************/
426 /* osl_setErrorReporting */
427 /*****************************************************************************/
428 sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
430 sal_Bool bOld = bErrorReportingEnabled;
431 bErrorReportingEnabled = bEnable;
433 return bOld;