[PATCH 2/5] msvcrt: Use trampoline for _beginthreadex().
Arkadiusz Hiler
ahiler at codeweavers.com
Wed May 5 05:03:11 CDT 2021
This way we can call _endthreadex() at the end as stated in the documentation.
This will also simplify FreeLibrary()-safe implementation for UCRT.
Thread handle in TLS is set to INVALID_HANDLE_VALUE, so that accidental
_endthread() won't close it, see: existing tests.
The function is documented to return 0 (unlike _beginthreadex() which returns -1).
Signed-off-by: Arkadiusz Hiler <ahiler at codeweavers.com>
---
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
--
2.31.1
More information about the wine-devel
mailing list