[MINGW-W64]
[reactos.git] / reactos / lib / 3rdparty / mingw / crtexe.c
index 0e44535..ce76fc1 100644 (file)
@@ -1,29 +1,39 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
 #undef CRTDLL
-//#define _DLL
+#ifndef _DLL
+#define _DLL
+#endif
 
 #define SPECIAL_CRTEXE
 
-#include "oscalls.h"
-#include "internal.h"
+#include <oscalls.h>
+#include <internal.h>
 #include <process.h>
 #include <signal.h>
 #include <math.h>
 #include <stdlib.h>
 #include <tchar.h>
+#include <sect_attribs.h>
 #include <locale.h>
+#include <intrin.h>
 
 #ifndef __winitenv
-extern wchar_t ***_imp____winitenv;
-#define __winitenv (*_imp____winitenv)
+extern wchar_t *** __MINGW_IMP_SYMBOL(__winitenv);
+#define __winitenv (* __MINGW_IMP_SYMBOL(__winitenv))
 #endif
 
 #ifndef __initenv
-extern char ***_imp____initenv;
-#define __initenv (*_imp____initenv)
+extern char *** __MINGW_IMP_SYMBOL(__initenv);
+#define __initenv (* __MINGW_IMP_SYMBOL(__initenv))
 #endif
 
 /* Hack, for bug in ld.  Will be removed soon.  */
-#define __ImageBase _image_base__
+#define __ImageBase __MINGW_LSYMBOL(_image_base__)
 /* This symbol is defined by ld.  */
 extern IMAGE_DOS_HEADER __ImageBase;
 
@@ -33,15 +43,20 @@ extern void _fpreset (void);
 
 __declspec(dllimport) void __setusermatherr(int (__cdecl *)(struct _exception *));
 
-extern int *_imp___fmode;
-extern int *_imp___commode;
+extern int * __MINGW_IMP_SYMBOL(_fmode);
+extern int * __MINGW_IMP_SYMBOL(_commode);
 
 #undef _fmode
 extern int _fmode;
-extern int *_imp___commode;
-#define _commode (*_imp___commode)
+extern int * __MINGW_IMP_SYMBOL(_commode);
+#define _commode (* __MINGW_IMP_SYMBOL(_commode))
 extern int _dowildcard;
 
+#if defined(__GNUC__)
+int _MINGW_INSTALL_DEBUG_MATHERR __attribute__((weak)) = 0;
+#else
+int _MINGW_INSTALL_DEBUG_MATHERR = 0;
+#endif
 extern int __defaultmatherr;
 extern _CRTIMP void __cdecl _initterm(_PVFV *, _PVFV *);
 
@@ -52,6 +67,7 @@ extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];
 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];
 
+/* TLS initialization hook.  */
 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
 
 extern _PVFV *__onexitbegin;
@@ -59,8 +75,13 @@ extern _PVFV *__onexitend;
 
 extern int mingw_app_type;
 
+HINSTANCE __mingw_winmain_hInstance;
+_TCHAR *__mingw_winmain_lpCmdLine;
+DWORD __mingw_winmain_nShowCmd;
+
 static int argc;
 #ifdef WPRFLAG
+extern void __main(void);
 static wchar_t **argv;
 static wchar_t **envp;
 #else
@@ -73,10 +94,10 @@ static int mainret=0;
 static int managedapp;
 static int has_cctor = 0;
 static _startupinfo startinfo;
+static LPTOP_LEVEL_EXCEPTION_FILTER __mingw_oldexcpt_handler = NULL;
 
 extern void _pei386_runtime_relocator (void);
-static CALLBACK long _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
-//static LONG __mingw_vex(EXCEPTION_POINTERS * exception_data);
+static long CALLBACK _gnu_exception_handler (EXCEPTION_POINTERS * exception_data);
 #ifdef WPRFLAG
 static void duplicate_ppstrings (int ac, wchar_t ***av);
 #else
@@ -85,7 +106,7 @@ static void duplicate_ppstrings (int ac, char ***av);
 
 static int __cdecl pre_c_init (void);
 static void __cdecl pre_cpp_init (void);
-
+static void __cdecl __mingw_prepare_except_for_msvcr80_and_higher (void);
 _CRTALLOC(".CRT$XIAA") _PIFV mingw_pcinit = pre_c_init;
 _CRTALLOC(".CRT$XCAA") _PVFV mingw_pcppinit = pre_cpp_init;
 
@@ -99,17 +120,22 @@ pre_c_init (void)
     __set_app_type (_CONSOLE_APP);
   __onexitbegin = __onexitend = (_PVFV *) _encode_pointer ((_PVFV *)(-1));
 
-  *_imp___fmode = _fmode;
-  *_imp___commode = _commode;
+  * __MINGW_IMP_SYMBOL(_fmode) = _fmode;
+  * __MINGW_IMP_SYMBOL(_commode) = _commode;
 
 #ifdef WPRFLAG
   _wsetargv();
 #else
   _setargv();
 #endif
-
-  if (! __defaultmatherr)
-    __setusermatherr (_matherr);
+  if (_MINGW_INSTALL_DEBUG_MATHERR)
+    {
+      if (! __defaultmatherr)
+       {
+         __setusermatherr (_matherr);
+         __defaultmatherr = 1;
+       }
+    }
 
   if (__globallocalestatus == -1)
     {
@@ -131,35 +157,35 @@ pre_cpp_init (void)
 
 static int __tmainCRTStartup (void);
 
-#ifdef WPRFLAG
-int wWinMainCRTStartup (void)
-#else
+int WinMainCRTStartup (void);
+
 int WinMainCRTStartup (void)
-#endif
 {
   mingw_app_type = 1;
   __security_init_cookie ();
   return __tmainCRTStartup ();
 }
 
-#ifdef WPRFLAG
-int wmainCRTStartup (void)
-#else
-int mainCRTStartup (void)
+int mainCRTStartup (void);
+
+#ifdef _WIN64
+int __mingw_init_ehandler (void);
 #endif
+
+int mainCRTStartup (void)
 {
   mingw_app_type = 0;
   __security_init_cookie ();
   return __tmainCRTStartup ();
 }
 
-
+static
 __declspec(noinline) int
 __tmainCRTStartup (void)
 {
   _TCHAR *lpszCommandLine = NULL;
   STARTUPINFO StartupInfo;
-  BOOL inDoubleQuote = FALSE;
+  WINBOOL inDoubleQuote = FALSE;
   memset (&StartupInfo, 0, sizeof (STARTUPINFO));
   
   if (mingw_app_type)
@@ -199,44 +225,33 @@ __tmainCRTStartup (void)
     if (! nested)
       (VOID)InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
     
-    if (__dyn_tls_init_callback != NULL && _IsNonwritableInCurrentImage ((PBYTE) &__dyn_tls_init_callback))
+    if (__dyn_tls_init_callback != NULL)
       __dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
     
-#if defined(__i386__) || defined(__x86_64__)
     _pei386_runtime_relocator ();
+    __mingw_oldexcpt_handler = SetUnhandledExceptionFilter (_gnu_exception_handler);
+#ifdef _WIN64
+    __mingw_init_ehandler ();
 #endif
+    __mingw_prepare_except_for_msvcr80_and_higher ();
     
-    #if defined(__x86_64__)
-    __asm__ __volatile__ (
-       "xorq %rax,%rax\n\t"
-       "decq %rax\n\t"
-       "movq %rax,%gs:0" "\n");
-    #elif defined(__i386__)
-    __asm__ __volatile__ (
-       "xorl %eax,%eax\n\t"
-       "decl %eax\n\t"
-       "movl %eax,%fs:0" "\n");
-    #endif
-    //AddVectoredExceptionHandler (0, (PVECTORED_EXCEPTION_HANDLER)__mingw_vex);
-    SetUnhandledExceptionFilter (_gnu_exception_handler);
+    _fpreset ();
 
     if (mingw_app_type)
       {
 #ifdef WPRFLAG
-    if (_wcmdln == NULL)
-      return 255;
     lpszCommandLine = (_TCHAR *) _wcmdln;
 #else
     lpszCommandLine = (char *) _acmdln;
 #endif
-    while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine && inDoubleQuote))
+    while (*lpszCommandLine > SPACECHAR || (*lpszCommandLine&&inDoubleQuote))
       {
        if (*lpszCommandLine == DQUOTECHAR)
-         inDoubleQuote = TRUE;
+         inDoubleQuote = !inDoubleQuote;
 #ifdef _MBCS
        if (_ismbblead (*lpszCommandLine))
          {
-           if (lpszCommandLine)
+           if (lpszCommandLine) /* FIXME: Why this check? Should I check for *lpszCommandLine != 0 too? */
              lpszCommandLine++;
          }
 #endif
@@ -245,27 +260,22 @@ __tmainCRTStartup (void)
     while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
       lpszCommandLine++;
 
-#ifdef WPRFLAG
-    mainret = wmain (
-       (int) (StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow : SW_SHOWDEFAULT),
-       (wchar_t **) lpszCommandLine, (wchar_t **) (HINSTANCE) &__ImageBase);
-#else
-    mainret = main (
-       (int) (StartupInfo.dwFlags & STARTF_USESHOWWINDOW ? StartupInfo.wShowWindow : SW_SHOWDEFAULT),
-       (char **) lpszCommandLine, (char **) (HINSTANCE) &__ImageBase);
-#endif
+    __mingw_winmain_hInstance = (HINSTANCE) &__ImageBase;
+    __mingw_winmain_lpCmdLine = lpszCommandLine;
+    __mingw_winmain_nShowCmd = StartupInfo.dwFlags & STARTF_USESHOWWINDOW ?
+                               StartupInfo.wShowWindow : SW_SHOWDEFAULT;
     }
-  else
-    {
     duplicate_ppstrings (argc, &argv);
 #ifdef WPRFLAG
     __winitenv = envp;
+    /* C++ initialization.
+       gcc inserts this call automatically for a function called main, but not for wmain.  */
+    __main ();
     mainret = wmain (argc, argv, envp);
 #else
     __initenv = envp;
     mainret = main (argc, argv, envp);
 #endif
-    }
     if (!managedapp)
       exit (mainret);
 
@@ -289,10 +299,9 @@ check_managed_app (void)
   PIMAGE_OPTIONAL_HEADER64 pNTHeader64;
 
   /* Force to be linked.  */
-  //TLS sections
-  //mingw_initltsdrot_force=1;
-  //mingw_initltsdyn_force=1;
-  //mingw_initltssuo_force=1;
+  mingw_initltsdrot_force=1;
+  mingw_initltsdyn_force=1;
+  mingw_initltssuo_force=1;
   mingw_initcharmax=1;
 
   pDOSHeader = (PIMAGE_DOS_HEADER) &__ImageBase;
@@ -319,10 +328,8 @@ check_managed_app (void)
   return 0;
 }
 
-int __defaultmatherr;
-
-static CALLBACK long
-_gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
+static long CALLBACK
+_gnu_exception_handler (EXCEPTION_POINTERS *exception_data)
 {
   void (*old_handler) (int);
   long action = EXCEPTION_CONTINUE_SEARCH;
@@ -393,42 +400,26 @@ _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
          action = EXCEPTION_CONTINUE_EXECUTION;
        }
       break;
-
+#ifdef _WIN64
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+    case EXCEPTION_FLT_STACK_CHECK:
+    case EXCEPTION_INT_OVERFLOW:
+    case EXCEPTION_INVALID_HANDLE:
+    /*case EXCEPTION_POSSIBLE_DEADLOCK: */
+      action = EXCEPTION_CONTINUE_EXECUTION;
+      break;
+#endif
     default:
       break;
     }
-  return action;
-}
 
-#if 0
-static LONG __mingw_vex(EXCEPTION_POINTERS * exception_data)
-{
-  /* TODO this is not chainablem, therefore need rewrite. Disabled the ill code. */
-  #if 0
-  #ifdef _WIN64
-  __asm__ __volatile__ (
-      "movq %gs:0,%rax" "\n\t"
-      "orq %rax,%rax\n\t"
-      "jz l1\n\t"
-      "jmp *8(%rax)\n\r"
-      "l1:\n\t"
-      "nop\n");
-#else
-  __asm__ __volatile__ (
-      "movl %fs:0,%eax" "\n\t"
-      "orl %eax,%eax\n\t"
-      "jz l1\n\t"
-      "jmp *4(%eax)\n\r"
-      "l1:\n\t"
-      "nop\n");
-#endif
-#endif
-  return _gnu_exception_handler(exception_data);
+  if (action == EXCEPTION_CONTINUE_SEARCH && __mingw_oldexcpt_handler)
+    action = (*__mingw_oldexcpt_handler)(exception_data);
+  return action;
 }
-#endif
 
 #ifdef WPRFLAG
-
 static size_t wbytelen(const wchar_t *p)
 {
        size_t ret = 1;
@@ -471,3 +462,40 @@ static void duplicate_ppstrings (int ac, char ***av)
        *av = n;
 }
 #endif
+
+#ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
+#define __UNUSED_PARAM_1(x) x
+#else
+#define __UNUSED_PARAM_1       __UNUSED_PARAM
+#endif
+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))
+{
+#ifdef __MINGW_SHOW_INVALID_PARAMETER_EXCEPTION
+   wprintf(L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line);
+   wprintf(L"Expression: %s\n", expression);
+#endif
+}
+
+static void __cdecl 
+__mingw_prepare_except_for_msvcr80_and_higher (void)
+{
+  _invalid_parameter_handler (*fIPH)(_invalid_parameter_handler) = NULL;
+  HMODULE hmsv = GetModuleHandleA ("msvcr80.dll");
+  if(!hmsv)
+    hmsv = GetModuleHandleA ("msvcr70.dll");
+  if (!hmsv)
+    hmsv = GetModuleHandleA ("msvcrt.dll");
+  if (!hmsv)
+    hmsv = LoadLibraryA ("msvcrt.dll");
+  if (!hmsv)
+    return;
+  fIPH = (_invalid_parameter_handler (*)(_invalid_parameter_handler))
+    GetProcAddress (hmsv, "_set_invalid_parameter_handler");
+  if (fIPH)
+    (*fIPH)(__mingw_invalidParameterHandler);
+}