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