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