master
  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#include <oscalls.h>
  8#include <internal.h>
  9#include <stdlib.h>
 10#include <windows.h>
 11#define _DECL_DLLMAIN
 12#include <process.h>
 13#include <crtdbg.h>
 14
 15#ifndef _CRTIMP
 16#define _CRTIMP __declspec(dllimport)
 17#endif
 18#include <sect_attribs.h>
 19#include <locale.h>
 20
 21#if defined(__x86_64__) && !defined(__SEH__)
 22extern int __mingw_init_ehandler (void);
 23#endif
 24extern void __main ();
 25extern void _pei386_runtime_relocator (void);
 26extern _PIFV __xi_a[];
 27extern _PIFV __xi_z[];
 28extern _PVFV __xc_a[];
 29extern _PVFV __xc_z[];
 30
 31
 32/* TLS initialization hook.  */
 33extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
 34
 35static int __proc_attached = 0;
 36
 37static _onexit_table_t atexit_table;
 38
 39extern int __mingw_app_type;
 40
 41WINBOOL WINAPI _CRT_INIT (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 42{
 43  if (dwReason == DLL_PROCESS_DETACH)
 44    {
 45      if (__proc_attached > 0)
 46	__proc_attached--;
 47      else
 48	return FALSE;
 49    }
 50  if (dwReason == DLL_PROCESS_ATTACH)
 51    {
 52      void *lock_free = NULL;
 53      void *fiberid = ((PNT_TIB)NtCurrentTeb ())->StackBase;
 54      BOOL nested = FALSE;
 55      int ret = 0;
 56      
 57      while ((lock_free = InterlockedCompareExchangePointer (&__native_startup_lock,
 58							     fiberid, NULL)) != 0)
 59	{
 60	  if (lock_free == fiberid)
 61	    {
 62	      nested = TRUE;
 63	      break;
 64	    }
 65	  Sleep(1000);
 66	}
 67      if (__native_startup_state != __uninitialized)
 68	{
 69	  _amsg_exit (31);
 70	}
 71      else
 72	{
 73	  __native_startup_state = __initializing;
 74	  
 75	  _pei386_runtime_relocator ();
 76#if defined(__x86_64__) && !defined(__SEH__)
 77	  __mingw_init_ehandler ();
 78#endif
 79	  ret = _initialize_onexit_table (&atexit_table);
 80	  if (ret != 0)
 81	    goto i__leave;
 82	  ret = _initterm_e (__xi_a, __xi_z);
 83	  if (ret != 0)
 84	    goto i__leave;
 85	  _initterm (__xc_a, __xc_z);
 86	  __main ();
 87
 88	  __native_startup_state = __initialized;
 89	}
 90i__leave:
 91      if (! nested)
 92	{
 93	  (void) InterlockedExchangePointer (&__native_startup_lock, NULL);
 94	}
 95      if (ret != 0)
 96	{
 97	  return FALSE;
 98	}
 99      if (__dyn_tls_init_callback != NULL)
100	{
101	  __dyn_tls_init_callback (hDllHandle, DLL_THREAD_ATTACH, lpreserved);
102	}
103      __proc_attached++;
104    }
105  else if (dwReason == DLL_PROCESS_DETACH)
106    {
107      void *lock_free = NULL;
108      void *fiberid = ((PNT_TIB)NtCurrentTeb ())->StackBase;
109      BOOL nested = FALSE;
110
111      while ((lock_free = InterlockedCompareExchangePointer (&__native_startup_lock, fiberid, NULL)) != 0)
112	{
113	  if (lock_free == fiberid)
114	    {
115	      nested = TRUE;
116	      break;
117	    }
118	  Sleep(1000);
119	}
120      if (__native_startup_state != __initialized)
121	{
122	  _amsg_exit (31);
123	}
124      else
125	{
126          _execute_onexit_table(&atexit_table);
127	  __native_startup_state = __uninitialized;
128	}
129      if (! nested)
130	{
131	  (void) InterlockedExchangePointer (&__native_startup_lock, NULL);
132	}
133    }
134  return TRUE;
135}
136
137WINBOOL WINAPI DllMainCRTStartup (HANDLE, DWORD, LPVOID);
138
139#if defined(__i386__) || defined(_X86_)
140/* We need to make sure that we align the stack to 16 bytes for the sake of SSE
141   opts in DllMain or in functions called from DllMain.  */
142__attribute__((force_align_arg_pointer))
143#endif
144__attribute__((used)) /* required due to GNU LD bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30300 */
145WINBOOL WINAPI
146DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
147{
148  WINBOOL retcode = TRUE;
149
150  __mingw_app_type = 0;
151  __native_dllmain_reason = dwReason;
152  if (dwReason == DLL_PROCESS_DETACH && __proc_attached <= 0)
153    {
154	retcode = FALSE;
155	goto i__leave;
156    }
157
158  if (dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH)
159    {
160        retcode = _CRT_INIT (hDllHandle, dwReason, lpreserved);
161        if (!retcode)
162          goto i__leave;
163    }
164  retcode = DllMain(hDllHandle,dwReason,lpreserved);
165  if (dwReason == DLL_PROCESS_ATTACH && ! retcode)
166    {
167	DllMain (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
168	_CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
169    }
170  if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH)
171    {
172	retcode = _CRT_INIT (hDllHandle, dwReason, lpreserved);
173    }
174i__leave:
175  __native_dllmain_reason = UINT_MAX;
176  return retcode ;
177}
178
179int __cdecl atexit (_PVFV func)
180{
181    /* Do not use msvcrt's atexit() or UCRT's _crt_atexit() function as it
182     * cannot be called from DLL library which may be unloaded at runtime. */
183    return _register_onexit_function(&atexit_table, (_onexit_t)func);
184}
185
186char __mingw_module_is_dll = 1;