1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 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 #if defined(__SEH__) && (!defined(__clang__) || __clang_major__ >= 7)
25 #define SEH_INLINE_ASM
26 #endif
27
28 #ifndef __winitenv
29 extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv);
30 #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv))
31 #endif
32
33 #if !defined(__initenv)
34 extern char *** __MINGW_IMP_SYMBOL(__initenv);
35 #define __initenv (* __MINGW_IMP_SYMBOL(__initenv))
36 #endif
37
38 /* Hack, for bug in ld. Will be removed soon. */
39 #if defined(__GNUC__)
40 #define __ImageBase __MINGW_LSYMBOL(_image_base__)
41 #endif
42 /* This symbol is defined by ld. */
43 extern IMAGE_DOS_HEADER __ImageBase;
44
45 extern void _fpreset (void);
46 #define SPACECHAR _T(' ')
47 #define DQUOTECHAR _T('\"')
48
49 int *__cdecl __p__commode(void);
50
51 #undef _fmode
52 extern int _fmode;
53 extern int _commode;
54 extern int _dowildcard;
55
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
66 /* TLS initialization hook. */
67 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
68
69 extern int mingw_app_type;
70
71 HINSTANCE __mingw_winmain_hInstance;
72 _TCHAR *__mingw_winmain_lpCmdLine;
73 DWORD __mingw_winmain_nShowCmd = SW_SHOWDEFAULT;
74
75 static int argc;
76 extern void __main(void);
77 #ifdef WPRFLAG
78 static wchar_t **argv;
79 static wchar_t **envp;
80 #else
81 static char **argv;
82 static char **envp;
83 #endif
84
85 static int argret;
86 static int mainret=0;
87 static int managedapp;
88 static int has_cctor = 0;
89 static _startupinfo startinfo;
90 extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler;
91
92 extern void _pei386_runtime_relocator (void);
93 long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
94 #ifdef WPRFLAG
95 static void duplicate_ppstrings (int ac, wchar_t ***av);
96 #else
97 static void duplicate_ppstrings (int ac, char ***av);
98 #endif
99
100 static int __cdecl pre_c_init (void);
101 static void __cdecl pre_cpp_init (void);
102 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init;
103 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init;
104
105 extern int _MINGW_INSTALL_DEBUG_MATHERR;
106
107 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
108 #define __UNUSED_PARAM_1(x) x
109 #else
110 #define __UNUSED_PARAM_1 __UNUSED_PARAM
111 #endif
112 static void
__mingw_invalidParameterHandler(const wchar_t * __UNUSED_PARAM_1 (expression),const wchar_t * __UNUSED_PARAM_1 (function),const wchar_t * __UNUSED_PARAM_1 (file),unsigned int __UNUSED_PARAM_1 (line),uintptr_t __UNUSED_PARAM (pReserved))113 __mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression),
114 const wchar_t * __UNUSED_PARAM_1(function),
115 const wchar_t * __UNUSED_PARAM_1(file),
116 unsigned int __UNUSED_PARAM_1(line),
117 uintptr_t __UNUSED_PARAM(pReserved))
118 {
119 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
120 wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
121 wprintf(L"Expression: %s\n", expression);
122 #endif
123 }
124
125 static int __cdecl
pre_c_init(void)126 pre_c_init (void)
127 {
128 managedapp = check_managed_app ();
129 if (mingw_app_type)
130 __set_app_type(_GUI_APP);
131 else
132 __set_app_type (_CONSOLE_APP);
133
134 * __p__fmode() = _fmode;
135 * __p__commode() = _commode;
136
137 #ifdef WPRFLAG
138 _wsetargv();
139 #else
140 _setargv();
141 #endif
142 if (_MINGW_INSTALL_DEBUG_MATHERR == 1)
143 {
144 __setusermatherr (_matherr);
145 }
146
147 if (__globallocalestatus == -1)
148 {
149 }
150 return 0;
151 }
152
153 static void __cdecl
pre_cpp_init(void)154 pre_cpp_init (void)
155 {
156 startinfo.newmode = _newmode;
157
158 #ifdef WPRFLAG
159 argret = __wgetmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
160 #else
161 argret = __getmainargs(&argc,&argv,&envp,_dowildcard,&startinfo);
162 #endif
163 }
164
165 static int __tmainCRTStartup (void);
166
167 int WinMainCRTStartup (void);
168
WinMainCRTStartup(void)169 int WinMainCRTStartup (void)
170 {
171 int ret = 255;
172 #ifdef SEH_INLINE_ASM
173 asm ("\t.l_startw:\n");
174 #endif
175 mingw_app_type = 1;
176 ret = __tmainCRTStartup ();
177 #ifdef SEH_INLINE_ASM
178 asm ("\tnop\n"
179 "\t.l_endw: nop\n"
180 "\t.seh_handler __C_specific_handler, @except\n"
181 "\t.seh_handlerdata\n"
182 "\t.long 1\n"
183 "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
184 "\t.text");
185 #endif
186 return ret;
187 }
188
189 int mainCRTStartup (void);
190
191 #if defined(__x86_64__) && !defined(__SEH__)
192 int __mingw_init_ehandler (void);
193 #endif
194
mainCRTStartup(void)195 int mainCRTStartup (void)
196 {
197 int ret = 255;
198 #ifdef SEH_INLINE_ASM
199 asm ("\t.l_start:\n");
200 #endif
201 mingw_app_type = 0;
202 ret = __tmainCRTStartup ();
203 #ifdef SEH_INLINE_ASM
204 asm ("\tnop\n"
205 "\t.l_end: nop\n"
206 "\t.seh_handler __C_specific_handler, @except\n"
207 "\t.seh_handlerdata\n"
208 "\t.long 1\n"
209 "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n"
210 "\t.text");
211 #endif
212 return ret;
213 }
214
215 static
216 #if defined(__i386__) || defined(_X86_)
217 /* We need to make sure that we align the stack to 16 bytes for the sake of SSE
218 opts in main or in functions called main. */
219 __attribute__((force_align_arg_pointer))
220 #endif
221 __declspec(noinline) int
__tmainCRTStartup(void)222 __tmainCRTStartup (void)
223 {
224 _TCHAR *lpszCommandLine = NULL;
225 STARTUPINFO StartupInfo;
226 WINBOOL inDoubleQuote = FALSE;
227 memset (&StartupInfo, 0, sizeof (STARTUPINFO));
228
229 if (mingw_app_type)
230 GetStartupInfo (&StartupInfo);
231 {
232 void *lock_free = NULL;
233 void *fiberid = ((PNT_TIB)NtCurrentTeb())->StackBase;
234 int nested = FALSE;
235 while((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
236 fiberid, 0)) != 0)
237 {
238 if (lock_free == fiberid)
239 {
240 nested = TRUE;
241 break;
242 }
243 Sleep(1000);
244 }
245 if (__native_startup_state == __initializing)
246 {
247 _amsg_exit (31);
248 }
249 else if (__native_startup_state == __uninitialized)
250 {
251 __native_startup_state = __initializing;
252 _initterm ((_PVFV *)(void *)__xi_a, (_PVFV *)(void *) __xi_z);
253 }
254 else
255 has_cctor = 1;
256
257 if (__native_startup_state == __initializing)
258 {
259 _initterm (__xc_a, __xc_z);
260 __native_startup_state = __initialized;
261 }
262 _ASSERTE(__native_startup_state == __initialized);
263 if (! nested)
264 (VOID)InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
265
266 if (__dyn_tls_init_callback != NULL)
267 __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
268
269 _pei386_runtime_relocator ();
270 __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler);
271 #if defined(__x86_64__) && !defined(__SEH__)
272 __mingw_init_ehandler ();
273 #endif
274 _set_invalid_parameter_handler (__mingw_invalidParameterHandler);
275
276 _fpreset ();
277
278 __mingw_winmain_hInstance = (HINSTANCE) &__ImageBase;
279
280 #ifdef WPRFLAG
281 lpszCommandLine = (_TCHAR *) _wcmdln;
282 #else
283 lpszCommandLine = (char *) _acmdln;
284 #endif
285
286 if (lpszCommandLine)
287 {
288 while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine && inDoubleQuote))
289 {
290 if (*lpszCommandLine == DQUOTECHAR)
291 inDoubleQuote = !inDoubleQuote;
292 #ifdef _MBCS
293 if (_ismbblead (*lpszCommandLine))
294 {
295 if (lpszCommandLine[1])
296 ++lpszCommandLine;
297 }
298 #endif
299 ++lpszCommandLine;
300 }
301 while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
302 lpszCommandLine++;
303
304 __mingw_winmain_lpCmdLine = lpszCommandLine;
305 }
306
307 if (mingw_app_type)
308 {
309 __mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ?
310 StartupInfo.wShowWindow : SW_SHOWDEFAULT;
311 }
312 duplicate_ppstrings (argc, &argv);
313 __main ();
314 #ifdef WPRFLAG
315 __winitenv = envp;
316 /* C++ initialization.
317 gcc inserts this call automatically for a function called main, but not for wmain. */
318 mainret = wmain (argc, argv, envp);
319 #else
320 __initenv = envp;
321 mainret = main (argc, argv, envp);
322 #endif
323 if (!managedapp)
324 exit (mainret);
325
326 if (has_cctor == 0)
327 _cexit ();
328 }
329 return mainret;
330 }
331
332 extern int mingw_initltsdrot_force;
333 extern int mingw_initltsdyn_force;
334 extern int mingw_initltssuo_force;
335 extern int mingw_initcharmax;
336
337 static int __cdecl
check_managed_app(void)338 check_managed_app (void)
339 {
340 PIMAGE_DOS_HEADER pDOSHeader;
341 PIMAGE_NT_HEADERS pPEHeader;
342 PIMAGE_OPTIONAL_HEADER32 pNTHeader32;
343 PIMAGE_OPTIONAL_HEADER64 pNTHeader64;
344
345 /* Force to be linked. */
346 mingw_initltsdrot_force=1;
347 mingw_initltsdyn_force=1;
348 mingw_initltssuo_force=1;
349 mingw_initcharmax=1;
350
351 pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase;
352 if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
353 return 0;
354
355 pPEHeader = (PIMAGE_NT_HEADERS)((char *)pDOSHeader + pDOSHeader->e_lfanew);
356 if (pPEHeader->Signature != IMAGE_NT_SIGNATURE)
357 return 0;
358
359 pNTHeader32 = (PIMAGE_OPTIONAL_HEADER32) &pPEHeader->OptionalHeader;
360 switch (pNTHeader32->Magic)
361 {
362 case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
363 if (pNTHeader32->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
364 return 0;
365 return !! pNTHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
366 case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
367 pNTHeader64 = (PIMAGE_OPTIONAL_HEADER64)pNTHeader32;
368 if (pNTHeader64->NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
369 return 0;
370 return !! pNTHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress;
371 }
372 return 0;
373 }
374
375 #ifdef WPRFLAG
wbytelen(const wchar_t * p)376 static size_t wbytelen(const wchar_t *p)
377 {
378 size_t ret = 1;
379 while (*p!=0) {
380 ret++,++p;
381 }
382 return ret*2;
383 }
duplicate_ppstrings(int ac,wchar_t *** av)384 static void duplicate_ppstrings (int ac, wchar_t ***av)
385 {
386 wchar_t **avl;
387 int i;
388 wchar_t **n = (wchar_t **) malloc (sizeof (wchar_t *) * (ac + 1));
389
390 avl=*av;
391 for (i=0; i < ac; i++)
392 {
393 size_t l = wbytelen (avl[i]);
394 n[i] = (wchar_t *) malloc (l);
395 memcpy (n[i], avl[i], l);
396 }
397 n[i] = NULL;
398 *av = n;
399 }
400 #else
duplicate_ppstrings(int ac,char *** av)401 static void duplicate_ppstrings (int ac, char ***av)
402 {
403 char **avl;
404 int i;
405 char **n = (char **) malloc (sizeof (char *) * (ac + 1));
406
407 avl=*av;
408 for (i=0; i < ac; i++)
409 {
410 size_t l = strlen (avl[i]) + 1;
411 n[i] = (char *) malloc (l);
412 memcpy (n[i], avl[i], l);
413 }
414 n[i] = NULL;
415 *av = n;
416 }
417 #endif
418
atexit(_PVFV func)419 int __cdecl atexit (_PVFV func)
420 {
421 return _onexit((_onexit_t)func) ? 0 : -1;
422 }
423
424 char __mingw_module_is_dll = 0;
425