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