0cd1968206c3502812fd3e65fd4ff3904bd947c0
[reactos.git] / reactos / lib / sdk / crt / startup / crtdll.c
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
37 #if defined(__GNUC__)
38 extern void __main (void);
39 extern void _pei386_runtime_relocator (void);
40 #endif
41
42 extern _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
43 extern _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[];
44 extern _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
45 extern _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[];
46
47 /* TLS initialization hook. */
48 extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
49
50 static int __proc_attached = 0;
51
52 extern _PVFV *__onexitbegin;
53 extern _PVFV *__onexitend;
54
55 extern int mingw_app_type;
56
57 extern WINBOOL WINAPI DllMain (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved);
58
59 extern WINBOOL WINAPI DllEntryPoint (HANDLE, DWORD, LPVOID);
60
61 static int pre_c_init (void);
62
63 _CRTALLOC(".CRT$XIAA") _PIFV pcinit = pre_c_init;
64
65 static int
66 pre_c_init (void)
67 {
68 _PVFV *onexitbegin;
69
70 onexitbegin = (_PVFV *) malloc (32 * sizeof (_PVFV));
71 __onexitend = __onexitbegin = (_PVFV *) _encode_pointer (onexitbegin);
72
73 if (onexitbegin == NULL)
74 return 1;
75 *onexitbegin = (_PVFV) NULL;
76 return 0;
77 }
78
79 WINBOOL WINAPI _CRT_INIT (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
80 {
81 if (dwReason == DLL_PROCESS_DETACH)
82 {
83 if (__proc_attached > 0)
84 __proc_attached--;
85 else
86 return FALSE;
87 }
88 if (dwReason == DLL_PROCESS_ATTACH)
89 {
90 void *lock_free = NULL;
91 void *fiberid = ((PNT_TIB)NtCurrentTeb ())->StackBase;
92 int nested = FALSE;
93
94 while ((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
95 fiberid, 0)) != 0)
96 {
97 if (lock_free == fiberid)
98 {
99 nested = TRUE;
100 break;
101 }
102 Sleep(1000);
103 }
104 if (__native_startup_state != __uninitialized)
105 {
106 _amsg_exit(31);
107 }
108 else
109 {
110 __native_startup_state = __initializing;
111
112 _initterm ((_PVFV *) (void *) __xi_a, (_PVFV *) (void *) __xi_z);
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 #if defined(__GNUC__)
187 _pei386_runtime_relocator ();
188 #endif
189 if (dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH)
190 {
191 retcode = _CRT_INIT (hDllHandle, dwReason, lpreserved);
192 if (!retcode)
193 goto i__leave;
194 retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
195 if (! retcode)
196 {
197 if (dwReason == DLL_PROCESS_ATTACH)
198 _CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
199 goto i__leave;
200 }
201 }
202 #if defined(__GNUC__)
203 if (dwReason == DLL_PROCESS_ATTACH)
204 __main ();
205 #endif
206 retcode = DllMain(hDllHandle,dwReason,lpreserved);
207 if (dwReason == DLL_PROCESS_ATTACH && ! retcode)
208 {
209 DllMain (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
210 DllEntryPoint (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
211 _CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
212 }
213 if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH)
214 {
215 retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
216 if (_CRT_INIT (hDllHandle, dwReason, lpreserved) == FALSE)
217 retcode = FALSE;
218 }
219 i__leave:
220 __native_dllmain_reason = UINT_MAX;
221 return retcode ;
222 }
223 #endif