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