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