Module: wine Branch: master Commit: 9e2fb411dbe5e1bea3e6349fbb14e5346fb5b922 URL: https://source.winehq.org/git/wine.git/?a=commit;h=9e2fb411dbe5e1bea3e6349fb...
Author: Arkadiusz Hiler ahiler@codeweavers.com Date: Wed May 5 13:03:11 2021 +0300
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
---
dlls/msvcrt/thread.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-)
diff --git a/dlls/msvcrt/thread.c b/dlls/msvcrt/thread.c index 8bf8d9327c1..d342d57d38c 100644 --- a/dlls/msvcrt/thread.c +++ b/dlls/msvcrt/thread.c @@ -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