Commit 1db20bfd authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard

- Migrate CRTDLL to MSVCRT.

- Many fixes and a load of new functions.
parent ca43a641
......@@ -45,6 +45,7 @@ Other DLLs:
avifil32/ - COM object to play AVI files
comctl32/ - common controls
commdlg/ - common dialog boxes (both 16 & 32 bit)
crtdll/ - Old C runtime library
dplayx/ - DirectX dplayx
dsound/ - DirectX dsound
imagehlp/ - PE (Portable Executable) Image Helper lib
......@@ -55,6 +56,7 @@ Other DLLs:
msacm/ - audio compression manager (multimedia) (16 bit)
msacm32/ - audio compression manager (multimedia) (32 bit)
msnet/
msvcrt/ - C runtime library
msvideo/ - 16 bit video manager
ole32/ - 32 bit OLE 2.0 librairies
oleaut32/ - 32 bit OLE 2.0 automation
......
......@@ -129,6 +129,7 @@ DLLS = \
msacm.drv \
msacm32 \
msnet32 \
msvcrt \
msvfw32 \
odbc32 \
ole32 \
......
......@@ -7000,6 +7000,7 @@ dlls/lzexpand/Makefile
dlls/mpr/Makefile
dlls/msacm/Makefile
dlls/msnet32/Makefile
dlls/msvcrt/Makefile
dlls/msvideo/Makefile
dlls/ntdll/Makefile
dlls/odbc32/Makefile
......@@ -7241,6 +7242,7 @@ dlls/lzexpand/Makefile
dlls/mpr/Makefile
dlls/msacm/Makefile
dlls/msnet32/Makefile
dlls/msvcrt/Makefile
dlls/msvideo/Makefile
dlls/ntdll/Makefile
dlls/odbc32/Makefile
......
......@@ -1200,6 +1200,7 @@ dlls/lzexpand/Makefile
dlls/mpr/Makefile
dlls/msacm/Makefile
dlls/msnet32/Makefile
dlls/msvcrt/Makefile
dlls/msvideo/Makefile
dlls/ntdll/Makefile
dlls/odbc32/Makefile
......
......@@ -32,6 +32,7 @@ DLLFILES = \
mpr/libmpr.@LIBEXT@ \
msacm/libmsacm32.@LIBEXT@ \
msnet32/libmsnet32.@LIBEXT@ \
msvcrt/libmsvcrt.@LIBEXT@ \
msvideo/libmsvfw32.@LIBEXT@ \
ntdll/libntdll.@LIBEXT@ \
odbc32/libodbc32.@LIBEXT@ \
......@@ -145,6 +146,7 @@ SUBDIRS = \
mpr \
msacm \
msnet32 \
msvcrt \
msvideo \
ntdll \
odbc32 \
......@@ -283,6 +285,9 @@ libmsacm32.@LIBEXT@ libmsacm.@LIBEXT@: msacm/libmsacm32.@LIBEXT@
libmsnet32.@LIBEXT@: msnet32/libmsnet32.@LIBEXT@
$(RM) $@ && $(LN_S) msnet32/libmsnet32.@LIBEXT@ $@
libmsvcrt.@LIBEXT@: msvcrt/libmsvcrt.@LIBEXT@
$(RM) $@ && $(LN_S) msvcrt/libmsvcrt.@LIBEXT@ $@
libmsvfw32.@LIBEXT@ libmsvideo.@LIBEXT@: msvideo/libmsvfw32.@LIBEXT@
$(RM) $@ && $(LN_S) msvideo/libmsvfw32.@LIBEXT@ $@
......@@ -418,6 +423,7 @@ lzexpand/liblz32.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
mpr/libmpr.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
msacm/libmsacm32.@LIBEXT@: libwinmm.@LIBEXT@ libuser32.@LIBEXT@ libadvapi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
msnet32/libmsnet32.@LIBEXT@: libntdll.@LIBEXT@
msvcrt/libmsvcrt.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
msvideo/libmsvfw32.@LIBEXT@: libwinmm.@LIBEXT@ libuser32.@LIBEXT@ libgdi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
odbc32/libodbc32.@LIBEXT@: libntdll.@LIBEXT@
ole32/libole32.@LIBEXT@: libadvapi32.@LIBEXT@ libuser32.@LIBEXT@ libgdi32.@LIBEXT@ librpcrt4.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
......
Makefile
msvcrt.spec.c
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = msvcrt
EXTRALIBS = $(LIBUNICODE)
LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
console.c \
cpp.c \
ctype.c \
data.c \
dir.c \
environ.c \
errno.c \
except.c \
exit.c \
file.c \
heap.c \
locale.c \
main.c \
math.c \
mbcs.c \
misc.c \
process.c \
string.c \
thread.c \
time.c \
wcs.c
@MAKE_DLL_RULES@
### Dependencies:
/*
* msvcrt.dll C++ objects
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
void __cdecl MSVCRT__purecall(void);
typedef void (__cdecl *v_table_ptr)();
static v_table_ptr exception_vtable[2];
static v_table_ptr bad_typeid_vtable[3];
static v_table_ptr __non_rtti_object_vtable[3];
static v_table_ptr bad_cast_vtable[3];
static v_table_ptr type_info_vtable[1];
typedef struct __exception
{
v_table_ptr *vtable;
const char *name;
int do_free; /* FIXME: take string copy with char* ctor? */
} exception;
typedef struct __bad_typeid
{
exception base;
} bad_typeid;
typedef struct ____non_rtti_object
{
bad_typeid base;
} __non_rtti_object;
typedef struct __bad_cast
{
exception base;
} bad_cast;
typedef struct __type_info
{
v_table_ptr *vtable;
void *data;
char name[1];
} type_info;
/******************************************************************
* ??0exception@@QAE@ABQBD@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_exception_ctor(exception * _this, const char ** name)
{
TRACE("(%p %s)\n",_this,*name);
_this->vtable = exception_vtable;
_this->name = *name;
TRACE("name = %s\n",_this->name);
_this->do_free = 0; /* FIXME */
}
/******************************************************************
* ??0exception@@QAE@ABV0@@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_exception_copy_ctor(exception * _this, const exception * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
if (_this != rhs)
memcpy (_this, rhs, sizeof (*_this));
TRACE("name = %s\n",_this->name);
}
/******************************************************************
* ??0exception@@QAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT_exception_default_ctor(exception * _this)
{
TRACE("(%p)\n",_this);
_this->vtable = exception_vtable;
_this->name = "";
_this->do_free = 0; /* FIXME */
}
/******************************************************************
* ??1exception@@UAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT_exception_dtor(exception * _this)
{
TRACE("(%p)\n",_this);
}
/******************************************************************
* ??4exception@@QAEAAV0@ABV0@@Z (MSVCRT.@)
*/
exception * __cdecl MSVCRT_exception_opequals(exception * _this, const exception * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
memcpy (_this, rhs, sizeof (*_this));
TRACE("name = %s\n",_this->name);
return _this;
}
/******************************************************************
* ??_Eexception@@UAEPAXI@Z (MSVCRT.@)
*/
void * __cdecl MSVCRT_exception__unknown_E(exception * _this, unsigned int arg1)
{
TRACE("(%p %d)\n",_this,arg1);
MSVCRT__purecall();
return NULL;
}
/******************************************************************
* ??_Gexception@@UAEPAXI@Z (MSVCRT.@)
*/
void * __cdecl MSVCRT_exception__unknown_G(exception * _this, unsigned int arg1)
{
TRACE("(%p %d)\n",_this,arg1);
MSVCRT__purecall();
return NULL;
}
/******************************************************************
* ?what@exception@@UBEPBDXZ (MSVCRT.@)
*/
const char * __stdcall MSVCRT_exception_what(exception * _this)
{
TRACE("(%p) returning %s\n",_this,_this->name);
return _this->name;
}
/******************************************************************
* ??0bad_typeid@@QAE@ABV0@@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_typeid_copy_ctor(bad_typeid * _this, const bad_typeid * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
MSVCRT_exception_copy_ctor(&_this->base,&rhs->base);
}
/******************************************************************
* ??0bad_typeid@@QAE@PBD@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_typeid_ctor(bad_typeid * _this, const char * name)
{
TRACE("(%p %s)\n",_this,name);
MSVCRT_exception_ctor(&_this->base, &name);
_this->base.vtable = bad_typeid_vtable;
}
/******************************************************************
* ??1bad_typeid@@UAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_typeid_dtor(bad_typeid * _this)
{
TRACE("(%p)\n",_this);
MSVCRT_exception_dtor(&_this->base);
}
/******************************************************************
* ??4bad_typeid@@QAEAAV0@ABV0@@Z (MSVCRT.@)
*/
bad_typeid * __cdecl MSVCRT_bad_typeid_opequals(bad_typeid * _this, const bad_typeid * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
MSVCRT_exception_copy_ctor(&_this->base,&rhs->base);
return _this;
}
/******************************************************************
* ??0__non_rtti_object@@QAE@ABV0@@Z (MSVCRT.@)
*/
void __cdecl MSVCRT___non_rtti_object_copy_ctor(__non_rtti_object * _this,
const __non_rtti_object * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
MSVCRT_bad_typeid_copy_ctor(&_this->base,&rhs->base);
}
/******************************************************************
* ??0__non_rtti_object@@QAE@PBD@Z (MSVCRT.@)
*/
void __cdecl MSVCRT___non_rtti_object_ctor(__non_rtti_object * _this,
const char * name)
{
TRACE("(%p %s)\n",_this,name);
MSVCRT_bad_typeid_ctor(&_this->base,name);
_this->base.base.vtable = __non_rtti_object_vtable;
}
/******************************************************************
* ??1__non_rtti_object@@UAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT___non_rtti_object_dtor(__non_rtti_object * _this)
{
TRACE("(%p)\n",_this);
MSVCRT_bad_typeid_dtor(&_this->base);
}
/******************************************************************
* ??4__non_rtti_object@@QAEAAV0@ABV0@@Z (MSVCRT.@)
*/
__non_rtti_object * __cdecl MSVCRT___non_rtti_object_opequals(__non_rtti_object * _this,
const __non_rtti_object *rhs)
{
TRACE("(%p %p)\n",_this,rhs);
memcpy (_this, rhs, sizeof (*_this));
TRACE("name = %s\n",_this->base.base.name);
return _this;
}
/******************************************************************
* ??_E__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
*/
void * __cdecl MSVCRT___non_rtti_object__unknown_E(__non_rtti_object * _this, unsigned int arg1)
{
TRACE("(%p %d)\n",_this,arg1);
MSVCRT__purecall();
return NULL;
}
/******************************************************************
* ??_G__non_rtti_object@@UAEPAXI@Z (MSVCRT.@)
*/
void * __cdecl MSVCRT___non_rtti_object__unknown_G(__non_rtti_object * _this, unsigned int arg1)
{
TRACE("(%p %d)\n",_this,arg1);
MSVCRT__purecall();
return NULL;
}
/******************************************************************
* ??0bad_cast@@QAE@ABQBD@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_cast_ctor(bad_cast * _this, const char ** name)
{
TRACE("(%p %s)\n",_this,*name);
MSVCRT_exception_ctor(&_this->base, name);
_this->base.vtable = bad_cast_vtable;
}
/******************************************************************
* ??0bad_cast@@QAE@ABV0@@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_cast_copy_ctor(bad_cast * _this, const bad_cast * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
MSVCRT_exception_copy_ctor(&_this->base,&rhs->base);
}
/******************************************************************
* ??1bad_cast@@UAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT_bad_cast_dtor(bad_cast * _this)
{
TRACE("(%p)\n",_this);
MSVCRT_exception_dtor(&_this->base);
}
/******************************************************************
* ??4bad_cast@@QAEAAV0@ABV0@@Z (MSVCRT.@)
*/
bad_cast * __cdecl MSVCRT_bad_cast_opequals(bad_cast * _this, const bad_cast * rhs)
{
TRACE("(%p %p)\n",_this,rhs);
MSVCRT_exception_copy_ctor(&_this->base,&rhs->base);
return _this;
}
/******************************************************************
* ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
*/
int __stdcall MSVCRT_type_info_opequals_equals(type_info * _this, const type_info * rhs)
{
TRACE("(%p %p) returning %d\n",_this,rhs,_this->name == rhs->name);
return _this->name == rhs->name;
}
/******************************************************************
* ??9type_info@@QBEHABV0@@Z (MSVCRT.@)
*/
int __stdcall MSVCRT_type_info_opnot_equals(type_info * _this, const type_info * rhs)
{
TRACE("(%p %p) returning %d\n",_this,rhs,_this->name == rhs->name);
return _this->name != rhs->name;
}
/******************************************************************
* ??1type_info@@UAE@XZ (MSVCRT.@)
*/
void __cdecl MSVCRT_type_info_dtor(type_info * _this)
{
TRACE("(%p)\n",_this);
if (_this->data)
MSVCRT_free(_this->data);
}
/******************************************************************
* ?name@type_info@@QBEPBDXZ (MSVCRT.@)
*/
const char * __stdcall MSVCRT_type_info_name(type_info * _this)
{
TRACE("(%p) returning %s\n",_this,_this->name);
return _this->name;
}
/******************************************************************
* ?raw_name@type_info@@QBEPBDXZ (MSVCRT.@)
*/
const char * __stdcall MSVCRT_type_info_raw_name(type_info * _this)
{
TRACE("(%p) returning %s\n",_this,_this->name);
return _this->name;
}
/* INTERNAL: Set up vtables
* FIXME:should be static, cope with versions?
*/
void MSVCRT_init_vtables(void)
{
exception_vtable[0] = MSVCRT_exception_dtor;
exception_vtable[1] = (void*)MSVCRT_exception_what;
bad_typeid_vtable[0] = MSVCRT_bad_typeid_dtor;
bad_typeid_vtable[1] = exception_vtable[1];
bad_typeid_vtable[2] = MSVCRT__purecall; /* FIXME */
__non_rtti_object_vtable[0] = MSVCRT___non_rtti_object_dtor;
__non_rtti_object_vtable[1] = bad_typeid_vtable[1];
__non_rtti_object_vtable[2] = bad_typeid_vtable[2];
bad_cast_vtable[0] = MSVCRT_bad_cast_dtor;
bad_cast_vtable[1] = exception_vtable[1];
bad_cast_vtable[2] = MSVCRT__purecall; /* FIXME */
type_info_vtable[0] = MSVCRT_type_info_dtor;
}
/*
* msvcrt.dll ctype functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* ASCII char classification table - binary compatible */
#define MSVCRT_UPPER C1_UPPER
#define MSVCRT_LOWER C1_LOWER
#define MSVCRT_DIGIT C1_DIGIT
#define MSVCRT_SPACE C1_SPACE
#define MSVCRT_PUNCT C1_PUNCT
#define MSVCRT_CONTROL C1_CNTRL
#define MSVCRT_BLANK C1_BLANK
#define MSVCRT_HEX C1_XDIGIT
#define MSVCRT_LEADBYTE 0x8000
#define MSVCRT_ALPHA (C1_ALPHA|MSVCRT_UPPER|MSVCRT_LOWER)
#define _C_ MSVCRT_CONTROL
#define _S_ MSVCRT_SPACE
#define _P_ MSVCRT_PUNCT
#define _D_ MSVCRT_DIGIT
#define _H_ MSVCRT_HEX
#define _U_ MSVCRT_UPPER
#define _L_ MSVCRT_LOWER
WORD MSVCRT__ctype [257] = {
0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
_S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|MSVCRT_BLANK,
_P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
_P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
_D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
_U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
_U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
_U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
_L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
_L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
_C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Internal: Current ctype table for locale */
WORD MSVCRT_current_ctype[257];
/* pctype is used by macros in the Win32 headers. It must point
* To a table of flags exactly like ctype. To allow locale
* changes to affect ctypes (i.e. isleadbyte), we use a second table
* and update its flags whenever the current locale changes.
*/
WORD* MSVCRT__pctype = MSVCRT_current_ctype + 1;
/* mbctype data */
extern int MSVCRT___mb_cur_max;
extern LCID MSVCRT_current_lc_all_lcid;
/*********************************************************************
* MSVCRT___p__pctype (MSVCRT.@)
*/
WORD** MSVCRT___p__pctype(void)
{
return &MSVCRT__pctype;
}
/*********************************************************************
* _isctype (MSVCRT.@)
*/
int __cdecl MSVCRT__isctype(int c, int type)
{
if (c >= -1 && c <= 255)
return MSVCRT__pctype[c] & type;
if (MSVCRT___mb_cur_max != 1 && c > 0)
{
/* FIXME: Is there a faster way to do this? */
WORD typeInfo;
char convert[3], *pconv = convert;
if (MSVCRT__pctype[(UINT)c >> 8] & MSVCRT_LEADBYTE)
*pconv++ = (UINT)c >> 8;
*pconv++ = c & 0xff;
*pconv = 0;
/* FIXME: Use ctype LCID, not lc_all */
if (GetStringTypeExA(MSVCRT_current_lc_all_lcid, CT_CTYPE1,
convert, convert[1] ? 2 : 1, &typeInfo))
return typeInfo & type;
}
return 0;
}
/*********************************************************************
* isalnum (MSVCRT.@)
*/
int __cdecl MSVCRT_isalnum(int c)
{
return MSVCRT__isctype( c,MSVCRT_ALPHA | MSVCRT_DIGIT );
}
/*********************************************************************
* isalpha (MSVCRT.@)
*/
int __cdecl MSVCRT_isalpha(int c)
{
return MSVCRT__isctype( c, MSVCRT_ALPHA );
}
/*********************************************************************
* iscntrl (MSVCRT.@)
*/
int __cdecl MSVCRT_iscntrl(int c)
{
return MSVCRT__isctype( c, MSVCRT_CONTROL );
}
/*********************************************************************
* isdigit (MSVCRT.@)
*/
int __cdecl MSVCRT_isdigit(int c)
{
return MSVCRT__isctype( c, MSVCRT_DIGIT );
}
/*********************************************************************
* isgraph (MSVCRT.@)
*/
int __cdecl MSVCRT_isgraph(int c)
{
return MSVCRT__isctype( c, MSVCRT_ALPHA | MSVCRT_DIGIT | MSVCRT_PUNCT );
}
/*********************************************************************
* isleadbyte (MSVCRT.@)
*/
int __cdecl MSVCRT_isleadbyte(int c)
{
return MSVCRT__isctype( c, MSVCRT_LEADBYTE );
}
/*********************************************************************
* islower (MSVCRT.@)
*/
int __cdecl MSVCRT_islower(int c)
{
return MSVCRT__isctype( c, MSVCRT_LOWER );
}
/*********************************************************************
* isprint (MSVCRT.@)
*/
int __cdecl MSVCRT_isprint(int c)
{
return MSVCRT__isctype( c, MSVCRT_ALPHA | MSVCRT_DIGIT |
MSVCRT_BLANK | MSVCRT_PUNCT );
}
/*********************************************************************
* ispunct (MSVCRT.@)
*/
int __cdecl MSVCRT_ispunct(int c)
{
return MSVCRT__isctype( c, MSVCRT_PUNCT );
}
/*********************************************************************
* isspace (MSVCRT.@)
*/
int __cdecl MSVCRT_isspace(int c)
{
return MSVCRT__isctype( c, MSVCRT_SPACE );
}
/*********************************************************************
* isupper (MSVCRT.@)
*/
int __cdecl MSVCRT_isupper(int c)
{
return MSVCRT__isctype( c, MSVCRT_UPPER );
}
/*********************************************************************
* isxdigit (MSVCRT.@)
*/
int __cdecl MSVCRT_isxdigit(int c)
{
return MSVCRT__isctype( c, MSVCRT_HEX );
}
/*********************************************************************
* __isascii (MSVCRT.@)
*/
int __cdecl MSVCRT___isascii(int c)
{
return isascii((unsigned)c);
}
/*********************************************************************
* __toascii (MSVCRT.@)
*/
int __cdecl MSVCRT___toascii(int c)
{
return (unsigned)c & 0x7f;
}
/*********************************************************************
* iswascii (MSVCRT.@)
*
*/
int __cdecl MSVCRT_iswascii(WCHAR c)
{
return ((unsigned)c < 0x80);
}
/*********************************************************************
* __iscsym (MSVCRT.@)
*/
int __cdecl MSVCRT___iscsym(int c)
{
return (c < 127 && (isalnum(c) || c == '_'));
}
/*********************************************************************
* __iscsymf (MSVCRT.@)
*/
int __cdecl MSVCRT___iscsymf(int c)
{
return (c < 127 && (isalpha(c) || c == '_'));
}
/*********************************************************************
* _toupper (MSVCRT.@)
*/
int __cdecl MSVCRT__toupper(int c)
{
return toupper(c);
}
/*********************************************************************
* _tolower (MSVCRT.@)
*/
int __cdecl MSVCRT__tolower(int c)
{
return tolower(c);
}
/*
* msvcrt.dll dll data items
*
* Copyright 2000 Jon Griffiths
*/
#include <math.h>
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
unsigned int MSVCRT___argc;
unsigned int MSVCRT_basemajor;/* FIXME: */
unsigned int MSVCRT_baseminor;/* FIXME: */
unsigned int MSVCRT_baseversion; /* FIXME: */
unsigned int MSVCRT__commode;
unsigned int MSVCRT__fmode;
unsigned int MSVCRT_osmajor;/* FIXME: */
unsigned int MSVCRT_osminor;/* FIXME: */
unsigned int MSVCRT_osmode;/* FIXME: */
unsigned int MSVCRT__osver;
unsigned int MSVCRT_osversion; /* FIXME: */
unsigned int MSVCRT__winmajor;
unsigned int MSVCRT__winminor;
unsigned int MSVCRT__winver;
unsigned int MSVCRT__sys_nerr;
unsigned int MSVCRT___setlc_active;
unsigned int MSVCRT___unguarded_readlc_active;
double MSVCRT__HUGE;
char **MSVCRT___argv;
WCHAR **MSVCRT___wargv;
char *MSVCRT__acmdln;
WCHAR *MSVCRT__wcmdln;
char *MSVCRT__environ;
WCHAR *MSVCRT__wenviron;
char **MSVCRT___initenv;
WCHAR **MSVCRT___winitenv;
int MSVCRT_timezone;
int MSVCRT_app_type;
typedef void (__cdecl *MSVCRT__INITTERMFUN)(void);
char * __cdecl MSVCRT__strdup(const char *);
/* Data access functions */
#define GET_UINT_PTR(x) unsigned int __cdecl *MSVCRT___p_##x(void) { return &MSVCRT_##x; }
GET_UINT_PTR(__argc)
GET_UINT_PTR(_commode)
GET_UINT_PTR(_fmode)
GET_UINT_PTR(_osver)
GET_UINT_PTR(_winmajor)
GET_UINT_PTR(_winminor)
GET_UINT_PTR(_winver)
char **__cdecl MSVCRT___p__acmdln(void) { return &MSVCRT__acmdln; }
WCHAR **__cdecl MSVCRT___p__wcmdln(void) { return &MSVCRT__wcmdln; }
char ***__cdecl MSVCRT___p___argv(void) { return &MSVCRT___argv; }
WCHAR ***__cdecl MSVCRT___p___wargv(void) { return &MSVCRT___wargv; }
char **__cdecl MSVCRT___p__environ(void) { return &MSVCRT__environ; }
WCHAR **__cdecl MSVCRT___p__wenviron(void) { return &MSVCRT__wenviron; }
char ***__cdecl MSVCRT___p___initenv(void) { return &MSVCRT___initenv; }
WCHAR ***__cdecl MSVCRT___p___winitenv(void) { return &MSVCRT___winitenv; }
int *__cdecl MSVCRT___p__timezone(void) { return &MSVCRT_timezone; }
/* INTERNAL: Create a wide string from an ascii string */
static WCHAR *wstrdupa(const char *str)
{
const size_t len = strlen(str) + 1 ;
WCHAR *wstr = MSVCRT_malloc(len* sizeof (WCHAR));
if (!wstr)
return NULL;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len*sizeof(char),wstr,len* sizeof (WCHAR));
return wstr;
}
/* INTERNAL: Since we can't rely on Winelib startup code calling w/getmainargs,
* we initialise data values during DLL loading. The when called by a native
* program we simply return the data we've already initialised. This also means
* you can call multiple times without leaking
*/
void MSVCRT_init_args(void)
{
char *cmdline, **xargv = NULL;
WCHAR *wcmdline, **wxargv = NULL;
int xargc,end,last_arg,afterlastspace;
DWORD version;
MSVCRT__acmdln = cmdline = MSVCRT__strdup( GetCommandLineA() );
MSVCRT__wcmdln = wcmdline = wstrdupa(cmdline);
TRACE("got '%s', wide = '%s'\n", cmdline, debugstr_w(wcmdline));
version = GetVersion();
MSVCRT__osver = version >> 16;
MSVCRT__winminor = version & 0xFF;
MSVCRT__winmajor = (version>>8) & 0xFF;
MSVCRT_baseversion = version >> 16;
MSVCRT__winver = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
MSVCRT_baseminor = (version >> 16) & 0xFF;
MSVCRT_basemajor = (version >> 24) & 0xFF;
MSVCRT_osversion = version & 0xFFFF;
MSVCRT_osminor = version & 0xFF;
MSVCRT_osmajor = (version>>8) & 0xFF;
MSVCRT__sys_nerr = 43;
MSVCRT__HUGE = HUGE_VAL;
MSVCRT___setlc_active = 0;
MSVCRT___unguarded_readlc_active = 0;
MSVCRT_timezone = 0;
/* FIXME: set app type for Winelib apps */
end = last_arg = xargc = afterlastspace = 0;
while (1)
{
if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
{
if (cmdline[end]=='\0')
last_arg=1;
else
cmdline[end]='\0';
/* alloc xargc + NULL entry */
xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
sizeof(char*)*(xargc+1));
wxargv=(WCHAR**)HeapReAlloc( GetProcessHeap(), 0, wxargv,
sizeof(WCHAR*)*(xargc+1));
if (strlen(cmdline+afterlastspace))
{
xargv[xargc] = MSVCRT__strdup(cmdline+afterlastspace);
wxargv[xargc] = wstrdupa(xargv[xargc]);
xargc++;
if (!last_arg) /* need to seek to the next arg ? */
{
end++;
while (cmdline[end]==' ')
end++;
}
afterlastspace=end;
}
else
{
xargv[xargc] = NULL;
wxargv[xargc] = NULL; /* the last entry is NULL */
break;
}
}
else
end++;
}
MSVCRT___argc = xargc;
MSVCRT___argv = xargv;
MSVCRT___wargv = wxargv;
TRACE("found %d arguments\n",MSVCRT___argc);
MSVCRT__environ = GetEnvironmentStringsA();
MSVCRT___initenv = &MSVCRT__environ;
MSVCRT__wenviron = GetEnvironmentStringsW();
MSVCRT___winitenv = &MSVCRT__wenviron;
}
/* INTERNAL: free memory used by args */
void MSVCRT_free_args(void)
{
/* FIXME */
}
/*********************************************************************
* __getmainargs (MSVCRT.@)
*/
char** __cdecl MSVCRT___getmainargs(DWORD *argc,char ***argv,char **environ,DWORD flag)
{
TRACE("(%p,%p,%p,%ld).\n",argc,argv,environ,flag);
*argc = MSVCRT___argc;
*argv = MSVCRT___argv;
*environ = MSVCRT__environ;
return environ;
}
/*********************************************************************
* __wgetmainargs (MSVCRT.@)
*/
WCHAR** __cdecl MSVCRT___wgetmainargs(DWORD *argc,WCHAR ***wargv,WCHAR **wenviron,DWORD flag)
{
TRACE("(%p,%p,%p,%ld).\n",argc,wargv,wenviron,flag);
*argc = MSVCRT___argc;
*wargv = MSVCRT___wargv;
*wenviron = MSVCRT__wenviron;
return wenviron;
}
/*********************************************************************
* _initterm (MSVCRT.@)
*/
unsigned int __cdecl MSVCRT__initterm(MSVCRT__INITTERMFUN *start,MSVCRT__INITTERMFUN *end)
{
MSVCRT__INITTERMFUN*current = start;
TRACE("(%p,%p)\n",start,end);
while (current<end)
{
if (*current)
{
TRACE("Call init function %p\n",*current);
(**current)();
TRACE("returned\n");
}
current++;
}
return 0;
}
/*********************************************************************
* __set_app_type (MSVCRT.@)
*/
void __cdecl MSVCRT___set_app_type(int app_type)
{
TRACE("(%d) %s application\n", app_type, app_type == 2 ? "Gui" : "Console");
MSVCRT_app_type = app_type;
}
/*
* msvcrt.dll environment functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*/
#include "wine/unicode.h"
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
LPWSTR __cdecl wcsrchr( LPWSTR str, WCHAR ch );
/*********************************************************************
* getenv (MSVCRT.@)
*/
char *__cdecl MSVCRT_getenv(const char *name)
{
LPSTR environ = GetEnvironmentStringsA();
LPSTR pp,pos = NULL;
unsigned int length;
for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
{
pos =strchr(pp,'=');
if (pos)
length = pos -pp;
else
length = strlen(pp);
if (!strncmp(pp,name,length)) break;
}
if ((pp)&& (pos))
{
pp = pos+1;
TRACE("got %s\n",pp);
}
FreeEnvironmentStringsA( environ );
return pp;
}
/*********************************************************************
* _wgetenv (MSVCRT.@)
*/
WCHAR *__cdecl MSVCRT__wgetenv(const WCHAR *name)
{
WCHAR* environ = GetEnvironmentStringsW();
WCHAR* pp,*pos = NULL;
unsigned int length;
for (pp = environ; (*pp); pp = pp + strlenW(pp) + 1)
{
pos =wcsrchr(pp,'=');
if (pos)
length = pos -pp;
else
length = strlenW(pp);
if (!strncmpW(pp,name,length)) break;
}
if ((pp)&& (pos))
{
pp = pos+1;
TRACE("got %s\n",debugstr_w(pp));
}
FreeEnvironmentStringsW( environ );
return pp;
}
/*
* msvcrt.dll errno functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
#include "ms_errno.h"
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);
int *doserrno = GET_THREAD_VAR_PTR(doserrno);
*doserrno = err;
switch(err)
{
#define ERR_CASE(oserr) case oserr:
#define ERR_MAPS(oserr,crterr) case oserr:*errno = crterr;break;
ERR_CASE(ERROR_ACCESS_DENIED)
ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
ERR_CASE(ERROR_CANNOT_MAKE)
ERR_CASE(ERROR_SEEK_ON_DEVICE)
ERR_CASE(ERROR_LOCK_FAILED)
ERR_CASE(ERROR_FAIL_I24)
ERR_CASE(ERROR_CURRENT_DIRECTORY)
ERR_CASE(ERROR_DRIVE_LOCKED)
ERR_CASE(ERROR_NOT_LOCKED)
ERR_CASE(ERROR_INVALID_ACCESS)
ERR_MAPS(ERROR_LOCK_VIOLATION, MSVCRT_EACCES);
ERR_CASE(ERROR_FILE_NOT_FOUND)
ERR_CASE(ERROR_NO_MORE_FILES)
ERR_CASE(ERROR_BAD_PATHNAME)
ERR_CASE(ERROR_BAD_NETPATH)
ERR_CASE(ERROR_INVALID_DRIVE)
ERR_CASE(ERROR_BAD_NET_NAME)
ERR_CASE(ERROR_FILENAME_EXCED_RANGE)
ERR_MAPS(ERROR_PATH_NOT_FOUND, MSVCRT_ENOENT);
ERR_MAPS(ERROR_IO_DEVICE, MSVCRT_EIO);
ERR_MAPS(ERROR_BAD_FORMAT, MSVCRT_ENOEXEC);
ERR_MAPS(ERROR_INVALID_HANDLE, MSVCRT_EBADF);
ERR_CASE(ERROR_OUTOFMEMORY)
ERR_CASE(ERROR_INVALID_BLOCK)
ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
ERR_MAPS(ERROR_ARENA_TRASHED, MSVCRT_ENOMEM);
ERR_MAPS(ERROR_BUSY, MSVCRT_EBUSY);
ERR_CASE(ERROR_ALREADY_EXISTS)
ERR_MAPS(ERROR_FILE_EXISTS, MSVCRT_EEXIST);
ERR_MAPS(ERROR_BAD_DEVICE, MSVCRT_ENODEV);
ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, MSVCRT_EMFILE);
ERR_MAPS(ERROR_DISK_FULL, MSVCRT_ENOSPC);
ERR_MAPS(ERROR_BROKEN_PIPE, MSVCRT_EPIPE);
ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, MSVCRT_EDEADLK);
ERR_MAPS(ERROR_DIR_NOT_EMPTY, MSVCRT_ENOTEMPTY);
ERR_MAPS(ERROR_BAD_ENVIRONMENT, MSVCRT_E2BIG);
ERR_CASE(ERROR_WAIT_NO_CHILDREN)
ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, MSVCRT_ECHILD);
ERR_CASE(ERROR_NO_PROC_SLOTS)
ERR_CASE(ERROR_MAX_THRDS_REACHED)
ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, MSVCRT_EAGAIN);
default:
/* Remaining cases map to EINVAL */
/* FIXME: may be missing some errors above */
*errno = MSVCRT_EINVAL;
}
}
/*********************************************************************
* _errno (MSVCRT.@)
*/
LPINT __cdecl MSVCRT__errno( VOID )
{
return GET_THREAD_VAR_PTR(errno);
}
/*********************************************************************
* __doserrno (MSVCRT.@)
*/
LPINT __cdecl MSVCRT___doserrno( VOID )
{
return GET_THREAD_VAR_PTR(doserrno);
}
char *strerror(int);
/*********************************************************************
* strerror (MSVCRT.@)
*/
char * __cdecl MSVCRT_strerror (int err)
{
return strerror(err); /* FIXME */
}
/**********************************************************************
* _strerror (MSVCRT.@)
*/
extern int sprintf(char *str, const char *format, ...);
LPSTR __cdecl MSVCRT__strerror (LPCSTR err)
{
static char strerrbuff[256]; /* FIXME: Per thread, nprintf */
sprintf(strerrbuff,"%s: %s\n",err,MSVCRT_strerror(GET_THREAD_VAR(errno)));
return strerrbuff;
}
int __cdecl MSVCRT__cprintf( const char * format, ... );
/*********************************************************************
* perror (MSVCRT.@)
*/
void __cdecl MSVCRT_perror (const char *str)
{
MSVCRT__cprintf("%s: %s\n",str,MSVCRT_strerror(GET_THREAD_VAR(errno)));
}
/*
* msvcrt.dll exception handling
*
* Copyright 2000 Jon Griffiths
*
* See http://www.microsoft.com/msj/0197/exception/exception.htm,
* but don't believe all of it.
*
* FIXME: Incomplete, no support for nested exceptions or try block cleanup.
*/
#include <setjmp.h>
#include "ntddk.h"
#include "thread.h"
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef void (*MSVCRT_sig_handler_func)(void);
/* VC++ extensions to Win32 SEH */
typedef struct _SCOPETABLE
{
DWORD previousTryLevel;
int (__cdecl *lpfnFilter)(int, PEXCEPTION_POINTERS);
int (__cdecl *lpfnHandler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_FRAME *);
} SCOPETABLE, *PSCOPETABLE;
typedef struct _MSVCRT_EXCEPTION_REGISTRATION
{
struct _EXCEPTION_REGISTRATION *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_RECORD);
PSCOPETABLE scopetable;
int trylevel;
int _ebp;
PEXCEPTION_POINTERS xpointers;
} MSVCRT_EXCEPTION_REGISTRATION;
typedef struct _EXCEPTION_REGISTRATION
{
struct _EXCEPTION_REGISTRATION *prev;
void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_FRAME,
PCONTEXT, PEXCEPTION_RECORD);
} EXCEPTION_REGISTRATION;
/*********************************************************************
* _EH_prolog (MSVCRT.@)
*/
void __cdecl MSVCRT__EH_prolog(void)
{
FIXME("stub\n");
}
/*********************************************************************
* _XcptFilter (MSVCRT.@)
*/
int __cdecl MSVCRT__XcptFilter(int ex, PEXCEPTION_POINTERS ptr)
{
FIXME("(%d,%p)semi-stub\n", ex, ptr);
return UnhandledExceptionFilter(ptr);
}
/*******************************************************************
* _global_unwind2 (MSVCRT.@)
*/
void __cdecl MSVCRT__global_unwind2(PEXCEPTION_FRAME frame)
{
#if defined(__GNUC__) && defined(__i386__)
TRACE("(%p)\n",frame);
if (0)
unwind_label: return;
RtlUnwind( frame, &&unwind_label, 0, 0 );
#else
FIXME("(%p) stub\n",frame);
#endif
}
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void __cdecl MSVCRT__local_unwind2(MSVCRT_EXCEPTION_REGISTRATION *endframe, DWORD nr )
{
FIXME("(%p,%ld) stub\n",endframe,nr);
}
/*********************************************************************
* _except_handler2 (MSVCRT.@)
*/
int __cdecl MSVCRT__except_handler2(PEXCEPTION_RECORD rec,
PEXCEPTION_FRAME frame,
PCONTEXT context, PEXCEPTION_FRAME *dispatcher)
{
FIXME("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
frame->Handler, context, dispatcher);
return ExceptionContinueSearch;
}
/*********************************************************************
* _except_handler3 (MSVCRT.@)
*/
int __cdecl MSVCRT__except_handler3(PEXCEPTION_RECORD rec,
MSVCRT_EXCEPTION_REGISTRATION *frame,
PCONTEXT context,void *dispatcher)
{
FIXME("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
frame->handler, context, dispatcher);
return ExceptionContinueSearch;
}
/*********************************************************************
* _abnormal_termination (MSVCRT.@)
*/
int __cdecl MSVCRT__abnormal_termination(void)
{
FIXME("(void)stub\n");
return 0;
}
/*******************************************************************
* _setjmp (MSVCRT.@)
*/
int __cdecl MSVCRT__setjmp(LPDWORD *jmpbuf)
{
FIXME(":(%p): stub\n",jmpbuf);
return 0;
}
/*********************************************************************
* longjmp (MSVCRT.@)
*/
void __cdecl MSVCRT_longjmp(jmp_buf env, int val)
{
FIXME("MSVCRT_longjmp semistub, expect crash\n");
longjmp(env, val);
}
/*********************************************************************
* signal (MSVCRT.@)
*/
void * __cdecl MSVCRT_signal(int sig, MSVCRT_sig_handler_func func)
{
FIXME("(%d %p):stub\n", sig, func);
return (void*)-1;
}
/*
* msvcrt.dll exit functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* MT */
extern CRITICAL_SECTION MSVCRT_exit_cs;
#define LOCK_EXIT EnterCriticalSection(&MSVCRT_exit_cs)
#define UNLOCK_EXIT LeaveCriticalSection(&MSVCRT_exit_cs)
typedef void (__cdecl *MSVCRT_atexit_func)(void);
static MSVCRT_atexit_func *MSVCRT_atexit_table = NULL;
static int MSVCRT_atexit_table_size = 0;
static int MSVCRT_atexit_registered = 0; /* Points to free slot */
extern int MSVCRT_app_type;
/* INTERNAL: call atexit functions */
void __MSVCRT__call_atexit(void)
{
/* Note: should only be called with the exit lock held */
TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
/* Last registered gets executed first */
while (MSVCRT_atexit_registered > 0)
{
MSVCRT_atexit_registered--;
TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
(*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
TRACE("returned\n");
}
}
/*********************************************************************
* __dllonexit (MSVCRT.@)
*/
void __cdecl MSVCRT___dllonexit (MSVCRT_atexit_func func, MSVCRT_atexit_func **start,
MSVCRT_atexit_func **end)
{
FIXME("(%p,%p,%p)stub\n", func, start,end);
/* FIXME: How do we know when to increase the table? */
}
/*********************************************************************
* _exit (MSVCRT.@)
*/
void __cdecl MSVCRT__exit(int exitcode)
{
TRACE("(%d)\n", exitcode);
ExitProcess(exitcode);
}
/*********************************************************************
* _amsg_exit (MSVCRT.@)
*/
void __cdecl MSVCRT__amsg_exit(int errnum)
{
TRACE("(%d)\n", errnum);
/* FIXME: text for the error number. */
if (MSVCRT_app_type == 2)
{
/* FIXME: MsgBox */
}
MSVCRT__cprintf("\nruntime error R60%d\n",errnum);
MSVCRT__exit(255);
}
/*********************************************************************
* abort (MSVCRT.@)
*/
void __cdecl MSVCRT_abort(void)
{
TRACE("(void)\n");
if (MSVCRT_app_type == 2)
{
/* FIXME: MsgBox */
}
MSVCRT__cputs("\nabnormal program termination\n");
MSVCRT__exit(3);
}
/*********************************************************************
* _assert (MSVCRT.@)
*/
void __cdecl MSVCRT__assert(const char* str, const char* file, unsigned int line)
{
TRACE("(%s,%s,%d)\n",str,file,line);
if (MSVCRT_app_type == 2)
{
/* FIXME: MsgBox */
}
MSVCRT__cprintf("Assertion failed: %s, file %s, line %d\n\n",str,file, line);
MSVCRT_abort();
}
/*********************************************************************
* _c_exit (MSVCRT.@)
*/
void __cdecl MSVCRT__c_exit(void)
{
TRACE("(void)\n");
/* All cleanup is done on DLL detach; Return to caller */
}
/*********************************************************************
* _cexit (MSVCRT.@)
*/
void __cdecl MSVCRT__cexit(void)
{
TRACE("(void)\n");
/* All cleanup is done on DLL detach; Return to caller */
}
/*********************************************************************
* _onexit (MSVCRT.@)
*/
MSVCRT_atexit_func __cdecl MSVCRT__onexit(MSVCRT_atexit_func func)
{
TRACE("(%p)\n",func);
if (!func)
return NULL;
LOCK_EXIT;
if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
{
MSVCRT_atexit_func *newtable;
TRACE("expanding table\n");
newtable = MSVCRT_calloc(sizeof(void *),MSVCRT_atexit_table_size + 32);
if (!newtable)
{
TRACE("failed!\n");
UNLOCK_EXIT;
return NULL;
}
memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size);
MSVCRT_atexit_table_size += 32;
if (MSVCRT_atexit_table)
MSVCRT_free (MSVCRT_atexit_table);
MSVCRT_atexit_table = newtable;
}
MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
MSVCRT_atexit_registered++;
UNLOCK_EXIT;
return func;
}
/*********************************************************************
* exit (MSVCRT.@)
*/
void __cdecl MSVCRT_exit(int exitcode)
{
TRACE("(%d)\n",exitcode);
LOCK_EXIT;
__MSVCRT__call_atexit();
UNLOCK_EXIT;
ExitProcess(exitcode);
}
/*********************************************************************
* atexit (MSVCRT.@)
*/
int __cdecl MSVCRT_atexit(MSVCRT_atexit_func func)
{
TRACE("(%p)\n", func);
return MSVCRT__onexit(func) == func ? 0 : -1;
}
/*********************************************************************
* _purecall (MSVCRT.@)
*/
void __cdecl MSVCRT__purecall(void)
{
TRACE("(void)\n");
MSVCRT__amsg_exit( 25 );
}
/*
* msvcrt.dll heap functions
*
* Copyright 2000 Jon Griffiths
*
* Note: Win32 heap operations are MT safe. We only lock the new
* handler and non atomic heap operations
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* MT */
extern CRITICAL_SECTION MSVCRT_heap_cs;
#define LOCK_HEAP EnterCriticalSection(&MSVCRT_heap_cs)
#define UNLOCK_HEAP LeaveCriticalSection(&MSVCRT_heap_cs)
/* heap function constants */
#define MSVCRT_HEAPEMPTY -1
#define MSVCRT_HEAPOK -2
#define MSVCRT_HEAPBADBEGIN -3
#define MSVCRT_HEAPBADNODE -4
#define MSVCRT_HEAPEND -5
#define MSVCRT_HEAPBADPTR -6
#define MSVCRT_FREEENTRY 0
#define MSVCRT_USEDENTRY 1
typedef struct MSVCRT_heapinfo
{
int * _pentry;
size_t _size;
int _useflag;
} MSVCRT_HEAPINFO;
typedef void (*MSVCRT_new_handler_func)(void);
static MSVCRT_new_handler_func MSVCRT_new_handler;
static int MSVCRT_new_mode;
/*********************************************************************
* ??2@YAPAXI@Z (MSVCRT.@)
*/
void *__cdecl MSVCRT_operator_new(unsigned long size)
{
void *retval = HeapAlloc(GetProcessHeap(), 0, size);
TRACE("(%ld) returning %p\n", size, retval);
LOCK_HEAP;
if(retval && MSVCRT_new_handler)
(*MSVCRT_new_handler)();
UNLOCK_HEAP;
return retval;
}
/*********************************************************************
* ??3@YAXPAX@Z (MSVCRT.@)
*/
void __cdecl MSVCRT_operator_delete(void *mem)
{
TRACE("(%p)\n", mem);
HeapFree(GetProcessHeap(), 0, mem);
}
/*********************************************************************
* ?_query_new_handler@@YAP6AHI@ZXZ (MSVCRT.@)
*/
MSVCRT_new_handler_func __cdecl MSVCRT__query_new_handler(void)
{
return MSVCRT_new_handler;
}
/*********************************************************************
* ?_query_new_mode@@YAHXZ (MSVCRT.@)
*/
int __cdecl MSVCRT__query_new_mode(void)
{
return MSVCRT_new_mode;
}
/*********************************************************************
* ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z (MSVCRT.@)
*/
MSVCRT_new_handler_func __cdecl MSVCRT__set_new_handler(MSVCRT_new_handler_func func)
{
MSVCRT_new_handler_func old_handler;
LOCK_HEAP;
old_handler = MSVCRT_new_handler;
MSVCRT_new_handler = func;
UNLOCK_HEAP;
return old_handler;
}
/*********************************************************************
* ?_set_new_mode@@YAHH@Z (MSVCRT.@)
*/
int __cdecl MSVCRT__set_new_mode(int mode)
{
int old_mode;
LOCK_HEAP;
old_mode = MSVCRT_new_mode;
MSVCRT_new_mode = mode;
UNLOCK_HEAP;
return old_mode;
}
/*********************************************************************
* _expand (MSVCRT.@)
*/
void *__cdecl MSVCRT__expand(void *mem, unsigned int size)
{
return HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, mem, size);
}
/*********************************************************************
* _heapchk (MSVCRT.@)
*/
int __cdecl MSVCRT__heapchk(void)
{
if (!HeapValidate( GetProcessHeap(), 0, NULL))
{
MSVCRT__set_errno(GetLastError());
return MSVCRT_HEAPBADNODE;
}
return MSVCRT_HEAPOK;
}
/*********************************************************************
* _heapmin (MSVCRT.@)
*/
int __cdecl MSVCRT__heapmin(void)
{
if (!HeapCompact( GetProcessHeap(), 0 ))
{
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
MSVCRT__set_errno(GetLastError());
return -1;
}
return 0;
}
/*********************************************************************
* _heapwalk (MSVCRT.@)
*/
int __cdecl MSVCRT__heapwalk(MSVCRT_HEAPINFO *next)
{
PROCESS_HEAP_ENTRY phe;
LOCK_HEAP;
phe.lpData = next->_pentry;
phe.cbData = next->_size;
phe.wFlags = next->_useflag == MSVCRT_USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
!HeapValidate( GetProcessHeap(), 0, phe.lpData ))
{
UNLOCK_HEAP;
MSVCRT__set_errno(GetLastError());
return MSVCRT_HEAPBADNODE;
}
do
{
if (!HeapWalk( GetProcessHeap(), &phe ))
{
UNLOCK_HEAP;
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return MSVCRT_HEAPEND;
MSVCRT__set_errno(GetLastError());
if (!phe.lpData)
return MSVCRT_HEAPBADBEGIN;
return MSVCRT_HEAPBADNODE;
}
} while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
UNLOCK_HEAP;
next->_pentry = phe.lpData;
next->_size = phe.cbData;
next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? MSVCRT_USEDENTRY : MSVCRT_FREEENTRY;
return MSVCRT_HEAPOK;
}
/*********************************************************************
* _heapset (MSVCRT.@)
*/
int __cdecl MSVCRT__heapset(unsigned int value)
{
int retval;
MSVCRT_HEAPINFO heap;
memset( &heap, 0, sizeof(MSVCRT_HEAPINFO) );
LOCK_HEAP;
while ((retval = MSVCRT__heapwalk(&heap)) == MSVCRT_HEAPOK)
{
if (heap._useflag == MSVCRT_FREEENTRY)
memset(heap._pentry, value, heap._size);
}
UNLOCK_HEAP;
return retval == MSVCRT_HEAPEND? MSVCRT_HEAPOK : retval;
}
/*********************************************************************
* _msize (MSVCRT.@)
*/
long __cdecl MSVCRT__msize(void *mem)
{
long size = HeapSize(GetProcessHeap(),0,mem);
if (size == -1)
{
WARN(":Probably called with non wine-allocated memory, ret = -1\n");
/* At least the Win32 crtdll/msvcrt also return -1 in this case */
}
return size;
}
/*********************************************************************
* calloc (MSVCRT.@)
*/
void *__cdecl MSVCRT_calloc(unsigned int size, unsigned int count)
{
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
}
/*********************************************************************
* free (MSVCRT.@)
*/
void __cdecl MSVCRT_free(void *ptr)
{
HeapFree(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* malloc (MSVCRT.@)
*/
void * __cdecl MSVCRT_malloc(unsigned int size)
{
void *ret = HeapAlloc(GetProcessHeap(),0,size);
if (!ret)
MSVCRT__set_errno(GetLastError());
return ret;
}
/*********************************************************************
* realloc (MSVCRT.@)
*/
void *__cdecl MSVCRT_realloc(void *ptr, unsigned int size)
{
return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
}
/*
* msvcrt.dll initialisation functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* Index to TLS */
DWORD MSVCRT_tls_index;
/* MT locks */
CRITICAL_SECTION MSVCRT_heap_cs;
CRITICAL_SECTION MSVCRT_file_cs;
CRITICAL_SECTION MSVCRT_exit_cs;
CRITICAL_SECTION MSVCRT_console_cs;
CRITICAL_SECTION MSVCRT_locale_cs;
static inline BOOL MSVCRT_init_tls(void);
static inline BOOL MSVCRT_free_tls(void);
static inline void MSVCRT_init_critical_sections(void);
static inline void MSVCRT_free_critical_sections(void);
#ifdef __GNUC__
const char *MSVCRT_get_reason(DWORD reason) __attribute__((unused));
#else
const char *MSVCRT_get_reason(DWORD reason);
#endif
void MSVCRT_init_io(void);
void MSVCRT_init_console(void);
void MSVCRT_free_console(void);
void MSVCRT_init_args(void);
void MSVCRT_free_args(void);
void MSVCRT_init_vtables(void);
char *__cdecl MSVCRT_setlocale(int category, const char *locale);
/*********************************************************************
* Init
*/
BOOL WINAPI MSVCRT_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
MSVCRT_thread_data *tls;
TRACE("(0x%08x, %s, %p) pid(%ld), tid(%ld), tls(%ld)\n",
hinstDLL, MSVCRT_get_reason(fdwReason), lpvReserved,
(long)GetCurrentProcessId(), (long)GetCurrentThreadId(),
(long)MSVCRT_tls_index);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
if (!MSVCRT_init_tls())
return FALSE;
MSVCRT_init_vtables();
MSVCRT_init_critical_sections();
MSVCRT_init_io();
MSVCRT_init_console();
MSVCRT_init_args();
MSVCRT_setlocale(0, "C");
TRACE("finished process init\n");
/* FALL THROUGH for Initial TLS allocation!! */
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_critical_sections();
MSVCRT__fcloseall();
MSVCRT_free_console();
MSVCRT_free_args();
if (!MSVCRT_free_tls())
return FALSE;
TRACE("finished process free\n");
break;
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);
TRACE("finished thread free\n");
break;
}
return TRUE;
}
static inline BOOL MSVCRT_init_tls(void)
{
MSVCRT_tls_index = TlsAlloc();
if (MSVCRT_tls_index == TLS_OUT_OF_INDEXES)
{
ERR("TlsAlloc() failed!\n");
return FALSE;
}
return TRUE;
}
static inline BOOL MSVCRT_free_tls(void)
{
if (!TlsFree(MSVCRT_tls_index))
{
ERR("TlsFree() failed!\n");
return FALSE;
}
return TRUE;
}
static inline void MSVCRT_init_critical_sections(void)
{
InitializeCriticalSectionAndSpinCount(&MSVCRT_heap_cs, 4000);
InitializeCriticalSection(&MSVCRT_file_cs);
InitializeCriticalSection(&MSVCRT_exit_cs);
InitializeCriticalSection(&MSVCRT_console_cs);
InitializeCriticalSection(&MSVCRT_locale_cs);
}
static inline void MSVCRT_free_critical_sections(void)
{
DeleteCriticalSection(&MSVCRT_locale_cs);
DeleteCriticalSection(&MSVCRT_console_cs);
DeleteCriticalSection(&MSVCRT_exit_cs);
DeleteCriticalSection(&MSVCRT_file_cs);
DeleteCriticalSection(&MSVCRT_heap_cs);
}
const char *MSVCRT_get_reason(DWORD reason)
{
switch (reason)
{
case DLL_PROCESS_ATTACH: return "DLL_PROCESS_ATTACH";
case DLL_PROCESS_DETACH: return "DLL_PROCESS_DETACH";
case DLL_THREAD_ATTACH: return "DLL_THREAD_ATTACH";
case DLL_THREAD_DETACH: return "DLL_THREAD_DETACH";
}
return "UNKNOWN";
}
/*********************************************************************
* Fixup functions
*
* Anything not really understood but needed to make the DLL work
*/
void MSVCRT_I10_OUTPUT(void)
{
/* FIXME: This is probably data, not a function */
}
void MSVCRT___unDName(void)
{
/* Called by all VC compiled progs on startup. No idea what it does */
}
void MSVCRT___unDNameEx(void)
{
/* As above */
}
/*
* msvcrt.dll misc functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef INT (__cdecl *MSVCRT_comp_func)(LPCVOID, LPCVOID );
/*********************************************************************
* _beep (MSVCRT.@)
*/
void __cdecl MSVCRT__beep( unsigned int freq, unsigned int duration)
{
TRACE(":Freq %d, Duration %d\n",freq,duration);
Beep(freq, duration);
}
extern int rand(void);
/*********************************************************************
* rand (MSVCRT.@)
*/
INT __cdecl MSVCRT_rand()
{
return (rand() & 0x7fff);
}
/*********************************************************************
* _sleep (MSVCRT.@)
*/
VOID __cdecl MSVCRT__sleep(ULONG timeout)
{
TRACE("MSVCRT__sleep for %ld milliseconds\n",timeout);
Sleep((timeout)?timeout:1);
}
/*********************************************************************
* _lfind (MSVCRT.@)
*/
void* __cdecl MSVCRT__lfind(const void * match, const void * start,
unsigned int * array_size,unsigned int elem_size, MSVCRT_comp_func cf)
{
unsigned int size = *array_size;
if (size)
do
{
if (cf(match, start) == 0)
return (void *)start; /* found */
start += elem_size;
} while (--size);
return NULL;
}
/*********************************************************************
* _lsearch (MSVCRT.@)
*/
void * __cdecl MSVCRT__lsearch(const void * match,void * start,
unsigned int * array_size,unsigned int elem_size, MSVCRT_comp_func cf)
{
unsigned int size = *array_size;
if (size)
do
{
if (cf(match, start) == 0)
return start; /* found */
start += elem_size;
} while (--size);
/* not found, add to end */
memcpy(start, match, elem_size);
array_size[0]++;
return start;
}
/*********************************************************************
* _chkesp (MSVCRT.@)
*/
void __cdecl MSVCRT__chkesp(void)
{
}
#ifndef __WINE_MSVCRT_ERRNO_H
#define __WINE_MSVCRT_ERRNO_H
#define MSVCRT_EPERM 1
#define MSVCRT_ENOENT 2
#define MSVCRT_ESRCH 3
#define MSVCRT_EINTR 4
#define MSVCRT_EIO 5
#define MSVCRT_ENXIO 6
#define MSVCRT_E2BIG 7
#define MSVCRT_ENOEXEC 8
#define MSVCRT_EBADF 9
#define MSVCRT_ECHILD 10
#define MSVCRT_EAGAIN 11
#define MSVCRT_ENOMEM 12
#define MSVCRT_EACCES 13
#define MSVCRT_EFAULT 14
#define MSVCRT_EBUSY 16
#define MSVCRT_EEXIST 17
#define MSVCRT_EXDEV 18
#define MSVCRT_ENODEV 19
#define MSVCRT_ENOTDIR 20
#define MSVCRT_EISDIR 21
#define MSVCRT_EINVAL 22
#define MSVCRT_ENFILE 23
#define MSVCRT_EMFILE 24
#define MSVCRT_ENOTTY 25
#define MSVCRT_EFBIG 27
#define MSVCRT_ENOSPC 28
#define MSVCRT_ESPIPE 29
#define MSVCRT_EROFS 30
#define MSVCRT_EMLINK 31
#define MSVCRT_EPIPE 32
#define MSVCRT_EDOM 33
#define MSVCRT_ERANGE 34
#define MSVCRT_EDEADLK 36
#define MSVCRT_ENAMETOOLONG 38
#define MSVCRT_ENOLCK 39
#define MSVCRT_ENOSYS 40
#define MSVCRT_ENOTEMPTY 41
#endif /* __WINE_MSVCRT_ERRNO_H */
#ifndef __WINE_MSVCRT_H
#define __WINE_MSVCRT_H
#include "config.h"
#include "windef.h"
#include "debugtools.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include <stdarg.h>
/* Files */
#define MSVCRT_EOF -1
#define MSVCRT_WEOF (WCHAR)(0xFFFF)
/* TLS data */
extern DWORD MSVCRT_tls_index;
typedef struct __MSVCRT_thread_data
{
int errno;
int doserrno;
} 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
void MSVCRT__set_errno(int);
int __cdecl MSVCRT__fcloseall(void);
void *__cdecl MSVCRT_malloc(unsigned int);
void *__cdecl MSVCRT_calloc(unsigned int, unsigned int);
void __cdecl MSVCRT_free(void *);
int __cdecl MSVCRT__cputs(const char *);
int __cdecl MSVCRT__cprintf( const char *, ... );
char *__cdecl MSVCRT__strdup(const char *);
#endif /* __WINE_MSVCRT_H */
/*
* msvcrt.dll spawn/exec functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* FIXME:
* -File handles need some special handling. Sometimes children get
* open file handles, sometimes not. The docs are confusing
* -No check for maximum path/argument/environment size is done
*/
#include "msvcrt.h"
#include "ms_errno.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* Process creation flags */
#define _P_WAIT 0
#define _P_NOWAIT 1
#define _P_OVERLAY 2
#define _P_NOWAITO 3
#define _P_DETACH 4
void __cdecl MSVCRT__exit(int);
void __cdecl MSVCRT__searchenv(const char* file, const char* env, char *buf);
/* FIXME: Check file extenstions for app to run */
static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
/* INTERNAL: Spawn a child process */
static int __MSVCRT__spawn(int flags, const char *exe, char * args, char *env)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
if (sizeof(HANDLE) != sizeof(int))
WARN("This call is unsuitable for your architecture\n");
if ((unsigned)flags > _P_DETACH)
{
SET_THREAD_VAR(errno,MSVCRT_EINVAL);
return -1;
}
FIXME(":must dup/kill streams for child process\n");
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcessA(exe, args, NULL, NULL, TRUE,
flags == _P_DETACH ? DETACHED_PROCESS : 0,
env, NULL, &si, &pi))
{
MSVCRT__set_errno(GetLastError());
return -1;
}
switch(flags)
{
case _P_WAIT:
WaitForSingleObject(pi.hProcess,-1); /* wait forvever */
GetExitCodeProcess(pi.hProcess,&pi.dwProcessId);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return (int)pi.dwProcessId;
case _P_DETACH:
CloseHandle(pi.hProcess);
pi.hProcess = 0;
/* fall through */
case _P_NOWAIT:
case _P_NOWAITO:
CloseHandle(pi.hThread);
return (int)pi.hProcess;
case _P_OVERLAY:
MSVCRT__exit(0);
}
return -1; /* can't reach here */
}
/* INTERNAL: Convert argv list to a single 'delim'-seperated string */
static char * __MSVCRT__argvtos(const char * *arg, char delim)
{
const char **search = arg;
long size = 0;
char *ret;
if (!arg && !delim)
return NULL;
/* get length */
while(*search)
{
size += strlen(*search) + 1;
search++;
}
if (!(ret = (char *)MSVCRT_calloc(size + 1, 1)))
return NULL;
/* fill string */
search = arg;
size = 0;
while(*search)
{
int strsize = strlen(*search);
memcpy(ret+size,*search,strsize);
ret[size+strsize] = delim;
size += strsize + 1;
search++;
}
return ret;
}
/*********************************************************************
* _cwait (MSVCRT.@)
*/
int __cdecl MSVCRT__cwait(int *status, int pid, int action)
{
HANDLE hPid = (HANDLE)pid;
int doserrno;
action = action; /* Remove warning */
if (!WaitForSingleObject(hPid, -1)) /* wait forever */
{
if (status)
{
DWORD stat;
GetExitCodeProcess(hPid, &stat);
*status = (int)stat;
}
return (int)pid;
}
doserrno = GetLastError();
if (doserrno == ERROR_INVALID_HANDLE)
{
SET_THREAD_VAR(errno, MSVCRT_ECHILD);
SET_THREAD_VAR(doserrno,doserrno);
}
else
MSVCRT__set_errno(doserrno);
return status ? *status = -1 : -1;
}
/*********************************************************************
* _spawnve (MSVCRT.@)
*/
int __cdecl MSVCRT__spawnve(int flags, const char *name, const char **argv,
const char **envv)
{
char * args = __MSVCRT__argvtos(argv,' ');
char * envs = __MSVCRT__argvtos(envv,0);
LPCSTR fullname = name;
int ret = -1;
FIXME(":not translating name %s to locate program\n",fullname);
TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
if (args)
{
ret = __MSVCRT__spawn(flags, fullname, args, envs);
MSVCRT_free(args);
}
if (envs)
MSVCRT_free(envs);
return ret;
}
/*********************************************************************
* _spawnv (MSVCRT.@)
*/
int __cdecl MSVCRT__spawnv(int flags, const char *name, const char **argv)
{
return MSVCRT__spawnve(flags, name, argv, NULL);
}
/*********************************************************************
* _spawnvpe (MSVCRT.@)
*/
int __cdecl MSVCRT__spawnvpe(int flags, const char *name, const char **argv,
const char **envv)
{
char fullname[MAX_PATH];
MSVCRT__searchenv(name, "PATH", fullname);
return MSVCRT__spawnve(flags, fullname[0] ? fullname : name, argv, envv);
}
/*********************************************************************
* _spawnvp (MSVCRT.@)
*/
int __cdecl MSVCRT__spawnvp(int flags, const char *name, const char **argv)
{
return MSVCRT__spawnvpe(flags, name, argv, NULL);
}
/*********************************************************************
* system (MSVCRT.@)
*/
int __cdecl MSVCRT_system(const char *cmd)
{
/* FIXME: should probably launch cmd interpreter in COMSPEC */
return __MSVCRT__spawn(_P_WAIT, cmd, NULL, NULL);
}
/*********************************************************************
* _loaddll (MSVCRT.@)
*/
int __cdecl MSVCRT__loaddll(const char *dllname)
{
return LoadLibraryA(dllname);
}
/*********************************************************************
* _unloaddll (MSVCRT.@)
*/
int __cdecl MSVCRT__unloaddll(int dll)
{
if (FreeLibrary((HANDLE)dll))
return 0;
else
{
int err = GetLastError();
MSVCRT__set_errno(err);
return err;
}
}
/*
* MSVCRT string functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* INTERNAL: MSVCRT_malloc() based strndup */
char * MSVCRT__strndup(const char * buf, unsigned int size)
{
char* ret;
unsigned int len = strlen(buf), max_len;
max_len = size <= len? size : len + 1;
ret = MSVCRT_malloc(max_len);
if (ret)
{
memcpy(ret,buf,max_len);
ret[max_len] = 0;
}
return ret;
}
/*********************************************************************
* _strdec (MSVCRT.@)
*/
char * __cdecl MSVCRT__strdec(const char * str1, const char * str2)
{
/* Hmm. While the docs suggest that the following should work... */
/* return (str2<=str1?0:str2-1); */
/* ...Version 2.50.4170 (NT) from win98 constantly decrements! */
str1 = str1; /* remove warning */
return (char *)str2-1;
}
/*********************************************************************
* _strdup (MSVCRT.@)
*/
char * __cdecl MSVCRT__strdup(const char * str)
{
char * ret = MSVCRT_malloc(strlen(str)+1);
if (ret) strcpy( ret, str );
return ret;
}
/*********************************************************************
* _strinc (MSVCRT.@)
*/
char * __cdecl MSVCRT__strinc(const char * str)
{
return (char*)str+1;
}
/*********************************************************************
* _strnextc (MSVCRT.@)
*/
unsigned int __cdecl MSVCRT__strnextc(const char * str)
{
return (unsigned int)*str;
}
/*********************************************************************
* _strninc (MSVCRT.@)
*
* Return a pointer to the 'n'th character in a string
*/
char * __cdecl MSVCRT__strninc(char * str, unsigned int n)
{
return str + n;
}
/*********************************************************************
* _strnset (MSVCRT.@)
*/
char * __cdecl MSVCRT__strnset(char * str, int value, unsigned int len)
{
if (len > 0 && str)
while (*str && len--)
*str++ = value;
return str;
}
/*********************************************************************
* _strrev (MSVCRT.@)
*/
char * __cdecl MSVCRT__strrev (char * str)
{
char * p1;
char * p2;
if (str && *str)
for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
return str;
}
/*********************************************************************
* _strset (MSVCRT.@)
*/
char * __cdecl MSVCRT__strset (char * str, int value)
{
char *ptr = str;
while (*ptr)
*ptr++ = value;
return str;
}
/*********************************************************************
* _strncnt (MSVCRT.@)
*/
unsigned int __cdecl MSVCRT__strncnt(char * str, unsigned int max)
{
unsigned int len = strlen(str);
return (len > max? max : len);
}
/*********************************************************************
* _strspnp (MSVCRT.@)
*/
char * __cdecl MSVCRT__strspnp(char * str1, char * str2)
{
str1 += strspn(str1,str2);
return *str1? str1 : 0;
}
/*********************************************************************
* _swab (MSVCRT.@)
*/
void __cdecl MSVCRT__swab(char * src, char * dst, int len)
{
if (len > 1)
{
len = (unsigned)len >> 1;
while (len--) {
*dst++ = src[1];
*dst++ = *src++;
src++;
}
}
}
/*
* msvcrt.dll thread functions
*
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/*********************************************************************
* _beginthreadex (MSVCRT.@)
*/
unsigned long __cdecl MSVCRT__beginthreadex(void *sec,
unsigned int stack,
LPTHREAD_START_ROUTINE start,
void *arg, unsigned flag,
unsigned int*addr)
{
TRACE("(%p,%d,%p,%p,%d,%p)\n",sec, stack,start, arg,flag,addr);
/* FIXME */
return CreateThread( sec, stack, (LPTHREAD_START_ROUTINE)start, arg,flag,(LPDWORD)addr);
}
/*********************************************************************
* _endthreadex (MSVCRT.@)
*/
void __cdecl MSVCRT__endthreadex(unsigned int retval)
{
TRACE("(%d)\n",retval);
/* FIXME */
ExitThread(retval);
}
/*
* msvcrt.dll date/time functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*/
#include <time.h>
#include <sys/times.h>
#include "msvcrt.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef struct __MSVCRT_timeb
{
time_t time;
unsigned short millitm;
short timezone;
short dstflag;
} MSVCRT_timeb;
/* INTERNAL: Return formatted current time/date */
char * MSVCRT_get_current_time(char * out, const char * format)
{
static const time_t bad_time = (time_t)-1;
time_t t;
struct tm *_tm = NULL;
char *retval = NULL;
if (time(&t) != bad_time && (_tm = localtime(&t)) &&
strftime(out,9,format,_tm) == 8)
retval = out;
if (_tm)
MSVCRT_free(_tm);
return retval;
}
/**********************************************************************
* _strdate (MSVCRT.@)
*/
char * __cdecl MSVCRT__strdate (char * date)
{
return MSVCRT_get_current_time(date,"%m/%d/%y");
}
/*********************************************************************
* _strtime (MSVCRT.@)
*/
char * __cdecl MSVCRT__strtime (char * date)
{
return MSVCRT_get_current_time(date,"%H:%M:%S");
}
/*********************************************************************
* clock (MSVCRT.@)
*/
clock_t __cdecl MSVCRT_clock(void)
{
struct tms alltimes;
clock_t res;
times(&alltimes);
res = alltimes.tms_utime + alltimes.tms_stime +
alltimes.tms_cutime + alltimes.tms_cstime;
/* FIXME: We need some symbolic representation for CLOCKS_PER_SEC,
* 10 holds only for Windows/Linux_i86)
*/
return 10*res;
}
/*********************************************************************
* difftime (MSVCRT.@)
*/
double __cdecl MSVCRT_difftime (time_t time1, time_t time2)
{
return (double)(time1 - time2);
}
/*********************************************************************
* time (MSVCRT.@)
*/
time_t __cdecl MSVCRT_time(time_t *buf)
{
time_t curtime = time(NULL);
return buf ? *buf = curtime : curtime;
}
/*********************************************************************
* _ftime (MSVCRT.@)
*/
void __cdecl MSVCRT__ftime (MSVCRT_timeb *buf)
{
buf->time = MSVCRT_time(NULL);
buf->millitm = 0; /* FIXME */
buf->timezone = 0;
buf->dstflag = 0;
}
/*
* msvcrt.dll wide-char functions
*
* Copyright 1999 Alexandre Julliard
* Copyright 2000 Jon Griffiths
*/
#include "msvcrt.h"
#include "winnls.h"
#include "wine/unicode.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* INTERNAL: MSVCRT_malloc() based wstrndup */
LPWSTR MSVCRT__wstrndup(LPCWSTR buf, unsigned int size)
{
WCHAR* ret;
unsigned int len = strlenW(buf), max_len;
max_len = size <= len? size : len + 1;
ret = MSVCRT_malloc(max_len * sizeof (WCHAR));
if (ret)
{
memcpy(ret,buf,max_len * sizeof (WCHAR));
ret[max_len] = 0;
}
return ret;
}
/*********************************************************************
* MSVCRT__wcsdup (MSVCRT.@)
*/
LPWSTR __cdecl MSVCRT__wcsdup( LPCWSTR str )
{
LPWSTR ret = NULL;
if (str)
{
int size = (strlenW(str) + 1) * sizeof(WCHAR);
ret = MSVCRT_malloc( size );
if (ret) memcpy( ret, str, size );
}
return ret;
}
/*********************************************************************
* MSVCRT__wcsicoll (MSVCRT.@)
*/
INT __cdecl MSVCRT__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
{
/* FIXME: handle collates */
return strcmpiW( str1, str2 );
}
/*********************************************************************
* MSVCRT__wcsnset (MSVCRT.@)
*/
LPWSTR __cdecl MSVCRT__wcsnset( LPWSTR str, WCHAR c, INT n )
{
LPWSTR ret = str;
while ((n-- > 0) && *str) *str++ = c;
return ret;
}
/*********************************************************************
* MSVCRT__wcsrev (MSVCRT.@)
*/
LPWSTR __cdecl MSVCRT__wcsrev( LPWSTR str )
{
LPWSTR ret = str;
LPWSTR end = str + strlenW(str) - 1;
while (end > str)
{
WCHAR t = *end;
*end-- = *str;
*str++ = t;
}
return ret;
}
/*********************************************************************
* MSVCRT__wcsset (MSVCRT.@)
*/
LPWSTR __cdecl MSVCRT__wcsset( LPWSTR str, WCHAR c )
{
LPWSTR ret = str;
while (*str) *str++ = c;
return ret;
}
/*********************************************************************
* MSVCRT_wcscoll (MSVCRT.@)
*/
DWORD __cdecl MSVCRT_wcscoll( LPCWSTR str1, LPCWSTR str2 )
{
/* FIXME: handle collates */
return strcmpW( str1, str2 );
}
/*********************************************************************
* MSVCRT_wcspbrk (MSVCRT.@)
*/
LPWSTR __cdecl MSVCRT_wcspbrk( LPCWSTR str, LPCWSTR accept )
{
LPCWSTR p;
while (*str)
{
for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
str++;
}
return NULL;
}
/*********************************************************************
* MSVCRT_wctomb (MSVCRT.@)
*/
INT __cdecl MSVCRT_wctomb( LPSTR dst, WCHAR ch )
{
return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL );
}
/*********************************************************************
* MSVCRT_iswalnum (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswalnum( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* MSVCRT_iswalpha (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswalpha( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* MSVCRT_iswcntrl (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswcntrl( WCHAR wc )
{
return get_char_typeW(wc) & C1_CNTRL;
}
/*********************************************************************
* MSVCRT_iswdigit (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswdigit( WCHAR wc )
{
return get_char_typeW(wc) & C1_DIGIT;
}
/*********************************************************************
* MSVCRT_iswgraph (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswgraph( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* MSVCRT_iswlower (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswlower( WCHAR wc )
{
return get_char_typeW(wc) & C1_LOWER;
}
/*********************************************************************
* MSVCRT_iswprint (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswprint( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* MSVCRT_iswpunct (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswpunct( WCHAR wc )
{
return get_char_typeW(wc) & C1_PUNCT;
}
/*********************************************************************
* MSVCRT_iswspace (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswspace( WCHAR wc )
{
return get_char_typeW(wc) & C1_SPACE;
}
/*********************************************************************
* MSVCRT_iswupper (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswupper( WCHAR wc )
{
return get_char_typeW(wc) & C1_UPPER;
}
/*********************************************************************
* MSVCRT_iswxdigit (MSVCRT.@)
*/
INT __cdecl MSVCRT_iswxdigit( WCHAR wc )
{
return get_char_typeW(wc) & C1_XDIGIT;
}
extern LPSTR __cdecl _itoa( long , LPSTR , INT);
extern LPSTR __cdecl _ultoa( long , LPSTR , INT);
extern LPSTR __cdecl _ltoa( long , LPSTR , INT);
/*********************************************************************
* _itow (MSVCRT.@)
*/
WCHAR* __cdecl MSVCRT__itow(int value,WCHAR* out,int base)
{
char buf[64];
_itoa(value, buf, base);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
return out;
}
/*********************************************************************
* _ltow (MSVCRT.@)
*/
WCHAR* __cdecl MSVCRT__ltow(long value,WCHAR* out,int base)
{
char buf[128];
_ltoa(value, buf, base);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
return out;
}
/*********************************************************************
* _ultow (MSVCRT.@)
*/
WCHAR* __cdecl MSVCRT__ultow(unsigned long value,WCHAR* out,int base)
{
char buf[128];
_ultoa(value, buf, base);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
return out;
}
......@@ -93,6 +93,7 @@ WINE REGISTRY Version 2
"dsound" = "builtin, native"
"mmsystem" = "builtin"
"winmm" = "builtin"
"msvcrt" = "native, builtin"
"msvideo" = "builtin, native"
"msvfw32" = "builtin, native"
"mcicda.drv" = "builtin, native"
......
......@@ -43,6 +43,7 @@ static struct tagDllOverride {
{"advapi32,crtdll,ntdll", "builtin,native"},
{"lz32,lzexpand", "builtin,native"},
{"version,ver", "builtin,native"},
{"msvcrt", "native,builtin"},
/* "new" interface */
{"comdlg32,commdlg", "builtin,native"},
{"shell32,shell", "builtin,native"},
......
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