4 * Implements C run-time functionality as known from UNIX.
6 * Copyright 1996,1998 Marcus Meissner
7 * Copyright 1996 Jukka Iivonen
8 * Copyright 1997,2000 Uwe Bonnes
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
20 - needs a proper stdio emulation based on Win32 file handles
21 - should set CRTDLL errno from GetLastError() in every function
23 - probably not thread safe
26 /* NOTE: This file also implements the wcs* functions. They _ARE_ in
27 * the newer Linux libcs, but use 4 byte wide characters, so are unusable,
28 * since we need 2 byte wide characters. - Marcus Meissner, 981031
39 #include <sys/times.h>
52 #include "debugtools.h"
61 DEFAULT_DEBUG_CHANNEL(crtdll);
63 /* windows.h RAND_MAX is smaller than normal RAND_MAX */
64 #define CRTDLL_RAND_MAX 0x7fff
66 static DOS_FULL_NAME CRTDLL_tmpname;
68 UINT CRTDLL_argc_dll; /* CRTDLL.23 */
69 LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
70 LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
71 UINT CRTDLL_basemajor_dll; /* CRTDLL.42 */
72 UINT CRTDLL_baseminor_dll; /* CRTDLL.43 */
73 UINT CRTDLL_baseversion_dll; /* CRTDLL.44 */
74 UINT CRTDLL_commode_dll; /* CRTDLL.59 */
75 LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
76 UINT CRTDLL_fmode_dll; /* CRTDLL.104 */
77 UINT CRTDLL_osmajor_dll; /* CRTDLL.241 */
78 UINT CRTDLL_osminor_dll; /* CRTDLL.242 */
79 UINT CRTDLL_osmode_dll; /* CRTDLL.243 */
80 UINT CRTDLL_osver_dll; /* CRTDLL.244 */
81 UINT CRTDLL_osversion_dll; /* CRTDLL.245 */
82 UINT CRTDLL_winmajor_dll; /* CRTDLL.329 */
83 UINT CRTDLL_winminor_dll; /* CRTDLL.330 */
84 UINT CRTDLL_winver_dll; /* CRTDLL.331 */
86 /* FIXME: structure layout is obviously not correct */
93 CRTDLL_FILE CRTDLL_iob[3];
95 static CRTDLL_FILE * const CRTDLL_stdin = &CRTDLL_iob[0];
96 static CRTDLL_FILE * const CRTDLL_stdout = &CRTDLL_iob[1];
97 static CRTDLL_FILE * const CRTDLL_stderr = &CRTDLL_iob[2];
99 typedef VOID (*new_handler_type)(VOID);
101 static new_handler_type new_handler;
103 #if defined(__GNUC__) && defined(__i386__)
104 #define USING_REAL_FPU
105 #define DO_FPU(x,y) __asm__ __volatile__( x " %0;fwait" : "=m" (y) : )
106 #define POP_FPU(x) DO_FPU("fstpl",x)
109 CRTDLL_FILE * __cdecl CRTDLL__fdopen(INT handle, LPCSTR mode);
111 /*********************************************************************
112 * CRTDLL_MainInit (CRTDLL.init)
114 BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
116 TRACE("(0x%08x,%ld,%p)\n",hinstDLL,fdwReason,lpvReserved);
118 if (fdwReason == DLL_PROCESS_ATTACH) {
119 CRTDLL__fdopen(0,"r");
120 CRTDLL__fdopen(1,"w");
121 CRTDLL__fdopen(2,"w");
126 /*********************************************************************
127 * _GetMainArgs (CRTDLL.022)
129 LPSTR * __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
130 LPSTR *environ,DWORD flag)
134 int xargc,end,last_arg,afterlastspace;
137 TRACE("(%p,%p,%p,%ld).\n",
138 argc,argv,environ,flag
141 if (CRTDLL_acmdln_dll != NULL)
142 HeapFree(GetProcessHeap(), 0, CRTDLL_acmdln_dll);
144 CRTDLL_acmdln_dll = cmdline = HEAP_strdupA( GetProcessHeap(), 0,
146 TRACE("got '%s'\n", cmdline);
148 version = GetVersion();
149 CRTDLL_osver_dll = version >> 16;
150 CRTDLL_winminor_dll = version & 0xFF;
151 CRTDLL_winmajor_dll = (version>>8) & 0xFF;
152 CRTDLL_baseversion_dll = version >> 16;
153 CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
154 CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
155 CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
156 CRTDLL_osversion_dll = version & 0xFFFF;
157 CRTDLL_osminor_dll = version & 0xFF;
158 CRTDLL_osmajor_dll = (version>>8) & 0xFF;
160 /* missing threading init */
162 end=0;last_arg=0;xargv=NULL;xargc=0;afterlastspace=0;
165 if ((cmdline[end]==' ') || (cmdline[end]=='\0'))
167 if (cmdline[end]=='\0')
171 /* alloc xargc + NULL entry */
172 xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
173 sizeof(char*)*(xargc+1));
174 if (strlen(cmdline+afterlastspace))
176 xargv[xargc] = HEAP_strdupA( GetProcessHeap(), 0,
177 cmdline+afterlastspace);
179 if (!last_arg) /* need to seek to the next arg ? */
182 while (cmdline[end]==' ')
189 xargv[xargc] = NULL; /* the last entry is NULL */
196 CRTDLL_argc_dll = xargc;
198 CRTDLL_argv_dll = xargv;
201 TRACE("found %d arguments\n",
203 CRTDLL_environ_dll = *environ = GetEnvironmentStringsA();
208 typedef void (*_INITTERMFUN)();
210 /* fixme: move to header */
213 time_t time_create; /* -1 when not avaiable */
214 time_t time_access; /* -1 when not avaiable */
216 unsigned long size; /* fixme: 64 bit ??*/
219 /*********************************************************************
220 * _findfirst (CRTDLL.099)
225 DWORD __cdecl CRTDLL__findfirst(LPCSTR fname, struct find_t * x2)
227 FIXME(":(%s,%p): stub\n",fname,x2);
228 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
232 /*********************************************************************
233 * _findnext (CRTDLL.100)
238 INT __cdecl CRTDLL__findnext(DWORD hand, struct find_t * x2)
240 FIXME(":(%ld,%p): stub\n",hand,x2);
241 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
245 /*********************************************************************
246 * _fstat (CRTDLL.111)
251 int __cdecl CRTDLL__fstat(int file, struct stat* buf)
253 FIXME(":(%d,%p): stub\n",file,buf);
254 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
258 /*********************************************************************
259 * _initterm (CRTDLL.135)
261 DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
263 _INITTERMFUN *current;
265 TRACE("(%p,%p)\n",start,end);
267 while (current<end) {
268 if (*current) (*current)();
274 /*********************************************************************
275 * _fsopen (CRTDLL.110)
277 CRTDLL_FILE * __cdecl CRTDLL__fsopen(LPCSTR x, LPCSTR y, INT z) {
278 FIXME("(%s,%s,%d),stub!\n",x,y,z);
282 /*********************************************************************
283 * _fdopen (CRTDLL.91)
285 CRTDLL_FILE * __cdecl CRTDLL__fdopen(INT handle, LPCSTR mode)
293 if (!file->handle) file->handle = GetStdHandle( STD_INPUT_HANDLE );
296 file = CRTDLL_stdout;
297 if (!file->handle) file->handle = GetStdHandle( STD_OUTPUT_HANDLE );
301 if (!file->handle) file->handle = GetStdHandle( STD_ERROR_HANDLE );
304 file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
305 file->handle = handle;
308 TRACE("open handle %d mode %s got file %p\n",
314 /*******************************************************************
315 * _global_unwind2 (CRTDLL.129)
317 void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
319 RtlUnwind( frame, 0, NULL, 0 );
322 /*******************************************************************
323 * _local_unwind2 (CRTDLL.173)
325 void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
327 TRACE("(%p,%ld)\n",endframe,nr);
329 /*******************************************************************
330 * _setjmp (CRTDLL.264)
332 INT __cdecl CRTDLL__setjmp(LPDWORD *jmpbuf)
334 FIXME(":(%p): stub\n",jmpbuf);
338 /*********************************************************************
341 CRTDLL_FILE * __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
343 CRTDLL_FILE *file = NULL;
346 DOS_FULL_NAME full_name;
348 if (!DOSFS_GetFullName( path, FALSE, &full_name )) {
349 WARN("file %s bad name\n",path);
353 file=fopen(full_name.long_name ,mode);
355 DWORD access = 0, creation = 0;
357 if ((strchr(mode,'r')&&strchr(mode,'a'))||
358 (strchr(mode,'r')&&strchr(mode,'w'))||
359 (strchr(mode,'w')&&strchr(mode,'a')))
364 access = GENERIC_READ;
365 creation = OPEN_EXISTING;
366 if (mode[1] == '+') access |= GENERIC_WRITE;
368 else if (mode[0] == 'w')
370 access = GENERIC_WRITE;
371 creation = CREATE_ALWAYS;
372 if (mode[1] == '+') access |= GENERIC_READ;
374 else if (mode[0] == 'a')
376 /* FIXME: there is no O_APPEND in CreateFile, should emulate it */
377 access = GENERIC_WRITE;
378 creation = OPEN_ALWAYS;
379 if (mode[1] == '+') access |= GENERIC_READ;
381 /* FIXME: should handle text/binary mode */
383 if ((handle = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
384 NULL, creation, FILE_ATTRIBUTE_NORMAL,
385 -1 )) != INVALID_HANDLE_VALUE)
387 file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
388 file->handle = handle;
390 TRACE("file %s mode %s got handle %d file %p\n",
391 path,mode,handle,file);
395 /*********************************************************************
398 DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT size, INT nmemb, CRTDLL_FILE *file)
404 /* If we would honour CR/LF <-> LF translation, we could do it like this.
405 We should keep track of all files opened, and probably files with \
406 known binary extensions must be unchanged */
407 while ( (i < (nmemb*size)) && (ret==1)) {
408 ret=fread(temp,1,1,file);
409 TRACE("got %c 0x%02x ret %d\n",
410 (isalpha(*(unsigned char*)temp))? *(unsigned char*)temp:
411 ' ',*(unsigned char*)temp, ret);
412 if (*(unsigned char*)temp != 0xd) { /* skip CR */
417 TRACE("skipping ^M\n");
419 TRACE("0x%08x items of size %d from file %p to %p\n",
420 nmemb,size,file,ptr,);
428 TRACE("0x%08x items of size %d from file %p to %p\n",
429 nmemb,size,file,ptr);
430 if (!ReadFile( file->handle, ptr, size * nmemb, &ret, NULL ))
436 /*********************************************************************
437 * freopen (CRTDLL.379)
442 DWORD __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode, LPVOID stream)
444 FIXME(":(%s,%s,%p): stub\n", path, mode, stream);
445 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
449 /*********************************************************************
450 * fscanf (CRTDLL.381)
452 INT __cdecl CRTDLL_fscanf( CRTDLL_FILE *stream, LPSTR format, ... )
458 va_start( valist, format );
460 res = vfscanf( xlat_file_ptr(stream), format, valist );
469 /*********************************************************************
470 * _lseek (CRTDLL.179)
472 LONG __cdecl CRTDLL__lseek( INT fd, LONG offset, INT whence)
474 TRACE("fd %d to 0x%08lx pos %s\n",
475 fd,offset,(whence==SEEK_SET)?"SEEK_SET":
476 (whence==SEEK_CUR)?"SEEK_CUR":
477 (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
478 return SetFilePointer( fd, offset, NULL, whence );
481 /*********************************************************************
484 LONG __cdecl CRTDLL_fseek( CRTDLL_FILE *file, LONG offset, INT whence)
486 TRACE("file %p to 0x%08lx pos %s\n",
487 file,offset,(whence==SEEK_SET)?"SEEK_SET":
488 (whence==SEEK_CUR)?"SEEK_CUR":
489 (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
490 if (SetFilePointer( file->handle, offset, NULL, whence ) != 0xffffffff)
496 /*********************************************************************
497 * fsetpos (CRTDLL.383)
499 INT __cdecl CRTDLL_fsetpos( CRTDLL_FILE *file, INT *pos )
501 TRACE("file %p pos %d\n", file, *pos );
502 return CRTDLL_fseek(file, *pos, SEEK_SET);
505 /*********************************************************************
508 LONG __cdecl CRTDLL_ftell( CRTDLL_FILE *file )
510 return SetFilePointer( file->handle, 0, NULL, SEEK_CUR );
513 /*********************************************************************
514 * fwrite (CRTDLL.386)
516 DWORD __cdecl CRTDLL_fwrite( LPVOID ptr, INT size, INT nmemb, CRTDLL_FILE *file )
520 TRACE("0x%08x items of size %d to file %p(%d) from %p\n",
521 nmemb,size,file,file-(CRTDLL_FILE*)CRTDLL_iob,ptr);
524 if (!WriteFile( file->handle, ptr, size * nmemb, &ret, NULL ))
529 /*********************************************************************
530 * setbuf (CRTDLL.452)
532 INT __cdecl CRTDLL_setbuf(CRTDLL_FILE *file, LPSTR buf)
534 TRACE("(file %p buf %p)\n", file, buf);
535 /* this doesn't work:"void value not ignored as it ought to be"
536 return setbuf(file,buf);
538 /* FIXME: no buffering for now */
542 /*********************************************************************
543 * _open_osfhandle (CRTDLL.240)
545 HFILE __cdecl CRTDLL__open_osfhandle(LONG osfhandle, INT flags)
550 case STD_INPUT_HANDLE :
554 case STD_OUTPUT_HANDLE:
558 case STD_ERROR_HANDLE:
565 TRACE("(handle %08lx,flags %d) return %d\n",
566 osfhandle,flags,handle);
571 /*********************************************************************
574 void __cdecl CRTDLL_srand(DWORD seed)
576 /* FIXME: should of course be thread? process? local */
580 /*********************************************************************
581 * vfprintf (CRTDLL.373)
583 INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE *file, LPSTR format, va_list args )
585 char buffer[2048]; /* FIXME... */
587 vsprintf( buffer, format, args );
588 return CRTDLL_fwrite( buffer, 1, strlen(buffer), file );
591 /*********************************************************************
592 * fprintf (CRTDLL.373)
594 INT __cdecl CRTDLL_fprintf( CRTDLL_FILE *file, LPSTR format, ... )
599 va_start( valist, format );
600 res = CRTDLL_vfprintf( file, format, valist );
605 /*********************************************************************
608 time_t __cdecl CRTDLL_time(time_t *timeptr)
610 time_t curtime = time(NULL);
617 /*********************************************************************
620 clock_t __cdecl CRTDLL_clock(void)
626 res = alltimes.tms_utime + alltimes.tms_stime+
627 alltimes.tms_cutime + alltimes.tms_cstime;
628 /* Fixme: We need some symbolic representation
629 for (Hostsystem_)CLOCKS_PER_SEC
630 and (Emulated_system_)CLOCKS_PER_SEC
631 10 holds only for Windows/Linux_i86)
636 /*********************************************************************
637 * _isatty (CRTDLL.137)
639 BOOL __cdecl CRTDLL__isatty(DWORD x)
645 /*********************************************************************
649 INT __cdecl CRTDLL__read(INT fd, LPVOID buf, UINT count)
651 TRACE("0x%08x bytes fd %d to %p\n", count,fd,buf);
652 if (!fd) fd = GetStdHandle( STD_INPUT_HANDLE );
653 return _lread( fd, buf, count );
656 /*********************************************************************
657 * _write (CRTDLL.332)
659 INT __cdecl CRTDLL__write(INT fd,LPCVOID buf,UINT count)
666 len = (UINT)write(fd,buf,(LONG)count);
668 len = _lwrite(fd,buf,count);
669 TRACE("%d/%d byte to dfh %d from %p,\n",
675 /*********************************************************************
678 * FIXME: What the heck is the difference between
679 * FIXME _c_exit (CRTDLL.47)
680 * FIXME _cexit (CRTDLL.49)
681 * FIXME _exit (CRTDLL.87)
682 * FIXME exit (CRTDLL.359)
684 * atexit-processing comes to mind -- MW.
687 void __cdecl CRTDLL__cexit(INT ret)
694 /*********************************************************************
697 void __cdecl CRTDLL_exit(DWORD ret)
699 TRACE("(%ld)\n",ret);
704 /*********************************************************************
705 * _abnormal_termination (CRTDLL.36)
707 INT __cdecl CRTDLL__abnormal_termination(void)
714 /*********************************************************************
715 * _access (CRTDLL.37)
717 INT __cdecl CRTDLL__access(LPCSTR filename, INT mode)
719 DWORD attr = GetFileAttributesA(filename);
723 if (GetLastError() == ERROR_INVALID_ACCESS)
730 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
740 /*********************************************************************
741 * fflush (CRTDLL.365)
743 INT __cdecl CRTDLL_fflush( CRTDLL_FILE *file )
745 return FlushFileBuffers( file->handle ) ? 0 : -1;
749 /*********************************************************************
752 INT __cdecl CRTDLL_rand()
754 return (rand() & CRTDLL_RAND_MAX);
758 /*********************************************************************
759 * putchar (CRTDLL.442)
761 void __cdecl CRTDLL_putchar( INT x )
767 /*********************************************************************
770 INT __cdecl CRTDLL_fputc( INT c, CRTDLL_FILE *file )
774 TRACE("%c to file %p\n",c,file);
775 if (!WriteFile( file->handle, &ch, 1, &res, NULL )) return -1;
780 /*********************************************************************
783 INT __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE *file )
786 TRACE("%s to file %p\n",s,file);
787 if (!WriteFile( file->handle, s, strlen(s), &res, NULL )) return -1;
792 /*********************************************************************
795 INT __cdecl CRTDLL_puts(LPCSTR s)
802 /*********************************************************************
805 INT __cdecl CRTDLL_putc( INT c, CRTDLL_FILE *file )
807 return CRTDLL_fputc( c, file );
810 /*********************************************************************
813 INT __cdecl CRTDLL_fgetc( CRTDLL_FILE *file )
817 if (!ReadFile( file->handle, &ch, 1, &res, NULL )) return -1;
818 if (res != 1) return -1;
823 /*********************************************************************
826 INT __cdecl CRTDLL_getc( CRTDLL_FILE *file )
828 return CRTDLL_fgetc( file );
832 /*********************************************************************
835 CHAR* __cdecl CRTDLL_fgets( LPSTR s, INT size, CRTDLL_FILE *file )
840 /* BAD, for the whole WINE process blocks... just done this way to test
841 * windows95's ftp.exe.
844 for(cc = CRTDLL_fgetc(file); cc != EOF && cc != '\n'; cc = CRTDLL_fgetc(file))
847 if (--size <= 0) break;
850 if ((cc == EOF) &&(s == buf_start)) /* If nothing read, return 0*/
857 TRACE("got '%s'\n", buf_start);
862 /*********************************************************************
865 LPSTR __cdecl CRTDLL_gets(LPSTR buf)
868 LPSTR buf_start = buf;
870 /* BAD, for the whole WINE process blocks... just done this way to test
871 * windows95's ftp.exe.
874 for(cc = fgetc(stdin); cc != EOF && cc != '\n'; cc = fgetc(stdin))
875 if(cc != '\r') *buf++ = (char)cc;
879 TRACE("got '%s'\n", buf_start);
884 /*********************************************************************
887 UINT __cdecl CRTDLL__rotl(UINT x,INT shift)
889 unsigned int ret = (x >> shift)|( x >>((sizeof(x))-shift));
891 TRACE("got 0x%08x rot %d ret 0x%08x\n",
896 /*********************************************************************
897 * _lrotl (CRTDLL.176)
899 DWORD __cdecl CRTDLL__lrotl(DWORD x,INT shift)
901 unsigned long ret = (x >> shift)|( x >>((sizeof(x))-shift));
903 TRACE("got 0x%08lx rot %d ret 0x%08lx\n",
910 /*********************************************************************
911 * _mbsicmp (CRTDLL.204)
913 int __cdecl CRTDLL__mbsicmp(unsigned char *x,unsigned char *y)
920 /* FIXME: MBCS handling... */
929 /*********************************************************************
930 * vsprintf (CRTDLL.500)
932 INT __cdecl CRTDLL_vsprintf( LPSTR buffer, LPCSTR spec, va_list args )
934 return wvsprintfA( buffer, spec, args );
937 /*********************************************************************
938 * vswprintf (CRTDLL.501)
940 INT __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
942 return wvsprintfW( buffer, spec, args );
945 /*********************************************************************
946 * _strcmpi (CRTDLL.282) (CRTDLL.287)
948 INT __cdecl CRTDLL__strcmpi( LPCSTR s1, LPCSTR s2 )
950 return lstrcmpiA( s1, s2 );
954 /*********************************************************************
955 * _strnicmp (CRTDLL.293)
957 INT __cdecl CRTDLL__strnicmp( LPCSTR s1, LPCSTR s2, INT n )
959 return lstrncmpiA( s1, s2, n );
963 /*********************************************************************
964 * _strlwr (CRTDLL.293)
966 * convert a string in place to lowercase
968 LPSTR __cdecl CRTDLL__strlwr(LPSTR x)
972 TRACE("CRTDLL_strlwr got %s\n", x);
974 if ((*y > 0x40) && (*y< 0x5b))
978 TRACE(" returned %s\n", x);
983 /*********************************************************************
984 * system (CRTDLL.485)
986 INT __cdecl CRTDLL_system(LPSTR x)
988 #define SYSBUF_LENGTH 1500
989 char buffer[SYSBUF_LENGTH];
990 unsigned char *y = x;
994 sprintf( buffer, "%s \"", argv0 );
995 bp = buffer + strlen(buffer);
996 i = strlen(buffer) + strlen(x) +2;
998 /* Calculate needed buffer size to prevent overflow. */
1003 /* If buffer too short, exit. */
1004 if (i > SYSBUF_LENGTH) {
1005 TRACE("_system buffer to small\n");
1014 if (*(y-1) =='\\') *bp++ = '\\';
1016 /* Remove spaces from end of string. */
1017 while (*(y-1) == ' ') {
1022 TRACE("_system got '%s', executing '%s'\n",x,buffer);
1024 return system(buffer);
1027 /*********************************************************************
1028 * _strupr (CRTDLL.300)
1030 LPSTR __cdecl CRTDLL__strupr(LPSTR x)
1041 /*********************************************************************
1042 * longjmp (CRTDLL.426)
1044 VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
1046 FIXME("CRTDLL_longjmp semistup, expect crash\n");
1050 /*********************************************************************
1051 * malloc (CRTDLL.427)
1053 VOID* __cdecl CRTDLL_malloc(DWORD size)
1055 return HeapAlloc(GetProcessHeap(),0,size);
1058 /*********************************************************************
1061 VOID* __cdecl CRTDLL_new(DWORD size)
1064 if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
1069 /*********************************************************************
1070 * set_new_handler(CRTDLL.003)
1072 new_handler_type __cdecl CRTDLL_set_new_handler(new_handler_type func)
1074 new_handler_type old_handler = new_handler;
1079 /*********************************************************************
1080 * calloc (CRTDLL.350)
1082 VOID* __cdecl CRTDLL_calloc(DWORD size, DWORD count)
1084 return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
1087 /*********************************************************************
1088 * realloc (CRTDLL.447)
1090 VOID* __cdecl CRTDLL_realloc( VOID *ptr, DWORD size )
1092 return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
1095 /*********************************************************************
1098 VOID __cdecl CRTDLL_free(LPVOID ptr)
1100 HeapFree(GetProcessHeap(),0,ptr);
1103 /*********************************************************************
1104 * delete (CRTDLL.002)
1106 VOID __cdecl CRTDLL_delete(VOID* ptr)
1108 HeapFree(GetProcessHeap(),0,ptr);
1111 /*********************************************************************
1112 * _strdup (CRTDLL.285)
1114 LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr)
1116 return HEAP_strdupA(GetProcessHeap(),0,ptr);
1119 /*********************************************************************
1120 * fclose (CRTDLL.362)
1122 INT __cdecl CRTDLL_fclose( CRTDLL_FILE *file )
1124 TRACE("%p\n", file );
1125 if (!CloseHandle( file->handle )) return -1;
1126 HeapFree( GetProcessHeap(), 0, file );
1130 /*********************************************************************
1131 * _unlink (CRTDLL.315)
1133 INT __cdecl CRTDLL__unlink(LPCSTR pathname)
1135 return DeleteFileA( pathname ) ? 0 : -1;
1138 /*********************************************************************
1139 * rename (CRTDLL.449)
1141 INT __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath)
1143 BOOL ok = MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING );
1148 /*********************************************************************
1149 * _stat (CRTDLL.280)
1167 int __cdecl CRTDLL__stat(const char * filename, struct win_stat * buf)
1170 DOS_FULL_NAME full_name;
1173 if (!DOSFS_GetFullName( filename, TRUE, &full_name ))
1175 WARN("CRTDLL__stat filename %s bad name\n",filename);
1178 ret=stat(full_name.long_name,&mystat);
1179 TRACE("CRTDLL__stat %s\n", filename);
1183 /* FIXME: should check what Windows returns */
1185 buf->win_st_dev = mystat.st_dev;
1186 buf->win_st_ino = mystat.st_ino;
1187 buf->win_st_mode = mystat.st_mode;
1188 buf->win_st_nlink = mystat.st_nlink;
1189 buf->win_st_uid = mystat.st_uid;
1190 buf->win_st_gid = mystat.st_gid;
1191 buf->win_st_rdev = mystat.st_rdev;
1192 buf->win_st_size = mystat.st_size;
1193 buf->win_st_atime = mystat.st_atime;
1194 buf->win_st_mtime = mystat.st_mtime;
1195 buf->win_st_ctime = mystat.st_ctime;
1199 /*********************************************************************
1200 * _open (CRTDLL.239)
1202 HFILE __cdecl CRTDLL__open(LPCSTR path,INT flags)
1204 DWORD access = 0, creation = 0;
1208 the flags in lcc's header differ from the ones in Linux, e.g.
1209 Linux: define O_APPEND 02000 (= 0x400)
1210 lcc: define _O_APPEND 0x0008
1211 so here a scheme to translate them
1212 Probably lcc is wrong here, but at least a hack to get is going
1216 case O_RDONLY: access |= GENERIC_READ; break;
1217 case O_WRONLY: access |= GENERIC_WRITE; break;
1218 case O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
1221 if (flags & 0x0100) /* O_CREAT */
1223 if (flags & 0x0400) /* O_EXCL */
1224 creation = CREATE_NEW;
1225 else if (flags & 0x0200) /* O_TRUNC */
1226 creation = CREATE_ALWAYS;
1228 creation = OPEN_ALWAYS;
1230 else /* no O_CREAT */
1232 if (flags & 0x0200) /* O_TRUNC */
1233 creation = TRUNCATE_EXISTING;
1235 creation = OPEN_EXISTING;
1237 if (flags & 0x0008) /* O_APPEND */
1238 FIXME("O_APPEND not supported\n" );
1239 if (!(flags & 0x8000 /* O_BINARY */ ) || (flags & 0x4000 /* O_TEXT */))
1240 FIXME(":text mode not supported\n");
1242 TRACE("CRTDLL_open file unsupported flags 0x%04x\n",flags);
1245 ret = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
1246 NULL, creation, FILE_ATTRIBUTE_NORMAL, -1 );
1247 TRACE("CRTDLL_open file %s mode 0x%04x got handle %d\n", path,flags,ret);
1251 /*********************************************************************
1252 * _close (CRTDLL.57)
1254 INT __cdecl CRTDLL__close(HFILE fd)
1256 int ret=_lclose(fd);
1265 /*********************************************************************
1267 * FIXME: Care for large files
1268 * FIXME: Check errors
1270 INT __cdecl CRTDLL_feof( CRTDLL_FILE *file )
1272 DWORD curpos=SetFilePointer( file->handle, 0, NULL, SEEK_CUR );
1273 DWORD endpos=SetFilePointer( file->handle, 0, NULL, FILE_END );
1278 SetFilePointer( file->handle, curpos,0,FILE_BEGIN);
1282 /*********************************************************************
1283 * setlocale (CRTDLL.453)
1285 LPSTR __cdecl CRTDLL_setlocale(INT category,LPCSTR locale)
1290 case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
1291 case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
1292 case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
1293 case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
1294 case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
1295 case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
1296 default: categorystr = "UNKNOWN?";break;
1298 FIXME("(%s,%s),stub!\n",categorystr,locale);
1302 /*********************************************************************
1303 * _setmode (CRTDLL.265)
1304 * FIXME: At present we ignore the request to translate CR/LF to LF.
1306 * We allways translate when we read with fgets, we never do with fread
1309 INT __cdecl CRTDLL__setmode( INT fh,INT mode)
1312 #define O_TEXT 0x4000
1313 #define O_BINARY 0x8000
1315 FIXME("on fhandle %d mode %s, STUB.\n",
1316 fh,(mode=O_TEXT)?"O_TEXT":
1317 (mode=O_BINARY)?"O_BINARY":"UNKNOWN");
1321 /*********************************************************************
1322 * _fpreset (CRTDLL.107)
1324 VOID __cdecl CRTDLL__fpreset(void)
1329 /*********************************************************************
1330 * atexit (CRTDLL.345)
1332 INT __cdecl CRTDLL_atexit(LPVOID x)
1334 FIXME("(%p), STUB.\n",x);
1335 return 0; /* successful */
1338 /*********************************************************************
1339 * _isctype (CRTDLL.138)
1341 BOOL __cdecl CRTDLL__isctype(CHAR x,CHAR type)
1343 if ((type & CRTDLL_SPACE) && isspace(x))
1345 if ((type & CRTDLL_PUNCT) && ispunct(x))
1347 if ((type & CRTDLL_LOWER) && islower(x))
1349 if ((type & CRTDLL_UPPER) && isupper(x))
1351 if ((type & CRTDLL_ALPHA) && isalpha(x))
1353 if ((type & CRTDLL_DIGIT) && isdigit(x))
1355 if ((type & CRTDLL_CONTROL) && iscntrl(x))
1357 /* check CRTDLL_LEADBYTE */
1361 /*********************************************************************
1362 * _chdrive (CRTDLL.52)
1364 * newdir [I] drive to change to, A=1
1367 BOOL __cdecl CRTDLL__chdrive(INT newdrive)
1369 /* FIXME: generates errnos */
1370 return DRIVE_SetCurrentDrive(newdrive-1);
1373 /*********************************************************************
1374 * _chdir (CRTDLL.51)
1376 INT __cdecl CRTDLL__chdir(LPCSTR newdir)
1378 if (!SetCurrentDirectoryA(newdir))
1383 /*********************************************************************
1384 * _fullpath (CRTDLL.114)
1386 LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT size)
1388 DOS_FULL_NAME full_name;
1393 if(!(buf = CRTDLL_malloc(size))) return NULL;
1395 if (!DOSFS_GetFullName( name, FALSE, &full_name )) return NULL;
1396 lstrcpynA(buf,full_name.short_name,size);
1397 TRACE("CRTDLL_fullpath got %s\n",buf);
1401 /*********************************************************************
1402 * _splitpath (CRTDLL.279)
1404 VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
1407 directory includes leading and trailing (forward and backward slashes)
1408 filename without dot and slashes
1409 extension with leading dot
1411 char * drivechar,*dirchar,*namechar;
1413 TRACE("CRTDLL__splitpath got %s\n",path);
1415 drivechar = strchr(path,':');
1416 dirchar = strrchr(path,'/');
1417 namechar = strrchr(path,'\\');
1418 dirchar = max(dirchar,namechar);
1420 namechar = strrchr(dirchar,'.');
1422 namechar = strrchr(path,'.');
1430 strncat(drive,path,drivechar-path+1);
1439 strncat(directory,path,dirchar-path+1);
1448 strncat(filename,path,namechar-path);
1452 strcat(extension,namechar);
1457 TRACE("CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
1462 /*********************************************************************
1463 * _makepath (CRTDLL.182)
1466 VOID __cdecl CRTDLL__makepath(LPSTR path, LPCSTR drive,
1467 LPCSTR directory, LPCSTR filename,
1471 TRACE("CRTDLL__makepath got %s %s %s %s\n", drive, directory,
1472 filename, extension);
1480 sprintf(path, "%c:", drive[0]);
1483 if ( directory[0] ) {
1484 strcat(path, directory);
1485 ch = path[strlen(path)-1];
1486 if (ch != '/' && ch != '\\')
1490 if ( filename[0] ) {
1491 strcat(path, filename);
1493 if ( extension[0] ) {
1494 if ( extension[0] != '.' ) {
1497 strcat(path,extension);
1502 TRACE("CRTDLL__makepath returns %s\n",path);
1505 /*********************************************************************
1506 * _getcwd (CRTDLL.120)
1508 CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
1515 if (size < 0) /* allocate as big as nescessary */
1516 len =GetCurrentDirectoryA(1,test) + 1;
1517 if(!(buf = CRTDLL_malloc(len)))
1519 /* set error to OutOfRange */
1524 if(!(len =GetCurrentDirectoryA(len,buf)))
1530 /* set error to ERANGE */
1531 TRACE("CRTDLL_getcwd buffer to small\n");
1538 /*********************************************************************
1539 * _getdcwd (CRTDLL.121)
1541 CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size)
1546 FIXME("(\"%c:\",%s,%d)\n",drive+'A',buf,size);
1549 if (size < 0) /* allocate as big as nescessary */
1550 len =GetCurrentDirectoryA(1,test) + 1;
1551 if(!(buf = CRTDLL_malloc(len)))
1553 /* set error to OutOfRange */
1558 if(!(len =GetCurrentDirectoryA(len,buf)))
1564 /* set error to ERANGE */
1565 TRACE("buffer to small\n");
1572 /*********************************************************************
1573 * _getdrive (CRTDLL.124)
1575 * Return current drive, 1 for A, 2 for B
1577 INT __cdecl CRTDLL__getdrive(VOID)
1579 return DRIVE_GetCurrentDrive() + 1;
1582 /*********************************************************************
1583 * _mkdir (CRTDLL.234)
1585 INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
1587 if (!CreateDirectoryA(newdir,NULL))
1592 /*********************************************************************
1593 * remove (CRTDLL.448)
1595 INT __cdecl CRTDLL_remove(LPCSTR file)
1597 if (!DeleteFileA(file))
1602 /*********************************************************************
1603 * _errno (CRTDLL.52)
1604 * Yes, this is a function.
1606 LPINT __cdecl CRTDLL__errno()
1608 static int crtdllerrno;
1610 /* FIXME: we should set the error at the failing function call time */
1611 crtdllerrno = LastErrorToErrno(GetLastError());
1612 return &crtdllerrno;
1615 /*********************************************************************
1616 * _tempnam (CRTDLL.305)
1619 LPSTR __cdecl CRTDLL__tempnam(LPCSTR dir, LPCSTR prefix)
1623 DOS_FULL_NAME tempname;
1625 if ((ret = tempnam(dir,prefix))==NULL) {
1626 WARN("Unable to get unique filename\n");
1629 if (!DOSFS_GetFullName(ret,FALSE,&tempname))
1631 TRACE("Wrong path?\n");
1635 if ((ret = CRTDLL_malloc(strlen(tempname.short_name)+1)) == NULL) {
1636 WARN("CRTDL_malloc for shortname failed\n");
1639 if ((ret = strcpy(ret,tempname.short_name)) == NULL) {
1640 WARN("Malloc for shortname failed\n");
1644 TRACE("dir %s prefix %s got %s\n",
1649 /*********************************************************************
1650 * tmpnam (CRTDLL.490)
1652 * lcclnk from lcc-win32 relies on a terminating dot in the name returned
1655 LPSTR __cdecl CRTDLL_tmpnam(LPSTR s)
1659 if ((ret =tmpnam(s))== NULL) {
1660 WARN("Unable to get unique filename\n");
1663 if (!DOSFS_GetFullName(ret,FALSE,&CRTDLL_tmpname))
1665 TRACE("Wrong path?\n");
1668 strcat(CRTDLL_tmpname.short_name,".");
1669 TRACE("for buf %p got %s\n",
1670 s,CRTDLL_tmpname.short_name);
1671 TRACE("long got %s\n",
1672 CRTDLL_tmpname.long_name);
1674 return strcpy(s,CRTDLL_tmpname.short_name);
1676 return CRTDLL_tmpname.short_name;
1680 /*********************************************************************
1681 * _itoa (CRTDLL.165)
1683 LPSTR __cdecl CRTDLL__itoa(INT x,LPSTR buf,INT buflen)
1685 wsnprintfA(buf,buflen,"%d",x);
1689 /*********************************************************************
1690 * _ltoa (CRTDLL.180)
1692 LPSTR __cdecl CRTDLL__ltoa(long x,LPSTR buf,INT radix)
1695 case 2: FIXME("binary format not implemented !\n");
1697 case 8: wsnprintfA(buf,0x80,"%o",x);
1699 case 10: wsnprintfA(buf,0x80,"%d",x);
1701 case 16: wsnprintfA(buf,0x80,"%x",x);
1703 default: FIXME("radix %d not implemented !\n", radix);
1708 /*********************************************************************
1709 * _ultoa (CRTDLL.311)
1711 LPSTR __cdecl CRTDLL__ultoa(long x,LPSTR buf,INT radix)
1714 case 2: FIXME("binary format not implemented !\n");
1716 case 8: wsnprintfA(buf,0x80,"%lo",x);
1718 case 10: wsnprintfA(buf,0x80,"%ld",x);
1720 case 16: wsnprintfA(buf,0x80,"%lx",x);
1722 default: FIXME("radix %d not implemented !\n", radix);
1727 typedef VOID (*sig_handler_type)(VOID);
1729 /*********************************************************************
1730 * signal (CRTDLL.455)
1732 void * __cdecl CRTDLL_signal(int sig, sig_handler_type ptr)
1734 FIXME("(%d %p):stub.\n", sig, ptr);
1738 /*********************************************************************
1739 * _ftol (CRTDLL.113)
1741 #ifdef USING_REAL_FPU
1742 LONG __cdecl CRTDLL__ftol(void) {
1743 /* don't just do DO_FPU("fistp",retval), because the rounding
1744 * mode must also be set to "round towards zero"... */
1750 LONG __cdecl CRTDLL__ftol(double fl) {
1751 FIXME("should be register function\n");
1756 /*********************************************************************
1757 * _CIpow (CRTDLL.14)
1759 #ifdef USING_REAL_FPU
1760 LONG __cdecl CRTDLL__CIpow(void) {
1767 LONG __cdecl CRTDLL__CIpow(double x,double y) {
1768 FIXME("should be register function\n");
1773 /*********************************************************************
1774 * _sleep (CRTDLL.267)
1776 VOID __cdecl CRTDLL__sleep(unsigned long timeout)
1778 TRACE("CRTDLL__sleep for %ld milliseconds\n",timeout);
1779 Sleep((timeout)?timeout:1);
1782 /*********************************************************************
1783 * getenv (CRTDLL.437)
1785 LPSTR __cdecl CRTDLL_getenv(const char *name)
1787 LPSTR environ = GetEnvironmentStringsA();
1788 LPSTR pp,pos = NULL;
1789 unsigned int length;
1791 for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
1793 pos =strchr(pp,'=');
1797 length = strlen(pp);
1798 if (!strncmp(pp,name,length)) break;
1803 TRACE("got %s\n",pp);
1805 FreeEnvironmentStringsA( environ );
1809 /*********************************************************************
1810 * _mbsrchr (CRTDLL.223)
1812 LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x) {
1813 /* FIXME: handle multibyte strings */
1814 return strrchr(s,x);
1817 /*********************************************************************
1818 * _memicmp (CRTDLL.233)(NTDLL.868)
1819 * A stringcompare, without \0 check
1821 * -1:if first string is alphabetically before second string
1822 * 1:if second '' '' '' '' first ''
1823 * 0:if both are equal.
1825 INT __cdecl CRTDLL__memicmp(
1826 LPCSTR s1, /* [in] first string */
1827 LPCSTR s2, /* [in] second string */
1828 DWORD len /* [in] length to compare */
1832 for (i=0;i<len;i++) {
1833 if (tolower(s1[i])<tolower(s2[i]))
1835 if (tolower(s1[i])>tolower(s2[i]))
1840 /*********************************************************************
1841 * __dllonexit (CRTDLL.25)
1843 VOID __cdecl CRTDLL___dllonexit ()
1848 /*********************************************************************
1849 * wcstol (CRTDLL.520)
1850 * Like strtol, but for wide character strings.
1852 INT __cdecl CRTDLL_wcstol(LPWSTR s,LPWSTR *end,INT base) {
1853 LPSTR sA = HEAP_strdupWtoA(GetProcessHeap(),0,s),endA;
1854 INT ret = strtol(sA,&endA,base);
1856 HeapFree(GetProcessHeap(),0,sA);
1857 if (end) *end = s+(endA-sA); /* pointer magic checked. */
1860 /*********************************************************************
1861 * _strdate (CRTDLL.283)
1863 LPSTR __cdecl CRTDLL__strdate (LPSTR date)
1864 { FIXME("%p stub\n", date);
1868 /*********************************************************************
1869 * _strtime (CRTDLL.299)
1871 LPSTR __cdecl CRTDLL__strtime (LPSTR date)
1872 { FIXME("%p stub\n", date);
1876 /*********************************************************************
1877 * _except_handler2 (CRTDLL.78)
1879 INT __cdecl CRTDLL__except_handler2 (
1880 PEXCEPTION_RECORD rec,
1881 PEXCEPTION_FRAME frame,
1883 PEXCEPTION_FRAME *dispatcher)
1885 FIXME ("exception %lx flags=%lx at %p handler=%p %p %p stub\n",
1886 rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress,
1887 frame->Handler, context, dispatcher);
1888 return ExceptionContinueSearch;