Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319//// exit.cpp//// Copyright (c) Microsoft Corporation. All rights reserved.//// The exit() implementation//#include <corecrt_internal.h>#include <eh.h>#include <process.h>
static long c_termination_complete = FALSE;
extern "C" _onexit_table_t __acrt_atexit_table;extern "C" _onexit_table_t __acrt_at_quick_exit_table;
// thread_local atexit dtor handling. The APPCRT exports a function to set the// callback function. The exe main function will call this to set the callback// function so exit() can invoke destructors for thread-storage objects owned// by the main thread.static _tls_callback_type thread_local_exit_callback_func;
// CRT_REFACTOR TODO This needs to be declared somewhere more accessible and we// need to clean up the static CRT exit coordination.#if !defined CRTDLL && defined _DEBUG extern "C" bool __cdecl __scrt_uninitialize_crt(bool is_terminating, bool from_exit);#endif
// Enclaves have no support for managed apps#ifdef _UCRT_ENCLAVE_BUILD
static bool __cdecl is_managed_app() throw() { return false; }
static void __cdecl try_cor_exit_process(UINT const) throw() { }
// This function never returns. It causes the process to exit.static void __cdecl exit_or_terminate_process(UINT const return_code) throw(){ TerminateProcess(GetCurrentProcess(), return_code);}
#else /* ^^^ _UCRT_ENCLAVE_BUILD ^^^ // vvv !_UCRT_ENCLAVE_BUILD vvv */
typedef void (WINAPI* exit_process_pft)(UINT);
// CRT_REFACTOR TODO This is duplicated in the VCStartup utility_desktop.cpp.static bool __cdecl is_managed_app() throw(){ PIMAGE_DOS_HEADER const dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(GetModuleHandleW(nullptr)); if (dos_header == nullptr) return false;
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) return false;
PIMAGE_NT_HEADERS const pe_header = reinterpret_cast<PIMAGE_NT_HEADERS>( reinterpret_cast<BYTE*>(dos_header) + dos_header->e_lfanew);
if (pe_header->Signature != IMAGE_NT_SIGNATURE) return false;
if (pe_header->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) return false;
// prefast assumes we are overrunning __ImageBase #pragma warning(push) #pragma warning(disable: 26000)
if (pe_header->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) return false;
#pragma warning(pop)
if (pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress == 0) return false;
return true;}
static void __cdecl try_cor_exit_process(UINT const return_code) throw(){ __crt_unique_hmodule mscoree; if (!GetModuleHandleExW(0, L"mscoree.dll", mscoree.get_address_of())) return;
auto const cor_exit_process = __crt_get_proc_address<exit_process_pft>(mscoree.get(), "CorExitProcess"); if (!cor_exit_process) return;
cor_exit_process(return_code);}
// For Windows Store apps, starting in Windows 10, we use TerminateProcess// instead of ExitProcess. ExitProcess will allow threads to run during// termination in an unordered fashion. This has lead to problems in various// apps. TerminateProcess does not allow threads to run while the process is// being torn down. See also CoreApplication::Run, which does the same.//// For non-Windows Store app processes, we continue to call ExitProcess, for// compatibility with the legacy runtimes.static bool __cdecl should_call_terminate_process() throw(){ if (__acrt_get_process_end_policy() == process_end_policy_exit_process) { return false; }
// If application verifier is running, we still want to call ExitProcess, // to enable tools that require DLLs to be unloaded cleanly at process exit // to do their work. if (__acrt_app_verifier_enabled()) { return false; }
return true;}
// This function never returns. It causes the process to exit.static void __cdecl exit_or_terminate_process(UINT const return_code) throw(){ if (should_call_terminate_process()) { TerminateProcess(GetCurrentProcess(), return_code); }
try_cor_exit_process(return_code);
// If that returned, then the exe for this process is not managed or we // failed to exit via a call to CorExitProcess. Exit the normal way: ExitProcess(return_code);}
#endif /* _UCRT_ENCLAVE_BUILD */
static int __cdecl atexit_exception_filter(unsigned long const _exception_code) throw(){ if (_exception_code == ('msc' | 0xE0000000)) { return EXCEPTION_EXECUTE_HANDLER; }
return EXCEPTION_CONTINUE_SEARCH;}
extern "C" void __cdecl __acrt_initialize_thread_local_exit_callback(void * encoded_null){ thread_local_exit_callback_func = reinterpret_cast<_tls_callback_type>(encoded_null);}
// Register the dynamic TLS dtor callback. Called from the vcstartup library// as part of the EXE common_main to allow the acrt to call back into the scrt.extern "C" void __cdecl _register_thread_local_exe_atexit_callback(_In_ _tls_callback_type const _Callback){ // Can only set the callback once. if (thread_local_exit_callback_func != __crt_fast_encode_pointer(nullptr)) { terminate(); }
thread_local_exit_callback_func = __crt_fast_encode_pointer(_Callback);}
static void __cdecl common_exit( int const return_code, _crt_exit_cleanup_mode const cleanup_mode, _crt_exit_return_mode const return_mode ) throw(){ // First, check to see if we're loaded in a managed app. If we are, try to // call CorExitProcess to let the CLR handle the process termination. If // the call to CorExitProcess is successful, then it will call back through // this function with a return mode of _crt_exit_return_to_caller, at which // point we will run the C termination routines. It will then terminate the // process itself and not return. if (return_mode == _crt_exit_terminate_process && is_managed_app()) { try_cor_exit_process(return_code); }
// Run the C termination: bool crt_uninitialization_required = false;
__acrt_lock_and_call(__acrt_select_exit_lock(), [&] { static bool c_exit_complete = false; if (c_exit_complete) { return; }
_InterlockedExchange(&c_termination_complete, TRUE);
__try { if (cleanup_mode == _crt_exit_full_cleanup) {
// If this module has any dynamically initialized // __declspec(thread) variables, then we invoke their // destruction for the primary thread. All thread_local // destructors are sequenced before any atexit calls or static // object destructors (3.6.3/1) if (thread_local_exit_callback_func != __crt_fast_encode_pointer(nullptr)) { (__crt_fast_decode_pointer(thread_local_exit_callback_func))(nullptr, DLL_PROCESS_DETACH, nullptr); }
_execute_onexit_table(&__acrt_atexit_table); } else if (cleanup_mode == _crt_exit_quick_cleanup) { _execute_onexit_table(&__acrt_at_quick_exit_table); } } __except (atexit_exception_filter(GetExceptionCode())) { terminate(); } __endtry
#ifndef CRTDLL // When the CRT is statically linked, we are responsible for executing // the terminators here, because the CRT code is present in this module. // When the CRT DLLs are used, the terminators will be executed when // the CRT DLLs are unloaded, after the call to ExitProcess. if (cleanup_mode == _crt_exit_full_cleanup) { _initterm(__xp_a, __xp_z); }
_initterm(__xt_a, __xt_z); #endif // CRTDLL
if (return_mode == _crt_exit_terminate_process) { c_exit_complete = true; crt_uninitialization_required = true; } });
// Do NOT try to uninitialize the CRT while holding one of its locks. if (crt_uninitialization_required) { // If we are about to terminate the process, if the debug CRT is linked // statically into this module and this module is an EXE, we need to // ensure that we fully and correctly uninitialize the CRT so that the // debug on-exit() checks (e.g. debug heap leak detection) have a chance // to run. // // We do not need to uninitialize the CRT when it is statically linked // into a DLL because its DllMain will be called for DLL_PROCESS_DETACH // and we can uninitialize the CRT there. // // We never need to uninitialize the retail CRT during exit() because // the process is about to terminate. #if !CRTDLL && _DEBUG __scrt_uninitialize_crt(true, true); #endif }
if (return_mode == _crt_exit_terminate_process) { exit_or_terminate_process(return_code); }}
extern "C" int __cdecl _is_c_termination_complete(){ return static_cast<int>(__crt_interlocked_read(&c_termination_complete));}
extern "C" void __cdecl exit(int const return_code){ common_exit(return_code, _crt_exit_full_cleanup, _crt_exit_terminate_process); UNREACHABLE;}
extern "C" void __cdecl _exit(int const return_code){ common_exit(return_code, _crt_exit_no_cleanup, _crt_exit_terminate_process); UNREACHABLE;}
extern "C" void __cdecl _Exit(int const return_code){ common_exit(return_code, _crt_exit_no_cleanup, _crt_exit_terminate_process); UNREACHABLE;}
extern "C" void __cdecl quick_exit(int const return_code){ common_exit(return_code, _crt_exit_quick_cleanup, _crt_exit_terminate_process); UNREACHABLE;}
extern "C" void __cdecl _cexit(){ common_exit(0, _crt_exit_full_cleanup, _crt_exit_return_to_caller);}
extern "C" void __cdecl _c_exit(){ common_exit(0, _crt_exit_no_cleanup, _crt_exit_return_to_caller);}