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;