Commit 44b4235a authored by Alexandre Julliard's avatar Alexandre Julliard

Fixed per-thread data handling.

Made terminate and unexpected function pointer per-thread. Added set_se_translator.
parent 8a191ff5
......@@ -20,7 +20,7 @@
#include "msvcrt.h"
#include "msvcrt/eh.h"
#include "msvcrt/malloc.h"
#include "msvcrt/stdlib.h"
#include "wine/debug.h"
......@@ -177,18 +177,16 @@ const char * MSVCRT_what_exception(exception * _this)
}
static terminate_function func_terminate=NULL;
static unexpected_function func_unexpected=NULL;
/******************************************************************
* ?set_terminate@@YAP6AXXZP6AXXZ@Z (MSVCRT.@)
*/
terminate_function MSVCRT_set_terminate(terminate_function func)
{
terminate_function previous=func_terminate;
TRACE("(%p) returning %p\n",func,previous);
func_terminate=func;
return previous;
MSVCRT_thread_data *data = msvcrt_get_thread_data();
terminate_function previous = data->terminate_handler;
TRACE("(%p) returning %p\n",func,previous);
data->terminate_handler = func;
return previous;
}
/******************************************************************
......@@ -196,26 +194,43 @@ terminate_function MSVCRT_set_terminate(terminate_function func)
*/
unexpected_function MSVCRT_set_unexpected(unexpected_function func)
{
unexpected_function previous=func_unexpected;
TRACE("(%p) returning %p\n",func,previous);
func_unexpected=func;
return previous;
MSVCRT_thread_data *data = msvcrt_get_thread_data();
unexpected_function previous = data->unexpected_handler;
TRACE("(%p) returning %p\n",func,previous);
data->unexpected_handler = func;
return previous;
}
/******************************************************************
* ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z (MSVCRT.@)
*/
_se_translator_function MSVCRT__set_se_translator(_se_translator_function func)
{
MSVCRT_thread_data *data = msvcrt_get_thread_data();
_se_translator_function previous = data->se_translator;
TRACE("(%p) returning %p\n",func,previous);
data->se_translator = func;
return previous;
}
/******************************************************************
* ?terminate@@YAXXZ (MSVCRT.@)
*/
void MSVCRT_terminate()
void MSVCRT_terminate(void)
{
(*func_terminate)();
MSVCRT_thread_data *data = msvcrt_get_thread_data();
if (data->terminate_handler) data->terminate_handler();
MSVCRT_abort();
}
/******************************************************************
* ?unexpected@@YAXXZ (MSVCRT.@)
*/
void MSVCRT_unexpected()
void MSVCRT_unexpected(void)
{
(*func_unexpected)();
MSVCRT_thread_data *data = msvcrt_get_thread_data();
if (data->unexpected_handler) data->unexpected_handler();
MSVCRT_terminate();
}
......@@ -523,4 +538,3 @@ void msvcrt_init_vtables(void)
type_info_vtable[0] = MSVCRT_type_info_dtor;
}
......@@ -118,7 +118,7 @@ int _chdrive(int newdrive)
{
MSVCRT__set_errno(GetLastError());
if (newdrive <= 0)
SET_THREAD_VAR(errno,MSVCRT_EACCES);
*MSVCRT__errno() = MSVCRT_EACCES;
return -1;
}
return 0;
......@@ -185,7 +185,7 @@ int _findnext(long hand, struct _finddata_t * ft)
if (!FindNextFileA(hand, &find_data))
{
SET_THREAD_VAR(errno,MSVCRT_ENOENT);
*MSVCRT__errno() = MSVCRT_ENOENT;
return -1;
}
......@@ -202,7 +202,7 @@ int _wfindnext(long hand, struct _wfinddata_t * ft)
if (!FindNextFileW(hand, &find_data))
{
SET_THREAD_VAR(errno,MSVCRT_ENOENT);
*MSVCRT__errno() = MSVCRT_ENOENT;
return -1;
}
......@@ -229,7 +229,7 @@ char* _getcwd(char * buf, int size)
}
if (dir_len >= size)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
return NULL; /* buf too small */
}
strcpy(buf,dir);
......@@ -255,7 +255,7 @@ WCHAR* _wgetcwd(WCHAR * buf, int size)
}
if (dir_len >= size)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
return NULL; /* buf too small */
}
strcpyW(buf,dir);
......@@ -293,14 +293,14 @@ char* _getdcwd(int drive, char * buf, int size)
drivespec[0] += drive - 1;
if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
{
SET_THREAD_VAR(errno,MSVCRT_EACCES);
*MSVCRT__errno() = MSVCRT_EACCES;
return NULL;
}
dir_len = GetFullPathNameA(drivespec,MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
return NULL; /* buf too small */
}
......@@ -333,14 +333,14 @@ WCHAR* _wgetdcwd(int drive, WCHAR * buf, int size)
drivespec[0] += drive - 1;
if (GetDriveTypeW(drivespec) < DRIVE_REMOVABLE)
{
SET_THREAD_VAR(errno,MSVCRT_EACCES);
*MSVCRT__errno() = MSVCRT_EACCES;
return NULL;
}
dir_len = GetFullPathNameW(drivespec,MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
return NULL; /* buf too small */
}
......@@ -629,7 +629,7 @@ char *_fullpath(char * absPath, const char* relPath, unsigned int size)
if (size < 4)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
return NULL;
}
......@@ -818,4 +818,3 @@ void _searchenv(const char* file, const char* env, char *buf)
penv = *end ? end + 1 : end;
} while(1);
}
......@@ -37,8 +37,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
/* INTERNAL: Set the crt and dos errno's from the OS error given. */
void MSVCRT__set_errno(int err)
{
int *errno = GET_THREAD_VAR_PTR(errno);
unsigned long *doserrno = GET_THREAD_VAR_PTR(doserrno);
int *errno = MSVCRT__errno();
unsigned long *doserrno = __doserrno();
*doserrno = err;
......@@ -99,7 +99,7 @@ void MSVCRT__set_errno(int err)
*/
int* MSVCRT__errno(void)
{
return GET_THREAD_VAR_PTR(errno);
return &msvcrt_get_thread_data()->errno;
}
/*********************************************************************
......@@ -107,7 +107,7 @@ int* MSVCRT__errno(void)
*/
unsigned long* __doserrno(void)
{
return GET_THREAD_VAR_PTR(doserrno);
return &msvcrt_get_thread_data()->doserrno;
}
/*********************************************************************
......@@ -124,7 +124,7 @@ char* MSVCRT_strerror(int err)
char* _strerror(const char* err)
{
static char strerrbuff[256]; /* FIXME: Per thread, nprintf */
sprintf(strerrbuff,"%s: %s\n",err,MSVCRT_strerror(GET_THREAD_VAR(errno)));
sprintf(strerrbuff,"%s: %s\n",err,MSVCRT_strerror(msvcrt_get_thread_data()->errno));
return strerrbuff;
}
......@@ -133,5 +133,5 @@ char* _strerror(const char* err)
*/
void MSVCRT_perror(const char* str)
{
_cprintf("%s: %s\n",str,MSVCRT_strerror(GET_THREAD_VAR(errno)));
_cprintf("%s: %s\n",str,MSVCRT_strerror(msvcrt_get_thread_data()->errno));
}
......@@ -102,8 +102,8 @@ static HANDLE msvcrt_fdtoh(int fd)
MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
{
WARN(":fd (%d) - no handle!\n",fd);
SET_THREAD_VAR(doserrno,0);
SET_THREAD_VAR(errno,MSVCRT_EBADF);
*__doserrno() = 0;
*MSVCRT__errno() = MSVCRT_EBADF;
return INVALID_HANDLE_VALUE;
}
return MSVCRT_handles[fd];
......@@ -160,8 +160,8 @@ static MSVCRT_FILE* msvcrt_alloc_fp(int fd)
MSVCRT_handles[fd] == INVALID_HANDLE_VALUE)
{
WARN(":invalid fd %d\n",fd);
SET_THREAD_VAR(doserrno,0);
SET_THREAD_VAR(errno,MSVCRT_EBADF);
*__doserrno() = 0;
*MSVCRT__errno() = MSVCRT_EBADF;
return NULL;
}
if (!MSVCRT_files[fd])
......@@ -490,7 +490,7 @@ LONG _lseek(int fd, LONG offset, int whence)
if (whence < 0 || whence > 2)
{
SET_THREAD_VAR(errno,MSVCRT_EINVAL);
*MSVCRT__errno() = MSVCRT_EINVAL;
return -1;
}
......@@ -538,7 +538,7 @@ int _locking(int fd, int mode, LONG nbytes)
if (mode < 0 || mode > 4)
{
SET_THREAD_VAR(errno,MSVCRT_EINVAL);
*MSVCRT__errno() = MSVCRT_EINVAL;
return -1;
}
......@@ -553,7 +553,7 @@ int _locking(int fd, int mode, LONG nbytes)
if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == 0xffffffff)
{
FIXME ("Seek failed\n");
SET_THREAD_VAR(errno,MSVCRT_EINVAL); /* FIXME */
*MSVCRT__errno() = MSVCRT_EINVAL; /* FIXME */
return -1;
}
if (mode == _LK_LOCK || mode == _LK_RLCK)
......
......@@ -25,6 +25,7 @@
#include "ms_errno.h"
#include "msvcrt/malloc.h"
#include "msvcrt/stdlib.h"
#include "mtdll.h"
#include "wine/debug.h"
......@@ -230,7 +231,7 @@ int _heapset(unsigned int value)
int _heapadd(void* mem, MSVCRT_size_t size)
{
TRACE("(%p,%d) unsupported in Win32\n", mem,size);
SET_THREAD_VAR(errno,MSVCRT_ENOSYS);
*MSVCRT__errno() = MSVCRT_ENOSYS;
return -1;
}
......
......@@ -60,18 +60,8 @@ BOOL WINAPI MSVCRT_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
msvcrt_init_args();
MSVCRT_setlocale(0, "C");
TRACE("finished process init\n");
/* FALL THROUGH for Initial TLS allocation!! */
break;
case DLL_THREAD_ATTACH:
TRACE("starting thread init\n");
/* Create TLS */
tls = (MSVCRT_thread_data*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(MSVCRT_thread_data));
if (!tls || !TlsSetValue(MSVCRT_tls_index, tls))
{
ERR("TLS init failed! error = %ld\n", GetLastError());
return FALSE;
}
TRACE("finished thread init\n");
break;
case DLL_PROCESS_DETACH:
msvcrt_free_mt_locks();
......@@ -85,13 +75,7 @@ BOOL WINAPI MSVCRT_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
case DLL_THREAD_DETACH:
/* Free TLS */
tls = TlsGetValue(MSVCRT_tls_index);
if (!tls)
{
ERR("TLS free failed! error = %ld\n", GetLastError());
return FALSE;
}
HeapFree(GetProcessHeap(), 0, tls);
if (tls) HeapFree(GetProcessHeap(), 0, tls);
TRACE("finished thread free\n");
break;
}
......
......@@ -129,7 +129,7 @@ static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
double _CIacos(void)
{
FPU_DOUBLE(x);
if (x < -1.0 || x > 1.0 || !finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return acos(x);
}
......@@ -139,7 +139,7 @@ double _CIacos(void)
double _CIasin(void)
{
FPU_DOUBLE(x);
if (x < -1.0 || x > 1.0 || !finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return asin(x);
}
......@@ -149,7 +149,7 @@ double _CIasin(void)
double _CIatan(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return atan(x);
}
......@@ -159,7 +159,7 @@ double _CIatan(void)
double _CIatan2(void)
{
FPU_DOUBLES(x,y);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return atan2(x,y);
}
......@@ -169,7 +169,7 @@ double _CIatan2(void)
double _CIcos(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return cos(x);
}
......@@ -179,7 +179,7 @@ double _CIcos(void)
double _CIcosh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return cosh(x);
}
......@@ -189,7 +189,7 @@ double _CIcosh(void)
double _CIexp(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return exp(x);
}
......@@ -199,7 +199,7 @@ double _CIexp(void)
double _CIfmod(void)
{
FPU_DOUBLES(x,y);
if (!finite(x) || !finite(y)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x) || !finite(y)) *MSVCRT__errno() = MSVCRT_EDOM;
return fmod(x,y);
}
......@@ -209,8 +209,8 @@ double _CIfmod(void)
double _CIlog(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (x == 0.0) SET_THREAD_VAR(errno,MSVCRT_ERANGE);
if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
return log(x);
}
......@@ -220,8 +220,8 @@ double _CIlog(void)
double _CIlog10(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (x == 0.0) SET_THREAD_VAR(errno,MSVCRT_ERANGE);
if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
return log10(x);
}
......@@ -234,7 +234,7 @@ double _CIpow(void)
FPU_DOUBLES(x,y);
/* FIXME: If x < 0 and y is not integral, set EDOM */
z = pow(x,y);
if (!finite(z)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
return z;
}
......@@ -244,7 +244,7 @@ double _CIpow(void)
double _CIsin(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return sin(x);
}
......@@ -254,7 +254,7 @@ double _CIsin(void)
double _CIsinh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return sinh(x);
}
......@@ -264,7 +264,7 @@ double _CIsinh(void)
double _CIsqrt(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return sqrt(x);
}
......@@ -274,7 +274,7 @@ double _CIsqrt(void)
double _CItan(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return tan(x);
}
......@@ -284,7 +284,7 @@ double _CItan(void)
double _CItanh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
return tanh(x);
}
......@@ -363,7 +363,7 @@ unsigned int _rotl(unsigned int num, int shift)
*/
double _logb(double num)
{
if (!finite(num)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
return logb(num);
}
......@@ -401,7 +401,7 @@ double _scalb(double num, long power)
{
/* Note - Can't forward directly as libc expects y as double */
double dblpower = (double)power;
if (!finite(num)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
return scalb(num, dblpower);
}
......@@ -474,7 +474,7 @@ double MSVCRT_ldexp(double num, long exp)
double z = ldexp(num,exp);
if (!finite(z))
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
*MSVCRT__errno() = MSVCRT_ERANGE;
else if (z == 0 && signbit(z))
z = 0.0; /* Convert -0 -> +0 */
return z;
......@@ -628,11 +628,11 @@ INT _isnan(double num)
double _y0(double num)
{
double retval;
if (!finite(num)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
retval = y0(num);
if (_fpclass(retval) == _FPCLASS_NINF)
{
SET_THREAD_VAR(errno,MSVCRT_EDOM);
*MSVCRT__errno() = MSVCRT_EDOM;
retval = sqrt(-1);
}
return retval;
......@@ -644,11 +644,11 @@ double _y0(double num)
double _y1(double num)
{
double retval;
if (!finite(num)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
retval = y1(num);
if (_fpclass(retval) == _FPCLASS_NINF)
{
SET_THREAD_VAR(errno,MSVCRT_EDOM);
*MSVCRT__errno() = MSVCRT_EDOM;
retval = sqrt(-1);
}
return retval;
......@@ -660,11 +660,11 @@ double _y1(double num)
double _yn(int order, double num)
{
double retval;
if (!finite(num)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
retval = yn(order,num);
if (_fpclass(retval) == _FPCLASS_NINF)
{
SET_THREAD_VAR(errno,MSVCRT_EDOM);
*MSVCRT__errno() = MSVCRT_EDOM;
retval = sqrt(-1);
}
return retval;
......@@ -676,7 +676,7 @@ double _yn(int order, double num)
double _nextafter(double num, double next)
{
double retval;
if (!finite(num) || !finite(next)) SET_THREAD_VAR(errno,MSVCRT_EDOM);
if (!finite(num) || !finite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
retval = nextafter(num,next);
return retval;
}
......@@ -995,5 +995,3 @@ void _safe_fprem1(void)
{
TRACE("(): stub\n");
}
......@@ -28,23 +28,21 @@
#include "winerror.h"
#include "winnls.h"
#include "msvcrt/eh.h"
/* TLS data */
extern DWORD MSVCRT_tls_index;
typedef struct __MSVCRT_thread_data
{
int errno;
unsigned long doserrno;
int errno;
unsigned long doserrno;
terminate_function terminate_handler;
unexpected_function unexpected_handler;
_se_translator_function se_translator;
} MSVCRT_thread_data;
#define GET_THREAD_DATA(x) \
x = TlsGetValue(MSVCRT_tls_index)
#define GET_THREAD_VAR(x) \
((MSVCRT_thread_data*)TlsGetValue(MSVCRT_tls_index))->x
#define GET_THREAD_VAR_PTR(x) \
(&((MSVCRT_thread_data*)TlsGetValue(MSVCRT_tls_index))->x)
#define SET_THREAD_VAR(x,y) \
((MSVCRT_thread_data*)TlsGetValue(MSVCRT_tls_index))->x = y
extern MSVCRT_thread_data *msvcrt_get_thread_data(void);
extern int MSVCRT_current_lc_all_cp;
......@@ -53,6 +51,8 @@ void MSVCRT__set_errno(int);
char* msvcrt_strndup(const char*,unsigned int);
LPWSTR msvcrt_wstrndup(LPCWSTR, unsigned int);
void MSVCRT__amsg_exit(int errnum);
/* FIXME: This should be declared in new.h but it's not an extern "C" so
* it would not be much use anyway. Even for Winelib applications.
*/
......
......@@ -42,7 +42,7 @@ init MSVCRT_Init
@ cdecl ?_query_new_mode@@YAHXZ() MSVCRT__query_new_mode
@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) MSVCRT__set_new_handler
@ cdecl ?_set_new_mode@@YAHH@Z(long) MSVCRT__set_new_mode
@ stub ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z
@ cdecl ?_set_se_translator@@YAP6AXIPAU_EXCEPTION_POINTERS@@@ZP6AXI0@Z@Z(ptr) MSVCRT__set_se_translator
@ stub ?before@type_info@@QBEHABV1@@Z #(ptr ptr) stdcall
@ stdcall ?name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_name
@ stdcall ?raw_name@type_info@@QBEPBDXZ(ptr) MSVCRT_type_info_raw_name
......
......@@ -53,7 +53,7 @@ static int msvcrt_spawn(int flags, const char* exe, char* cmdline, char* env)
if ((unsigned)flags > _P_DETACH)
{
SET_THREAD_VAR(errno,MSVCRT_EINVAL);
*MSVCRT__errno() = MSVCRT_EINVAL;
return -1;
}
......@@ -203,8 +203,8 @@ int _cwait(int *status, int pid, int action)
if (doserrno == ERROR_INVALID_HANDLE)
{
SET_THREAD_VAR(errno, MSVCRT_ECHILD);
SET_THREAD_VAR(doserrno,doserrno);
*MSVCRT__errno() = MSVCRT_ECHILD;
*__doserrno() = doserrno;
}
else
MSVCRT__set_errno(doserrno);
......@@ -456,4 +456,3 @@ int _unloaddll(int dll)
return err;
}
}
......@@ -34,6 +34,27 @@ typedef struct {
} _beginthread_trampoline_t;
/*********************************************************************
* msvcrt_get_thread_data
*
* Return the thread local storage structure.
*/
MSVCRT_thread_data *msvcrt_get_thread_data(void)
{
MSVCRT_thread_data *ptr;
DWORD err = GetLastError(); /* need to preserve last error */
if (!(ptr = TlsGetValue( MSVCRT_tls_index )))
{
if (!(ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptr) )))
MSVCRT__amsg_exit(16);
if (!TlsSetValue( MSVCRT_tls_index, ptr )) MSVCRT__amsg_exit(16);
}
SetLastError( err );
return ptr;
}
/*********************************************************************
* _beginthread_trampoline
*/
static DWORD CALLBACK _beginthread_trampoline(LPVOID arg)
......@@ -114,4 +135,3 @@ void _endthreadex(
/* FIXME */
ExitThread(retval);
}
......@@ -31,15 +31,18 @@
#define MSVCRT(x) x
#endif
struct _EXCEPTION_POINTERS;
typedef void (*terminate_handler)();
typedef void (*terminate_function)();
typedef void (*unexpected_handler)();
typedef void (*unexpected_function)();
typedef void (*_se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info);
terminate_function MSVCRT(set_terminate)(terminate_function func);
unexpected_function MSVCRT(set_unexpected)(unexpected_function func);
_se_translator_function MSVCRT(_set_se_translator)(_se_translator_function func);
void MSVCRT(terminate)();
void MSVCRT(unexpected)();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment