msvcrt: Use trampoline for _beginthreadex().

This way we can call _endthreadex() at the end as stated in the documentation.

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:
Arkadiusz Hiler 2021-05-05 13:03:11 +03:00 committed by Alexandre Julliard
parent 80678c4395
commit 9e2fb411db
1 changed files with 42 additions and 5 deletions

View File

@ -27,7 +27,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef struct {
HANDLE thread;
_beginthread_start_routine_t start_address;
union {
_beginthread_start_routine_t start_address;
_beginthreadex_start_routine_t start_address_ex;
};
void *arglist;
} _beginthread_trampoline_t;
@ -147,6 +150,22 @@ uintptr_t CDECL _beginthread(
return (uintptr_t)thread;
}
/*********************************************************************
* _beginthreadex_trampoline
*/
static DWORD CALLBACK _beginthreadex_trampoline(LPVOID arg)
{
unsigned int retval;
_beginthread_trampoline_t local_trampoline;
thread_data_t *data = msvcrt_get_thread_data();
memcpy(&local_trampoline, arg, sizeof(local_trampoline));
data->handle = local_trampoline.thread;
free(arg);
retval = local_trampoline.start_address_ex(local_trampoline.arglist);
_endthreadex(retval);
}
/*********************************************************************
* _beginthreadex (MSVCRT.@)
*/
@ -158,12 +177,30 @@ uintptr_t CDECL _beginthreadex(
unsigned int initflag, /* [in] Initial state of new thread (0 for running or CREATE_SUSPEND for suspended) */
unsigned int *thrdaddr) /* [out] Points to a 32-bit variable that receives the thread identifier */
{
_beginthread_trampoline_t* trampoline;
HANDLE thread;
TRACE("(%p, %d, %p, %p, %d, %p)\n", security, stack_size, start_address, arglist, initflag, thrdaddr);
/* FIXME */
return (uintptr_t)CreateThread(security, stack_size,
start_address, arglist,
initflag, thrdaddr);
/* FIXME: may use different errno / return values */
if (!MSVCRT_CHECK_PMT(start_address)) return 0;
if (!(trampoline = malloc(sizeof(*trampoline))))
return 0;
trampoline->thread = INVALID_HANDLE_VALUE;
trampoline->start_address_ex = start_address;
trampoline->arglist = arglist;
thread = CreateThread(security, stack_size, _beginthreadex_trampoline,
trampoline, initflag, thrdaddr);
if(!thread) {
free(trampoline);
msvcrt_set_errno(GetLastError());
return 0;
}
return (uintptr_t)thread;
}
#if _MSVCR_VER>=80