- 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
+