Skip to content
Snippets Groups Projects
Commit 1db20bfd authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard
Browse files

- Migrate CRTDLL to MSVCRT.

- Many fixes and a load of new functions.
parent ca43a641
No related merge requests found
Showing with 5166 additions and 0 deletions
......@@ -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 console functions
*
* Copyright 2000 Jon Griffiths
*
* Note: init and free don't need MT locking since they are called at DLL
* (de)attachment time, which is syncronised for us
*/
#include "msvcrt.h"
#include "wincon.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
/* MT */
extern CRITICAL_SECTION MSVCRT_console_cs;
#define LOCK_CONSOLE EnterCriticalSection(&MSVCRT_console_cs)
#define UNLOCK_CONSOLE LeaveCriticalSection(&MSVCRT_console_cs)
static HANDLE MSVCRT_console_in = INVALID_HANDLE_VALUE;
static HANDLE MSVCRT_console_out= INVALID_HANDLE_VALUE;
static int __MSVCRT_console_buffer = MSVCRT_EOF;
/* INTERNAL: Initialise console handles */
void MSVCRT_init_console(void)
{
TRACE(":Opening console handles\n");
MSVCRT_console_in = GetStdHandle(STD_INPUT_HANDLE);
/* FIXME: Should be initialised with:
* CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ,
* NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
*/
MSVCRT_console_out= CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
if ((MSVCRT_console_in == INVALID_HANDLE_VALUE) ||
(MSVCRT_console_out== INVALID_HANDLE_VALUE))
WARN(":Console handle Initialisation FAILED!\n");
}
/* INTERNAL: Free console handles */
void MSVCRT_free_console(void)
{
TRACE(":Closing console handles\n");
CloseHandle(MSVCRT_console_in);
CloseHandle(MSVCRT_console_out);
}
/*********************************************************************
* _cputs (MSVCRT.@)
*/
int __cdecl MSVCRT__cputs(const char * str)
{
DWORD count;
int retval = MSVCRT_EOF;
LOCK_CONSOLE;
if (WriteConsoleA(MSVCRT_console_out, str, strlen(str), &count, NULL)
&& count == 1)
retval = 0;
UNLOCK_CONSOLE;
return retval;
}
/*********************************************************************
* _getch (MSVCRT.@)
*/
int __cdecl MSVCRT__getch(void)
{
int retval = MSVCRT_EOF;
LOCK_CONSOLE;
if (__MSVCRT_console_buffer != MSVCRT_EOF)
{
retval = __MSVCRT_console_buffer;
__MSVCRT_console_buffer = MSVCRT_EOF;
}
else
{
INPUT_RECORD ir;
DWORD count;
DWORD mode = 0;
GetConsoleMode(MSVCRT_console_in, &mode);
if(mode)
SetConsoleMode(MSVCRT_console_in, 0);
do {
if (ReadConsoleInputA(MSVCRT_console_in, &ir, 1, &count))
{
/* Only interested in ASCII chars */
if (ir.EventType == KEY_EVENT &&
ir.Event.KeyEvent.bKeyDown &&
ir.Event.KeyEvent.uChar.AsciiChar)
{
retval = ir.Event.KeyEvent.uChar.AsciiChar;
break;
}
}
else
break;
} while(1);
if (mode)
SetConsoleMode(MSVCRT_console_in, mode);
}
UNLOCK_CONSOLE;
return retval;
}
/*********************************************************************
* _putch (MSVCRT.@)
*/
int __cdecl MSVCRT__putch(int c)
{
int retval = MSVCRT_EOF;
DWORD count;
LOCK_CONSOLE;
if (WriteConsoleA(MSVCRT_console_out, &c, 1, &count, NULL) && count == 1)
retval = c;
UNLOCK_CONSOLE;
return retval;
}
/*********************************************************************
* _getche (MSVCRT.@)
*/
int __cdecl MSVCRT__getche(void)
{
int retval;
LOCK_CONSOLE;
retval = MSVCRT__getch();
if (retval != MSVCRT_EOF)
retval = MSVCRT__putch(retval);
UNLOCK_CONSOLE;
return retval;
}
/*********************************************************************
* _cgets (MSVCRT.@)
*/
char *__cdecl MSVCRT__cgets(char *str)
{
char *buf = str + 2;
int c;
str[1] = 0; /* Length */
/* FIXME: No editing of string supported */
LOCK_CONSOLE;
do
{
if (str[1] >= str[0] || (str[1]++, c = MSVCRT__getche()) == MSVCRT_EOF || c == '\n')
break;
*buf++ = c & 0xff;
} while (1);
UNLOCK_CONSOLE;
*buf = '\0';
return str + 2;
}
/*********************************************************************
* _ungetch (MSVCRT.@)
*/
int __cdecl MSVCRT__ungetch(int c)
{
int retval = MSVCRT_EOF;
LOCK_CONSOLE;
if (c != MSVCRT_EOF && __MSVCRT_console_buffer == MSVCRT_EOF)
retval = __MSVCRT_console_buffer = c;
UNLOCK_CONSOLE;
return retval;
}
/*********************************************************************
* _cscanf (MSVCRT.@)
*/
int __cdecl MSVCRT__cscanf( const char * format, ... )
{
/* NOTE: If you extend this function, extend MSVCRT_fscanf in file.c too */
int rd = 0;
int nch;
va_list ap;
if (!*format) return 0;
WARN("\"%s\": semi-stub\n", format);
va_start(ap, format);
LOCK_CONSOLE;
nch = MSVCRT__getch();
while (*format) {
if (*format == ' ') {
/* skip whitespace */
while ((nch!=MSVCRT_EOF) && isspace(nch))
nch = MSVCRT__getch();
}
else if (*format == '%') {
int st = 0;
format++;
switch(*format) {
case 'd': { /* read an integer */
int*val = va_arg(ap, int*);
int cur = 0;
/* skip initial whitespace */
while ((nch!=MSVCRT_EOF) && isspace(nch))
nch = MSVCRT__getch();
/* get sign and first digit */
if (nch == '-') {
nch = MSVCRT__getch();
if (isdigit(nch))
cur = -(nch - '0');
else break;
} else {
if (isdigit(nch))
cur = nch - '0';
else break;
}
nch = MSVCRT__getch();
/* read until no more digits */
while ((nch!=MSVCRT_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = MSVCRT__getch();
}
st = 1;
*val = cur;
}
break;
case 'f': { /* read a float */
float*val = va_arg(ap, float*);
float cur = 0;
/* skip initial whitespace */
while ((nch!=MSVCRT_EOF) && isspace(nch))
nch = MSVCRT__getch();
/* get sign and first digit */
if (nch == '-') {
nch = MSVCRT__getch();
if (isdigit(nch))
cur = -(nch - '0');
else break;
} else {
if (isdigit(nch))
cur = nch - '0';
else break;
}
/* read until no more digits */
while ((nch!=MSVCRT_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = MSVCRT__getch();
}
if (nch == '.') {
/* handle decimals */
float dec = 1;
nch = MSVCRT__getch();
while ((nch!=MSVCRT_EOF) && isdigit(nch)) {
dec /= 10;
cur += dec * (nch - '0');
nch = MSVCRT__getch();
}
}
st = 1;
*val = cur;
}
break;
case 's': { /* read a word */
char*str = va_arg(ap, char*);
char*sptr = str;
/* skip initial whitespace */
while ((nch!=MSVCRT_EOF) && isspace(nch))
nch = MSVCRT__getch();
/* read until whitespace */
while ((nch!=MSVCRT_EOF) && !isspace(nch)) {
*sptr++ = nch; st++;
nch = MSVCRT__getch();
}
/* terminate */
*sptr = 0;
TRACE("read word: %s\n", str);
}
break;
default: FIXME("unhandled: %%%c\n", *format);
}
if (st) rd++;
else break;
}
else {
/* check for character match */
if (nch == *format)
nch = MSVCRT__getch();
else break;
}
format++;
}
if (nch != MSVCRT_EOF)
MSVCRT__ungetch(nch);
UNLOCK_CONSOLE;
va_end(ap);
TRACE("returning %d\n", rd);
return rd;
}
/*********************************************************************
* _kbhit (MSVCRT.@)
*/
int __cdecl MSVCRT__kbhit(void)
{
int retval = 0;
LOCK_CONSOLE;
if (__MSVCRT_console_buffer != MSVCRT_EOF)
retval = 1;
else
{
/* FIXME: There has to be a faster way than this in Win32.. */
INPUT_RECORD *ir = NULL;
DWORD count = 0, i;
GetNumberOfConsoleInputEvents(MSVCRT_console_in, &count);
if (count && (ir = MSVCRT_malloc(count * sizeof(INPUT_RECORD))) &&
PeekConsoleInputA(MSVCRT_console_in, ir, count, &count))
for(i = 0; i < count - 1; i++)
{
if (ir[i].EventType == KEY_EVENT &&
ir[i].Event.KeyEvent.bKeyDown &&
ir[i].Event.KeyEvent.uChar.AsciiChar)
{
retval = 1;
break;
}
}
if (ir)
MSVCRT_free(ir);
}
UNLOCK_CONSOLE;
return retval;
}
extern int snprintf(char *, int, const char *, ...);
/*********************************************************************
* _cprintf (MSVCRT.@)
*/
int __cdecl MSVCRT__cprintf( const char * format, ... )
{
char buf[2048], *mem = buf;
int written, resize = sizeof(buf), retval;
va_list valist;
va_start( valist, format );
/* There are two conventions for snprintf failing:
* Return -1 if we truncated, or
* Return the number of bytes that would have been written
* The code below handles both cases
*/
while ((written = snprintf( mem, resize, format, valist )) == -1 ||
written > resize)
{
resize = (written == -1 ? resize * 2 : written + 1);
if (mem != buf)
MSVCRT_free (mem);
if (!(mem = (char *)MSVCRT_malloc(resize)))
return MSVCRT_EOF;
va_start( valist, format );
}
va_end(valist);
LOCK_CONSOLE;
retval = MSVCRT__cputs( mem );
UNLOCK_CONSOLE;
if (mem != buf)
MSVCRT_free (mem);
return retval;
}
/*
* 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 drive/directory functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*/
#include <time.h>
#include "ntddk.h"
#include "wine/unicode.h"
#include "msvcrt.h"
#include "ms_errno.h"
DEFAULT_DEBUG_CHANNEL(msvcrt);
typedef struct MSVCRT_finddata_t
{
unsigned attrib;
time_t time_create; /* -1 when N/A */
time_t time_access; /* -1 when N/A */
time_t time_write;
unsigned long size; /* FIXME: 64 bit ??*/
char name[MAX_PATH];
} MSVCRT_finddata_t;
typedef struct MSVCRT_wfinddata_t
{
unsigned attrib;
time_t time_create; /* -1 when N/A */
time_t time_access; /* -1 when N/A */
time_t time_write;
unsigned long size; /* FIXME: 64 bit ??*/
WCHAR name[MAX_PATH];
} MSVCRT_wfinddata_t;
typedef struct __MSVCRT_diskfree_t {
unsigned num_clusters;
unsigned available;
unsigned cluster_sectors;
unsigned sector_bytes;
} MSVCRT_diskfree_t;
/* INTERNAL: Translate finddata_t to PWIN32_FIND_DATAA */
static void MSVCRT__fttofd(LPWIN32_FIND_DATAA fd, MSVCRT_finddata_t* ft)
{
DWORD dw;
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
ft->attrib = 0;
else
ft->attrib = fd->dwFileAttributes;
RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
ft->time_create = dw;
RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
ft->time_access = dw;
RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
ft->time_write = dw;
ft->size = fd->nFileSizeLow;
strcpy(ft->name, fd->cFileName);
}
/* INTERNAL: Translate wfinddata_t to PWIN32_FIND_DATAA */
static void MSVCRT__wfttofd(LPWIN32_FIND_DATAW fd, MSVCRT_wfinddata_t* ft)
{
DWORD dw;
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
ft->attrib = 0;
else
ft->attrib = fd->dwFileAttributes;
RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
ft->time_create = dw;
RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
ft->time_access = dw;
RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
ft->time_write = dw;
ft->size = fd->nFileSizeLow;
strcpyW(ft->name, fd->cFileName);
}
char * MSVCRT__strndup(const char *, unsigned int);
LPWSTR __cdecl MSVCRT__wcsdup( LPCWSTR );
LPWSTR __cdecl MSVCRT__wstrndup( LPCWSTR , unsigned int );
char *__cdecl MSVCRT_getenv(const char *);
/*********************************************************************
* _chdir (MSVCRT.@)
*/
int __cdecl MSVCRT__chdir(const char * newdir)
{
if (!SetCurrentDirectoryA(newdir))
{
MSVCRT__set_errno(newdir?GetLastError():0);
return -1;
}
return 0;
}
/*********************************************************************
* _wchdir (MSVCRT.@)
*/
int __cdecl MSVCRT__wchdir(const WCHAR * newdir)
{
if (!SetCurrentDirectoryW(newdir))
{
MSVCRT__set_errno(newdir?GetLastError():0);
return -1;
}
return 0;
}
/*********************************************************************
* _chdrive (MSVCRT.@)
*/
int __cdecl MSVCRT__chdrive(int newdrive)
{
char buffer[3] = "A:";
buffer[0] += newdrive - 1;
if (!SetCurrentDirectoryA( buffer ))
{
MSVCRT__set_errno(GetLastError());
if (newdrive <= 0)
SET_THREAD_VAR(errno,MSVCRT_EACCES);
return -1;
}
return 0;
}
/*********************************************************************
* _findclose (MSVCRT.@)
*/
int __cdecl MSVCRT__findclose(DWORD hand)
{
TRACE(":handle %ld\n",hand);
if (!FindClose((HANDLE)hand))
{
MSVCRT__set_errno(GetLastError());
return -1;
}
return 0;
}
/*********************************************************************
* _findfirst (MSVCRT.@)
*/
DWORD __cdecl MSVCRT__findfirst(const char * fspec, MSVCRT_finddata_t* ft)
{
WIN32_FIND_DATAA find_data;
HANDLE hfind;
hfind = FindFirstFileA(fspec, &find_data);
if (hfind == INVALID_HANDLE_VALUE)
{
MSVCRT__set_errno(GetLastError());
return -1;
}
MSVCRT__fttofd(&find_data,ft);
TRACE(":got handle %d\n",hfind);
return hfind;
}
/*********************************************************************
* _wfindfirst (MSVCRT.@)
*/
DWORD __cdecl MSVCRT__wfindfirst(const WCHAR * fspec, MSVCRT_wfinddata_t* ft)
{
WIN32_FIND_DATAW find_data;
HANDLE hfind;
hfind = FindFirstFileW(fspec, &find_data);
if (hfind == INVALID_HANDLE_VALUE)
{
MSVCRT__set_errno(GetLastError());
return -1;
}
MSVCRT__wfttofd(&find_data,ft);
TRACE(":got handle %d\n",hfind);
return hfind;
}
/*********************************************************************
* _findnext (MSVCRT.@)
*/
int __cdecl MSVCRT__findnext(DWORD hand, MSVCRT_finddata_t * ft)
{
WIN32_FIND_DATAA find_data;
if (!FindNextFileA(hand, &find_data))
{
SET_THREAD_VAR(errno,MSVCRT_ENOENT);
return -1;
}
MSVCRT__fttofd(&find_data,ft);
return 0;
}
/*********************************************************************
* _wfindnext (MSVCRT.@)
*/
int __cdecl MSVCRT__wfindnext(DWORD hand, MSVCRT_wfinddata_t * ft)
{
WIN32_FIND_DATAW find_data;
if (!FindNextFileW(hand, &find_data))
{
SET_THREAD_VAR(errno,MSVCRT_ENOENT);
return -1;
}
MSVCRT__wfttofd(&find_data,ft);
return 0;
}
/*********************************************************************
* _getcwd (MSVCRT.@)
*/
char* __cdecl MSVCRT__getcwd(char * buf, int size)
{
char dir[_MAX_PATH];
int dir_len = GetCurrentDirectoryA(MAX_PATH,dir);
if (dir_len < 1)
return NULL; /* FIXME: Real return value untested */
if (!buf)
{
if (size < 0)
return MSVCRT__strdup(dir);
return MSVCRT__strndup(dir,size);
}
if (dir_len >= size)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
return NULL; /* buf too small */
}
strcpy(buf,dir);
return buf;
}
/*********************************************************************
* _wgetcwd (MSVCRT.@)
*/
WCHAR* __cdecl MSVCRT__wgetcwd(WCHAR * buf, int size)
{
WCHAR dir[_MAX_PATH];
int dir_len = GetCurrentDirectoryW(MAX_PATH,dir);
if (dir_len < 1)
return NULL; /* FIXME: Real return value untested */
if (!buf)
{
if (size < 0)
return MSVCRT__wcsdup(dir);
return MSVCRT__wstrndup(dir,size);
}
if (dir_len >= size)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
return NULL; /* buf too small */
}
strcpyW(buf,dir);
return buf;
}
/*********************************************************************
* _getdrive (MSVCRT.@)
*/
int __cdecl MSVCRT__getdrive(void)
{
char buffer[MAX_PATH];
if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
if (buffer[1] != ':') return 0;
return toupper(buffer[0]) - 'A' + 1;
}
/*********************************************************************
* _getdcwd (MSVCRT.@)
*/
char* __cdecl MSVCRT__getdcwd(int drive, char * buf, int size)
{
static char* dummy;
TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
if (!drive || drive == MSVCRT__getdrive())
return MSVCRT__getcwd(buf,size); /* current */
else
{
char dir[_MAX_PATH];
char drivespec[4] = {'A', ':', '\\', 0};
int dir_len;
drivespec[0] += drive - 1;
if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
{
SET_THREAD_VAR(errno,MSVCRT_EACCES);
return NULL;
}
dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
return NULL; /* buf too small */
}
TRACE(":returning '%s'\n", dir);
if (!buf)
return MSVCRT__strdup(dir); /* allocate */
strcpy(buf,dir);
}
return buf;
}
/*********************************************************************
* _wgetdcwd (MSVCRT.@)
*/
WCHAR* __cdecl MSVCRT__wgetdcwd(int drive, WCHAR * buf, int size)
{
static WCHAR* dummy;
TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
if (!drive || drive == MSVCRT__getdrive())
return MSVCRT__wgetcwd(buf,size); /* current */
else
{
WCHAR dir[_MAX_PATH];
WCHAR drivespec[4] = {'A', ':', '\\', 0};
int dir_len;
drivespec[0] += drive - 1;
if (GetDriveTypeW(drivespec) < DRIVE_REMOVABLE)
{
SET_THREAD_VAR(errno,MSVCRT_EACCES);
return NULL;
}
dir_len = GetFullPathNameW(drivespec,_MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
return NULL; /* buf too small */
}
TRACE(":returning '%s'\n", debugstr_w(dir));
if (!buf)
return MSVCRT__wcsdup(dir); /* allocate */
strcpyW(buf,dir);
}
return buf;
}
/*********************************************************************
* _getdiskfree (MSVCRT.@)
*/
unsigned int __cdecl MSVCRT__getdiskfree(unsigned int disk, MSVCRT_diskfree_t* d)
{
char drivespec[4] = {'@', ':', '\\', 0};
DWORD ret[4];
unsigned int err;
if (disk > 26)
return ERROR_INVALID_PARAMETER; /* MSVCRT doesn't set errno here */
drivespec[0] += disk; /* make a drive letter */
if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
{
d->cluster_sectors = (unsigned)ret[0];
d->sector_bytes = (unsigned)ret[1];
d->available = (unsigned)ret[2];
d->num_clusters = (unsigned)ret[3];
return 0;
}
err = GetLastError();
MSVCRT__set_errno(err);
return err;
}
/*********************************************************************
* _mkdir (MSVCRT.@)
*/
int __cdecl MSVCRT__mkdir(const char * newdir)
{
if (CreateDirectoryA(newdir,NULL))
return 0;
MSVCRT__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _wmkdir (MSVCRT.@)
*/
int __cdecl MSVCRT__wmkdir(const WCHAR* newdir)
{
if (CreateDirectoryW(newdir,NULL))
return 0;
MSVCRT__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _rmdir (MSVCRT.@)
*/
int __cdecl MSVCRT__rmdir(const char * dir)
{
if (RemoveDirectoryA(dir))
return 0;
MSVCRT__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _wrmdir (MSVCRT.@)
*/
int __cdecl MSVCRT__wrmdir(const WCHAR * dir)
{
if (RemoveDirectoryW(dir))
return 0;
MSVCRT__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _splitpath (MSVCRT.@)
*/
void __cdecl MSVCRT__splitpath(const char* inpath, char * drv, char * dir,
char* fname, char * ext )
{
/* Modified PD code from 'snippets' collection. */
char ch, *ptr, *p;
char pathbuff[MAX_PATH],*path=pathbuff;
TRACE(":splitting path '%s'\n",path);
strcpy(pathbuff, inpath);
/* convert slashes to backslashes for searching */
for (ptr = (char*)path; *ptr; ++ptr)
if ('/' == *ptr)
*ptr = '\\';
/* look for drive spec */
if ('\0' != (ptr = strchr(path, ':')))
{
++ptr;
if (drv)
{
strncpy(drv, path, ptr - path);
drv[ptr - path] = '\0';
}
path = ptr;
}
else if (drv)
*drv = '\0';
/* find rightmost backslash or leftmost colon */
if (NULL == (ptr = strrchr(path, '\\')))
ptr = (strchr(path, ':'));
if (!ptr)
{
ptr = (char *)path; /* no path */
if (dir)
*dir = '\0';
}
else
{
++ptr; /* skip the delimiter */
if (dir)
{
ch = *ptr;
*ptr = '\0';
strcpy(dir, path);
*ptr = ch;
}
}
if (NULL == (p = strrchr(ptr, '.')))
{
if (fname)
strcpy(fname, ptr);
if (ext)
*ext = '\0';
}
else
{
*p = '\0';
if (fname)
strcpy(fname, ptr);
*p = '.';
if (ext)
strcpy(ext, p);
}
/* Fix pathological case - Win returns ':' as part of the
* directory when no drive letter is given.
*/
if (drv && drv[0] == ':')
{
*drv = '\0';
if (dir)
{
pathbuff[0] = ':';
pathbuff[1] = '\0';
strcat(pathbuff,dir);
strcpy(dir,pathbuff);
}
}
}
/* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */
static void fln_fix(char *path)
{
int dir_flag = 0, root_flag = 0;
char *r, *p, *q, *s;
/* Skip drive */
if (NULL == (r = strrchr(path, ':')))
r = path;
else
++r;
/* Ignore leading slashes */
while ('\\' == *r)
if ('\\' == r[1])
strcpy(r, &r[1]);
else
{
root_flag = 1;
++r;
}
p = r; /* Change "\\" to "\" */
while (NULL != (p = strchr(p, '\\')))
if ('\\' == p[1])
strcpy(p, &p[1]);
else
++p;
while ('.' == *r) /* Scrunch leading ".\" */
{
if ('.' == r[1])
{
/* Ignore leading ".." */
for (p = (r += 2); *p && (*p != '\\'); ++p)
;
}
else
{
for (p = r + 1 ;*p && (*p != '\\'); ++p)
;
}
strcpy(r, p + ((*p) ? 1 : 0));
}
while ('\\' == path[strlen(path)-1]) /* Strip last '\\' */
{
dir_flag = 1;
path[strlen(path)-1] = '\0';
}
s = r;
/* Look for "\." in path */
while (NULL != (p = strstr(s, "\\.")))
{
if ('.' == p[2])
{
/* Execute this section if ".." found */
q = p - 1;
while (q > r) /* Backup one level */
{
if (*q == '\\')
break;
--q;
}
if (q > r)
{
strcpy(q, p + 3);
s = q;
}
else if ('.' != *q)
{
strcpy(q + ((*q == '\\') ? 1 : 0),
p + 3 + ((*(p + 3)) ? 1 : 0));
s = q;
}
else s = ++p;
}
else
{
/* Execute this section if "." found */
q = p + 2;
for ( ;*q && (*q != '\\'); ++q)
;
strcpy (p, q);
}
}
if (root_flag) /* Embedded ".." could have bubbled up to root */
{
for (p = r; *p && ('.' == *p || '\\' == *p); ++p)
;
if (r != p)
strcpy(r, p);
}
if (dir_flag)
strcat(path, "\\");
}
/*********************************************************************
* _fullpath (MSVCRT.@)
*/
LPSTR __cdecl MSVCRT__fullpath(char * absPath, const char* relPath, unsigned int size)
{
char drive[5],dir[MAX_PATH],file[MAX_PATH],ext[MAX_PATH];
char res[MAX_PATH];
size_t len;
res[0] = '\0';
if (!relPath || !*relPath)
return MSVCRT__getcwd(absPath, size);
if (size < 4)
{
SET_THREAD_VAR(errno,MSVCRT_ERANGE);
return NULL;
}
TRACE(":resolving relative path '%s'\n",relPath);
MSVCRT__splitpath(relPath, drive, dir, file, ext);
/* Get Directory and drive into 'res' */
if (!dir[0] || (dir[0] != '/' && dir[0] != '\\'))
{
/* Relative or no directory given */
MSVCRT__getdcwd(drive[0] ? toupper(drive[0]) - 'A' + 1 : 0, res, MAX_PATH);
strcat(res,"\\");
if (dir[0])
strcat(res,dir);
if (drive[0])
res[0] = drive[0]; /* If given a drive, preserve the letter case */
}
else
{
strcpy(res,drive);
strcat(res,dir);
}
strcat(res,"\\");
strcat(res, file);
strcat(res, ext);
fln_fix(res);
len = strlen(res);
if (len >= MAX_PATH || len >= (size_t)size)
return NULL; /* FIXME: errno? */
if (!absPath)
return MSVCRT__strdup(res);
strcpy(absPath,res);
return absPath;
}
/*********************************************************************
* _makepath (MSVCRT.@)
*/
VOID __cdecl MSVCRT__makepath(char * path, const char * drive,
const char *directory, const char * filename,
const char * extension )
{
char ch;
TRACE("MSVCRT__makepath got %s %s %s %s\n", drive, directory,
filename, extension);
if ( !path )
return;
path[0] = 0;
if (drive && drive[0])
{
path[0] = drive[0];
path[1] = ':';
path[2] = 0;
}
if (directory && directory[0])
{
strcat(path, directory);
ch = path[strlen(path)-1];
if (ch != '/' && ch != '\\')
strcat(path,"\\");
}
if (filename && filename[0])
{
strcat(path, filename);
if (extension && extension[0])
{
if ( extension[0] != '.' )
strcat(path,".");
strcat(path,extension);
}
}
TRACE("MSVCRT__makepath returns %s\n",path);
}
/*********************************************************************
* _searchenv (MSVCRT.@)
*/
void __cdecl MSVCRT__searchenv(const char* file, const char* env, char *buf)
{
char*envVal, *penv;
char curPath[MAX_PATH];
*buf = '\0';
/* Try CWD first */
if (GetFileAttributesA( file ) != 0xFFFFFFFF)
{
GetFullPathNameA( file, MAX_PATH, buf, NULL );
/* Sigh. This error is *always* set, regardless of success */
MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
/* Search given environment variable */
envVal = MSVCRT_getenv(env);
if (!envVal)
{
MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
penv = envVal;
TRACE(":searching for %s in paths %s\n", file, envVal);
do
{
LPSTR end = penv;
while(*end && *end != ';') end++; /* Find end of next path */
if (penv == end || !*penv)
{
MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
strncpy(curPath, penv, end - penv);
if (curPath[end - penv] != '/' || curPath[end - penv] != '\\')
{
curPath[end - penv] = '\\';
curPath[end - penv + 1] = '\0';
}
else
curPath[end - penv] = '\0';
strcat(curPath, file);
TRACE("Checking for file %s\n", curPath);
if (GetFileAttributesA( curPath ) != 0xFFFFFFFF)
{
strcpy(buf, curPath);
MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
return; /* Found */
}
penv = *end ? end + 1 : end;
} while(1);
}
/*
* 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 );
}
This diff is collapsed.
/*
* 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);
}
This diff is collapsed.
/*
* 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 */
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment