Release 980822
[wine] / misc / crtdll.c
1 /*
2  * The C RunTime DLL
3  * 
4  * Implements C run-time functionality as known from UNIX.
5  *
6  * Copyright 1996 Marcus Meissner
7  * Copyright 1996 Jukka Iivonen
8  * Copyright 1997 Uwe Bonnes
9  */
10
11 /*
12 Unresolved issues Uwe Bonnes 970904:
13 - Handling of Binary/Text Files is crude. If in doubt, use fromdos or recode
14 - Arguments in crtdll.spec for functions with double argument
15 - system-call calls another wine process, but without debugging arguments
16               and uses the first wine executable in the path
17 - tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
18                 for Win32, based on lcc, from Jacob Navia
19 */
20
21 /* FIXME: all the file handling is hopelessly broken -- AJ */
22
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/times.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <ctype.h>
32 #include <math.h>
33 #include <fcntl.h>
34 #include <setjmp.h>
35 #include "win.h"
36 #include "windows.h"
37 #include "winerror.h"
38 #include "debug.h"
39 #include "module.h"
40 #include "heap.h"
41 #include "crtdll.h"
42 #include "drive.h"
43 #include "file.h"
44 #include "except.h"
45 #include "options.h"
46 #include "winnls.h"
47
48 extern int FILE_GetUnixHandle( HFILE32  );
49
50 static DOS_FULL_NAME CRTDLL_tmpname;
51
52 UINT32 CRTDLL_argc_dll;         /* CRTDLL.23 */
53 LPSTR *CRTDLL_argv_dll;         /* CRTDLL.24 */
54 LPSTR  CRTDLL_acmdln_dll;       /* CRTDLL.38 */
55 UINT32 CRTDLL_basemajor_dll;    /* CRTDLL.42 */
56 UINT32 CRTDLL_baseminor_dll;    /* CRTDLL.43 */
57 UINT32 CRTDLL_baseversion_dll;  /* CRTDLL.44 */
58 UINT32 CRTDLL_commode_dll;      /* CRTDLL.59 */
59 LPSTR  CRTDLL_environ_dll;      /* CRTDLL.75 */
60 UINT32 CRTDLL_fmode_dll;        /* CRTDLL.104 */
61 UINT32 CRTDLL_osmajor_dll;      /* CRTDLL.241 */
62 UINT32 CRTDLL_osminor_dll;      /* CRTDLL.242 */
63 UINT32 CRTDLL_osmode_dll;       /* CRTDLL.243 */
64 UINT32 CRTDLL_osver_dll;        /* CRTDLL.244 */
65 UINT32 CRTDLL_osversion_dll;    /* CRTDLL.245 */
66 UINT32 CRTDLL_winmajor_dll;     /* CRTDLL.329 */
67 UINT32 CRTDLL_winminor_dll;     /* CRTDLL.330 */
68 UINT32 CRTDLL_winver_dll;       /* CRTDLL.331 */
69
70 BYTE CRTDLL_iob[32*3];  /* FIXME */
71
72 typedef VOID (*new_handler_type)(VOID);
73
74 static new_handler_type new_handler;
75
76 /*********************************************************************
77  *                  _GetMainArgs  (CRTDLL.022)
78  */
79 DWORD __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
80                                 LPSTR *environ,DWORD flag)
81 {
82         char *cmdline;
83         char  **xargv;
84         int     xargc,i,afterlastspace;
85         DWORD   version;
86
87         TRACE(crtdll,"(%p,%p,%p,%ld).\n",
88                 argc,argv,environ,flag
89         );
90         CRTDLL_acmdln_dll = cmdline = HEAP_strdupA( GetProcessHeap(), 0,
91                                                     GetCommandLine32A() );
92         TRACE(crtdll,"got '%s'\n", cmdline);
93
94         version = GetVersion32();
95         CRTDLL_osver_dll       = version >> 16;
96         CRTDLL_winminor_dll    = version & 0xFF;
97         CRTDLL_winmajor_dll    = (version>>8) & 0xFF;
98         CRTDLL_baseversion_dll = version >> 16;
99         CRTDLL_winver_dll      = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
100         CRTDLL_baseminor_dll   = (version >> 16) & 0xFF;
101         CRTDLL_basemajor_dll   = (version >> 24) & 0xFF;
102         CRTDLL_osversion_dll   = version & 0xFFFF;
103         CRTDLL_osminor_dll     = version & 0xFF;
104         CRTDLL_osmajor_dll     = (version>>8) & 0xFF;
105
106         /* missing threading init */
107
108         i=0;xargv=NULL;xargc=0;afterlastspace=0;
109         while (cmdline[i]) {
110                 if (cmdline[i]==' ') {
111                         xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
112                                                    sizeof(char*)*(++xargc));
113                         cmdline[i]='\0';
114                         xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0,
115                                                        cmdline+afterlastspace);
116                         i++;
117                         while (cmdline[i]==' ')
118                                 i++;
119                         if (cmdline[i])
120                                 afterlastspace=i;
121                 } else
122                         i++;
123         }
124         xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
125                                    sizeof(char*)*(++xargc));
126         cmdline[i]='\0';
127         xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0,
128                                        cmdline+afterlastspace);
129         CRTDLL_argc_dll = xargc;
130         *argc           = xargc;
131         CRTDLL_argv_dll = xargv;
132         *argv           = xargv;
133
134         TRACE(crtdll,"found %d arguments\n",
135                 CRTDLL_argc_dll);
136         CRTDLL_environ_dll = *environ = GetEnvironmentStrings32A();
137         return 0;
138 }
139
140
141 typedef void (*_INITTERMFUN)();
142
143  /*********************************************************************
144  *                  _findfirst    (CRTDLL.099)
145  * 
146  * BUGS
147  *   Unimplemented
148  */
149 DWORD __cdecl CRTDLL__findfirst(LPCSTR fname,struct find_t* x2)
150 {
151   FIXME(crtdll, ":(%s,%p): stub\n",fname,x2);
152   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
153   return FALSE;
154 }
155
156 /*********************************************************************
157  *                  _findnext     (CRTDLL.100)
158  * 
159  * BUGS
160  *   Unimplemented
161  */
162 INT32 __cdecl CRTDLL__findnext(DWORD hand,struct find_t* x2)
163 {
164   FIXME(crtdll, ":(%d,%p): stub\n",hand,x2);
165   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
166   return FALSE;
167 }
168
169 /*********************************************************************
170  *                  _fstat        (CRTDLL.111)
171  * 
172  * BUGS
173  *   Unimplemented
174  */
175 int __cdecl CRTDLL__fstat(int file, struct stat* buf)
176 {
177   FIXME(crtdll, ":(%d,%p): stub\n",file,buf);
178   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
179   return FALSE;
180 }
181
182 /*********************************************************************
183  *                  _initterm     (CRTDLL.135)
184  */
185 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
186 {
187         _INITTERMFUN    *current;
188
189         TRACE(crtdll,"(%p,%p)\n",start,end);
190         current=start;
191         while (current<end) {
192                 if (*current) (*current)();
193                 current++;
194         }
195         return 0;
196 }
197
198 /*********************************************************************
199  *                  _fdopen     (CRTDLL.91)
200  */
201 DWORD __cdecl CRTDLL__fdopen(INT32 handle, LPCSTR mode)
202 {
203   FILE *file;
204
205   switch (handle) 
206     {
207     case 0 : file=stdin;
208       break;
209     case 1 : file=stdout;
210       break;
211     case 2 : file=stderr;
212       break;
213     default:
214       file=fdopen(handle,mode);
215     }
216   TRACE(crtdll, "open handle %d mode %s  got file %p\n",
217                handle, mode, file);
218   return (DWORD)file;
219 }
220
221 static FILE *xlat_file_ptr(void *ptr)
222 {
223     unsigned long dif;
224     
225     /* CRT sizeof(FILE) == 32 */
226     dif = ((char *)ptr - (char *)CRTDLL_iob) / 32;
227     switch(dif)
228     {
229         case 0: return stdin;
230         case 1: return stdout;
231         case 2: return stderr;
232     }
233     return (FILE*)ptr;
234 }
235
236 /*******************************************************************
237  *         _global_unwind2  (CRTDLL.129)
238  */
239 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
240 {
241     RtlUnwind( frame, 0, NULL, 0 );
242 }
243
244 /*******************************************************************
245  *         _local_unwind2  (CRTDLL.173)
246  */
247 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
248 {
249     TRACE(crtdll,"(%p,%ld)\n",endframe,nr);
250 }
251 /*********************************************************************
252  *                  _read     (CRTDLL.256)
253  * 
254  * BUGS
255  *   Unimplemented
256  */
257 INT32 __cdecl CRTDLL__read(INT32 fd, LPVOID buf, UINT32 count)
258 {
259   FIXME(crtdll,":(%d,%p,%d): stub\n",fd,buf,count);
260   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
261   return FALSE;
262 }
263
264 /*********************************************************************
265  *                  fopen     (CRTDLL.372)
266  */
267 DWORD __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
268 {
269   FILE *file;
270   HFILE32 dos_fildes;
271 #if 0
272   DOS_FULL_NAME full_name;
273   
274   if (!DOSFS_GetFullName( path, FALSE, &full_name )) {
275     WARN(crtdll, "file %s bad name\n",path);
276    return 0;
277   }
278   
279   file=fopen(full_name.long_name ,mode);
280 #endif
281   INT32 flagmode=0;
282   int unix_fildes=0;
283
284   if ((strchr(mode,'r')&&strchr(mode,'a'))||
285       (strchr(mode,'r')&&strchr(mode,'w'))||
286       (strchr(mode,'w')&&strchr(mode,'a')))
287     return 0;
288        
289   if (strstr(mode,"r+")) flagmode=O_RDWR;
290   else if (strchr(mode,'r')) flagmode = O_RDONLY;
291   else if (strstr(mode,"w+")) flagmode= O_RDWR | O_TRUNC | O_CREAT;
292   else if (strchr(mode,'w')) flagmode = O_WRONLY | O_TRUNC | O_CREAT;
293   else if (strstr(mode,"a+")) flagmode= O_RDWR | O_CREAT | O_APPEND;
294   else if (strchr(mode,'w')) flagmode = O_RDWR | O_CREAT | O_APPEND;
295   else if (strchr(mode,'b'))
296     TRACE(crtdll, "%s in BINARY mode\n",path);
297       
298   dos_fildes=FILE_Open(path, flagmode);
299   unix_fildes=FILE_GetUnixHandle(dos_fildes);
300   file = fdopen(unix_fildes,mode);
301
302   TRACE(crtdll, "file %s mode %s got ufh %d dfh %d file %p\n",
303                  path,mode,unix_fildes,dos_fildes,file);
304   return (DWORD)file;
305 }
306
307 /*********************************************************************
308  *                  fread     (CRTDLL.377)
309  */
310 DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile)
311 {
312   size_t ret=1;
313   FILE *file=xlat_file_ptr(vfile);
314 #if 0
315   int i=0;
316   void *temp=ptr;
317
318   /* If we would honour CR/LF <-> LF translation, we could do it like this.
319      We should keep track of all files opened, and probably files with \
320      known binary extensions must be unchanged */
321   while ( (i < (nmemb*size)) && (ret==1)) {
322     ret=fread(temp,1,1,file);
323     TRACE(crtdll, "got %c 0x%02x ret %d\n",
324                  (isalpha(*(unsigned char*)temp))? *(unsigned char*)temp:
325                  ' ',*(unsigned char*)temp, ret);
326     if (*(unsigned char*)temp != 0xd) { /* skip CR */
327       temp++;
328       i++;
329     }
330     else
331       TRACE(crtdll, "skipping ^M\n");
332   }
333   TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n",
334                nmemb,size,file,ptr,);
335   if(i!=nmemb)
336     WARN(crtdll, " failed!\n");
337
338   return i;
339 #else
340     
341   ret=fread(ptr,size,nmemb,file);
342   TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n",
343                nmemb,size,file,ptr);
344   if(ret!=nmemb)
345     WARN(crtdll, " failed!\n");
346
347   return ret;
348 #endif
349 }
350 /*********************************************************************
351  *                  freopen    (CRTDLL.379)
352  * 
353  * BUGS
354  *   Unimplemented
355  */
356 DWORD __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode, LPVOID stream)
357 {
358   FIXME(crtdll, ":(%s,%s,%p): stub\n", path, mode, stream);
359   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
360   return FALSE;
361 }
362
363 /*********************************************************************
364  *                  fscanf     (CRTDLL.381)
365  */
366 INT32 __cdecl CRTDLL_fscanf( LPVOID stream, LPSTR format, ... )
367 {
368     va_list valist;
369     INT32 res;
370
371     va_start( valist, format );
372 #ifdef HAVE_VFSCANF
373     res = vfscanf( xlat_file_ptr(stream), format, valist );
374 #endif
375     va_end( valist );
376     return res;
377 }
378
379 /*********************************************************************
380  *                  fseek     (CRTDLL.382)
381  */
382 LONG __cdecl CRTDLL_fseek(LPVOID stream, LONG offset, INT32 whence)
383 {
384   long ret;
385
386   ret=fseek(xlat_file_ptr(stream),offset,whence);
387   TRACE(crtdll, "file %p to 0x%08lx pos %s\n",
388                stream,offset,(whence==SEEK_SET)?"SEEK_SET":
389                (whence==SEEK_CUR)?"SEEK_CUR":
390                (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
391   if(ret)
392     WARN(crtdll, " failed!\n");
393
394   return ret;
395 }
396   
397 /*********************************************************************
398  *                  fsetpos     (CRTDLL.383)
399  */
400 INT32 __cdecl CRTDLL_fsetpos(LPVOID stream, fpos_t *pos)
401 {
402   TRACE(crtdll, "file %p\n", stream);
403   return fseek(xlat_file_ptr(stream), *pos, SEEK_SET);
404 }
405
406 /*********************************************************************
407  *                  ftell     (CRTDLL.384)
408  */
409 LONG __cdecl CRTDLL_ftell(LPVOID stream)
410 {
411   long ret;
412
413   ret=ftell(xlat_file_ptr(stream));
414   TRACE(crtdll, "file %p at 0x%08lx\n",
415                stream,ret);
416   return ret;
417 }
418   
419 /*********************************************************************
420  *                  fwrite     (CRTDLL.386)
421  */
422 DWORD __cdecl CRTDLL_fwrite(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile)
423 {
424   size_t ret;
425   FILE *file=xlat_file_ptr(vfile);
426
427   ret=fwrite(ptr,size,nmemb,file);
428   TRACE(crtdll, "0x%08x items of size %d from %p to file %p\n",
429                nmemb,size,ptr,file);
430   if(ret!=nmemb)
431     WARN(crtdll, " Failed!\n");
432
433   return ret;
434 }
435
436 /*********************************************************************
437  *                  setbuf     (CRTDLL.452)
438  */
439 INT32 __cdecl CRTDLL_setbuf(LPVOID file, LPSTR buf)
440 {
441   TRACE(crtdll, "(file %p buf %p)\n", file, buf);
442   /* this doesn't work:"void value not ignored as it ought to be" 
443   return setbuf(file,buf); 
444   */
445   setbuf(xlat_file_ptr(file),buf);
446   return 0;
447 }
448
449 /*********************************************************************
450  *                  _open_osfhandle         (CRTDLL.240)
451  */
452 HFILE32 __cdecl CRTDLL__open_osfhandle(LONG osfhandle, INT32 flags)
453 {
454 HFILE32 handle;
455  
456         switch (osfhandle) {
457         case STD_INPUT_HANDLE :
458         case 0 :
459           handle=0;
460           break;
461         case STD_OUTPUT_HANDLE:
462         case 1:
463           handle=1;
464           break;
465         case STD_ERROR_HANDLE:
466         case 2:
467           handle=2;
468           break;
469         default:
470           return (-1);
471         }
472         TRACE(crtdll, "(handle %08lx,flags %d) return %d\n",
473                      osfhandle,flags,handle);
474         return handle;
475         
476 }
477
478 /*********************************************************************
479  *                  srand         (CRTDLL.460)
480  */
481 void __cdecl CRTDLL_srand(DWORD seed)
482 {
483         /* FIXME: should of course be thread? process? local */
484         srand(seed);
485 }
486
487 /*********************************************************************
488  *                  fprintf       (CRTDLL.373)
489  */
490 INT32 __cdecl CRTDLL_fprintf( FILE *file, LPSTR format, ... )
491 {
492     va_list valist;
493     INT32 res;
494
495     va_start( valist, format );
496     res = vfprintf( xlat_file_ptr(file), format, valist );
497     va_end( valist );
498     return res;
499 }
500
501 /*********************************************************************
502  *                  vfprintf       (CRTDLL.373)
503  */
504 INT32 __cdecl CRTDLL_vfprintf( FILE *file, LPSTR format, va_list args )
505 {
506     return vfprintf( xlat_file_ptr(file), format, args );
507 }
508
509 /*********************************************************************
510  *                  time          (CRTDLL.488)
511  */
512 time_t __cdecl CRTDLL_time(time_t *timeptr)
513 {
514         time_t  curtime = time(NULL);
515
516         if (timeptr)
517                 *timeptr = curtime;
518         return curtime;
519 }
520
521 /*********************************************************************
522  *                            (CRTDLL.350)
523  */
524 clock_t __cdecl CRTDLL_clock(void)
525 {
526         struct tms alltimes;
527         clock_t res;
528
529         times(&alltimes);
530         res = alltimes.tms_utime + alltimes.tms_stime+
531                alltimes.tms_cutime + alltimes.tms_cstime;
532         /* Fixme: We need some symbolic representation
533            for (Hostsystem_)CLOCKS_PER_SEC 
534            and (Emulated_system_)CLOCKS_PER_SEC
535            10 holds only for Windows/Linux_i86)
536            */
537         return 10*res;
538 }
539
540 /*********************************************************************
541  *                  _isatty       (CRTDLL.137)
542  */
543 BOOL32 __cdecl CRTDLL__isatty(DWORD x)
544 {
545         TRACE(crtdll,"(%ld)\n",x);
546         return TRUE;
547 }
548
549 /*********************************************************************
550  *                  _write        (CRTDLL.332)
551  */
552 INT32 __cdecl CRTDLL__write(INT32 fd,LPCVOID buf,UINT32 count)
553 {
554         INT32 len=0;
555
556         if (fd == -1)
557           len = -1;
558         else if (fd<=2)
559           len = (UINT32)write(fd,buf,(LONG)count);
560         else
561           len = _lwrite32(fd,buf,count);
562         TRACE(crtdll,"%d/%d byte to dfh %d from %p,\n",
563                        len,count,fd,buf);
564         return len;
565 }
566
567
568 /*********************************************************************
569  *                  _cexit          (CRTDLL.49)
570  *
571  *  FIXME: What the heck is the difference between 
572  *  FIXME           _c_exit         (CRTDLL.47)
573  *  FIXME           _cexit          (CRTDLL.49)
574  *  FIXME           _exit           (CRTDLL.87)
575  *  FIXME           exit            (CRTDLL.359)
576  *
577  * atexit-processing comes to mind -- MW.
578  *
579  */
580 void __cdecl CRTDLL__cexit(INT32 ret)
581 {
582         TRACE(crtdll,"(%d)\n",ret);
583         ExitProcess(ret);
584 }
585
586
587 /*********************************************************************
588  *                  exit          (CRTDLL.359)
589  */
590 void __cdecl CRTDLL_exit(DWORD ret)
591 {
592         TRACE(crtdll,"(%ld)\n",ret);
593         ExitProcess(ret);
594 }
595
596
597 /*********************************************************************
598  *                  _abnormal_termination          (CRTDLL.36)
599  */
600 INT32 __cdecl CRTDLL__abnormal_termination(void)
601 {
602         TRACE(crtdll,"(void)\n");
603         return 0;
604 }
605
606
607 /*********************************************************************
608  *                  _access          (CRTDLL.37)
609  */
610 INT32 __cdecl CRTDLL__access(LPCSTR filename, INT32 mode)
611 {
612     DWORD attr = GetFileAttributes32A(filename);
613
614     if (attr == -1)
615     {
616         if (GetLastError() == ERROR_INVALID_ACCESS)
617             errno = EACCES;
618         else
619             errno = ENOENT;
620         return -1;
621     }
622
623     if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
624     {
625         errno = EACCES;
626         return -1;
627     }
628     else
629         return 0;
630 }
631
632
633 /*********************************************************************
634  *                  fflush        (CRTDLL.365)
635  */
636 INT32 __cdecl CRTDLL_fflush(LPVOID stream)
637 {
638     int ret;
639
640     ret = fflush(xlat_file_ptr(stream));
641     TRACE(crtdll,"%p returnd %d\n",stream,ret);
642     if(ret)
643       WARN(crtdll, " Failed!\n");
644
645     return ret;
646 }
647
648
649 /*********************************************************************
650  *                  gets          (CRTDLL.391)
651  */
652 LPSTR __cdecl CRTDLL_gets(LPSTR buf)
653 {
654    char * ret;
655   /* BAD, for the whole WINE process blocks... just done this way to test
656    * windows95's ftp.exe.
657    */
658    ret = gets(buf);
659    TRACE(crtdll,"got %s\n",ret);
660    return ret;
661 }
662
663
664 /*********************************************************************
665  *                  rand          (CRTDLL.446)
666  */
667 INT32 __cdecl CRTDLL_rand()
668 {
669     return rand();
670 }
671
672
673 /*********************************************************************
674  *                  putchar       (CRTDLL.442)
675  */
676 void __cdecl CRTDLL_putchar( INT32 x )
677 {
678     putchar(x);
679 }
680
681
682 /*********************************************************************
683  *                  fputc       (CRTDLL.374)
684  */
685 INT32 __cdecl CRTDLL_fputc( INT32 c, FILE *stream )
686 {
687     TRACE(crtdll, "%c to file %p\n",c,stream);
688     return fputc(c,xlat_file_ptr(stream));
689 }
690
691
692 /*********************************************************************
693  *                  fputs       (CRTDLL.375)
694  */
695 INT32 __cdecl CRTDLL_fputs( LPCSTR s, FILE *stream )
696 {
697     TRACE(crtdll, "%s to file %p\n",s,stream);
698     return fputs(s,xlat_file_ptr(stream));
699 }
700
701
702 /*********************************************************************
703  *                  puts       (CRTDLL.443)
704  */
705 INT32 __cdecl CRTDLL_puts(LPCSTR s)
706 {
707     TRACE(crtdll, "%s \n",s);
708     return puts(s);
709 }
710
711
712 /*********************************************************************
713  *                  putc       (CRTDLL.441)
714  */
715 INT32 __cdecl CRTDLL_putc(INT32 c, FILE *stream)
716 {
717     TRACE(crtdll, " %c to file %p\n",c,stream);
718     return fputc(c,xlat_file_ptr(stream));
719 }
720 /*********************************************************************
721  *                  fgetc       (CRTDLL.366)
722  */
723 INT32 __cdecl CRTDLL_fgetc( FILE *stream )
724 {
725   int ret= fgetc(xlat_file_ptr(stream));
726   TRACE(crtdll, "got %d\n",ret);
727   return ret;
728 }
729
730
731 /*********************************************************************
732  *                  getc       (CRTDLL.388)
733  */
734 INT32 __cdecl CRTDLL_getc( FILE *stream )
735 {
736   int ret= fgetc(xlat_file_ptr(stream));
737   TRACE(crtdll, "got %d\n",ret);
738   return ret;
739 }
740
741 /*********************************************************************
742  *                  _rotl          (CRTDLL.259)
743  */
744 UINT32 __cdecl CRTDLL__rotl(UINT32 x,INT32 shift)
745 {
746    unsigned int ret = (x >> shift)|( x >>((sizeof(x))-shift));
747
748    TRACE(crtdll, "got 0x%08x rot %d ret 0x%08x\n",
749                   x,shift,ret);
750    return ret;
751     
752 }
753 /*********************************************************************
754  *                  _lrotl          (CRTDLL.176)
755  */
756 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT32 shift)
757 {
758    unsigned long ret = (x >> shift)|( x >>((sizeof(x))-shift));
759
760    TRACE(crtdll, "got 0x%08lx rot %d ret 0x%08lx\n",
761                   x,shift,ret);
762    return ret;
763     
764 }
765
766
767 /*********************************************************************
768  *                  fgets       (CRTDLL.368)
769  */
770 CHAR* __cdecl CRTDLL_fgets(LPSTR s,INT32 size, LPVOID stream)
771 {
772   char * ret;
773   char * control_M;
774   
775   ret=fgets(s, size,xlat_file_ptr(stream));
776   /*FIXME: Control with CRTDLL_setmode */
777   control_M= strrchr(s,'\r');
778   /*delete CR if we read a DOS File */
779   if (control_M)
780     {
781       *control_M='\n';
782       *(control_M+1)=0;
783     }
784   TRACE(crtdll, "got %s for %d chars from file %p\n",
785                  s,size,stream);
786   if(ret)
787     WARN(crtdll, " Failed!\n");
788
789   return ret;
790 }
791
792
793 /*********************************************************************
794  *                  _mbsicmp      (CRTDLL.204)
795  */
796 int __cdecl CRTDLL__mbsicmp(unsigned char *x,unsigned char *y)
797 {
798     do {
799         if (!*x)
800             return !!*y;
801         if (!*y)
802             return !!*x;
803         /* FIXME: MBCS handling... */
804         if (*x!=*y)
805             return 1;
806         x++;
807         y++;
808     } while (1);
809 }
810
811
812 /*********************************************************************
813  *                  _mbsinc       (CRTDLL.205)
814  */
815 unsigned char * __cdecl CRTDLL__mbsinc(unsigned char *x)
816 {
817     /* FIXME: mbcs */
818     return x++;
819 }
820
821
822 /*********************************************************************
823  *                  vsprintf      (CRTDLL.500)
824  */
825 INT32 __cdecl CRTDLL_vsprintf( LPSTR buffer, LPCSTR spec, va_list args )
826 {
827     return wvsprintf32A( buffer, spec, args );
828 }
829
830 /*********************************************************************
831  *                  vswprintf      (CRTDLL.501)
832  */
833 INT32 __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
834 {
835     return wvsprintf32W( buffer, spec, args );
836 }
837
838 /*********************************************************************
839  *                  _mbscpy       (CRTDLL.200)
840  */
841 unsigned char* __cdecl CRTDLL__mbscpy(unsigned char *x,unsigned char *y)
842 {
843     TRACE(crtdll,"CRTDLL_mbscpy %s and %s\n",x,y);
844     return strcpy(x,y);
845 }
846
847
848 /*********************************************************************
849  *                  _mbscat       (CRTDLL.197)
850  */
851 unsigned char* __cdecl CRTDLL__mbscat(unsigned char *x,unsigned char *y)
852 {
853     return strcat(x,y);
854 }
855
856
857 /*********************************************************************
858  *                  _strcmpi   (CRTDLL.282) (CRTDLL.287)
859  */
860 INT32 __cdecl CRTDLL__strcmpi( LPCSTR s1, LPCSTR s2 )
861 {
862     return lstrcmpi32A( s1, s2 );
863 }
864
865
866 /*********************************************************************
867  *                  _strnicmp   (CRTDLL.293)
868  */
869 INT32 __cdecl CRTDLL__strnicmp( LPCSTR s1, LPCSTR s2, INT32 n )
870 {
871     return lstrncmpi32A( s1, s2, n );
872 }
873
874
875 /*********************************************************************
876  *                  _strlwr      (CRTDLL.293)
877  *
878  * convert a string in place to lowercase 
879  */
880 LPSTR CRTDLL__strlwr(LPSTR x)
881 {
882   unsigned char *y =x;
883   
884   TRACE(crtdll, "CRTDLL_strlwr got %s\n", x);
885   while (*y) {
886     if ((*y > 0x40) && (*y< 0x5b))
887       *y = *y + 0x20;
888     y++;
889   }
890   TRACE(crtdll, "   returned %s\n", x);
891                  
892   return x;
893 }
894
895 /*********************************************************************
896  *                  system       (CRTDLL.485)
897  */
898 INT32 CRTDLL_system(LPSTR x)
899 {
900 #define SYSBUF_LENGTH 1500
901   char buffer[SYSBUF_LENGTH];
902   unsigned char *y = x;
903   unsigned char *bp;
904   int i;
905
906   sprintf( buffer, "%s \"", Options.argv0 );
907   bp = buffer + strlen(buffer);
908   i = strlen(buffer) + strlen(x) +2;
909
910   /* Calculate needed buffer size to prevent overflow.  */
911   while (*y) {
912     if (*y =='\\') i++;
913     y++;
914   }
915   /* If buffer too short, exit.  */
916   if (i > SYSBUF_LENGTH) {
917     TRACE(crtdll,"_system buffer to small\n");
918     return 127;
919   }
920   
921   y =x;
922
923   while (*y) {
924     *bp = *y;
925     bp++; y++;
926     if (*(y-1) =='\\') *bp++ = '\\';
927   }
928   /* Remove spaces from end of string.  */
929   while (*(y-1) == ' ') {
930     bp--;y--;
931   }
932   *bp++ = '"';
933   *bp = 0;
934   TRACE(crtdll, "_system got '%s', executing '%s'\n",x,buffer);
935
936   return system(buffer);
937 }
938
939 /*********************************************************************
940  *                  _strupr       (CRTDLL.300)
941  */
942 LPSTR __cdecl CRTDLL__strupr(LPSTR x)
943 {
944         LPSTR   y=x;
945
946         while (*y) {
947                 *y=toupper(*y);
948                 y++;
949         }
950         return x;
951 }
952
953 /*********************************************************************
954  *                  _wcsupr       (CRTDLL.328)
955  */
956 LPWSTR __cdecl CRTDLL__wcsupr(LPWSTR x)
957 {
958         LPWSTR  y=x;
959
960         while (*y) {
961                 *y=towupper(*y);
962                 y++;
963         }
964         return x;
965 }
966
967 /*********************************************************************
968  *                  _wcslwr       (CRTDLL.323)
969  */
970 LPWSTR __cdecl CRTDLL__wcslwr(LPWSTR x)
971 {
972         LPWSTR  y=x;
973
974         while (*y) {
975                 *y=towlower(*y);
976                 y++;
977         }
978         return x;
979 }
980
981
982 /*********************************************************************
983  *                  longjmp        (CRTDLL.426)
984  */
985 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
986 {
987     FIXME(crtdll,"CRTDLL_longjmp semistup, expect crash\n");
988     return longjmp(env, val);
989 }
990
991 /*********************************************************************
992  *                  malloc        (CRTDLL.427)
993  */
994 VOID* __cdecl CRTDLL_malloc(DWORD size)
995 {
996     return HeapAlloc(GetProcessHeap(),0,size);
997 }
998
999 /*********************************************************************
1000  *                  new           (CRTDLL.001)
1001  */
1002 VOID* __cdecl CRTDLL_new(DWORD size)
1003 {
1004     VOID* result;
1005     if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
1006         (*new_handler)();
1007     return result;
1008 }
1009
1010 /*********************************************************************
1011  *                  set_new_handler(CRTDLL.003)
1012  */
1013 new_handler_type __cdecl CRTDLL_set_new_handler(new_handler_type func)
1014 {
1015     new_handler_type old_handler = new_handler;
1016     new_handler = func;
1017     return old_handler;
1018 }
1019
1020 /*********************************************************************
1021  *                  calloc        (CRTDLL.350)
1022  */
1023 VOID* __cdecl CRTDLL_calloc(DWORD size, DWORD count)
1024 {
1025     return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
1026 }
1027
1028 /*********************************************************************
1029  *                  realloc        (CRTDLL.447)
1030  */
1031 VOID* __cdecl CRTDLL_realloc( VOID *ptr, DWORD size )
1032 {
1033     return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
1034 }
1035
1036 /*********************************************************************
1037  *                  free          (CRTDLL.427)
1038  */
1039 VOID __cdecl CRTDLL_free(LPVOID ptr)
1040 {
1041     HeapFree(GetProcessHeap(),0,ptr);
1042 }
1043
1044 /*********************************************************************
1045  *                  delete       (CRTDLL.002)
1046  */
1047 VOID __cdecl CRTDLL_delete(VOID* ptr)
1048 {
1049     HeapFree(GetProcessHeap(),0,ptr);
1050 }
1051
1052 /*********************************************************************
1053  *                  _strdup          (CRTDLL.285)
1054  */
1055 LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr)
1056 {
1057     return HEAP_strdupA(GetProcessHeap(),0,ptr);
1058 }
1059
1060 /*********************************************************************
1061  *                  _wcsdup          (CRTDLL.320)
1062  */
1063 LPWSTR __cdecl CRTDLL__wcsdup(LPCWSTR ptr)
1064 {
1065     return HEAP_strdupW(GetProcessHeap(),0,ptr);
1066 }
1067
1068 /*********************************************************************
1069  *                  fclose           (CRTDLL.362)
1070  */
1071 INT32 __cdecl CRTDLL_fclose( FILE *stream )
1072 {
1073     int unix_handle;
1074     HFILE32 dos_handle=1;
1075     HFILE32 ret=EOF;
1076
1077     stream=xlat_file_ptr(stream);
1078     unix_handle=fileno(stream);
1079
1080     if (unix_handle<4) ret= fclose(stream);
1081     else {
1082       while(FILE_GetUnixHandle(dos_handle) != unix_handle) dos_handle++;
1083       fclose(stream);
1084       ret = _lclose32( dos_handle);
1085     }
1086     TRACE(crtdll,"(%p) ufh %d dfh %d\n",
1087                    stream,unix_handle,dos_handle);
1088
1089     if(ret)
1090       WARN(crtdll, " Failed!\n");
1091
1092     return ret;
1093 }
1094
1095 /*********************************************************************
1096  *                  _unlink           (CRTDLL.315)
1097  */
1098 INT32 __cdecl CRTDLL__unlink(LPCSTR pathname)
1099 {
1100     int ret=0;
1101     DOS_FULL_NAME full_name;
1102
1103     if (!DOSFS_GetFullName( pathname, FALSE, &full_name )) {
1104       WARN(crtdll, "CRTDLL_unlink file %s bad name\n",pathname);
1105       return EOF;
1106     }
1107   
1108     ret=unlink(full_name.long_name);
1109     TRACE(crtdll,"(%s unix %s)\n",
1110                    pathname,full_name.long_name);
1111     if(ret)
1112       WARN(crtdll, " Failed!\n");
1113
1114     return ret;
1115 }
1116
1117 /*********************************************************************
1118  *                  rename           (CRTDLL.449)
1119  */
1120 INT32 __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath)
1121 {
1122     BOOL32 ok = MoveFileEx32A( oldpath, newpath, MOVEFILE_REPLACE_EXISTING );
1123     return ok ? 0 : -1;
1124 }
1125
1126
1127 /*********************************************************************
1128  *                  _stat          (CRTDLL.280)
1129  */
1130
1131 struct win_stat
1132 {
1133     UINT16 win_st_dev;
1134     UINT16 win_st_ino;
1135     UINT16 win_st_mode;
1136     INT16  win_st_nlink;
1137     INT16  win_st_uid;
1138     INT16  win_st_gid;
1139     UINT32 win_st_rdev;
1140     INT32  win_st_size;
1141     INT32  win_st_atime;
1142     INT32  win_st_mtime;
1143     INT32  win_st_ctime;
1144 };
1145
1146 int __cdecl CRTDLL__stat(const char * filename, struct win_stat * buf)
1147 {
1148     int ret=0;
1149     DOS_FULL_NAME full_name;
1150     struct stat mystat;
1151
1152     if (!DOSFS_GetFullName( filename, TRUE, &full_name ))
1153     {
1154       WARN(crtdll, "CRTDLL__stat filename %s bad name\n",filename);
1155       return -1;
1156     }
1157     ret=stat(full_name.long_name,&mystat);
1158     TRACE(crtdll,"CRTDLL__stat %s\n", filename);
1159     if(ret) 
1160       WARN(crtdll, " Failed!\n");
1161
1162     /* FIXME: should check what Windows returns */
1163
1164     buf->win_st_dev   = mystat.st_dev;
1165     buf->win_st_ino   = mystat.st_ino;
1166     buf->win_st_mode  = mystat.st_mode;
1167     buf->win_st_nlink = mystat.st_nlink;
1168     buf->win_st_uid   = mystat.st_uid;
1169     buf->win_st_gid   = mystat.st_gid;
1170     buf->win_st_rdev  = mystat.st_rdev;
1171     buf->win_st_size  = mystat.st_size;
1172     buf->win_st_atime = mystat.st_atime;
1173     buf->win_st_mtime = mystat.st_mtime;
1174     buf->win_st_ctime = mystat.st_ctime;
1175     return ret;
1176 }
1177
1178 /*********************************************************************
1179  *                  _open           (CRTDLL.239)
1180  */
1181 HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags)
1182 {
1183     HFILE32 ret=0;
1184     int wineflags=0;
1185     
1186     /* FIXME:
1187        the flags in lcc's header differ from the ones in Linux, e.g.
1188        Linux: define O_APPEND         02000   (= 0x400)
1189        lcc:  define _O_APPEND       0x0008  
1190        so here a scheme to translate them
1191        Probably lcc is wrong here, but at least a hack to get is going
1192        */
1193     wineflags = (flags & 3);
1194     if (flags & 0x0008 ) wineflags |= O_APPEND;
1195     if (flags & 0x0100 ) wineflags |= O_CREAT;
1196     if (flags & 0x0200 ) wineflags |= O_TRUNC;
1197     if (flags & 0x0400 ) wineflags |= O_EXCL;
1198     if (flags & 0xf0f4 ) 
1199       TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags);
1200     /* End Fixme */
1201
1202     ret = FILE_Open(path,wineflags);
1203     TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x (lccmode 0x%04x) got dfh %d\n",
1204                    path,wineflags,flags,ret);
1205     return ret;
1206 }
1207
1208 /*********************************************************************
1209  *                  _close           (CRTDLL.57)
1210  */
1211 INT32 __cdecl CRTDLL__close(HFILE32 fd)
1212 {
1213     int ret=_lclose32(fd);
1214
1215     TRACE(crtdll,"(%d)\n",fd);
1216     if(ret)
1217       WARN(crtdll, " Failed!\n");
1218
1219     return ret;
1220 }
1221
1222 /*********************************************************************
1223  *                  feof           (CRTDLL.363)
1224  */
1225 INT32 __cdecl CRTDLL_feof( FILE *stream )
1226 {
1227     int ret;
1228     
1229     ret=feof(xlat_file_ptr(stream));
1230     TRACE(crtdll,"(%p) %s\n",stream,(ret)?"true":"false");
1231     return ret;
1232 }
1233
1234 /*********************************************************************
1235  *                  setlocale           (CRTDLL.453)
1236  */
1237 LPSTR __cdecl CRTDLL_setlocale(INT32 category,LPCSTR locale)
1238 {
1239         LPSTR categorystr;
1240
1241         switch (category) {
1242         case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
1243         case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
1244         case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
1245         case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
1246         case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
1247         case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
1248         default: categorystr = "UNKNOWN?";break;
1249         }
1250         FIXME(crtdll,"(%s,%s),stub!\n",categorystr,locale);
1251         return "C";
1252 }
1253
1254 /*********************************************************************
1255  *                  wcscat           (CRTDLL.503)
1256  */
1257 LPWSTR __cdecl CRTDLL_wcscat( LPWSTR s1, LPCWSTR s2 )
1258 {
1259     return lstrcat32W( s1, s2 );
1260 }
1261
1262 /*********************************************************************
1263  *                  wcschr           (CRTDLL.504)
1264  */
1265 LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR str,WCHAR xchar)
1266 {
1267         LPCWSTR s;
1268
1269         s=str;
1270         do {
1271                 if (*s==xchar)
1272                         return (LPWSTR)s;
1273         } while (*s++);
1274         return NULL;
1275 }
1276
1277 /*********************************************************************
1278  *                  wcscmp           (CRTDLL.505)
1279  */
1280 INT32 __cdecl CRTDLL_wcscmp( LPCWSTR s1, LPCWSTR s2 )
1281 {
1282     return lstrcmp32W( s1, s2 );
1283 }
1284
1285 /*********************************************************************
1286  *                  wcscpy           (CRTDLL.507)
1287  */
1288 LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR s1, LPCWSTR s2 )
1289 {
1290     return lstrcpy32W( s1, s2 );
1291 }
1292
1293 /*********************************************************************
1294  *                  wcscspn           (CRTDLL.508)
1295  */
1296 INT32 __cdecl CRTDLL_wcscspn(LPWSTR str,LPWSTR reject)
1297 {
1298         LPWSTR  s,t;
1299
1300         s=str;
1301         do {
1302                 t=reject;
1303                 while (*t) { if (*t==*s) break;t++;}
1304                 if (*t) break;
1305                 s++;
1306         } while (*s);
1307         return s-str; /* nr of wchars */
1308 }
1309
1310 /*********************************************************************
1311  *                  wcslen           (CRTDLL.510)
1312  */
1313 INT32 __cdecl CRTDLL_wcslen( LPCWSTR s )
1314 {
1315     return lstrlen32W( s );
1316 }
1317
1318 /*********************************************************************
1319  *                  wcsncat           (CRTDLL.511)
1320  */
1321 LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT32 n )
1322 {
1323     return lstrcatn32W( s1, s2, n );
1324 }
1325
1326 /*********************************************************************
1327  *                  wcsncmp           (CRTDLL.512)
1328  */
1329 INT32 __cdecl CRTDLL_wcsncmp( LPCWSTR s1, LPCWSTR s2, INT32 n )
1330 {
1331     return lstrncmp32W( s1, s2, n );
1332 }
1333
1334 /*********************************************************************
1335  *                  wcsncpy           (CRTDLL.513)
1336  */
1337 LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT32 n )
1338 {
1339     return lstrcpyn32W( s1, s2, n );
1340 }
1341
1342 /*********************************************************************
1343  *                  wcsspn           (CRTDLL.516)
1344  */
1345 INT32 __cdecl CRTDLL_wcsspn(LPWSTR str,LPWSTR accept)
1346 {
1347         LPWSTR  s,t;
1348
1349         s=str;
1350         do {
1351                 t=accept;
1352                 while (*t) { if (*t==*s) break;t++;}
1353                 if (!*t) break;
1354                 s++;
1355         } while (*s);
1356         return s-str; /* nr of wchars */
1357 }
1358
1359 /*********************************************************************
1360  *                  _wcsicmp           (CRTDLL.321)
1361  */
1362 DWORD __cdecl CRTDLL__wcsicmp( LPCWSTR s1, LPCWSTR s2 )
1363 {
1364     return lstrcmpi32W( s1, s2 );
1365 }
1366
1367 /*********************************************************************
1368  *                  _wcsicoll           (CRTDLL.322)
1369  */
1370 DWORD __cdecl CRTDLL__wcsicoll(LPCWSTR a1,LPCWSTR a2)
1371 {
1372     /* FIXME: handle collates */
1373     return lstrcmpi32W(a1,a2);
1374 }
1375
1376 /*********************************************************************
1377  *                  _wcsnicmp           (CRTDLL.324)
1378  */
1379 DWORD __cdecl CRTDLL__wcsnicmp( LPCWSTR s1, LPCWSTR s2, INT32 len )
1380 {
1381     return lstrncmpi32W( s1, s2, len );
1382 }
1383
1384 /*********************************************************************
1385  *                  wcscoll           (CRTDLL.506)
1386  */
1387 DWORD __cdecl CRTDLL_wcscoll(LPWSTR a1,LPWSTR a2)
1388 {
1389     /* FIXME: handle collates */
1390     return lstrcmp32W(a1,a2);
1391 }
1392
1393 /*********************************************************************
1394  *                  _wcsrev           (CRTDLL.326)
1395  */
1396 VOID __cdecl CRTDLL__wcsrev(LPWSTR s) {
1397         LPWSTR  e;
1398
1399         e=s;
1400         while (*e)
1401                 e++;
1402         while (s<e) {
1403                 WCHAR   a;
1404
1405                 a=*s;*s=*e;*e=a;
1406                 s++;e--;
1407         }
1408 }
1409
1410 /*********************************************************************
1411  *                  wcsstr           (CRTDLL.517)
1412  */
1413 LPWSTR __cdecl CRTDLL_wcsstr(LPWSTR s,LPWSTR b)
1414 {
1415         LPWSTR  x,y,c;
1416
1417         x=s;
1418         while (*x) {
1419                 if (*x==*b) {
1420                         y=x;c=b;
1421                         while (*y && *c && *y==*c) { c++;y++; }
1422                         if (!*c)
1423                                 return x;
1424                 }
1425                 x++;
1426         }
1427         return NULL;
1428 }
1429
1430 /*********************************************************************
1431  *                  wcstombs   (CRTDLL.521)
1432  */
1433 INT32 __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT32 len )
1434 {
1435     lstrcpynWtoA( dst, src, len );
1436     return strlen(dst);  /* FIXME: is this right? */
1437 }
1438
1439 /*********************************************************************
1440  *                  wcsrchr           (CRTDLL.515)
1441  */
1442 LPWSTR __cdecl CRTDLL_wcsrchr(LPWSTR str,WCHAR xchar)
1443 {
1444         LPWSTR  s;
1445
1446         s=str+lstrlen32W(str);
1447         do {
1448                 if (*s==xchar)
1449                         return s;
1450                 s--;
1451         } while (s>=str);
1452         return NULL;
1453 }
1454
1455 /*********************************************************************
1456  *                  _setmode           (CRTDLL.265)
1457  * FIXME: At present we ignore the request to translate CR/LF to LF.
1458  *
1459  * We allways translate when we read with fgets, we never do with fread
1460  *
1461  */
1462 INT32 __cdecl CRTDLL__setmode( INT32 fh,INT32 mode)
1463 {
1464         /* FIXME */
1465 #define O_TEXT     0x4000
1466 #define O_BINARY   0x8000
1467
1468         FIXME(crtdll, "on fhandle %d mode %s, STUB.\n",
1469                       fh,(mode=O_TEXT)?"O_TEXT":
1470                       (mode=O_BINARY)?"O_BINARY":"UNKNOWN");
1471         return -1;
1472 }
1473
1474 /*********************************************************************
1475  *                  _fpreset           (CRTDLL.107)
1476  */
1477 VOID __cdecl CRTDLL__fpreset(void)
1478 {
1479        FIXME(crtdll," STUB.\n");
1480 }
1481
1482 /*********************************************************************
1483  *                  atexit           (CRTDLL.345)
1484  */
1485 INT32 __cdecl CRTDLL_atexit(LPVOID x)
1486 {
1487         FIXME(crtdll,"(%p), STUB.\n",x);
1488         return 0; /* successful */
1489 }
1490
1491 /*********************************************************************
1492  *                  mblen          (CRTDLL.428)
1493  * FIXME: check multibyte support
1494  */
1495 WCHAR  __cdecl CRTDLL_mblen(CHAR *mb,INT32 size)
1496 {
1497
1498     int ret=1;
1499     
1500     if (!mb)
1501       ret = 0;
1502     else if ((size<1)||(!*(mb+1)))
1503       ret = -1;
1504     else if (!(*mb))
1505       ret =0;
1506       
1507     TRACE(crtdll,"CRTDLL_mlen %s for max %d bytes ret %d\n",mb,size,ret);
1508
1509     return ret;
1510 }
1511
1512 /*********************************************************************
1513  *                  mbstowcs           (CRTDLL.429)
1514  * FIXME: check multibyte support
1515  */
1516 INT32 __cdecl CRTDLL_mbstowcs(LPWSTR wcs, LPCSTR mbs, INT32 size)
1517 {
1518
1519 /* Slightly modified lstrcpynAtoW functions from memory/strings.c
1520  *  We need the number of characters transfered 
1521  *  FIXME: No multibyte support yet
1522  */
1523
1524     LPWSTR p = wcs;
1525     LPCSTR src= mbs;
1526     int ret, n=size;
1527
1528     while ((n-- > 0) && *src) {
1529       *p++ = (WCHAR)(unsigned char)*src++;
1530         }
1531     p++;
1532     ret = (p -wcs);
1533           
1534     TRACE(crtdll,"CRTDLL_mbstowcs %s for %d chars put %d wchars\n",
1535                    mbs,size,ret);
1536     return ret;
1537 }
1538
1539 /*********************************************************************
1540  *                  mbtowc           (CRTDLL.430)
1541  * FIXME: check multibyte support
1542  */
1543 WCHAR __cdecl CRTDLL_mbtowc(WCHAR* wc,CHAR* mb,INT32 size) 
1544 {
1545    int ret;
1546
1547    if (!mb)
1548      ret = 0;
1549    else if (!wc)
1550      ret =-1;
1551    else 
1552      if ( (ret = mblen(mb,size)) != -1 )
1553        {
1554          if (ret <= sizeof(char))
1555            *wc = (WCHAR) ((unsigned char)*mb);
1556         else
1557         ret=   -1;
1558         }   
1559      else
1560        ret = -1;
1561    
1562    TRACE(crtdll,"CRTDLL_mbtowc %s for %d chars\n",mb,size);
1563          
1564    return ret;
1565 }
1566
1567 /*********************************************************************
1568  *                  _isctype           (CRTDLL.138)
1569  */
1570 BOOL32 __cdecl CRTDLL__isctype(CHAR x,CHAR type)
1571 {
1572         if ((type & CRTDLL_SPACE) && isspace(x))
1573                 return TRUE;
1574         if ((type & CRTDLL_PUNCT) && ispunct(x))
1575                 return TRUE;
1576         if ((type & CRTDLL_LOWER) && islower(x))
1577                 return TRUE;
1578         if ((type & CRTDLL_UPPER) && isupper(x))
1579                 return TRUE;
1580         if ((type & CRTDLL_ALPHA) && isalpha(x))
1581                 return TRUE;
1582         if ((type & CRTDLL_DIGIT) && isdigit(x))
1583                 return TRUE;
1584         if ((type & CRTDLL_CONTROL) && iscntrl(x))
1585                 return TRUE;
1586         /* check CRTDLL_LEADBYTE */
1587         return FALSE;
1588 }
1589
1590 /*********************************************************************
1591  *                  _chdrive           (CRTDLL.52)
1592  *
1593  *  newdir      [I] drive to change to, A=1
1594  *
1595  */
1596 BOOL32 __cdecl CRTDLL__chdrive(INT32 newdrive)
1597 {
1598         /* FIXME: generates errnos */
1599         return DRIVE_SetCurrentDrive(newdrive-1);
1600 }
1601
1602 /*********************************************************************
1603  *                  _chdir           (CRTDLL.51)
1604  */
1605 INT32 __cdecl CRTDLL__chdir(LPCSTR newdir)
1606 {
1607         if (!SetCurrentDirectory32A(newdir))
1608                 return 1;
1609         return 0;
1610 }
1611
1612 /*********************************************************************
1613  *                  _fullpath           (CRTDLL.114)
1614  */
1615 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT32 size)
1616 {
1617   DOS_FULL_NAME full_name;
1618
1619   if (!buf)
1620   {
1621       size = 256;
1622       if(!(buf = CRTDLL_malloc(size))) return NULL;
1623   }
1624   if (!DOSFS_GetFullName( name, FALSE, &full_name )) return NULL;
1625   lstrcpyn32A(buf,full_name.short_name,size);
1626   TRACE(crtdll,"CRTDLL_fullpath got %s\n",buf);
1627   return buf;
1628 }
1629
1630 /*********************************************************************
1631  *                  _splitpath           (CRTDLL.279)
1632  */
1633 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
1634 {
1635   /* drive includes :
1636      directory includes leading and trailing (forward and backward slashes)
1637      filename without dot and slashes
1638      extension with leading dot
1639      */
1640   char * drivechar,*dirchar,*namechar;
1641
1642   TRACE(crtdll,"CRTDLL__splitpath got %s\n",path);
1643
1644   drivechar  = strchr(path,':');
1645   dirchar    = strrchr(path,'/');
1646   namechar   = strrchr(path,'\\');
1647   dirchar = MAX(dirchar,namechar);
1648   if (dirchar)
1649     namechar   = strrchr(dirchar,'.');
1650   else
1651     namechar   = strrchr(path,'.');
1652   
1653   
1654   if (drive) 
1655     {
1656       *drive = NULL;
1657       if (drivechar) 
1658         {
1659           strncat(drive,path,drivechar-path+1);
1660           path = drivechar+1;
1661         }
1662     }
1663   if (directory) 
1664     {
1665       *directory = NULL;
1666       if (dirchar)
1667         {
1668           strncat(directory,path,dirchar-path+1);
1669           path = dirchar+1;
1670         }
1671     }
1672   if (filename)
1673     {
1674       *filename = NULL;
1675       if (namechar)
1676         {
1677           strncat(filename,path,namechar-path);
1678           if (extension) 
1679             {
1680               *extension = NULL;
1681               strcat(extension,namechar);
1682             }
1683         }
1684     }
1685
1686   TRACE(crtdll,"CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
1687   
1688 }
1689
1690 /*********************************************************************
1691  *                  _getcwd           (CRTDLL.120)
1692  */
1693 CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT32 size)
1694 {
1695   char test[1];
1696   int len;
1697
1698   len = size;
1699   if (!buf) {
1700     if (size < 0) /* allocate as big as nescessary */
1701       len =GetCurrentDirectory32A(1,test) + 1;
1702     if(!(buf = CRTDLL_malloc(len)))
1703     {
1704         /* set error to OutOfRange */
1705         return( NULL );
1706     }
1707   }
1708   size = len;
1709   if(!(len =GetCurrentDirectory32A(len,buf)))
1710     {
1711       return NULL;
1712     }
1713   if (len > size)
1714     {
1715       /* set error to ERANGE */
1716       TRACE(crtdll,"CRTDLL_getcwd buffer to small\n");
1717       return NULL;
1718     }
1719   return buf;
1720
1721 }
1722
1723 /*********************************************************************
1724  *                  _getdrive           (CRTDLL.124)
1725  *
1726  *  Return current drive, 1 for A, 2 for B
1727  */
1728 INT32 __cdecl CRTDLL__getdrive(VOID)
1729 {
1730     return DRIVE_GetCurrentDrive() + 1;
1731 }
1732
1733 /*********************************************************************
1734  *                  _mkdir           (CRTDLL.234)
1735  */
1736 INT32 __cdecl CRTDLL__mkdir(LPCSTR newdir)
1737 {
1738         if (!CreateDirectory32A(newdir,NULL))
1739                 return -1;
1740         return 0;
1741 }
1742
1743 /*********************************************************************
1744  *                  _errno           (CRTDLL.52)
1745  * Yes, this is a function.
1746  */
1747 LPINT32 __cdecl CRTDLL__errno()
1748 {
1749         static  int crtdllerrno;
1750         
1751         /* FIXME: we should set the error at the failing function call time */
1752         crtdllerrno = LastErrorToErrno(GetLastError());
1753         return &crtdllerrno;
1754 }
1755
1756 /*********************************************************************
1757  *                  _tempnam           (CRTDLL.305)
1758  * 
1759  */
1760 LPSTR __cdecl CRTDLL__tempnam(LPCSTR dir, LPCSTR prefix)
1761 {
1762
1763      char *ret;
1764      DOS_FULL_NAME tempname;
1765      
1766      if ((ret = tempnam(dir,prefix))==NULL) {
1767        WARN(crtdll, "Unable to get unique filename\n");
1768        return NULL;
1769      }
1770      if (!DOSFS_GetFullName(ret,FALSE,&tempname))
1771      {
1772        TRACE(crtdll, "Wrong path?\n");
1773        return NULL;
1774      }
1775      free(ret);
1776      if ((ret = CRTDLL_malloc(strlen(tempname.short_name)+1)) == NULL) {
1777          WARN(crtdll, "CRTDL_malloc for shortname failed\n");
1778          return NULL;
1779      }
1780      if ((ret = strcpy(ret,tempname.short_name)) == NULL) { 
1781        WARN(crtdll, "Malloc for shortname failed\n");
1782        return NULL;
1783      }
1784      
1785      TRACE(crtdll,"dir %s prefix %s got %s\n",
1786                     dir,prefix,ret);
1787      return ret;
1788
1789 }
1790 /*********************************************************************
1791  *                  tmpnam           (CRTDLL.490)
1792  *
1793  * lcclnk from lcc-win32 relies on a terminating dot in the name returned
1794  * 
1795  */
1796 LPSTR __cdecl CRTDLL_tmpnam(LPSTR s)
1797 {
1798      char *ret;
1799
1800      if ((ret =tmpnam(s))== NULL) {
1801        WARN(crtdll, "Unable to get unique filename\n");
1802        return NULL;
1803      }
1804      if (!DOSFS_GetFullName(ret,FALSE,&CRTDLL_tmpname))
1805      {
1806        TRACE(crtdll, "Wrong path?\n");
1807        return NULL;
1808      }
1809      strcat(CRTDLL_tmpname.short_name,".");
1810      TRACE(crtdll,"for buf %p got %s\n",
1811                     s,CRTDLL_tmpname.short_name);
1812      TRACE(crtdll,"long got %s\n",
1813                     CRTDLL_tmpname.long_name);
1814      if ( s != NULL) 
1815        return strcpy(s,CRTDLL_tmpname.short_name);
1816      else 
1817        return CRTDLL_tmpname.short_name;
1818
1819 }
1820
1821 /*********************************************************************
1822  *                  _itoa           (CRTDLL.165)
1823  */
1824 LPSTR  __cdecl CRTDLL__itoa(INT32 x,LPSTR buf,INT32 buflen)
1825 {
1826     wsnprintf32A(buf,buflen,"%d",x);
1827     return buf;
1828 }
1829
1830 /*********************************************************************
1831  *                  _ltoa           (CRTDLL.180)
1832  */
1833 LPSTR  __cdecl CRTDLL__ltoa(long x,LPSTR buf,INT32 radix)
1834 {
1835     switch(radix) {
1836         case  2: FIXME(crtdll, "binary format not implemented !\n");
1837                  break;
1838         case  8: wsnprintf32A(buf,0x80,"%o",x);
1839                  break;
1840         case 10: wsnprintf32A(buf,0x80,"%d",x);
1841                  break;
1842         case 16: wsnprintf32A(buf,0x80,"%x",x);
1843                  break;
1844         default: FIXME(crtdll, "radix %d not implemented !\n", radix);
1845     }
1846     return buf;
1847 }
1848
1849 typedef VOID (*sig_handler_type)(VOID);
1850
1851 /*********************************************************************
1852  *                  signal           (CRTDLL.455)
1853  */
1854 VOID __cdecl CRTDLL_signal(int sig, sig_handler_type ptr)
1855 {
1856     FIXME(crtdll, "(%d %p):stub.\n", sig, ptr);
1857 }
1858
1859 /*********************************************************************
1860  *                  _ftol           (CRTDLL.113)
1861  */
1862 LONG __cdecl CRTDLL__ftol(double fl) {
1863         return (LONG)fl;
1864 }
1865 /*********************************************************************
1866  *                  _sleep           (CRTDLL.267)
1867  */
1868 VOID __cdecl CRTDLL__sleep(unsigned long timeout) 
1869 {
1870   TRACE(crtdll,"CRTDLL__sleep for %ld milliseconds\n",timeout);
1871   Sleep((timeout)?timeout:1);
1872 }
1873
1874 /*********************************************************************
1875  *                  getenv           (CRTDLL.437)
1876  */
1877 LPSTR __cdecl CRTDLL_getenv(const char *name) 
1878 {
1879      LPSTR environ = GetEnvironmentStrings32A();
1880      LPSTR pp,pos = NULL;
1881      unsigned int length;
1882   
1883      for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
1884        {
1885          pos =strchr(pp,'=');
1886          if (pos)
1887            length = pos -pp;
1888          else
1889            length = strlen(pp);
1890          if (!strncmp(pp,name,length)) break;
1891        }
1892      if ((pp)&& (pos)) 
1893        {
1894          pp = pos+1;
1895          TRACE(crtdll,"got %s\n",pp);
1896        }
1897      FreeEnvironmentStrings32A( environ );
1898      return pp;
1899 }
1900
1901 /*********************************************************************
1902  *                  _mbsrchr           (CRTDLL.223)
1903  */
1904 LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x) {
1905         /* FIXME: handle multibyte strings */
1906         return strrchr(s,x);
1907 }
1908
1909 /*********************************************************************
1910  *                  _memicmp           (CRTDLL.233)(NTDLL.868)
1911  * A stringcompare, without \0 check
1912  * RETURNS
1913  *      -1:if first string is alphabetically before second string
1914  *      1:if second ''    ''      ''          ''   first   ''
1915  *      0:if both are equal.
1916  */
1917 INT32 __cdecl CRTDLL__memicmp(
1918         LPCSTR s1,      /* [in] first string */
1919         LPCSTR s2,      /* [in] second string */
1920         DWORD len       /* [in] length to compare */
1921 ) { 
1922         int     i;
1923
1924         for (i=0;i<len;i++) {
1925                 if (tolower(s1[i])<tolower(s2[i]))
1926                         return -1;
1927                 if (tolower(s1[i])>tolower(s2[i]))
1928                         return  1;
1929         }
1930         return 0;
1931 }