msvcrt: Make UCRT _beginthread[ex]() hold the DLL reference.
MSVCRT's _beginthread[ex]() doesn't exhibit the same behavior and using ThreadExit() does leak the reference. FreeLibraryAndExit() has to be used because the DLL may be the only user of the given CRT. This fixes Baldur's Gate 3 crashing shortly after launch. Signed-off-by: Arkadiusz Hiler <ahiler@codeweavers.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9e2fb411db
commit
7435ca8545
|
@ -168,6 +168,7 @@ struct __thread_data {
|
|||
void *unk10[100];
|
||||
#if _MSVCR_VER >= 140
|
||||
_invalid_parameter_handler invalid_parameter_handler;
|
||||
HMODULE module;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,9 @@ thread_data_t *CDECL msvcrt_get_thread_data(void)
|
|||
ptr->random_seed = 1;
|
||||
ptr->locinfo = MSVCRT_locale->locinfo;
|
||||
ptr->mbcinfo = MSVCRT_locale->mbcinfo;
|
||||
#if _MSVCR_VER >= 140
|
||||
ptr->module = NULL;
|
||||
#endif
|
||||
}
|
||||
SetLastError( err );
|
||||
return ptr;
|
||||
|
@ -76,8 +79,7 @@ void CDECL _endthread(void)
|
|||
} else
|
||||
WARN("tls=%p tls->handle=%p\n", tls, tls ? tls->handle : INVALID_HANDLE_VALUE);
|
||||
|
||||
/* FIXME */
|
||||
ExitThread(0);
|
||||
_endthreadex(0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -88,7 +90,17 @@ void CDECL _endthreadex(
|
|||
{
|
||||
TRACE("(%d)\n", retval);
|
||||
|
||||
/* FIXME */
|
||||
#if _MSVCR_VER >= 140
|
||||
{
|
||||
thread_data_t *tls = TlsGetValue(msvcrt_tls_index);
|
||||
|
||||
if (tls && tls->module != NULL)
|
||||
FreeLibraryAndExitThread(tls->module, retval);
|
||||
else
|
||||
WARN("tls=%p tls->module=%p\n", tls, tls ? tls->module : NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
ExitThread(retval);
|
||||
}
|
||||
|
||||
|
@ -104,6 +116,15 @@ static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
|
|||
data->handle = local_trampoline.thread;
|
||||
free(arg);
|
||||
|
||||
#if _MSVCR_VER >= 140
|
||||
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(void*)local_trampoline.start_address, &data->module))
|
||||
{
|
||||
data->module = NULL;
|
||||
WARN("failed to get module for the start_address: %d\n", GetLastError());
|
||||
}
|
||||
#endif
|
||||
|
||||
local_trampoline.start_address(local_trampoline.arglist);
|
||||
_endthread();
|
||||
}
|
||||
|
@ -163,6 +184,18 @@ static DWORD CALLBACK _beginthreadex_trampoline(LPVOID arg)
|
|||
data->handle = local_trampoline.thread;
|
||||
free(arg);
|
||||
|
||||
#if _MSVCR_VER >= 140
|
||||
{
|
||||
thread_data_t *data = msvcrt_get_thread_data();
|
||||
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(void*)local_trampoline.start_address_ex, &data->module))
|
||||
{
|
||||
data->module = NULL;
|
||||
WARN("failed to get module for the start_address: %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
retval = local_trampoline.start_address_ex(local_trampoline.arglist);
|
||||
_endthreadex(retval);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue