Reactos
at master 345 lines 10 kB view raw
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}