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