| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #ifdef _MSC_VER |
| #pragma warning(push,1) /* disable warnings within system headers */ |
| #endif |
| #include <windows.h> |
| #ifdef _MSC_VER |
| #pragma warning(pop) |
| #endif |
| #include <tlhelp32.h> |
| #include <systools/win32/uwinapi.h> |
| #include <winsock.h> |
| #include <osl/diagnose.h> |
| #include <sal/types.h> |
| #include <float.h> |
| |
| #include <osl/diagnose.h> |
| #include <osl/mutex.h> |
| #include <sal/types.h> |
| |
| //------------------------------------------------------------------------------ |
| // externals |
| //------------------------------------------------------------------------------ |
| |
| extern DWORD g_dwTLSTextEncodingIndex; |
| extern void SAL_CALL _osl_callThreadKeyCallbackOnThreadDetach(void); |
| extern CRITICAL_SECTION g_ThreadKeyListCS; |
| extern oslMutex g_Mutex; |
| extern oslMutex g_CurrentDirectoryMutex; |
| |
| extern void rtl_locale_fini (void); |
| extern void rtl_memory_fini (void); |
| extern void rtl_cache_fini (void); |
| extern void rtl_arena_fini (void); |
| |
| #ifdef __MINGW32__ |
| |
| typedef void (*func_ptr) (void); |
| extern func_ptr __CTOR_LIST__[]; |
| extern func_ptr __DTOR_LIST__[]; |
| |
| static void do_startup(void); |
| static void do_cleanup(void); |
| |
| #else |
| |
| /* |
| This is needed because DllMain is called after static constructors. A DLL's |
| startup and shutdown sequence looks like this: |
| |
| _pRawDllMain() |
| _CRT_INIT() |
| DllMain() |
| .... |
| DllMain() |
| _CRT_INIT() |
| _pRawDllMain() |
| |
| */ |
| |
| static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); |
| extern BOOL (WINAPI *_pRawDllMain)(HANDLE, DWORD, LPVOID) = _RawDllMain; |
| |
| #endif |
| |
| //------------------------------------------------------------------------------ |
| // globales |
| //------------------------------------------------------------------------------ |
| |
| DWORD g_dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; // remember plattform |
| |
| //------------------------------------------------------------------------------ |
| // DllMain |
| //------------------------------------------------------------------------------ |
| #ifdef _M_IX86 |
| int osl_isSingleCPU = 0; |
| #endif |
| |
| #ifdef __MINGW32__ |
| |
| void |
| __do_global_dtors (void) |
| { |
| static func_ptr *p = __DTOR_LIST__ + 1; |
| |
| /* |
| * Call each destructor in the destructor list until a null pointer |
| * is encountered. |
| */ |
| while (*p) |
| { |
| (*(p)) (); |
| p++; |
| } |
| } |
| |
| void |
| __do_global_ctors (void) |
| { |
| unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; |
| unsigned i; |
| |
| /* |
| * If the first entry in the constructor list is -1 then the list |
| * is terminated with a null entry. Otherwise the first entry was |
| * the number of pointers in the list. |
| */ |
| if (nptrs == -1) |
| { |
| for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++) |
| ; |
| } |
| |
| /* |
| * Go through the list backwards calling constructors. |
| */ |
| for (i = nptrs; i >= 1; i--) |
| { |
| __CTOR_LIST__[i] (); |
| } |
| |
| /* |
| * Register the destructors for processing on exit. |
| */ |
| atexit (__do_global_dtors); |
| } |
| |
| static int initialized = 0; |
| |
| void |
| __main (void) |
| { |
| if (!initialized) |
| { |
| initialized = 1; |
| do_startup(); |
| __do_global_ctors (); |
| } |
| } |
| |
| static void do_startup( void ) |
| { |
| #else |
| static BOOL WINAPI _RawDllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) |
| { |
| (void)hinstDLL; /* avoid warnings */ |
| (void)lpvReserved; /* avoid warnings */ |
| |
| switch (fdwReason) |
| { |
| case DLL_PROCESS_ATTACH: |
| { |
| #endif |
| OSVERSIONINFO aInfo; |
| |
| #ifdef _M_IX86 |
| SYSTEM_INFO SystemInfo; |
| |
| GetSystemInfo(&SystemInfo); |
| |
| /* Determine if we are on a multiprocessor/multicore/HT x86/x64 system |
| * |
| * The lock prefix for atomic operations in osl_[inc|de]crementInterlockedCount() |
| * comes with a cost and is especially expensive on pre HT x86 single processor |
| * systems, where it isn't needed at all. |
| */ |
| if ( SystemInfo.dwNumberOfProcessors == 1 ) { |
| osl_isSingleCPU = 1; |
| } |
| #endif |
| /* Suppress file error messages from system like "Floppy A: not inserted" */ |
| SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS ); |
| |
| /* initialize global mutex */ |
| g_Mutex = osl_createMutex(); |
| |
| /* initialize "current directory" mutex */ |
| g_CurrentDirectoryMutex = osl_createMutex(); |
| |
| |
| /* initialize Win9x unicode functions */ |
| aInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); |
| |
| if ( GetVersionEx(&aInfo) ) |
| g_dwPlatformId = aInfo.dwPlatformId; |
| |
| g_dwTLSTextEncodingIndex = TlsAlloc(); |
| InitializeCriticalSection( &g_ThreadKeyListCS ); |
| |
| //We disable floating point exceptions. This is the usual state at program startup |
| //but on Windows 98 and ME this is not always the case. |
| _control87(_MCW_EM, _MCW_EM); |
| #ifdef __MINGW32__ |
| atexit(do_cleanup); |
| } |
| |
| void do_cleanup( void ) |
| { |
| #else |
| break; |
| } |
| |
| case DLL_PROCESS_DETACH: |
| #endif |
| |
| WSACleanup( ); |
| |
| TlsFree( g_dwTLSTextEncodingIndex ); |
| DeleteCriticalSection( &g_ThreadKeyListCS ); |
| |
| osl_destroyMutex( g_Mutex ); |
| |
| osl_destroyMutex( g_CurrentDirectoryMutex ); |
| |
| #ifndef __MINGW32__ |
| |
| /* |
| |
| On a product build memory management finalization might |
| cause a crash without assertion (assertions off) if heap is |
| corrupted. But a crash report won't help here because at |
| this point all other threads have been terminated and only |
| ntdll is on the stack. No chance to find the reason for the |
| corrupted heap if so. |
| |
| So annoying the user with a crash report is completly useless. |
| |
| */ |
| |
| #ifndef DBG_UTIL |
| __try |
| #endif |
| { |
| /* cleanup locale hashtable */ |
| rtl_locale_fini(); |
| |
| /* finalize memory management */ |
| rtl_memory_fini(); |
| rtl_cache_fini(); |
| rtl_arena_fini(); |
| } |
| #ifndef DBG_UTIL |
| __except( EXCEPTION_EXECUTE_HANDLER ) |
| { |
| } |
| #endif |
| break; |
| } |
| |
| return TRUE; |
| #endif |
| } |
| |
| static DWORD GetParentProcessId() |
| { |
| DWORD dwParentProcessId = 0; |
| HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); |
| |
| if ( IsValidHandle( hSnapshot ) ) |
| { |
| PROCESSENTRY32 pe; |
| BOOL fSuccess; |
| |
| ZeroMemory( &pe, sizeof(pe) ); |
| pe.dwSize = sizeof(pe); |
| fSuccess = Process32First( hSnapshot, &pe ); |
| |
| while( fSuccess ) |
| { |
| if ( GetCurrentProcessId() == pe.th32ProcessID ) |
| { |
| dwParentProcessId = pe.th32ParentProcessID; |
| break; |
| } |
| |
| fSuccess = Process32Next( hSnapshot, &pe ); |
| } |
| |
| CloseHandle( hSnapshot ); |
| } |
| |
| return dwParentProcessId; |
| } |
| |
| static DWORD WINAPI ParentMonitorThreadProc( LPVOID lpParam ) |
| { |
| DWORD dwParentProcessId = (DWORD)lpParam; |
| |
| HANDLE hParentProcess = OpenProcess( SYNCHRONIZE, FALSE, dwParentProcessId ); |
| if ( IsValidHandle( hParentProcess ) ) |
| { |
| if ( WAIT_OBJECT_0 == WaitForSingleObject( hParentProcess, INFINITE ) ) |
| { |
| TerminateProcess( GetCurrentProcess(), 0 ); |
| } |
| CloseHandle( hParentProcess ); |
| } |
| return 0; |
| } |
| |
| BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) |
| { |
| (void)hinstDLL; /* avoid warning */ |
| (void)lpvReserved; /* avoid warning */ |
| switch (fdwReason) |
| { |
| case DLL_PROCESS_ATTACH: |
| { |
| TCHAR szBuffer[64]; |
| |
| // This code will attach the process to it's parent process |
| // if the parent process had set the environment variable. |
| // The corresponding code (setting the environment variable) |
| // is is desktop/win32/source/officeloader.cxx |
| |
| |
| DWORD dwResult = GetEnvironmentVariable( "ATTACHED_PARENT_PROCESSID", szBuffer, sizeof(szBuffer) ); |
| |
| if ( dwResult && dwResult < sizeof(szBuffer) ) |
| { |
| DWORD dwThreadId = 0; |
| |
| DWORD dwParentProcessId = (DWORD)atol( szBuffer ); |
| |
| if ( dwParentProcessId && GetParentProcessId() == dwParentProcessId ) |
| { |
| // No error check, it works or it does not |
| // Thread should only be started for headless mode, see desktop/win32/source/officeloader.cxx |
| CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); // |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| case DLL_THREAD_ATTACH: |
| break; |
| |
| case DLL_THREAD_DETACH: |
| _osl_callThreadKeyCallbackOnThreadDetach( ); |
| break; |
| } |
| |
| return TRUE; |
| } |