// // __vcrt_init.c // // Copyright (c) 2024 Timo Kreuzer // // Implementation of vcruntime initialization and termination functions. // // SPDX-License-Identifier: MIT // #include void msvcrt_init_exception(HINSTANCE hinstDLL); BOOL msvcrt_init_tls(void); void msvcrt_free_tls_mem(void); BOOL msvcrt_free_tls(void); __vcrt_bool __cdecl __vcrt_initialize(void) { msvcrt_init_exception(GetModuleHandle(NULL)); if (!msvcrt_init_tls()) return FALSE; return TRUE; } __vcrt_bool __cdecl __vcrt_uninitialize(_In_ __vcrt_bool _Terminating) { if (!msvcrt_free_tls()) return FALSE; return TRUE; } __vcrt_bool __cdecl __vcrt_uninitialize_critical(void) { return TRUE; } __vcrt_bool __cdecl __vcrt_thread_attach(void) { // Not called by UCRT return TRUE; } __vcrt_bool __cdecl __vcrt_thread_detach(void) { // Not called by UCRT return TRUE; } // UCRT doesn't have a thread detach callback for the vcruntime TLS, because // the native vcruntime uses FlsAlloc and provides a cleanup callback there. // Since we don't have that, we use TLS callbacks. const IMAGE_TLS_DIRECTORY* __p_tls_used = &_tls_used; static VOID WINAPI wine_tls_cleanup_callback(PVOID hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { // For the last thread, only DLL_PROCESS_DETACH is called if ((fdwReason == DLL_THREAD_DETACH) || (fdwReason == DLL_PROCESS_DETACH)) { msvcrt_free_tls_mem(); } } _CRTALLOC(".CRT$XLD") PIMAGE_TLS_CALLBACK wine_tls_cleanup_ptr = wine_tls_cleanup_callback;