xref: /reactos/sdk/lib/crt/startup/crtdll.c (revision 6d8aafb6)
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     __onexitend = __onexitbegin = NULL;
66 
67     return 0;
68 }
69 
70 WINBOOL WINAPI _CRT_INIT (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
71 {
72     if (dwReason == DLL_PROCESS_DETACH)
73     {
74         if (__proc_attached > 0)
75             __proc_attached--;
76         else
77             return FALSE;
78     }
79     if (dwReason == DLL_PROCESS_ATTACH)
80     {
81         void *lock_free = NULL;
82         void *fiberid = ((PNT_TIB)NtCurrentTeb ())->StackBase;
83         int nested = FALSE;
84 
85         while ((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,
86                             fiberid, 0)) != 0)
87         {
88             if (lock_free == fiberid)
89             {
90                 nested = TRUE;
91                 break;
92             }
93             Sleep(1000);
94         }
95         if (__native_startup_state == __initializing)
96         {
97             _amsg_exit (31);
98         }
99         else if (__native_startup_state == __uninitialized)
100         {
101             __native_startup_state = __initializing;
102 
103             _initterm ((_PVFV *) (void *) __xi_a, (_PVFV *) (void *) __xi_z);
104         }
105         if (__native_startup_state == __initializing)
106         {
107             _initterm (__xc_a, __xc_z);
108             __native_startup_state = __initialized;
109         }
110         if (! nested)
111         {
112             (void) InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
113         }
114         if (__dyn_tls_init_callback != NULL)
115         {
116             __dyn_tls_init_callback (hDllHandle, DLL_THREAD_ATTACH, lpreserved);
117         }
118         __proc_attached++;
119     }
120     else if (dwReason == DLL_PROCESS_DETACH)
121     {
122         void *lock_free = NULL;
123         while ((lock_free = InterlockedCompareExchangePointer ((volatile PVOID *) &__native_startup_lock,(PVOID) 1, 0)) != 0)
124         {
125             Sleep(1000);
126         }
127         if (__native_startup_state != __initialized)
128         {
129             _amsg_exit (31);
130         }
131         else
132         {
133             if (__onexitbegin)
134             {
135                 _PVFV *onexitbegin = (_PVFV *) _decode_pointer (__onexitbegin);
136                 _PVFV *onexitend = (_PVFV *) _decode_pointer (__onexitend);
137                 while (--onexitend >= onexitbegin)
138                     if (*onexitend != NULL)
139                         (**onexitend) ();
140                 if (!lpreserved)
141                     free(onexitbegin);
142                 __onexitbegin = __onexitend = (_PVFV *) NULL;
143             }
144             __native_startup_state = __uninitialized;
145             (void) InterlockedExchangePointer ((volatile PVOID *) &__native_startup_lock, 0);
146         }
147     }
148     return TRUE;
149 }
150 
151 static WINBOOL __DllMainCRTStartup (HANDLE, DWORD, LPVOID);
152 
153 WINBOOL WINAPI DllMainCRTStartup (HANDLE, DWORD, LPVOID);
154 int __mingw_init_ehandler (void);
155 
156 WINBOOL WINAPI
157 DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
158 {
159     mingw_app_type = 0;
160     if (dwReason == DLL_PROCESS_ATTACH)
161     {
162         __security_init_cookie ();
163 #ifdef _WIN64
164         __mingw_init_ehandler ();
165 #endif
166     }
167     return __DllMainCRTStartup (hDllHandle, dwReason, lpreserved);
168 }
169 
170 __declspec(noinline) WINBOOL
171 __DllMainCRTStartup (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
172 {
173     WINBOOL retcode = TRUE;
174 
175     __native_dllmain_reason = dwReason;
176     if (dwReason == DLL_PROCESS_DETACH && __proc_attached == 0)
177     {
178         retcode = FALSE;
179         goto i__leave;
180     }
181     _pei386_runtime_relocator ();
182     if (dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH)
183     {
184         retcode = _CRT_INIT (hDllHandle, dwReason, lpreserved);
185         if (!retcode)
186             goto i__leave;
187         retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
188         if (! retcode)
189         {
190             if (dwReason == DLL_PROCESS_ATTACH)
191                 _CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
192             goto i__leave;
193         }
194     }
195     if (dwReason == DLL_PROCESS_ATTACH)
196         __main ();
197     retcode = DllMain(hDllHandle,dwReason,lpreserved);
198     if (dwReason == DLL_PROCESS_ATTACH && ! retcode)
199     {
200         DllMain (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
201         DllEntryPoint (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
202         _CRT_INIT (hDllHandle, DLL_PROCESS_DETACH, lpreserved);
203     }
204     if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH)
205     {
206         retcode = DllEntryPoint (hDllHandle, dwReason, lpreserved);
207         if (_CRT_INIT (hDllHandle, dwReason, lpreserved) == FALSE)
208             retcode = FALSE;
209     }
210 i__leave:
211     __native_dllmain_reason = UINT_MAX;
212     return retcode ;
213 }
214 #endif
215