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.
12 #define SPECIAL_CRTEXE
21 #include <sect_attribs.h>
28 extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv
);
29 #define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv))
33 extern char *** __MINGW_IMP_SYMBOL(__initenv
);
34 #define __initenv (* __MINGW_IMP_SYMBOL(__initenv))
37 /* Hack, for bug in ld. Will be removed soon. */
39 #define __ImageBase __MINGW_LSYMBOL(_image_base__)
42 /* This symbol is defined by ld. */
43 extern IMAGE_DOS_HEADER __ImageBase
;
45 extern void __cdecl
_fpreset (void);
46 #define SPACECHAR _T(' ')
47 #define DQUOTECHAR _T('\"')
49 extern int * __MINGW_IMP_SYMBOL(_fmode
);
50 extern int * __MINGW_IMP_SYMBOL(_commode
);
54 extern int * __MINGW_IMP_SYMBOL(_commode
);
55 #define _commode (* __MINGW_IMP_SYMBOL(_commode))
56 extern int _dowildcard
;
58 extern _CRTIMP
void __cdecl
_initterm(_PVFV
*, _PVFV
*);
60 static int __cdecl
check_managed_app (void);
62 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a
[];
63 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z
[];
64 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a
[];
65 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z
[];
67 /* TLS initialization hook. */
68 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback
;
70 extern _PVFV
*__onexitbegin
;
71 extern _PVFV
*__onexitend
;
73 extern int mingw_app_type
;
75 HINSTANCE __mingw_winmain_hInstance
;
76 _TCHAR
*__mingw_winmain_lpCmdLine
;
77 DWORD __mingw_winmain_nShowCmd
;
80 extern void __main(void);
82 static wchar_t **argv
;
83 static wchar_t **envp
;
91 static int managedapp
;
92 static int has_cctor
= 0;
93 static _startupinfo startinfo
;
94 extern LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler
;
96 extern void _pei386_runtime_relocator (void);
97 long CALLBACK
_gnu_exception_handler (EXCEPTION_POINTERS
* exception_data
);
99 static void duplicate_ppstrings (int ac
, wchar_t ***av
);
101 static void duplicate_ppstrings (int ac
, char ***av
);
104 static int __cdecl
pre_c_init (void);
105 static void __cdecl
pre_cpp_init (void);
106 static void __cdecl
__mingw_prepare_except_for_msvcr80_and_higher (void);
107 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit
= pre_c_init
;
108 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit
= pre_cpp_init
;
110 extern int _MINGW_INSTALL_DEBUG_MATHERR
;
115 managedapp
= check_managed_app ();
117 __set_app_type(_GUI_APP
);
119 __set_app_type (_CONSOLE_APP
);
120 __onexitbegin
= __onexitend
= (_PVFV
*) _encode_pointer ((_PVFV
*)(-1));
122 * __MINGW_IMP_SYMBOL(_fmode
) = _fmode
;
123 * __MINGW_IMP_SYMBOL(_commode
) = _commode
;
130 if (_MINGW_INSTALL_DEBUG_MATHERR
== 1)
132 __setusermatherr (_matherr
);
134 #ifndef __clang__ /* FIXME: CORE-14042 */
135 if (__globallocalestatus
== -1)
145 startinfo
.newmode
= _newmode
;
148 argret
= __wgetmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
150 argret
= __getmainargs(&argc
,&argv
,&envp
,_dowildcard
,&startinfo
);
154 static int __cdecl
__tmainCRTStartup (void);
156 int __cdecl
WinMainCRTStartup (void);
158 int __cdecl
WinMainCRTStartup (void)
162 asm ("\t.l_startw:\n"
163 "\t.seh_handler __C_specific_handler, @except\n"
164 "\t.seh_handlerdata\n"
166 "\t.rva .l_startw, .l_endw, _gnu_exception_handler ,.l_endw\n"
171 __security_init_cookie ();
172 ret
= __tmainCRTStartup ();
180 int __cdecl
mainCRTStartup (void);
183 int __mingw_init_ehandler (void);
186 int __cdecl
mainCRTStartup (void)
191 "\t.seh_handler __C_specific_handler, @except\n"
192 "\t.seh_handlerdata\n"
194 "\t.rva .l_start, .l_end, _gnu_exception_handler ,.l_end\n"
199 __security_init_cookie ();
200 ret
= __tmainCRTStartup ();
211 __tmainCRTStartup (void)
213 _TCHAR
*lpszCommandLine
= NULL
;
214 STARTUPINFO StartupInfo
;
215 WINBOOL inDoubleQuote
= FALSE
;
216 memset (&StartupInfo
, 0, sizeof (STARTUPINFO
));
219 /* We need to make sure that this function is build with frame-pointer
220 and that we align the stack to 16 bytes for the sake of SSE ops in main
221 or in functions inlined into main. */
222 lpszCommandLine
= (_TCHAR
*) alloca (32);
223 memset (lpszCommandLine
, 0xcc, 32);
225 asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
230 GetStartupInfo (&StartupInfo
);
232 void *lock_free
= NULL
;
233 void *fiberid
= ((PNT_TIB
)NtCurrentTeb())->StackBase
;
235 while((lock_free
= InterlockedCompareExchangePointer ((volatile PVOID
*) &__native_startup_lock
,
238 if (lock_free
== fiberid
)
245 if (__native_startup_state
== __initializing
)
249 else if (__native_startup_state
== __uninitialized
)
251 __native_startup_state
= __initializing
;
252 _initterm ((_PVFV
*)(void *)__xi_a
, (_PVFV
*)(void *) __xi_z
);
257 if (__native_startup_state
== __initializing
)
259 _initterm (__xc_a
, __xc_z
);
260 __native_startup_state
= __initialized
;
262 _ASSERTE(__native_startup_state
== __initialized
);
264 (VOID
)InterlockedExchangePointer ((volatile PVOID
*) &__native_startup_lock
, 0);
266 if (__dyn_tls_init_callback
!= NULL
)
267 __dyn_tls_init_callback (NULL
, DLL_THREAD_ATTACH
, NULL
);
269 _pei386_runtime_relocator ();
270 __mingw_oldexcpt_handler
= SetUnhandledExceptionFilter (_gnu_exception_handler
);
272 __mingw_init_ehandler ();
274 __mingw_prepare_except_for_msvcr80_and_higher ();
281 lpszCommandLine
= (_TCHAR
*) _wcmdln
;
283 lpszCommandLine
= (char *) _acmdln
;
285 while (*lpszCommandLine
> SPACECHAR
|| (*lpszCommandLine
&& inDoubleQuote
))
287 if (*lpszCommandLine
== DQUOTECHAR
)
288 inDoubleQuote
= !inDoubleQuote
;
290 if (_ismbblead (*lpszCommandLine
))
292 if (lpszCommandLine
) /* FIXME: Why this check? Should I check for *lpszCommandLine != 0 too? */
298 while (*lpszCommandLine
&& (*lpszCommandLine
<= SPACECHAR
))
301 __mingw_winmain_hInstance
= (HINSTANCE
) &__ImageBase
;
302 __mingw_winmain_lpCmdLine
= lpszCommandLine
;
303 __mingw_winmain_nShowCmd
= StartupInfo
.dwFlags
& STARTF_USESHOWWINDOW
?
304 StartupInfo
.wShowWindow
: SW_SHOWDEFAULT
;
306 duplicate_ppstrings (argc
, &argv
);
310 /* C++ initialization.
311 gcc inserts this call automatically for a function called main, but not for wmain. */
312 mainret
= wmain (argc
, argv
, envp
);
315 mainret
= main (argc
, argv
, envp
);
326 extern int mingw_initltsdrot_force
;
327 extern int mingw_initltsdyn_force
;
328 extern int mingw_initltssuo_force
;
329 extern int mingw_initcharmax
;
332 check_managed_app (void)
334 PIMAGE_DOS_HEADER pDOSHeader
;
335 PIMAGE_NT_HEADERS pPEHeader
;
336 PIMAGE_OPTIONAL_HEADER32 pNTHeader32
;
337 PIMAGE_OPTIONAL_HEADER64 pNTHeader64
;
339 /* Force to be linked. */
340 mingw_initltsdrot_force
=1;
341 mingw_initltsdyn_force
=1;
342 mingw_initltssuo_force
=1;
345 pDOSHeader
= (PIMAGE_DOS_HEADER
) &__ImageBase
;
346 if (pDOSHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
349 pPEHeader
= (PIMAGE_NT_HEADERS
)((char *)pDOSHeader
+ pDOSHeader
->e_lfanew
);
350 if (pPEHeader
->Signature
!= IMAGE_NT_SIGNATURE
)
353 pNTHeader32
= (PIMAGE_OPTIONAL_HEADER32
) &pPEHeader
->OptionalHeader
;
354 switch (pNTHeader32
->Magic
)
356 case IMAGE_NT_OPTIONAL_HDR32_MAGIC
:
357 if (pNTHeader32
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
359 return !! pNTHeader32
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
360 case IMAGE_NT_OPTIONAL_HDR64_MAGIC
:
361 pNTHeader64
= (PIMAGE_OPTIONAL_HEADER64
)pNTHeader32
;
362 if (pNTHeader64
->NumberOfRvaAndSizes
<= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
)
364 return !! pNTHeader64
->DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
;
370 static size_t wbytelen(const wchar_t *p
)
378 static void duplicate_ppstrings (int ac
, wchar_t ***av
)
382 wchar_t **n
= (wchar_t **) malloc (sizeof (wchar_t *) * (ac
+ 1));
385 for (i
=0; i
< ac
; i
++)
387 size_t l
= wbytelen (avl
[i
]);
388 n
[i
] = (wchar_t *) malloc (l
);
389 memcpy (n
[i
], avl
[i
], l
);
395 static void duplicate_ppstrings (int ac
, char ***av
)
399 char **n
= (char **) malloc (sizeof (char *) * (ac
+ 1));
402 for (i
=0; i
< ac
; i
++)
404 size_t l
= strlen (avl
[i
]) + 1;
405 n
[i
] = (char *) malloc (l
);
406 memcpy (n
[i
], avl
[i
], l
);
413 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
414 #define __UNUSED_PARAM_1(x) x
416 #define __UNUSED_PARAM_1 __UNUSED_PARAM
419 __mingw_invalidParameterHandler (const wchar_t * __UNUSED_PARAM_1(expression
),
420 const wchar_t * __UNUSED_PARAM_1(function
),
421 const wchar_t * __UNUSED_PARAM_1(file
),
422 unsigned int __UNUSED_PARAM_1(line
),
423 uintptr_t __UNUSED_PARAM(pReserved
))
425 #ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
426 wprintf(L
"Invalid parameter detected in function %s. File: %s Line: %u\n", function
, file
, line
);
427 wprintf(L
"Expression: %s\n", expression
);
431 HANDLE
__mingw_get_msvcrt_handle(void);
434 __mingw_prepare_except_for_msvcr80_and_higher (void)
436 _invalid_parameter_handler (*fIPH
)(_invalid_parameter_handler
) = NULL
;
438 fIPH
= (void*)GetProcAddress (__mingw_get_msvcrt_handle(), "_set_invalid_parameter_handler");
440 (*fIPH
)(__mingw_invalidParameterHandler
);