Reactos
1//
2// initialization.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// This file defines the main initialization and uninitialization routines for
7// the AppCRT, shared by both the static and dynamic AppCRT libraries. In the
8// dynamic AppCRT library, these are called by DllMain. In the static AppCRT
9// library, these are called by the initialization code.
10//
11#include <corecrt_internal.h>
12#include <corecrt_internal_stdio.h>
13#include <stdlib.h>
14#include <stdio.h>
15
16extern "C" {
17
18
19
20extern _onexit_table_t __acrt_atexit_table;
21extern _onexit_table_t __acrt_at_quick_exit_table;
22extern void* __acrt_stdout_buffer;
23extern void* __acrt_stderr_buffer;
24
25
26
27static bool __cdecl initialize_global_variables()
28{
29 __acrt_current_locale_data.initialize(&__acrt_initial_locale_data);
30 return true;
31}
32
33
34
35#ifdef CRTDLL
36
37 static bool __cdecl initialize_c()
38 {
39 _initialize_onexit_table(&__acrt_atexit_table);
40 _initialize_onexit_table(&__acrt_at_quick_exit_table);
41
42 // Do C initialization:
43 if (_initterm_e(__xi_a, __xi_z) != 0)
44 {
45 return false;
46 }
47
48 // Do C++ initialization:
49 _initterm(__xc_a, __xc_z);
50 return true;
51 }
52
53 static bool __cdecl uninitialize_c(bool)
54 {
55 // Do pre-termination:
56 _initterm(__xp_a, __xp_z);
57
58 // Do termination:
59 _initterm(__xt_a, __xt_z);
60 return true;
61 }
62
63// C4505: unreferenced local function
64#pragma warning( suppress: 4505 )
65 static bool __cdecl initialize_environment()
66 {
67 if (_initialize_narrow_environment() < 0)
68 {
69 return false;
70 }
71
72 if (!_get_initial_narrow_environment())
73 {
74 return false;
75 }
76
77 return true;
78 }
79
80#else
81
82 static bool __cdecl initialize_c()
83 {
84 _initialize_onexit_table(&__acrt_atexit_table);
85 _initialize_onexit_table(&__acrt_at_quick_exit_table);
86 return true;
87 }
88
89 static bool __cdecl uninitialize_c(bool)
90 {
91 return true;
92 }
93
94// C4505: unreferenced local function
95#pragma warning( suppress: 4505 )
96 static bool __cdecl initialize_environment()
97 {
98 return true;
99 }
100
101#endif
102
103// C4505: unreferenced local function
104#pragma warning( suppress: 4505 )
105static bool __cdecl uninitialize_environment(bool const terminating)
106{
107 UNREFERENCED_PARAMETER(terminating);
108
109 #ifdef _DEBUG
110 if (terminating)
111 {
112 return true;
113 }
114 #endif
115
116 __dcrt_uninitialize_environments_nolock();
117 return true;
118}
119
120#ifdef _CRT_GLOBAL_STATE_ISOLATION
121
122 static bool __cdecl initialize_global_state_isolation()
123 {
124 // Configure CRT's per-thread global state mode data
125 return __crt_state_management::initialize_global_state_isolation();
126 }
127
128 static bool __cdecl uninitialize_global_state_isolation(bool const terminating)
129 {
130 // Configure CRT's per-thread global state mode data
131 __crt_state_management::uninitialize_global_state_isolation(terminating);
132 return true;
133 }
134
135#else
136
137 static bool __cdecl initialize_global_state_isolation()
138 {
139 return true;
140 }
141
142 static bool __cdecl uninitialize_global_state_isolation(bool const /* terminating */)
143 {
144 return true;
145 }
146
147#endif
148
149
150
151static bool __cdecl initialize_pointers()
152{
153 void* const encoded_null = __crt_fast_encode_pointer(nullptr);
154 __acrt_initialize_invalid_parameter_handler(encoded_null);
155 __acrt_initialize_new_handler(encoded_null);
156 __acrt_initialize_signal_handlers(encoded_null);
157 __acrt_initialize_user_matherr(encoded_null);
158 __acrt_initialize_thread_local_exit_callback(encoded_null);
159 return true;
160}
161
162static bool __cdecl uninitialize_vcruntime(const bool /* terminating */)
163{
164 return __vcrt_uninitialize(false);
165}
166
167static bool __cdecl uninitialize_allocated_memory(bool const /* terminating */)
168{
169 __acrt_current_multibyte_data.uninitialize([](__crt_multibyte_data*& multibyte_data)
170 {
171 if (_InterlockedDecrement(&multibyte_data->refcount) == 0 &&
172 multibyte_data != &__acrt_initial_multibyte_data)
173 {
174 _free_crt(multibyte_data);
175 multibyte_data = &__acrt_initial_multibyte_data;
176 }
177 });
178
179 return true;
180}
181
182// C4505: unreferenced local function
183#pragma warning( suppress: 4505 )
184static bool __cdecl uninitialize_allocated_io_buffers(bool const /* terminating */)
185{
186 _free_crt(__acrt_stdout_buffer);
187 __acrt_stdout_buffer = nullptr;
188
189 _free_crt(__acrt_stderr_buffer);
190 __acrt_stderr_buffer = nullptr;
191
192 _free_crt(__argv);
193 __argv = nullptr;
194
195 _free_crt(__wargv);
196 __wargv = nullptr;
197
198 return true;
199}
200
201static bool __cdecl report_memory_leaks(bool const /* terminating */)
202{
203 #ifdef _DEBUG
204 if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
205 {
206 _CrtSetDumpClient(nullptr);
207 _CrtDumpMemoryLeaks();
208 }
209 #endif
210
211 return true;
212}
213
214
215
216// This is the table of initializer/uninitializer pairs that is used to perform
217// AppCRT initialization. Initializers are run first-to-last during AppCRT
218// initialization, and uninitializers are run last-to-first during termination.
219static __acrt_initializer const __acrt_initializers[] =
220{
221 // Init globals that can't be set at compile time because they have c'tors
222 { initialize_global_variables, nullptr },
223
224 // Global pointers are stored in encoded form; they must be dynamically
225 // initialized to the encoded nullptr value before they are used by the CRT.
226 { initialize_pointers, nullptr },
227 // Enclaves only require initializers for supported features.
228#ifndef _UCRT_ENCLAVE_BUILD
229 { __acrt_initialize_winapi_thunks, __acrt_uninitialize_winapi_thunks },
230#endif
231
232 // Configure CRT's global state isolation system. This system calls FlsAlloc
233 // and thus must occur after the initialize_pointers initialization, otherwise
234 // it will fall back to call TlsAlloc, then try to use the allocated TLS slot
235 // with the FLS functions. This does not turn out well. By running this
236 // initialization after the initialize_pointers step, we ensure that it can
237 // call FlsAlloc.
238 { initialize_global_state_isolation, uninitialize_global_state_isolation },
239
240 // The heap and locks must be initialized before most other initialization
241 // takes place, as other initialization steps rely on the heap and locks:
242 { __acrt_initialize_locks, __acrt_uninitialize_locks },
243 { __acrt_initialize_heap, __acrt_uninitialize_heap },
244
245 // During uninitialization, before the heap is uninitialized, the AppCRT
246 // needs to notify all VCRuntime instances in the process to allow them to
247 // release any memory that they allocated via the AppCRT heap.
248 //
249 // First, we notify all modules that registered for shutdown notification.
250 // This only occurs in the AppCRT DLL, because the static CRT is only ever
251 // used by a single module, so this notification is never required.
252 //
253 // Then, we notify our own VCRuntime instance. Note that after this point
254 // during uninitialization, no exception handling may take place in any
255 // CRT module.
256 { nullptr, uninitialize_vcruntime },
257
258 { __acrt_initialize_ptd, __acrt_uninitialize_ptd },
259 // Enclaves only require initializers for supported features.
260#ifndef _UCRT_ENCLAVE_BUILD
261 { __acrt_initialize_lowio, __acrt_uninitialize_lowio },
262 { __acrt_initialize_command_line, __acrt_uninitialize_command_line },
263#endif
264 { __acrt_initialize_multibyte, nullptr },
265 { nullptr, report_memory_leaks },
266 // Enclaves only require initializers for supported features.
267#ifndef _UCRT_ENCLAVE_BUILD
268 { nullptr, uninitialize_allocated_io_buffers },
269#endif
270 { nullptr, uninitialize_allocated_memory },
271 // Enclaves only require initializers for supported features.
272#ifndef _UCRT_ENCLAVE_BUILD
273 { initialize_environment, uninitialize_environment },
274#endif
275 { initialize_c, uninitialize_c },
276};
277
278
279
280
281__crt_bool __cdecl __acrt_initialize()
282{
283 #if defined CRTDLL
284 __isa_available_init();
285 #endif
286
287 return __acrt_execute_initializers(
288 __acrt_initializers,
289 __acrt_initializers + _countof(__acrt_initializers)
290 );
291}
292
293__crt_bool __cdecl __acrt_uninitialize(__crt_bool const terminating)
294{
295 UNREFERENCED_PARAMETER(terminating);
296
297 // If the process is terminating, there's no point in cleaning up, except
298 // in debug builds.
299 #ifndef _DEBUG
300 if (terminating) {
301 #ifndef _UCRT_ENCLAVE_BUILD
302 if (__acrt_stdio_is_initialized()) {
303 _flushall();
304 }
305 #endif
306 return TRUE;
307 }
308 #endif
309
310 return __acrt_execute_uninitializers(
311 __acrt_initializers,
312 __acrt_initializers + _countof(__acrt_initializers)
313 );
314}
315
316__crt_bool __cdecl __acrt_uninitialize_critical(__crt_bool const terminating)
317{
318 __acrt_uninitialize_ptd(terminating);
319
320 #ifdef _CRT_GLOBAL_STATE_ISOLATION
321 uninitialize_global_state_isolation(terminating);
322 #endif
323
324 return true;
325}
326
327__crt_bool __cdecl __acrt_thread_attach()
328{
329 // Create a per-thread data structure for this thread (getptd will attempt
330 // to create a new per-thread data structure if one does not already exist
331 // for this thread):
332 if (__acrt_getptd_noexit() == nullptr)
333 return false;
334
335 return true;
336}
337
338__crt_bool __cdecl __acrt_thread_detach()
339{
340 // Free the per-thread data structure for this thread:
341 __acrt_freeptd();
342 return true;
343}
344
345}