xref: /aoo4110/main/sal/osl/w32/dllentry.c (revision b1cdbd2c)
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
__do_global_dtors(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
__do_global_ctors(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
__main(void)152 __main (void)
153 {
154   if (!initialized)
155     {
156       initialized = 1;
157       do_startup();
158       __do_global_ctors ();
159     }
160 }
161 
do_startup(void)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