1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 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. 14 * 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). 20 * 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. 25 * 26 ************************************************************************/ 27 28 #ifdef _MSC_VER 29 #pragma warning(push,1) /* disable warnings within system headers */ 30 #endif 31 #include <windows.h> 32 #ifdef _MSC_VER 33 #pragma warning(pop) 34 #endif 35 #include <tlhelp32.h> 36 #include <systools/win32/uwinapi.h> 37 #include <winsock.h> 38 #include <osl/diagnose.h> 39 #include <sal/types.h> 40 #include <float.h> 41 42 #include <osl/diagnose.h> 43 #include <osl/mutex.h> 44 #include <sal/types.h> 45 46 //------------------------------------------------------------------------------ 47 // externals 48 //------------------------------------------------------------------------------ 49 50 extern DWORD g_dwTLSTextEncodingIndex; 51 extern void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void); 52 extern CRITICAL_SECTION g_ThreadKeyListCS; 53 extern oslMutex g_Mutex; 54 extern oslMutex g_CurrentDirectoryMutex; 55 56 extern void rtl_locale_fini (void); 57 extern void rtl_memory_fini (void); 58 extern void rtl_cache_fini (void); 59 extern void rtl_arena_fini (void); 60 61 #ifdef __MINGW32__ 62 63 typedef void (*func_ptr) (void); 64 extern func_ptr __CTOR_LIST__[]; 65 extern func_ptr __DTOR_LIST__[]; 66 67 static void do_startup(void); 68 static void do_cleanup(void); 69 70 #else 71 72 /* 73 This is needed because DllMain is called after static constructors. A DLL's 74 startup and shutdown sequence looks like this: 75 76 _pRawDllMain() 77 _CRT_INIT() 78 DllMain() 79 .... 80 DllMain() 81 _CRT_INIT() 82 _pRawDllMain() 83 84 */ 85 86 static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); 87 extern BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID) = _RawDllMain; 88 89 #endif 90 91 //------------------------------------------------------------------------------ 92 // globales 93 //------------------------------------------------------------------------------ 94 95 DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; // remember plattform 96 97 //------------------------------------------------------------------------------ 98 // DllMain 99 //------------------------------------------------------------------------------ 100 #ifdef _M_IX86 101 int osl_isSingleCPU = 0; 102 #endif 103 104 #ifdef __MINGW32__ 105 106 void 107 __do_global_dtors (void) 108 { 109 static func_ptr *p = __DTOR_LIST__ + 1; 110 111 /* 112 * Call each destructor in the destructor list until a null pointer 113 * is encountered. 114 */ 115 while (*p) 116 { 117 (*(p)) (); 118 p++; 119 } 120 } 121 122 void 123 __do_global_ctors (void) 124 { 125 unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; 126 unsigned i; 127 128 /* 129 * If the first entry in the constructor list is -1 then the list 130 * is terminated with a null entry. Otherwise the first entry was 131 * the number of pointers in the list. 132 */ 133 if (nptrs == -1) 134 { 135 for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++) 136 ; 137 } 138 139 /* 140 * Go through the list backwards calling constructors. 141 */ 142 for (i = nptrs; i >= 1; i--) 143 { 144 __CTOR_LIST__[i] (); 145 } 146 147 /* 148 * Register the destructors for processing on exit. 149 */ 150 atexit (__do_global_dtors); 151 } 152 153 static int initialized = 0; 154 155 void 156 __main (void) 157 { 158 if (!initialized) 159 { 160 initialized = 1; 161 do_startup(); 162 __do_global_ctors (); 163 } 164 } 165 166 static void do_startup( void ) 167 { 168 #else 169 static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) 170 { 171 (void)hinstDLL; /* avoid warnings */ 172 (void)lpvReserved; /* avoid warnings */ 173 174 switch (fdwReason) 175 { 176 case DLL_PROCESS_ATTACH: 177 { 178 #endif 179 OSVERSIONINFO aInfo; 180 181 #ifdef _M_IX86 182 SYSTEM_INFO SystemInfo; 183 184 GetSystemInfo(&SystemInfo); 185 186 /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system 187 * 188 * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount() 189 * comes with a cost and is especially expensive on pre HT x86 single processor 190 * systems, where it isn't needed at all. 191 */ 192 if ( SystemInfo.dwNumberOfProcessors == 1 ) { 193 osl_isSingleCPU = 1; 194 } 195 #endif 196 /* Suppress file error messages from system like "Floppy A: not inserted" */ 197 SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS ); 198 199 /* initialize global mutex */ 200 g_Mutex = osl_createMutex(); 201 202 /* initialize "current directory" mutex */ 203 g_CurrentDirectoryMutex = osl_createMutex(); 204 205 206 /* initialize Win9x unicode functions */ 207 aInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); 208 209 if ( GetVersionEx(&aInfo) ) 210 g_dwPlatformId = aInfo.dwPlatformId; 211 212 g_dwTLSTextEncodingIndex = TlsAlloc(); 213 InitializeCriticalSection( &g_ThreadKeyListCS ); 214 215 //We disable floating point exceptions. This is the usual state at program startup 216 //but on Windows 98 and ME this is not always the case. 217 _control87(_MCW_EM, _MCW_EM); 218 #ifdef __MINGW32__ 219 atexit(do_cleanup); 220 } 221 222 void do_cleanup( void ) 223 { 224 #else 225 break; 226 } 227 228 case DLL_PROCESS_DETACH: 229 #endif 230 231 WSACleanup( ); 232 233 TlsFree( g_dwTLSTextEncodingIndex ); 234 DeleteCriticalSection( &g_ThreadKeyListCS ); 235 236 osl_destroyMutex( g_Mutex ); 237 238 osl_destroyMutex( g_CurrentDirectoryMutex ); 239 240 #ifndef __MINGW32__ 241 242 /* 243 244 On a product build memory management finalization might 245 cause a crash without assertion (assertions off) if heap is 246 corrupted. But a crash report won't help here because at 247 this point all other threads have been terminated and only 248 ntdll is on the stack. No chance to find the reason for the 249 corrupted heap if so. 250 251 So annoying the user with a crash report is completly useless. 252 253 */ 254 255 #ifndef DBG_UTIL 256 __try 257 #endif 258 { 259 /* cleanup locale hashtable */ 260 rtl_locale_fini(); 261 262 /* finalize memory management */ 263 rtl_memory_fini(); 264 rtl_cache_fini(); 265 rtl_arena_fini(); 266 } 267 #ifndef DBG_UTIL 268 __except( EXCEPTION_EXECUTE_HANDLER ) 269 { 270 } 271 #endif 272 break; 273 } 274 275 return TRUE; 276 #endif 277 } 278 279 static DWORD GetParentProcessId() 280 { 281 DWORD dwParentProcessId = 0; 282 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); 283 284 if ( IsValidHandle( hSnapshot ) ) 285 { 286 PROCESSENTRY32 pe; 287 BOOL fSuccess; 288 289 ZeroMemory( &pe, sizeof(pe) ); 290 pe.dwSize = sizeof(pe); 291 fSuccess = Process32First( hSnapshot, &pe ); 292 293 while( fSuccess ) 294 { 295 if ( GetCurrentProcessId() == pe.th32ProcessID ) 296 { 297 dwParentProcessId = pe.th32ParentProcessID; 298 break; 299 } 300 301 fSuccess = Process32Next( hSnapshot, &pe ); 302 } 303 304 CloseHandle( hSnapshot ); 305 } 306 307 return dwParentProcessId; 308 } 309 310 static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam ) 311 { 312 DWORD dwParentProcessId = (DWORD)lpParam; 313 314 HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId ); 315 if ( IsValidHandle( hParentProcess ) ) 316 { 317 if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) ) 318 { 319 TerminateProcess( GetCurrentProcess(), 0 ); 320 } 321 CloseHandle( hParentProcess ); 322 } 323 return 0; 324 } 325 326 BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) 327 { 328 (void)hinstDLL; /* avoid warning */ 329 (void)lpvReserved; /* avoid warning */ 330 switch (fdwReason) 331 { 332 case DLL_PROCESS_ATTACH: 333 { 334 TCHAR szBuffer[64]; 335 336 // This code will attach the process to it's parent process 337 // if the parent process had set the environment variable. 338 // The corresponding code (setting the environment variable) 339 // is is desktop/win32/source/officeloader.cxx 340 341 342 DWORD dwResult = GetEnvironmentVariable( "ATTACHED_PARENT_PROCESSID", szBuffer, sizeof(szBuffer) ); 343 344 if ( dwResult && dwResult < sizeof(szBuffer) ) 345 { 346 DWORD dwThreadId = 0; 347 348 DWORD dwParentProcessId = (DWORD)atol( szBuffer ); 349 350 if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId ) 351 { 352 // No error check, it works or it does not 353 // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx 354 CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); // 355 } 356 } 357 358 return TRUE; 359 } 360 361 case DLL_THREAD_ATTACH: 362 break; 363 364 case DLL_THREAD_DETACH: 365 _osl_callThreadKeyCallbackOnThreadDetach( ); 366 break; 367 } 368 369 return TRUE; 370 } 371