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