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