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 platform
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] != NULL; 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 completely 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