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