[MINGW]
[reactos.git] / reactos / lib / 3rdparty / mingw / crtexe.c
1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6
7 #undef CRTDLL
8 #ifndef _DLL
9 #define _DLL
10 #endif
11
12 #define SPECIAL_CRTEXE
13
14 #include <oscalls.h>
15 #include <internal.h>
16 #include <process.h>
17 #include <signal.h>
18 #include <math.h>
19 #include <stdlib.h>
20 #include <tchar.h>
21 #include <sect_attribs.h>
22 #include <locale.h>
23
24 #ifndef __winitenv
25 extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv);
26 #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv))
27 #endif
28
29 #ifndef __initenv
30 extern char *** __MINGW_IMP_SYMBOL(__initenv);
31 #define __initenv (* __MINGW_IMP_SYMBOL(__initenv))
32 #endif
33
34 /* Hack, for bug in ld. Will be removed soon. */
35 #define __ImageBase __MINGW_LSYMBOL(_image_base__)
36 /* This symbol is defined by ld. */
37 extern IMAGE_DOS_HEADER __ImageBase;
38
39 extern void _fpreset (void);
40 #define SPACECHAR _T(' ')
41 #define DQUOTECHAR _T('\"')
42
43 __declspec(dllimport) void __setusermatherr(int (__cdecl *)(struct _exception *));
44
45 extern int * __MINGW_IMP_SYMBOL(_fmode);
46 extern int * __MINGW_IMP_SYMBOL(_commode);
47
48 #undef _fmode
49 extern int _fmode;
50 extern int * __MINGW_IMP_SYMBOL(_commode);
51 #define _commode (* __MINGW_IMP_SYMBOL(_commode))
52 extern int _dowildcard;
53
54 int _MINGW_INSTALL_DEBUG_MATHERR __attribute__((weak)) = 0;
55 extern int __defaultmatherr;
56 extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
57
58 static int __cdecl check_managed_app (void);
59
60 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
61 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];
62 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
63 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];
64
65 /* TLS initialization hook. */
66 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
67
68 extern _PVFV *__onexitbegin;
69 extern _PVFV *__onexitend;
70
71 extern int mingw_app_type;
72
73 HINSTANCE __mingw_winmain_hInstance;
74 _TCHAR *__mingw_winmain_lpCmdLine;
75 DWORD __mingw_winmain_nShowCmd;
76
77 static int argc;
78 #ifdef WPRFLAG
79 extern void __main(void);
80 static wchar_t **argv;
81 static wchar_t **envp;
82 #else
83 static char **argv;
84 static char **envp;
85 #endif
86
87 static int argret;
88 static int mainret=0;
89 static int managedapp;
90 static int has_cctor = 0;
91 static _startupinfo startinfo;
92 static LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
93
94 extern void _pei386_runtime_relocator (void);
95 static long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
96 #ifdef WPRFLAG
97 static void duplicate_ppstrings (int ac, wchar_t ***av);
98 #else
99 static void duplicate_ppstrings (int ac, char ***av);
100 #endif
101
102 static int __cdecl pre_c_init (void);
103 static void __cdecl pre_cpp_init (void);
104 static void __cdecl __mingw_prepare_except_for_msvcr80_and_higher (void);
105 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init;
106 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init;
107
108 static int __cdecl
109 pre_c_init (void)
110 {
111 managedapp = check_managed_app ();
112 if (mingw_app_type)
113 __set_app_type(_GUI_APP);
114 else
115 __set_app_type (_CONSOLE_APP);
116 __onexitbegin = __onexitend = (_PVFV *) _encode_pointer ((_PVFV *)(-1));
117
118 * __MINGW_IMP_SYMBOL(_fmode) = _fmode;
119 * __MINGW_IMP_SYMBOL(_commode) = _commode;
120
121 #ifdef WPRFLAG
122 _wsetargv();
123 #else
124 _setargv();
125 #endif
126 if (_MINGW_INSTALL_DEBUG_MATHERR)
127 {
128 if (! __defaultmatherr)
129 {
130 __setusermatherr (_matherr);
131 __defaultmatherr = 1;
132 }
133 }
134
135 if (__globallocalestatus == -1)
136 {
137 }
138 return 0;
139 }
140
141 static void __cdecl
142 pre_cpp_init (void)
143 {
144 startinfo.newmode = _newmode;
145
146 #ifdef WPRFLAG
147 argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
148 #else
149 argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
150 #endif
151 }
152
153 static int __tmainCRTStartup (void);
154
155 int WinMainCRTStartup (void);
156
157 int WinMainCRTStartup (void)
158 {
159 mingw_app_type = 1;
160 __security_init_cookie ();
161 return __tmainCRTStartup ();
162 }
163
164 int mainCRTStartup (void);
165
166 #ifdef _WIN64
167 int __mingw_init_ehandler (void);
168 #endif
169
170 int mainCRTStartup (void)
171 {
172 mingw_app_type = 0;
173 __security_init_cookie ();
174 return __tmainCRTStartup ();
175 }
176
177 static
178 __declspec(noinline) int
179 __tmainCRTStartup (void)
180 {
181 _TCHAR *lpszCommandLine = NULL;
182 STARTUPINFO StartupInfo;
183 WINBOOL inDoubleQuote = FALSE;
184 memset (&StartupInfo, 0, sizeof (STARTUPINFO));
185
186 if (mingw_app_type)
187 GetStartupInfo (&StartupInfo);
188 {
189 void *lock_free = NULL;
190 void *fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase;
191 int nested = FALSE;
192 while((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
193 fiberid, 0)) != 0)
194 {
195 if (lock_free == fiberid)
196 {
197 nested = TRUE;
198 break;
199 }
200 Sleep(1000);
201 }
202 if (__native_startup_state == __initializing)
203 {
204 _amsg_exit (31);
205 }
206 else if (__native_startup_state == __uninitialized)
207 {
208 __native_startup_state = __initializing;
209 _initterm ((_PVFV *)(void *)__xi_a, (_PVFV *)(void *) __xi_z);
210 }
211 else
212 has_cctor = 1;
213
214 if (__native_startup_state == __initializing)
215 {
216 _initterm (__xc_a, __xc_z);
217 __native_startup_state = __initialized;
218 }
219 _ASSERTE(__native_startup_state == __initialized);
220 if (! nested)
221 (VOID)InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
222
223 if (__dyn_tls_init_callback != NULL)
224 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
225
226 _pei386_runtime_relocator ();
227 __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler);
228 #ifdef _WIN64
229 __mingw_init_ehandler ();
230 #endif
231 __mingw_prepare_except_for_msvcr80_and_higher ();
232
233 _fpreset ();
234
235 if (mingw_app_type)
236 {
237 #ifdef WPRFLAG
238 lpszCommandLine = (_TCHAR *) _wcmdln;
239 #else
240 lpszCommandLine = (char *) _acmdln;
241 #endif
242 while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine&&inDoubleQuote))
243 {
244 if (*lpszCommandLine == DQUOTECHAR)
245 inDoubleQuote = !inDoubleQuote;
246 #ifdef _MBCS
247 if (_ismbblead (*lpszCommandLine))
248 {
249 if (*lpszCommandLine)
250 lpszCommandLine++;
251 }
252 #endif
253 ++lpszCommandLine;
254 }
255 while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
256 lpszCommandLine++;
257
258 __mingw_winmain_hInstance = (HINSTANCE) &__ImageBase;
259 __mingw_winmain_lpCmdLine = lpszCommandLine;
260 __mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ?
261 StartupInfo.wShowWindow : SW_SHOWDEFAULT;
262 }
263 duplicate_ppstrings (argc, &argv);
264 #ifdef WPRFLAG
265 __winitenv = envp;
266 /* C++ initialization.
267 gcc inserts this call automatically for a function called main, but not for wmain. */
268 __main ();
269 mainret = wmain (argc, argv, envp);
270 #else
271 __initenv = envp;
272 mainret = main (argc, argv, envp);
273 #endif
274 if (!managedapp)
275 exit (mainret);
276
277 if (has_cctor == 0)
278 _cexit ();
279 }
280 return mainret;
281 }
282
283 extern int mingw_initltsdrot_force;
284 extern int mingw_initltsdyn_force;
285 extern int mingw_initltssuo_force;
286 extern int mingw_initcharmax;
287
288 static int __cdecl
289 check_managed_app (void)
290 {
291 PIMAGE_DOS_HEADER pDOSHeader;
292 PIMAGE_NT_HEADERS pPEHeader;
293 PIMAGE_OPTIONAL_HEADER32 pNTHeader32;
294 PIMAGE_OPTIONAL_HEADER64 pNTHeader64;
295
296 /* Force to be linked. */
297 mingw_initltsdrot_force=1;
298 mingw_initltsdyn_force=1;
299 mingw_initltssuo_force=1;
300 mingw_initcharmax=1;
301
302 pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase;
303 if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
304 return 0;
305
306 pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew);
307 if (pPEHeader->Signature != IMAGE_NT_SIGNATURE)
308 return 0;
309
310 pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader;
311 switch (pNTHeader32->Magic)
312 {
313 case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
314 if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
315 return 0;
316 return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
317 case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
318 pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32;
319 if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
320 return 0;
321 return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
322 }
323 return 0;
324 }
325
326 static long CALLBACK
327 _gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
328 {
329 void (*old_handler) (int);
330 long action = EXCEPTION_CONTINUE_SEARCH;
331 int reset_fpu = 0;
332
333 switch (exception_data->ExceptionRecord->ExceptionCode)
334 {
335 case EXCEPTION_ACCESS_VIOLATION:
336 /* test if the user has set SIGSEGV */
337 old_handler = signal (SIGSEGV, SIG_DFL);
338 if (old_handler == SIG_IGN)
339 {
340 /* this is undefined if the signal was raised by anything other
341 than raise (). */
342 signal (SIGSEGV, SIG_IGN);
343 action = EXCEPTION_CONTINUE_EXECUTION;
344 }
345 else if (old_handler != SIG_DFL)
346 {
347 /* This means 'old' is a user defined function. Call it */
348 (*old_handler) (SIGSEGV);
349 action = EXCEPTION_CONTINUE_EXECUTION;
350 }
351 break;
352
353 case EXCEPTION_ILLEGAL_INSTRUCTION:
354 case EXCEPTION_PRIV_INSTRUCTION:
355 /* test if the user has set SIGILL */
356 old_handler = signal (SIGILL, SIG_DFL);
357 if (old_handler == SIG_IGN)
358 {
359 /* this is undefined if the signal was raised by anything other
360 than raise (). */
361 signal (SIGILL, SIG_IGN);
362 action = EXCEPTION_CONTINUE_EXECUTION;
363 }
364 else if (old_handler != SIG_DFL)
365 {
366 /* This means 'old' is a user defined function. Call it */
367 (*old_handler) (SIGILL);
368 action = EXCEPTION_CONTINUE_EXECUTION;
369 }
370 break;
371
372 case EXCEPTION_FLT_INVALID_OPERATION:
373 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
374 case EXCEPTION_FLT_DENORMAL_OPERAND:
375 case EXCEPTION_FLT_OVERFLOW:
376 case EXCEPTION_FLT_UNDERFLOW:
377 case EXCEPTION_FLT_INEXACT_RESULT:
378 reset_fpu = 1;
379 /* fall through. */
380
381 case EXCEPTION_INT_DIVIDE_BY_ZERO:
382 /* test if the user has set SIGFPE */
383 old_handler = signal (SIGFPE, SIG_DFL);
384 if (old_handler == SIG_IGN)
385 {
386 signal (SIGFPE, SIG_IGN);
387 if (reset_fpu)
388 _fpreset ();
389 action = EXCEPTION_CONTINUE_EXECUTION;
390 }
391 else if (old_handler != SIG_DFL)
392 {
393 /* This means 'old' is a user defined function. Call it */
394 (*old_handler) (SIGFPE);
395 action = EXCEPTION_CONTINUE_EXECUTION;
396 }
397 break;
398 #ifdef _WIN64
399 case EXCEPTION_DATATYPE_MISALIGNMENT:
400 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
401 case EXCEPTION_FLT_STACK_CHECK:
402 case EXCEPTION_INT_OVERFLOW:
403 case EXCEPTION_INVALID_HANDLE:
404 /*case EXCEPTION_POSSIBLE_DEADLOCK: */
405 action = EXCEPTION_CONTINUE_EXECUTION;
406 break;
407 #endif
408 default:
409 break;
410 }
411
412 if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
413 action = (*__mingw_oldexcpt_handler)(exception_data);
414 return action;
415 }
416
417 #ifdef WPRFLAG
418 static size_t wbytelen(const wchar_t *p)
419 {
420 size_t ret = 1;
421 while (*p!=0) {
422 ret++,++p;
423 }
424 return ret*2;
425 }
426 static void duplicate_ppstrings (int ac, wchar_t ***av)
427 {
428 wchar_t **avl;
429 int i;
430 wchar_t **n = (wchar_t **) malloc (sizeof (wchar_t *) * (ac + 1));
431
432 avl=*av;
433 for (i=0; i < ac; i++)
434 {
435 int l = wbytelen (avl[i]);
436 n[i] = (wchar_t *) malloc (l);
437 memcpy (n[i], avl[i], l);
438 }
439 n[i] = NULL;
440 *av = n;
441 }
442 #else
443 static void duplicate_ppstrings (int ac, char ***av)
444 {
445 char **avl;
446 int i;
447 char **n = (char **) malloc (sizeof (char *) * (ac + 1));
448
449 avl=*av;
450 for (i=0; i < ac; i++)
451 {
452 int l = strlen (avl[i]) + 1;
453 n[i] = (char *) malloc (l);
454 memcpy (n[i], avl[i], l);
455 }
456 n[i] = NULL;
457 *av = n;
458 }
459 #endif
460
461 static void
462 __mingw_invalidParameterHandler (const wchar_t *expression __attribute__ ((__unused__)),
463 const wchar_t *function __attribute__ ((__unused__)),
464 const wchar_t *file __attribute__ ((__unused__)),
465 unsigned int line __attribute__ ((__unused__)),
466 uintptr_t pReserved __attribute__ ((__unused__)))
467 {
468 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
469 wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
470 wprintf(L"Expression: %s\n", expression);
471 #endif
472 }
473
474 static void __cdecl
475 __mingw_prepare_except_for_msvcr80_and_higher (void)
476 {
477 _invalid_parameter_handler (*fIPH)(_invalid_parameter_handler) = NULL;
478 HMODULE hmsv = GetModuleHandleA ("msvcr80.dll");
479 if(!hmsv)
480 hmsv = GetModuleHandleA ("msvcr70.dll");
481 if (!hmsv)
482 hmsv = GetModuleHandleA ("msvcrt.dll");
483 if (!hmsv)
484 hmsv = LoadLibraryA ("msvcrt.dll");
485 if (!hmsv)
486 return;
487 fIPH = (_invalid_parameter_handler (*)(_invalid_parameter_handler))
488 GetProcAddress (hmsv, "_set_invalid_parameter_handler");
489 if (fIPH)
490 (*fIPH)(__mingw_invalidParameterHandler);
491 }