| /* | 
 |  * The C RunTime DLL | 
 |  *  | 
 |  * Implements C run-time functionality as known from UNIX. | 
 |  * | 
 |  * Copyright 1996,1998 Marcus Meissner | 
 |  * Copyright 1996 Jukka Iivonen | 
 |  * Copyright 1997 Uwe Bonnes | 
 |  */ | 
 |  | 
 | /* | 
 | 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 | 
 | */ | 
 |  | 
 | /* NOTE: This file also implements the wcs* functions. They _ARE_ in  | 
 |  * the newer Linux libcs, but use 4 byte wide characters, so are unusable, | 
 |  * since we need 2 byte wide characters. - Marcus Meissner, 981031 | 
 |  */ | 
 |  | 
 | /* FIXME: all the file handling is hopelessly broken -- AJ */ | 
 |  | 
 | #include <errno.h> | 
 | #include <stdlib.h> | 
 | #include <stdarg.h> | 
 | #include <string.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 "win.h" | 
 | #include "windows.h" | 
 | #include "winerror.h" | 
 | #include "debug.h" | 
 | #include "module.h" | 
 | #include "heap.h" | 
 | #include "crtdll.h" | 
 | #include "drive.h" | 
 | #include "file.h" | 
 | #include "except.h" | 
 | #include "options.h" | 
 | #include "winnls.h" | 
 |  | 
 | extern int FILE_GetUnixHandle( HFILE32  ); | 
 |  | 
 | static DOS_FULL_NAME CRTDLL_tmpname; | 
 |  | 
 | UINT32 CRTDLL_argc_dll;         /* CRTDLL.23 */ | 
 | LPSTR *CRTDLL_argv_dll;         /* CRTDLL.24 */ | 
 | LPSTR  CRTDLL_acmdln_dll;       /* CRTDLL.38 */ | 
 | UINT32 CRTDLL_basemajor_dll;    /* CRTDLL.42 */ | 
 | UINT32 CRTDLL_baseminor_dll;    /* CRTDLL.43 */ | 
 | UINT32 CRTDLL_baseversion_dll;  /* CRTDLL.44 */ | 
 | UINT32 CRTDLL_commode_dll;      /* CRTDLL.59 */ | 
 | LPSTR  CRTDLL_environ_dll;      /* CRTDLL.75 */ | 
 | UINT32 CRTDLL_fmode_dll;        /* CRTDLL.104 */ | 
 | UINT32 CRTDLL_osmajor_dll;      /* CRTDLL.241 */ | 
 | UINT32 CRTDLL_osminor_dll;      /* CRTDLL.242 */ | 
 | UINT32 CRTDLL_osmode_dll;       /* CRTDLL.243 */ | 
 | UINT32 CRTDLL_osver_dll;        /* CRTDLL.244 */ | 
 | UINT32 CRTDLL_osversion_dll;    /* CRTDLL.245 */ | 
 | UINT32 CRTDLL_winmajor_dll;     /* CRTDLL.329 */ | 
 | UINT32 CRTDLL_winminor_dll;     /* CRTDLL.330 */ | 
 | UINT32 CRTDLL_winver_dll;       /* CRTDLL.331 */ | 
 |  | 
 | BYTE CRTDLL_iob[32*3];  /* FIXME */ | 
 |  | 
 | typedef VOID (*new_handler_type)(VOID); | 
 |  | 
 | static new_handler_type new_handler; | 
 |  | 
 | /********************************************************************* | 
 |  *                  _GetMainArgs  (CRTDLL.022) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv, | 
 |                                 LPSTR *environ,DWORD flag) | 
 | { | 
 |         char *cmdline; | 
 |         char  **xargv; | 
 | 	int	xargc,i,afterlastspace; | 
 | 	DWORD	version; | 
 |  | 
 | 	TRACE(crtdll,"(%p,%p,%p,%ld).\n", | 
 | 		argc,argv,environ,flag | 
 | 	); | 
 | 	CRTDLL_acmdln_dll = cmdline = HEAP_strdupA( GetProcessHeap(), 0, | 
 |                                                     GetCommandLine32A() ); | 
 |  	TRACE(crtdll,"got '%s'\n", cmdline); | 
 |  | 
 | 	version	= GetVersion32(); | 
 | 	CRTDLL_osver_dll       = version >> 16; | 
 | 	CRTDLL_winminor_dll    = version & 0xFF; | 
 | 	CRTDLL_winmajor_dll    = (version>>8) & 0xFF; | 
 | 	CRTDLL_baseversion_dll = version >> 16; | 
 | 	CRTDLL_winver_dll      = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8); | 
 | 	CRTDLL_baseminor_dll   = (version >> 16) & 0xFF; | 
 | 	CRTDLL_basemajor_dll   = (version >> 24) & 0xFF; | 
 | 	CRTDLL_osversion_dll   = version & 0xFFFF; | 
 | 	CRTDLL_osminor_dll     = version & 0xFF; | 
 | 	CRTDLL_osmajor_dll     = (version>>8) & 0xFF; | 
 |  | 
 | 	/* missing threading init */ | 
 |  | 
 | 	i=0;xargv=NULL;xargc=0;afterlastspace=0; | 
 | 	while (cmdline[i]) { | 
 | 		if (cmdline[i]==' ') { | 
 | 			xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv, | 
 |                                                    sizeof(char*)*(++xargc)); | 
 | 			cmdline[i]='\0'; | 
 | 			xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0, | 
 |                                                        cmdline+afterlastspace); | 
 | 			i++; | 
 | 			while (cmdline[i]==' ') | 
 | 				i++; | 
 | 			if (cmdline[i]) | 
 | 				afterlastspace=i; | 
 | 		} else | 
 | 			i++; | 
 | 	} | 
 | 	xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv, | 
 |                                    sizeof(char*)*(++xargc)); | 
 | 	cmdline[i]='\0'; | 
 | 	xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0, | 
 |                                        cmdline+afterlastspace); | 
 | 	CRTDLL_argc_dll	= xargc; | 
 | 	*argc		= xargc; | 
 | 	CRTDLL_argv_dll	= xargv; | 
 | 	*argv		= xargv; | 
 |  | 
 | 	TRACE(crtdll,"found %d arguments\n", | 
 | 		CRTDLL_argc_dll); | 
 | 	CRTDLL_environ_dll = *environ = GetEnvironmentStrings32A(); | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | 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(crtdll, ":(%s,%p): stub\n",fname,x2); | 
 |   SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
 |   return FALSE; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _findnext     (CRTDLL.100) | 
 |  *  | 
 |  * BUGS | 
 |  *   Unimplemented | 
 |  */ | 
 | INT32 __cdecl CRTDLL__findnext(DWORD hand, struct find_t * x2) | 
 | { | 
 |   FIXME(crtdll, ":(%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(crtdll, ":(%d,%p): stub\n",file,buf); | 
 |   SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
 |   return FALSE; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _initterm     (CRTDLL.135) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end) | 
 | { | 
 | 	_INITTERMFUN	*current; | 
 |  | 
 | 	TRACE(crtdll,"(%p,%p)\n",start,end); | 
 | 	current=start; | 
 | 	while (current<end) { | 
 | 		if (*current) (*current)(); | 
 | 		current++; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _fdopen     (CRTDLL.91) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__fdopen(INT32 handle, LPCSTR mode) | 
 | { | 
 |   FILE *file; | 
 |  | 
 |   switch (handle)  | 
 |     { | 
 |     case 0 : file=stdin; | 
 |       break; | 
 |     case 1 : file=stdout; | 
 |       break; | 
 |     case 2 : file=stderr; | 
 |       break; | 
 |     default: | 
 |       file=fdopen(handle,mode); | 
 |     } | 
 |   TRACE(crtdll, "open handle %d mode %s  got file %p\n", | 
 | 	       handle, mode, file); | 
 |   return (DWORD)file; | 
 | } | 
 |  | 
 | static FILE *xlat_file_ptr(void *ptr) | 
 | { | 
 |     unsigned long dif; | 
 |      | 
 |     /* CRT sizeof(FILE) == 32 */ | 
 |     dif = ((char *)ptr - (char *)CRTDLL_iob) / 32; | 
 |     switch(dif) | 
 |     { | 
 | 	case 0: return stdin; | 
 | 	case 1: return stdout; | 
 | 	case 2: return stderr; | 
 |     } | 
 |     return (FILE*)ptr; | 
 | } | 
 |  | 
 | /******************************************************************* | 
 |  *         _global_unwind2  (CRTDLL.129) | 
 |  */ | 
 | void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame ) | 
 | { | 
 |     RtlUnwind( frame, 0, NULL, 0 ); | 
 | } | 
 |  | 
 | /******************************************************************* | 
 |  *         _local_unwind2  (CRTDLL.173) | 
 |  */ | 
 | void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr ) | 
 | { | 
 |     TRACE(crtdll,"(%p,%ld)\n",endframe,nr); | 
 | } | 
 | /********************************************************************* | 
 |  *                  _read     (CRTDLL.256) | 
 |  *  | 
 |  * BUGS | 
 |  *   Unimplemented | 
 |  */ | 
 | INT32 __cdecl CRTDLL__read(INT32 fd, LPVOID buf, UINT32 count) | 
 | { | 
 |   FIXME(crtdll,":(%d,%p,%d): stub\n",fd,buf,count); | 
 |   SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
 |   return FALSE; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fopen     (CRTDLL.372) | 
 |  */ | 
 | DWORD __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode) | 
 | { | 
 |   FILE *file; | 
 |   HFILE32 dos_fildes; | 
 | #if 0 | 
 |   DOS_FULL_NAME full_name; | 
 |    | 
 |   if (!DOSFS_GetFullName( path, FALSE, &full_name )) { | 
 |     WARN(crtdll, "file %s bad name\n",path); | 
 |    return 0; | 
 |   } | 
 |    | 
 |   file=fopen(full_name.long_name ,mode); | 
 | #endif | 
 |   INT32 flagmode=0; | 
 |   int unix_fildes=0; | 
 |  | 
 |   if ((strchr(mode,'r')&&strchr(mode,'a'))|| | 
 |       (strchr(mode,'r')&&strchr(mode,'w'))|| | 
 |       (strchr(mode,'w')&&strchr(mode,'a'))) | 
 |     return 0; | 
 |         | 
 |   if (strstr(mode,"r+")) flagmode=O_RDWR; | 
 |   else if (strchr(mode,'r')) flagmode = O_RDONLY; | 
 |   else if (strstr(mode,"w+")) flagmode= O_RDWR | O_TRUNC | O_CREAT; | 
 |   else if (strchr(mode,'w')) flagmode = O_WRONLY | O_TRUNC | O_CREAT; | 
 |   else if (strstr(mode,"a+")) flagmode= O_RDWR | O_CREAT | O_APPEND; | 
 |   else if (strchr(mode,'w')) flagmode = O_RDWR | O_CREAT | O_APPEND; | 
 |   else if (strchr(mode,'b')) | 
 |     TRACE(crtdll, "%s in BINARY mode\n",path); | 
 |        | 
 |   dos_fildes=FILE_Open(path, flagmode,0); | 
 |   unix_fildes=FILE_GetUnixHandle(dos_fildes); | 
 |   file = fdopen(unix_fildes,mode); | 
 |  | 
 |   TRACE(crtdll, "file %s mode %s got ufh %d dfh %d file %p\n", | 
 | 		 path,mode,unix_fildes,dos_fildes,file); | 
 |   return (DWORD)file; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fread     (CRTDLL.377) | 
 |  */ | 
 | DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile) | 
 | { | 
 |   size_t ret=1; | 
 |   FILE *file=xlat_file_ptr(vfile); | 
 | #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(crtdll, "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(crtdll, "skipping ^M\n"); | 
 |   } | 
 |   TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n", | 
 | 	       nmemb,size,file,ptr,); | 
 |   if(i!=nmemb) | 
 |     WARN(crtdll, " failed!\n"); | 
 |  | 
 |   return i; | 
 | #else | 
 |      | 
 |   ret=fread(ptr,size,nmemb,file); | 
 |   TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n", | 
 | 	       nmemb,size,file,ptr); | 
 |   if(ret!=nmemb) | 
 |     WARN(crtdll, " failed!\n"); | 
 |  | 
 |   return ret; | 
 | #endif | 
 | } | 
 | /********************************************************************* | 
 |  *                  freopen    (CRTDLL.379) | 
 |  *  | 
 |  * BUGS | 
 |  *   Unimplemented | 
 |  */ | 
 | DWORD __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode, LPVOID stream) | 
 | { | 
 |   FIXME(crtdll, ":(%s,%s,%p): stub\n", path, mode, stream); | 
 |   SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
 |   return FALSE; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fscanf     (CRTDLL.381) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fscanf( LPVOID stream, LPSTR format, ... ) | 
 | { | 
 |     va_list valist; | 
 |     INT32 res; | 
 |  | 
 |     va_start( valist, format ); | 
 | #ifdef HAVE_VFSCANF | 
 |     res = vfscanf( xlat_file_ptr(stream), format, valist ); | 
 | #endif | 
 |     va_end( valist ); | 
 |     return res; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fseek     (CRTDLL.382) | 
 |  */ | 
 | LONG __cdecl CRTDLL_fseek(LPVOID stream, LONG offset, INT32 whence) | 
 | { | 
 |   long ret; | 
 |  | 
 |   ret=fseek(xlat_file_ptr(stream),offset,whence); | 
 |   TRACE(crtdll, "file %p to 0x%08lx pos %s\n", | 
 | 	       stream,offset,(whence==SEEK_SET)?"SEEK_SET": | 
 | 	       (whence==SEEK_CUR)?"SEEK_CUR": | 
 | 	       (whence==SEEK_END)?"SEEK_END":"UNKNOWN"); | 
 |   if(ret) | 
 |     WARN(crtdll, " failed!\n"); | 
 |  | 
 |   return ret; | 
 | } | 
 |    | 
 | /********************************************************************* | 
 |  *                  fsetpos     (CRTDLL.383) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fsetpos(LPVOID stream, fpos_t *pos) | 
 | { | 
 |   TRACE(crtdll, "file %p\n", stream); | 
 |   return fseek(xlat_file_ptr(stream), *pos, SEEK_SET); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  ftell     (CRTDLL.384) | 
 |  */ | 
 | LONG __cdecl CRTDLL_ftell(LPVOID stream) | 
 | { | 
 |   long ret; | 
 |  | 
 |   ret=ftell(xlat_file_ptr(stream)); | 
 |   TRACE(crtdll, "file %p at 0x%08lx\n", | 
 | 	       stream,ret); | 
 |   return ret; | 
 | } | 
 |    | 
 | /********************************************************************* | 
 |  *                  fwrite     (CRTDLL.386) | 
 |  */ | 
 | DWORD __cdecl CRTDLL_fwrite(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile) | 
 | { | 
 |   size_t ret; | 
 |   FILE *file=xlat_file_ptr(vfile); | 
 |  | 
 |   ret=fwrite(ptr,size,nmemb,file); | 
 |   TRACE(crtdll, "0x%08x items of size %d from %p to file %p\n", | 
 | 	       nmemb,size,ptr,file); | 
 |   if(ret!=nmemb) | 
 |     WARN(crtdll, " Failed!\n"); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  setbuf     (CRTDLL.452) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_setbuf(LPVOID file, LPSTR buf) | 
 | { | 
 |   TRACE(crtdll, "(file %p buf %p)\n", file, buf); | 
 |   /* this doesn't work:"void value not ignored as it ought to be"  | 
 |   return setbuf(file,buf);  | 
 |   */ | 
 |   setbuf(xlat_file_ptr(file),buf); | 
 |   return 0; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _open_osfhandle         (CRTDLL.240) | 
 |  */ | 
 | HFILE32 __cdecl CRTDLL__open_osfhandle(LONG osfhandle, INT32 flags) | 
 | { | 
 | HFILE32 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(crtdll, "(handle %08lx,flags %d) return %d\n", | 
 | 		     osfhandle,flags,handle); | 
 | 	return handle; | 
 | 	 | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  srand         (CRTDLL.460) | 
 |  */ | 
 | void __cdecl CRTDLL_srand(DWORD seed) | 
 | { | 
 | 	/* FIXME: should of course be thread? process? local */ | 
 | 	srand(seed); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fprintf       (CRTDLL.373) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fprintf( FILE *file, LPSTR format, ... ) | 
 | { | 
 |     va_list valist; | 
 |     INT32 res; | 
 |  | 
 |     va_start( valist, format ); | 
 |     res = vfprintf( xlat_file_ptr(file), format, valist ); | 
 |     va_end( valist ); | 
 |     return res; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  vfprintf       (CRTDLL.373) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_vfprintf( FILE *file, LPSTR format, va_list args ) | 
 | { | 
 |     return vfprintf( xlat_file_ptr(file), format, args ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  time          (CRTDLL.488) | 
 |  */ | 
 | time_t __cdecl CRTDLL_time(time_t *timeptr) | 
 | { | 
 | 	time_t	curtime = time(NULL); | 
 |  | 
 | 	if (timeptr) | 
 | 		*timeptr = curtime; | 
 | 	return curtime; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                            (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) | 
 |  */ | 
 | BOOL32 __cdecl CRTDLL__isatty(DWORD x) | 
 | { | 
 | 	TRACE(crtdll,"(%ld)\n",x); | 
 | 	return TRUE; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _write        (CRTDLL.332) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__write(INT32 fd,LPCVOID buf,UINT32 count) | 
 | { | 
 |         INT32 len=0; | 
 |  | 
 | 	if (fd == -1) | 
 | 	  len = -1; | 
 | 	else if (fd<=2) | 
 | 	  len = (UINT32)write(fd,buf,(LONG)count); | 
 | 	else | 
 | 	  len = _lwrite32(fd,buf,count); | 
 | 	TRACE(crtdll,"%d/%d byte to dfh %d from %p,\n", | 
 | 		       len,count,fd,buf); | 
 | 	return len; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _cexit          (CRTDLL.49) | 
 |  * | 
 |  *  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) | 
 |  * | 
 |  * atexit-processing comes to mind -- MW. | 
 |  * | 
 |  */ | 
 | void __cdecl CRTDLL__cexit(INT32 ret) | 
 | { | 
 |         TRACE(crtdll,"(%d)\n",ret); | 
 | 	ExitProcess(ret); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  exit          (CRTDLL.359) | 
 |  */ | 
 | void __cdecl CRTDLL_exit(DWORD ret) | 
 | { | 
 |         TRACE(crtdll,"(%ld)\n",ret); | 
 | 	ExitProcess(ret); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _abnormal_termination          (CRTDLL.36) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__abnormal_termination(void) | 
 | { | 
 |         TRACE(crtdll,"(void)\n"); | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _access          (CRTDLL.37) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__access(LPCSTR filename, INT32 mode) | 
 | { | 
 |     DWORD attr = GetFileAttributes32A(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) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fflush(LPVOID stream) | 
 | { | 
 |     int ret; | 
 |  | 
 |     ret = fflush(xlat_file_ptr(stream)); | 
 |     TRACE(crtdll,"%p returnd %d\n",stream,ret); | 
 |     if(ret) | 
 |       WARN(crtdll, " Failed!\n"); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  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 = fgetc(stdin); cc != EOF && cc != '\n'; cc = fgetc(stdin)) | 
 | 	if(cc != '\r') *buf++ = (char)cc; | 
 |  | 
 |     *buf = '\0'; | 
 |  | 
 |     TRACE(crtdll,"got '%s'\n", buf_start); | 
 |     return buf_start; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  rand          (CRTDLL.446) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_rand() | 
 | { | 
 |     return rand(); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  putchar       (CRTDLL.442) | 
 |  */ | 
 | void __cdecl CRTDLL_putchar( INT32 x ) | 
 | { | 
 |     putchar(x); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  fputc       (CRTDLL.374) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fputc( INT32 c, FILE *stream ) | 
 | { | 
 |     TRACE(crtdll, "%c to file %p\n",c,stream); | 
 |     return fputc(c,xlat_file_ptr(stream)); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  fputs       (CRTDLL.375) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fputs( LPCSTR s, FILE *stream ) | 
 | { | 
 |     TRACE(crtdll, "%s to file %p\n",s,stream); | 
 |     return fputs(s,xlat_file_ptr(stream)); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  puts       (CRTDLL.443) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_puts(LPCSTR s) | 
 | { | 
 |     TRACE(crtdll, "%s \n",s); | 
 |     return puts(s); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  putc       (CRTDLL.441) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_putc(INT32 c, FILE *stream) | 
 | { | 
 |     TRACE(crtdll, " %c to file %p\n",c,stream); | 
 |     return fputc(c,xlat_file_ptr(stream)); | 
 | } | 
 | /********************************************************************* | 
 |  *                  fgetc       (CRTDLL.366) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fgetc( FILE *stream ) | 
 | { | 
 |   int ret= fgetc(xlat_file_ptr(stream)); | 
 |   TRACE(crtdll, "got %d\n",ret); | 
 |   return ret; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  getc       (CRTDLL.388) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_getc( FILE *stream ) | 
 | { | 
 |   int ret= fgetc(xlat_file_ptr(stream)); | 
 |   TRACE(crtdll, "got %d\n",ret); | 
 |   return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _rotl          (CRTDLL.259) | 
 |  */ | 
 | UINT32 __cdecl CRTDLL__rotl(UINT32 x,INT32 shift) | 
 | { | 
 |    unsigned int ret = (x >> shift)|( x >>((sizeof(x))-shift)); | 
 |  | 
 |    TRACE(crtdll, "got 0x%08x rot %d ret 0x%08x\n", | 
 | 		  x,shift,ret); | 
 |    return ret; | 
 |      | 
 | } | 
 | /********************************************************************* | 
 |  *                  _lrotl          (CRTDLL.176) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__lrotl(DWORD x,INT32 shift) | 
 | { | 
 |    unsigned long ret = (x >> shift)|( x >>((sizeof(x))-shift)); | 
 |  | 
 |    TRACE(crtdll, "got 0x%08lx rot %d ret 0x%08lx\n", | 
 | 		  x,shift,ret); | 
 |    return ret; | 
 |      | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  fgets       (CRTDLL.368) | 
 |  */ | 
 | CHAR* __cdecl CRTDLL_fgets(LPSTR s,INT32 size, LPVOID stream) | 
 | { | 
 |   char * ret; | 
 |   char * control_M; | 
 |    | 
 |   ret=fgets(s, size,xlat_file_ptr(stream)); | 
 |   /*FIXME: Control with CRTDLL_setmode */ | 
 |   control_M= strrchr(s,'\r'); | 
 |   /*delete CR if we read a DOS File */ | 
 |   if (control_M) | 
 |     { | 
 |       *control_M='\n'; | 
 |       *(control_M+1)=0; | 
 |     } | 
 |   TRACE(crtdll, "got %s for %d chars from file %p\n", | 
 | 		 s,size,stream); | 
 |   if(ret) | 
 |     WARN(crtdll, " Failed!\n"); | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _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); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _mbsinc       (CRTDLL.205) | 
 |  */ | 
 | unsigned char * __cdecl CRTDLL__mbsinc(unsigned char *x) | 
 | { | 
 |     /* FIXME: mbcs */ | 
 |     return x++; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  vsprintf      (CRTDLL.500) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_vsprintf( LPSTR buffer, LPCSTR spec, va_list args ) | 
 | { | 
 |     return wvsprintf32A( buffer, spec, args ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  vswprintf      (CRTDLL.501) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args ) | 
 | { | 
 |     return wvsprintf32W( buffer, spec, args ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _mbscpy       (CRTDLL.200) | 
 |  */ | 
 | unsigned char* __cdecl CRTDLL__mbscpy(unsigned char *x,unsigned char *y) | 
 | { | 
 |     TRACE(crtdll,"CRTDLL_mbscpy %s and %s\n",x,y); | 
 |     return strcpy(x,y); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _mbscat       (CRTDLL.197) | 
 |  */ | 
 | unsigned char* __cdecl CRTDLL__mbscat(unsigned char *x,unsigned char *y) | 
 | { | 
 |     return strcat(x,y); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _strcmpi   (CRTDLL.282) (CRTDLL.287) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__strcmpi( LPCSTR s1, LPCSTR s2 ) | 
 | { | 
 |     return lstrcmpi32A( s1, s2 ); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _strnicmp   (CRTDLL.293) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__strnicmp( LPCSTR s1, LPCSTR s2, INT32 n ) | 
 | { | 
 |     return lstrncmpi32A( s1, s2, n ); | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  _strlwr      (CRTDLL.293) | 
 |  * | 
 |  * convert a string in place to lowercase  | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__strlwr(LPSTR x) | 
 | { | 
 |   unsigned char *y =x; | 
 |    | 
 |   TRACE(crtdll, "CRTDLL_strlwr got %s\n", x); | 
 |   while (*y) { | 
 |     if ((*y > 0x40) && (*y< 0x5b)) | 
 |       *y = *y + 0x20; | 
 |     y++; | 
 |   } | 
 |   TRACE(crtdll, "   returned %s\n", x); | 
 | 		  | 
 |   return x; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  system       (CRTDLL.485) | 
 |  */ | 
 | INT32 __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 \"", Options.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(crtdll,"_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(crtdll, "_system got '%s', executing '%s'\n",x,buffer); | 
 |  | 
 |   return system(buffer); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _strupr       (CRTDLL.300) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__strupr(LPSTR x) | 
 | { | 
 | 	LPSTR	y=x; | 
 |  | 
 | 	while (*y) { | 
 | 		*y=toupper(*y); | 
 | 		y++; | 
 | 	} | 
 | 	return x; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsupr       (CRTDLL.328) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL__wcsupr(LPWSTR x) | 
 | { | 
 | 	LPWSTR	y=x; | 
 |  | 
 | 	while (*y) { | 
 | 		*y=towupper(*y); | 
 | 		y++; | 
 | 	} | 
 | 	return x; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcslwr       (CRTDLL.323) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL__wcslwr(LPWSTR x) | 
 | { | 
 | 	LPWSTR	y=x; | 
 |  | 
 | 	while (*y) { | 
 | 		*y=towlower(*y); | 
 | 		y++; | 
 | 	} | 
 | 	return x; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************* | 
 |  *                  longjmp        (CRTDLL.426) | 
 |  */ | 
 | VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val) | 
 | { | 
 |     FIXME(crtdll,"CRTDLL_longjmp semistup, expect crash\n"); | 
 |     return longjmp(env, val); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  malloc        (CRTDLL.427) | 
 |  */ | 
 | VOID* __cdecl CRTDLL_malloc(DWORD size) | 
 | { | 
 |     return HeapAlloc(GetProcessHeap(),0,size); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  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); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _strdup          (CRTDLL.285) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr) | 
 | { | 
 |     return HEAP_strdupA(GetProcessHeap(),0,ptr); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsdup          (CRTDLL.320) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL__wcsdup(LPCWSTR ptr) | 
 | { | 
 |     return HEAP_strdupW(GetProcessHeap(),0,ptr); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  fclose           (CRTDLL.362) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_fclose( FILE *stream ) | 
 | { | 
 |     int unix_handle; | 
 |     HFILE32 dos_handle=1; | 
 |     HFILE32 ret=EOF; | 
 |  | 
 |     stream=xlat_file_ptr(stream); | 
 |     unix_handle=fileno(stream); | 
 |  | 
 |     if (unix_handle<4) ret= fclose(stream); | 
 |     else { | 
 |       while(FILE_GetUnixHandle(dos_handle) != unix_handle) dos_handle++; | 
 |       fclose(stream); | 
 |       ret = _lclose32( dos_handle); | 
 |     } | 
 |     TRACE(crtdll,"(%p) ufh %d dfh %d\n", | 
 | 		   stream,unix_handle,dos_handle); | 
 |  | 
 |     if(ret) | 
 |       WARN(crtdll, " Failed!\n"); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _unlink           (CRTDLL.315) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__unlink(LPCSTR pathname) | 
 | { | 
 |     int ret=0; | 
 |     DOS_FULL_NAME full_name; | 
 |  | 
 |     if (!DOSFS_GetFullName( pathname, FALSE, &full_name )) { | 
 |       WARN(crtdll, "CRTDLL_unlink file %s bad name\n",pathname); | 
 |       return EOF; | 
 |     } | 
 |    | 
 |     ret=unlink(full_name.long_name); | 
 |     TRACE(crtdll,"(%s unix %s)\n", | 
 | 		   pathname,full_name.long_name); | 
 |     if(ret) | 
 |       WARN(crtdll, " Failed!\n"); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  rename           (CRTDLL.449) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath) | 
 | { | 
 |     BOOL32 ok = MoveFileEx32A( 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; | 
 |     UINT32 win_st_rdev; | 
 |     INT32  win_st_size; | 
 |     INT32  win_st_atime; | 
 |     INT32  win_st_mtime; | 
 |     INT32  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, "CRTDLL__stat filename %s bad name\n",filename); | 
 |       return -1; | 
 |     } | 
 |     ret=stat(full_name.long_name,&mystat); | 
 |     TRACE(crtdll,"CRTDLL__stat %s\n", filename); | 
 |     if(ret)  | 
 |       WARN(crtdll, " 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) | 
 |  */ | 
 | HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags) | 
 | { | 
 |     HFILE32 ret=0; | 
 |     int wineflags=0; | 
 |      | 
 |     /* 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 | 
 |        */ | 
 |     wineflags = (flags & 3); | 
 |     if (flags & 0x0008 ) wineflags |= O_APPEND; | 
 |     if (flags & 0x0100 ) wineflags |= O_CREAT; | 
 |     if (flags & 0x0200 ) wineflags |= O_TRUNC; | 
 |     if (flags & 0x0400 ) wineflags |= O_EXCL; | 
 |     if (flags & 0xf0f4 )  | 
 |       TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags); | 
 |     /* End Fixme */ | 
 |  | 
 |     ret = FILE_Open(path,wineflags,0); | 
 |     TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x (lccmode 0x%04x) got dfh %d\n", | 
 | 		   path,wineflags,flags,ret); | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _close           (CRTDLL.57) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__close(HFILE32 fd) | 
 | { | 
 |     int ret=_lclose32(fd); | 
 |  | 
 |     TRACE(crtdll,"(%d)\n",fd); | 
 |     if(ret) | 
 |       WARN(crtdll, " Failed!\n"); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  feof           (CRTDLL.363) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_feof( FILE *stream ) | 
 | { | 
 |     int ret; | 
 |      | 
 |     ret=feof(xlat_file_ptr(stream)); | 
 |     TRACE(crtdll,"(%p) %s\n",stream,(ret)?"true":"false"); | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  setlocale           (CRTDLL.453) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL_setlocale(INT32 category,LPCSTR locale) | 
 | { | 
 | 	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(crtdll,"(%s,%s),stub!\n",categorystr,locale); | 
 | 	return "C"; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcscat           (CRTDLL.503) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcscat( LPWSTR s1, LPCWSTR s2 ) | 
 | { | 
 |     return lstrcat32W( s1, s2 ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcschr           (CRTDLL.504) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR str,WCHAR xchar) | 
 | { | 
 | 	LPCWSTR	s; | 
 |  | 
 | 	s=str; | 
 | 	do { | 
 | 		if (*s==xchar) | 
 | 			return (LPWSTR)s; | 
 | 	} while (*s++); | 
 | 	return NULL; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcscmp           (CRTDLL.505) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcscmp( LPCWSTR s1, LPCWSTR s2 ) | 
 | { | 
 |     return lstrcmp32W( s1, s2 ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcscpy           (CRTDLL.507) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR s1, LPCWSTR s2 ) | 
 | { | 
 |     return lstrcpy32W( s1, s2 ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcscspn           (CRTDLL.508) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcscspn(LPWSTR str,LPWSTR reject) | 
 | { | 
 | 	LPWSTR	s,t; | 
 |  | 
 | 	s=str; | 
 | 	do { | 
 | 		t=reject; | 
 | 		while (*t) { if (*t==*s) break;t++;} | 
 | 		if (*t) break; | 
 | 		s++; | 
 | 	} while (*s); | 
 | 	return s-str; /* nr of wchars */ | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcslen           (CRTDLL.510) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcslen( LPCWSTR s ) | 
 | { | 
 |     return lstrlen32W( s ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsncat           (CRTDLL.511) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT32 n ) | 
 | { | 
 |     return lstrcatn32W( s1, s2, n ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsncmp           (CRTDLL.512) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcsncmp( LPCWSTR s1, LPCWSTR s2, INT32 n ) | 
 | { | 
 |     return lstrncmp32W( s1, s2, n ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsncpy           (CRTDLL.513) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT32 n ) | 
 | { | 
 |     return lstrcpyn32W( s1, s2, n ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsspn           (CRTDLL.516) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcsspn(LPWSTR str,LPWSTR accept) | 
 | { | 
 | 	LPWSTR	s,t; | 
 |  | 
 | 	s=str; | 
 | 	do { | 
 | 		t=accept; | 
 | 		while (*t) { if (*t==*s) break;t++;} | 
 | 		if (!*t) break; | 
 | 		s++; | 
 | 	} while (*s); | 
 | 	return s-str; /* nr of wchars */ | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsicmp           (CRTDLL.321) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__wcsicmp( LPCWSTR s1, LPCWSTR s2 ) | 
 | { | 
 |     return lstrcmpi32W( s1, s2 ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsicoll           (CRTDLL.322) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__wcsicoll(LPCWSTR a1,LPCWSTR a2) | 
 | { | 
 |     /* FIXME: handle collates */ | 
 |     return lstrcmpi32W(a1,a2); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsnicmp           (CRTDLL.324) | 
 |  */ | 
 | DWORD __cdecl CRTDLL__wcsnicmp( LPCWSTR s1, LPCWSTR s2, INT32 len ) | 
 | { | 
 |     return lstrncmpi32W( s1, s2, len ); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcscoll           (CRTDLL.506) | 
 |  */ | 
 | DWORD __cdecl CRTDLL_wcscoll(LPWSTR a1,LPWSTR a2) | 
 | { | 
 |     /* FIXME: handle collates */ | 
 |     return lstrcmp32W(a1,a2); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _wcsrev           (CRTDLL.326) | 
 |  */ | 
 | VOID __cdecl CRTDLL__wcsrev(LPWSTR s) { | 
 | 	LPWSTR	e; | 
 |  | 
 | 	e=s; | 
 | 	while (*e) | 
 | 		e++; | 
 | 	while (s<e) { | 
 | 		WCHAR	a; | 
 |  | 
 | 		a=*s;*s=*e;*e=a; | 
 | 		s++;e--; | 
 | 	} | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsstr           (CRTDLL.517) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcsstr(LPWSTR s,LPWSTR b) | 
 | { | 
 | 	LPWSTR	x,y,c; | 
 |  | 
 | 	x=s; | 
 | 	while (*x) { | 
 | 		if (*x==*b) { | 
 | 			y=x;c=b; | 
 | 			while (*y && *c && *y==*c) { c++;y++; } | 
 | 			if (!*c) | 
 | 				return x; | 
 | 		} | 
 | 		x++; | 
 | 	} | 
 | 	return NULL; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcstombs   (CRTDLL.521) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT32 len ) | 
 | { | 
 |     lstrcpynWtoA( dst, src, len ); | 
 |     return strlen(dst);  /* FIXME: is this right? */ | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcsrchr           (CRTDLL.515) | 
 |  */ | 
 | LPWSTR __cdecl CRTDLL_wcsrchr(LPWSTR str,WCHAR xchar) | 
 | { | 
 | 	LPWSTR	s; | 
 |  | 
 | 	s=str+lstrlen32W(str); | 
 | 	do { | 
 | 		if (*s==xchar) | 
 | 			return s; | 
 | 		s--; | 
 | 	} while (s>=str); | 
 | 	return NULL; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _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 | 
 |  * | 
 |  */ | 
 | INT32 __cdecl CRTDLL__setmode( INT32 fh,INT32 mode) | 
 | { | 
 | 	/* FIXME */ | 
 | #define O_TEXT     0x4000 | 
 | #define O_BINARY   0x8000 | 
 |  | 
 | 	FIXME(crtdll, "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(crtdll," STUB.\n"); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  atexit           (CRTDLL.345) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_atexit(LPVOID x) | 
 | { | 
 | 	FIXME(crtdll,"(%p), STUB.\n",x); | 
 | 	return 0; /* successful */ | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  mblen          (CRTDLL.428) | 
 |  * FIXME: check multibyte support | 
 |  */ | 
 | WCHAR  __cdecl CRTDLL_mblen(CHAR *mb,INT32 size) | 
 | { | 
 |  | 
 |     int ret=1; | 
 |      | 
 |     if (!mb) | 
 |       ret = 0; | 
 |     else if ((size<1)||(!*(mb+1))) | 
 |       ret = -1; | 
 |     else if (!(*mb)) | 
 |       ret =0; | 
 |        | 
 |     TRACE(crtdll,"CRTDLL_mlen %s for max %d bytes ret %d\n",mb,size,ret); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  mbstowcs           (CRTDLL.429) | 
 |  * FIXME: check multibyte support | 
 |  */ | 
 | INT32 __cdecl CRTDLL_mbstowcs(LPWSTR wcs, LPCSTR mbs, INT32 size) | 
 | { | 
 |  | 
 | /* Slightly modified lstrcpynAtoW functions from memory/strings.c | 
 |  *  We need the number of characters transfered  | 
 |  *  FIXME: No multibyte support yet | 
 |  */ | 
 |  | 
 |     LPWSTR p = wcs; | 
 |     LPCSTR src= mbs; | 
 |     int ret, n=size; | 
 |  | 
 |     while ((n-- > 0) && *src) { | 
 |       *p++ = (WCHAR)(unsigned char)*src++; | 
 | 	} | 
 |     p++; | 
 |     ret = (p -wcs); | 
 |            | 
 |     TRACE(crtdll,"CRTDLL_mbstowcs %s for %d chars put %d wchars\n", | 
 | 		   mbs,size,ret); | 
 |     return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  mbtowc           (CRTDLL.430) | 
 |  * FIXME: check multibyte support | 
 |  */ | 
 | WCHAR __cdecl CRTDLL_mbtowc(WCHAR* wc,CHAR* mb,INT32 size)  | 
 | { | 
 |    int ret; | 
 |  | 
 |    if (!mb) | 
 |      ret = 0; | 
 |    else if (!wc) | 
 |      ret =-1; | 
 |    else  | 
 |      if ( (ret = mblen(mb,size)) != -1 ) | 
 |        { | 
 | 	 if (ret <= sizeof(char)) | 
 | 	   *wc = (WCHAR) ((unsigned char)*mb); | 
 |         else | 
 |         ret=   -1; | 
 |         }    | 
 |      else | 
 |        ret = -1; | 
 |     | 
 |    TRACE(crtdll,"CRTDLL_mbtowc %s for %d chars\n",mb,size); | 
 |           | 
 |    return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _isctype           (CRTDLL.138) | 
 |  */ | 
 | BOOL32 __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; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _chdrive           (CRTDLL.52) | 
 |  * | 
 |  *  newdir      [I] drive to change to, A=1 | 
 |  * | 
 |  */ | 
 | BOOL32 __cdecl CRTDLL__chdrive(INT32 newdrive) | 
 | { | 
 | 	/* FIXME: generates errnos */ | 
 | 	return DRIVE_SetCurrentDrive(newdrive-1); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _chdir           (CRTDLL.51) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__chdir(LPCSTR newdir) | 
 | { | 
 | 	if (!SetCurrentDirectory32A(newdir)) | 
 | 		return 1; | 
 | 	return 0; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _fullpath           (CRTDLL.114) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT32 size) | 
 | { | 
 |   DOS_FULL_NAME full_name; | 
 |  | 
 |   if (!buf) | 
 |   { | 
 |       size = 256; | 
 |       if(!(buf = CRTDLL_malloc(size))) return NULL; | 
 |   } | 
 |   if (!DOSFS_GetFullName( name, FALSE, &full_name )) return NULL; | 
 |   lstrcpyn32A(buf,full_name.short_name,size); | 
 |   TRACE(crtdll,"CRTDLL_fullpath got %s\n",buf); | 
 |   return buf; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _splitpath           (CRTDLL.279) | 
 |  */ | 
 | VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension ) | 
 | { | 
 |   /* drive includes : | 
 |      directory includes leading and trailing (forward and backward slashes) | 
 |      filename without dot and slashes | 
 |      extension with leading dot | 
 |      */ | 
 |   char * drivechar,*dirchar,*namechar; | 
 |  | 
 |   TRACE(crtdll,"CRTDLL__splitpath got %s\n",path); | 
 |  | 
 |   drivechar  = strchr(path,':'); | 
 |   dirchar    = strrchr(path,'/'); | 
 |   namechar   = strrchr(path,'\\'); | 
 |   dirchar = MAX(dirchar,namechar); | 
 |   if (dirchar) | 
 |     namechar   = strrchr(dirchar,'.'); | 
 |   else | 
 |     namechar   = strrchr(path,'.'); | 
 |    | 
 |    | 
 |   if (drive)  | 
 |     { | 
 |       *drive = 0x00; | 
 |       if (drivechar)  | 
 | 	{ | 
 | 	  strncat(drive,path,drivechar-path+1); | 
 | 	  path = drivechar+1; | 
 | 	} | 
 |     } | 
 |   if (directory)  | 
 |     { | 
 |       *directory = 0x00; | 
 |       if (dirchar) | 
 | 	{ | 
 | 	  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); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   TRACE(crtdll,"CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension); | 
 |    | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _getcwd           (CRTDLL.120) | 
 |  */ | 
 | CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT32 size) | 
 | { | 
 |   char test[1]; | 
 |   int len; | 
 |  | 
 |   len = size; | 
 |   if (!buf) { | 
 |     if (size < 0) /* allocate as big as nescessary */ | 
 |       len =GetCurrentDirectory32A(1,test) + 1; | 
 |     if(!(buf = CRTDLL_malloc(len))) | 
 |     { | 
 | 	/* set error to OutOfRange */ | 
 | 	return( NULL ); | 
 |     } | 
 |   } | 
 |   size = len; | 
 |   if(!(len =GetCurrentDirectory32A(len,buf))) | 
 |     { | 
 |       return NULL; | 
 |     } | 
 |   if (len > size) | 
 |     { | 
 |       /* set error to ERANGE */ | 
 |       TRACE(crtdll,"CRTDLL_getcwd buffer to small\n"); | 
 |       return NULL; | 
 |     } | 
 |   return buf; | 
 |  | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _getdcwd           (CRTDLL.121) | 
 |  */ | 
 | CHAR* __cdecl CRTDLL__getdcwd(INT32 drive,LPSTR buf, INT32 size) | 
 | { | 
 |   char test[1]; | 
 |   int len; | 
 |  | 
 |   FIXME(crtdll,"(\"%c:\",%s,%d)\n",drive+'A',buf,size); | 
 |   len = size; | 
 |   if (!buf) { | 
 |     if (size < 0) /* allocate as big as nescessary */ | 
 |       len =GetCurrentDirectory32A(1,test) + 1; | 
 |     if(!(buf = CRTDLL_malloc(len))) | 
 |     { | 
 | 	/* set error to OutOfRange */ | 
 | 	return( NULL ); | 
 |     } | 
 |   } | 
 |   size = len; | 
 |   if(!(len =GetCurrentDirectory32A(len,buf))) | 
 |     { | 
 |       return NULL; | 
 |     } | 
 |   if (len > size) | 
 |     { | 
 |       /* set error to ERANGE */ | 
 |       TRACE(crtdll,"buffer to small\n"); | 
 |       return NULL; | 
 |     } | 
 |   return buf; | 
 |  | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _getdrive           (CRTDLL.124) | 
 |  * | 
 |  *  Return current drive, 1 for A, 2 for B | 
 |  */ | 
 | INT32 __cdecl CRTDLL__getdrive(VOID) | 
 | { | 
 |     return DRIVE_GetCurrentDrive() + 1; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _mkdir           (CRTDLL.234) | 
 |  */ | 
 | INT32 __cdecl CRTDLL__mkdir(LPCSTR newdir) | 
 | { | 
 | 	if (!CreateDirectory32A(newdir,NULL)) | 
 | 		return -1; | 
 | 	return 0; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  remove           (CRTDLL.448) | 
 |  */ | 
 | INT32 __cdecl CRTDLL_remove(LPCSTR file) | 
 | { | 
 | 	if (!DeleteFile32A(file)) | 
 | 		return -1; | 
 | 	return 0; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _errno           (CRTDLL.52) | 
 |  * Yes, this is a function. | 
 |  */ | 
 | LPINT32 __cdecl CRTDLL__errno() | 
 | { | 
 | 	static	int crtdllerrno; | 
 | 	 | 
 | 	/* FIXME: we should set the error at the failing function call time */ | 
 | 	crtdllerrno = LastErrorToErrno(GetLastError()); | 
 | 	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(crtdll, "Unable to get unique filename\n"); | 
 |        return NULL; | 
 |      } | 
 |      if (!DOSFS_GetFullName(ret,FALSE,&tempname)) | 
 |      { | 
 |        TRACE(crtdll, "Wrong path?\n"); | 
 |        return NULL; | 
 |      } | 
 |      free(ret); | 
 |      if ((ret = CRTDLL_malloc(strlen(tempname.short_name)+1)) == NULL) { | 
 | 	 WARN(crtdll, "CRTDL_malloc for shortname failed\n"); | 
 | 	 return NULL; | 
 |      } | 
 |      if ((ret = strcpy(ret,tempname.short_name)) == NULL) {  | 
 |        WARN(crtdll, "Malloc for shortname failed\n"); | 
 |        return NULL; | 
 |      } | 
 |       | 
 |      TRACE(crtdll,"dir %s prefix %s got %s\n", | 
 | 		    dir,prefix,ret); | 
 |      return ret; | 
 |  | 
 | } | 
 | /********************************************************************* | 
 |  *                  tmpnam           (CRTDLL.490) | 
 |  * | 
 |  * lcclnk from lcc-win32 relies on a terminating dot in the name returned | 
 |  *  | 
 |  */ | 
 | LPSTR __cdecl CRTDLL_tmpnam(LPSTR s) | 
 | { | 
 |      char *ret; | 
 |  | 
 |      if ((ret =tmpnam(s))== NULL) { | 
 |        WARN(crtdll, "Unable to get unique filename\n"); | 
 |        return NULL; | 
 |      } | 
 |      if (!DOSFS_GetFullName(ret,FALSE,&CRTDLL_tmpname)) | 
 |      { | 
 |        TRACE(crtdll, "Wrong path?\n"); | 
 |        return NULL; | 
 |      } | 
 |      strcat(CRTDLL_tmpname.short_name,"."); | 
 |      TRACE(crtdll,"for buf %p got %s\n", | 
 | 		    s,CRTDLL_tmpname.short_name); | 
 |      TRACE(crtdll,"long got %s\n", | 
 | 		    CRTDLL_tmpname.long_name); | 
 |      if ( s != NULL)  | 
 |        return strcpy(s,CRTDLL_tmpname.short_name); | 
 |      else  | 
 |        return CRTDLL_tmpname.short_name; | 
 |  | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _itoa           (CRTDLL.165) | 
 |  */ | 
 | LPSTR  __cdecl CRTDLL__itoa(INT32 x,LPSTR buf,INT32 buflen) | 
 | { | 
 |     wsnprintf32A(buf,buflen,"%d",x); | 
 |     return buf; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _ltoa           (CRTDLL.180) | 
 |  */ | 
 | LPSTR  __cdecl CRTDLL__ltoa(long x,LPSTR buf,INT32 radix) | 
 | { | 
 |     switch(radix) { | 
 |         case  2: FIXME(crtdll, "binary format not implemented !\n"); | 
 |                  break; | 
 |         case  8: wsnprintf32A(buf,0x80,"%o",x); | 
 |                  break; | 
 |         case 10: wsnprintf32A(buf,0x80,"%d",x); | 
 |                  break; | 
 |         case 16: wsnprintf32A(buf,0x80,"%x",x); | 
 |                  break; | 
 |         default: FIXME(crtdll, "radix %d not implemented !\n", radix); | 
 |     } | 
 |     return buf; | 
 | } | 
 |  | 
 | typedef VOID (*sig_handler_type)(VOID); | 
 |  | 
 | /********************************************************************* | 
 |  *                  signal           (CRTDLL.455) | 
 |  */ | 
 | VOID __cdecl CRTDLL_signal(int sig, sig_handler_type ptr) | 
 | { | 
 |     FIXME(crtdll, "(%d %p):stub.\n", sig, ptr); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _ftol           (CRTDLL.113) | 
 |  */ | 
 | LONG __cdecl CRTDLL__ftol(double fl) { | 
 | 	return (LONG)fl; | 
 | } | 
 | /********************************************************************* | 
 |  *                  _sleep           (CRTDLL.267) | 
 |  */ | 
 | VOID __cdecl CRTDLL__sleep(unsigned long timeout)  | 
 | { | 
 |   TRACE(crtdll,"CRTDLL__sleep for %ld milliseconds\n",timeout); | 
 |   Sleep((timeout)?timeout:1); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  getenv           (CRTDLL.437) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL_getenv(const char *name)  | 
 | { | 
 |      LPSTR environ = GetEnvironmentStrings32A(); | 
 |      LPSTR pp,pos = NULL; | 
 |      unsigned int length; | 
 |    | 
 |      for (pp = environ; (*pp); pp = pp + strlen(pp) +1) | 
 |        { | 
 | 	 pos =strchr(pp,'='); | 
 | 	 if (pos) | 
 | 	   length = pos -pp; | 
 | 	 else | 
 | 	   length = strlen(pp); | 
 | 	 if (!strncmp(pp,name,length)) break; | 
 |        } | 
 |      if ((pp)&& (pos))  | 
 |        { | 
 | 	 pp = pos+1; | 
 | 	 TRACE(crtdll,"got %s\n",pp); | 
 |        } | 
 |      FreeEnvironmentStrings32A( environ ); | 
 |      return pp; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _mbsrchr           (CRTDLL.223) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x) { | 
 | 	/* FIXME: handle multibyte strings */ | 
 | 	return strrchr(s,x); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  _memicmp           (CRTDLL.233)(NTDLL.868) | 
 |  * A stringcompare, without \0 check | 
 |  * RETURNS | 
 |  *	-1:if first string is alphabetically before second string | 
 |  *	1:if second ''    ''      ''          ''   first   '' | 
 |  *      0:if both are equal. | 
 |  */ | 
 | INT32 __cdecl CRTDLL__memicmp( | 
 | 	LPCSTR s1,	/* [in] first string */ | 
 | 	LPCSTR s2,	/* [in] second string */ | 
 | 	DWORD len	/* [in] length to compare */ | 
 | ) {  | 
 | 	int	i; | 
 |  | 
 | 	for (i=0;i<len;i++) { | 
 | 		if (tolower(s1[i])<tolower(s2[i])) | 
 | 			return -1; | 
 | 		if (tolower(s1[i])>tolower(s2[i])) | 
 | 			return  1; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 | /********************************************************************* | 
 |  *                  __dllonexit           (CRTDLL.25) | 
 |  */ | 
 | VOID __cdecl CRTDLL__dllonexit () | 
 | {	 | 
 | 	FIXME(crtdll,"stub\n"); | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcstok           (CRTDLL.519) | 
 |  * Like strtok, but for wide character strings. s is modified, yes. | 
 |  */ | 
 | LPWSTR CRTDLL_wcstok(LPWSTR s,LPCWSTR delim) { | 
 | 	static LPWSTR nexttok = NULL; | 
 | 	LPWSTR	x,ret; | 
 |  | 
 | 	if (!s) | 
 | 		s = nexttok; | 
 | 	if (!s)	 | 
 | 		return NULL; | 
 | 	x = s; | 
 | 	while (*x && !CRTDLL_wcschr(delim,*x)) | 
 | 		x++; | 
 | 	ret = nexttok; | 
 | 	if (*x) { | 
 | 		*x='\0'; | 
 | 		nexttok = x+1; | 
 | 	} else | 
 | 		nexttok = NULL; | 
 | 	return ret; | 
 | } | 
 |  | 
 | /********************************************************************* | 
 |  *                  wcstol           (CRTDLL.520) | 
 |  * Like strtol, but for wide character strings. | 
 |  */ | 
 | INT32 CRTDLL_wcstol(LPWSTR s,LPWSTR *end,INT32 base) { | 
 | 	LPSTR	sA = HEAP_strdupWtoA(GetProcessHeap(),0,s),endA; | 
 | 	INT32	ret = strtol(sA,&endA,base); | 
 |  | 
 | 	HeapFree(GetProcessHeap(),0,sA); | 
 | 	if (end) *end = s+(endA-sA); /* pointer magic checked. */ | 
 | 	return ret; | 
 | } | 
 | /********************************************************************* | 
 |  *                  strdate           (CRTDLL.283) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__strdate (LPSTR date) | 
 | {	FIXME (crtdll,"%p stub\n", date); | 
 | 	return 0; | 
 | } | 
 | /********************************************************************* | 
 |  *                  strtime           (CRTDLL.299) | 
 |  */ | 
 | LPSTR __cdecl CRTDLL__strtime (LPSTR date) | 
 | {	FIXME (crtdll,"%p stub\n", date); | 
 | 	return 0; | 
 | } |