Commit 0b47b289 authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard

Turn crtdll into forwards to msvcrt.

parent 5f308d3c
......@@ -412,7 +412,7 @@ advapi32/libadvapi32.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
avifil32/libavifil32.@LIBEXT@: libmsvfw32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
comctl32/libcomctl32.@LIBEXT@: libmsvfw32.@LIBEXT@ libwinmm.@LIBEXT@ libuser32.@LIBEXT@ libgdi32.@LIBEXT@ libadvapi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
commdlg/libcomdlg32.@LIBEXT@: libshell32.@LIBEXT@ libshlwapi.@LIBEXT@ libcomctl32.@LIBEXT@ libwinspool.drv.@LIBEXT@ libuser32.@LIBEXT@ libgdi32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
crtdll/libcrtdll.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
crtdll/libcrtdll.@LIBEXT@: libmsvcrt.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
dciman32/libdciman32.@LIBEXT@: libkernel32.@LIBEXT@ libntdll.@LIBEXT@
ddraw/libddraw.@LIBEXT@: libuser32.@LIBEXT@ libx11drv.@LIBEXT@ libgdi32.@LIBEXT@ libkernel32.@LIBEXT@
dinput/libdinput.@LIBEXT@: libuser32.@LIBEXT@ libkernel32.@LIBEXT@ libntdll.@LIBEXT@
......
......@@ -9,18 +9,7 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
console.c \
crtdll_main.c \
dir.c \
exit.c \
file.c \
locale.c \
mbstring.c \
memory.c \
spawn.c \
string.c \
time.c \
wcstring.c
crtdll_main.c
@MAKE_DLL_RULES@
......
/*
* CRTDLL console functions
*
* Copyright 2000 Jon Griffiths
*
* NOTES
* Only a one byte ungetch buffer is implemented, as per MS docs.
* Output is not redirectable using these functions, as per MS docs.
*
* FIXME:
* There are several problems with the console input mechanism as
* currently implemented in Wine. When these are ironed out the
* getch() function will work correctly (gets() is currently fine).
* The problem is that opening CONIN$ does not work, and
* reading from STD_INPUT_HANDLE is line buffered.
*/
#include "crtdll.h"
#include "wincon.h"
#include <stdio.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
static HANDLE __CRTDLL_console_in = INVALID_HANDLE_VALUE;
static HANDLE __CRTDLL_console_out = INVALID_HANDLE_VALUE;
static int __CRTDLL_console_buffer = CRTDLL_EOF;
/* INTERNAL: Initialise console handles */
VOID __CRTDLL_init_console(VOID)
{
TRACE(":Opening console handles\n");
__CRTDLL_console_in = GetStdHandle(STD_INPUT_HANDLE);
/* FIXME: Should be initialised with:
* CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ,
* NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
*/
__CRTDLL_console_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
if ((__CRTDLL_console_in == INVALID_HANDLE_VALUE) ||
(__CRTDLL_console_out == INVALID_HANDLE_VALUE))
WARN(":Console handle Initialisation FAILED!\n");
}
/* INTERNAL: Free console handles */
void __CRTDLL_free_console(void)
{
TRACE(":Closing console handles\n");
CloseHandle(__CRTDLL_console_in);
CloseHandle(__CRTDLL_console_out);
}
/*********************************************************************
* _cgets (CRTDLL.050)
*
* Get a string from CONIN$.
*/
LPSTR __cdecl CRTDLL__cgets(LPSTR str)
{
char *buf = str + 2;
int c;
str[1] = 0; /* Length */
/* FIXME: No editing of string supported */
do
{
if (str[1] >= str[0] || (str[1]++, c = CRTDLL__getche()) == CRTDLL_EOF || c == '\n')
{
*buf = '\0';
return str + 2;
}
*buf++ = c & 0xff;
} while(1);
}
/*********************************************************************
* _cprintf (CRTDLL.064)
*
* Write a formatted string to CONOUT$.
*/
INT __cdecl CRTDLL__cprintf( LPCSTR format, ... )
{
va_list valist;
char buffer[2048];
va_start( valist, format );
if (snprintf( buffer, sizeof(buffer), format, valist ) == -1)
ERR("Format too large for internal buffer!\n");
va_end(valist);
return CRTDLL__cputs( buffer );
}
/*********************************************************************
* _cputs (CRTDLL.065)
*
* Write a string to CONOUT$.
*/
INT __cdecl CRTDLL__cputs(LPCSTR str)
{
DWORD count;
if (WriteConsoleA(__CRTDLL_console_out, str, strlen(str), &count, NULL)
&& count == 1)
return 0;
return CRTDLL_EOF;
}
/*********************************************************************
* _cscanf (CRTDLL.067)
*
* Read formatted input from CONIN$.
*/
INT __cdecl CRTDLL__cscanf( LPCSTR format, ... )
{
/* NOTE: If you extend this function, extend CRTDLL_fscanf in file.c too */
INT rd = 0;
int nch;
va_list ap;
if (!*format) return 0;
WARN("\"%s\": semi-stub\n", format);
nch = CRTDLL__getch();
va_start(ap, format);
while (*format) {
if (*format == ' ') {
/* skip whitespace */
while ((nch!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL__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!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL__getch();
/* get sign and first digit */
if (nch == '-') {
nch = CRTDLL__getch();
if (isdigit(nch))
cur = -(nch - '0');
else break;
} else {
if (isdigit(nch))
cur = nch - '0';
else break;
}
nch = CRTDLL__getch();
/* read until no more digits */
while ((nch!=CRTDLL_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = CRTDLL__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!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL__getch();
/* get sign and first digit */
if (nch == '-') {
nch = CRTDLL__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!=CRTDLL_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = CRTDLL__getch();
}
if (nch == '.') {
/* handle decimals */
float dec = 1;
nch = CRTDLL__getch();
while ((nch!=CRTDLL_EOF) && isdigit(nch)) {
dec /= 10;
cur += dec * (nch - '0');
nch = CRTDLL__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!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL__getch();
/* read until whitespace */
while ((nch!=CRTDLL_EOF) && !isspace(nch)) {
*sptr++ = nch; st++;
nch = CRTDLL__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 = CRTDLL__getch();
else break;
}
format++;
}
va_end(ap);
if (nch != CRTDLL_EOF)
CRTDLL__ungetch(nch);
TRACE("returning %d\n", rd);
return rd;
}
/*********************************************************************
* _getch (CRTDLL.118)
*
* Get a character from CONIN$.
*/
INT __cdecl CRTDLL__getch(VOID)
{
if (__CRTDLL_console_buffer != CRTDLL_EOF)
{
INT retVal = __CRTDLL_console_buffer;
__CRTDLL_console_buffer = CRTDLL_EOF;
return retVal;
}
else
{
INPUT_RECORD ir;
DWORD count;
DWORD mode = 0;
GetConsoleMode(__CRTDLL_console_in, &mode);
if(mode) SetConsoleMode(__CRTDLL_console_in, 0);
do {
if (ReadConsoleInputA(__CRTDLL_console_in, &ir, 1, &count))
{
/* Only interested in ASCII chars */
if (ir.EventType == KEY_EVENT &&
ir.Event.KeyEvent.bKeyDown &&
ir.Event.KeyEvent.uChar.AsciiChar)
{
if(mode) SetConsoleMode(__CRTDLL_console_in, mode);
return ir.Event.KeyEvent.uChar.AsciiChar;
}
}
else
break;
} while(1);
if (mode) SetConsoleMode(__CRTDLL_console_in, mode);
}
return CRTDLL_EOF;
}
/*********************************************************************
* _getche (CRTDLL.119)
*
* Get a character from CONIN$ and echo it to CONOUT$.
*/
INT __cdecl CRTDLL__getche(VOID)
{
INT res = CRTDLL__getch();
if (res != CRTDLL_EOF && CRTDLL__putch(res) != CRTDLL_EOF)
return res;
return CRTDLL_EOF;
}
/*********************************************************************
* _kbhit (CRTDLL.169)
*
* Check if a character is waiting in CONIN$.
*/
INT __cdecl CRTDLL__kbhit(VOID)
{
if (__CRTDLL_console_buffer != CRTDLL_EOF)
return 1;
else
{
/* FIXME: There has to be a faster way than this in Win32.. */
INPUT_RECORD *ir;
DWORD count = 0, i;
int retVal = 0;
GetNumberOfConsoleInputEvents(__CRTDLL_console_in, &count);
if (!count)
return 0;
if (!(ir = CRTDLL_malloc(count * sizeof(INPUT_RECORD))))
return 0;
if (PeekConsoleInputA(__CRTDLL_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;
}
}
CRTDLL_free(ir);
return retVal;
}
}
/*********************************************************************
* _putch (CRTDLL.250)
*
* Write a character to CONOUT$.
*/
INT __cdecl CRTDLL__putch(INT c)
{
DWORD count;
if (WriteConsoleA(__CRTDLL_console_out, &c, 1, &count, NULL) &&
count == 1)
return c;
return CRTDLL_EOF;
}
/*********************************************************************
* _ungetch (CRTDLL.311)
*
* Un-get a character from CONIN$.
*/
INT __cdecl CRTDLL__ungetch(INT c)
{
if (c == CRTDLL_EOF || __CRTDLL_console_buffer != CRTDLL_EOF)
return CRTDLL_EOF;
return __CRTDLL_console_buffer = c;
}
#ifndef __WINE_CRTDLL_H
#define __WINE_CRTDLL_H
#include "config.h"
#include "windef.h"
#include "wine/windef16.h"
#include "debugtools.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#include <time.h>
#include <stdarg.h>
#include <setjmp.h>
#define CRTDLL_LC_ALL 0
#define CRTDLL_LC_COLLATE 1
#define CRTDLL_LC_CTYPE 2
#define CRTDLL_LC_MONETARY 3
#define CRTDLL_LC_NUMERIC 4
#define CRTDLL_LC_TIME 5
#define CRTDLL_LC_MIN CRTDLL_LC_ALL
#define CRTDLL_LC_MAX CRTDLL_LC_TIME
/* ctype defines */
#define CRTDLL_UPPER C1_UPPER
#define CRTDLL_LOWER C1_LOWER
#define CRTDLL_DIGIT C1_DIGIT
#define CRTDLL_SPACE C1_SPACE
#define CRTDLL_PUNCT C1_PUNCT
#define CRTDLL_CONTROL C1_CNTRL
#define CRTDLL_BLANK C1_BLANK
#define CRTDLL_HEX C1_XDIGIT
#define CRTDLL_LEADBYTE 0x8000
#define CRTDLL_ALPHA (C1_ALPHA|CRTDLL_UPPER|CRTDLL_LOWER)
/* stat() mode bits */
#define _S_IFMT 0170000
#define _S_IFREG 0100000
#define _S_IFDIR 0040000
#define _S_IFCHR 0020000
#define _S_IFIFO 0010000
#define _S_IREAD 0000400
#define _S_IWRITE 0000200
#define _S_IEXEC 0000100
/* _open modes */
#define _O_RDONLY 0x0000
#define _O_WRONLY 0x0001
#define _O_RDWR 0x0002
#define _O_APPEND 0x0008
#define _O_CREAT 0x0100
#define _O_TRUNC 0x0200
#define _O_EXCL 0x0400
#define _O_TEXT 0x4000
#define _O_BINARY 0x8000
#define _O_TEMPORARY 0x0040 /* Will be closed and deleted on exit */
/* _access() bit flags FIXME: incomplete */
#define W_OK 2
/* windows.h RAND_MAX is smaller than normal RAND_MAX */
#define CRTDLL_RAND_MAX 0x7fff
/* heap function constants */
#define _HEAPEMPTY -1
#define _HEAPOK -2
#define _HEAPBADBEGIN -3
#define _HEAPBADNODE -4
#define _HEAPEND -5
#define _HEAPBADPTR -6
#define _FREEENTRY 0
#define _USEDENTRY 1
/* fpclass constants */
#define _FPCLASS_SNAN 1
#define _FPCLASS_QNAN 2
#define _FPCLASS_NINF 4
#define _FPCLASS_NN 8
#define _FPCLASS_ND 16
#define _FPCLASS_NZ 32
#define _FPCLASS_PZ 64
#define _FPCLASS_PD 128
#define _FPCLASS_PN 256
#define _FPCLASS_PINF 512
/* _statusfp bit flags */
#define _SW_INEXACT 0x1
#define _SW_UNDERFLOW 0x2
#define _SW_OVERFLOW 0x4
#define _SW_ZERODIVIDE 0x8
#define _SW_INVALID 0x10
#define _SW_DENORMAL 0x80000
/* _controlfp masks and bitflags - x86 only so far*/
#ifdef __i386__
#define _MCW_EM 0x8001f
#define _EM_INEXACT 0x1
#define _EM_UNDERFLOW 0x2
#define _EM_OVERFLOW 0x4
#define _EM_ZERODIVIDE 0x8
#define _EM_INVALID 0x10
#define _MCW_RC 0x300
#define _RC_NEAR 0x0
#define _RC_DOWN 0x100
#define _RC_UP 0x200
#define _RC_CHOP 0x300
#define _MCW_PC 0x30000
#define _PC_64 0x0
#define _PC_53 0x10000
#define _PC_24 0x20000
#define _MCW_IC 0x40000
#define _IC_AFFINE 0x40000
#define _IC_PROJECTIVE 0x0
#define _EM_DENORMAL 0x80000
#endif
/* CRTDLL Globals */
extern INT CRTDLL_doserrno;
extern INT CRTDLL_errno;
/* Binary compatible structures, types and defines used
* by CRTDLL. These should move to external header files,
* and in some cases need to be renamed (CRTDLL_FILE!) to defs
* as used by lcc/bcc/watcom/vc++ etc, in order to get source
* compatibility for winelib.
*/
typedef struct _crtfile
{
CHAR* _ptr;
INT _cnt;
CHAR* _base;
INT _flag;
INT _file; /* fd */
int _charbuf;
int _bufsiz;
char *_tmpfname;
} CRTDLL_FILE;
/* file._flag flags */
#define _IOREAD 0x0001
#define _IOWRT 0x0002
#define _IOEOF 0x0010
#define _IOERR 0x0020
#define _IORW 0x0080
#define _IOAPPEND 0x0200
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define CRTDLL_EOF -1
#define CRTDLL_WEOF (WCHAR)(0xFFFF)
extern CRTDLL_FILE __CRTDLL_iob[3];
#define CRTDLL_stdin (&__CRTDLL_iob[0])
#define CRTDLL_stdout (&__CRTDLL_iob[1])
#define CRTDLL_stderr (&__CRTDLL_iob[2])
typedef struct _find_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];
} find_t;
typedef struct _diskfree_t {
unsigned num_clusters;
unsigned available;
unsigned cluster_sectors;
unsigned sector_bytes;
} diskfree_t;
struct _stat
{
UINT16 st_dev;
UINT16 st_ino;
UINT16 st_mode;
INT16 st_nlink;
INT16 st_uid;
INT16 st_gid;
UINT st_rdev;
INT st_size;
INT st_atime;
INT st_mtime;
INT st_ctime;
};
struct _timeb
{
time_t time;
UINT16 millitm;
INT16 timezone;
INT16 dstflag;
};
typedef long CRTDLL_fpos_t;
struct complex
{
double real;
double imaginary;
};
typedef struct _heapinfo
{
int * _pentry;
size_t _size;
int _useflag;
} _HEAPINFO;
struct _utimbuf
{
time_t actime;
time_t modtime;
};
/* _matherr exception type */
struct _exception
{
int type;
char *name;
double arg1;
double arg2;
double retval;
};
typedef VOID (*sig_handler_type)(VOID);
typedef VOID (*new_handler_type)(VOID);
typedef VOID (*_INITTERMFUN)();
typedef VOID (*atexit_function)(VOID);
typedef INT (__cdecl *comp_func)(LPCVOID, LPCVOID );
/* CRTDLL functions */
/* dir.c */
INT __cdecl CRTDLL__chdir( LPCSTR newdir );
BOOL __cdecl CRTDLL__chdrive( INT newdrive );
INT __cdecl CRTDLL__findclose( DWORD hand );
DWORD __cdecl CRTDLL__findfirst( LPCSTR fspec, find_t* ft );
INT __cdecl CRTDLL__findnext( DWORD hand, find_t * ft );
CHAR* __cdecl CRTDLL__getcwd( LPSTR buf, INT size );
CHAR* __cdecl CRTDLL__getdcwd( INT drive,LPSTR buf, INT size );
UINT __cdecl CRTDLL__getdiskfree( UINT disk, diskfree_t* d );
INT __cdecl CRTDLL__getdrive( VOID );
INT __cdecl CRTDLL__mkdir( LPCSTR newdir );
INT __cdecl CRTDLL__rmdir( LPSTR dir );
/* exit.c */
INT __cdecl CRTDLL__abnormal_termination( VOID );
VOID __cdecl CRTDLL__amsg_exit( INT err );
VOID __cdecl CRTDLL__assert( LPVOID str, LPVOID file, UINT line );
VOID __cdecl CRTDLL__c_exit( VOID );
VOID __cdecl CRTDLL__cexit( VOID );
void __cdecl CRTDLL_exit( DWORD ret );
VOID __cdecl CRTDLL__exit( LONG ret );
VOID __cdecl CRTDLL_abort( VOID );
INT __cdecl CRTDLL_atexit( atexit_function x );
atexit_function __cdecl CRTDLL__onexit( atexit_function func);
/* file.c */
CRTDLL_FILE* __cdecl CRTDLL__iob( VOID );
CRTDLL_FILE* __cdecl CRTDLL__fsopen( LPCSTR path, LPCSTR mode, INT share );
CRTDLL_FILE* __cdecl CRTDLL__fdopen( INT fd, LPCSTR mode );
LPSTR __cdecl CRTDLL__mktemp( LPSTR pattern );
CRTDLL_FILE* __cdecl CRTDLL_fopen( LPCSTR path, LPCSTR mode );
CRTDLL_FILE* __cdecl CRTDLL_freopen( LPCSTR path,LPCSTR mode,CRTDLL_FILE* f );
CRTDLL_FILE* __cdecl CRTDLL_tmpfile( void );
WCHAR __cdecl CRTDLL__fgetwchar( VOID );
INT __cdecl CRTDLL__fgetchar( VOID );
DWORD __cdecl CRTDLL_fread( LPVOID ptr,INT size,INT nmemb,CRTDLL_FILE* file );
INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* stream, LPCSTR format, ... );
INT __cdecl CRTDLL__filbuf( CRTDLL_FILE* file );
LONG __cdecl CRTDLL__filelength( INT fd );
INT __cdecl CRTDLL__fileno( CRTDLL_FILE* file );
INT __cdecl CRTDLL__flsbuf( INT c, CRTDLL_FILE* file );
INT __cdecl CRTDLL__fputchar( INT c );
WCHAR __cdecl CRTDLL__fputwchar( WCHAR wc );
INT __cdecl CRTDLL__flushall( VOID );
INT __cdecl CRTDLL__fcloseall( VOID );
LONG __cdecl CRTDLL__lseek( INT fd, LONG offset, INT whence );
LONG __cdecl CRTDLL_fseek( CRTDLL_FILE* file, LONG offset, INT whence );
VOID __cdecl CRTDLL_rewind( CRTDLL_FILE* file );
INT __cdecl CRTDLL_fsetpos( CRTDLL_FILE* file, CRTDLL_fpos_t *pos );
LONG __cdecl CRTDLL_ftell( CRTDLL_FILE* file );
UINT __cdecl CRTDLL_fwrite( LPCVOID ptr,INT size,INT nmemb,CRTDLL_FILE*file);
INT __cdecl CRTDLL_setbuf( CRTDLL_FILE* file, LPSTR buf );
INT __cdecl CRTDLL__open_osfhandle( HANDLE osfhandle, INT flags );
INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE* file, LPCSTR format,va_list args);
INT __cdecl CRTDLL_fprintf( CRTDLL_FILE* file, LPCSTR format, ... );
INT __cdecl CRTDLL__putw( INT val, CRTDLL_FILE* file );
INT __cdecl CRTDLL__read( INT fd, LPVOID buf, UINT count );
INT __cdecl CRTDLL__rmtmp( void );
UINT __cdecl CRTDLL__write( INT fd,LPCVOID buf,UINT count );
INT __cdecl CRTDLL__access( LPCSTR filename, INT mode );
INT __cdecl CRTDLL_fflush( CRTDLL_FILE* file );
INT __cdecl CRTDLL_fputc( INT c, CRTDLL_FILE* file );
VOID __cdecl CRTDLL_putchar( INT x );
INT __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE* file );
INT __cdecl CRTDLL_puts( LPCSTR s );
INT __cdecl CRTDLL_putc( INT c, CRTDLL_FILE* file );
INT __cdecl CRTDLL_fgetc( CRTDLL_FILE* file );
INT __cdecl CRTDLL_getchar( VOID );
INT __cdecl CRTDLL_getc( CRTDLL_FILE* file );
WCHAR __cdecl CRTDLL_fgetwc( CRTDLL_FILE* file );
WCHAR __cdecl CRTDLL_fputwc( WCHAR wc, CRTDLL_FILE* file );
CHAR* __cdecl CRTDLL_fgets( LPSTR s, INT size, CRTDLL_FILE* file );
LPSTR __cdecl CRTDLL_gets( LPSTR buf );
INT __cdecl CRTDLL_fclose( CRTDLL_FILE* file );
INT __cdecl CTRDLL__creat( LPCSTR path, INT flags );
INT __cdecl CRTDLL__eof( INT fd );
LONG __cdecl CRTDLL__tell( INT fd );
INT __cdecl CRTDLL__umask( INT umask );
INT __cdecl CRTDLL__utime( LPCSTR path, struct _utimbuf *t );
INT __cdecl CRTDLL__unlink( LPCSTR pathname );
INT __cdecl CRTDLL_scanf( LPCSTR format, ... );
INT __cdecl CRTDLL_rename( LPCSTR oldpath,LPCSTR newpath );
int __cdecl CRTDLL__stat( LPCSTR filename, struct _stat * buf );
INT __cdecl CRTDLL__open( LPCSTR path,INT flags );
INT __cdecl CRTDLL__chmod( LPCSTR path, INT flags );
INT __cdecl CRTDLL__close( INT fd );
INT __cdecl CRTDLL_feof( CRTDLL_FILE* file );
INT __cdecl CRTDLL__setmode( INT fh,INT mode );
INT __cdecl CRTDLL_remove( LPCSTR path );
INT __cdecl CRTDLL__commit( INT fd );
INT __cdecl CRTDLL__fstat( int file, struct _stat* buf );
INT __cdecl CRTDLL__futime( INT fd, struct _utimbuf *t );
HANDLE __cdecl CRTDLL__get_osfhandle( INT fd );
/* CRTDLL_main.c */
DWORD __cdecl CRTDLL__initterm( _INITTERMFUN *start,_INITTERMFUN *end );
VOID __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame );
VOID __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr );
INT __cdecl CRTDLL__setjmp( LPDWORD *jmpbuf );
VOID __cdecl CRTDLL_srand( DWORD seed );
INT __cdecl CRTDLL__getw( CRTDLL_FILE* file );
INT __cdecl CRTDLL__isatty( INT fd );
VOID __cdecl CRTDLL__beep( UINT freq, UINT duration );
INT __cdecl CRTDLL_rand( VOID );
UINT __cdecl CRTDLL__rotl( UINT x,INT shift );
double __cdecl CRTDLL__logb( double x );
DWORD __cdecl CRTDLL__lrotl( DWORD x,INT shift );
DWORD __cdecl CRTDLL__lrotr( DWORD x,INT shift );
DWORD __cdecl CRTDLL__rotr( UINT x,INT shift );
double __cdecl CRTDLL__scalb( double x, LONG y );
INT __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args );
VOID __cdecl CRTDLL_longjmp( jmp_buf env, int val );
LPSTR __cdecl CRTDLL_setlocale( INT category,LPCSTR locale );
INT __cdecl CRTDLL__isctype( INT c, UINT type );
LPSTR __cdecl CRTDLL__fullpath( LPSTR buf, LPCSTR name, INT size );
VOID __cdecl CRTDLL__splitpath( LPCSTR inpath, LPSTR drv, LPSTR dir,
LPSTR fname, LPSTR ext );
INT __cdecl CRTDLL__matherr( struct _exception *e );
VOID __cdecl CRTDLL__makepath( LPSTR path, LPCSTR drive,
LPCSTR directory, LPCSTR filename,
LPCSTR extension );
LPINT __cdecl CRTDLL__errno( VOID );
LPINT __cdecl CRTDLL___doserrno( VOID );
LPCSTR**__cdecl CRTDLL__sys_errlist( VOID );
VOID __cdecl CRTDLL_perror( LPCSTR err );
UINT __cdecl CRTDLL__statusfp( VOID );
LPSTR __cdecl CRTDLL__strerror( LPCSTR err );
LPSTR __cdecl CRTDLL_strerror( INT err );
LPSTR __cdecl CRTDLL__tempnam( LPCSTR dir, LPCSTR prefix );
LPSTR __cdecl CRTDLL_tmpnam( LPSTR s );
LPVOID __cdecl CRTDLL_signal( INT sig, sig_handler_type ptr );
VOID __cdecl CRTDLL__sleep( ULONG timeout );
LPSTR __cdecl CRTDLL_getenv( LPCSTR name );
INT __cdecl CRTDLL_isalnum( INT c );
INT __cdecl CRTDLL_isalpha( INT c );
INT __cdecl CRTDLL_iscntrl( INT c );
INT __cdecl CRTDLL_isdigit( INT c );
INT __cdecl CRTDLL_isgraph( INT c );
INT __cdecl CRTDLL_islower( INT c);
INT __cdecl CRTDLL_isprint( INT c);
INT __cdecl CRTDLL_ispunct( INT c);
INT __cdecl CRTDLL_isspace( INT c);
INT __cdecl CRTDLL_isupper( INT c);
INT __cdecl CRTDLL_isxdigit( INT c );
INT __cdecl CRTDLL_isleadbyte( UCHAR c );
double __cdecl CRTDLL_ldexp( double x, LONG y );
VOID __cdecl CRTDLL___dllonexit ( VOID );
VOID __cdecl CRTDLL__mbccpy( LPSTR dest, LPSTR src );
INT __cdecl CRTDLL___isascii( INT c );
INT __cdecl CRTDLL___toascii( INT c );
INT __cdecl CRTDLL_iswascii( LONG c );
INT __cdecl CRTDLL___iscsym( UCHAR c );
INT __cdecl CRTDLL___iscsymf( UCHAR c );
INT __cdecl CRTDLL__loaddll( LPSTR dllname );
INT __cdecl CRTDLL__unloaddll( HANDLE dll );
WCHAR* __cdecl CRTDLL__itow( INT value,WCHAR* out,INT base );
WCHAR* __cdecl CRTDLL__ltow( LONG value,WCHAR* out,INT base );
WCHAR* __cdecl CRTDLL__ultow( ULONG value,WCHAR* out,INT base );
CHAR __cdecl CRTDLL__toupper( CHAR c );
CHAR __cdecl CRTDLL__tolower( CHAR c );
double __cdecl CRTDLL__cabs( struct complex c );
double __cdecl CRTDLL__chgsign( double d );
UINT __cdecl CRTDLL__control87( UINT newVal, UINT mask);
UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask);
double __cdecl CRTDLL__copysign( double x, double sign );
INT __cdecl CRTDLL__finite( double d );
UINT __cdecl CRTDLL__clearfp( VOID );
INT __cdecl CRTDLL__fpclass( double d );
VOID __cdecl CRTDLL__fpreset( void );
INT __cdecl CRTDLL__isnan( double d );
LPVOID __cdecl CRTDLL__lsearch( LPVOID match, LPVOID start, LPUINT array_size,
UINT elem_size, comp_func cf );
VOID __cdecl CRTDLL__purecall( VOID );
double __cdecl CRTDLL__y0( double x );
double __cdecl CRTDLL__y1( double x );
double __cdecl CRTDLL__yn( INT x, double y );
double __cdecl CRTDLL__nextafter( double x, double y );
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff);
/* memory.c */
LPVOID __cdecl CRTDLL_new( DWORD size );
VOID __cdecl CRTDLL_delete( LPVOID ptr );
new_handler_type __cdecl CRTDLL_set_new_handler( new_handler_type func );
INT __cdecl CRTDLL__heapchk( VOID );
INT __cdecl CRTDLL__heapmin( VOID );
INT __cdecl CRTDLL__heapset( UINT value );
INT __cdecl CRTDLL__heapwalk( struct _heapinfo *next );
LPVOID __cdecl CRTDLL__expand( LPVOID ptr, INT size );
LONG __cdecl CRTDLL__msize( LPVOID mem );
LPVOID __cdecl CRTDLL_calloc( DWORD size, DWORD count );
VOID __cdecl CRTDLL_free( LPVOID ptr );
LPVOID __cdecl CRTDLL_malloc( DWORD size );
LPVOID __cdecl CRTDLL_realloc( VOID *ptr, DWORD size );
/* spawn.c */
HANDLE __cdecl CRTDLL__spawnv( INT flags, LPCSTR name, LPCSTR *argv);
HANDLE __cdecl CRTDLL__spawnve( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
HANDLE __cdecl CRTDLL__spawnvp( INT flags, LPCSTR name, LPCSTR *argv);
HANDLE __cdecl CRTDLL__spawnvpe( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
INT __cdecl CRTDLL_system( LPCSTR cmd );
INT __cdecl CRTDLL__cwait( LPINT status, INT pid, INT action );
/* str.c */
LPSTR __cdecl CRTDLL__strdec( LPSTR str1, LPSTR str2 );
LPSTR __cdecl CRTDLL__strdup( LPCSTR ptr );
LPSTR __cdecl CRTDLL__strinc( LPSTR str );
UINT __cdecl CRTDLL__strnextc( LPCSTR str );
LPSTR __cdecl CRTDLL__strninc( LPSTR str, INT n );
LPSTR __cdecl CRTDLL__strnset( LPSTR str, INT c, INT len );
LPSTR __cdecl CRTDLL__strrev ( LPSTR str );
LPSTR __cdecl CRTDLL__strset ( LPSTR str, INT set );
LONG __cdecl CRTDLL__strncnt( LPSTR str, LONG max );
LPSTR __cdecl CRTDLL__strspnp( LPSTR str1, LPSTR str2 );
VOID __cdecl CRTDLL__swab( LPSTR src, LPSTR dst, INT len );
/* time.c */
LPSTR __cdecl CRTDLL__strdate ( LPSTR date );
LPSTR __cdecl CRTDLL__strtime ( LPSTR date );
clock_t __cdecl CRTDLL_clock ( void );
double __cdecl CRTDLL_difftime ( time_t time1, time_t time2 );
time_t __cdecl CRTDLL_time ( time_t *timeptr );
/* mbstring.c */
LPSTR __cdecl CRTDLL__mbsinc( LPCSTR str );
INT __cdecl CRTDLL__mbslen( LPCSTR str );
INT __cdecl CRTDLL_mbtowc( WCHAR *dst, LPCSTR str, INT n );
LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str );
INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 );
LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n );
LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str );
LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c );
DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 );
LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept );
INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch );
LPSTR __cdecl CRTDLL__mbsdec( LPCSTR start, LPCSTR cur );
LPSTR __cdecl CRTDLL__mbsninc( LPCSTR str, INT num );
INT __cdecl CRTDLL__mbscmp( LPCSTR str, LPCSTR cmp );
INT __cdecl CRTDLL__mbsicmp( LPCSTR str, LPCSTR cmp );
INT __cdecl CRTDLL__mbsncmp( LPCSTR str, LPCSTR cmp, UINT len );
INT __cdecl CRTDLL__mbsnicmp( LPCSTR str, LPCSTR cmp, UINT len );
LPSTR __cdecl CRTDLL__mbsrchr( LPCSTR s,CHAR x );
USHORT __cdecl CRTDLL__mbbtombc( USHORT c );
INT __cdecl CRTDLL__mbclen( LPCSTR str );
INT __cdecl CRTDLL__ismbbkana( UINT c );
INT __cdecl CRTDLL__ismbckata( UINT c );
INT __cdecl CRTDLL__ismbchira( UINT c );
INT __cdecl CRTDLL__ismbblead( UINT c );
INT __cdecl CRTDLL__ismbslead( LPCSTR start, LPCSTR str);
INT __cdecl CRTDLL__ismbbtrail( UINT c );
INT __cdecl CRTDLL__ismbstrail( LPCSTR start, LPCSTR str );
LPSTR __cdecl CRTDLL__mbsset( LPSTR str, UINT c );
LPSTR __cdecl CRTDLL__mbsnset( LPSTR str, UINT c, UINT len );
INT __cdecl CRTDLL__mbstrlen( LPCSTR str );
UINT __cdecl CRTDLL__mbsnextc( LPCSTR str );
LPSTR __cdecl CRTDLL__mbsncpy( LPSTR dst, LPCSTR src, UINT len );
LPSTR __cdecl CRTDLL__mbschr( LPCSTR str, UINT c );
UINT __cdecl CRTDLL__mbsnccnt( LPCSTR str, UINT len );
LPSTR __cdecl CRTDLL__mbsncat( LPSTR dst, LPCSTR src, UINT len );
/* wcstring.c */
INT __cdecl CRTDLL_iswalnum( WCHAR wc );
INT __cdecl CRTDLL_iswalpha( WCHAR wc );
INT __cdecl CRTDLL_iswcntrl( WCHAR wc );
INT __cdecl CRTDLL_iswdigit( WCHAR wc );
INT __cdecl CRTDLL_iswgraph( WCHAR wc );
INT __cdecl CRTDLL_iswlower( WCHAR wc );
INT __cdecl CRTDLL_iswprint( WCHAR wc );
INT __cdecl CRTDLL_iswpunct( WCHAR wc );
INT __cdecl CRTDLL_iswspace( WCHAR wc );
INT __cdecl CRTDLL_iswupper( WCHAR wc );
INT __cdecl CRTDLL_iswxdigit( WCHAR wc );
/* console.c */
LPSTR __cdecl CRTDLL__cgets( LPSTR str );
INT __cdecl CRTDLL__cfprintf( LPCSTR format, ... );
INT __cdecl CRTDLL__cputs( LPCSTR str );
INT __cdecl CRTDLL__cscanf( LPCSTR format, ... );
INT __cdecl CRTDLL__getch( VOID );
INT __cdecl CRTDLL__getche( VOID );
INT __cdecl CRTDLL__kbhit( VOID );
INT __cdecl CRTDLL__putch( INT c );
INT __cdecl CRTDLL__ungetch( INT c );
/* INTERNAL: Shared internal functions */
void __CRTDLL__set_errno(ULONG err);
LPSTR __CRTDLL__strndup(LPSTR buf, INT size);
VOID __CRTDLL__init_io(VOID);
VOID __CRTDLL_init_console(VOID);
VOID __CRTDLL_free_console(VOID);
extern WORD CRTDLL_ctype [257];
extern UCHAR CRTDLL_mbctype[257];
extern WORD __CRTDLL_current_ctype[257];
extern WORD* CRTDLL_pctype_dll;
extern INT CRTDLL__mb_cur_max_dll;
extern LCID __CRTDLL_current_lc_all_lcid;
extern UINT __CRTDLL_current_lc_all_cp;
#endif /* __WINE_CRTDLL_H */
# C RunTime DLL. All functions use cdecl!
# Old C runtime library. All functions provided by msvcrt
name crtdll
type win32
init CRTDLL_Init
import msvcrt.dll
import kernel32.dll
import ntdll.dll
debug_channels (crtdll)
@ cdecl ??2@YAPAXI@Z(long) CRTDLL_new
@ cdecl ??3@YAXPAX@Z(long) CRTDLL_delete
@ cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) CRTDLL_set_new_handler
@ cdecl _CIacos() CRTDLL__CIacos
@ cdecl _CIasin() CRTDLL__CIasin
@ cdecl _CIatan() CRTDLL__CIatan
@ cdecl _CIatan2() CRTDLL__CIatan2
@ cdecl _CIcos() CRTDLL__CIcos
@ cdecl _CIcosh() CRTDLL__CIcosh
@ cdecl _CIexp() CRTDLL__CIexp
@ cdecl _CIfmod() CRTDLL__CIfmod
@ cdecl _CIlog() CRTDLL__CIlog
@ cdecl _CIlog10() CRTDLL__CIlog10
@ cdecl _CIpow() CRTDLL__CIpow
@ cdecl _CIsin() CRTDLL__CIsin
@ cdecl _CIsinh() CRTDLL__CIsinh
@ cdecl _CIsqrt() CRTDLL__CIsqrt
@ cdecl _CItan() CRTDLL__CItan
@ cdecl _CItanh() CRTDLL__CItanh
@ extern _HUGE_dll CRTDLL_HUGE_dll
@ stub _XcptFilter
@ cdecl __GetMainArgs(ptr ptr ptr long) CRTDLL__GetMainArgs
@ extern __argc_dll CRTDLL_argc_dll
@ extern __argv_dll CRTDLL_argv_dll
@ cdecl __dllonexit() CRTDLL___dllonexit
@ cdecl __doserrno() CRTDLL___doserrno
@ stub __fpecode
@ cdecl __isascii(long) CRTDLL___isascii
@ cdecl __iscsym(long) CRTDLL___iscsym
@ cdecl __iscsymf(long) CRTDLL___iscsymf
@ extern __mb_cur_max_dll CRTDLL__mb_cur_max_dll
@ stub __pxcptinfoptrs
@ forward __threadhandle kernel32.GetCurrentThread
@ forward __threadid kernel32.GetCurrentThreadId
@ cdecl __toascii(long) CRTDLL___toascii
@ cdecl _abnormal_termination() CRTDLL__abnormal_termination
@ cdecl _access(str long) CRTDLL__access
@ extern _acmdln_dll CRTDLL_acmdln_dll
@ stub _aexit_rtn_dll
@ cdecl _amsg_exit(long) CRTDLL__amsg_exit
@ cdecl _assert(ptr ptr long) CRTDLL__assert
@ extern _basemajor_dll CRTDLL_basemajor_dll
@ extern _baseminor_dll CRTDLL_baseminor_dll
@ extern _baseversion_dll CRTDLL_baseversion_dll
@ cdecl _beep(long long) CRTDLL__beep
@ stub _beginthread
@ cdecl _c_exit() CRTDLL__c_exit
@ cdecl _cabs(long) CRTDLL__cabs
@ cdecl _cexit() CRTDLL__cexit
@ cdecl _cgets(str) CRTDLL__cgets
@ cdecl _chdir(str) CRTDLL__chdir
@ cdecl _chdrive(long) CRTDLL__chdrive
@ cdecl _chgsign(double) CRTDLL__chgsign
@ cdecl _chmod(str long) CRTDLL__chmod
@ stub _chsize
@ cdecl _clearfp() CRTDLL__clearfp
@ cdecl _close(long) CRTDLL__close
@ cdecl _commit(long) CRTDLL__commit
@ extern _commode_dll CRTDLL_commode_dll
@ cdecl _control87(long long) CRTDLL__control87
@ cdecl _controlfp(long long) CRTDLL__controlfp
@ cdecl _copysign(double double) CRTDLL__copysign
@ varargs _cprintf(str) CRTDLL__cprintf
@ stub _cpumode_dll
@ cdecl _cputs(str) CRTDLL__cputs
@ cdecl _creat(str long) CRTDLL__creat
@ varargs _cscanf(str) CRTDLL__cscanf
@ extern _ctype CRTDLL_ctype
@ cdecl _cwait(ptr long long) CRTDLL__cwait
@ stub _daylight_dll
@ stub _dup
@ stub _dup2
@ cdecl _ecvt(double long ptr ptr) ecvt
@ stub _endthread
@ extern _environ_dll CRTDLL_environ_dll
@ cdecl _eof(long) CRTDLL__eof
@ cdecl _errno() CRTDLL__errno
@ cdecl _except_handler2(ptr ptr ptr ptr) CRTDLL__except_handler2
@ stub _execl
@ stub _execle
@ stub _execlp
@ stub _execlpe
@ stub _execv
@ stub _execve
@ stub _execvp
@ stub _execvpe
@ cdecl _exit(long) CRTDLL__exit
@ cdecl _expand(ptr long) CRTDLL__expand
@ cdecl _fcloseall() CRTDLL__fcloseall
@ cdecl _fcvt(double long ptr ptr) fcvt
@ cdecl _fdopen(long ptr) CRTDLL__fdopen
@ cdecl _fgetchar() CRTDLL__fgetchar
@ cdecl _fgetwchar() CRTDLL__fgetwchar
@ cdecl _filbuf(ptr) CRTDLL__filbuf
@ stub _fileinfo_dll
@ cdecl _filelength(long) CRTDLL__filelength
@ cdecl _fileno(ptr) CRTDLL__fileno
@ cdecl _findclose(long) CRTDLL__findclose
@ cdecl _findfirst(str ptr) CRTDLL__findfirst
@ cdecl _findnext(long ptr) CRTDLL__findnext
@ cdecl _finite(double) CRTDLL__finite
@ cdecl _flsbuf(long ptr) CRTDLL__flsbuf
@ cdecl _flushall() CRTDLL__flushall
@ extern _fmode_dll CRTDLL_fmode_dll
@ cdecl _fpclass(double) CRTDLL__fpclass
@ stub _fpieee_flt
@ cdecl _fpreset() CRTDLL__fpreset
@ cdecl _fputchar(long) CRTDLL__fputchar
@ cdecl _fputwchar(long) CRTDLL__fputwchar
@ cdecl _fsopen(str str long) CRTDLL__fsopen
@ cdecl _fstat(long ptr) CRTDLL__fstat
@ cdecl _ftime(ptr) CRTDLL__ftime
@ forward _ftol ntdll._ftol
@ cdecl _fullpath(ptr str long) CRTDLL__fullpath
@ cdecl _futime(long ptr) CRTDLL__futime
@ cdecl _gcvt(double long str) gcvt
@ cdecl _get_osfhandle(long) CRTDLL__get_osfhandle
@ cdecl _getch() CRTDLL__getch
@ cdecl _getche() CRTDLL__getche
@ cdecl _getcwd(ptr long) CRTDLL__getcwd
@ cdecl _getdcwd(long ptr long) CRTDLL__getdcwd
@ cdecl _getdiskfree(long ptr) CRTDLL__getdiskfree
@ forward _getdllprocaddr kernel32.GetProcAddress
@ cdecl _getdrive() CRTDLL__getdrive
@ forward _getdrives kernel32.GetLogicalDrives
@ forward _getpid kernel32.GetCurrentProcessId
@ stub _getsystime
@ cdecl _getw(ptr) CRTDLL__getw
@ cdecl _global_unwind2(ptr) CRTDLL__global_unwind2
@ cdecl _heapchk() CRTDLL__heapchk
@ cdecl _heapmin() CRTDLL__heapmin
@ cdecl _heapset(long) CRTDLL__heapset
@ cdecl _heapwalk(ptr) CRTDLL__heapwalk
@ cdecl _hypot(double double) hypot
@ cdecl _initterm(ptr ptr) CRTDLL__initterm
@ extern _iob __CRTDLL_iob
@ cdecl _isatty(long) CRTDLL__isatty
@ cdecl _isctype(long long) CRTDLL__isctype
@ stub _ismbbalnum
@ stub _ismbbalpha
@ stub _ismbbgraph
@ stub _ismbbkalnum
@ cdecl _ismbbkana(long) CRTDLL__ismbbkana
@ stub _ismbbkpunct
@ cdecl _ismbblead(long) CRTDLL__ismbblead
@ stub _ismbbprint
@ stub _ismbbpunct
@ cdecl _ismbbtrail(long) CRTDLL__ismbbtrail
@ stub _ismbcalpha
@ stub _ismbcdigit
@ cdecl _ismbchira(long) CRTDLL__ismbchira
@ cdecl _ismbckata(long) CRTDLL__ismbckata
@ stub _ismbcl0
@ stub _ismbcl1
@ stub _ismbcl2
@ stub _ismbclegal
@ stub _ismbclower
@ stub _ismbcprint
@ stub _ismbcspace
@ stub _ismbcsymbol
@ stub _ismbcupper
@ cdecl _ismbslead(ptr ptr) CRTDLL__ismbslead
@ cdecl _ismbstrail(ptr ptr) CRTDLL__ismbstrail
@ cdecl _isnan(double) CRTDLL__isnan
@ forward _itoa ntdll._itoa
@ cdecl _j0(double) j0
@ cdecl _j1(double) j1
@ cdecl _jn(long double) jn
@ cdecl _kbhit() CRTDLL__kbhit
@ cdecl _lfind(ptr ptr ptr long ptr) CRTDLL__lfind
@ cdecl _loaddll(str) CRTDLL__loaddll
@ cdecl _local_unwind2(ptr long) CRTDLL__local_unwind2
@ stub _locking
@ cdecl _logb(double) CRTDLL__logb
@ cdecl _lrotl (long long) CRTDLL__lrotl
@ cdecl _lrotr (long long) CRTDLL__lrotr
@ cdecl _lsearch(ptr ptr long long ptr) CRTDLL__lsearch
@ cdecl _lseek(long long long) CRTDLL__lseek
@ forward _ltoa ntdll._ltoa
@ cdecl _makepath (ptr str str str str) CRTDLL__makepath
@ cdecl _matherr(ptr) CRTDLL__matherr
@ cdecl _mbbtombc(long) CRTDLL__mbbtombc
@ stub _mbbtype
@ cdecl _mbccpy (str str) strcpy
@ stub _mbcjistojms
@ stub _mbcjmstojis
@ cdecl _mbclen(long) CRTDLL__mbclen
@ stub _mbctohira
@ stub _mbctokata
@ stub _mbctolower
@ stub _mbctombb
@ stub _mbctoupper
@ extern _mbctype CRTDLL_mbctype
@ stub _mbsbtype
@ cdecl _mbscat(str str) strcat
@ cdecl _mbschr(str long) CRTDLL__mbschr
@ cdecl _mbscmp(str str) CRTDLL__mbscmp
@ cdecl _mbscpy(ptr str) strcpy
@ stub _mbscspn
@ cdecl _mbsdec(str str) CRTDLL__mbsdec
@ cdecl _mbsdup(str) CRTDLL__strdup
@ cdecl _mbsicmp(str str) CRTDLL__mbsicmp
@ cdecl _mbsinc(str) CRTDLL__mbsinc
@ cdecl _mbslen(str) CRTDLL__mbslen
@ stub _mbslwr
@ stub _mbsnbcat
@ stub _mbsnbcmp
@ stub _mbsnbcnt
@ stub _mbsnbcpy
@ stub _mbsnbicmp
@ stub _mbsnbset
@ cdecl _mbsncat(str str long) CRTDLL__mbsncat
@ cdecl _mbsnccnt(str long) CRTDLL__mbsnccnt
@ cdecl _mbsncmp(str str long) CRTDLL__mbsncmp
@ cdecl _mbsncpy(str str long) CRTDLL__mbsncpy
@ cdecl _mbsnextc(str) CRTDLL__mbsnextc
@ cdecl _mbsnicmp(str str long) CRTDLL__mbsncmp
@ cdecl _mbsninc(str long) CRTDLL__mbsninc
@ cdecl _mbsnset(str long long) CRTDLL__mbsnset
@ stub _mbspbrk
@ cdecl _mbsrchr(str long) CRTDLL__mbsrchr
@ stub _mbsrev
@ cdecl _mbsset(str long) CRTDLL__mbsset
@ stub _mbsspn
@ stub _mbsspnp
@ cdecl _mbsstr(str str) strstr
@ stub _mbstok
@ cdecl _mbstrlen(str) CRTDLL__mbstrlen
@ stub _mbsupr
@ cdecl _memccpy(ptr ptr long long) memccpy
@ forward _memicmp ntdll._memicmp
@ cdecl _mkdir(str) CRTDLL__mkdir
@ cdecl _mktemp(str) CRTDLL__mktemp
@ cdecl _msize(ptr) CRTDLL__msize
@ cdecl _nextafter(double double) CRTDLL__nextafter
@ cdecl _onexit(ptr) CRTDLL__onexit
@ cdecl _open(str long) CRTDLL__open
@ cdecl _open_osfhandle(long long) CRTDLL__open_osfhandle
@ extern _osmajor_dll CRTDLL_osmajor_dll
@ extern _osminor_dll CRTDLL_osminor_dll
@ extern _osmode_dll CRTDLL_osmode_dll
@ extern _osver_dll CRTDLL_osver_dll
@ extern _osversion_dll CRTDLL_osversion_dll
@ stub _pclose
@ extern _pctype_dll CRTDLL_pctype_dll
@ stub _pgmptr_dll
@ stub _pipe
@ stub _popen
@ cdecl _purecall() CRTDLL__purecall
@ cdecl _putch(long) CRTDLL__putch
@ stub _putenv
@ cdecl _putw(long ptr) CRTDLL__putw
@ stub _pwctype_dll
@ cdecl _read(long ptr long) CRTDLL__read
@ cdecl _rmdir(str) CRTDLL__rmdir
@ cdecl _rmtmp() CRTDLL__rmtmp
@ cdecl _rotl (long long) CRTDLL__rotl
@ cdecl _rotr (long long) CRTDLL__rotr
@ cdecl _scalb (double long) CRTDLL__scalb
@ cdecl _searchenv(str str str) CRTDLL__searchenv
@ stub _seterrormode
@ cdecl _setjmp (ptr) CRTDLL__setjmp
@ cdecl _setmode(long long) CRTDLL__setmode
@ stub _setsystime
@ cdecl _sleep(long) CRTDLL__sleep
@ varargs _snprintf(ptr long ptr) snprintf
@ stub _snwprintf
@ stub _sopen
@ stub _spawnl
@ stub _spawnle
@ stub _spawnlp
@ stub _spawnlpe
@ cdecl _spawnv(long str ptr) CRTDLL__spawnv
@ cdecl _spawnve(long str ptr ptr) CRTDLL__spawnve
@ cdecl _spawnvp(long str ptr) CRTDLL__spawnvp
@ cdecl _spawnvpe(long str ptr ptr) CRTDLL__spawnvpe
@ cdecl _splitpath (str ptr ptr ptr ptr) CRTDLL__splitpath
@ cdecl _stat (str ptr) CRTDLL__stat
@ cdecl _statusfp() CRTDLL__statusfp
@ cdecl _strcmpi(str str) strcasecmp
@ cdecl _strdate(str) CRTDLL__strdate
@ cdecl _strdec(str str) CRTDLL__strdec
@ cdecl _strdup(str) CRTDLL__strdup
@ cdecl _strerror(long) CRTDLL__strerror
@ cdecl _stricmp(str str) strcasecmp
@ stub _stricoll
@ cdecl _strinc(str) CRTDLL__strinc
@ forward _strlwr ntdll._strlwr
@ cdecl _strncnt(str long) CRTDLL__strncnt
@ cdecl _strnextc(str) CRTDLL__strnextc
@ cdecl _strnicmp(str str long) strncasecmp
@ cdecl _strninc(str long) CRTDLL__strninc
@ cdecl _strnset(str long long) CRTDLL__strnset
@ cdecl _strrev(str) CRTDLL__strrev
@ cdecl _strset(str long) CRTDLL__strset
@ cdecl _strspnp(str str) CRTDLL__strspnp
@ cdecl _strtime(str) CRTDLL__strtime
@ forward _strupr ntdll._strupr
@ cdecl _swab(str str long) CRTDLL__swab
@ extern _sys_errlist sys_errlist
@ extern _sys_nerr_dll CRTDLL__sys_nerr
@ cdecl _tell(long) CRTDLL__tell
@ cdecl _tempnam(str ptr) CRTDLL__tempnam
@ extern _timezone_dll CRTDLL_timezone_dll
@ cdecl _tolower(long) CRTDLL__toupper
@ cdecl _toupper(long) CRTDLL__tolower
@ stub _tzname
@ stub _tzset
@ forward _ultoa ntdll._ultoa
@ cdecl _ultow(long str long) CRTDLL__ultow
@ cdecl _umask(long) CRTDLL__umask
@ cdecl _ungetch(long) CRTDLL__ungetch
@ cdecl _unlink(str) CRTDLL__unlink
@ cdecl _unloaddll(long) CRTDLL__unloaddll
@ cdecl _utime(str ptr) CRTDLL__utime
@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
@ stub _vsnwprintf
@ cdecl _wcsdup(wstr) CRTDLL__wcsdup
@ forward _wcsicmp ntdll._wcsicmp
@ cdecl _wcsicoll(wstr wstr) CRTDLL__wcsicoll
@ forward _wcslwr ntdll._wcslwr
@ forward _wcsnicmp ntdll._wcsnicmp
@ cdecl _wcsnset(wstr long long) CRTDLL__wcsnset
@ cdecl _wcsrev(wstr) CRTDLL__wcsrev
@ cdecl _wcsset(wstr long) CRTDLL__wcsset
@ forward _wcsupr ntdll._wcsupr
@ extern _winmajor_dll CRTDLL_winmajor_dll
@ extern _winminor_dll CRTDLL_winminor_dll
@ extern _winver_dll CRTDLL_winver_dll
@ cdecl _write(long ptr long) CRTDLL__write
@ forward _wtoi NTDLL._wtoi
@ forward _wtol NTDLL._wtol
@ cdecl _y0(double) CRTDLL__y0
@ cdecl _y1(double) CRTDLL__y1
@ cdecl _yn(long double) CRTDLL__yn
@ cdecl abort() CRTDLL_abort
@ cdecl abs(long) abs
@ cdecl acos(double) acos
@ cdecl asctime(ptr) asctime
@ cdecl asin(double) asin
@ cdecl atan(double) atan
@ cdecl atan2(double double) atan2
@ cdecl atexit(ptr) CRTDLL_atexit
@ cdecl atof(str) atof
@ cdecl atoi(str) atoi
@ cdecl atol(str) atol
@ cdecl bsearch(ptr ptr long long ptr) bsearch
@ cdecl calloc(long long) CRTDLL_calloc
@ cdecl ceil(double) ceil
@ cdecl clearerr(ptr) CRTDLL_clearerr
@ cdecl clock() CRTDLL_clock
@ cdecl cos(double) cos
@ cdecl cosh(double) cosh
@ cdecl ctime(ptr) ctime
@ cdecl difftime(long long) CRTDLL_difftime
@ cdecl -noimport div(long long) CRTDLL_div
@ cdecl exit(long) CRTDLL_exit
@ cdecl exp(double) exp
@ cdecl fabs(double) fabs
@ cdecl fclose(ptr) CRTDLL_fclose
@ cdecl feof(ptr) CRTDLL_feof
@ cdecl ferror(ptr) CRTDLL_ferror
@ cdecl fflush(ptr) CRTDLL_fflush
@ cdecl fgetc(ptr) CRTDLL_fgetc
@ cdecl fgetpos(ptr ptr) CRTDLL_fgetpos
@ cdecl fgets(ptr long ptr) CRTDLL_fgets
@ cdecl fgetwc(ptr) CRTDLL_fgetwc
@ cdecl floor(double) floor
@ cdecl fmod(double double) fmod
@ cdecl fopen(str str) CRTDLL_fopen
@ varargs fprintf(ptr str) CRTDLL_fprintf
@ cdecl fputc(long ptr) CRTDLL_fputc
@ cdecl fputs(str ptr) CRTDLL_fputs
@ cdecl fputwc(long ptr) CRTDLL_fputwc
@ cdecl fread(ptr long long ptr) CRTDLL_fread
@ cdecl free(ptr) CRTDLL_free
@ cdecl freopen(str str ptr) CRTDLL_freopen
@ cdecl frexp(double ptr) frexp
@ varargs fscanf(ptr str) CRTDLL_fscanf
@ cdecl fseek(ptr long long) CRTDLL_fseek
@ cdecl fsetpos(ptr ptr) CRTDLL_fsetpos
@ cdecl ftell(ptr) CRTDLL_ftell
@ stub fwprintf
@ cdecl fwrite(ptr long long ptr) CRTDLL_fwrite
@ stub fwscanf
@ cdecl getc(ptr) CRTDLL_getc
@ cdecl getchar() CRTDLL_getchar
@ cdecl getenv (str) CRTDLL_getenv
@ cdecl gets(ptr) CRTDLL_gets
@ cdecl gmtime(ptr) gmtime
@ forward is_wctype ntdll.iswctype
@ cdecl isalnum(long) CRTDLL_isalnum
@ cdecl isalpha(long) CRTDLL_isalpha
@ cdecl iscntrl(long) CRTDLL_iscntrl
@ cdecl isdigit(long) CRTDLL_isdigit
@ cdecl isgraph(long) CRTDLL_isgraph
@ cdecl isleadbyte(long) CRTDLL_isleadbyte
@ cdecl islower(long) CRTDLL_islower
@ cdecl isprint(long) CRTDLL_isprint
@ cdecl ispunct(long) CRTDLL_ispunct
@ cdecl isspace(long) CRTDLL_isspace
@ cdecl isupper(long) CRTDLL_isupper
@ cdecl iswalnum(long) CRTDLL_iswalnum
@ forward iswalpha ntdll.iswalpha
@ cdecl iswascii(long) CRTDLL_iswascii
@ cdecl iswcntrl(long) CRTDLL_iswcntrl
@ forward iswctype ntdll.iswctype
@ cdecl iswdigit(long) CRTDLL_iswdigit
@ cdecl iswgraph(long) CRTDLL_iswgraph
@ cdecl iswlower(long) CRTDLL_iswlower
@ cdecl iswprint(long) CRTDLL_iswprint
@ cdecl iswpunct(long) CRTDLL_iswpunct
@ cdecl iswspace(long) CRTDLL_iswspace
@ cdecl iswupper(long) CRTDLL_iswupper
@ cdecl iswxdigit(long) CRTDLL_iswxdigit
@ cdecl isxdigit(long) CRTDLL_isxdigit
@ cdecl labs(long) labs
@ cdecl ldexp(double long) CRTDLL_ldexp
@ cdecl -noimport ldiv(long long) CRTDLL_ldiv
@ stub localeconv
@ cdecl localtime(ptr) localtime
@ cdecl log(double) log
@ cdecl log10(double) log10
@ cdecl longjmp(ptr long) CRTDLL_longjmp
@ cdecl malloc(ptr) CRTDLL_malloc
@ cdecl mblen(str long) mblen
@ forward mbstowcs ntdll.mbstowcs
@ cdecl mbtowc(ptr ptr long) CRTDLL_mbtowc
@ cdecl memchr(ptr long long) memchr
@ cdecl memcmp(ptr ptr long) memcmp
@ cdecl memcpy(ptr ptr long) memcpy
@ cdecl memmove(ptr ptr long) memmove
@ cdecl memset(ptr long long) memset
@ cdecl mktime(ptr) mktime
@ cdecl modf(double ptr) modf
@ cdecl perror(str) CRTDLL_perror
@ cdecl pow(double double) pow
@ varargs printf() printf
@ cdecl putc(long ptr) CRTDLL_putc
@ cdecl putchar(long) CRTDLL_putchar
@ cdecl puts(str) CRTDLL_puts
@ cdecl qsort(ptr long long ptr) qsort
@ stub raise
@ cdecl rand() CRTDLL_rand
@ cdecl realloc(ptr long) CRTDLL_realloc
@ cdecl remove(str) CRTDLL_remove
@ cdecl rename(str str) CRTDLL_rename
@ cdecl rewind(ptr) CRTDLL_rewind
@ varargs scanf(str) CRTDLL_scanf
@ cdecl setbuf(ptr ptr) CRTDLL_setbuf
@ cdecl setlocale(long ptr) CRTDLL_setlocale
@ stub setvbuf
@ cdecl signal(long ptr) CRTDLL_signal
@ cdecl sin(double) sin
@ cdecl sinh(double) sinh
@ varargs sprintf(ptr ptr) sprintf
@ cdecl sqrt(double) sqrt
@ cdecl srand(long) srand
@ varargs sscanf() sscanf
@ cdecl strcat(str str) strcat
@ cdecl strchr(str long) strchr
@ cdecl strcmp(str str) strcmp
@ cdecl strcoll(str str) strcoll
@ cdecl strcpy(ptr str) strcpy
@ cdecl strcspn(str str) strcspn
@ cdecl strerror(long) CRTDLL_strerror
@ cdecl strftime(ptr long str ptr) strftime
@ cdecl strlen(str) strlen
@ cdecl strncat(str str long) strncat
@ cdecl strncmp(str str long) strncmp
@ cdecl strncpy(ptr str long) strncpy
@ cdecl strpbrk(str str) strpbrk
@ cdecl strrchr(str long) strrchr
@ cdecl strspn(str str) strspn
@ cdecl strstr(str str) strstr
@ cdecl strtod(str ptr) strtod
@ cdecl strtok(str str) strtok
@ cdecl strtol(str ptr long) strtol
@ cdecl strtoul(str ptr long) strtoul
@ cdecl strxfrm(ptr str long) strxfrm
@ stub swprintf
@ stub swscanf
@ cdecl system(str) CRTDLL_system
@ cdecl tan(double) tan
@ cdecl tanh(double) tanh
@ cdecl time(ptr) CRTDLL_time
@ cdecl tmpfile() CRTDLL_tmpfile
@ cdecl tmpnam(str) CRTDLL_tmpnam
@ cdecl tolower(long) tolower
@ cdecl toupper(long) toupper
@ forward towlower ntdll.towlower
@ forward towupper ntdll.towupper
@ stub ungetc
@ stub ungetwc
@ cdecl vfprintf(ptr str ptr) CRTDLL_vfprintf
@ stub vfwprintf
@ stub vprintf
@ cdecl vsprintf(ptr str ptr) vsprintf
@ stub vswprintf
@ stub vwprintf
@ forward wcscat ntdll.wcscat
@ forward wcschr ntdll.wcschr
@ forward wcscmp ntdll.wcscmp
@ cdecl wcscoll(wstr wstr) CRTDLL_wcscoll
@ forward wcscpy ntdll.wcscpy
@ forward wcscspn ntdll.wcscspn
@ stub wcsftime
@ forward wcslen ntdll.wcslen
@ forward wcsncat ntdll.wcsncat
@ forward wcsncmp ntdll.wcsncmp
@ forward wcsncpy ntdll.wcsncpy
@ cdecl wcspbrk(wstr wstr) CRTDLL_wcspbrk
@ forward wcsrchr ntdll.wcsrchr
@ forward wcsspn ntdll.wcsspn
@ forward wcsstr ntdll.wcsstr
@ stub wcstod
@ forward wcstok ntdll.wcstok
@ forward wcstol ntdll.wcstol
@ forward wcstombs ntdll.wcstombs
@ stub wcstoul
@ stub wcsxfrm
@ cdecl wctomb(ptr long) CRTDLL_wctomb
@ stub wprintf
@ stub wscanf
#@ cdecl _itow(long str long) CRTDLL__itow
#@ cdecl _ltow(long str long) CRTDLL__ltow
@ forward ??2@YAPAXI@Z msvcrt.??2@YAPAXI@Z
@ forward ??3@YAXPAX@Z msvcrt.??3@YAXPAX@Z
@ forward ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z msvcrt.?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z
@ forward _CIacos msvcrt._CIacos
@ forward _CIasin msvcrt._CIasin
@ forward _CIatan msvcrt._CIatan
@ forward _CIatan2 msvcrt._CIatan2
@ forward _CIcos msvcrt._CIcos
@ forward _CIcosh msvcrt._CIcosh
@ forward _CIexp msvcrt._CIexp
@ forward _CIfmod msvcrt._CIfmod
@ forward _CIlog msvcrt._CIlog
@ forward _CIlog10 msvcrt._CIlog10
@ forward _CIpow msvcrt._CIpow
@ forward _CIsin msvcrt._CIsin
@ forward _CIsinh msvcrt._CIsinh
@ forward _CIsqrt msvcrt._CIsqrt
@ forward _CItan msvcrt._CItan
@ forward _CItanh msvcrt._CItanh
@ forward _HUGE_dll msvcrt._HUGE
@ forward _XcptFilter msvcrt._XcptFilter
@ forward __GetMainArgs msvcrt.__getmainargs
@ forward __argc_dll msvcrt.__argc
@ forward __argv_dll msvcrt.__argv
@ forward __dllonexit msvcrt.__dllonexit
@ forward __doserrno msvcrt.__doserrno
@ forward __fpecode msvcrt.__fpecode
@ forward __isascii msvcrt.__isascii
@ forward __iscsym msvcrt.__iscsym
@ forward __iscsymf msvcrt.__iscsymf
@ forward __mb_cur_max_dll msvcrt.__mb_cur_max
@ forward __pxcptinfoptrs msvcrt.__pxcptinfoptrs
@ forward __threadhandle msvcrt.__threadhandle
@ forward __threadid msvcrt.__threadid
@ forward __toascii msvcrt.__toascii
@ forward _abnormal_termination msvcrt._abnormal_termination
@ forward _access msvcrt._access
@ forward _acmdln_dll msvcrt._acmdln
@ forward _aexit_rtn_dll msvcrt._aexit_rtn
@ forward _amsg_exit msvcrt._amsg_exit
@ forward _assert msvcrt._assert
@ extern _basemajor_dll CRTDLL__basemajor_dll
@ extern _baseminor_dll CRTDLL__basemajor_dll
@ extern _baseversion_dll CRTDLL__basemajor_dll
@ forward _beep msvcrt._beep
@ forward _beginthread msvcrt._beginthread
@ forward _c_exit msvcrt._c_exit
@ forward _cabs msvcrt._cabs
@ forward _cexit msvcrt._cexit
@ forward _cgets msvcrt._cgets
@ forward _chdir msvcrt._chdir
@ forward _chdrive msvcrt._chdrive
@ forward _chgsign msvcrt._chgsign
@ forward _chmod msvcrt._chmod
@ forward _chsize msvcrt._chsize
@ forward _clearfp msvcrt._clearfp
@ forward _close msvcrt._close
@ forward _commit msvcrt._commit
@ forward _commode_dll msvcrt._commode
@ forward _control87 msvcrt._control87
@ forward _controlfp msvcrt._controlfp
@ forward _copysign msvcrt._copysign
@ forward _cprintf msvcrt._cprintf
@ extern _cpumode_dll CRTDLL__cpumode_dll
@ forward _cputs msvcrt._cputs
@ forward _creat msvcrt._creat
@ forward _cscanf msvcrt._cscanf
@ forward _ctype msvcrt._ctype
@ forward _cwait msvcrt._cwait
@ forward _daylight_dll msvcrt._daylight
@ forward _dup msvcrt._dup
@ forward _dup2 msvcrt._dup2
@ forward _ecvt msvcrt._ecvt
@ forward _endthread msvcrt._endthread
@ forward _environ_dll msvcrt._environ
@ forward _eof msvcrt._eof
@ forward _errno msvcrt._errno
@ forward _except_handler2 msvcrt._except_handler2
@ forward _execl msvcrt._execl
@ forward _execle msvcrt._execle
@ forward _execlp msvcrt._execlp
@ forward _execlpe msvcrt._execlpe
@ forward _execv msvcrt._execv
@ forward _execve msvcrt._execve
@ forward _execvp msvcrt._execvp
@ forward _execvpe msvcrt._execvpe
@ forward _exit msvcrt._exit
@ forward _expand msvcrt._expand
@ forward _fcloseall msvcrt._fcloseall
@ forward _fcvt msvcrt._fcvt
@ forward _fdopen msvcrt._fdopen
@ forward _fgetchar msvcrt._fgetchar
@ forward _fgetwchar msvcrt._fgetwchar
@ forward _filbuf msvcrt._filbuf
@ forward _fileinfo_dll msvcrt._fileinfo
@ forward _filelength msvcrt._filelength
@ forward _fileno msvcrt._fileno
@ forward _findclose msvcrt._findclose
@ forward _findfirst msvcrt._findfirst
@ forward _findnext msvcrt._findnext
@ forward _finite msvcrt._finite
@ forward _flsbuf msvcrt._flsbuf
@ forward _flushall msvcrt._flushall
@ forward _fmode_dll msvcrt._fmode
@ forward _fpclass msvcrt._fpclass
@ forward _fpieee_flt msvcrt._fpieee_flt
@ forward _fpreset msvcrt._fpreset
@ forward _fputchar msvcrt._fputchar
@ forward _fputwchar msvcrt._fputwchar
@ forward _fsopen msvcrt._fsopen
@ forward _fstat msvcrt._fstat
@ forward _ftime msvcrt._ftime
@ forward _ftol msvcrt._ftol
@ forward _fullpath msvcrt._fullpath
@ forward _futime msvcrt._futime
@ forward _gcvt msvcrt._gcvt
@ forward _get_osfhandle msvcrt._get_osfhandle
@ forward _getch msvcrt._getch
@ forward _getche msvcrt._getche
@ forward _getcwd msvcrt._getcwd
@ forward _getdcwd msvcrt._getdcwd
@ forward _getdiskfree msvcrt._getdiskfree
@ forward _getdllprocaddr msvcrt._getdllprocaddr
@ forward _getdrive msvcrt._getdrive
@ forward _getdrives msvcrt._getdrives
@ forward _getpid msvcrt._getpid
@ forward _getsystime msvcrt._getsystime
@ forward _getw msvcrt._getw
@ forward _global_unwind2 msvcrt._global_unwind2
@ forward _heapchk msvcrt._heapchk
@ forward _heapmin msvcrt._heapmin
@ forward _heapset msvcrt._heapset
@ forward _heapwalk msvcrt._heapwalk
@ forward _hypot msvcrt._hypot
@ forward _initterm msvcrt._initterm
@ forward _iob msvcrt._iob
@ forward _isatty msvcrt._isatty
@ forward _isctype msvcrt._isctype
@ forward _ismbbalnum msvcrt._ismbbalnum
@ forward _ismbbalpha msvcrt._ismbbalpha
@ forward _ismbbgraph msvcrt._ismbbgraph
@ forward _ismbbkalnum msvcrt._ismbbkalnum
@ forward _ismbbkana msvcrt._ismbbkana
@ forward _ismbbkpunct msvcrt._ismbbkpunct
@ forward _ismbblead msvcrt._ismbblead
@ forward _ismbbprint msvcrt._ismbbprint
@ forward _ismbbpunct msvcrt._ismbbpunct
@ forward _ismbbtrail msvcrt._ismbbtrail
@ forward _ismbcalpha msvcrt._ismbcalpha
@ forward _ismbcdigit msvcrt._ismbcdigit
@ forward _ismbchira msvcrt._ismbchira
@ forward _ismbckata msvcrt._ismbckata
@ forward _ismbcl0 msvcrt._ismbcl0
@ forward _ismbcl1 msvcrt._ismbcl1
@ forward _ismbcl2 msvcrt._ismbcl2
@ forward _ismbclegal msvcrt._ismbclegal
@ forward _ismbclower msvcrt._ismbclower
@ forward _ismbcprint msvcrt._ismbcprint
@ forward _ismbcspace msvcrt._ismbcspace
@ forward _ismbcsymbol msvcrt._ismbcsymbol
@ forward _ismbcupper msvcrt._ismbcupper
@ forward _ismbslead msvcrt._ismbslead
@ forward _ismbstrail msvcrt._ismbstrail
@ forward _isnan msvcrt._isnan
@ forward _itoa msvcrt._itoa
@ forward _j0 msvcrt._j0
@ forward _j1 msvcrt._j1
@ forward _jn msvcrt._jn
@ forward _kbhit msvcrt._kbhit
@ forward _lfind msvcrt._lfind
@ forward _loaddll msvcrt._loaddll
@ forward _local_unwind2 msvcrt._local_unwind2
@ forward _locking msvcrt._locking
@ forward _logb msvcrt._logb
@ forward _lrotl msvcrt._lrotl
@ forward _lrotr msvcrt._lrotr
@ forward _lsearch msvcrt._lsearch
@ forward _lseek msvcrt._lseek
@ forward _ltoa msvcrt._ltoa
@ forward _makepath msvcrt._makepath
@ forward _matherr msvcrt._matherr
@ forward _mbbtombc msvcrt._mbbtombc
@ forward _mbbtype msvcrt._mbbtype
@ forward _mbccpy msvcrt._mbccpy
@ forward _mbcjistojms msvcrt._mbcjistojms
@ forward _mbcjmstojis msvcrt._mbcjmstojis
@ forward _mbclen msvcrt._mbclen
@ forward _mbctohira msvcrt._mbctohira
@ forward _mbctokata msvcrt._mbctokata
@ forward _mbctolower msvcrt._mbctolower
@ forward _mbctombb msvcrt._mbctombb
@ forward _mbctoupper msvcrt._mbctoupper
@ forward _mbctype msvcrt._mbctype
@ forward _mbsbtype msvcrt._mbsbtype
@ forward _mbscat msvcrt._mbscat
@ forward _mbschr msvcrt._mbschr
@ forward _mbscmp msvcrt._mbscmp
@ forward _mbscpy msvcrt._mbscpy
@ forward _mbscspn msvcrt._mbscspn
@ forward _mbsdec msvcrt._mbsdec
@ forward _mbsdup msvcrt._mbsdup
@ forward _mbsicmp msvcrt._mbsicmp
@ forward _mbsinc msvcrt._mbsinc
@ forward _mbslen msvcrt._mbslen
@ forward _mbslwr msvcrt._mbslwr
@ forward _mbsnbcat msvcrt._mbsnbcat
@ forward _mbsnbcmp msvcrt._mbsnbcmp
@ forward _mbsnbcnt msvcrt._mbsnbcnt
@ forward _mbsnbcpy msvcrt._mbsnbcpy
@ forward _mbsnbicmp msvcrt._mbsnbicmp
@ forward _mbsnbset msvcrt._mbsnbset
@ forward _mbsncat msvcrt._mbsncat
@ forward _mbsnccnt msvcrt._mbsnccnt
@ forward _mbsncmp msvcrt._mbsncmp
@ forward _mbsncpy msvcrt._mbsncpy
@ forward _mbsnextc msvcrt._mbsnextc
@ forward _mbsnicmp msvcrt._mbsnicmp
@ forward _mbsninc msvcrt._mbsninc
@ forward _mbsnset msvcrt._mbsnset
@ forward _mbspbrk msvcrt._mbspbrk
@ forward _mbsrchr msvcrt._mbsrchr
@ forward _mbsrev msvcrt._mbsrev
@ forward _mbsset msvcrt._mbsset
@ forward _mbsspn msvcrt._mbsspn
@ forward _mbsspnp msvcrt._mbsspnp
@ forward _mbsstr msvcrt._mbsstr
@ forward _mbstok msvcrt._mbstok
@ forward _mbstrlen msvcrt._mbstrlen
@ forward _mbsupr msvcrt._mbsupr
@ forward _memccpy msvcrt._memccpy
@ forward _memicmp msvcrt._memicmp
@ forward _mkdir msvcrt._mkdir
@ forward _mktemp msvcrt._mktemp
@ forward _msize msvcrt._msize
@ forward _nextafter msvcrt._nextafter
@ forward _onexit msvcrt._onexit
@ forward _open msvcrt._open
@ forward _open_osfhandle msvcrt._open_osfhandle
@ extern _osmajor_dll CRTDLL__osmajor_dll
@ extern _osminor_dll CRTDLL__osminor_dll
@ extern _osmode_dll CRTDLL__osmode_dll
@ forward _osver_dll msvcrt._osver
@ extern _osversion_dll CRTDLL__osversion_dll
@ forward _pclose msvcrt._pclose
@ forward _pctype_dll msvcrt._pctype
@ forward _pgmptr_dll msvcrt._pgmptr
@ forward _pipe msvcrt._pipe
@ forward _popen msvcrt._popen
@ forward _purecall msvcrt._purecall
@ forward _putch msvcrt._putch
@ forward _putenv msvcrt._putenv
@ forward _putw msvcrt._putw
@ forward _pwctype_dll msvcrt._pwctype
@ forward _read msvcrt._read
@ forward _rmdir msvcrt._rmdir
@ forward _rmtmp msvcrt._rmtmp
@ forward _rotl msvcrt._rotl
@ forward _rotr msvcrt._rotr
@ forward _scalb msvcrt._scalb
@ forward _searchenv msvcrt._searchenv
@ forward _seterrormode msvcrt._seterrormode
@ forward _setjmp msvcrt._setjmp
@ forward _setmode msvcrt._setmode
@ forward _setsystime msvcrt._setsystime
@ forward _sleep msvcrt._sleep
@ forward _snprintf msvcrt._snprintf
@ forward _snwprintf msvcrt._snwprintf
@ forward _sopen msvcrt._sopen
@ forward _spawnl msvcrt._spawnl
@ forward _spawnle msvcrt._spawnle
@ forward _spawnlp msvcrt._spawnlp
@ forward _spawnlpe msvcrt._spawnlpe
@ forward _spawnv msvcrt._spawnv
@ forward _spawnve msvcrt._spawnve
@ forward _spawnvp msvcrt._spawnvp
@ forward _spawnvpe msvcrt._spawnvpe
@ forward _splitpath msvcrt._splitpath
@ forward _stat msvcrt._stat
@ forward _statusfp msvcrt._statusfp
@ forward _strcmpi msvcrt._strcmpi
@ forward _strdate msvcrt._strdate
@ forward _strdec msvcrt._strdec
@ forward _strdup msvcrt._strdup
@ forward _strerror msvcrt._strerror
@ forward _stricmp msvcrt._stricmp
@ forward _stricoll msvcrt._stricoll
@ forward _strinc msvcrt._strinc
@ forward _strlwr msvcrt._strlwr
@ forward _strncnt msvcrt._strncnt
@ forward _strnextc msvcrt._strnextc
@ forward _strnicmp msvcrt._strnicmp
@ forward _strninc msvcrt._strninc
@ forward _strnset msvcrt._strnset
@ forward _strrev msvcrt._strrev
@ forward _strset msvcrt._strset
@ forward _strspnp msvcrt._strspnp
@ forward _strtime msvcrt._strtime
@ forward _strupr msvcrt._strupr
@ forward _swab msvcrt._swab
@ forward _sys_errlist msvcrt._sys_errlist
@ forward _sys_nerr_dll msvcrt._sys_nerr
@ forward _tell msvcrt._tell
@ forward _tempnam msvcrt._tempnam
@ forward _timezone_dll msvcrt._timezone
@ forward _tolower msvcrt._tolower
@ forward _toupper msvcrt._toupper
@ forward _tzname msvcrt._tzname
@ forward _tzset msvcrt._tzset
@ forward _ultoa msvcrt._ultoa
@ forward _umask msvcrt._umask
@ forward _ungetch msvcrt._ungetch
@ forward _unlink msvcrt._unlink
@ forward _unloaddll msvcrt._unloaddll
@ forward _utime msvcrt._utime
@ forward _vsnprintf msvcrt._vsnprintf
@ forward _vsnwprintf msvcrt._vsnwprintf
@ forward _wcsdup msvcrt._wcsdup
@ forward _wcsicmp msvcrt._wcsicmp
@ forward _wcsicoll msvcrt._wcsicoll
@ forward _wcslwr msvcrt._wcslwr
@ forward _wcsnicmp msvcrt._wcsnicmp
@ forward _wcsnset msvcrt._wcsnset
@ forward _wcsrev msvcrt._wcsrev
@ forward _wcsset msvcrt._wcsset
@ forward _wcsupr msvcrt._wcsupr
@ forward _winmajor_dll msvcrt._winmajor
@ forward _winminor_dll msvcrt._winminor
@ forward _winver_dll msvcrt._winver
@ forward _write msvcrt._write
@ forward _wtoi msvcrt._wtoi
@ forward _wtol msvcrt._wtol
@ forward _y0 msvcrt._y0
@ forward _y1 msvcrt._y1
@ forward _yn msvcrt._yn
@ forward abort msvcrt.abort
@ forward abs msvcrt.abs
@ forward acos msvcrt.acos
@ forward asctime msvcrt.asctime
@ forward asin msvcrt.asin
@ forward atan msvcrt.atan
@ forward atan2 msvcrt.atan2
@ forward atexit msvcrt.atexit
@ forward atof msvcrt.atof
@ forward atoi msvcrt.atoi
@ forward atol msvcrt.atol
@ forward bsearch msvcrt.bsearch
@ forward calloc msvcrt.calloc
@ forward ceil msvcrt.ceil
@ forward clearerr msvcrt.clearerr
@ forward clock msvcrt.clock
@ forward cos msvcrt.cos
@ forward cosh msvcrt.cosh
@ forward ctime msvcrt.ctime
@ forward difftime msvcrt.difftime
@ forward div msvcrt.div
@ forward exit msvcrt.exit
@ forward exp msvcrt.exp
@ forward fabs msvcrt.fabs
@ forward fclose msvcrt.fclose
@ forward feof msvcrt.feof
@ forward ferror msvcrt.ferror
@ forward fflush msvcrt.fflush
@ forward fgetc msvcrt.fgetc
@ forward fgetpos msvcrt.fgetpos
@ forward fgets msvcrt.fgets
@ forward fgetwc msvcrt.fgetwc
@ forward floor msvcrt.floor
@ forward fmod msvcrt.fmod
@ forward fopen msvcrt.fopen
@ forward fprintf msvcrt.fprintf
@ forward fputc msvcrt.fputc
@ forward fputs msvcrt.fputs
@ forward fputwc msvcrt.fputwc
@ forward fread msvcrt.fread
@ forward free msvcrt.free
@ forward freopen msvcrt.freopen
@ forward frexp msvcrt.frexp
@ forward fscanf msvcrt.fscanf
@ forward fseek msvcrt.fseek
@ forward fsetpos msvcrt.fsetpos
@ forward ftell msvcrt.ftell
@ forward fwprintf msvcrt.fwprintf
@ forward fwrite msvcrt.fwrite
@ forward fwscanf msvcrt.fwscanf
@ forward getc msvcrt.getc
@ forward getchar msvcrt.getchar
@ forward getenv msvcrt.getenv
@ forward gets msvcrt.gets
@ forward gmtime msvcrt.gmtime
@ forward is_wctype msvcrt.is_wctype
@ forward isalnum msvcrt.isalnum
@ forward isalpha msvcrt.isalpha
@ forward iscntrl msvcrt.iscntrl
@ forward isdigit msvcrt.isdigit
@ forward isgraph msvcrt.isgraph
@ forward isleadbyte msvcrt.isleadbyte
@ forward islower msvcrt.islower
@ forward isprint msvcrt.isprint
@ forward ispunct msvcrt.ispunct
@ forward isspace msvcrt.isspace
@ forward isupper msvcrt.isupper
@ forward iswalnum msvcrt.iswalnum
@ forward iswalpha msvcrt.iswalpha
@ forward iswascii msvcrt.iswascii
@ forward iswcntrl msvcrt.iswcntrl
@ forward iswctype msvcrt.iswctype
@ forward iswdigit msvcrt.iswdigit
@ forward iswgraph msvcrt.iswgraph
@ forward iswlower msvcrt.iswlower
@ forward iswprint msvcrt.iswprint
@ forward iswpunct msvcrt.iswpunct
@ forward iswspace msvcrt.iswspace
@ forward iswupper msvcrt.iswupper
@ forward iswxdigit msvcrt.iswxdigit
@ forward isxdigit msvcrt.isxdigit
@ forward labs msvcrt.labs
@ forward ldexp msvcrt.ldexp
@ forward ldiv msvcrt.ldiv
@ forward localeconv msvcrt.localeconv
@ forward localtime msvcrt.localtime
@ forward log msvcrt.log
@ forward log10 msvcrt.log10
@ forward longjmp msvcrt.longjmp
@ forward malloc msvcrt.malloc
@ forward mblen msvcrt.mblen
@ forward mbstowcs msvcrt.mbstowcs
@ forward mbtowc msvcrt.mbtowc
@ forward memchr msvcrt.memchr
@ forward memcmp msvcrt.memcmp
@ forward memcpy msvcrt.memcpy
@ forward memmove msvcrt.memmove
@ forward memset msvcrt.memset
@ forward mktime msvcrt.mktime
@ forward modf msvcrt.modf
@ forward perror msvcrt.perror
@ forward pow msvcrt.pow
@ forward printf msvcrt.printf
@ forward putc msvcrt.putc
@ forward putchar msvcrt.putchar
@ forward puts msvcrt.puts
@ forward qsort msvcrt.qsort
@ forward raise msvcrt.raise
@ forward rand msvcrt.rand
@ forward realloc msvcrt.realloc
@ forward remove msvcrt.remove
@ forward rename msvcrt.rename
@ forward rewind msvcrt.rewind
@ forward scanf msvcrt.scanf
@ forward setbuf msvcrt.setbuf
@ forward setlocale msvcrt.setlocale
@ forward setvbuf msvcrt.setvbuf
@ forward signal msvcrt.signal
@ forward sin msvcrt.sin
@ forward sinh msvcrt.sinh
@ forward sprintf msvcrt.sprintf
@ forward sqrt msvcrt.sqrt
@ forward srand msvcrt.srand
@ forward sscanf msvcrt.sscanf
@ forward strcat msvcrt.strcat
@ forward strchr msvcrt.strchr
@ forward strcmp msvcrt.strcmp
@ forward strcoll msvcrt.strcoll
@ forward strcpy msvcrt.strcpy
@ forward strcspn msvcrt.strcspn
@ forward strerror msvcrt.strerror
@ forward strftime msvcrt.strftime
@ forward strlen msvcrt.strlen
@ forward strncat msvcrt.strncat
@ forward strncmp msvcrt.strncmp
@ forward strncpy msvcrt.strncpy
@ forward strpbrk msvcrt.strpbrk
@ forward strrchr msvcrt.strrchr
@ forward strspn msvcrt.strspn
@ forward strstr msvcrt.strstr
@ forward strtod msvcrt.strtod
@ forward strtok msvcrt.strtok
@ forward strtol msvcrt.strtol
@ forward strtoul msvcrt.strtoul
@ forward strxfrm msvcrt.strxfrm
@ forward swprintf msvcrt.swprintf
@ forward swscanf msvcrt.swscanf
@ forward system msvcrt.system
@ forward tan msvcrt.tan
@ forward tanh msvcrt.tanh
@ forward time msvcrt.time
@ forward tmpfile msvcrt.tmpfile
@ forward tmpnam msvcrt.tmpnam
@ forward tolower msvcrt._tolower
@ forward toupper msvcrt._toupper
@ forward towlower msvcrt.towlower
@ forward towupper msvcrt.towupper
@ forward ungetc msvcrt.ungetc
@ forward ungetwc msvcrt.ungetwc
@ forward vfprintf msvcrt.vfprintf
@ forward vfwprintf msvcrt.vfwprintf
@ forward vprintf msvcrt.vprintf
@ forward vsprintf msvcrt.vsprintf
@ forward vswprintf msvcrt.vswprintf
@ forward vwprintf msvcrt.vwprintf
@ forward wcscat msvcrt.wcscat
@ forward wcschr msvcrt.wcschr
@ forward wcscmp msvcrt.wcscmp
@ forward wcscoll msvcrt.wcscoll
@ forward wcscpy msvcrt.wcscpy
@ forward wcscspn msvcrt.wcscspn
@ forward wcsftime msvcrt.wcsftime
@ forward wcslen msvcrt.wcslen
@ forward wcsncat msvcrt.wcsncat
@ forward wcsncmp msvcrt.wcsncmp
@ forward wcsncpy msvcrt.wcsncpy
@ forward wcspbrk msvcrt.wcspbrk
@ forward wcsrchr msvcrt.wcsrchr
@ forward wcsspn msvcrt.wcsspn
@ forward wcsstr msvcrt.wcsstr
@ forward wcstod msvcrt.wcstod
@ forward wcstok msvcrt.wcstok
@ forward wcstol msvcrt.wcstol
@ forward wcstombs msvcrt.wcstombs
@ forward wcstoul msvcrt.wcstoul
@ forward wcsxfrm msvcrt.wcsxfrm
@ forward wctomb msvcrt.wctomb
@ forward wprintf msvcrt.wprintf
@ forward wscanf msvcrt.wscanf
@ forward _itow msvcrt._itow
@ forward _ltow msvcrt._ltow
/*
* The C RunTime DLL
*
* Implements C run-time functionality as known from UNIX.
* Old C RunTime DLL - All functionality is provided by msvcrt.
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*/
/*
Unresolved issues Uwe Bonnes 970904:
- tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
for Win32, based on lcc, from Jacob Navia
UB 000416:
- probably not thread safe
*/
/* NOTE: This file also implements the wcs* functions. They _ARE_ in
* the newer Linux libcs, but use 4 byte wide characters, so are unusable,
* since we need 2 byte wide characters. - Marcus Meissner, 981031
*/
#include "config.h"
#include "crtdll.h"
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#include <ctype.h>
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#include <errno.h>
#include <stdlib.h>
#include "ntddk.h"
#include "wingdi.h"
#include "winuser.h"
#ifndef HAVE_FINITE
#ifndef finite /* Could be macro */
#ifdef isfinite
#define finite(x) isfinite(x)
#else
#define finite(x) (!isnan(x)) /* At least catch some cases */
#endif
#endif
#endif
#ifndef signbit
#define signbit(x) 0
#endif
#include "windef.h"
#include "winbase.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
double CRTDLL_HUGE_dll; /* CRTDLL.20 */
UINT CRTDLL_argc_dll; /* CRTDLL.23 */
LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
UINT CRTDLL_commode_dll; /* CRTDLL.59 */
LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
UINT CRTDLL_osver_dll; /* CRTDLL.244 */
UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
LONG CRTDLL_timezone_dll = 0; /* CRTDLL.304 */
UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
UINT CRTDLL_winver_dll; /* CRTDLL.331 */
INT CRTDLL_doserrno = 0;
INT CRTDLL_errno = 0;
INT CRTDLL__mb_cur_max_dll = 1;
const INT CRTDLL__sys_nerr = 43;
/* ASCII char classification flags - binary compatible */
#define _C_ CRTDLL_CONTROL
#define _S_ CRTDLL_SPACE
#define _P_ CRTDLL_PUNCT
#define _D_ CRTDLL_DIGIT
#define _H_ CRTDLL_HEX
#define _U_ CRTDLL_UPPER
#define _L_ CRTDLL_LOWER
WORD CRTDLL_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_|CRTDLL_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 __CRTDLL_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* CRTDLL_pctype_dll = __CRTDLL_current_ctype + 1;
/* The following data items are not exported from msvcrt */
unsigned int CRTDLL__basemajor_dll;
unsigned int CRTDLL__baseminor_dll;
unsigned int CRTDLL__baseversion_dll;
unsigned int CRTDLL__cpumode_dll;
unsigned int CRTDLL__osmajor_dll;
unsigned int CRTDLL__osminor_dll;
unsigned int CRTDLL__osmode_dll;
unsigned int CRTDLL__osversion_dll;
/*********************************************************************
* CRTDLL_MainInit (CRTDLL.init)
*/
BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
if (fdwReason == DLL_PROCESS_ATTACH) {
__CRTDLL__init_io();
__CRTDLL_init_console();
CRTDLL_setlocale( CRTDLL_LC_ALL, "C" );
CRTDLL_HUGE_dll = HUGE_VAL;
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
CRTDLL__fcloseall();
__CRTDLL_free_console();
}
return TRUE;
}
/* INTERNAL: Set the crt and dos errno's from the OS error given. */
void __CRTDLL__set_errno(ULONG err)
{
/* FIXME: not MT safe */
CRTDLL_doserrno = err;
switch(err)
{
#define ERR_CASE(oserr) case oserr:
#define ERR_MAPS(oserr,crterr) case oserr:CRTDLL_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, 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, ENOENT);
ERR_MAPS(ERROR_IO_DEVICE, EIO);
ERR_MAPS(ERROR_BAD_FORMAT, ENOEXEC);
ERR_MAPS(ERROR_INVALID_HANDLE, EBADF);
ERR_CASE(ERROR_OUTOFMEMORY)
ERR_CASE(ERROR_INVALID_BLOCK)
ERR_CASE(ERROR_NOT_ENOUGH_QUOTA);
ERR_MAPS(ERROR_ARENA_TRASHED, ENOMEM);
ERR_MAPS(ERROR_BUSY, EBUSY);
ERR_CASE(ERROR_ALREADY_EXISTS)
ERR_MAPS(ERROR_FILE_EXISTS, EEXIST);
ERR_MAPS(ERROR_BAD_DEVICE, ENODEV);
ERR_MAPS(ERROR_TOO_MANY_OPEN_FILES, EMFILE);
ERR_MAPS(ERROR_DISK_FULL, ENOSPC);
ERR_MAPS(ERROR_BROKEN_PIPE, EPIPE);
ERR_MAPS(ERROR_POSSIBLE_DEADLOCK, EDEADLK);
ERR_MAPS(ERROR_DIR_NOT_EMPTY, ENOTEMPTY);
ERR_MAPS(ERROR_BAD_ENVIRONMENT, E2BIG);
ERR_CASE(ERROR_WAIT_NO_CHILDREN)
ERR_MAPS(ERROR_CHILD_NOT_COMPLETE, ECHILD);
ERR_CASE(ERROR_NO_PROC_SLOTS)
ERR_CASE(ERROR_MAX_THRDS_REACHED)
ERR_MAPS(ERROR_NESTING_NOT_ALLOWED, EAGAIN);
default:
/* Remaining cases map to EINVAL */
/* FIXME: may be missing some errors above */
CRTDLL_errno = EINVAL;
}
}
#if defined(__GNUC__) && defined(__i386__)
#define FPU_DOUBLE(var) double var; \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
#define FPU_DOUBLES(var1,var2) double var1,var2; \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
__asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
#else
#define FPU_DOUBLE(var) double var = sqrt(-1); \
FIXME(":not implemented\n");
#define FPU_DOUBLES(var1,var2) double var1,var2; \
var1=var2=sqrt(-1); FIXME(":not implemented\n")
#endif
/*********************************************************************
* _CIacos (CRTDLL.004)
*/
double __cdecl CRTDLL__CIacos(void)
{
FPU_DOUBLE(x);
if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
return acos(x);
}
/*********************************************************************
* _CIasin (CRTDLL.005)
*/
double __cdecl CRTDLL__CIasin(void)
{
FPU_DOUBLE(x);
if (x < -1.0 || x > 1.0 || !finite(x)) CRTDLL_errno = EDOM;
return asin(x);
}
/*********************************************************************
* _CIatan (CRTDLL.006)
*/
double __cdecl CRTDLL__CIatan(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return atan(x);
}
/*********************************************************************
* _CIatan2 (CRTDLL.007)
*/
double __cdecl CRTDLL__CIatan2(void)
{
FPU_DOUBLES(x,y);
if (!finite(x)) CRTDLL_errno = EDOM;
return atan2(x,y);
}
/*********************************************************************
* _CIcos (CRTDLL.008)
*/
double __cdecl CRTDLL__CIcos(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return cos(x);
}
/*********************************************************************
* _CIcosh (CRTDLL.009)
*/
double __cdecl CRTDLL__CIcosh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return cosh(x);
}
/*********************************************************************
* _CIexp (CRTDLL.010)
*/
double __cdecl CRTDLL__CIexp(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return exp(x);
}
/*********************************************************************
* _CIfmod (CRTDLL.011)
*/
double __cdecl CRTDLL__CIfmod(void)
{
FPU_DOUBLES(x,y);
if (!finite(x) || !finite(y)) CRTDLL_errno = EDOM;
return fmod(x,y);
}
/*********************************************************************
* _CIlog (CRTDLL.012)
*/
double __cdecl CRTDLL__CIlog(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
if (x == 0.0) CRTDLL_errno = ERANGE;
return log(x);
}
/*********************************************************************
* _CIlog10 (CRTDLL.013)
*/
double __cdecl CRTDLL__CIlog10(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
if (x == 0.0) CRTDLL_errno = ERANGE;
return log10(x);
}
/*********************************************************************
* _CIpow (CRTDLL.014)
*/
double __cdecl CRTDLL__CIpow(void)
{
double z;
FPU_DOUBLES(x,y);
/* FIXME: If x < 0 and y is not integral, set EDOM */
z = pow(x,y);
if (!finite(z)) CRTDLL_errno = EDOM;
return z;
}
/*********************************************************************
* _CIsin (CRTDLL.015)
*/
double __cdecl CRTDLL__CIsin(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return sin(x);
}
/*********************************************************************
* _CIsinh (CRTDLL.016)
*/
double __cdecl CRTDLL__CIsinh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return sinh(x);
}
/*********************************************************************
* _CIsqrt (CRTDLL.017)
*/
double __cdecl CRTDLL__CIsqrt(void)
{
FPU_DOUBLE(x);
if (x < 0.0 || !finite(x)) CRTDLL_errno = EDOM;
return sqrt(x);
}
/*********************************************************************
* _CItan (CRTDLL.018)
*/
double __cdecl CRTDLL__CItan(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return tan(x);
}
/*********************************************************************
* _CItanh (CRTDLL.019)
*/
double __cdecl CRTDLL__CItanh(void)
{
FPU_DOUBLE(x);
if (!finite(x)) CRTDLL_errno = EDOM;
return tanh(x);
}
/*********************************************************************
* _GetMainArgs (CRTDLL.022)
*/
LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
LPSTR *environ,DWORD flag)
{
char *cmdline;
char **xargv;
int xargc,end,last_arg,afterlastspace;
DWORD version;
TRACE("(%p,%p,%p,%ld).\n",
argc,argv,environ,flag
);
if (CRTDLL_acmdln_dll != NULL)
HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
CRTDLL_acmdln_dll = cmdline = CRTDLL__strdup( GetCommandLineA() );
TRACE("got '%s'\n", cmdline);
version = GetVersion();
CRTDLL_osver_dll = version >> 16;
CRTDLL_winminor_dll = version & 0xFF;
CRTDLL_winmajor_dll = (version>>8) & 0xFF;
CRTDLL_baseversion_dll = version >> 16;
CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
CRTDLL_osversion_dll = version & 0xFFFF;
CRTDLL_osminor_dll = version & 0xFF;
CRTDLL_osmajor_dll = (version>>8) & 0xFF;
/* missing threading init */
end=0;last_arg=0;xargv=NULL;xargc=0;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));
if (strlen(cmdline+afterlastspace))
{
xargv[xargc] = CRTDLL__strdup(cmdline+afterlastspace);
xargc++;
if (!last_arg) /* need to seek to the next arg ? */
{
end++;
while (cmdline[end]==' ')
end++;
}
afterlastspace=end;
}
else
{
xargv[xargc] = NULL; /* the last entry is NULL */
break;
}
}
else
end++;
}
CRTDLL_argc_dll = xargc;
*argc = xargc;
CRTDLL_argv_dll = xargv;
*argv = xargv;
TRACE("found %d arguments\n",
CRTDLL_argc_dll);
CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
return environ;
}
/*********************************************************************
* _clearfp (CRTDLL.056)
*
* Clear and return the previous FP status.
*/
UINT __cdecl CRTDLL__clearfp( VOID )
{
UINT retVal = CRTDLL__statusfp();
#if defined(__GNUC__) && defined(__i386__)
__asm__ __volatile__( "fnclex" );
#else
FIXME(":Not Implemented!\n");
#endif
return retVal;
}
/*********************************************************************
* _fpclass (CRTDLL.105)
*
* Return the FP classification of d.
*/
INT __cdecl CRTDLL__fpclass(double d)
{
#if defined(HAVE_FPCLASS) || defined(fpclass)
switch (fpclass( d ))
{
case FP_SNAN: return _FPCLASS_SNAN;
case FP_QNAN: return _FPCLASS_QNAN;
case FP_NINF: return _FPCLASS_NINF;
case FP_PINF: return _FPCLASS_PINF;
case FP_NDENORM: return _FPCLASS_ND;
case FP_PDENORM: return _FPCLASS_PD;
case FP_NZERO: return _FPCLASS_NZ;
case FP_PZERO: return _FPCLASS_PZ;
case FP_NNORM: return _FPCLASS_NN;
}
return _FPCLASS_PN;
#elif defined (fpclassify)
switch (fpclassify( d ))
{
case FP_NAN: return _FPCLASS_QNAN;
case FP_INFINITE: return signbit(d) ? _FPCLASS_NINF : _FPCLASS_PINF;
case FP_SUBNORMAL: return signbit(d) ?_FPCLASS_ND : _FPCLASS_PD;
case FP_ZERO: return signbit(d) ? _FPCLASS_NZ : _FPCLASS_PZ;
}
return signbit(d) ? _FPCLASS_NN : _FPCLASS_PN;
#else
if (!finite(d))
return _FPCLASS_QNAN;
return d == 0.0 ? _FPCLASS_PZ : (d < 0 ? _FPCLASS_NN : _FPCLASS_PN);
#endif
}
/*********************************************************************
* _initterm (CRTDLL.135)
*/
DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
{
_INITTERMFUN *current;
TRACE("(%p,%p)\n",start,end);
current=start;
while (current<end) {
if (*current) (*current)();
current++;
}
return 0;
}
/*******************************************************************
* _global_unwind2 (CRTDLL.129)
*/
void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
{
RtlUnwind( frame, 0, NULL, 0 );
}
/*******************************************************************
* _local_unwind2 (CRTDLL.173)
*/
void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
{
TRACE("(%p,%ld)\n",endframe,nr);
}
/*******************************************************************
* _setjmp (CRTDLL.264)
*/
INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
{
FIXME(":(%p): stub\n",jmpbuf);
return 0;
}
/*********************************************************************
* _beep (CRTDLL.045)
*
* Output a tone using the PC speaker.
*
* PARAMS
* freq [in] Frequency of the tone
*
* duration [in] Length of time the tone should sound
*
* RETURNS
* None.
*/
void __cdecl CRTDLL__beep( UINT freq, UINT duration)
{
TRACE(":Freq %d, Duration %d\n",freq,duration);
Beep(freq, duration);
}
/*********************************************************************
* rand (CRTDLL.446)
*/
INT __cdecl CRTDLL_rand()
{
return (rand() & CRTDLL_RAND_MAX);
}
/*********************************************************************
* _rotl (CRTDLL.259)
*/
UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
{
shift &= 31;
return (x << shift) | (x >> (32-shift));
}
/*********************************************************************
* _logb (CRTDLL.174)
*/
double __cdecl CRTDLL__logb(double x)
{
if (!finite(x)) CRTDLL_errno = EDOM;
return logb(x);
}
/*********************************************************************
* _lrotl (CRTDLL.175)
*/
DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
{
shift &= 31;
return (x << shift) | (x >> (32-shift));
}
/*********************************************************************
* _lrotr (CRTDLL.176)
*/
DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
{
shift &= 0x1f;
return (x >> shift) | (x << (32-shift));
}
/*********************************************************************
* _rotr (CRTDLL.258)
*/
DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
{
shift &= 0x1f;
return (x >> shift) | (x << (32-shift));
}
/*********************************************************************
* _scalb (CRTDLL.259)
*
* Return x*2^y.
*/
double __cdecl CRTDLL__scalb(double x, LONG y)
{
/* Note - Can't forward directly as libc expects y as double */
double y2 = (double)y;
if (!finite(x)) CRTDLL_errno = EDOM;
return scalb( x, y2 );
}
/*********************************************************************
* longjmp (CRTDLL.426)
*/
VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
{
FIXME("CRTDLL_longjmp semistup, expect crash\n");
longjmp(env, val);
}
/*********************************************************************
* _isctype (CRTDLL.138)
*/
INT __cdecl CRTDLL__isctype(INT c, UINT type)
{
if (c >= -1 && c <= 255)
return CRTDLL_pctype_dll[c] & type;
if (CRTDLL__mb_cur_max_dll != 1 && c > 0)
{
/* FIXME: Is there a faster way to do this? */
WORD typeInfo;
char convert[3], *pconv = convert;
if (CRTDLL_pctype_dll[(UINT)c >> 8] & CRTDLL_LEADBYTE)
*pconv++ = (UINT)c >> 8;
*pconv++ = c & 0xff;
*pconv = 0;
/* FIXME: Use ctype LCID */
if (GetStringTypeExA(__CRTDLL_current_lc_all_lcid, CT_CTYPE1,
convert, convert[1] ? 2 : 1, &typeInfo))
return typeInfo & type;
}
return 0;
}
/* 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 */
TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
while (NULL != (p = strstr(s, "\\.")))
if (fdwReason == DLL_PROCESS_ATTACH)
{
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);
}
DWORD version = GetVersion();
CRTDLL__basemajor_dll = (version >> 24) & 0xFF;
CRTDLL__baseminor_dll = (version >> 16) & 0xFF;
CRTDLL__baseversion_dll = (version >> 16);
CRTDLL__cpumode_dll = 1; /* FIXME */
CRTDLL__osmajor_dll = (version>>8) & 0xFF;
CRTDLL__osminor_dll = (version & 0xFF);
CRTDLL__osmode_dll = 1; /* FIXME */
CRTDLL__osversion_dll = (version & 0xFFFF);
}
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, "\\");
return TRUE;
}
/*********************************************************************
* _fullpath
*
* Convert a partial path into a complete, normalised path.
*/
LPSTR __cdecl CRTDLL__fullpath(LPSTR absPath, LPCSTR relPath, 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 CRTDLL__getcwd(absPath, size);
if (size < 4)
{
CRTDLL_errno = ERANGE;
return NULL;
}
TRACE(":resolving relative path '%s'\n",relPath);
CRTDLL__splitpath(relPath, drive, dir, file, ext);
/* Get Directory and drive into 'res' */
if (!dir[0] || (dir[0] != '/' && dir[0] != '\\'))
{
/* Relative or no directory given */
CRTDLL__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 CRTDLL__strdup(res);
strcpy(absPath,res);
return absPath;
}
/*********************************************************************
* _splitpath (CRTDLL.279)
*
* Split a path string into components.
*
* PARAMETERS
* inpath [in] Path to split
* drive [out] "x:" or ""
* directory [out] "\dir", "\dir\", "/dir", "/dir/", "./" etc
* filename [out] filename, without dot or slashes
* extension [out] ".ext" or ""
*/
VOID __cdecl CRTDLL__splitpath(LPCSTR inpath, LPSTR drv, LPSTR dir,
LPSTR fname, LPSTR 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);
}
}
}
/*********************************************************************
* _matherr (CRTDLL.181)
*
* Default handler for math errors.
*/
INT __cdecl CRTDLL__matherr(struct _exception *e)
{
/* FIXME: Supposedly this can be user overridden, but
* currently it will never be called anyway. User will
* need to use .spec ignore directive to override.
*/
FIXME(":Unhandled math error!\n");
return e == NULL ? 0 : 0;
}
/*********************************************************************
* _makepath (CRTDLL.182)
*/
VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
LPCSTR directory, LPCSTR filename,
LPCSTR extension )
{
char ch;
TRACE("CRTDLL__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("CRTDLL__makepath returns %s\n",path);
}
/*********************************************************************
* _errno (CRTDLL.52)
* Return the address of the CRT errno (Not the libc errno).
*
* BUGS
* Not MT safe.
*/
LPINT __cdecl CRTDLL__errno( VOID )
{
return &CRTDLL_errno;
}
/*********************************************************************
* __doserrno (CRTDLL.26)
*
* Return the address of the DOS errno (holding the last OS error).
*
* BUGS
* Not MT safe.
*/
LPINT __cdecl CRTDLL___doserrno( VOID )
{
return &CRTDLL_doserrno;
}
/**********************************************************************
* _statusfp (CRTDLL.279)
*
* Return the status of the FP control word.
*/
UINT __cdecl CRTDLL__statusfp( VOID )
{
UINT retVal = 0;
#if defined(__GNUC__) && defined(__i386__)
UINT fpword;
__asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
if (fpword & 0x1) retVal |= _SW_INVALID;
if (fpword & 0x2) retVal |= _SW_DENORMAL;
if (fpword & 0x4) retVal |= _SW_ZERODIVIDE;
if (fpword & 0x8) retVal |= _SW_OVERFLOW;
if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
if (fpword & 0x20) retVal |= _SW_INEXACT;
#else
FIXME(":Not implemented!\n");
#endif
return retVal;
}
/**********************************************************************
* _strerror (CRTDLL.284)
*
* Return a formatted system error message.
*
* NOTES
* The caller does not own the string returned.
*/
extern int sprintf(char *str, const char *format, ...);
LPSTR __cdecl CRTDLL__strerror (LPCSTR err)
{
static char strerrbuff[256];
sprintf(strerrbuff,"%s: %s\n",err,CRTDLL_strerror(CRTDLL_errno));
return strerrbuff;
}
/*********************************************************************
* perror (CRTDLL.435)
*
* Print a formatted system error message to stderr.
*/
VOID __cdecl CRTDLL_perror (LPCSTR err)
{
char *err_str = CRTDLL_strerror(CRTDLL_errno);
CRTDLL_fprintf(CRTDLL_stderr,"%s: %s\n",err,err_str);
}
/*********************************************************************
* strerror (CRTDLL.465)
*
* Return the text of an error.
*
* NOTES
* The caller does not own the string returned.
*/
extern char *strerror(int errnum);
LPSTR __cdecl CRTDLL_strerror (INT err)
{
return strerror(err);
}
/*********************************************************************
* signal (CRTDLL.455)
*/
LPVOID __cdecl CRTDLL_signal(INT sig, sig_handler_type ptr)
{
FIXME("(%d %p):stub.\n", sig, ptr);
return (void*)-1;
}
/*********************************************************************
* _sleep (CRTDLL.267)
*/
VOID __cdecl CRTDLL__sleep(ULONG timeout)
{
TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
Sleep((timeout)?timeout:1);
}
/*********************************************************************
* getenv (CRTDLL.437)
*/
LPSTR __cdecl CRTDLL_getenv(LPCSTR 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;
}
/*********************************************************************
* isalnum (CRTDLL.442)
*/
INT __cdecl CRTDLL_isalnum(INT c)
{
return CRTDLL__isctype( c,CRTDLL_ALPHA | CRTDLL_DIGIT );
}
/*********************************************************************
* isalpha (CRTDLL.443)
*/
INT __cdecl CRTDLL_isalpha(INT c)
{
return CRTDLL__isctype( c, CRTDLL_ALPHA );
}
/*********************************************************************
* iscntrl (CRTDLL.444)
*/
INT __cdecl CRTDLL_iscntrl(INT c)
{
return CRTDLL__isctype( c, CRTDLL_CONTROL );
}
/*********************************************************************
* isdigit (CRTDLL.445)
*/
INT __cdecl CRTDLL_isdigit(INT c)
{
return CRTDLL__isctype( c, CRTDLL_DIGIT );
}
/*********************************************************************
* isgraph (CRTDLL.446)
*/
INT __cdecl CRTDLL_isgraph(INT c)
{
return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT | CRTDLL_PUNCT );
}
/*********************************************************************
* isleadbyte (CRTDLL.447)
*/
INT __cdecl CRTDLL_isleadbyte(UCHAR c)
{
return CRTDLL__isctype( c, CRTDLL_LEADBYTE );
}
/*********************************************************************
* islower (CRTDLL.447)
*/
INT __cdecl CRTDLL_islower(INT c)
{
return CRTDLL__isctype( c, CRTDLL_LOWER );
}
/*********************************************************************
* isprint (CRTDLL.448)
*/
INT __cdecl CRTDLL_isprint(INT c)
{
return CRTDLL__isctype( c, CRTDLL_ALPHA | CRTDLL_DIGIT |
CRTDLL_BLANK | CRTDLL_PUNCT );
}
/*********************************************************************
* ispunct (CRTDLL.449)
*/
INT __cdecl CRTDLL_ispunct(INT c)
{
return CRTDLL__isctype( c, CRTDLL_PUNCT );
}
/*********************************************************************
* isspace (CRTDLL.450)
*/
INT __cdecl CRTDLL_isspace(INT c)
{
return CRTDLL__isctype( c, CRTDLL_SPACE );
}
/*********************************************************************
* isupper (CRTDLL.451)
*/
INT __cdecl CRTDLL_isupper(INT c)
{
return CRTDLL__isctype( c, CRTDLL_UPPER );
}
/*********************************************************************
* isxdigit (CRTDLL.452)
*/
INT __cdecl CRTDLL_isxdigit(INT c)
{
return CRTDLL__isctype( c, CRTDLL_HEX );
}
/*********************************************************************
* ldexp (CRTDLL.454)
*/
double __cdecl CRTDLL_ldexp(double x, LONG y)
{
double z = ldexp(x,y);
if (!finite(z))
CRTDLL_errno = ERANGE;
else if (z == 0 && signbit(z))
z = 0.0; /* Convert -0 -> +0 */
return z;
}
/*********************************************************************
* _except_handler2 (CRTDLL.78)
*/
INT __cdecl CRTDLL__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;
}
/*********************************************************************
* __isascii (CRTDLL.028)
*
*/
INT __cdecl CRTDLL___isascii(INT c)
{
return isascii((unsigned)c);
}
/*********************************************************************
* __toascii (CRTDLL.035)
*
*/
INT __cdecl CRTDLL___toascii(INT c)
{
return (unsigned)c & 0x7f;
}
/*********************************************************************
* iswascii (CRTDLL.404)
*
*/
INT __cdecl CRTDLL_iswascii(LONG c)
{
return ((unsigned)c < 0x80);
}
/*********************************************************************
* __iscsym (CRTDLL.029)
*
* Is a character valid in a C identifier (a-Z,0-9,_).
*
* PARAMS
* c [I]: Character to check
*
* RETURNS
* Non zero if c is valid as t a C identifier.
*/
INT __cdecl CRTDLL___iscsym(UCHAR c)
{
return (c < 127 && (isalnum(c) || c == '_'));
}
/*********************************************************************
* __iscsymf (CRTDLL.030)
*
* Is a character valid as the first letter in a C identifier (a-Z,_).
*
* PARAMS
* c [in] Character to check
*
* RETURNS
* Non zero if c is valid as the first letter in a C identifier.
*/
INT __cdecl CRTDLL___iscsymf(UCHAR c)
{
return (c < 127 && (isalpha(c) || c == '_'));
}
/*********************************************************************
* _lfind (CRTDLL.170)
*
* Perform a linear search of an array for an element.
*/
LPVOID __cdecl CRTDLL__lfind(LPCVOID match, LPCVOID start, LPUINT array_size,
UINT elem_size, comp_func cf)
{
UINT size = *array_size;
if (size)
do
{
if (cf(match, start) == 0)
return (LPVOID)start; /* found */
start += elem_size;
} while (--size);
return NULL;
}
/*********************************************************************
* _loaddll (CRTDLL.171)
*
* Get a handle to a DLL in memory. The DLL is loaded if it is not already.
*
* PARAMS
* dll [in] Name of DLL to load.
*
* RETURNS
* Success: A handle to the loaded DLL.
*
* Failure: FIXME.
*/
INT __cdecl CRTDLL__loaddll(LPSTR dllname)
{
return LoadLibraryA(dllname);
}
/*********************************************************************
* _unloaddll (CRTDLL.313)
*
* Free reference to a DLL handle from loaddll().
*
* PARAMS
* dll [in] Handle to free.
*
* RETURNS
* Success: 0.
*
* Failure: Error number.
*/
INT __cdecl CRTDLL__unloaddll(HANDLE dll)
{
INT err;
if (FreeLibrary(dll))
return 0;
err = GetLastError();
__CRTDLL__set_errno(err);
return err;
}
/*********************************************************************
* _lsearch (CRTDLL.177)
*
* Linear search of an array of elements. Adds the item to the array if
* not found.
*
* PARAMS
* match [in] Pointer to element to match
* start [in] Pointer to start of search memory
* array_size [in] Length of search array (element count)
* elem_size [in] Size of each element in memory
* cf [in] Pointer to comparison function (like qsort()).
*
* RETURNS
* Pointer to the location where element was found or added.
*/
LPVOID __cdecl CRTDLL__lsearch(LPVOID match,LPVOID start, LPUINT array_size,
UINT elem_size, comp_func cf)
{
UINT 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;
}
/*********************************************************************
* _itow (CRTDLL.164)
*
* Convert an integer to a wide char string.
*/
extern LPSTR __cdecl _itoa( long , LPSTR , INT); /* ntdll */
/********************************************************************/
WCHAR* __cdecl CRTDLL__itow(INT value,WCHAR* out,INT base)
{
char buff[64]; /* FIXME: Whats the maximum buffer size for INT_MAX? */
_itoa(value, buff, base);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
return out;
}
/*********************************************************************
* _ltow (CRTDLL.??)
*
* Convert a long to a wide char string.
*/
extern LPSTR __cdecl _ltoa( long , LPSTR , INT); /* ntdll */
/********************************************************************/
WCHAR* __cdecl CRTDLL__ltow(LONG value,WCHAR* out,INT base)
{
char buff[64]; /* FIXME: Whats the maximum buffer size for LONG_MAX? */
_ltoa(value, buff, base);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
return out;
}
/*********************************************************************
* _ultow (CRTDLL.??)
*
* Convert an unsigned long to a wide char string.
*/
extern LPSTR __cdecl _ultoa( long , LPSTR , INT); /* ntdll */
/********************************************************************/
WCHAR* __cdecl CRTDLL__ultow(ULONG value,WCHAR* out,INT base)
{
char buff[64]; /* FIXME: Whats the maximum buffer size for ULONG_MAX? */
_ultoa(value, buff, base);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buff, -1, out, 64);
return out;
}
/*********************************************************************
* _toupper (CRTDLL.489)
*/
CHAR __cdecl CRTDLL__toupper(CHAR c)
{
return toupper(c);
}
/*********************************************************************
* _tolower (CRTDLL.490)
*/
CHAR __cdecl CRTDLL__tolower(CHAR c)
{
return tolower(c);
}
/* FP functions */
/*********************************************************************
* _cabs (CRTDLL.048)
*
* Return the absolue value of a complex number.
*
* PARAMS
* c [in] Structure containing real and imaginary parts of complex number.
*
* RETURNS
* Absolute value of complex number (always a positive real number).
*/
double __cdecl CRTDLL__cabs(struct complex c)
{
return sqrt(c.real * c.real + c.imaginary * c.imaginary);
}
/*********************************************************************
* _chgsign (CRTDLL.053)
*
* Change the sign of an IEEE double.
*
* PARAMS
* d [in] Number to invert.
*
* RETURNS
* Number with sign inverted.
*/
double __cdecl CRTDLL__chgsign(double d)
{
/* FIXME: +-infinity,Nan not tested */
return -d;
}
/*********************************************************************
* _control87 (CRTDLL.060)
*
* X86 implementation of _controlfp.
*
*/
UINT __cdecl CRTDLL__control87(UINT newVal, UINT mask)
{
#if defined(__GNUC__) && defined(__i386__)
UINT fpword, flags = 0;
/* Get fp control word */
__asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
/* Convert into mask constants */
if (fpword & 0x1) flags |= _EM_INVALID;
if (fpword & 0x2) flags |= _EM_DENORMAL;
if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
if (fpword & 0x8) flags |= _EM_OVERFLOW;
if (fpword & 0x10) flags |= _EM_UNDERFLOW;
if (fpword & 0x20) flags |= _EM_INEXACT;
switch(fpword & 0xC00) {
case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
case 0x800: flags |= _RC_UP; break;
case 0x400: flags |= _RC_DOWN; break;
}
switch(fpword & 0x300) {
case 0x0: flags |= _PC_24; break;
case 0x200: flags |= _PC_53; break;
case 0x300: flags |= _PC_64; break;
}
if (fpword & 0x1000) flags |= _IC_AFFINE;
/* Mask with parameters */
flags = (flags & ~mask) | (newVal & mask);
/* Convert (masked) value back to fp word */
fpword = 0;
if (flags & _EM_INVALID) fpword |= 0x1;
if (flags & _EM_DENORMAL) fpword |= 0x2;
if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
if (flags & _EM_OVERFLOW) fpword |= 0x8;
if (flags & _EM_UNDERFLOW) fpword |= 0x10;
if (flags & _EM_INEXACT) fpword |= 0x20;
switch(flags & (_RC_UP | _RC_DOWN)) {
case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
case _RC_UP: fpword |= 0x800; break;
case _RC_DOWN: fpword |= 0x400; break;
}
switch (flags & (_PC_24 | _PC_53)) {
case _PC_64: fpword |= 0x300; break;
case _PC_53: fpword |= 0x200; break;
case _PC_24: fpword |= 0x0; break;
}
if (!(flags & _IC_AFFINE)) fpword |= 0x1000;
/* Put fp control word */
__asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
return fpword;
#else
return CRTDLL__controlfp( newVal, mask );
#endif
}
/*********************************************************************
* _controlfp (CRTDLL.061)
*
* Set the state of the floating point unit.
*/
UINT __cdecl CRTDLL__controlfp( UINT newVal, UINT mask)
{
#if defined(__GNUC__) && defined(__i386__)
return CRTDLL__control87( newVal, mask );
#else
FIXME(":Not Implemented!\n");
return 0;
#endif
}
/*********************************************************************
* _copysign (CRTDLL.062)
*
* Return the number x with the sign of y.
*/
double __cdecl CRTDLL__copysign(double x, double y)
{
/* FIXME: Behaviour for Nan/Inf etc? */
if (y < 0.0)
return x < 0.0 ? x : -x;
return x < 0.0 ? -x : x;
}
/*********************************************************************
* _finite (CRTDLL.101)
*
* Determine if an IEEE double is finite (i.e. not +/- Infinity).
*
* PARAMS
* d [in] Number to check.
*
* RETURNS
* Non zero if number is finite.
*/
INT __cdecl CRTDLL__finite(double d)
{
return (finite(d)?1:0); /* See comment for CRTDLL__isnan() */
}
/*********************************************************************
* _fpreset (CRTDLL.107)
*
* Reset the state of the floating point processor.
*/
VOID __cdecl CRTDLL__fpreset(void)
{
#if defined(__GNUC__) && defined(__i386__)
__asm__ __volatile__( "fninit" );
#else
FIXME(":Not Implemented!\n");
#endif
}
/*********************************************************************
* _isnan (CRTDLL.164)
*
* Determine if an IEEE double is unrepresentable (NaN).
*
* PARAMS
* d [in] Number to check.
*
* RETURNS
* Non zero if number is NaN.
*/
INT __cdecl CRTDLL__isnan(double d)
{
/* some implementations return -1 for true(glibc), crtdll returns 1.
* Do the same, as the result may be used in calculations.
*/
return isnan(d)?1:0;
}
/*********************************************************************
* _purecall (CRTDLL.249)
*
* Abort program after pure virtual function call.
*/
VOID __cdecl CRTDLL__purecall(VOID)
{
CRTDLL__amsg_exit( 25 );
}
/*********************************************************************
* div (CRTDLL.358)
*
* Return the quotient and remainder of long integer division.
*
* VERSION
* [i386] Windows binary compatible - returns the struct in eax/edx.
*/
#ifdef __i386__
LONGLONG __cdecl CRTDLL_div(INT x, INT y)
{
LONGLONG retVal;
div_t dt = div(x,y);
retVal = ((LONGLONG)dt.rem << 32) | dt.quot;
return retVal;
}
#endif /* !defined(__i386__) */
/*********************************************************************
* div (CRTDLL.358)
*
* Return the quotient and remainder of long integer division.
*
* VERSION
* [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
*/
#ifndef __i386__
div_t __cdecl CRTDLL_div(INT x, INT y)
{
return div(x,y);
}
#endif /* !defined(__i386__) */
/*********************************************************************
* ldiv (CRTDLL.249)
*
* Return the quotient and remainder of long integer division.
* VERSION
* [i386] Windows binary compatible - returns the struct in eax/edx.
*/
#ifdef __i386__
ULONGLONG __cdecl CRTDLL_ldiv(LONG x, LONG y)
{
ULONGLONG retVal;
ldiv_t ldt = ldiv(x,y);
retVal = ((ULONGLONG)ldt.rem << 32) | (ULONG)ldt.quot;
return retVal;
}
#endif /* defined(__i386__) */
/*********************************************************************
* ldiv (CRTDLL.249)
*
* Return the quotient and remainder of long integer division.
*
* VERSION
* [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
*/
#ifndef __i386__
ldiv_t __cdecl CRTDLL_ldiv(LONG x, LONG y)
{
return ldiv(x,y);
}
#endif /* !defined(__i386__) */
/*********************************************************************
* _y0 (CRTDLL.332)
*
*/
double __cdecl CRTDLL__y0(double x)
{
double retVal;
if (!finite(x)) CRTDLL_errno = EDOM;
retVal = y0(x);
if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
{
CRTDLL_errno = EDOM;
retVal = sqrt(-1);
}
return retVal;
}
/*********************************************************************
* _y1 (CRTDLL.333)
*
*/
double __cdecl CRTDLL__y1(double x)
{
double retVal;
if (!finite(x)) CRTDLL_errno = EDOM;
retVal = y1(x);
if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
{
CRTDLL_errno = EDOM;
retVal = sqrt(-1);
}
return retVal;
}
/*********************************************************************
* _yn (CRTDLL.334)
*
*/
double __cdecl CRTDLL__yn(INT x, double y)
{
double retVal;
if (!finite(y)) CRTDLL_errno = EDOM;
retVal = yn(x,y);
if (CRTDLL__fpclass(retVal) == _FPCLASS_NINF)
{
CRTDLL_errno = EDOM;
retVal = sqrt(-1);
}
return retVal;
}
/*********************************************************************
* _nextafter (CRTDLL.235)
*
*/
double __cdecl CRTDLL__nextafter(double x, double y)
{
double retVal;
if (!finite(x) || !finite(y)) CRTDLL_errno = EDOM;
retVal = nextafter(x,y);
return retVal;
}
/*********************************************************************
* _searchenv (CRTDLL.260)
*
* Search CWD and each directory of an environment variable for
* location of a file.
*/
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff)
{
LPSTR envVal, penv;
char curPath[MAX_PATH];
*buff = '\0';
/* Try CWD first */
if (GetFileAttributesA( file ) != 0xFFFFFFFF)
{
GetFullPathNameA( file, MAX_PATH, buff, NULL );
/* Sigh. This error is *always* set, regardless of sucess */
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
/* Search given environment variable */
envVal = CRTDLL_getenv(env);
if (!envVal)
{
__CRTDLL__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)
{
__CRTDLL__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(buff, curPath);
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return; /* Found */
}
penv = *end ? end + 1 : end;
} while(1);
}
/*
* CRTDLL drive/directory functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
*
* Implementation Notes:
* MT Safe.
*/
#include "crtdll.h"
#include <errno.h>
#include "ntddk.h"
#include <time.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
{
DWORD dw;
/* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
* attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
*/
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);
}
/*********************************************************************
* _chdir (CRTDLL.51)
*
* Change the current directory.
*
* PARAMS
* newdir [in] Directory to change to
*
* RETURNS
* Sucess: 0
*
* Failure: -1
*/
INT __cdecl CRTDLL__chdir(LPCSTR newdir)
{
if (!SetCurrentDirectoryA(newdir))
{
__CRTDLL__set_errno(newdir?GetLastError():0);
return -1;
}
return 0;
}
/*********************************************************************
* _chdrive (CRTDLL.52)
*
* Change the current drive.
*
* PARAMS
* newdrive [in] new drive to change to, A: =1, B: =2, etc
*
* RETURNS
* Sucess: 0
*
* Failure: 1
*/
BOOL __cdecl CRTDLL__chdrive(INT newdrive)
{
char buffer[3] = "A:";
buffer[0] += newdrive - 1;
if (!SetCurrentDirectoryA( buffer ))
{
__CRTDLL__set_errno(GetLastError());
if (newdrive <= 0)
CRTDLL_errno = EACCES;
return -1;
}
return 0;
}
/*********************************************************************
* _findclose (CRTDLL.098)
*
* Free the resources from a search handle created from _findfirst.
*
* PARAMS
* hand [in]: Search handle to close
*
* RETURNS
* Success: 0
*
* Failure: -1
*/
INT __cdecl CRTDLL__findclose(DWORD hand)
{
TRACE(":handle %ld\n",hand);
if (!FindClose((HANDLE)hand))
{
__CRTDLL__set_errno(GetLastError());
return -1;
}
return 0;
}
/*********************************************************************
* _findfirst (CRTDLL.099)
*
* Create and return a search handle for iterating through a file and
* directory list.
*
* PARAMS
* fspec [in] File specification string for search, e.g "C:\*.BAT"
*
* ft [out] A pointer to a find_t structure to populate.
*
* RETURNS
* Success: A handle for the search, suitable for passing to _findnext
* or _findclose. Populates the members of ft with the details
* of the first matching file.
*
* Failure: -1.
*/
DWORD __cdecl CRTDLL__findfirst(LPCSTR fspec, find_t* ft)
{
WIN32_FIND_DATAA find_data;
HANDLE hfind;
hfind = FindFirstFileA(fspec, &find_data);
if (hfind == INVALID_HANDLE_VALUE)
{
__CRTDLL__set_errno(GetLastError());
return -1;
}
__CRTDLL__fttofd(&find_data,ft);
TRACE(":got handle %d\n",hfind);
return hfind;
}
/*********************************************************************
* _findnext (CRTDLL.100)
*
* Return the next matching file/directory from a search hadle.
*
* PARAMS
* hand [in] Search handle from a pervious call to _findfirst
*
* ft [out] A pointer to a find_t structure to populate.
*
* RETURNS
* Success: 0. Populates the members of ft with the details
* of the first matching file
*
* Failure: -1
*/
INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft)
{
WIN32_FIND_DATAA find_data;
if (!FindNextFileA(hand, &find_data))
{
CRTDLL_errno = ENOENT;
return -1;
}
__CRTDLL__fttofd(&find_data,ft);
return 0;
}
/*********************************************************************
* _getcwd (CRTDLL.120)
*
* Get the current directory.
*
* PARAMS
* buf [out] A buffer to place the current directory name in
*
* size [in] The size of buf.
*
* RETURNS
* Success: buf, or if buf is NULL, an allocated buffer
*
* Failure: NULL
*/
CHAR* __cdecl CRTDLL__getcwd(LPSTR 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 */
TRACE(":returning '%s'\n", dir);
if (!buf)
{
if (size < 0)
return CRTDLL__strdup(dir);
return __CRTDLL__strndup(dir,size);
}
if (dir_len >= size)
{
CRTDLL_errno = ERANGE;
return NULL; /* buf too small */
}
strcpy(buf,dir);
return buf;
}
/*********************************************************************
* _getdcwd (CRTDLL.121)
*
* Get the current directory on a drive. A: =1, B: =2, etc.
* Passing drive 0 means the current drive.
*/
CHAR* __cdecl CRTDLL__getdcwd(INT drive, LPSTR buf, INT size)
{
static CHAR* dummy;
TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
if (!drive || drive == CRTDLL__getdrive())
return CRTDLL__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)
{
CRTDLL_errno = EACCES;
return NULL;
}
dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
if (dir_len >= size || dir_len < 1)
{
CRTDLL_errno = ERANGE;
return NULL; /* buf too small */
}
TRACE(":returning '%s'\n", dir);
if (!buf)
return CRTDLL__strdup(dir); /* allocate */
strcpy(buf,dir);
}
return buf;
}
/*********************************************************************
* _getdiskfree (CRTDLL.122)
*
* Get free disk space on given drive or the current drive.
*
*/
UINT __cdecl CRTDLL__getdiskfree(UINT disk, diskfree_t* d)
{
char drivespec[4] = {'@', ':', '\\', 0};
DWORD ret[4];
UINT err;
if (disk > 26)
return ERROR_INVALID_PARAMETER; /* CRTDLL 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();
__CRTDLL__set_errno(err);
return err;
}
/*********************************************************************
* _getdrive (CRTDLL.124)
*
* Return current drive, A: =1, B: =2, etc
*/
INT __cdecl CRTDLL__getdrive(VOID)
{
char buffer[MAX_PATH];
if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
if (buffer[1] != ':') return 0;
return toupper(buffer[0]) - 'A' + 1;
}
/*********************************************************************
* _mkdir (CRTDLL.234)
*
* Create a directory.
*/
INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
{
if (CreateDirectoryA(newdir,NULL))
return 0;
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _rmdir (CRTDLL.255)
*
* Delete a directory
*
*/
INT __cdecl CRTDLL__rmdir(LPSTR dir)
{
if (RemoveDirectoryA(dir))
return 0;
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*
* CRTDLL exit/abort/atexit functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* exit functions differ in whether they perform cleanup
* and whether they return to the caller (really!).
* return do
* Name to caller? cleanup?
* _c_exit Y N
* _cexit Y Y
* _exit N N
* exit N Y
*
* Implementation Notes:
* Not MT Safe - Adding/Executing exit() functions should be locked
* for MT safety.
*
* FIXME:
* Need a better way of printing errors for GUI programs(MsgBox?).
* Is there really a difference between onexit/atexit?
*/
#include "crtdll.h"
#include <errno.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: Table of registered atexit() functions */
/* FIXME: This should be dynamically allocated */
#define CRTDLL_ATEXIT_TABLE_SIZE 16
static atexit_function atexit_table[CRTDLL_ATEXIT_TABLE_SIZE];
static int atexit_registered = 0; /* Points to free slot */
/* INTERNAL: call atexit functions */
void __CRTDLL__call_atexit(VOID);
void __CRTDLL__call_atexit(VOID)
{
/* Last registered gets executed first */
while (atexit_registered > 0)
{
atexit_registered--;
TRACE(":call function (%p)\n",atexit_table[atexit_registered]);
(*atexit_table[atexit_registered])();
}
}
/*********************************************************************
* __dllonexit (CRTDLL.25)
*/
VOID __cdecl CRTDLL___dllonexit ()
{
FIXME("stub\n");
}
/*********************************************************************
* _abnormal_termination (CRTDLL.36)
*
* Check if execution is processing during an exception.
*/
INT __cdecl CRTDLL__abnormal_termination(VOID)
{
TRACE("(void)\n");
return 0; /* FIME: Can we determine if we are in an exception? */
}
/*********************************************************************
* _amsg_exit (CRTDLL.040)
*
* Print an error message and terminate execution. Returns 255 to the
* host OS.
*/
VOID __cdecl CRTDLL__amsg_exit(INT err)
{
/* FIXME: Should be a popup for msvcrt gui executables, and should have
* text for the error number.
*/
CRTDLL_fprintf(CRTDLL_stderr,"\nruntime error R60%d\n",err);
CRTDLL__exit(255);
}
/*********************************************************************
* _assert (CRTDLL.041)
*
* Print an assertion message and call abort(). Really only present
* for win binaries. Winelib programs would typically use libc's
* version.
*/
VOID __cdecl CRTDLL__assert(LPVOID str, LPVOID file, UINT line)
{
CRTDLL_fprintf(CRTDLL_stderr,"Assertion failed: %s, file %s, line %d\n\n",
(char*)str,(char*)file, line);
CRTDLL_abort();
}
/*********************************************************************
* _c_exit (CRTDLL.047)
*/
VOID __cdecl CRTDLL__c_exit(VOID)
{
/* All cleanup is done on DLL detach; Return to caller */
}
/*********************************************************************
* _cexit (CRTDLL.049)
*/
VOID __cdecl CRTDLL__cexit(VOID)
{
/* All cleanup is done on DLL detach; Return to caller */
}
/*********************************************************************
* _exit (CRTDLL.087)
*/
VOID __cdecl CRTDLL__exit(LONG ret)
{
TRACE(":exit code %ld\n",ret);
CRTDLL__c_exit();
ExitProcess(ret);
}
/*********************************************************************
* _onexit (CRTDLL.236)
*
* Register a function to be called when the process terminates.
*/
atexit_function __cdecl CRTDLL__onexit( atexit_function func)
{
TRACE("registering function (%p)\n",func);
if (func && atexit_registered <= CRTDLL_ATEXIT_TABLE_SIZE - 1)
{
atexit_table[atexit_registered] = (atexit_function)func;
atexit_registered++;
return func; /* successful */
}
ERR(":Too many onexit() functions, or NULL function - not registered!\n");
return NULL;
}
/*********************************************************************
* exit (CRTDLL.359)
*/
void __cdecl CRTDLL_exit(DWORD ret)
{
TRACE(":exit code %ld\n",ret);
__CRTDLL__call_atexit();
CRTDLL__cexit();
ExitProcess(ret);
}
/*********************************************************************
* abort (CRTDLL.335)
*
* Terminate the progam with an abnormal termination message. Returns
* 3 to the host OS.
*/
VOID __cdecl CRTDLL_abort()
{
CRTDLL_fprintf(CRTDLL_stderr,"\nabnormal program termination\n");
CRTDLL__exit(3);
}
/*********************************************************************
* atexit (CRTDLL.345)
*
* Register a function to be called when the process terminates.
*/
INT __cdecl CRTDLL_atexit( atexit_function func)
{
return CRTDLL__onexit(func) == func ? 0 : -1;
}
/*
* CRTDLL file functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* Implementation Notes:
* Mapping is performed between FILE*, fd and HANDLE's. This allows us to
* implement all calls using the Win32 API, support remapping fd's to
* FILES and do some other tricks as well (like closeall, _get_osfhandle).
* For mix and matching with the host libc, processes can use the Win32 HANDLE
* to get a real unix fd from the wineserver. Or we could do this once
* on create, and provide a function to return it quickly (store it
* in the mapping table). Note that If you actuall _do_ this, you should
* call rewind() before using any other crt functions on the file. To avoid
* the confusion I got when reading the API docs, fd is always refered
* to as a file descriptor here. In the API docs its called a file handle
* which is confusing with Win32 HANDLES.
* M$ CRT includes inline versions of some of these functions (like feof()).
* These inlines check/modify bitfields in the FILE structure, so we set
* _flags/_file/_cnt in the FILE* to be binary compatible with the win dll.
* lcc defines _IOAPPEND as one of the flags for a FILE*, but testing shows
* that M$ CRT never sets it. So we keep the flag in our mapping table but
* mask it out when we populate a FILE* with it. Then when we write we seek
* to EOF if _IOAPPEND is set for the underlying fd.
*
* FIXME:
* Not MT safe. Need locking around file access and allocation for this.
* NT has no effective limit on files - neither should we. This will be fixed
* with dynamic allocation of the file mapping array.
* Buffering is handled differently. Have to investigate a) how much control
* we have over buffering in win32, and b) if we care ;-)
*/
#include "crtdll.h"
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "ntddk.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
/* FIXME: Make this dynamic */
#define CRTDLL_MAX_FILES 257
HANDLE __CRTDLL_handles[CRTDLL_MAX_FILES];
CRTDLL_FILE* __CRTDLL_files[CRTDLL_MAX_FILES];
INT __CRTDLL_flags[CRTDLL_MAX_FILES];
LPSTR __CRTDLL_tempfiles[CRTDLL_MAX_FILES];
CRTDLL_FILE __CRTDLL_iob[3];
static int __CRTDLL_fdstart = 3; /* first unallocated fd */
static int __CRTDLL_fdend = 3; /* highest allocated fd */
/* INTERNAL: process umask */
static INT __CRTDLL_umask = 0;
/* INTERNAL: Static buffer for temp file name */
static char CRTDLL_tmpname[MAX_PATH];
/* file extentions recognised as executables */
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';
/* for stat mode, permissions apply to all,owner and group */
#define CRTDLL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
#define CRTDLL_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
#define CRTDLL_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
/* INTERNAL: Get the HANDLE for a fd */
static HANDLE __CRTDLL__fdtoh(INT fd);
static HANDLE __CRTDLL__fdtoh(INT fd)
{
if (fd < 0 || fd >= __CRTDLL_fdend ||
__CRTDLL_handles[fd] == INVALID_HANDLE_VALUE)
{
WARN(":fd (%d) - no handle!\n",fd);
CRTDLL_doserrno = 0;
CRTDLL_errno = EBADF;
return INVALID_HANDLE_VALUE;
}
return __CRTDLL_handles[fd];
}
/* INTERNAL: free a file entry fd */
static void __CRTDLL__free_fd(INT fd);
static void __CRTDLL__free_fd(INT fd)
{
__CRTDLL_handles[fd] = INVALID_HANDLE_VALUE;
__CRTDLL_files[fd] = 0;
__CRTDLL_flags[fd] = 0;
TRACE(":fd (%d) freed\n",fd);
if (fd < 3)
return; /* dont use 0,1,2 for user files */
if (fd == __CRTDLL_fdend - 1)
__CRTDLL_fdend--;
if (fd < __CRTDLL_fdstart)
__CRTDLL_fdstart = fd;
}
/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
static INT __CRTDLL__alloc_fd(HANDLE hand, INT flag);
static INT __CRTDLL__alloc_fd(HANDLE hand, INT flag)
{
INT fd = __CRTDLL_fdstart;
TRACE(":handle (%d) allocating fd (%d)\n",hand,fd);
if (fd >= CRTDLL_MAX_FILES)
{
WARN(":files exhausted!\n");
return -1;
}
__CRTDLL_handles[fd] = hand;
__CRTDLL_flags[fd] = flag;
/* locate next free slot */
if (fd == __CRTDLL_fdend)
__CRTDLL_fdstart = ++__CRTDLL_fdend;
else
while(__CRTDLL_fdstart < __CRTDLL_fdend &&
__CRTDLL_handles[__CRTDLL_fdstart] != INVALID_HANDLE_VALUE)
__CRTDLL_fdstart++;
return fd;
}
/* INTERNAL: Allocate a FILE* for an fd slot
* This is done lazily to avoid memory wastage for low level open/write
* usage when a FILE* is not requested (but may be later).
*/
static CRTDLL_FILE* __CRTDLL__alloc_fp(INT fd);
static CRTDLL_FILE* __CRTDLL__alloc_fp(INT fd)
{
TRACE(":fd (%d) allocating FILE*\n",fd);
if (fd < 0 || fd >= __CRTDLL_fdend ||
__CRTDLL_handles[fd] == INVALID_HANDLE_VALUE)
{
WARN(":invalid fd %d\n",fd);
CRTDLL_doserrno = 0;
CRTDLL_errno = EBADF;
return NULL;
}
if (!__CRTDLL_files[fd])
{
if ((__CRTDLL_files[fd] = CRTDLL_calloc(sizeof(CRTDLL_FILE),1)))
{
__CRTDLL_files[fd]->_file = fd;
__CRTDLL_files[fd]->_flag = __CRTDLL_flags[fd];
__CRTDLL_files[fd]->_flag &= ~_IOAPPEND; /* mask out, see above */
}
}
TRACE(":got FILE* (%p)\n",__CRTDLL_files[fd]);
return __CRTDLL_files[fd];
}
/* INTERNAL: Set up stdin, stderr and stdout */
VOID __CRTDLL__init_io(VOID)
{
int i;
memset(__CRTDLL_iob,0,3*sizeof(CRTDLL_FILE));
__CRTDLL_handles[0] = GetStdHandle(STD_INPUT_HANDLE);
__CRTDLL_flags[0] = __CRTDLL_iob[0]._flag = _IOREAD;
__CRTDLL_handles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
__CRTDLL_flags[1] = __CRTDLL_iob[1]._flag = _IOWRT;
__CRTDLL_handles[2] = GetStdHandle(STD_ERROR_HANDLE);
__CRTDLL_flags[2] = __CRTDLL_iob[2]._flag = _IOWRT;
TRACE(":handles (%d)(%d)(%d)\n",__CRTDLL_handles[0],
__CRTDLL_handles[1],__CRTDLL_handles[2]);
for (i = 0; i < 3; i++)
{
/* FILE structs for stdin/out/err are static and never deleted */
__CRTDLL_files[i] = &__CRTDLL_iob[i];
__CRTDLL_iob[i]._file = i;
__CRTDLL_tempfiles[i] = NULL;
}
}
/*********************************************************************
* _access (CRTDLL.37)
*/
INT __cdecl CRTDLL__access(LPCSTR filename, INT mode)
{
DWORD attr = GetFileAttributesA(filename);
if (attr == 0xffffffff)
{
if (!filename)
{
/* FIXME: Should GetFileAttributesA() return this? */
__CRTDLL__set_errno(ERROR_INVALID_DATA);
return -1;
}
__CRTDLL__set_errno(GetLastError());
return -1;
}
if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
{
__CRTDLL__set_errno(ERROR_ACCESS_DENIED);
return -1;
}
TRACE(":file %s, mode (%d) ok\n",filename,mode);
return 0;
}
/*********************************************************************
* _chmod (CRTDLL.054)
*
* Change a files permissions.
*/
INT __cdecl CRTDLL__chmod(LPCSTR path, INT flags)
{
DWORD oldFlags = GetFileAttributesA(path);
if (oldFlags != 0x0FFFFFFFF)
{
DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
oldFlags | FILE_ATTRIBUTE_READONLY;
if (newFlags == oldFlags || SetFileAttributesA( path, newFlags ))
return 0;
}
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _close (CRTDLL.57)
*
* Close an open file descriptor.
*/
INT __cdecl CRTDLL__close(INT fd)
{
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return -1;
/* Dont free std FILE*'s, they are not dynamic */
if (fd > 2 && __CRTDLL_files[fd])
CRTDLL_free(__CRTDLL_files[fd]);
__CRTDLL__free_fd(fd);
if (!CloseHandle(hand))
{
WARN(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
if (__CRTDLL_tempfiles[fd])
{
TRACE("deleting temporary file '%s'\n",__CRTDLL_tempfiles[fd]);
CRTDLL__unlink(__CRTDLL_tempfiles[fd]);
CRTDLL_free(__CRTDLL_tempfiles[fd]);
__CRTDLL_tempfiles[fd] = NULL;
}
TRACE(":ok\n");
return 0;
}
/*********************************************************************
* _commit (CRTDLL.58)
*
* Ensure all file operations have been flushed to the drive.
*/
INT __cdecl CRTDLL__commit(INT fd)
{
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return -1;
if (!FlushFileBuffers(hand))
{
if (GetLastError() == ERROR_INVALID_HANDLE)
{
/* FlushFileBuffers fails for console handles
* so we ignore this error.
*/
return 0;
}
TRACE(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
TRACE(":ok\n");
return 0;
}
/*********************************************************************
* _creat (CRTDLL.066)
*
* Open a file, creating it if it is not present.
*/
INT __cdecl CRTDLL__creat(LPCSTR path, INT flags)
{
INT usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
return CRTDLL__open(path, usedFlags);
}
/*********************************************************************
* _eof (CRTDLL.076)
*
* Determine if the file pointer is at the end of a file.
*
* FIXME
* Care for large files
*/
INT __cdecl CRTDLL__eof( INT fd )
{
DWORD curpos,endpos;
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return -1;
/* If we have a FILE* for this file, the EOF flag
* will be set by the read()/write() functions.
*/
if (__CRTDLL_files[fd])
return __CRTDLL_files[fd]->_flag & _IOEOF;
/* Otherwise we do it the hard way */
curpos = SetFilePointer( hand, 0, NULL, SEEK_CUR );
endpos = SetFilePointer( hand, 0, NULL, FILE_END );
if (curpos == endpos)
return TRUE;
SetFilePointer( hand, curpos, 0, FILE_BEGIN);
return FALSE;
}
/*********************************************************************
* _fcloseall (CRTDLL.089)
*
* Close all open files except stdin/stdout/stderr.
*/
INT __cdecl CRTDLL__fcloseall(VOID)
{
int num_closed = 0, i;
for (i = 3; i < __CRTDLL_fdend; i++)
if (__CRTDLL_handles[i] != INVALID_HANDLE_VALUE)
{
CRTDLL__close(i);
num_closed++;
}
if (num_closed)
TRACE(":closed (%d) handles\n",num_closed);
return num_closed;
}
/*********************************************************************
* _fdopen (CRTDLL.091)
*
* Get a FILE* from a low level file descriptor.
*/
CRTDLL_FILE* __cdecl CRTDLL__fdopen(INT fd, LPCSTR mode)
{
CRTDLL_FILE* file = __CRTDLL__alloc_fp(fd);
TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd,mode,file);
if (file)
CRTDLL_rewind(file);
return file;
}
/*********************************************************************
* _fgetwchar (CRTDLL.062)
*
* Read a wide character from stdin.
*/
WCHAR __cdecl CRTDLL__fgetwchar( VOID )
{
return CRTDLL_fgetwc(CRTDLL_stdin);
}
/*********************************************************************
* _fgetchar (CRTDLL.092)
*
* Read a character from stdin.
*/
INT __cdecl CRTDLL__fgetchar( VOID )
{
return CRTDLL_fgetc(CRTDLL_stdin);
}
/*********************************************************************
* _filbuf (CRTDLL.094)
*
* NOTES
* The macro version of getc calls this function whenever FILE->_cnt
* becomes negative. We ensure that _cnt is always 0 after any read
* so this function is always called. Our implementation simply calls
* fgetc as all the underlying buffering is handled by Wines
* implementation of the Win32 file I/O calls.
*/
INT __cdecl CRTDLL__filbuf(CRTDLL_FILE* file)
{
return CRTDLL_fgetc(file);
}
/*********************************************************************
* _filelength (CRTDLL.097)
*
* Get the length of an open file.
*/
LONG __cdecl CRTDLL__filelength(INT fd)
{
LONG curPos = CRTDLL__lseek(fd, 0, SEEK_CUR);
if (curPos != -1)
{
LONG endPos = CRTDLL__lseek(fd, 0, SEEK_END);
if (endPos != -1)
{
if (endPos != curPos)
CRTDLL__lseek(fd, curPos, SEEK_SET);
return endPos;
}
}
return -1;
}
/*********************************************************************
* _fileno (CRTDLL.097)
*
* Get the file descriptor from a FILE*.
*
* NOTES
* This returns the CRTDLL fd, _not_ the underlying *nix fd.
*/
INT __cdecl CRTDLL__fileno(CRTDLL_FILE* file)
{
TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
return file->_file;
}
/*********************************************************************
* _flsbuf (CRTDLL.102)
*
* NOTES
* The macro version of putc calls this function whenever FILE->_cnt
* becomes negative. We ensure that _cnt is always 0 after any write
* so this function is always called. Our implementation simply calls
* fputc as all the underlying buffering is handled by Wines
* implementation of the Win32 file I/O calls.
*/
INT __cdecl CRTDLL__flsbuf(INT c, CRTDLL_FILE* file)
{
return CRTDLL_fputc(c,file);
}
/*********************************************************************
* _flushall (CRTDLL.103)
*
* Flush all open files.
*/
INT __cdecl CRTDLL__flushall(VOID)
{
int num_flushed = 0, i = 3;
while(i < __CRTDLL_fdend)
if (__CRTDLL_handles[i] != INVALID_HANDLE_VALUE)
{
if (CRTDLL__commit(i) == -1)
if (__CRTDLL_files[i])
__CRTDLL_files[i]->_flag |= _IOERR;
num_flushed++;
}
TRACE(":flushed (%d) handles\n",num_flushed);
return num_flushed;
}
/*********************************************************************
* _fputchar (CRTDLL.108)
*
* Put a character to a file.
*/
INT __cdecl CRTDLL__fputchar(INT c)
{
return CRTDLL_fputc(c, CRTDLL_stdout);
}
/*********************************************************************
* _fputwchar (CRTDLL.109)
*
* Put a wide character to stdout.
*/
WCHAR __cdecl CRTDLL__fputwchar( WCHAR wc )
{
return CRTDLL_fputwc(wc, CRTDLL_stdout);
}
/*********************************************************************
* _fsopen (CRTDLL.110)
*
* Open a FILE* with sharing.
*/
CRTDLL_FILE* __cdecl CRTDLL__fsopen(LPCSTR path, LPCSTR mode, INT share)
{
FIXME(":(%s,%s,%d),ignoring share mode!\n",path,mode,share);
return CRTDLL_fopen(path,mode);
}
/*********************************************************************
* _fstat (CRTDLL.111)
*
* Get information about an open file.
*/
int __cdecl CRTDLL__fstat(int fd, struct _stat* buf)
{
DWORD dw;
BY_HANDLE_FILE_INFORMATION hfi;
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) stat (%p)\n",fd,buf);
if (hand == INVALID_HANDLE_VALUE)
return -1;
if (!buf)
{
WARN(":failed-NULL buf\n");
__CRTDLL__set_errno(ERROR_INVALID_PARAMETER);
return -1;
}
memset(&hfi, 0, sizeof(hfi));
memset(buf, 0, sizeof(struct _stat));
if (!GetFileInformationByHandle(hand, &hfi))
{
WARN(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(ERROR_INVALID_PARAMETER);
return -1;
}
FIXME(":dwFileAttributes = %d, mode set to 0",hfi.dwFileAttributes);
buf->st_nlink = hfi.nNumberOfLinks;
buf->st_size = hfi.nFileSizeLow;
RtlTimeToSecondsSince1970( &hfi.ftLastAccessTime, &dw );
buf->st_atime = dw;
RtlTimeToSecondsSince1970( &hfi.ftLastWriteTime, &dw );
buf->st_mtime = buf->st_ctime = dw;
return 0;
}
/*********************************************************************
* _futime (CRTDLL.115)
*
* Set the file access/modification times on an open file.
*/
INT __cdecl CRTDLL__futime(INT fd, struct _utimbuf *t)
{
HANDLE hand = __CRTDLL__fdtoh(fd);
FILETIME at, wt;
if (!t)
{
time_t currTime;
CRTDLL_time(&currTime);
RtlSecondsSince1970ToTime( currTime, &at );
memcpy( &wt, &at, sizeof(wt) );
}
else
{
RtlSecondsSince1970ToTime( t->actime, &at );
if (t->actime == t->modtime)
memcpy( &wt, &at, sizeof(wt) );
else
RtlSecondsSince1970ToTime( t->modtime, &wt );
}
if (!SetFileTime( hand, NULL, &at, &wt ))
{
__CRTDLL__set_errno(GetLastError());
return -1 ;
}
return 0;
}
/*********************************************************************
* _get_osfhandle (CRTDLL.117)
*
* Return a Win32 HANDLE from a file descriptor.
*
* PARAMS
* fd [in] A valid file descriptor
*
* RETURNS
* Success: A Win32 HANDLE
*
* Failure: INVALID_HANDLE_VALUE.
*
*/
HANDLE CRTDLL__get_osfhandle(INT fd)
{
HANDLE hand = __CRTDLL__fdtoh(fd);
HANDLE newhand = hand;
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand != INVALID_HANDLE_VALUE)
{
/* FIXME: I'm not convinced that I should be copying the
* handle here - it may be leaked if the app doesn't
* close it (and the API docs dont say that it should)
* Not duplicating it means that it can't be inherited
* and so lcc's wedit doesn't cope when it passes it to
* child processes. I've an idea that it should either
* be copied by CreateProcess, or marked as inheritable
* when initialised, or maybe both? JG 21-9-00.
*/
DuplicateHandle(GetCurrentProcess(),hand,GetCurrentProcess(),
&newhand,0,TRUE,DUPLICATE_SAME_ACCESS );
}
return newhand;
}
/*********************************************************************
* _getw (CRTDLL.128)
*
* Read an integter from a FILE*.
*/
INT __cdecl CRTDLL__getw( CRTDLL_FILE* file )
{
INT i;
if (CRTDLL__read(file->_file, &i, sizeof(INT)) != 1)
return CRTDLL_EOF;
return i;
}
/*********************************************************************
* _isatty (CRTDLL.137)
*
* Return non zero if fd is a character device (e.g console).
*/
INT __cdecl CRTDLL__isatty(INT fd)
{
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return 0;
return GetFileType(fd) == FILE_TYPE_CHAR? 1 : 0;
}
/*********************************************************************
* _lseek (CRTDLL.179)
*
* Move the file pointer within a file.
*/
LONG __cdecl CRTDLL__lseek( INT fd, LONG offset, INT whence)
{
DWORD ret;
HANDLE hand = __CRTDLL__fdtoh(fd);
TRACE(":fd (%d) handle (%d)\n",fd,hand);
if (hand == INVALID_HANDLE_VALUE)
return -1;
if (whence < 0 || whence > 2)
{
CRTDLL_errno = EINVAL;
return -1;
}
TRACE(":fd (%d) to 0x%08lx pos %s\n",
fd,offset,(whence==SEEK_SET)?"SEEK_SET":
(whence==SEEK_CUR)?"SEEK_CUR":
(whence==SEEK_END)?"SEEK_END":"UNKNOWN");
if ((ret = SetFilePointer( hand, offset, NULL, whence )) != 0xffffffff)
{
if ( __CRTDLL_files[fd])
__CRTDLL_files[fd]->_flag &= ~_IOEOF;
/* FIXME: What if we seek _to_ EOF - is EOF set? */
return ret;
}
TRACE(":error-last error (%ld)\n",GetLastError());
if ( __CRTDLL_files[fd])
switch(GetLastError())
{
case ERROR_NEGATIVE_SEEK:
case ERROR_SEEK_ON_DEVICE:
__CRTDLL__set_errno(GetLastError());
__CRTDLL_files[fd]->_flag |= _IOERR;
break;
default:
break;
}
return -1;
}
/*********************************************************************
* _mktemp (CRTDLL.239)
*
* Create a temporary file name.
*/
LPSTR __cdecl CRTDLL__mktemp(LPSTR pattern)
{
int numX = 0;
LPSTR retVal = pattern;
INT id;
char letter = 'a';
while(*pattern)
numX = (*pattern++ == 'X')? numX + 1 : 0;
if (numX < 5)
return NULL;
pattern--;
id = GetCurrentProcessId();
numX = 6;
while(numX--)
{
INT tempNum = id / 10;
*pattern-- = id - (tempNum * 10) + '0';
id = tempNum;
}
pattern++;
do
{
if (GetFileAttributesA( retVal ) == 0xFFFFFFFF &&
GetLastError() == ERROR_FILE_NOT_FOUND)
return retVal;
*pattern = letter++;
} while(letter != '|');
return NULL;
}
/*********************************************************************
* _open (CRTDLL.239)
* Open a file.
*/
INT __cdecl CRTDLL__open(LPCSTR path,INT flags)
{
DWORD access = 0, creation = 0;
INT ioflag = 0, fd;
HANDLE hand;
TRACE(":file (%s) mode 0x%04x\n",path,flags);
switch(flags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
{
case _O_RDONLY:
access |= GENERIC_READ;
ioflag |= _IOREAD;
break;
case _O_WRONLY:
access |= GENERIC_WRITE;
ioflag |= _IOWRT;
break;
case _O_RDWR:
access |= GENERIC_WRITE | GENERIC_READ;
ioflag |= _IORW;
break;
}
if (flags & _O_CREAT)
{
if (flags & _O_EXCL)
creation = CREATE_NEW;
else if (flags & _O_TRUNC)
creation = CREATE_ALWAYS;
else
creation = OPEN_ALWAYS;
}
else /* no _O_CREAT */
{
if (flags & _O_TRUNC)
creation = TRUNCATE_EXISTING;
else
creation = OPEN_EXISTING;
}
if (flags & _O_APPEND)
ioflag |= _IOAPPEND;
flags |= _O_BINARY; /* FIXME: Default to text */
if (flags & _O_TEXT)
{
/* Dont warn when writing */
if (ioflag & GENERIC_READ)
FIXME(":TEXT node not implemented\n");
flags &= ~_O_TEXT;
}
if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL
|_O_CREAT|_O_RDWR|_O_TEMPORARY))
TRACE(":unsupported flags 0x%04x\n",flags);
hand = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL, 0 );
if (hand == INVALID_HANDLE_VALUE)
{
WARN(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
fd = __CRTDLL__alloc_fd(hand, ioflag);
TRACE(":fd (%d) handle (%d)\n",fd, hand);
if (fd > 0)
{
if (flags & _O_TEMPORARY)
__CRTDLL_tempfiles[fd] = CRTDLL__strdup(path);
if (ioflag & _IOAPPEND)
CRTDLL__lseek(fd, 0, FILE_END );
}
return fd;
}
/*********************************************************************
* _open_osfhandle (CRTDLL.240)
*
* Create a file descriptor for a file HANDLE.
*/
INT __cdecl CRTDLL__open_osfhandle(HANDLE hand, INT flags)
{
INT fd = __CRTDLL__alloc_fd(hand,flags);
TRACE(":handle (%d) fd (%d)\n",hand,fd);
return fd;
}
/*********************************************************************
* _putw (CRTDLL.254)
*
* Write an int to a FILE*.
*/
INT __cdecl CRTDLL__putw(INT val, CRTDLL_FILE* file)
{
return CRTDLL__write(file->_file, &val, sizeof(val)) == 1? val : CRTDLL_EOF;
}
/*********************************************************************
* _rmtmp (CRTDLL.256)
*
* Remove all temporary files created by tmpfile().
*/
INT __cdecl CRTDLL__rmtmp(void)
{
int num_removed = 0, i;
for (i = 3; i < __CRTDLL_fdend; i++)
if (__CRTDLL_tempfiles[i])
{
CRTDLL__close(i);
num_removed++;
}
if (num_removed)
TRACE(":removed (%d) temp files\n",num_removed);
return num_removed;
}
/*********************************************************************
* _read (CRTDLL.256)
*
* Read data from a file.
*/
INT __cdecl CRTDLL__read(INT fd, LPVOID buf, UINT count)
{
DWORD num_read;
HANDLE hand = __CRTDLL__fdtoh(fd);
/* Dont trace small reads, it gets *very* annoying */
if (count > 4)
TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
if (hand == INVALID_HANDLE_VALUE)
return -1;
/* Set _cnt to 0 so optimised binaries will call our implementation
* of putc/getc. See _filbuf/_flsbuf comments.
*/
if (__CRTDLL_files[fd])
__CRTDLL_files[fd]->_cnt = 0;
if (ReadFile(hand, buf, count, &num_read, NULL))
{
if (num_read != count && __CRTDLL_files[fd])
{
TRACE(":EOF\n");
__CRTDLL_files[fd]->_flag |= _IOEOF;
}
return num_read;
}
TRACE(":failed-last error (%ld)\n",GetLastError());
if ( __CRTDLL_files[fd])
__CRTDLL_files[fd]->_flag |= _IOERR;
return -1;
}
/*********************************************************************
* _setmode (CRTDLL.265)
*
* FIXME: At present we ignore the request to translate CR/LF to LF.
*
* We always translate when we read with fgets, we never do with fread
*
*/
INT __cdecl CRTDLL__setmode(INT fd,INT mode)
{
if (mode & _O_TEXT)
FIXME("fd (%d) mode (%d) TEXT not implemented\n",fd,mode);
return 0;
}
/*********************************************************************
* _stat (CRTDLL.280)
*/
INT __cdecl CRTDLL__stat(const char* path, struct _stat * buf)
{
DWORD dw;
WIN32_FILE_ATTRIBUTE_DATA hfi;
unsigned short mode = CRTDLL_S_IREAD;
int plen;
TRACE(":file (%s) buf(%p)\n",path,buf);
if (!GetFileAttributesExA( path, GetFileExInfoStandard, &hfi ))
{
TRACE("failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return -1;
}
memset(buf,0,sizeof(struct _stat));
/* FIXME: rdev isnt drive num,despite what the docs say-what is it? */
if (isalpha(*path))
buf->st_dev = buf->st_rdev = toupper(*path - 'A'); /* drive num */
else
buf->st_dev = buf->st_rdev = CRTDLL__getdrive() - 1;
plen = strlen(path);
/* Dir, or regular file? */
if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
(path[plen-1] == '\\'))
mode |= (_S_IFDIR | CRTDLL_S_IEXEC);
else
{
mode |= _S_IFREG;
/* executable? */
if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
{
unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8)
| (tolower(path[plen-3]) << 16);
if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
mode |= CRTDLL_S_IEXEC;
}
}
if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
mode |= CRTDLL_S_IWRITE;
buf->st_mode = mode;
buf->st_nlink = 1;
buf->st_size = hfi.nFileSizeLow;
RtlTimeToSecondsSince1970( &hfi.ftLastAccessTime, &dw );
buf->st_atime = dw;
RtlTimeToSecondsSince1970( &hfi.ftLastWriteTime, &dw );
buf->st_mtime = buf->st_ctime = dw;
TRACE("\n%d %d %d %d %d %d\n", buf->st_mode,buf->st_nlink,buf->st_size,
buf->st_atime,buf->st_mtime, buf->st_ctime);
return 0;
}
/*********************************************************************
* _tell (CRTDLL.302)
*
* Get current file position.
*/
LONG __cdecl CRTDLL__tell(INT fd)
{
return CRTDLL__lseek(fd, 0, SEEK_CUR);
}
/*********************************************************************
* _tempnam (CRTDLL.305)
*
*/
LPSTR __cdecl CRTDLL__tempnam(LPCSTR dir, LPCSTR prefix)
{
char tmpbuf[MAX_PATH];
TRACE("dir (%s) prefix (%s)\n",dir,prefix);
if (GetTempFileNameA(dir,prefix,0,tmpbuf))
{
TRACE("got name (%s)\n",tmpbuf);
return CRTDLL__strdup(tmpbuf);
}
TRACE("failed-last error (%ld)\n",GetLastError());
return NULL;
}
/*********************************************************************
* _umask (CRTDLL.310)
*
* Set the process-wide umask.
*/
INT __cdecl CRTDLL__umask(INT umask)
{
INT old_umask = __CRTDLL_umask;
TRACE("umask (%d)\n",umask);
__CRTDLL_umask = umask;
return old_umask;
}
/*********************************************************************
* _utime (CRTDLL.314)
*
* Set the file access/modification times on a file.
*/
INT __cdecl CRTDLL__utime(LPCSTR path, struct _utimbuf *t)
{
INT fd = CRTDLL__open( path, _O_WRONLY | _O_BINARY );
if (fd > 0)
{
INT retVal = CRTDLL__futime(fd, t);
CRTDLL__close(fd);
return retVal;
}
return -1;
}
/*********************************************************************
* _unlink (CRTDLL.315)
*
* Delete a file.
*/
INT __cdecl CRTDLL__unlink(LPCSTR path)
{
TRACE("path (%s)\n",path);
if(DeleteFileA( path ))
return 0;
TRACE("failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* _write (CRTDLL.332)
*
* Write data to a file.
*/
UINT __cdecl CRTDLL__write(INT fd, LPCVOID buf, UINT count)
{
DWORD num_written;
HANDLE hand = __CRTDLL__fdtoh(fd);
/* Dont trace small writes, it gets *very* annoying */
if (count > 4)
TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
if (hand == INVALID_HANDLE_VALUE)
return -1;
/* If appending, go to EOF */
if (__CRTDLL_flags[fd] & _IOAPPEND)
CRTDLL__lseek(fd, 0, FILE_END );
/* Set _cnt to 0 so optimised binaries will call our implementation
* of putc/getc. See _filbuf/_flsbuf comments.
*/
if (__CRTDLL_files[fd])
__CRTDLL_files[fd]->_cnt = 0;
if (WriteFile(hand, buf, count, &num_written, NULL)
&& (num_written == count))
return num_written;
TRACE(":failed-last error (%ld)\n",GetLastError());
if ( __CRTDLL_files[fd])
__CRTDLL_files[fd]->_flag |= _IOERR;
return -1;
}
/*********************************************************************
* clearerr (CRTDLL.349)
*
* Clear a FILE's error indicator.
*/
VOID __cdecl CRTDLL_clearerr(CRTDLL_FILE* file)
{
TRACE(":file (%p) fd (%d)\n",file,file->_file);
file->_flag &= ~(_IOERR | _IOEOF);
}
/*********************************************************************
* fclose (CRTDLL.362)
*
* Close an open file.
*/
INT __cdecl CRTDLL_fclose( CRTDLL_FILE* file )
{
return CRTDLL__close(file->_file);
}
/*********************************************************************
* feof (CRTDLL.363)
*
* Check the eof indicator on a file.
*/
INT __cdecl CRTDLL_feof( CRTDLL_FILE* file )
{
return file->_flag & _IOEOF;
}
/*********************************************************************
* ferror (CRTDLL.361)
*
* Check the error indicator on a file.
*/
INT __cdecl CRTDLL_ferror( CRTDLL_FILE* file )
{
return file->_flag & _IOERR;
}
/*********************************************************************
* fflush (CRTDLL.362)
*/
INT __cdecl CRTDLL_fflush( CRTDLL_FILE* file )
{
return CRTDLL__commit(file->_file);
}
/*********************************************************************
* fgetc (CRTDLL.363)
*/
INT __cdecl CRTDLL_fgetc( CRTDLL_FILE* file )
{
char c;
if (CRTDLL__read(file->_file,&c,1) != 1)
return CRTDLL_EOF;
return c;
}
/*********************************************************************
* fgetpos (CRTDLL.364)
*/
INT __cdecl CRTDLL_fgetpos( CRTDLL_FILE* file, CRTDLL_fpos_t *pos)
{
*pos = CRTDLL__tell(file->_file);
return (*pos == -1? -1 : 0);
}
/*********************************************************************
* fgets (CRTDLL.365)
*/
CHAR* __cdecl CRTDLL_fgets(LPSTR s, INT size, CRTDLL_FILE* file)
{
int cc;
LPSTR buf_start = s;
TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
file,file->_file,s,size);
/* BAD, for the whole WINE process blocks... just done this way to test
* windows95's ftp.exe.
* JG - Is this true now we use ReadFile() on stdin too?
*/
for(cc = CRTDLL_fgetc(file); cc != CRTDLL_EOF && cc != '\n';
cc = CRTDLL_fgetc(file))
if (cc != '\r')
{
if (--size <= 0) break;
*s++ = (char)cc;
}
if ((cc == CRTDLL_EOF) && (s == buf_start)) /* If nothing read, return 0*/
{
TRACE(":nothing read\n");
return 0;
}
if (cc == '\n')
if (--size > 0)
*s++ = '\n';
*s = '\0';
TRACE(":got '%s'\n", buf_start);
return buf_start;
}
/*********************************************************************
* fgetwc (CRTDLL.366)
*
* Read a wide character from a FILE*.
*/
WCHAR __cdecl CRTDLL_fgetwc( CRTDLL_FILE* file )
{
WCHAR wc;
if (CRTDLL__read(file->_file, &wc, sizeof(wc)) != sizeof(wc))
return CRTDLL_WEOF;
return wc;
}
/*********************************************************************
* fputwc (CRTDLL.373)
*
* Write a wide character to a FILE*.
*/
WCHAR __cdecl CRTDLL_fputwc( WCHAR wc, CRTDLL_FILE* file)
{
if (CRTDLL__write(file->_file, &wc, sizeof(wc)) != sizeof(wc))
return CRTDLL_WEOF;
return wc;
}
/*********************************************************************
* fputs (CRTDLL.375)
*/
INT __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE* file )
{
return CRTDLL_fwrite(s,strlen(s),1,file) == 1 ? 0 : CRTDLL_EOF;
}
/*********************************************************************
* fprintf (CRTDLL.370)
*/
INT __cdecl CRTDLL_fprintf( CRTDLL_FILE* file, LPCSTR format, ... )
{
va_list valist;
INT res;
va_start( valist, format );
res = CRTDLL_vfprintf( file, format, valist );
va_end( valist );
return res;
}
/*********************************************************************
* fopen (CRTDLL.372)
*
* Open a file.
*/
CRTDLL_FILE* __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
{
CRTDLL_FILE* file;
INT flags = 0, plus = 0, fd;
const char* search = mode;
TRACE(":path (%s) mode (%s)\n",path,mode);
while (*search)
if (*search++ == '+')
plus = 1;
/* map mode string to open() flags. "man fopen" for possibilities. */
switch(*mode++)
{
case 'R': case 'r':
flags = (plus ? _O_RDWR : _O_RDONLY);
break;
case 'W': case 'w':
flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY);
break;
case 'A': case 'a':
flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY);
break;
default:
return NULL;
}
while (*mode)
switch (*mode++)
{
case 'B': case 'b':
flags |= _O_BINARY;
flags &= ~_O_TEXT;
break;
case 'T': case 't':
flags |= _O_TEXT;
flags &= ~_O_BINARY;
break;
case '+':
break;
default:
FIXME(":unknown flag %c not supported\n",mode[-1]);
}
fd = CRTDLL__open(path, flags);
if (fd < 0)
return NULL;
file = __CRTDLL__alloc_fp(fd);
TRACE(":get file (%p)\n",file);
if (!file)
CRTDLL__close(fd);
return file;
}
/*********************************************************************
* fputc (CRTDLL.374)
*/
INT __cdecl CRTDLL_fputc( INT c, CRTDLL_FILE* file )
{
return CRTDLL__write(file->_file, &c, 1) == 1? c : CRTDLL_EOF;
}
/*********************************************************************
* fread (CRTDLL.377)
*/
DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT size, INT nmemb, CRTDLL_FILE* file)
{
DWORD read = CRTDLL__read(file->_file,ptr, size * nmemb);
if (read <= 0)
return 0;
return read / size;
}
/*********************************************************************
* freopen (CRTDLL.379)
*
*/
CRTDLL_FILE* __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode,CRTDLL_FILE* file)
{
CRTDLL_FILE* newfile;
INT fd;
TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n",path,mode,file,file->_file);
if (!file || ((fd = file->_file) < 0) || fd > __CRTDLL_fdend)
return NULL;
if (fd > 2)
{
FIXME(":reopen on user file not implemented!\n");
__CRTDLL__set_errno(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
}
/* first, create the new file */
if ((newfile = CRTDLL_fopen(path,mode)) == NULL)
return NULL;
if (fd < 3 && SetStdHandle(fd == 0 ? STD_INPUT_HANDLE :
(fd == 1? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE),
__CRTDLL_handles[newfile->_file]))
{
/* Redirecting std handle to file , copy over.. */
__CRTDLL_handles[fd] = __CRTDLL_handles[newfile->_file];
__CRTDLL_flags[fd] = __CRTDLL_flags[newfile->_file];
memcpy(&__CRTDLL_iob[fd], newfile, sizeof (CRTDLL_FILE));
__CRTDLL_iob[fd]._file = fd;
/* And free up the resources allocated by fopen, but
* not the HANDLE we copied. */
CRTDLL_free(__CRTDLL_files[fd]);
__CRTDLL__free_fd(newfile->_file);
return &__CRTDLL_iob[fd];
}
WARN(":failed-last error (%ld)\n",GetLastError());
CRTDLL_fclose(newfile);
__CRTDLL__set_errno(GetLastError());
return NULL;
}
/*********************************************************************
* fsetpos (CRTDLL.380)
*/
INT __cdecl CRTDLL_fsetpos( CRTDLL_FILE* file, CRTDLL_fpos_t *pos)
{
return CRTDLL__lseek(file->_file,*pos,SEEK_SET);
}
/*********************************************************************
* fscanf (CRTDLL.381)
*/
INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPCSTR format, ... )
{
/* NOTE: If you extend this function, extend CRTDLL__cscanf in console.c too */
INT rd = 0;
int nch;
va_list ap;
if (!*format) return 0;
WARN("%p (\"%s\"): semi-stub\n", file, format);
nch = CRTDLL_fgetc(file);
va_start(ap, format);
while (*format) {
if (*format == ' ') {
/* skip whitespace */
while ((nch!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL_fgetc(file);
}
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!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL_fgetc(file);
/* get sign and first digit */
if (nch == '-') {
nch = CRTDLL_fgetc(file);
if (isdigit(nch))
cur = -(nch - '0');
else break;
} else {
if (isdigit(nch))
cur = nch - '0';
else break;
}
nch = CRTDLL_fgetc(file);
/* read until no more digits */
while ((nch!=CRTDLL_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = CRTDLL_fgetc(file);
}
st = 1;
*val = cur;
}
break;
case 'f': { /* read a float */
float*val = va_arg(ap, float*);
float cur = 0;
/* skip initial whitespace */
while ((nch!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL_fgetc(file);
/* get sign and first digit */
if (nch == '-') {
nch = CRTDLL_fgetc(file);
if (isdigit(nch))
cur = -(nch - '0');
else break;
} else {
if (isdigit(nch))
cur = nch - '0';
else break;
}
/* read until no more digits */
while ((nch!=CRTDLL_EOF) && isdigit(nch)) {
cur = cur*10 + (nch - '0');
nch = CRTDLL_fgetc(file);
}
if (nch == '.') {
/* handle decimals */
float dec = 1;
nch = CRTDLL_fgetc(file);
while ((nch!=CRTDLL_EOF) && isdigit(nch)) {
dec /= 10;
cur += dec * (nch - '0');
nch = CRTDLL_fgetc(file);
}
}
st = 1;
*val = cur;
}
break;
case 's': { /* read a word */
char*str = va_arg(ap, char*);
char*sptr = str;
/* skip initial whitespace */
while ((nch!=CRTDLL_EOF) && isspace(nch))
nch = CRTDLL_fgetc(file);
/* read until whitespace */
while ((nch!=CRTDLL_EOF) && !isspace(nch)) {
*sptr++ = nch; st++;
nch = CRTDLL_fgetc(file);
}
/* 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 = CRTDLL_fgetc(file);
else break;
}
format++;
}
va_end(ap);
if (nch!=CRTDLL_EOF) {
WARN("need ungetch\n");
}
TRACE("returning %d\n", rd);
return rd;
}
/*********************************************************************
* fseek (CRTDLL.382)
*/
LONG __cdecl CRTDLL_fseek( CRTDLL_FILE* file, LONG offset, INT whence)
{
return CRTDLL__lseek(file->_file,offset,whence);
}
/*********************************************************************
* ftell (CRTDLL.381)
*/
LONG __cdecl CRTDLL_ftell( CRTDLL_FILE* file )
{
return CRTDLL__tell(file->_file);
}
/*********************************************************************
* fwrite (CRTDLL.383)
*/
UINT __cdecl CRTDLL_fwrite( LPCVOID ptr, INT size, INT nmemb, CRTDLL_FILE* file )
{
UINT written = CRTDLL__write(file->_file, ptr, size * nmemb);
if (written <= 0)
return 0;
return written / size;
}
/*********************************************************************
* getchar (CRTDLL.386)
*/
INT __cdecl CRTDLL_getchar( VOID )
{
return CRTDLL_fgetc(CRTDLL_stdin);
}
/*********************************************************************
* getc (CRTDLL.388)
*/
INT __cdecl CRTDLL_getc( CRTDLL_FILE* file )
{
return CRTDLL_fgetc( file );
}
/*********************************************************************
* gets (CRTDLL.391)
*/
LPSTR __cdecl CRTDLL_gets(LPSTR buf)
{
int cc;
LPSTR buf_start = buf;
/* BAD, for the whole WINE process blocks... just done this way to test
* windows95's ftp.exe.
* JG 19/9/00: Is this still true, now we are using ReadFile?
*/
for(cc = CRTDLL_fgetc(CRTDLL_stdin); cc != CRTDLL_EOF && cc != '\n';
cc = CRTDLL_fgetc(CRTDLL_stdin))
if(cc != '\r') *buf++ = (char)cc;
*buf = '\0';
TRACE("got '%s'\n", buf_start);
return buf_start;
}
/*********************************************************************
* putc (CRTDLL.441)
*/
INT __cdecl CRTDLL_putc( INT c, CRTDLL_FILE* file )
{
return CRTDLL_fputc( c, file );
}
/*********************************************************************
* putchar (CRTDLL.442)
*/
void __cdecl CRTDLL_putchar( INT c )
{
CRTDLL_fputc(c, CRTDLL_stdout);
}
/*********************************************************************
* puts (CRTDLL.443)
*/
INT __cdecl CRTDLL_puts(LPCSTR s)
{
return CRTDLL_fputs(s, CRTDLL_stdout);
}
/*********************************************************************
* remove (CRTDLL.445)
*/
INT __cdecl CRTDLL_remove(LPCSTR path)
{
TRACE(":path (%s)\n",path);
if (DeleteFileA(path))
return 0;
TRACE(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* rewind (CRTDLL.447)
*
* Set the file pointer to the start of a file and clear any error
* indicators.
*/
VOID __cdecl CRTDLL_rewind(CRTDLL_FILE* file)
{
TRACE(":file (%p) fd (%d)\n",file,file->_file);
CRTDLL__lseek(file->_file,0,SEEK_SET);
file->_flag &= ~(_IOEOF | _IOERR);
}
/*********************************************************************
* scanf (CRTDLL.448)
*/
INT __cdecl CRTDLL_scanf( LPCSTR format, ... )
{
va_list valist;
INT res;
va_start( valist, format );
res = CRTDLL_fscanf(CRTDLL_stdin, format, valist);
va_end(valist);
return res;
}
/*********************************************************************
* rename (CRTDLL.449)
*/
INT __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath)
{
TRACE(":from %s to %s\n",oldpath,newpath);
if (MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
return 0;
TRACE(":failed-last error (%ld)\n",GetLastError());
__CRTDLL__set_errno(GetLastError());
return -1;
}
/*********************************************************************
* setbuf (CRTDLL.452)
*/
INT __cdecl CRTDLL_setbuf(CRTDLL_FILE* file, LPSTR buf)
{
TRACE(":file (%p) fd (%d) buf (%p)\n", file, file->_file,buf);
if (buf)
WARN(":user buffer will not be used!\n");
/* FIXME: no buffering for now */
return 0;
}
/*********************************************************************
* tmpfile (CRTDLL.486)
*
* Create and return a temporary file.
*/
CRTDLL_FILE* __cdecl CRTDLL_tmpfile(void)
{
LPSTR filename = CRTDLL_tmpnam(NULL);
int fd = CRTDLL__open(filename, _O_CREAT | _O_BINARY |
_O_RDWR | _O_TEMPORARY);
if (fd != -1)
return __CRTDLL__alloc_fp(fd);
return NULL;
}
/*********************************************************************
* tmpnam (CRTDLL.490)
*
* lcclnk from lcc-win32 relies on a terminating dot in the name returned
*
*/
LPSTR __cdecl CRTDLL_tmpnam(LPSTR s)
{
char tmpbuf[MAX_PATH];
char* prefix = "TMP";
if (!GetTempPathA(MAX_PATH,tmpbuf) ||
!GetTempFileNameA(tmpbuf,prefix,0,CRTDLL_tmpname))
{
TRACE(":failed-last error (%ld)\n",GetLastError());
return NULL;
}
TRACE(":got tmpnam %s\n",CRTDLL_tmpname);
s = CRTDLL_tmpname;
return s;
}
/*********************************************************************
* vfprintf (CRTDLL.494)
*
* Write formatted output to a file.
*/
/* we have avoided libc stdio.h so far, lets not start now */
extern int vsprintf(void *, const void *, va_list);
/********************************************************************/
INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE* file, LPCSTR format, va_list args )
{
/* FIXME: We should parse the format string, calculate the maximum,
* length of each arg, malloc a buffer, print to it, and fwrite that.
* Yes this sucks, but not as much as crashing 1/2 way through an
* app writing to a file :-(
*/
char buffer[2048];
TRACE(":file (%p) fd (%d) fmt (%s)\n",file,file->_file,format);
vsprintf( buffer, format, args );
return CRTDLL_fwrite( buffer, 1, strlen(buffer), file );
}
/*
* CRT Locale functions
*
* Copyright 2000 Jon Griffiths
*
* NOTES:
* Currently only LC_CTYPE behaviour is actually implemented.
* Passing a code page only is not yet supported.
*
* The code maps a (potentially incomplete) locale description to
* an LCID. The algorithm enumerates supported locales and
* compares the locale strings to the locale information given.
* Fully qualified locales should be completely compatable.
* Some countries (e.g. US) have synonyms that can be used in
* setlocale() calls - these are mapped to ISO codes before
* searching begins, but I may have missed some out of the list.
*
* It should be noted that the algorithm may locate a valid
* locale from a 2 letter ISO code, while the real DLL won't
* (it requires 3 letter codes or synonyms at a minimum).
* e.g. setlocale(LC_ALL,"de") will return "German_Germany.1252"
* with this implementation, while this fails in win32.
*
* It should also be noted that this implementation follows
* the MSVCRT behaviour, and not the CRTDLL behaviour.
* This is because MSVCRT provides a superset of the CRTDLL
* allowed locales, so this code can be used for both. Also
* The CRTDLL implementation can be considered broken.
*
* The code currently works for isleadbyte() but will fail
* (produce potentially incorrect values) for other locales
* with isalpha() etc. This is because the current Wine
* implementation of GetStringTypeA() is not locale aware.
* Fixing this requires a table of which characters in the
* code page are upper/lower/digit etc. If you locate such
* a table for a supported Wine locale, mail it to me and
* I will add the needed support (jon_p_griffiths@yahoo.com).
*/
#include "crtdll.h"
#include "winnt.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
#define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */
#define MAX_LOCALE_LENGTH 256
/* FIXME: Need to hold locale for each LC_* type and aggregate
* string to produce lc_all.
*/
char __CRTDLL_current_lc_all[MAX_LOCALE_LENGTH];
LCID __CRTDLL_current_lc_all_lcid;
UINT __CRTDLL_current_lc_all_cp;
/* Friendly country strings & iso codes for synonym support.
* Based on MS documentation for setlocale().
*/
static const char* _country_synonyms[] =
{
"Hong Kong","HK",
"Hong-Kong","HK",
"New Zealand","NZ",
"New-Zealand","NZ",
"PR China","CN",
"PR-China","CN",
"United Kingdom","GB",
"United-Kingdom","GB",
"Britain","GB",
"England","GB",
"Great Britain","GB",
"United States","US",
"United-States","US",
"America","US"
};
/* INTERNAL: Map a synonym to an ISO code */
static void remap_synonym(char *name)
{
size_t i;
for (i = 0; i < sizeof(_country_synonyms)/sizeof(char*); i += 2 )
{
if (!strcasecmp(_country_synonyms[i],name))
{
TRACE(":Mapping synonym %s to %s\n",name,_country_synonyms[i+1]);
name[0] = _country_synonyms[i+1][0];
name[1] = _country_synonyms[i+1][1];
name[2] = '\0';
return;
}
}
}
/* Note: Flags are weighted in order of matching importance */
#define FOUND_LANGUAGE 0x4
#define FOUND_COUNTRY 0x2
#define FOUND_CODEPAGE 0x1
typedef struct {
char search_language[MAX_ELEM_LEN];
char search_country[MAX_ELEM_LEN];
char search_codepage[MAX_ELEM_LEN];
char found_language[MAX_ELEM_LEN];
char found_country[MAX_ELEM_LEN];
char found_codepage[MAX_ELEM_LEN];
unsigned int match_flags;
LANGID found_lang_id;
} locale_search_t;
#define CONTINUE_LOOKING TRUE
#define STOP_LOOKING FALSE
/* INTERNAL: Get and compare locale info with a given string */
static int compare_info(LCID lcid, DWORD flags, char* buff, const char* cmp)
{
buff[0] = 0;
GetLocaleInfoA(lcid, flags|LOCALE_NOUSEROVERRIDE,buff, MAX_ELEM_LEN);
if (!buff[0] || !cmp[0])
return 0;
/* Partial matches are allowed, e.g. "Germ" matches "Germany" */
return !strncasecmp(cmp, buff, strlen(cmp));
}
/* INTERNAL: Callback for enumerated languages */
static BOOL CALLBACK
find_best_locale_proc(HMODULE hModule, LPCSTR type,
LPCSTR name, WORD LangID, LONG lParam)
{
locale_search_t *res = (locale_search_t *)lParam;
const LCID lcid = MAKELCID(LangID, SORT_DEFAULT);
char buff[MAX_ELEM_LEN];
unsigned int flags = 0;
if(PRIMARYLANGID(LangID) == LANG_NEUTRAL)
return CONTINUE_LOOKING;
/* Check Language */
if (compare_info(lcid,LOCALE_SISO639LANGNAME,buff,res->search_language) ||
compare_info(lcid,LOCALE_SABBREVLANGNAME,buff,res->search_language) ||
compare_info(lcid,LOCALE_SENGLANGUAGE,buff,res->search_language))
{
TRACE(":Found language: %s->%s\n", res->search_language, buff);
flags |= FOUND_LANGUAGE;
memcpy(res->found_language,res->search_language,MAX_ELEM_LEN);
}
else if (res->match_flags & FOUND_LANGUAGE)
{
return CONTINUE_LOOKING;
}
/* Check Country */
if (compare_info(lcid,LOCALE_SISO3166CTRYNAME,buff,res->search_country) ||
compare_info(lcid,LOCALE_SABBREVCTRYNAME,buff,res->search_country) ||
compare_info(lcid,LOCALE_SENGCOUNTRY,buff,res->search_country))
{
TRACE("Found country:%s->%s\n", res->search_country, buff);
flags |= FOUND_COUNTRY;
memcpy(res->found_country,res->search_country,MAX_ELEM_LEN);
}
else if (res->match_flags & FOUND_COUNTRY)
{
return CONTINUE_LOOKING;
}
/* Check codepage */
if (compare_info(lcid,LOCALE_IDEFAULTCODEPAGE,buff,res->search_codepage) ||
(compare_info(lcid,LOCALE_IDEFAULTANSICODEPAGE,buff,res->search_codepage)))
{
TRACE("Found codepage:%s->%s\n", res->search_codepage, buff);
flags |= FOUND_CODEPAGE;
memcpy(res->found_codepage,res->search_codepage,MAX_ELEM_LEN);
}
else if (res->match_flags & FOUND_CODEPAGE)
{
return CONTINUE_LOOKING;
}
if (flags > res->match_flags)
{
/* Found a better match than previously */
res->match_flags = flags;
res->found_lang_id = LangID;
}
if (flags & (FOUND_LANGUAGE & FOUND_COUNTRY & FOUND_CODEPAGE))
{
TRACE(":found exact locale match\n");
return STOP_LOOKING;
}
return CONTINUE_LOOKING;
}
/* Internal: Find the LCID for a locale specification */
static LCID __CRTDLL_locale_to_LCID(locale_search_t* locale)
{
LCID lcid;
EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), RT_STRINGA,
(LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
(LONG)locale);
if (!locale->match_flags)
return 0;
/* If we were given something that didn't match, fail */
if (locale->search_country[0] && !(locale->match_flags & FOUND_COUNTRY))
return 0;
lcid = MAKELCID(locale->found_lang_id, SORT_DEFAULT);
/* Populate partial locale, translating LCID to locale string elements */
if (!locale->found_codepage[0])
{
/* Even if a codepage is not enumerated for a locale
* it can be set if valid */
if (locale->search_codepage[0])
{
if (IsValidCodePage(atoi(locale->search_codepage)))
memcpy(locale->found_codepage,locale->search_codepage,MAX_ELEM_LEN);
else
{
/* Special codepage values: OEM & ANSI */
if (strcasecmp(locale->search_codepage,"OCP"))
{
GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
}
if (strcasecmp(locale->search_codepage,"ACP"))
{
GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
}
else
return 0;
if (!atoi(locale->found_codepage))
return 0;
}
}
else
{
/* Prefer ANSI codepages if present */
GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
if (!locale->found_codepage[0] || !atoi(locale->found_codepage))
GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
}
}
GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE,
locale->found_language, MAX_ELEM_LEN);
GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY|LOCALE_NOUSEROVERRIDE,
locale->found_country, MAX_ELEM_LEN);
return lcid;
}
/* INTERNAL: Set ctype behaviour for a codepage */
static void __CRTDLL_set_ctype(UINT codepage, LCID lcid)
{
CPINFO cp;
memset(&cp, 0, sizeof(CPINFO));
if (GetCPInfo(codepage, &cp))
{
int i;
char str[3];
unsigned char *traverse = (unsigned char *)cp.LeadByte;
memset(__CRTDLL_current_ctype, 0, sizeof(CRTDLL_ctype));
__CRTDLL_current_lc_all_cp = codepage;
/* Switch ctype macros to MBCS if needed */
CRTDLL__mb_cur_max_dll = cp.MaxCharSize;
/* Set remaining ctype flags: FIXME: faster way to do this? */
str[1] = str[2] = 0;
for (i = 0; i < 256; i++)
{
if (!(CRTDLL_pctype_dll[i] & CRTDLL_LEADBYTE))
{
str[0] = i;
GetStringTypeA(lcid, CT_CTYPE1, str, 1, CRTDLL_pctype_dll + i);
}
}
/* Set leadbyte flags */
while (traverse[0] || traverse[1])
{
for( i = traverse[0]; i <= traverse[1]; i++ )
__CRTDLL_current_ctype[i+1] |= CRTDLL_LEADBYTE;
traverse += 2;
};
}
}
/*********************************************************************
* setlocale (CRTDLL.453)
*/
LPSTR __cdecl CRTDLL_setlocale(INT category, LPCSTR locale)
{
LCID lcid = 0;
locale_search_t lc;
int haveLang, haveCountry, haveCP;
char* next;
int lc_all = 0;
if (category < CRTDLL_LC_MIN || category > CRTDLL_LC_MAX)
return NULL;
if (locale == NULL)
{
/* Report the current Locale */
return __CRTDLL_current_lc_all;
}
if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_')
{
FIXME(":restore previous locale not implemented!\n");
/* FIXME: Easiest way to do this is parse the string and
* call this function recursively with its elements,
* Where they differ for each lc_ type.
*/
return __CRTDLL_current_lc_all;
}
/* Default Locale: Special case handling */
if (!strlen(locale) || ((toupper(locale[0]) == 'C') && !locale[1]))
{
__CRTDLL_current_lc_all[0] = 'C';
__CRTDLL_current_lc_all[1] = '\0';
__CRTDLL_current_lc_all_cp = GetACP();
switch (category) {
case CRTDLL_LC_ALL:
lc_all = 1; /* Fall through all cases ... */
case CRTDLL_LC_COLLATE:
if (!lc_all) break;
case CRTDLL_LC_CTYPE:
/* Restore C locale ctype info */
CRTDLL__mb_cur_max_dll = 1;
memcpy(__CRTDLL_current_ctype, CRTDLL_ctype, sizeof(CRTDLL_ctype));
memset(CRTDLL_mbctype, 0, sizeof(CRTDLL_mbctype));
if (!lc_all) break;
case CRTDLL_LC_MONETARY:
if (!lc_all) break;
case CRTDLL_LC_NUMERIC:
if (!lc_all) break;
case CRTDLL_LC_TIME:
}
return __CRTDLL_current_lc_all;
}
/* Get locale elements */
haveLang = haveCountry = haveCP = 0;
memset(&lc,0,sizeof(lc));
next = strchr(locale,'_');
if (next && next != locale)
{
haveLang = 1;
strncpy(lc.search_language,locale,next-locale);
locale += next-locale+1;
}
next = strchr(locale,'.');
if (next)
{
haveCP = 1;
if (next == locale)
{
locale++;
strncpy(lc.search_codepage, locale, MAX_ELEM_LEN);
}
else
{
if (haveLang)
{
haveCountry = 1;
strncpy(lc.search_country,locale,next-locale);
locale += next-locale+1;
}
else
{
haveLang = 1;
strncpy(lc.search_language,locale,next-locale);
locale += next-locale+1;
}
strncpy(lc.search_codepage, locale, MAX_ELEM_LEN);
}
}
else
{
if (haveLang)
{
haveCountry = 1;
strncpy(lc.search_country, locale, MAX_ELEM_LEN);
}
else
{
haveLang = 1;
strncpy(lc.search_language, locale, MAX_ELEM_LEN);
}
}
if (haveCountry)
remap_synonym(lc.search_country);
if (haveCP && !haveCountry && !haveLang)
{
FIXME(":Codepage only locale not implemented");
/* FIXME: Use default lang/country and skip locale_to_LCID()
* call below...
*/
return NULL;
}
lcid = __CRTDLL_locale_to_LCID(&lc);
TRACE(":found LCID %ld\n",lcid);
if (lcid == 0)
return NULL;
__CRTDLL_current_lc_all_lcid = lcid;
snprintf(__CRTDLL_current_lc_all,MAX_LOCALE_LENGTH,"%s_%s.%s",
lc.found_language,lc.found_country,lc.found_codepage);
switch (category) {
case CRTDLL_LC_ALL:
lc_all = 1; /* Fall through all cases ... */
case CRTDLL_LC_COLLATE:
if (!lc_all) break;
case CRTDLL_LC_CTYPE:
__CRTDLL_set_ctype(atoi(lc.found_codepage),lcid);
if (!lc_all) break;
break;
case CRTDLL_LC_MONETARY:
if (!lc_all) break;
case CRTDLL_LC_NUMERIC:
if (!lc_all) break;
case CRTDLL_LC_TIME:
}
return __CRTDLL_current_lc_all;
}
/*
* CRTDLL multi-byte string functions
*
* Copyright 1999 Alexandre Julliard
* Copyright 2000 Jon Griffths
*
* NOTES
* See msdn.microsoft.com
* /library/devprods/vs6/visualc/vccore/_crt__ismbb_routines.htm
* For details and CP 932 information.
*
* This code assumes that MB_LEN_MAX is 2 and that [0,0] is an
* invalid MB char. If that changes, this will need to too.
*
* CRTDLL reports valid CP 932 multibyte chars when the current
* code page is not 932. MSVCRT fixes this bug - we implement
* MSVCRT's behaviour, since its correct. However, MSVCRT fails
* to set the code page correctly when the locale is changed, so
* it must be explicitly set to get matching results.
*
* FIXME
* Not currently binary compatable with win32. CRTDLL_mbctype must be
* populated correctly and the ismb* functions should reference it.
*/
#include "crtdll.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
UCHAR CRTDLL_mbctype[257];
/*********************************************************************
* _mbscmp (CRTDLL.??)
*
* Compare two multibyte strings.
*/
INT __cdecl CRTDLL__mbscmp( LPCSTR str, LPCSTR cmp )
{
if (CRTDLL__mb_cur_max_dll > 1)
{
UINT strc, cmpc;
do {
if (!*str)
return *cmp ? -1 : 0;
if (!*cmp)
return 1;
strc = CRTDLL__mbsnextc(str);
cmpc = CRTDLL__mbsnextc(cmp);
if (strc != cmpc)
return strc < cmpc ? -1 : 1;
str += (strc > 255) ? 2 : 1;
cmp += (strc > 255) ? 2 : 1; /* equal, use same increment */
} while (1);
}
return strcmp(str, cmp); /* ASCII CP */
}
/*********************************************************************
* _mbsicmp (CRTDLL.??)
*
* Compare two multibyte strings case insensitively.
*/
INT __cdecl CRTDLL__mbsicmp( LPCSTR str, LPCSTR cmp )
{
/* FIXME: No tolower() for mb strings yet */
if (CRTDLL__mb_cur_max_dll > 1)
return CRTDLL__mbscmp( str, cmp );
return strcasecmp( str, cmp ); /* ASCII CP */
}
/*********************************************************************
* _mbsncmp (CRTDLL.??)
*
* Compare two multibyte strings to 'len' characters.
*/
INT __cdecl CRTDLL__mbsncmp( LPCSTR str, LPCSTR cmp, UINT len )
{
if (!len)
return 0;
if (CRTDLL__mb_cur_max_dll > 1)
{
UINT strc, cmpc;
while (len--)
{
if (!*str)
return *cmp ? -1 : 0;
if (!*cmp)
return 1;
strc = CRTDLL__mbsnextc(str);
cmpc = CRTDLL__mbsnextc(cmp);
if (strc != cmpc)
return strc < cmpc ? -1 : 1;
str += (strc > 255) ? 2 : 1;
cmp += (strc > 255) ? 2 : 1; /* Equal, use same increment */
}
return 0; /* Matched len chars */
}
return strncmp(str, cmp, len); /* ASCII CP */
}
/*********************************************************************
* _mbsnicmp (CRTDLL.??)
*
* Compare two multibyte strings case insensitively to 'len' characters.
*/
INT __cdecl CRTDLL__mbsnicmp( LPCSTR str, LPCSTR cmp, UINT len )
{
/* FIXME: No tolower() for mb strings yet */
if (CRTDLL__mb_cur_max_dll > 1)
return CRTDLL__mbsncmp( str, cmp, len );
return strncasecmp( str, cmp, len ); /* ASCII CP */
}
/*********************************************************************
* _mbsinc (CRTDLL.205)
*
* Return the next character of a string.
*/
LPSTR __cdecl CRTDLL__mbsinc( LPCSTR str )
{
if (CRTDLL__mb_cur_max_dll > 1 &&
CRTDLL_isleadbyte(*str))
return (LPSTR)str + 2; /* MB char */
return (LPSTR)str + 1; /* ASCII CP or SB char */
}
/*********************************************************************
* _mbsninc (CRTDLL.??)
*
* Return the 'num'th character of a string.
*/
LPSTR CRTDLL__mbsninc( LPCSTR str, INT num )
{
if (!str || num < 1)
return NULL;
if (CRTDLL__mb_cur_max_dll > 1)
{
while(num--)
str = CRTDLL__mbsinc( str );
return (LPSTR)str;
}
return (LPSTR)str + num; /* ASCII CP */
}
/*********************************************************************
* _mbslen (CRTDLL.206)
*
* Get the length of a string.
*/
INT __cdecl CRTDLL__mbslen( LPCSTR str )
{
if (CRTDLL__mb_cur_max_dll > 1)
{
INT len = 0;
while (*str)
{
str += CRTDLL_isleadbyte( *str ) ? 2 : 1;
len++;
}
return len;
}
return strlen( str ); /* ASCII CP */
}
/*********************************************************************
* _mbsrchr (CRTDLL.223)
*/
LPSTR __cdecl CRTDLL__mbsrchr(LPCSTR s,CHAR x)
{
/* FIXME: handle multibyte strings */
return strrchr(s,x);
}
/*********************************************************************
* mbtowc (CRTDLL.430)
*/
INT __cdecl CRTDLL_mbtowc( WCHAR *dst, LPCSTR str, INT n )
{
if (n <= 0) return 0;
if (!str) return 0;
if (!MultiByteToWideChar( CP_ACP, 0, str, n, dst, 1 )) return 0;
/* return the number of bytes from src that have been used */
if (!*str) return 0;
if (n >= 2 && CRTDLL_isleadbyte(*str) && str[1]) return 2;
return 1;
}
/*********************************************************************
* _mbccpy (CRTDLL.??)
*
* Copy one multibyte character to another
*/
VOID __cdecl CRTDLL__mbccpy(LPSTR dest, LPSTR src)
{
*dest++ = *src;
if (CRTDLL__mb_cur_max_dll > 1 && CRTDLL_isleadbyte(*src))
*dest = *++src; /* MB char */
}
/*********************************************************************
* _mbsdec (CRTDLL.??)
*
* Return the character before 'cur'.
*/
LPSTR __cdecl CRTDLL__mbsdec( LPCSTR start, LPCSTR cur )
{
if (CRTDLL__mb_cur_max_dll > 1)
return (LPSTR)(CRTDLL__ismbstrail(start,cur-1) ? cur - 2 : cur -1);
return (LPSTR)cur - 1; /* ASCII CP or SB char */
}
/*********************************************************************
* _mbbtombc (CRTDLL.??)
*
* Convert a single byte character to a multi byte character.
*/
USHORT __cdecl CRTDLL__mbbtombc( USHORT c )
{
if (CRTDLL__mb_cur_max_dll > 1 &&
((c >= 0x20 && c <=0x7e) || (c >= 0xa1 && c <= 0xdf)))
{
/* FIXME: I can't get this function to return anything
* different to what I pass it...
*/
}
return c; /* ASCII CP or no MB char */
}
/*********************************************************************
* _mbclen (CRTDLL.??)
*
* Get the length of a multibyte character.
*/
INT __cdecl CRTDLL__mbclen( LPCSTR str )
{
return CRTDLL_isleadbyte( *str ) ? 2 : 1;
}
/*********************************************************************
* _ismbbkana (CRTDLL.??)
*
* Is the given single byte character Katakana?
*/
INT __cdecl CRTDLL__ismbbkana( UINT c )
{
/* FIXME: use lc_ctype when supported, not lc_all */
if (__CRTDLL_current_lc_all_cp == 932)
{
/* Japanese/Katakana, CP 932 */
return (c >= 0xa1 && c <= 0xdf);
}
return 0;
}
/*********************************************************************
* _ismbchira (CRTDLL.??)
*
* Is the given character Hiragana?
*/
INT __cdecl CRTDLL__ismbchira( UINT c )
{
/* FIXME: use lc_ctype when supported, not lc_all */
if (__CRTDLL_current_lc_all_cp == 932)
{
/* Japanese/Hiragana, CP 932 */
return (c >= 0x829f && c <= 0x82f1);
}
return 0;
}
/*********************************************************************
* _ismbckata (CRTDLL.??)
*
* Is the given double byte character Katakana?
*/
INT __cdecl CRTDLL__ismbckata( UINT c )
{
/* FIXME: use lc_ctype when supported, not lc_all */
if (__CRTDLL_current_lc_all_cp == 932)
{
if ( c < 256)
return CRTDLL__ismbbkana( c );
/* Japanese/Katakana, CP 932 */
return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
}
return 0;
}
/*********************************************************************
* _ismbblead (CRTDLL.??)
*
* Is the given single byte character a lead byte?
*/
INT __cdecl CRTDLL__ismbblead( UINT c )
{
/* FIXME: should reference CRTDLL_mbctype */
return CRTDLL__mb_cur_max_dll > 1 && CRTDLL_isleadbyte( c );
}
/*********************************************************************
* _ismbbtrail (CRTDLL.??)
*
* Is the given single byte character a trail byte?
*/
INT __cdecl CRTDLL__ismbbtrail( UINT c )
{
/* FIXME: should reference CRTDLL_mbctype */
return !CRTDLL__ismbblead( c );
}
/*********************************************************************
* _ismbslead (CRTDLL.??)
*
* Is the character pointed to 'str' a lead byte?
*/
INT __cdecl CRTDLL__ismbslead( LPCSTR start, LPCSTR str )
{
/* Lead bytes can also be trail bytes if caller messed up
* iterating through the string...
*/
if (CRTDLL__mb_cur_max_dll > 1)
{
while (start < str)
start += CRTDLL_isleadbyte ( *str ) ? 2 : 1;
if (start == str)
return CRTDLL_isleadbyte( *str );
}
return 0; /* Must have been a trail, we skipped it */
}
/*********************************************************************
* _ismbstrail (CRTDLL.??)
*
* Is the character pointed to 'str' a trail byte?
*/
INT __cdecl CRTDLL__ismbstrail( LPCSTR start, LPCSTR str )
{
/* Must not be a lead, and must be preceeded by one */
return !CRTDLL__ismbslead( start, str ) && CRTDLL_isleadbyte(str[-1]);
}
/*********************************************************************
* _mbsset (CRTDLL.??)
*
* Fill a multibyte string with a value.
*/
LPSTR __cdecl CRTDLL__mbsset( LPSTR str, UINT c )
{
LPSTR ret = str;
if (CRTDLL__mb_cur_max_dll == 1 || c < 256)
return CRTDLL__strset( str, c ); /* ASCII CP or SB char */
c &= 0xffff; /* Strip high bits */
while (str[0] && str[1])
{
*str++ = c >> 8;
*str++ = c & 0xff;
}
if (str[0])
str[0] = '\0'; /* FIXME: OK to shorten? */
return ret;
}
/*********************************************************************
* _mbsnset (CRTDLL.??)
*
* Fill a multibyte string with a value up to 'len' characters.
*/
LPSTR __cdecl CRTDLL__mbsnset( LPSTR str, UINT c, UINT len )
{
LPSTR ret = str;
if (!len)
return ret;
if (CRTDLL__mb_cur_max_dll == 1 || c < 256)
return CRTDLL__strnset( str, c, len ); /* ASCII CP or SB char */
c &= 0xffff; /* Strip high bits */
while (str[0] && str[1] && len--)
{
*str++ = c >> 8;
*str++ = c & 0xff;
}
if (len && str[0])
str[0] = '\0'; /* FIXME: OK to shorten? */
return ret;
}
/*********************************************************************
* _mbstrlen (CRTDLL.??)
*
* Get the length of a multibyte string.
*/
INT __cdecl CRTDLL__mbstrlen( LPCSTR str )
{
if (CRTDLL__mb_cur_max_dll > 1)
{
INT len = 0;
while (*str)
{
str += CRTDLL_isleadbyte ( *str ) ? 2 : 1;
len++;
}
return len;
}
return strlen( str ); /* ASCII CP */
}
/*********************************************************************
* _mbsnextc (CRTDLL.??)
*
* Get the next character from a multibyte string.
*/
UINT __cdecl CRTDLL__mbsnextc( LPCSTR str )
{
if (CRTDLL__mb_cur_max_dll > 1 && CRTDLL_isleadbyte( *str ))
return *str << 8 | str[1];
return *str; /* ASCII CP or SB char */
}
/*********************************************************************
* _mbsncpy (CRTDLL.??)
*
* Copy one multibyte string to another up to 'len' characters.
*/
LPSTR __cdecl CRTDLL__mbsncpy( LPSTR dst, LPCSTR src, UINT len )
{
if (!len)
return dst;
if (CRTDLL__mb_cur_max_dll > 1)
{
LPSTR ret = dst;
while (src[0] && src[1] && len--)
{
*dst++ = *src++;
*dst++ = *src++;
}
if (len--)
{
*dst++ = *src++; /* Last char or '\0' */
while(len--)
*dst++ = '\0';
}
return ret;
}
return strncpy( dst, src, len ); /* ASCII CP */
}
/*********************************************************************
* _mbschr (CRTDLL.??)
*
* Find a multibyte character in a multibyte string.
*/
LPSTR __cdecl CRTDLL__mbschr( LPCSTR str, UINT c )
{
if (CRTDLL__mb_cur_max_dll > 1)
{
UINT next;
while((next = CRTDLL__mbsnextc( str )))
{
if (next == c)
return (LPSTR)str;
str += next > 255 ? 2 : 1;
}
return c ? NULL : (LPSTR)str;
}
return strchr( str, c ); /* ASCII CP */
}
/*********************************************************************
* _mbsnccnt (CRTDLL.??)
*
* Return the number of mutibyte characters in 'len' bytes of a string.
*/
UINT __cdecl CRTDLL__mbsnccnt( LPCSTR str, UINT len )
{
int ret = 0;
if (CRTDLL__mb_cur_max_dll > 1)
{
while(*str && len-- > 0)
{
if (CRTDLL_isleadbyte ( *str ))
{
str++;
len--;
}
ret++;
str++;
}
return ret;
}
return min( strlen( str ), len ); /* ASCII CP */
}
/*********************************************************************
* _mbsncat (CRTDLL.??)
*
* Add 'len' characters from one multibyte string to another.
*/
LPSTR __cdecl CRTDLL__mbsncat( LPSTR dst, LPCSTR src, UINT len )
{
if (CRTDLL__mb_cur_max_dll > 1)
{
LPSTR res = dst;
dst += CRTDLL__mbslen( dst );
while (*src && len--)
{
*dst = *src;
if (CRTDLL_isleadbyte( *src ))
*++dst = *++src;
dst++;
src++;
}
*dst++ = '\0';
return res;
}
return strncat( dst, src, len ); /* ASCII CP */
}
/*
* CRTDLL memory functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* Implementation Notes:
* MT Safe.
* heapwalk from win does not work. This is most likely due to internal
* differences between wine and win (see memory/heap.c comments). This
* version works fine, however.
*/
#include "crtdll.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
static new_handler_type new_handler;
/*********************************************************************
* new (CRTDLL.001)
*
* Allocate memory.
*/
LPVOID __cdecl CRTDLL_new(DWORD size)
{
VOID* result;
if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
(*new_handler)();
return result;
}
/*********************************************************************
* delete (CRTDLL.002)
*
* Free memory created with new.
*/
VOID __cdecl CRTDLL_delete(LPVOID ptr)
{
HeapFree(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* set_new_handler(CRTDLL.003)
*/
new_handler_type __cdecl CRTDLL_set_new_handler(new_handler_type func)
{
new_handler_type old_handler = new_handler;
new_handler = func;
return old_handler;
}
/*********************************************************************
* _expand (CRTDLL.088)
*
* Increase the size of a block of memory allocated with malloc()
* or realloc().
*/
LPVOID __cdecl CRTDLL__expand(LPVOID ptr, INT size)
{
return HeapReAlloc( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, ptr, size );
}
/*********************************************************************
* _heapchk (CRTDLL.130)
*
* Check the consistency of the process heap.
*/
INT __cdecl CRTDLL__heapchk(VOID)
{
if (!HeapValidate( GetProcessHeap(), 0, NULL))
{
__CRTDLL__set_errno(GetLastError());
return _HEAPBADNODE;
}
return _HEAPOK;
}
/*********************************************************************
* _heapmin (CRTDLL.131)
*
* Minimise the size of the heap.
*/
INT __cdecl CRTDLL__heapmin(VOID)
{
if (!HeapCompact( GetProcessHeap(), 0 ))
{
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
__CRTDLL__set_errno(GetLastError());
return -1;
}
return 0;
}
/*********************************************************************
* _heapset (CRTDLL.132)
*
* Fill free memory in the heap with a given value.
*/
INT __cdecl CRTDLL__heapset(UINT value)
{
INT retVal;
struct _heapinfo heap;
memset( &heap, 0, sizeof(heap) );
while ((retVal = CRTDLL__heapwalk(&heap)) == _HEAPOK)
{
if (heap._useflag == _FREEENTRY)
memset(heap._pentry, value, heap._size);
}
return retVal == _HEAPEND? _HEAPOK : retVal;
}
/*********************************************************************
* _heapwalk (CRTDLL.133)
*
* Walk the heap block by block.
*/
INT __cdecl CRTDLL__heapwalk(struct _heapinfo *next)
{
PROCESS_HEAP_ENTRY phe;
phe.lpData = next->_pentry;
phe.cbData = next->_size;
phe.wFlags = next->_useflag == _USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0;
if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY &&
!HeapValidate( GetProcessHeap(), 0, phe.lpData ))
{
__CRTDLL__set_errno(GetLastError());
return _HEAPBADNODE;
}
do
{
if (!HeapWalk( GetProcessHeap(), &phe ))
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
return _HEAPEND;
__CRTDLL__set_errno(GetLastError());
if (!phe.lpData)
return _HEAPBADBEGIN;
return _HEAPBADNODE;
}
} while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE));
next->_pentry = phe.lpData;
next->_size = phe.cbData;
next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? _USEDENTRY : _FREEENTRY;
return _HEAPOK;
}
/*********************************************************************
* _msize (CRTDLL.234)
*
* Return the actual used size of an allocated block of memory.
*
*/
LONG __cdecl CRTDLL__msize(LPVOID mem)
{
LONG size = HeapSize(GetProcessHeap(),0,mem);
if (size == -1)
{
WARN(":Probably called with non wine-allocated memory, ret = -1\n");
/* At least the win98/nt crtdlls also return -1 in this case */
}
return size;
}
/*********************************************************************
* calloc (CRTDLL.350)
*
* Allocate memory from the heap and initialise it to zero.
*/
LPVOID __cdecl CRTDLL_calloc(DWORD size, DWORD count)
{
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
}
/*********************************************************************
* free (CRTDLL.375)
*
* Free a block of memory allocated with malloc()
*/
VOID __cdecl CRTDLL_free(LPVOID ptr)
{
HeapFree(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* malloc (CRTDLL.424)
*
* Alocate memory from the heap.
*/
LPVOID __cdecl CRTDLL_malloc(DWORD size)
{
LPVOID ret = HeapAlloc(GetProcessHeap(),0,size);
if (!ret)
__CRTDLL__set_errno(GetLastError());
return ret;
}
/*********************************************************************
* realloc (CRTDLL.444)
*
* Resize a block of memory allocated with malloc() or realloc().
*/
LPVOID __cdecl CRTDLL_realloc( VOID *ptr, DWORD size )
{
return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
}
/*
* CRTDLL spawn functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* These functions differ in whether they pass arguments as an array
* (v in the name) or as varags (l in the name), whether they
* seach the path (p in the name) and/or whether they take an
* environment (e in the name) or pass the parents environment.
* Args as Search Take
* Name varargs? path? environment?
* spawnl N N N
* spawnle N N Y
* spawnlp N Y N
* spawnlpe N Y Y
* spawnv Y N N
* spawnve Y N Y
* spawnvp Y Y N
* spawnvpe Y Y Y
*
* Implementation Notes:
* MT Safe - But only because of missing functionality.
*
* After translating input arguments into the required format for
* CreateProcess(), the internal function __CRTDLL__spawn() is
* called to perform the actual spawning.
*
* 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.
* Unresolved issues Uwe Bonnes 970904:
* -system-call calls another wine process, but without debugging arguments
* and uses the first wine executable in the path
*/
#include "crtdll.h"
#include <errno.h>
#include <stdlib.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
/* Process creation flags */
#define _P_WAIT 0
#define _P_NOWAIT 1
#define _P_OVERLAY 2
#define _P_NOWAITO 3
#define _P_DETACH 4
extern void __CRTDLL__set_errno(ULONG err);
extern LPVOID __cdecl CRTDLL_calloc(DWORD size, DWORD count);
extern VOID __cdecl CRTDLL_free(void *ptr);
extern VOID __cdecl CRTDLL__exit(LONG ret);
extern INT CRTDLL_doserrno;
/* INTERNAL: Spawn a child process */
static int __CRTDLL__spawn(INT flags, LPCSTR exe, LPSTR args, LPSTR env)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
if ((unsigned)flags > _P_DETACH)
{
CRTDLL_errno = 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))
{
__CRTDLL__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 pi.dwProcessId;
case _P_DETACH:
CloseHandle(pi.hProcess);
pi.hProcess = 0;
/* fall through */
case _P_NOWAIT:
case _P_NOWAITO:
CloseHandle(pi.hThread);
return pi.hProcess;
case _P_OVERLAY:
CRTDLL__exit(0);
}
return -1; /* cant reach here */
}
/* INTERNAL: Convert argv list to a single 'delim'-seperated string */
static LPSTR __CRTDLL__argvtos(LPCSTR *arg, CHAR delim)
{
LPCSTR *search = arg;
LONG size = 0;
LPSTR ret;
if (!arg && !delim)
return NULL;
/* get length */
while(*search)
{
size += strlen(*search) + 1;
search++;
}
if (!(ret = (LPSTR)CRTDLL_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 (CRTDLL.069)
*
* Wait for a spawned process to finish.
*/
INT __cdecl CRTDLL__cwait(LPINT status, INT pid, INT action)
{
HANDLE hPid = (HANDLE)pid;
action = action; /* Remove warning */
if (!WaitForSingleObject(hPid, -1)) /* wait forvever */
{
if (status)
{
DWORD stat;
GetExitCodeProcess(hPid, &stat);
*status = (INT)stat;
}
return pid;
}
CRTDLL_doserrno = GetLastError();
if (CRTDLL_doserrno == ERROR_INVALID_HANDLE)
CRTDLL_errno = ECHILD;
else
__CRTDLL__set_errno(CRTDLL_doserrno);
return status ? *status = -1 : -1;
}
/*********************************************************************
* _spawnv (CRTDLL.273)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnv(INT flags, LPCSTR name, LPCSTR *argv)
{
return CRTDLL__spawnve(flags, name, argv, NULL);
}
/*********************************************************************
* _spawnve (CRTDLL.274)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnve(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
{
LPSTR args = __CRTDLL__argvtos(argv,' ');
LPSTR envs = __CRTDLL__argvtos(envv,0);
LPCSTR fullname = name;
HANDLE 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 = __CRTDLL__spawn(flags, fullname, args, envs);
CRTDLL_free(args);
}
if (envs)
CRTDLL_free(envs);
return ret;
}
/*********************************************************************
* _spawnvp (CRTDLL.275)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnvp(INT flags, LPCSTR name, LPCSTR *argv)
{
return CRTDLL__spawnvpe(flags, name, argv, NULL);
}
/*********************************************************************
* _spawnvpe (CRTDLL.276)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnvpe(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
{
char fullname[MAX_PATH];
CRTDLL__searchenv(name, "PATH", fullname);
return CRTDLL__spawnve(flags, fullname[0] ? fullname : name, argv, envv);
}
/*********************************************************************
* system (CRTDLL.485)
*
* Spawn an O/S process.
*/
INT __cdecl CRTDLL_system(LPCSTR cmd)
{
/* FIXME: should probably launch cmd interpreter in COMSPEC */
return __CRTDLL__spawn(_P_WAIT, cmd, NULL, NULL);
}
/*
* CRTDLL string functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* Implementation Notes:
* MT Safe.
*/
#include "crtdll.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: CRTDLL_malloc() based strndup */
LPSTR __CRTDLL__strndup(LPSTR buf, INT size);
LPSTR __CRTDLL__strndup(LPSTR buf, INT size)
{
char* ret;
int len = strlen(buf);
int max_len;
max_len = size <= len? size : len + 1;
ret = CRTDLL_malloc(max_len);
if (ret)
{
memcpy(ret,buf,max_len);
ret[max_len] = 0;
}
return ret;
}
/*********************************************************************
* _strdec (CRTDLL.282)
*
* Return the byte before str2 while it is >= to str1.
*
* PARAMS
* str1 [in] Terminating string
*
* sre2 [in] string to start searching from
*
* RETURNS
* The byte before str2, or str1, whichever is greater
*
* NOTES
* This function is implemented as tested with windows, which means
* it does not have a terminating condition. It always returns
* the byte before str2. Use with extreme caution!
*/
LPSTR __cdecl CRTDLL__strdec(LPSTR str1, LPSTR 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 str2-1;
}
/*********************************************************************
* _strdup (CRTDLL.285)
*
* Duplicate a string.
*/
LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr)
{
LPSTR ret = CRTDLL_malloc(strlen(ptr)+1);
if (ret) strcpy( ret, ptr );
return ret;
}
/*********************************************************************
* _strinc (CRTDLL.287)
*
* Return a pointer to the next character in a string
*/
LPSTR __cdecl CRTDLL__strinc(LPSTR str)
{
return str+1;
}
/*********************************************************************
* _strnextc (CRTDLL.290)
*
* Return an unsigned int from a string.
*/
UINT __cdecl CRTDLL__strnextc(LPCSTR str)
{
return (UINT)*str;
}
/*********************************************************************
* _strninc (CRTDLL.292)
*
* Return a pointer to the 'n'th character in a string
*/
LPSTR __cdecl CRTDLL__strninc(LPSTR str, INT n)
{
return str+n;
}
/*********************************************************************
* _strnset (CRTDLL.293)
*
* Fill a string with a character up to a certain length
*/
LPSTR __cdecl CRTDLL__strnset(LPSTR str, INT c, INT len)
{
if (len > 0 && str)
while (*str && len--)
*str++ = c;
return str;
}
/*********************************************************************
* _strrev (CRTDLL.294)
*
* Reverse a string in place
*/
LPSTR __cdecl CRTDLL__strrev (LPSTR str)
{
LPSTR p1;
LPSTR 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 (CRTDLL.295)
*
* Fill a string with a value.
*/
LPSTR __cdecl CRTDLL__strset (LPSTR str, INT set)
{
char *ptr = str;
while (*ptr)
*ptr++ = set;
return str;
}
/*********************************************************************
* _strncnt (CRTDLL.289)
*
* Return the length of a string or the maximum given length.
*/
LONG __cdecl CRTDLL__strncnt(LPSTR str, LONG max)
{
LONG len = strlen(str);
return (len > max? max : len);
}
/*********************************************************************
* _strspnp (CRTDLL.296)
*
*/
LPSTR __cdecl CRTDLL__strspnp(LPSTR str1, LPSTR str2)
{
str1 += strspn(str1,str2);
return *str1? str1 : 0;
}
/*********************************************************************
* _swab (CRTDLL.299)
*
* Copy from source to dest alternating bytes (i.e 16 bit big-to-little
* endian or vice versa).
*/
void __cdecl CRTDLL__swab(LPSTR src, LPSTR dst, INT len)
{
if (len > 1)
{
len = (unsigned)len >> 1;
while (len--) {
*dst++ = src[1];
*dst++ = *src++;
src++;
}
}
}
/*
* CRTDLL date/time functions
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
* Copyright 2000 Jon Griffiths
*
* Implementation Notes:
* MT Safe.
*/
#include "crtdll.h"
#include <stdlib.h>
#include <sys/times.h>
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: Return formatted current time/date */
static LPSTR __CRTDLL__get_current_time(LPSTR out, const char * format);
static LPSTR __CRTDLL__get_current_time(LPSTR out, const char * format)
{
time_t t;
struct tm *_tm;
if ((time(&t) != ((time_t)-1)) &&
((_tm = localtime(&t)) != 0) &&
(strftime(out,9,format,_tm) == 8))
{
CRTDLL_free(_tm);
return out;
}
return NULL;
}
/*********************************************************************
* _ftime (CRTDLL.112)
*
* Get current time.
*/
VOID __cdecl CRTDLL__ftime (struct _timeb* t)
{
t->time = CRTDLL_time(NULL);
t->millitm = 0; /* FIXME */
t->timezone = 0;
t->dstflag = 0;
}
/**********************************************************************
* _strdate (CRTDLL.283)
*
* Return the current date as MM/DD/YY - (American Format)
*/
LPSTR __cdecl CRTDLL__strdate (LPSTR date)
{
return __CRTDLL__get_current_time(date,"%m/%d/%y");
}
/*********************************************************************
* _strtime (CRTDLL.299)
*
* Return the current time as HH:MM:SS
*/
LPSTR __cdecl CRTDLL__strtime (LPSTR date)
{
return __CRTDLL__get_current_time(date,"%H:%M:%S");
}
/*********************************************************************
* clock (CRTDLL.350)
*/
clock_t __cdecl CRTDLL_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 (Hostsystem_)CLOCKS_PER_SEC
and (Emulated_system_)CLOCKS_PER_SEC
10 holds only for Windows/Linux_i86)
*/
return 10*res;
}
/*********************************************************************
* difftime (CRTDLL.357)
*/
double __cdecl CRTDLL_difftime (time_t time1, time_t time2)
{
double timediff;
timediff = (double)(time1 - time2);
return timediff;
}
/*********************************************************************
* time (CRTDLL.488)
*/
time_t __cdecl CRTDLL_time(time_t *timeptr)
{
time_t curtime = time(NULL);
if (timeptr)
*timeptr = curtime;
return curtime;
}
/*
* CRTDLL wide-char functions
*
* Copyright 1999 Alexandre Julliard
*/
#include "crtdll.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "winnls.h"
#include "wine/unicode.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
/*********************************************************************
* CRTDLL__wcsdup (CRTDLL.320)
*/
LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str )
{
LPWSTR ret = NULL;
if (str)
{
int size = (strlenW(str) + 1) * sizeof(WCHAR);
ret = CRTDLL_malloc( size );
if (ret) memcpy( ret, str, size );
}
return ret;
}
/*********************************************************************
* CRTDLL__wcsicoll (CRTDLL.322)
*/
INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
{
/* FIXME: handle collates */
return strcmpiW( str1, str2 );
}
/*********************************************************************
* CRTDLL__wcsnset (CRTDLL.325)
*/
LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n )
{
LPWSTR ret = str;
while ((n-- > 0) && *str) *str++ = c;
return ret;
}
/*********************************************************************
* CRTDLL__wcsrev (CRTDLL.326)
*/
LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str )
{
LPWSTR ret = str;
LPWSTR end = str + strlenW(str) - 1;
while (end > str)
{
WCHAR t = *end;
*end-- = *str;
*str++ = t;
}
return ret;
}
/*********************************************************************
* CRTDLL__wcsset (CRTDLL.327)
*/
LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c )
{
LPWSTR ret = str;
while (*str) *str++ = c;
return ret;
}
/*********************************************************************
* CRTDLL_wcscoll (CRTDLL.506)
*/
DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 )
{
/* FIXME: handle collates */
return strcmpW( str1, str2 );
}
/*********************************************************************
* CRTDLL_wcspbrk (CRTDLL.514)
*/
LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
{
LPCWSTR p;
while (*str)
{
for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
str++;
}
return NULL;
}
/*********************************************************************
* CRTDLL_wctomb (CRTDLL.524)
*/
INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch )
{
return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL );
}
/*********************************************************************
* CRTDLL_iswalnum (CRTDLL.405)
*/
INT __cdecl CRTDLL_iswalnum( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* CRTDLL_iswalpha (CRTDLL.406)
*/
INT __cdecl CRTDLL_iswalpha( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* CRTDLL_iswcntrl (CRTDLL.408)
*/
INT __cdecl CRTDLL_iswcntrl( WCHAR wc )
{
return get_char_typeW(wc) & C1_CNTRL;
}
/*********************************************************************
* CRTDLL_iswdigit (CRTDLL.410)
*/
INT __cdecl CRTDLL_iswdigit( WCHAR wc )
{
return get_char_typeW(wc) & C1_DIGIT;
}
/*********************************************************************
* CRTDLL_iswgraph (CRTDLL.411)
*/
INT __cdecl CRTDLL_iswgraph( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* CRTDLL_iswlower (CRTDLL.412)
*/
INT __cdecl CRTDLL_iswlower( WCHAR wc )
{
return get_char_typeW(wc) & C1_LOWER;
}
/*********************************************************************
* CRTDLL_iswprint (CRTDLL.413)
*/
INT __cdecl CRTDLL_iswprint( WCHAR wc )
{
return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
}
/*********************************************************************
* CRTDLL_iswpunct (CRTDLL.414)
*/
INT __cdecl CRTDLL_iswpunct( WCHAR wc )
{
return get_char_typeW(wc) & C1_PUNCT;
}
/*********************************************************************
* CRTDLL_iswspace (CRTDLL.415)
*/
INT __cdecl CRTDLL_iswspace( WCHAR wc )
{
return get_char_typeW(wc) & C1_SPACE;
}
/*********************************************************************
* CRTDLL_iswupper (CRTDLL.416)
*/
INT __cdecl CRTDLL_iswupper( WCHAR wc )
{
return get_char_typeW(wc) & C1_UPPER;
}
/*********************************************************************
* CRTDLL_iswxdigit (CRTDLL.417)
*/
INT __cdecl CRTDLL_iswxdigit( WCHAR wc )
{
return get_char_typeW(wc) & C1_XDIGIT;
}
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