xref: /reactos/sdk/lib/crt/startup/crtdll.c (revision 40462c92)
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 #ifdef CRTDLL
8 #undef CRTDLL
9 #ifndef _DLL
10 #define _DLL
11 #endif
12 
13 #include <oscalls.h>
14 #include <internal.h>
15 #include <stdlib.h>
16 //#include <windows.h>
17 #define _DECL_DLLMAIN
18 #include <process.h>
19 #include <crtdbg.h>
20 
21 #ifndef _CRTIMP
22 #ifdef CRTDLL
23 #define _CRTIMP __declspec(dllexport)
24 #else
25 #ifdef _DLL
26 #define _CRTIMP __declspec(dllimport)
27 #else
28 #define _CRTIMP
29 #endif
30 #endif
31 #endif
32 #include <sect_attribs.h>
33 #include <locale.h>
34 
35 extern void __cdecl _initterm(_PVFV *,_PVFV *);
36 extern void __main ();
37 extern void _pei386_runtime_relocator (void);
38 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
39 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];
40 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
41 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];
42 
43 /* TLS initialization hook.  */
44 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
45 
46 static int __proc_attached = 0;
47 
48 extern _PVFV *__onexitbegin;
49 extern _PVFV *__onexitend;
50 
51 extern int mingw_app_type;
52 
53 extern WINBOOL WINAPI DllMain (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved);
54 
55 extern WINBOOL WINAPI DllEntryPoint (HANDLE, DWORD, LPVOID);
56 
57 static int __cdecl pre_c_init (void);
58 
59 _CRTALLOC(".CRT$XIAA") _PIFV pcinit = pre_c_init;
60 
61 static int
62 __cdecl
63 pre_c_init (void)
64 {
65   _PVFV *onexitbegin;
66 
67   onexitbegin = (_PVFV *) malloc (32 * sizeof (_PVFV));
68   __onexitend = __onexitbegin = (_PVFV *) _encode_pointer (onexitbegin);
69 
70   if (onexitbegin == NULL)
71     return 1;
72   *onexitbegin = (_PVFV) NULL;
73   return 0;
74 }
75 
76 WINBOOL WINAPI _CRT_INIT (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
77 {
78   if (dwReason == DLL_PROCESS_DETACH)
79     {
80       if (__proc_attached > 0)
81 	__proc_attached--;
82       else
83 	return FALSE;
84     }
85   if (dwReason == DLL_PROCESS_ATTACH)
86     {
87       void *lock_free = NULL;
88       void *fiberid = ((PNT_TIB)NtCurrentTeb ())->StackBase;
89       int nested = FALSE;
90 
91       while ((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
92 							     fiberid, 0)) != 0)
93 	{
94 	  if (lock_free == fiberid)
95 	    {
96 	      nested = TRUE;
97 	      break;
98 	    }
99 	  Sleep(1000);
100 	}
101       if (__native_startup_state == __initializing)
102 	{
103 	  _amsg_exit (31);
104 	}
105       else if (__native_startup_state == __uninitialized)
106 	{
107 	  __native_startup_state = __initializing;
108 
109 	  _initterm ((_PVFV *) (void *) __xi_a, (_PVFV *) (void *) __xi_z);
110 	}
111       if (__native_startup_state == __initializing)
112 	{
113 	  _initterm (__xc_a, __xc_z);
114 	  __native_startup_state = __initialized;
115 	}
116       if (! nested)
117 	{
118 	  (void) InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
119 	}
120       if (__dyn_tls_init_callback != NULL)
121 	{
122 	  __dyn_tls_init_callback (hDllHandle, DLL_THREAD_ATTACH, lpreserved);
123 	}
124       __proc_attached++;
125     }
126   else if (dwReason == DLL_PROCESS_DETACH)
127     {
128       void *lock_free = NULL;
129       while ((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,(PVOID) 1, 0)) != 0)
130 	{
131 	  Sleep(1000);
132 	}
133       if (__native_startup_state != __initialized)
134 	{
135 	  _amsg_exit (31);
136 	}
137       else
138 	{
139 	  _PVFV * onexitbegin = (_PVFV *) _decode_pointer (__onexitbegin);
140 	  if (onexitbegin)
141 	    {
142 	      _PVFV *onexitend = (_PVFV *) _decode_pointer (__onexitend);
143 	      while (--onexitend >= onexitbegin)
144 		if (*onexitend != NULL)
145 		  (**onexitend) ();
146 	      free (onexitbegin);
147 	      __onexitbegin = __onexitend = (_PVFV *) NULL;
148 	    }
149 	  __native_startup_state = __uninitialized;
150 	  (void) InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
151 	}
152     }
153   return TRUE;
154 }
155 
156 static WINBOOL __DllMainCRTStartup (HANDLE, DWORD, LPVOID);
157 
158 WINBOOL WINAPI DllMainCRTStartup (HANDLE, DWORD, LPVOID);
159 int __mingw_init_ehandler (void);
160 
161 WINBOOL WINAPI
162 DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
163 {
164   mingw_app_type = 0;
165   if (dwReason == DLL_PROCESS_ATTACH)
166     {
167       __security_init_cookie ();
168 #ifdef _WIN64
169       __mingw_init_ehandler ();
170 #endif
171     }
172   return __DllMainCRTStartup (hDllHandle, dwReason, lpreserved);
173 }
174 
175 __declspec(noinline) WINBOOL
176 __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
177 {
178   WINBOOL retcode = TRUE;
179 
180   __native_dllmain_reason = dwReason;
181   if (dwReason == DLL_PROCESS_DETACH && __proc_attached == 0)
182     {
183 	retcode = FALSE;
184 	goto i__leave;
185     }
186   _pei386_runtime_relocator ();
187   if (dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH)
188     {
189         retcode = _CRT_INIT (hDllHandle, dwReason, lpreserved);
190         if (!retcode)
191           goto i__leave;
192         retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
193 	if (! retcode)
194 	  {
195 	    if (dwReason == DLL_PROCESS_ATTACH)
196 	      _CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
197 	    goto i__leave;
198 	  }
199     }
200   if (dwReason == DLL_PROCESS_ATTACH)
201     __main ();
202   retcode = DllMain(hDllHandle,dwReason,lpreserved);
203   if (dwReason == DLL_PROCESS_ATTACH && ! retcode)
204     {
205 	DllMain (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
206 	DllEntryPoint (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
207 	_CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
208     }
209   if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH)
210     {
211         retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
212 	if (_CRT_INIT (hDllHandle, dwReason, lpreserved) == FALSE)
213 	  retcode = FALSE;
214     }
215 i__leave:
216   __native_dllmain_reason = UINT_MAX;
217   return retcode ;
218 }
219 #endif
220