- Implemented 73 CRT functions
- Reimplemented file I/O using Win32 calls
- Set errno/doserrno in most calls
diff --git a/dlls/crtdll/Makefile.in b/dlls/crtdll/Makefile.in
index dda4f9e..62e2703 100644
--- a/dlls/crtdll/Makefile.in
+++ b/dlls/crtdll/Makefile.in
@@ -8,7 +8,14 @@
C_SRCS = \
crtdll_main.c \
+ dir.c \
+ exit.c \
+ file.c \
mbstring.c \
+ memory.c \
+ spawn.c \
+ string.c \
+ time.c \
wcstring.c
@MAKE_DLL_RULES@
diff --git a/dlls/crtdll/crtdll.h b/dlls/crtdll/crtdll.h
index 9d731ff..a7f1cd4 100644
--- a/dlls/crtdll/crtdll.h
+++ b/dlls/crtdll/crtdll.h
@@ -1,7 +1,17 @@
#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
@@ -24,19 +34,324 @@
#define CRTDLL_LEADBYTE 0x8000
#define CRTDLL_ALPHA (0x0100|CRTDLL_UPPER|CRTDLL_LOWER)
-/* function prototypes used in crtdll.c */
-extern int LastErrorToErrno(DWORD);
+/* 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
-void __cdecl *CRTDLL_malloc( DWORD size );
-void __cdecl CRTDLL_free( void *ptr );
+/* _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
+/* _access() bit flags FIXME: incomplete */
+#define W_OK 2
+
+/* windows.h RAND_MAX is smaller than normal RAND_MAX */
+#define CRTDLL_RAND_MAX 0x7fff
+
+/* CRTDLL Globals */
+extern INT CRTDLL_doserrno;
+extern INT CRTDLL_errno;
+
+
+/* Binary compatable structures, types and defines used
+ * by CRTDLL. These should move to external header files,
+ * and in some cases need be renamed (CRTDLL_FILE!) to defs
+ * as used by lcc/bcc/watcom/vc++ etc, in order to get source
+ * compatability 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 EOF -1
+
+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 fpos_t;
+
+struct complex
+{
+ double real;
+ double imaginary;
+};
+
+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)(LPVOID *,LPVOID *);
+
+/* CRTDLL functions */
+
+/* CRTDLL_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 );
+
+/* CRTDLL_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);
+
+/* CRTDLL_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 );
+CRTDLL_FILE* __cdecl CRTDLL_fopen( LPCSTR path, LPCSTR mode );
+CRTDLL_FILE* __cdecl CRTDLL_freopen( LPCSTR path,LPCSTR mode,CRTDLL_FILE* f );
+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, LPSTR format, ... );
+INT __cdecl CRTDLL__filbuf( CRTDLL_FILE* file );
+INT __cdecl CRTDLL__fileno( CRTDLL_FILE* file );
+INT __cdecl CRTDLL__flsbuf( INT c, CRTDLL_FILE* file );
+INT __cdecl CRTDLL__fputchar( INT c );
+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, 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__read( INT fd, LPVOID buf, UINT count );
+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 );
+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__unlink( LPCSTR pathname );
+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__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 );
+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__isatty(INT fd);
+VOID __cdecl CRTDLL__beep( UINT freq, UINT duration );
+INT __cdecl CRTDLL_rand( VOID );
+UINT __cdecl CRTDLL__rotl( UINT x,INT shift );
+DWORD __cdecl CRTDLL__lrotl( DWORD x,INT shift );
+DWORD __cdecl CRTDLL__lrotr( DWORD x,INT shift );
+DWORD __cdecl CRTDLL__rotr( UINT x,INT shift );
+INT __cdecl CRTDLL__mbsicmp( unsigned char *x,unsigned char *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 );
+BOOL __cdecl CRTDLL__isctype( CHAR x,CHAR type );
+LPSTR __cdecl CRTDLL__fullpath( LPSTR buf, LPCSTR name, INT size );
+VOID __cdecl CRTDLL__splitpath( LPCSTR path, LPSTR drive, LPSTR directory,
+ LPSTR filename, LPSTR extension );
+LPINT __cdecl CRTDLL__errno( VOID );
+LPINT __cdecl CRTDLL___doserrno( VOID );
+LPCSTR**__cdecl CRTDLL__sys_errlist( VOID );
+VOID __cdecl CRTDLL_perror( LPCSTR err );
+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 );
+LPSTR __cdecl CRTDLL__mbsrchr( LPSTR s,CHAR x );
+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( LONG c );
+INT __cdecl CRTDLL___iscsymf( LONG 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, UINT );
+UINT __cdecl CRTDLL__controlfp( UINT, UINT );
+double __cdecl CRTDLL__copysign(double x, double sign);
+INT __cdecl CRTDLL__finite( 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 );
+
+/* CRTDLL_mem.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 );
+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 );
+
+/* CRTDLL_spawn.c */
+HANDLE __cdecl CRTDLL__spawnve( INT flags, LPSTR name, LPSTR *argv, LPSTR *envv);
+INT __cdecl CRTDLL_system( LPSTR x );
+
+/* CRTDLL_str.c */
+LPSTR __cdecl CRTDLL__strdec( LPSTR str1, LPSTR str2 );
+LPSTR __cdecl CRTDLL__strdup( LPCSTR ptr );
+LPSTR __cdecl CRTDLL__strinc( LPSTR 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 );
+
+/* CRTDLL_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 );
+
+/* wcstring.c */
INT __cdecl CRTDLL_iswalnum( WCHAR wc );
INT __cdecl CRTDLL_iswalpha( WCHAR wc );
INT __cdecl CRTDLL_iswcntrl( WCHAR wc );
@@ -48,35 +363,10 @@
INT __cdecl CRTDLL_iswspace( WCHAR wc );
INT __cdecl CRTDLL_iswupper( WCHAR wc );
INT __cdecl CRTDLL_iswxdigit( WCHAR wc );
-INT __cdecl CRTDLL_iswctype( WCHAR wc, WCHAR wct );
-INT __cdecl CRTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n );
-INT __cdecl CRTDLL_mbtowc( WCHAR *dst, LPCSTR str, INT n );
-DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 );
-LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept );
-INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch );
-#ifdef notyet
-#define _mbsinc CRTDLL__mbsinc
-#define _mbslen CRTDLL__mbslen
-#define _wcsdup CRTDLL__wcsdup
-#define _wcsicoll CRTDLL__wcsicoll
-#define _wcsnset CRTDLL__wcsnset
-#define _wcsrev CRTDLL__wcsrev
-#define _wcsset CRTDLL__wcsset
-#define iswalnum CRTDLL_iswalnum
-#define iswalpha CRTDLL_iswalpha
-#define iswcntrl CRTDLL_iswcntrl
-#define iswdigit CRTDLL_iswdigit
-#define iswgraph CRTDLL_iswgraph
-#define iswlower CRTDLL_iswlower
-#define iswprint CRTDLL_iswprint
-#define iswpunct CRTDLL_iswpunct
-#define iswspace CRTDLL_iswspace
-#define iswupper CRTDLL_iswupper
-#define iswxdigit CRTDLL_iswxdigit
-#define mbtowc CRTDLL_mbtowc
-#define wcscoll CRTDLL_wcscoll
-#define wctomb CRTDLL_wctomb
-#endif
+/* INTERNAL: Shared internal functions */
+void __CRTDLL__set_errno(ULONG err);
+LPSTR __CRTDLL__strndup(LPSTR buf, INT size);
+VOID __CRTDLL__init_io(VOID);
#endif /* __WINE_CRTDLL_H */
diff --git a/dlls/crtdll/crtdll.spec b/dlls/crtdll/crtdll.spec
index c29c186..0634435 100644
--- a/dlls/crtdll/crtdll.spec
+++ b/dlls/crtdll/crtdll.spec
@@ -33,47 +33,47 @@
@ extern __argc_dll CRTDLL_argc_dll
@ extern __argv_dll CRTDLL_argv_dll
@ cdecl __dllonexit() CRTDLL___dllonexit
-@ stub __doserrno
+@ cdecl __doserrno() CRTDLL___doserrno
@ stub __fpecode
-@ stub __isascii
-@ stub __iscsym
-@ stub __iscsymf
+@ cdecl __isascii(long) CRTDLL___isascii
+@ cdecl __iscsym(long) CRTDLL___iscsym
+@ cdecl __iscsymf(long) CRTDLL___iscsymf
@ stub __mb_cur_max_dll
@ stub __pxcptinfoptrs
@ cdecl __threadhandle() GetCurrentThread
@ cdecl __threadid() GetCurrentThreadId
-@ stub __toascii
+@ 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
-@ stub _amsg_exit
-@ stub _assert
+@ 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
-@ stub _beep
+@ cdecl _beep(long long) CRTDLL__beep
@ stub _beginthread
-@ stub _c_exit
-@ stub _cabs
-@ cdecl _cexit(long) CRTDLL__cexit
+@ cdecl _c_exit() CRTDLL__c_exit
+@ cdecl _cabs(long) CRTDLL__cabs
+@ cdecl _cexit() CRTDLL__cexit
@ stub _cgets
@ cdecl _chdir(str) CRTDLL__chdir
@ cdecl _chdrive(long) CRTDLL__chdrive
-@ stub _chgsign
+@ cdecl _chgsign(double) CRTDLL__chgsign
@ stub _chmod
@ stub _chsize
@ stub _clearfp
@ cdecl _close(long) CRTDLL__close
-@ stub _commit
+@ cdecl _commit(long) CRTDLL__commit
@ extern _commode_dll CRTDLL_commode_dll
-@ stub _control87
-@ stub _controlfp
-@ stub _copysign
+@ cdecl _control87(long long) CRTDLL__control87
+@ cdecl _controlfp(long long) CRTDLL__controlfp
+@ cdecl _copysign(double double) CRTDLL__copysign
@ stub _cprintf
@ stub _cpumode_dll
@ stub _cputs
-@ stub _creat
+@ cdecl _creat(str long) CTRDLL__creat
@ stub _cscanf
@ stub _ctype
@ stub _cwait
@@ -83,7 +83,7 @@
@ stub _ecvt
@ stub _endthread
@ extern _environ_dll CRTDLL_environ_dll
-@ stub _eof
+@ cdecl _eof(long) CRTDLL__eof
@ cdecl _errno() CRTDLL__errno
@ cdecl _except_handler2(ptr ptr ptr ptr) CRTDLL__except_handler2
@ stub _execl
@@ -94,45 +94,45 @@
@ stub _execve
@ stub _execvp
@ stub _execvpe
-@ stub _exit
-@ stub _expand
-@ stub _fcloseall
+@ cdecl _exit(long) CRTDLL__exit
+@ cdecl _expand(ptr long) CRTDLL__expand
+@ cdecl _fcloseall() CRTDLL__fcloseall
@ stub _fcvt
@ cdecl _fdopen(long ptr) CRTDLL__fdopen
-@ stub _fgetchar
+@ cdecl _fgetchar() CRTDLL__fgetchar
@ stub _fgetwchar
-@ stub _filbuf
+@ cdecl _filbuf(ptr) CRTDLL__filbuf
@ stub _fileinfo_dll
@ stub _filelength
-@ stub _fileno
-@ stub _findclose
+@ cdecl _fileno(ptr) CRTDLL__fileno
+@ cdecl _findclose(long) CRTDLL__findclose
@ cdecl _findfirst(str ptr) CRTDLL__findfirst
@ cdecl _findnext(long ptr) CRTDLL__findnext
-@ stub _finite
-@ stub _flsbuf
-@ stub _flushall
+@ cdecl _finite(double) CRTDLL__finite
+@ cdecl _flsbuf(long ptr) CRTDLL__flsbuf
+@ cdecl _flushall() CRTDLL__flushall
@ extern _fmode_dll CRTDLL_fmode_dll
@ stub _fpclass
@ stub _fpieee_flt
@ cdecl _fpreset() CRTDLL__fpreset
-@ stub _fputchar
+@ cdecl _fputchar(long) CRTDLL__fputchar
@ stub _fputwchar
@ cdecl _fsopen(str str long) CRTDLL__fsopen
@ cdecl _fstat(long ptr) CRTDLL__fstat
-@ stub _ftime
+@ cdecl _ftime(ptr) CRTDLL__ftime
@ forward _ftol ntdll._ftol
@ cdecl _fullpath(ptr str long) CRTDLL__fullpath
@ stub _futime
@ stub _gcvt
-@ stub _get_osfhandle
+@ cdecl _get_osfhandle(long) CRTDLL__get_osfhandle
@ stub _getch
@ stub _getche
@ cdecl _getcwd(ptr long) CRTDLL__getcwd
@ cdecl _getdcwd(long ptr long) CRTDLL__getdcwd
-@ stub _getdiskfree
-@ stub _getdllprocaddr
+@ cdecl _getdiskfree(long ptr) CRTDLL__getdiskfree
+@ forward _getdllprocaddr kernel32.GetProcAddress
@ cdecl _getdrive() CRTDLL__getdrive
-@ stub _getdrives
+@ forward _getdrives kernel32.GetLogicalDrives
@ stub _getpid
@ stub _getsystime
@ stub _getw
@@ -143,7 +143,7 @@
@ stub _heapwalk
@ cdecl _hypot(double double) hypot
@ cdecl _initterm(ptr ptr) CRTDLL__initterm
-@ extern _iob CRTDLL_iob
+@ extern _iob __CRTDLL_iob
@ cdecl _isatty(long) CRTDLL__isatty
@ cdecl _isctype(long long) CRTDLL__isctype
@ stub _ismbbalnum
@@ -171,29 +171,29 @@
@ stub _ismbcupper
@ stub _ismbslead
@ stub _ismbstrail
-@ stub _isnan
+@ cdecl _isnan(double) CRTDLL__isnan
@ forward _itoa ntdll._itoa
-@ stub _itow
-@ cdecl _j0(double) j0
-@ cdecl _j1(double) j1
-@ cdecl _jn(long double) jn
+@ cdecl _itow(long str long) CRTDLL__itow
+@ cdecl _j0(double) CRTDLL__j0
+@ cdecl _j1(double) CRTDLL__j1
+@ cdecl _jn(long double) CRTDLL__jn
@ stub _kbhit
@ stub _lfind
-@ stub _loaddll
+@ cdecl _loaddll(str) CRTDLL__loaddll
@ cdecl _local_unwind2(ptr long) CRTDLL__local_unwind2
@ stub _locking
@ stub _logb
@ cdecl _lrotl (long long) CRTDLL__lrotl
-@ stub _lrotr
-@ stub _lsearch
+@ 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
-@ stub _ltow
+@ cdecl _ltow(long str long) CRTDLL__ltow
@ cdecl _makepath (ptr str str str str) CRTDLL__makepath
@ stub _matherr
@ stub _mbbtombc
@ stub _mbbtype
-@ stub _mbccpy
+@ cdecl _mbccpy (str str) CRTDLL__mbccpy
@ stub _mbcjistojms
@ stub _mbcjmstojis
@ stub _mbclen
@@ -239,13 +239,13 @@
@ stub _mbstok
@ stub _mbstrlen
@ stub _mbsupr
-@ stub _memccpy
+@ cdecl _memccpy(ptr ptr long long) memccpy
@ forward _memicmp ntdll._memicmp
@ cdecl _mkdir(str) CRTDLL__mkdir
@ stub _mktemp
-@ stub _msize
+@ cdecl _msize(ptr) CRTDLL__msize
@ stub _nextafter
-@ stub _onexit
+@ 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
@@ -264,10 +264,10 @@
@ stub _putw
@ stub _pwctype_dll
@ cdecl _read(long ptr long) CRTDLL__read
-@ stub _rmdir
+@ cdecl _rmdir(str) CRTDLL__rmdir
@ stub _rmtmp
@ cdecl _rotl (long long) CRTDLL__rotl
-@ stub _rotr
+@ cdecl _rotr (long long) CRTDLL__rotr
@ stub _scalb
@ stub _searchenv
@ stub _seterrormode
@@ -283,7 +283,7 @@
@ stub _spawnlp
@ stub _spawnlpe
@ stub _spawnv
-@ stub _spawnve
+@ cdecl _spawnve(long str ptr ptr) CRTDLL__spawnve
@ stub _spawnvp
@ stub _spawnvpe
@ cdecl _splitpath (str ptr ptr ptr ptr) CRTDLL__splitpath
@@ -291,39 +291,39 @@
@ stub _statusfp
@ cdecl _strcmpi(str str) strcasecmp
@ cdecl _strdate(str) CRTDLL__strdate
-@ stub _strdec
+@ cdecl _strdec(str str) CRTDLL__strdec
@ cdecl _strdup(str) CRTDLL__strdup
-@ stub _strerror
+@ cdecl _strerror(long) CRTDLL__strerror
@ cdecl _stricmp(str str) strcasecmp
@ stub _stricoll
-@ stub _strinc
+@ cdecl _strinc(str) CRTDLL__strinc
@ forward _strlwr ntdll._strlwr
-@ stub _strncnt
+@ cdecl _strncnt(str long) CRTDLL__strncnt
@ stub _strnextc
@ cdecl _strnicmp(str str long) strncasecmp
-@ stub _strninc
-@ stub _strnset
-@ stub _strrev
-@ stub _strset
-@ stub _strspnp
+@ 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
-@ stub _swab
-@ stub _sys_errlist
-@ stub _sys_nerr_dll
-@ stub _tell
+@ 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
@ stub _timezone_dll
-@ stub _tolower
-@ stub _toupper
+@ cdecl _tolower(long) CRTDLL__toupper
+@ cdecl _toupper(long) CRTDLL__tolower
@ stub _tzname
@ stub _tzset
@ forward _ultoa ntdll._ultoa
-@ stub _ultow
-@ stub _umask
+@ cdecl _ultow(long str long) CRTDLL__ultow
+@ cdecl _umask(long) CRTDLL__umask
@ stub _ungetch
@ cdecl _unlink(str) CRTDLL__unlink
-@ stub _unloaddll
+@ cdecl _unloaddll(long) CRTDLL__unloaddll
@ stub _utime
@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
@ stub _vsnwprintf
@@ -345,7 +345,7 @@
@ cdecl _y0(double) y0
@ cdecl _y1(double) y1
@ cdecl _yn(long double) yn
-@ stub abort
+@ cdecl abort() CRTDLL_abort
@ cdecl abs(long) abs
@ cdecl acos(double) acos
@ cdecl asctime(ptr) asctime
@@ -359,7 +359,7 @@
@ cdecl bsearch(ptr ptr long long ptr) bsearch
@ cdecl calloc(long long) CRTDLL_calloc
@ cdecl ceil(double) ceil
-@ stub clearerr
+@ cdecl clearerr(ptr) CRTDLL_clearerr
@ cdecl clock() CRTDLL_clock
@ cdecl cos(double) cos
@ cdecl cosh(double) cosh
@@ -371,10 +371,10 @@
@ cdecl fabs(double) fabs
@ cdecl fclose(ptr) CRTDLL_fclose
@ cdecl feof(ptr) CRTDLL_feof
-@ stub ferror
+@ cdecl ferror(ptr) CRTDLL_ferror
@ cdecl fflush(ptr) CRTDLL_fflush
@ cdecl fgetc(ptr) CRTDLL_fgetc
-@ stub fgetpos
+@ cdecl fgetpos(ptr ptr) CRTDLL_fgetpos
@ cdecl fgets(ptr long ptr) CRTDLL_fgets
@ stub fgetwc
@ cdecl floor(double) floor
@@ -396,11 +396,11 @@
@ cdecl fwrite(ptr long long ptr) CRTDLL_fwrite
@ stub fwscanf
@ cdecl getc(ptr) CRTDLL_getc
-@ stub getchar
+@ cdecl getchar() CRTDLL_getchar
@ cdecl getenv (str) CRTDLL_getenv
@ cdecl gets(ptr) CRTDLL_gets
@ cdecl gmtime(ptr) gmtime
-@ stub is_wctype
+@ forward is_wctype ntdll.iswctype
@ cdecl isalnum(long) isalnum
@ cdecl isalpha(long) isalpha
@ cdecl iscntrl(long) iscntrl
@@ -414,7 +414,7 @@
@ cdecl isupper(long) isupper
@ cdecl iswalnum(long) CRTDLL_iswalnum
@ forward iswalpha ntdll.iswalpha
-@ stub iswascii
+@ cdecl iswascii(long) CRTDLL_iswascii
@ cdecl iswcntrl(long) CRTDLL_iswcntrl
@ forward iswctype ntdll.iswctype
@ cdecl iswdigit(long) CRTDLL_iswdigit
@@ -445,7 +445,7 @@
@ cdecl memset(ptr long long) memset
@ cdecl mktime(ptr) mktime
@ cdecl modf(double ptr) modf
-@ stub perror
+@ cdecl perror(str) CRTDLL_perror
@ cdecl pow(double double) pow
@ varargs printf() printf
@ cdecl putc(long ptr) CRTDLL_putc
@@ -457,7 +457,7 @@
@ cdecl realloc(ptr long) CRTDLL_realloc
@ cdecl remove(str) CRTDLL_remove
@ cdecl rename(str str) CRTDLL_rename
-@ stub rewind
+@ cdecl rewind(ptr) CRTDLL_rewind
@ stub scanf
@ cdecl setbuf(ptr ptr) CRTDLL_setbuf
@ cdecl setlocale(long ptr) CRTDLL_setlocale
@@ -475,7 +475,7 @@
@ cdecl strcoll(str str) strcoll
@ cdecl strcpy(ptr str) strcpy
@ cdecl strcspn(str str) strcspn
-@ cdecl strerror(long) strerror
+@ cdecl strerror(long) CRTDLL_strerror
@ cdecl strftime(ptr long str ptr) strftime
@ cdecl strlen(str) strlen
@ cdecl strncat(str str long) strncat
diff --git a/dlls/crtdll/crtdll_main.c b/dlls/crtdll/crtdll_main.c
index 993669d..7422e3b 100644
--- a/dlls/crtdll/crtdll_main.c
+++ b/dlls/crtdll/crtdll_main.c
@@ -6,19 +6,13 @@
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997,2000 Uwe Bonnes
+ * Copyright 2000 Jon Griffiths
*/
/*
Unresolved issues Uwe Bonnes 970904:
-- Handling of Binary/Text Files is crude. If in doubt, use fromdos or recode
-- Arguments in crtdll.spec for functions with double argument
-- system-call calls another wine process, but without debugging arguments
- and uses the first wine executable in the path
- tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
for Win32, based on lcc, from Jacob Navia
-AJ 990101:
-- needs a proper stdio emulation based on Win32 file handles
-- should set CRTDLL errno from GetLastError() in every function
UB 000416:
- probably not thread safe
*/
@@ -28,50 +22,29 @@
* since we need 2 byte wide characters. - Marcus Meissner, 981031
*/
-#include "config.h"
-
+#include "crtdll.h"
+#include <ctype.h>
+#define __USE_ISOC9X 1 /* for isfinite */
+#include <math.h>
#include <errno.h>
#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/times.h>
-#include <unistd.h>
-#include <time.h>
-#include <ctype.h>
-#include <math.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#include "winbase.h"
-#include "windef.h"
+#include "file.h"
+#include "ntddk.h"
#include "wingdi.h"
#include "winuser.h"
-#include "winerror.h"
-#include "ntddk.h"
-#include "debugtools.h"
-#include "heap.h"
-#include "crtdll.h"
-#include "drive.h"
-#include "file.h"
-#include "options.h"
-#include "winnls.h"
+
DEFAULT_DEBUG_CHANNEL(crtdll);
-/* windows.h RAND_MAX is smaller than normal RAND_MAX */
-#define CRTDLL_RAND_MAX 0x7fff
-
-static DOS_FULL_NAME CRTDLL_tmpname;
UINT CRTDLL_argc_dll; /* CRTDLL.23 */
-LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
-LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
+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 */
+LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
@@ -81,59 +54,83 @@
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;
+const INT CRTDLL__sys_nerr = 43;
-/* FIXME: structure layout is obviously not correct */
-typedef struct
-{
- HANDLE handle;
- int pad[7];
-} CRTDLL_FILE;
-
-CRTDLL_FILE CRTDLL_iob[3];
-
-static CRTDLL_FILE * const CRTDLL_stdin = &CRTDLL_iob[0];
-static CRTDLL_FILE * const CRTDLL_stdout = &CRTDLL_iob[1];
-static CRTDLL_FILE * const CRTDLL_stderr = &CRTDLL_iob[2];
-
-typedef VOID (*new_handler_type)(VOID);
-
-static new_handler_type new_handler;
-
-CRTDLL_FILE * __cdecl CRTDLL__fdopen(INT handle, LPCSTR mode);
-INT __cdecl CRTDLL_fgetc( CRTDLL_FILE *file );
/*********************************************************************
* CRTDLL_MainInit (CRTDLL.init)
*/
-BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+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__fdopen(0,"r");
- CRTDLL__fdopen(1,"w");
- CRTDLL__fdopen(2,"w");
+ __CRTDLL__init_io();
}
return TRUE;
}
-/*********************************************************************
- * malloc (CRTDLL.427)
- */
-VOID* __cdecl CRTDLL_malloc(DWORD size)
+
+/* INTERNAL: Set the crt and dos errno's from the OS error given. */
+void __CRTDLL__set_errno(ULONG err)
{
- return HeapAlloc(GetProcessHeap(),0,size);
+ /* 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;
+ }
}
-/*********************************************************************
- * _strdup (CRTDLL.285)
- */
-LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr)
-{
- LPSTR ret = CRTDLL_malloc(strlen(ptr)+1);
- if (ret) strcpy( ret, ptr );
- return ret;
-}
/*********************************************************************
* _GetMainArgs (CRTDLL.022)
@@ -215,56 +212,6 @@
}
-typedef void (*_INITTERMFUN)();
-
-/* fixme: move to header */
-struct find_t
-{ unsigned attrib;
- time_t time_create; /* -1 when not avaiable */
- time_t time_access; /* -1 when not avaiable */
- time_t time_write;
- unsigned long size; /* fixme: 64 bit ??*/
- char name[260];
-};
- /*********************************************************************
- * _findfirst (CRTDLL.099)
- *
- * BUGS
- * Unimplemented
- */
-DWORD __cdecl CRTDLL__findfirst(LPCSTR fname, struct find_t * x2)
-{
- FIXME(":(%s,%p): stub\n",fname,x2);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
-
-/*********************************************************************
- * _findnext (CRTDLL.100)
- *
- * BUGS
- * Unimplemented
- */
-INT __cdecl CRTDLL__findnext(DWORD hand, struct find_t * x2)
-{
- FIXME(":(%ld,%p): stub\n",hand,x2);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
-
-/*********************************************************************
- * _fstat (CRTDLL.111)
- *
- * BUGS
- * Unimplemented
- */
-int __cdecl CRTDLL__fstat(int file, struct stat* buf)
-{
- FIXME(":(%d,%p): stub\n",file,buf);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
-
/*********************************************************************
* _initterm (CRTDLL.135)
*/
@@ -281,45 +228,6 @@
return 0;
}
-/*********************************************************************
- * _fsopen (CRTDLL.110)
- */
-CRTDLL_FILE * __cdecl CRTDLL__fsopen(LPCSTR x, LPCSTR y, INT z) {
- FIXME("(%s,%s,%d),stub!\n",x,y,z);
- return NULL;
-}
-
-/*********************************************************************
- * _fdopen (CRTDLL.91)
- */
-CRTDLL_FILE * __cdecl CRTDLL__fdopen(INT handle, LPCSTR mode)
-{
- CRTDLL_FILE *file;
-
- switch (handle)
- {
- case 0:
- file = CRTDLL_stdin;
- if (!file->handle) file->handle = GetStdHandle( STD_INPUT_HANDLE );
- break;
- case 1:
- file = CRTDLL_stdout;
- if (!file->handle) file->handle = GetStdHandle( STD_OUTPUT_HANDLE );
- break;
- case 2:
- file=CRTDLL_stderr;
- if (!file->handle) file->handle = GetStdHandle( STD_ERROR_HANDLE );
- break;
- default:
- file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
- file->handle = handle;
- break;
- }
- TRACE("open handle %d mode %s got file %p\n",
- handle, mode, file);
- return file;
-}
-
/*******************************************************************
* _global_unwind2 (CRTDLL.129)
@@ -329,6 +237,7 @@
RtlUnwind( frame, 0, NULL, 0 );
}
+
/*******************************************************************
* _local_unwind2 (CRTDLL.173)
*/
@@ -336,6 +245,8 @@
{
TRACE("(%p,%ld)\n",endframe,nr);
}
+
+
/*******************************************************************
* _setjmp (CRTDLL.264)
*/
@@ -345,344 +256,6 @@
return 0;
}
-/*********************************************************************
- * fopen (CRTDLL.372)
- */
-CRTDLL_FILE * __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
-{
- CRTDLL_FILE *file = NULL;
- HFILE handle;
-#if 0
- DOS_FULL_NAME full_name;
-
- if (!DOSFS_GetFullName( path, FALSE, &full_name )) {
- WARN("file %s bad name\n",path);
- return 0;
- }
-
- file=fopen(full_name.long_name ,mode);
-#endif
- DWORD access = 0, creation = 0;
-
- if ((strchr(mode,'r')&&strchr(mode,'a'))||
- (strchr(mode,'r')&&strchr(mode,'w'))||
- (strchr(mode,'w')&&strchr(mode,'a')))
- return NULL;
-
- if (mode[0] == 'r')
- {
- access = GENERIC_READ;
- creation = OPEN_EXISTING;
- if (mode[1] == '+') access |= GENERIC_WRITE;
- }
- else if (mode[0] == 'w')
- {
- access = GENERIC_WRITE;
- creation = CREATE_ALWAYS;
- if (mode[1] == '+') access |= GENERIC_READ;
- }
- else if (mode[0] == 'a')
- {
- access = GENERIC_WRITE;
- creation = OPEN_ALWAYS;
- if (mode[1] == '+') access |= GENERIC_READ;
- }
- /* FIXME: should handle text/binary mode */
-
- if ((handle = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, creation, FILE_ATTRIBUTE_NORMAL,
- -1 )) != INVALID_HANDLE_VALUE)
- {
- file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
- file->handle = handle;
- }
- TRACE("file %s mode %s got handle %d file %p\n",
- path,mode,handle,file);
- if (mode[0] == 'a')
- {
- /* if appending, seek to end of file */
- SetFilePointer( handle, 0, NULL, FILE_END );
- }
- return file;
-}
-
-/*********************************************************************
- * fread (CRTDLL.377)
- */
-DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT size, INT nmemb, CRTDLL_FILE *file)
-{
-#if 0
- int i=0;
- void *temp=ptr;
-
- /* If we would honour CR/LF <-> LF translation, we could do it like this.
- We should keep track of all files opened, and probably files with \
- known binary extensions must be unchanged */
- while ( (i < (nmemb*size)) && (ret==1)) {
- ret=fread(temp,1,1,file);
- TRACE("got %c 0x%02x ret %d\n",
- (isalpha(*(unsigned char*)temp))? *(unsigned char*)temp:
- ' ',*(unsigned char*)temp, ret);
- if (*(unsigned char*)temp != 0xd) { /* skip CR */
- temp++;
- i++;
- }
- else
- TRACE("skipping ^M\n");
- }
- TRACE("0x%08x items of size %d from file %p to %p\n",
- nmemb,size,file,ptr,);
- if(i!=nmemb)
- WARN(" failed!\n");
-
- return i;
-#else
- DWORD ret;
-
- TRACE("0x%08x items of size %d from file %p to %p\n",
- nmemb,size,file,ptr);
- if (!ReadFile( file->handle, ptr, size * nmemb, &ret, NULL ))
- WARN(" failed!\n");
-
- return ret / size;
-#endif
-}
-/*********************************************************************
- * freopen (CRTDLL.379)
- *
- * BUGS
- * Unimplemented
- */
-DWORD __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode, LPVOID stream)
-{
- FIXME(":(%s,%s,%p): stub\n", path, mode, stream);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
-}
-
-/*********************************************************************
- * fscanf (CRTDLL.381)
- */
-INT __cdecl CRTDLL_fscanf( CRTDLL_FILE *stream, LPSTR format, ... )
-{
- INT rd = 0;
- int nch;
- va_list ap;
- if (!*format) return 0;
- WARN("%p (\"%s\"): semi-stub\n", stream, format);
- nch = CRTDLL_fgetc(stream);
- va_start(ap, format);
- while (*format) {
- if (*format == ' ') {
- /* skip whitespace */
- while ((nch!=EOF) && isspace(nch))
- nch = CRTDLL_fgetc(stream);
- }
- 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!=EOF) && isspace(nch))
- nch = CRTDLL_fgetc(stream);
- /* get sign and first digit */
- if (nch == '-') {
- nch = CRTDLL_fgetc(stream);
- if (isdigit(nch))
- cur = -(nch - '0');
- else break;
- } else {
- if (isdigit(nch))
- cur = nch - '0';
- else break;
- }
- nch = CRTDLL_fgetc(stream);
- /* read until no more digits */
- while ((nch!=EOF) && isdigit(nch)) {
- cur = cur*10 + (nch - '0');
- nch = CRTDLL_fgetc(stream);
- }
- st = 1;
- *val = cur;
- }
- break;
- case 'f': { /* read a float */
- float*val = va_arg(ap, float*);
- float cur = 0;
- /* skip initial whitespace */
- while ((nch!=EOF) && isspace(nch))
- nch = CRTDLL_fgetc(stream);
- /* get sign and first digit */
- if (nch == '-') {
- nch = CRTDLL_fgetc(stream);
- if (isdigit(nch))
- cur = -(nch - '0');
- else break;
- } else {
- if (isdigit(nch))
- cur = nch - '0';
- else break;
- }
- /* read until no more digits */
- while ((nch!=EOF) && isdigit(nch)) {
- cur = cur*10 + (nch - '0');
- nch = CRTDLL_fgetc(stream);
- }
- if (nch == '.') {
- /* handle decimals */
- float dec = 1;
- nch = CRTDLL_fgetc(stream);
- while ((nch!=EOF) && isdigit(nch)) {
- dec /= 10;
- cur += dec * (nch - '0');
- nch = CRTDLL_fgetc(stream);
- }
- }
- st = 1;
- *val = cur;
- }
- break;
- case 's': { /* read a word */
- char*str = va_arg(ap, char*);
- char*sptr = str;
- /* skip initial whitespace */
- while ((nch!=EOF) && isspace(nch))
- nch = CRTDLL_fgetc(stream);
- /* read until whitespace */
- while ((nch!=EOF) && !isspace(nch)) {
- *sptr++ = nch; st++;
- nch = CRTDLL_fgetc(stream);
- }
- /* 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(stream);
- else break;
- }
- format++;
- }
- va_end(ap);
- if (nch!=EOF) {
- WARN("need ungetch\n");
- }
- TRACE("returning %d\n", rd);
- return rd;
-}
-
-/*********************************************************************
- * _lseek (CRTDLL.179)
- */
-LONG __cdecl CRTDLL__lseek( INT fd, LONG offset, INT whence)
-{
- 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");
- return SetFilePointer( fd, offset, NULL, whence );
-}
-
-/*********************************************************************
- * fseek (CRTDLL.382)
- */
-LONG __cdecl CRTDLL_fseek( CRTDLL_FILE *file, LONG offset, INT whence)
-{
- TRACE("file %p to 0x%08lx pos %s\n",
- file,offset,(whence==SEEK_SET)?"SEEK_SET":
- (whence==SEEK_CUR)?"SEEK_CUR":
- (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
- if (SetFilePointer( file->handle, offset, NULL, whence ) != 0xffffffff)
- return 0;
- WARN(" failed!\n");
- return -1;
-}
-
-/*********************************************************************
- * fsetpos (CRTDLL.383)
- */
-INT __cdecl CRTDLL_fsetpos( CRTDLL_FILE *file, INT *pos )
-{
- TRACE("file %p pos %d\n", file, *pos );
- return CRTDLL_fseek(file, *pos, SEEK_SET);
-}
-
-/*********************************************************************
- * ftell (CRTDLL.384)
- */
-LONG __cdecl CRTDLL_ftell( CRTDLL_FILE *file )
-{
- return SetFilePointer( file->handle, 0, NULL, SEEK_CUR );
-}
-
-/*********************************************************************
- * fwrite (CRTDLL.386)
- */
-DWORD __cdecl CRTDLL_fwrite( LPVOID ptr, INT size, INT nmemb, CRTDLL_FILE *file )
-{
- DWORD ret;
-
- TRACE("0x%08x items of size %d to file %p(%d) from %p\n",
- nmemb,size,file,file-(CRTDLL_FILE*)CRTDLL_iob,ptr);
-
-
- if (!WriteFile( file->handle, ptr, size * nmemb, &ret, NULL ))
- WARN(" failed!\n");
- return ret / size;
-}
-
-/*********************************************************************
- * setbuf (CRTDLL.452)
- */
-INT __cdecl CRTDLL_setbuf(CRTDLL_FILE *file, LPSTR buf)
-{
- TRACE("(file %p buf %p)\n", file, buf);
- /* this doesn't work:"void value not ignored as it ought to be"
- return setbuf(file,buf);
- */
- /* FIXME: no buffering for now */
- return 0;
-}
-
-/*********************************************************************
- * _open_osfhandle (CRTDLL.240)
- */
-HFILE __cdecl CRTDLL__open_osfhandle(LONG osfhandle, INT flags)
-{
-HFILE handle;
-
- switch (osfhandle) {
- case STD_INPUT_HANDLE :
- case 0 :
- handle=0;
- break;
- case STD_OUTPUT_HANDLE:
- case 1:
- handle=1;
- break;
- case STD_ERROR_HANDLE:
- case 2:
- handle=2;
- break;
- default:
- return (-1);
- }
- TRACE("(handle %08lx,flags %d) return %d\n",
- osfhandle,flags,handle);
- return handle;
-
-}
/*********************************************************************
* srand (CRTDLL.460)
@@ -693,183 +266,24 @@
srand(seed);
}
-/*********************************************************************
- * vfprintf (CRTDLL.373)
- */
-INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE *file, LPSTR format, va_list args )
-{
- char buffer[2048]; /* FIXME... */
-
- vsprintf( buffer, format, args );
- return CRTDLL_fwrite( buffer, 1, strlen(buffer), file );
-}
/*********************************************************************
- * fprintf (CRTDLL.373)
- */
-INT __cdecl CRTDLL_fprintf( CRTDLL_FILE *file, LPSTR format, ... )
-{
- va_list valist;
- INT res;
-
- va_start( valist, format );
- res = CRTDLL_vfprintf( file, format, valist );
- va_end( valist );
- return res;
-}
-
-/*********************************************************************
- * time (CRTDLL.488)
- */
-time_t __cdecl CRTDLL_time(time_t *timeptr)
-{
- time_t curtime = time(NULL);
-
- if (timeptr)
- *timeptr = curtime;
- return curtime;
-}
-
-/*********************************************************************
- * difftime (CRTDLL.357)
- */
-double __cdecl CRTDLL_difftime (time_t time1, time_t time2)
-{
- double timediff;
-
- timediff = (double)(time1 - time2);
- return timediff;
-}
-
-/*********************************************************************
- * 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;
-}
-
-/*********************************************************************
- * _isatty (CRTDLL.137)
- */
-BOOL __cdecl CRTDLL__isatty(DWORD x)
-{
- TRACE("(%ld)\n",x);
- return TRUE;
-}
-
-/*********************************************************************
- * _read (CRTDLL.256)
+ * _beep (CRTDLL.045)
*
- */
-INT __cdecl CRTDLL__read(INT fd, LPVOID buf, UINT count)
-{
- TRACE("0x%08x bytes fd %d to %p\n", count,fd,buf);
- if (!fd) fd = GetStdHandle( STD_INPUT_HANDLE );
- return _lread( fd, buf, count );
-}
-
-/*********************************************************************
- * _write (CRTDLL.332)
- */
-INT __cdecl CRTDLL__write(INT fd,LPCVOID buf,UINT count)
-{
- INT len=0;
-
- if (fd == -1)
- len = -1;
- else if (fd<=2)
- len = (UINT)write(fd,buf,(LONG)count);
- else
- len = _lwrite(fd,buf,count);
- TRACE("%d/%d byte to dfh %d from %p,\n",
- len,count,fd,buf);
- return len;
-}
-
-
-/*********************************************************************
- * _cexit (CRTDLL.49)
+ * Output a tone using the PC speaker.
*
- * FIXME: What the heck is the difference between
- * FIXME _c_exit (CRTDLL.47)
- * FIXME _cexit (CRTDLL.49)
- * FIXME _exit (CRTDLL.87)
- * FIXME exit (CRTDLL.359)
+ * PARAMS
+ * freq [in] Frequency of the tone
*
- * atexit-processing comes to mind -- MW.
+ * duration [in] Length of time the tone should sound
*
+ * RETURNS
+ * None.
*/
-void __cdecl CRTDLL__cexit(INT ret)
+void __cdecl CRTDLL__beep( UINT freq, UINT duration)
{
- TRACE("(%d)\n",ret);
- ExitProcess(ret);
-}
-
-
-/*********************************************************************
- * exit (CRTDLL.359)
- */
-void __cdecl CRTDLL_exit(DWORD ret)
-{
- TRACE("(%ld)\n",ret);
- ExitProcess(ret);
-}
-
-
-/*********************************************************************
- * _abnormal_termination (CRTDLL.36)
- */
-INT __cdecl CRTDLL__abnormal_termination(void)
-{
- TRACE("(void)\n");
- return 0;
-}
-
-
-/*********************************************************************
- * _access (CRTDLL.37)
- */
-INT __cdecl CRTDLL__access(LPCSTR filename, INT mode)
-{
- DWORD attr = GetFileAttributesA(filename);
-
- if (attr == -1)
- {
- if (GetLastError() == ERROR_INVALID_ACCESS)
- errno = EACCES;
- else
- errno = ENOENT;
- return -1;
- }
-
- if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
- {
- errno = EACCES;
- return -1;
- }
- else
- return 0;
-}
-
-
-/*********************************************************************
- * fflush (CRTDLL.365)
- */
-INT __cdecl CRTDLL_fflush( CRTDLL_FILE *file )
-{
- return FlushFileBuffers( file->handle ) ? 0 : -1;
+ TRACE(":Freq %d, Duration %d\n",freq,duration);
+ Beep(freq, duration);
}
@@ -883,173 +297,50 @@
/*********************************************************************
- * fputc (CRTDLL.374)
- */
-INT __cdecl CRTDLL_fputc( INT c, CRTDLL_FILE *file )
-{
- char ch = (char)c;
- DWORD res;
- TRACE("%c to file %p\n",c,file);
- if (!WriteFile( file->handle, &ch, 1, &res, NULL )) return -1;
- return c;
-}
-
-
-/*********************************************************************
- * putchar (CRTDLL.442)
- */
-void __cdecl CRTDLL_putchar( INT x )
-{
- CRTDLL_fputc( x, CRTDLL_stdout );
-}
-
-
-/*********************************************************************
- * fputs (CRTDLL.375)
- */
-INT __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE *file )
-{
- DWORD res;
- TRACE("%s to file %p\n",s,file);
- if (!WriteFile( file->handle, s, strlen(s), &res, NULL )) return -1;
- return res;
-}
-
-
-/*********************************************************************
- * puts (CRTDLL.443)
- */
-INT __cdecl CRTDLL_puts(LPCSTR s)
-{
- TRACE("%s \n",s);
- return CRTDLL_fputs(s, CRTDLL_stdout);
-}
-
-
-/*********************************************************************
- * putc (CRTDLL.441)
- */
-INT __cdecl CRTDLL_putc( INT c, CRTDLL_FILE *file )
-{
- return CRTDLL_fputc( c, file );
-}
-
-/*********************************************************************
- * fgetc (CRTDLL.366)
- */
-INT __cdecl CRTDLL_fgetc( CRTDLL_FILE *file )
-{
- DWORD res;
- char ch;
- if (!ReadFile( file->handle, &ch, 1, &res, NULL )) return -1;
- if (res != 1) return -1;
- return ch;
-}
-
-
-/*********************************************************************
- * getc (CRTDLL.388)
- */
-INT __cdecl CRTDLL_getc( CRTDLL_FILE *file )
-{
- return CRTDLL_fgetc( file );
-}
-
-
-/*********************************************************************
- * fgets (CRTDLL.368)
- */
-CHAR* __cdecl CRTDLL_fgets( LPSTR s, INT size, CRTDLL_FILE *file )
-{
- int cc;
- LPSTR buf_start = s;
-
- /* BAD, for the whole WINE process blocks... just done this way to test
- * windows95's ftp.exe.
- */
-
- for(cc = CRTDLL_fgetc(file); cc != EOF && cc != '\n'; cc = CRTDLL_fgetc(file))
- if (cc != '\r')
- {
- if (--size <= 0) break;
- *s++ = (char)cc;
- }
- if ((cc == EOF) &&(s == buf_start)) /* If nothing read, return 0*/
- return 0;
- if (cc == '\n')
- if (--size > 0)
- *s++ = '\n';
- *s = '\0';
-
- TRACE("got '%s'\n", buf_start);
- return buf_start;
-}
-
-
-/*********************************************************************
- * 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.
- */
-
- for(cc = CRTDLL_fgetc(CRTDLL_stdin); cc != 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;
-}
-
-
-/*********************************************************************
* _rotl (CRTDLL.259)
*/
UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
{
unsigned int ret = (x >> shift)|( x >>((sizeof(x))-shift));
- TRACE("got 0x%08x rot %d ret 0x%08x\n",
- x,shift,ret);
+ TRACE("got 0x%08x rot %d ret 0x%08x\n", x,shift,ret);
return ret;
-
}
+
+
/*********************************************************************
- * _lrotl (CRTDLL.176)
+ * _lrotl (CRTDLL.175)
*/
DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
{
unsigned long ret = (x >> shift)|( x >>((sizeof(x))-shift));
- TRACE("got 0x%08lx rot %d ret 0x%08lx\n",
- x,shift,ret);
+ TRACE("got 0x%08lx rot %d ret 0x%08lx\n", x,shift,ret);
return ret;
-
}
/*********************************************************************
- * _mbsicmp (CRTDLL.204)
+ * _lrotr (CRTDLL.176)
*/
-int __cdecl CRTDLL__mbsicmp(unsigned char *x,unsigned char *y)
+DWORD __cdecl CRTDLL__lrotr(DWORD x,INT shift)
{
- do {
- if (!*x)
- return !!*y;
- if (!*y)
- return !!*x;
- /* FIXME: MBCS handling... */
- if (*x!=*y)
- return 1;
- x++;
- y++;
- } while (1);
+ /* Depends on "long long" being 64 bit or greater */
+ unsigned long long arg = x;
+ unsigned long long ret = (arg << 32 | (x & 0xFFFFFFFF)) >> (shift & 0x1f);
+ return ret & 0xFFFFFFFF;
+}
+
+
+/*********************************************************************
+ * _rotr (CRTDLL.258)
+ */
+DWORD __cdecl CRTDLL__rotr(UINT x,INT shift)
+{
+ /* Depends on "long long" being 64 bit or greater */
+ unsigned long long arg = x;
+ unsigned long long ret = (arg << 32 | (x & 0xFFFFFFFF)) >> (shift & 0x1f);
+ return ret & 0xFFFFFFFF;
}
@@ -1063,50 +354,6 @@
/*********************************************************************
- * system (CRTDLL.485)
- */
-INT __cdecl CRTDLL_system(LPSTR x)
-{
-#define SYSBUF_LENGTH 1500
- char buffer[SYSBUF_LENGTH];
- unsigned char *y = x;
- unsigned char *bp;
- int i;
-
- sprintf( buffer, "%s \"", argv0 );
- bp = buffer + strlen(buffer);
- i = strlen(buffer) + strlen(x) +2;
-
- /* Calculate needed buffer size to prevent overflow. */
- while (*y) {
- if (*y =='\\') i++;
- y++;
- }
- /* If buffer too short, exit. */
- if (i > SYSBUF_LENGTH) {
- TRACE("_system buffer to small\n");
- return 127;
- }
-
- y =x;
-
- while (*y) {
- *bp = *y;
- bp++; y++;
- if (*(y-1) =='\\') *bp++ = '\\';
- }
- /* Remove spaces from end of string. */
- while (*(y-1) == ' ') {
- bp--;y--;
- }
- *bp++ = '"';
- *bp = 0;
- TRACE("_system got '%s', executing '%s'\n",x,buffer);
-
- return system(buffer);
-}
-
-/*********************************************************************
* longjmp (CRTDLL.426)
*/
VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
@@ -1115,322 +362,51 @@
longjmp(env, val);
}
-/*********************************************************************
- * new (CRTDLL.001)
- */
-VOID* __cdecl CRTDLL_new(DWORD size)
-{
- VOID* result;
- if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
- (*new_handler)();
- return result;
-}
-
-/*********************************************************************
- * 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;
-}
-
-/*********************************************************************
- * calloc (CRTDLL.350)
- */
-VOID* __cdecl CRTDLL_calloc(DWORD size, DWORD count)
-{
- return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
-}
-
-/*********************************************************************
- * realloc (CRTDLL.447)
- */
-VOID* __cdecl CRTDLL_realloc( VOID *ptr, DWORD size )
-{
- return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
-}
-
-/*********************************************************************
- * free (CRTDLL.427)
- */
-VOID __cdecl CRTDLL_free(LPVOID ptr)
-{
- HeapFree(GetProcessHeap(),0,ptr);
-}
-
-/*********************************************************************
- * delete (CRTDLL.002)
- */
-VOID __cdecl CRTDLL_delete(VOID* ptr)
-{
- HeapFree(GetProcessHeap(),0,ptr);
-}
-
-/*********************************************************************
- * fclose (CRTDLL.362)
- */
-INT __cdecl CRTDLL_fclose( CRTDLL_FILE *file )
-{
- TRACE("%p\n", file );
- if (!CloseHandle( file->handle )) return -1;
- HeapFree( GetProcessHeap(), 0, file );
- return 0;
-}
-
-/*********************************************************************
- * _unlink (CRTDLL.315)
- */
-INT __cdecl CRTDLL__unlink(LPCSTR pathname)
-{
- return DeleteFileA( pathname ) ? 0 : -1;
-}
-
-/*********************************************************************
- * rename (CRTDLL.449)
- */
-INT __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath)
-{
- BOOL ok = MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING );
- return ok ? 0 : -1;
-}
-
-
-/*********************************************************************
- * _stat (CRTDLL.280)
- */
-
-struct win_stat
-{
- UINT16 win_st_dev;
- UINT16 win_st_ino;
- UINT16 win_st_mode;
- INT16 win_st_nlink;
- INT16 win_st_uid;
- INT16 win_st_gid;
- UINT win_st_rdev;
- INT win_st_size;
- INT win_st_atime;
- INT win_st_mtime;
- INT win_st_ctime;
-};
-
-int __cdecl CRTDLL__stat(const char * filename, struct win_stat * buf)
-{
- int ret=0;
- DOS_FULL_NAME full_name;
- struct stat mystat;
-
- if (!DOSFS_GetFullName( filename, TRUE, &full_name ))
- {
- WARN("CRTDLL__stat filename %s bad name\n",filename);
- return -1;
- }
- ret=stat(full_name.long_name,&mystat);
- TRACE("CRTDLL__stat %s\n", filename);
- if(ret)
- WARN(" Failed!\n");
-
- /* FIXME: should check what Windows returns */
-
- buf->win_st_dev = mystat.st_dev;
- buf->win_st_ino = mystat.st_ino;
- buf->win_st_mode = mystat.st_mode;
- buf->win_st_nlink = mystat.st_nlink;
- buf->win_st_uid = mystat.st_uid;
- buf->win_st_gid = mystat.st_gid;
- buf->win_st_rdev = mystat.st_rdev;
- buf->win_st_size = mystat.st_size;
- buf->win_st_atime = mystat.st_atime;
- buf->win_st_mtime = mystat.st_mtime;
- buf->win_st_ctime = mystat.st_ctime;
- return ret;
-}
-
-/*********************************************************************
- * _open (CRTDLL.239)
- */
-HFILE __cdecl CRTDLL__open(LPCSTR path,INT flags)
-{
- DWORD access = 0, creation = 0;
- HFILE ret;
-
- /* FIXME:
- the flags in lcc's header differ from the ones in Linux, e.g.
- Linux: define O_APPEND 02000 (= 0x400)
- lcc: define _O_APPEND 0x0008
- so here a scheme to translate them
- Probably lcc is wrong here, but at least a hack to get is going
- */
- switch(flags & 3)
- {
- case O_RDONLY: access |= GENERIC_READ; break;
- case O_WRONLY: access |= GENERIC_WRITE; break;
- case O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
- }
-
- if (flags & 0x0100) /* O_CREAT */
- {
- if (flags & 0x0400) /* O_EXCL */
- creation = CREATE_NEW;
- else if (flags & 0x0200) /* O_TRUNC */
- creation = CREATE_ALWAYS;
- else
- creation = OPEN_ALWAYS;
- }
- else /* no O_CREAT */
- {
- if (flags & 0x0200) /* O_TRUNC */
- creation = TRUNCATE_EXISTING;
- else
- creation = OPEN_EXISTING;
- }
- if (flags & 0x0008) /* O_APPEND */
- FIXME("O_APPEND not supported\n" );
- if (!(flags & 0x8000 /* O_BINARY */ ) || (flags & 0x4000 /* O_TEXT */))
- FIXME(":text mode not supported\n");
- if (flags & 0xf0f4)
- TRACE("CRTDLL_open file unsupported flags 0x%04x\n",flags);
- /* End Fixme */
-
- ret = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, creation, FILE_ATTRIBUTE_NORMAL, -1 );
- TRACE("CRTDLL_open file %s mode 0x%04x got handle %d\n", path,flags,ret);
- return ret;
-}
-
-/*********************************************************************
- * _close (CRTDLL.57)
- */
-INT __cdecl CRTDLL__close(HFILE fd)
-{
- int ret=_lclose(fd);
-
- TRACE("(%d)\n",fd);
- if(ret)
- WARN(" Failed!\n");
-
- return ret;
-}
-
-/*********************************************************************
- * feof (CRTDLL.363)
- * FIXME: Care for large files
- * FIXME: Check errors
- */
-INT __cdecl CRTDLL_feof( CRTDLL_FILE *file )
-{
- DWORD curpos=SetFilePointer( file->handle, 0, NULL, SEEK_CUR );
- DWORD endpos=SetFilePointer( file->handle, 0, NULL, FILE_END );
-
- if (curpos==endpos)
- return TRUE;
- else
- SetFilePointer( file->handle, curpos,0,FILE_BEGIN);
- return FALSE;
-}
/*********************************************************************
* setlocale (CRTDLL.453)
*/
LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
{
- LPSTR categorystr;
+ LPSTR categorystr;
- switch (category) {
- case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
- case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
- case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
- case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
- case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
- case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
- default: categorystr = "UNKNOWN?";break;
- }
- FIXME("(%s,%s),stub!\n",categorystr,locale);
- return "C";
+ switch (category) {
+ case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
+ case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
+ case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
+ case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
+ case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
+ case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
+ default: categorystr = "UNKNOWN?";break;
+ }
+ FIXME("(%s,%s),stub!\n",categorystr,locale);
+ return "C";
}
-/*********************************************************************
- * _setmode (CRTDLL.265)
- * FIXME: At present we ignore the request to translate CR/LF to LF.
- *
- * We allways translate when we read with fgets, we never do with fread
- *
- */
-INT __cdecl CRTDLL__setmode( INT fh,INT mode)
-{
- /* FIXME */
-#define O_TEXT 0x4000
-#define O_BINARY 0x8000
-
- FIXME("on fhandle %d mode %s, STUB.\n",
- fh,(mode=O_TEXT)?"O_TEXT":
- (mode=O_BINARY)?"O_BINARY":"UNKNOWN");
- return -1;
-}
-
-/*********************************************************************
- * _fpreset (CRTDLL.107)
- */
-VOID __cdecl CRTDLL__fpreset(void)
-{
- FIXME(" STUB.\n");
-}
-
-/*********************************************************************
- * atexit (CRTDLL.345)
- */
-INT __cdecl CRTDLL_atexit(LPVOID x)
-{
- FIXME("(%p), STUB.\n",x);
- return 0; /* successful */
-}
/*********************************************************************
* _isctype (CRTDLL.138)
*/
BOOL __cdecl CRTDLL__isctype(CHAR x,CHAR type)
{
- if ((type & CRTDLL_SPACE) && isspace(x))
- return TRUE;
- if ((type & CRTDLL_PUNCT) && ispunct(x))
- return TRUE;
- if ((type & CRTDLL_LOWER) && islower(x))
- return TRUE;
- if ((type & CRTDLL_UPPER) && isupper(x))
- return TRUE;
- if ((type & CRTDLL_ALPHA) && isalpha(x))
- return TRUE;
- if ((type & CRTDLL_DIGIT) && isdigit(x))
- return TRUE;
- if ((type & CRTDLL_CONTROL) && iscntrl(x))
- return TRUE;
- /* check CRTDLL_LEADBYTE */
- return FALSE;
+ if ((type & CRTDLL_SPACE) && isspace(x))
+ return TRUE;
+ if ((type & CRTDLL_PUNCT) && ispunct(x))
+ return TRUE;
+ if ((type & CRTDLL_LOWER) && islower(x))
+ return TRUE;
+ if ((type & CRTDLL_UPPER) && isupper(x))
+ return TRUE;
+ if ((type & CRTDLL_ALPHA) && isalpha(x))
+ return TRUE;
+ if ((type & CRTDLL_DIGIT) && isdigit(x))
+ return TRUE;
+ if ((type & CRTDLL_CONTROL) && iscntrl(x))
+ return TRUE;
+ /* check CRTDLL_LEADBYTE */
+ return FALSE;
}
-/*********************************************************************
- * _chdrive (CRTDLL.52)
- *
- * newdir [I] drive to change to, A=1
- *
- */
-BOOL __cdecl CRTDLL__chdrive(INT newdrive)
-{
- /* FIXME: generates errnos */
- return DRIVE_SetCurrentDrive(newdrive-1);
-}
-
-/*********************************************************************
- * _chdir (CRTDLL.51)
- */
-INT __cdecl CRTDLL__chdir(LPCSTR newdir)
-{
- if (!SetCurrentDirectoryA(newdir))
- return 1;
- return 0;
-}
/*********************************************************************
* _fullpath (CRTDLL.114)
@@ -1450,6 +426,7 @@
return buf;
}
+
/*********************************************************************
* _splitpath (CRTDLL.279)
*/
@@ -1472,42 +449,40 @@
namechar = strrchr(dirchar,'.');
else
namechar = strrchr(path,'.');
-
-
- if (drive)
+
+ if (drive)
{
*drive = 0x00;
- if (drivechar)
- {
- strncat(drive,path,drivechar-path+1);
- path = drivechar+1;
- }
+ if (drivechar)
+ {
+ strncat(drive,path,drivechar-path+1);
+ path = drivechar+1;
+ }
}
- if (directory)
+ if (directory)
{
*directory = 0x00;
if (dirchar)
- {
- strncat(directory,path,dirchar-path+1);
- path = dirchar+1;
- }
+ {
+ strncat(directory,path,dirchar-path+1);
+ path = dirchar+1;
+ }
}
if (filename)
{
*filename = 0x00;
if (namechar)
- {
- strncat(filename,path,namechar-path);
- if (extension)
- {
- *extension = 0x00;
- strcat(extension,namechar);
- }
- }
+ {
+ strncat(filename,path,namechar-path);
+ if (extension)
+ {
+ *extension = 0x00;
+ strcat(extension,namechar);
+ }
+ }
}
TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
-
}
@@ -1515,270 +490,150 @@
* _makepath (CRTDLL.182)
*/
-VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
- LPCSTR directory, LPCSTR filename,
- LPCSTR extension )
+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);
+ char ch;
+ TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
+ filename, extension);
- if ( !path )
- return;
+ if ( !path )
+ return;
- path[0] = 0;
- if ( drive )
- if ( drive[0] ) {
- sprintf(path, "%c:", drive[0]);
- }
- if ( directory )
- if ( directory[0] ) {
- strcat(path, directory);
- ch = path[strlen(path)-1];
- if (ch != '/' && ch != '\\')
- strcat(path,"\\");
- }
- if ( filename )
- if ( filename[0] ) {
- strcat(path, filename);
- if ( extension ) {
- if ( extension[0] ) {
- if ( extension[0] != '.' ) {
- strcat(path,".");
- }
- strcat(path,extension);
- }
- }
- }
-
- TRACE("CRTDLL__makepath returns %s\n",path);
+ 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);
}
-/*********************************************************************
- * _getcwd (CRTDLL.120)
- */
-CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
-{
- char test[1];
- int len;
-
- len = size;
- if (!buf) {
- if (size < 0) /* allocate as big as nescessary */
- len =GetCurrentDirectoryA(1,test) + 1;
- if(!(buf = CRTDLL_malloc(len)))
- {
- /* set error to OutOfRange */
- return( NULL );
- }
- }
- size = len;
- if(!(len =GetCurrentDirectoryA(len,buf)))
- {
- return NULL;
- }
- if (len > size)
- {
- /* set error to ERANGE */
- TRACE("CRTDLL_getcwd buffer to small\n");
- return NULL;
- }
- return buf;
-
-}
-
-/*********************************************************************
- * _getdcwd (CRTDLL.121)
- */
-CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size)
-{
- char test[1];
- int len;
-
- FIXME("(\"%c:\",%s,%d)\n",drive+'A',buf,size);
- len = size;
- if (!buf) {
- if (size < 0) /* allocate as big as nescessary */
- len =GetCurrentDirectoryA(1,test) + 1;
- if(!(buf = CRTDLL_malloc(len)))
- {
- /* set error to OutOfRange */
- return( NULL );
- }
- }
- size = len;
- if(!(len =GetCurrentDirectoryA(len,buf)))
- {
- return NULL;
- }
- if (len > size)
- {
- /* set error to ERANGE */
- TRACE("buffer to small\n");
- return NULL;
- }
- return buf;
-
-}
-
-/*********************************************************************
- * _getdrive (CRTDLL.124)
- *
- * Return current drive, 1 for A, 2 for B
- */
-INT __cdecl CRTDLL__getdrive(VOID)
-{
- return DRIVE_GetCurrentDrive() + 1;
-}
-
-/*********************************************************************
- * _mkdir (CRTDLL.234)
- */
-INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
-{
- if (!CreateDirectoryA(newdir,NULL))
- return -1;
- return 0;
-}
-
-/*********************************************************************
- * remove (CRTDLL.448)
- */
-INT __cdecl CRTDLL_remove(LPCSTR file)
-{
- if (!DeleteFileA(file))
- return -1;
- return 0;
-}
/*********************************************************************
* _errno (CRTDLL.52)
- * Yes, this is a function.
- */
-LPINT __cdecl CRTDLL__errno()
-{
- static int crtdllerrno;
-
- /* FIXME: we should set the error at the failing function call time */
-
- switch(GetLastError())
- {
- case ERROR_ACCESS_DENIED: crtdllerrno = EPERM; break;
- case ERROR_FILE_NOT_FOUND: crtdllerrno = ENOENT; break;
- case ERROR_INVALID_PARAMETER: crtdllerrno = EINVAL; break;
- case ERROR_IO_DEVICE: crtdllerrno = EIO; break;
- case ERROR_BAD_FORMAT: crtdllerrno = ENOEXEC; break;
- case ERROR_INVALID_HANDLE: crtdllerrno = EBADF; break;
- case ERROR_OUTOFMEMORY: crtdllerrno = ENOMEM; break;
- case ERROR_BUSY: crtdllerrno = EBUSY; break;
- case ERROR_FILE_EXISTS: crtdllerrno = EEXIST; break;
- case ERROR_BAD_DEVICE: crtdllerrno = ENODEV; break;
- case ERROR_TOO_MANY_OPEN_FILES: crtdllerrno = EMFILE; break;
- case ERROR_DISK_FULL: crtdllerrno = ENOSPC; break;
- case ERROR_SEEK_ON_DEVICE: crtdllerrno = ESPIPE; break;
- case ERROR_BROKEN_PIPE: crtdllerrno = EPIPE; break;
- case ERROR_POSSIBLE_DEADLOCK: crtdllerrno = EDEADLK; break;
- case ERROR_FILENAME_EXCED_RANGE: crtdllerrno = ENAMETOOLONG; break;
- case ERROR_DIR_NOT_EMPTY: crtdllerrno = ENOTEMPTY; break;
- }
- return &crtdllerrno;
-}
-
-/*********************************************************************
- * _tempnam (CRTDLL.305)
- *
- */
-LPSTR __cdecl CRTDLL__tempnam(LPCSTR dir, LPCSTR prefix)
-{
-
- char *ret;
- DOS_FULL_NAME tempname;
-
- if ((ret = tempnam(dir,prefix))==NULL) {
- WARN("Unable to get unique filename\n");
- return NULL;
- }
- if (!DOSFS_GetFullName(ret,FALSE,&tempname))
- {
- TRACE("Wrong path?\n");
- return NULL;
- }
- free(ret);
- if ((ret = CRTDLL_malloc(strlen(tempname.short_name)+1)) == NULL) {
- WARN("CRTDL_malloc for shortname failed\n");
- return NULL;
- }
- if ((ret = strcpy(ret,tempname.short_name)) == NULL) {
- WARN("Malloc for shortname failed\n");
- return NULL;
- }
-
- TRACE("dir %s prefix %s got %s\n",
- dir,prefix,ret);
- return ret;
-
-}
-/*********************************************************************
- * tmpnam (CRTDLL.490)
+ * Return the address of the CRT errno (Not the libc errno).
*
- * lcclnk from lcc-win32 relies on a terminating dot in the name returned
- *
+ * BUGS
+ * Not MT safe.
*/
-LPSTR __cdecl CRTDLL_tmpnam(LPSTR s)
+LPINT __cdecl CRTDLL__errno( VOID )
{
- char *ret;
-
- if ((ret =tmpnam(s))== NULL) {
- WARN("Unable to get unique filename\n");
- return NULL;
- }
- if (!DOSFS_GetFullName(ret,FALSE,&CRTDLL_tmpname))
- {
- TRACE("Wrong path?\n");
- return NULL;
- }
- strcat(CRTDLL_tmpname.short_name,".");
- TRACE("for buf %p got %s\n",
- s,CRTDLL_tmpname.short_name);
- TRACE("long got %s\n",
- CRTDLL_tmpname.long_name);
- if ( s != NULL)
- return strcpy(s,CRTDLL_tmpname.short_name);
- else
- return CRTDLL_tmpname.short_name;
-
+ return &CRTDLL_errno;
}
-typedef VOID (*sig_handler_type)(VOID);
+/*********************************************************************
+ * _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;
+}
+
+
+/**********************************************************************
+ * _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);
+ CRTDLL_free(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)
*/
-void * __cdecl CRTDLL_signal(int sig, sig_handler_type ptr)
+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(unsigned long timeout)
+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(const char *name)
+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,'=');
@@ -1797,37 +652,6 @@
return pp;
}
-/*********************************************************************
- * _mbsrchr (CRTDLL.223)
- */
-LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x) {
- /* FIXME: handle multibyte strings */
- return strrchr(s,x);
-}
-
-/*********************************************************************
- * __dllonexit (CRTDLL.25)
- */
-VOID __cdecl CRTDLL___dllonexit ()
-{
- FIXME("stub\n");
-}
-
-/*********************************************************************
- * _strdate (CRTDLL.283)
- */
-LPSTR __cdecl CRTDLL__strdate (LPSTR date)
-{ FIXME("%p stub\n", date);
- return 0;
-}
-
-/*********************************************************************
- * _strtime (CRTDLL.299)
- */
-LPSTR __cdecl CRTDLL__strtime (LPSTR date)
-{ FIXME("%p stub\n", date);
- return 0;
-}
/*********************************************************************
* _except_handler2 (CRTDLL.78)
@@ -1843,3 +667,386 @@
frame->Handler, context, dispatcher);
return ExceptionContinueSearch;
}
+
+
+/*********************************************************************
+ * __isascii (CRTDLL.028)
+ *
+ */
+INT __cdecl CRTDLL___isascii(INT c)
+{
+ return isascii(c);
+}
+
+
+/*********************************************************************
+ * __toascii (CRTDLL.035)
+ *
+ */
+INT __cdecl CRTDLL___toascii(INT c)
+{
+ return 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(LONG c)
+{
+ return (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(LONG c)
+{
+ return (isalpha(c) || c == '_');
+}
+
+
+/*********************************************************************
+ * _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
+ * comp_func [in] Pointer to comparason 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)
+ *
+ * Unimplemented. Obsolete. Give it up. Use controlfp(), if you must.
+ *
+ */
+UINT __cdecl CRTDLL__control87(UINT x, UINT y)
+{
+ /* Will never be supported, no possible targets have an 87/287 FP unit */
+ WARN(":Ignoring control87 call, dont trust any FP results!\n");
+ return 0;
+}
+
+
+/*********************************************************************
+ * _controlfp (CRTDLL.061)
+ *
+ * Set the state of the floating point unit.
+ *
+ * PARAMS
+ * FIXME:
+ *
+ * RETURNS
+ * None
+ *
+ * BUGS
+ * Unimplemented.
+ */
+UINT __cdecl CRTDLL__controlfp( UINT x, UINT y)
+{
+ FIXME(":stub!\n");
+ return 0;
+}
+
+
+/*********************************************************************
+ * _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 (isfinite(d)?1:0); /* See comment for CRTDLL__isnan() */
+}
+
+
+/*********************************************************************
+ * _fpreset (CRTDLL.107)
+ *
+ * Reset the state of the floating point processor.
+ *
+ * PARAMS
+ * None.
+ *
+ * RETURNS
+ * None.
+ *
+ * BUGS
+ * Unimplemented.
+ */
+VOID __cdecl CRTDLL__fpreset(void)
+{
+ FIXME(":stub!\n");
+}
+
+
+/*********************************************************************
+ * _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;
+}
+
+
+/*********************************************************************
+ * _j0 (CRTDLL.166)
+ */
+double CRTDLL__j0(double x)
+{
+ FIXME(":stub!\n");
+ return x;
+}
+
+/*********************************************************************
+ * _j1 (CRTDLL.167)
+ */
+double CRTDLL__j1(double x)
+{
+ FIXME(":stub!\n");
+ return x;
+}
+
+/*********************************************************************
+ * _jn (CRTDLL.168)
+ */
+double CRTDLL__jn(LONG x,double y)
+{
+ FIXME(":stub!\n");
+ return x;
+}
diff --git a/dlls/crtdll/dir.c b/dlls/crtdll/dir.c
new file mode 100644
index 0000000..5122cb4
--- /dev/null
+++ b/dlls/crtdll/dir.c
@@ -0,0 +1,336 @@
+/*
+ * 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 "drive.h"
+#include <time.h>
+#include "file.h"
+
+DEFAULT_DEBUG_CHANNEL(crtdll);
+
+/* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
+static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft);
+static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
+{
+ static DWORD dummy;
+
+ /* 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;
+
+ ft->time_create = DOSFS_FileTimeToUnixTime(&fd->ftCreationTime,&dummy);
+ ft->time_access = DOSFS_FileTimeToUnixTime(&fd->ftLastAccessTime,&dummy);
+ ft->time_write = DOSFS_FileTimeToUnixTime(&fd->ftLastWriteTime,&dummy);
+ 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)
+{
+ if (!DRIVE_SetCurrentDrive(newdrive-1))
+ {
+ __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))
+ {
+ SetLastError(ERROR_INVALID_DRIVE);
+ __CRTDLL__set_errno(GetLastError());
+ 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 */
+
+ 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;
+
+ if (!drive || --drive == DRIVE_GetCurrentDrive())
+ return CRTDLL__getcwd(buf,size); /* current */
+ else
+ {
+ char dir[_MAX_PATH];
+ char drivespec[4] = {'A', ':', '\\', 0};
+ int dir_len;
+
+ drivespec[0] += drive;
+ 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 */
+ }
+
+ 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)
+{
+ return DRIVE_GetCurrentDrive() + 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;
+}
diff --git a/dlls/crtdll/exit.c b/dlls/crtdll/exit.c
new file mode 100644
index 0000000..362f882
--- /dev/null
+++ b/dlls/crtdll/exit.c
@@ -0,0 +1,186 @@
+/*
+ * 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>
+#include "process.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)
+{
+ CRTDLL_fprintf(CRTDLL_stderr,"\nrun-time error:\nError Code %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)
+{
+ FIXME("not calling CRTDLL cleanup\n");
+ /* dont exit, return to caller */
+}
+
+
+/*********************************************************************
+ * _cexit (CRTDLL.049)
+ */
+VOID __cdecl CRTDLL__cexit(VOID)
+{
+ FIXME("not calling CRTDLL cleanup\n");
+ /* dont exit, 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;
+}
diff --git a/dlls/crtdll/file.c b/dlls/crtdll/file.c
new file mode 100644
index 0000000..bcad995
--- /dev/null
+++ b/dlls/crtdll/file.c
@@ -0,0 +1,1524 @@
+/*
+ * 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 compatable 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 "drive.h"
+#include "file.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];
+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;
+ }
+}
+
+
+/*********************************************************************
+ * _access (CRTDLL.37)
+ */
+INT __cdecl CRTDLL__access(LPCSTR filename, INT mode)
+{
+ DWORD attr = GetFileAttributesA(filename);
+
+ if (attr == -1)
+ {
+ 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;
+}
+
+
+/*********************************************************************
+ * _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;
+ }
+ 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.66)
+ *
+ * Open a file, creating it if it is not present.
+ */
+INT __cdecl CTRDLL__creat(LPCSTR path, INT flags)
+{
+ return CRTDLL__open(path,_O_CREAT|_O_WRONLY|_O_TRUNC);
+}
+
+
+/*********************************************************************
+ * _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 = 3;
+
+ while(i < __CRTDLL_fdend)
+ if (__CRTDLL_handles[i] != INVALID_HANDLE_VALUE)
+ {
+ CRTDLL__close(i);
+ 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;
+}
+
+
+/*********************************************************************
+ * _fgetchar (CRTDLL.092)
+ */
+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);
+}
+
+
+/*********************************************************************
+ * _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);
+}
+
+
+/*********************************************************************
+ * _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)
+{
+ static DWORD dummy;
+ 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;
+ buf->st_atime = DOSFS_FileTimeToUnixTime(&hfi.ftCreationTime,&dummy);
+ buf->st_mtime = DOSFS_FileTimeToUnixTime(&hfi.ftLastAccessTime,&dummy);
+ buf->st_ctime = DOSFS_FileTimeToUnixTime(&hfi.ftLastWriteTime,&dummy);
+ 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;
+}
+
+
+/*********************************************************************
+ * _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)
+{
+ LONG 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;
+}
+
+
+/*********************************************************************
+ * _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))
+ TRACE(":unsupported flags 0x%04x\n",flags);
+
+ /* clear those pesky flags ;-) */
+ flags &= (_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL|_O_CREAT|_O_RDWR);
+
+ hand = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, creation, FILE_ATTRIBUTE_NORMAL, -1);
+
+ 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 (flags & _IOAPPEND && fd > 0)
+ 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;
+}
+
+
+/*********************************************************************
+ * _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)
+{
+ static DWORD dummy;
+ DOS_FULL_NAME full_name;
+ BY_HANDLE_FILE_INFORMATION hfi;
+ unsigned short mode = CRTDLL_S_IREAD;
+ int plen;
+
+ TRACE(":file (%s) buf(%p)\n",path,buf);
+ if (!DOSFS_GetFullName( path, TRUE, &full_name ))
+ {
+ TRACE("failed-last error (%ld)\n",GetLastError());
+ __CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
+ return -1;
+ }
+
+ memset(&hfi,0,sizeof(hfi));
+
+ if (!FILE_Stat(full_name.long_name,&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 = DRIVE_GetCurrentDrive();
+
+ 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 = hfi.nNumberOfLinks;
+ buf->st_size = hfi.nFileSizeLow;
+ buf->st_atime = DOSFS_FileTimeToUnixTime(&hfi.ftCreationTime,&dummy);
+ buf->st_mtime =
+ buf->st_ctime = DOSFS_FileTimeToUnixTime(&hfi.ftLastWriteTime,&dummy);
+ 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;
+}
+
+
+/*********************************************************************
+ * _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 EOF;
+ return c;
+}
+
+
+/*********************************************************************
+ * fgetpos (CRTDLL.364)
+ */
+INT __cdecl CRTDLL_fgetpos( CRTDLL_FILE* file, 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 != EOF && cc != '\n';
+ cc = CRTDLL_fgetc(file))
+ if (cc != '\r')
+ {
+ if (--size <= 0) break;
+ *s++ = (char)cc;
+ }
+ if ((cc == 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;
+}
+
+
+/*********************************************************************
+ * fputs (CRTDLL.375)
+ */
+INT __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE* file )
+{
+ return CRTDLL_fwrite(s,strlen(s),1,file);
+}
+
+
+/*********************************************************************
+ * 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 : 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, fpos_t *pos)
+{
+ return CRTDLL__lseek(file->_file,*pos,SEEK_SET);
+}
+
+
+/*********************************************************************
+ * fscanf (CRTDLL.381)
+ */
+INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* file, LPSTR format, ... )
+{
+ 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!=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!=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!=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!=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!=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!=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!=EOF) && isspace(nch))
+ nch = CRTDLL_fgetc(file);
+ /* read until whitespace */
+ while ((nch!=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!=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 != 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);
+}
+
+
+/*********************************************************************
+ * 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);
+}
+
+
+/*********************************************************************
+ * remove (CRTDLL.448)
+ */
+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;
+}
+
+
+/*********************************************************************
+ * 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;
+}
+
+
+/*********************************************************************
+ * 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);
+ return CRTDLL_tmpname;
+}
+
+
+/*********************************************************************
+ * 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 );
+}
+
diff --git a/dlls/crtdll/mbstring.c b/dlls/crtdll/mbstring.c
index 4927d21..f61d770 100644
--- a/dlls/crtdll/mbstring.c
+++ b/dlls/crtdll/mbstring.c
@@ -4,12 +4,31 @@
* Copyright 1999 Alexandre Julliard
*/
-#include "windef.h"
-#include "winbase.h"
-#include "winnls.h"
#include "crtdll.h"
+DEFAULT_DEBUG_CHANNEL(crtdll);
+
+
+/*********************************************************************
+ * _mbsicmp (CRTDLL.204)
+ */
+int __cdecl CRTDLL__mbsicmp(unsigned char *x,unsigned char *y)
+{
+ do {
+ if (!*x)
+ return !!*y;
+ if (!*y)
+ return !!*x;
+ /* FIXME: MBCS handling... */
+ if (*x!=*y)
+ return 1;
+ x++;
+ y++;
+ } while (1);
+}
+
+
/*********************************************************************
* CRTDLL__mbsinc (CRTDLL.205)
*/
@@ -31,6 +50,17 @@
}
+
+/*********************************************************************
+ * _mbsrchr (CRTDLL.223)
+ */
+LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x)
+{
+ /* FIXME: handle multibyte strings */
+ return strrchr(s,x);
+}
+
+
/*********************************************************************
* CRTDLL_mbtowc (CRTDLL.430)
*/
@@ -44,3 +74,16 @@
if (n >= 2 && IsDBCSLeadByte(*str) && str[1]) return 2;
return 1;
}
+
+
+/*********************************************************************
+ * _mbccpy (CRTDLL.??)
+ *
+ * Copy one multibyte character to another
+ */
+VOID __cdecl CRTDLL__mbccpy(LPSTR dest, LPSTR src)
+{
+ FIXME("MBCS copy treated as ASCII\n");
+ *dest = *src;
+}
+
diff --git a/dlls/crtdll/memory.c b/dlls/crtdll/memory.c
new file mode 100644
index 0000000..b6192e0
--- /dev/null
+++ b/dlls/crtdll/memory.c
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#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 );
+}
+
+
+/*********************************************************************
+ * _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 );
+}
diff --git a/dlls/crtdll/spawn.c b/dlls/crtdll/spawn.c
new file mode 100644
index 0000000..20c308e
--- /dev/null
+++ b/dlls/crtdll/spawn.c
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ * -Wine has a "process.h" which is not the same as any crt version.
+ * 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 "process.h"
+#include "options.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, LPSTR exe, LPSTR args, LPSTR env);
+static int __CRTDLL__spawn(INT flags, LPSTR 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(LPSTR *arg, CHAR delim);
+static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
+{
+ LPSTR *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;
+}
+
+
+/*********************************************************************
+ * _spawnve (CRTDLL.274)
+ *
+ * Spawn a process.
+ *
+ */
+HANDLE __cdecl CRTDLL__spawnve(INT flags, LPSTR name, LPSTR *argv, LPSTR *envv)
+{
+ LPSTR args = __CRTDLL__argvtos(argv,' ');
+ LPSTR envs = __CRTDLL__argvtos(envv,0);
+ LPSTR fullname = name;
+
+ 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)
+ {
+ HANDLE ret = __CRTDLL__spawn(flags, fullname, args, envs);
+ CRTDLL_free(args);
+ CRTDLL_free(envs);
+ return ret;
+ }
+ if (envs)
+ CRTDLL_free(envs);
+
+ WARN(":No argv[0] passed - process will not be executed");
+ return -1;
+}
+
+
+/*********************************************************************
+ * system (CRTDLL.485)
+ */
+INT __cdecl CRTDLL_system(LPSTR x)
+{
+#define SYSBUF_LENGTH 1500
+ char buffer[SYSBUF_LENGTH];
+ unsigned char *y = x;
+ unsigned char *bp;
+ int i;
+
+ strcpy(buffer, argv0);
+ bp = buffer + strlen(buffer);
+ *bp++ = ' ';
+ *bp++ = '"';
+ *bp++ = 0;
+ i = strlen(buffer) + strlen(x) +2;
+
+ /* Calculate needed buffer size to prevent overflow. */
+ while (*y) {
+ if (*y =='\\') i++;
+ y++;
+ }
+ /* If buffer too short, exit. */
+ if (i > SYSBUF_LENGTH) {
+ TRACE("_system buffer to small\n");
+ return 127;
+ }
+
+ y =x;
+
+ while (*y) {
+ *bp = *y;
+ bp++; y++;
+ if (*(y-1) =='\\') *bp++ = '\\';
+ }
+ /* Remove spaces from end of string. */
+ while (*(y-1) == ' ') {
+ bp--;y--;
+ }
+ *bp++ = '"';
+ *bp = 0;
+ TRACE("_system got '%s', executing '%s'\n",x,buffer);
+
+ return system(buffer);
+}
diff --git a/dlls/crtdll/string.c b/dlls/crtdll/string.c
new file mode 100644
index 0000000..1e5099e
--- /dev/null
+++ b/dlls/crtdll/string.c
@@ -0,0 +1,192 @@
+/*
+ * 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! */
+ 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;
+}
+
+
+/*********************************************************************
+ * _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++;
+ }
+ }
+}
diff --git a/dlls/crtdll/time.c b/dlls/crtdll/time.c
new file mode 100644
index 0000000..cc2b026
--- /dev/null
+++ b/dlls/crtdll/time.c
@@ -0,0 +1,120 @@
+/*
+ * 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 "process.h"
+#include "options.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;
+}
diff --git a/dlls/crtdll/wcstring.c b/dlls/crtdll/wcstring.c
index cbc4805..09e28e1 100644
--- a/dlls/crtdll/wcstring.c
+++ b/dlls/crtdll/wcstring.c
@@ -4,18 +4,13 @@
* Copyright 1999 Alexandre Julliard
*/
-#include "config.h"
-
+#include "crtdll.h"
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
-
-#include "windef.h"
-#include "winbase.h"
#include "winnls.h"
#include "wine/unicode.h"
-#include "crtdll.h"
-#include "debugtools.h"
+
DEFAULT_DEBUG_CHANNEL(crtdll);
diff --git a/tools/winapi_check/win32/crtdll.api b/tools/winapi_check/win32/crtdll.api
index 3b25e00..bc898a4 100644
--- a/tools/winapi_check/win32/crtdll.api
+++ b/tools/winapi_check/win32/crtdll.api
@@ -11,6 +11,7 @@
HFILE
INT
LONG
+ULONG
UINT
WCHAR
clock_t
@@ -32,6 +33,7 @@
LPDWORD
LPDWORD *
LPINT
+LPUINT
LPSTR *
LPSTR **
LPVOID
@@ -44,10 +46,13 @@
_INITTERMFUN *
char *
jmp_buf
-struct find_t *
-struct stat *
+find_t *
+struct _stat *
struct win_stat *
+struct _timeb *
time_t *
+fpos_t *
+diskfree_t *
unsigned char *
va_list
void *
@@ -71,3 +76,7 @@
new_handler_type
sig_handler_type
+comp_func
+struct complex
+atexit_function
+