wine/misc/crtdll.c
Alexandre Julliard 0562539d18 Implemented file sharing checks in the server.
Added set file time server request.
Overall clean up of the file handling (DOS device handling is now
broken, should be redone).
1999-01-03 11:55:56 +00:00

2086 lines
52 KiB
C

/*
* The C RunTime DLL
*
* Implements C run-time functionality as known from UNIX.
*
* Copyright 1996,1998 Marcus Meissner
* Copyright 1996 Jukka Iivonen
* Copyright 1997 Uwe Bonnes
*/
/*
Unresolved issues Uwe Bonnes 970904:
- Handling of Binary/Text Files is crude. If in doubt, use fromdos or recode
- Arguments in crtdll.spec for functions with double argument
- system-call calls another wine process, but without debugging arguments
and uses the first wine executable in the path
- tested with ftp://ftp.remcomp.com/pub/remcomp/lcc-win32.zip, a C-Compiler
for Win32, based on lcc, from Jacob Navia
AJ 990101:
- needs a proper stdio emulation based on Win32 file handles
- should set CRTDLL errno from GetLastError() in every function
*/
/* NOTE: This file also implements the wcs* functions. They _ARE_ in
* the newer Linux libcs, but use 4 byte wide characters, so are unusable,
* since we need 2 byte wide characters. - Marcus Meissner, 981031
*/
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <math.h>
#include <fcntl.h>
#include <setjmp.h>
#include "win.h"
#include "windows.h"
#include "winerror.h"
#include "debug.h"
#include "module.h"
#include "heap.h"
#include "crtdll.h"
#include "drive.h"
#include "file.h"
#include "except.h"
#include "options.h"
#include "winnls.h"
static DOS_FULL_NAME CRTDLL_tmpname;
UINT32 CRTDLL_argc_dll; /* CRTDLL.23 */
LPSTR *CRTDLL_argv_dll; /* CRTDLL.24 */
LPSTR CRTDLL_acmdln_dll; /* CRTDLL.38 */
UINT32 CRTDLL_basemajor_dll; /* CRTDLL.42 */
UINT32 CRTDLL_baseminor_dll; /* CRTDLL.43 */
UINT32 CRTDLL_baseversion_dll; /* CRTDLL.44 */
UINT32 CRTDLL_commode_dll; /* CRTDLL.59 */
LPSTR CRTDLL_environ_dll; /* CRTDLL.75 */
UINT32 CRTDLL_fmode_dll; /* CRTDLL.104 */
UINT32 CRTDLL_osmajor_dll; /* CRTDLL.241 */
UINT32 CRTDLL_osminor_dll; /* CRTDLL.242 */
UINT32 CRTDLL_osmode_dll; /* CRTDLL.243 */
UINT32 CRTDLL_osver_dll; /* CRTDLL.244 */
UINT32 CRTDLL_osversion_dll; /* CRTDLL.245 */
UINT32 CRTDLL_winmajor_dll; /* CRTDLL.329 */
UINT32 CRTDLL_winminor_dll; /* CRTDLL.330 */
UINT32 CRTDLL_winver_dll; /* CRTDLL.331 */
/* FIXME: structure layout is obviously not correct */
typedef struct
{
HANDLE32 handle;
int pad[7];
} CRTDLL_FILE;
CRTDLL_FILE CRTDLL_iob[3];
static CRTDLL_FILE * const CRTDLL_stdin = &CRTDLL_iob[0];
static CRTDLL_FILE * const CRTDLL_stdout = &CRTDLL_iob[1];
static CRTDLL_FILE * const CRTDLL_stderr = &CRTDLL_iob[2];
typedef VOID (*new_handler_type)(VOID);
static new_handler_type new_handler;
/*********************************************************************
* _GetMainArgs (CRTDLL.022)
*/
DWORD __cdecl CRTDLL__GetMainArgs(LPDWORD argc,LPSTR **argv,
LPSTR *environ,DWORD flag)
{
char *cmdline;
char **xargv;
int xargc,i,afterlastspace;
DWORD version;
TRACE(crtdll,"(%p,%p,%p,%ld).\n",
argc,argv,environ,flag
);
CRTDLL_acmdln_dll = cmdline = HEAP_strdupA( GetProcessHeap(), 0,
GetCommandLine32A() );
TRACE(crtdll,"got '%s'\n", cmdline);
version = GetVersion32();
CRTDLL_osver_dll = version >> 16;
CRTDLL_winminor_dll = version & 0xFF;
CRTDLL_winmajor_dll = (version>>8) & 0xFF;
CRTDLL_baseversion_dll = version >> 16;
CRTDLL_winver_dll = ((version >> 8) & 0xFF) + ((version & 0xFF) << 8);
CRTDLL_baseminor_dll = (version >> 16) & 0xFF;
CRTDLL_basemajor_dll = (version >> 24) & 0xFF;
CRTDLL_osversion_dll = version & 0xFFFF;
CRTDLL_osminor_dll = version & 0xFF;
CRTDLL_osmajor_dll = (version>>8) & 0xFF;
/* missing threading init */
i=0;xargv=NULL;xargc=0;afterlastspace=0;
while (cmdline[i]) {
if (cmdline[i]==' ') {
xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
sizeof(char*)*(++xargc));
cmdline[i]='\0';
xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0,
cmdline+afterlastspace);
i++;
while (cmdline[i]==' ')
i++;
if (cmdline[i])
afterlastspace=i;
} else
i++;
}
xargv=(char**)HeapReAlloc( GetProcessHeap(), 0, xargv,
sizeof(char*)*(++xargc));
cmdline[i]='\0';
xargv[xargc-1] = HEAP_strdupA( GetProcessHeap(), 0,
cmdline+afterlastspace);
CRTDLL_argc_dll = xargc;
*argc = xargc;
CRTDLL_argv_dll = xargv;
*argv = xargv;
TRACE(crtdll,"found %d arguments\n",
CRTDLL_argc_dll);
CRTDLL_environ_dll = *environ = GetEnvironmentStrings32A();
return 0;
}
typedef void (*_INITTERMFUN)();
/* fixme: move to header */
struct find_t
{ unsigned attrib;
time_t time_create; /* -1 when not avaiable */
time_t time_access; /* -1 when not avaiable */
time_t time_write;
unsigned long size; /* fixme: 64 bit ??*/
char name[260];
};
/*********************************************************************
* _findfirst (CRTDLL.099)
*
* BUGS
* Unimplemented
*/
DWORD __cdecl CRTDLL__findfirst(LPCSTR fname, struct find_t * x2)
{
FIXME(crtdll, ":(%s,%p): stub\n",fname,x2);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*********************************************************************
* _findnext (CRTDLL.100)
*
* BUGS
* Unimplemented
*/
INT32 __cdecl CRTDLL__findnext(DWORD hand, struct find_t * x2)
{
FIXME(crtdll, ":(%ld,%p): stub\n",hand,x2);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*********************************************************************
* _fstat (CRTDLL.111)
*
* BUGS
* Unimplemented
*/
int __cdecl CRTDLL__fstat(int file, struct stat* buf)
{
FIXME(crtdll, ":(%d,%p): stub\n",file,buf);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*********************************************************************
* _initterm (CRTDLL.135)
*/
DWORD __cdecl CRTDLL__initterm(_INITTERMFUN *start,_INITTERMFUN *end)
{
_INITTERMFUN *current;
TRACE(crtdll,"(%p,%p)\n",start,end);
current=start;
while (current<end) {
if (*current) (*current)();
current++;
}
return 0;
}
/*********************************************************************
* _fdopen (CRTDLL.91)
*/
CRTDLL_FILE * __cdecl CRTDLL__fdopen(INT32 handle, LPCSTR mode)
{
CRTDLL_FILE *file;
switch (handle)
{
case 0:
file = CRTDLL_stdin;
if (!file->handle) file->handle = GetStdHandle( STD_INPUT_HANDLE );
break;
case 1:
file = CRTDLL_stdout;
if (!file->handle) file->handle = GetStdHandle( STD_OUTPUT_HANDLE );
break;
case 2:
file=CRTDLL_stderr;
if (!file->handle) file->handle = GetStdHandle( STD_ERROR_HANDLE );
break;
default:
file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
file->handle = handle;
break;
}
TRACE(crtdll, "open handle %d mode %s got file %p\n",
handle, mode, file);
return file;
}
/*******************************************************************
* _global_unwind2 (CRTDLL.129)
*/
void __cdecl CRTDLL__global_unwind2( PEXCEPTION_FRAME frame )
{
RtlUnwind( frame, 0, NULL, 0 );
}
/*******************************************************************
* _local_unwind2 (CRTDLL.173)
*/
void __cdecl CRTDLL__local_unwind2( PEXCEPTION_FRAME endframe, DWORD nr )
{
TRACE(crtdll,"(%p,%ld)\n",endframe,nr);
}
/*********************************************************************
* _read (CRTDLL.256)
*
* BUGS
* Unimplemented
*/
INT32 __cdecl CRTDLL__read(INT32 fd, LPVOID buf, UINT32 count)
{
FIXME(crtdll,":(%d,%p,%d): stub\n",fd,buf,count);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*********************************************************************
* fopen (CRTDLL.372)
*/
CRTDLL_FILE * __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
{
CRTDLL_FILE *file = NULL;
HFILE32 handle;
#if 0
DOS_FULL_NAME full_name;
if (!DOSFS_GetFullName( path, FALSE, &full_name )) {
WARN(crtdll, "file %s bad name\n",path);
return 0;
}
file=fopen(full_name.long_name ,mode);
#endif
DWORD access = 0, creation = 0;
if ((strchr(mode,'r')&&strchr(mode,'a'))||
(strchr(mode,'r')&&strchr(mode,'w'))||
(strchr(mode,'w')&&strchr(mode,'a')))
return NULL;
if (mode[0] == 'r')
{
access = GENERIC_READ;
creation = OPEN_EXISTING;
if (mode[1] == '+') access |= GENERIC_WRITE;
}
else if (mode[0] == 'w')
{
access = GENERIC_WRITE;
creation = CREATE_ALWAYS;
if (mode[1] == '+') access |= GENERIC_READ;
}
else if (mode[0] == 'a')
{
/* FIXME: there is no O_APPEND in CreateFile, should emulate it */
access = GENERIC_WRITE;
creation = OPEN_ALWAYS;
if (mode[1] == '+') access |= GENERIC_READ;
}
/* FIXME: should handle text/binary mode */
if ((handle = CreateFile32A( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL,
-1 )) != INVALID_HANDLE_VALUE32)
{
file = HeapAlloc( GetProcessHeap(), 0, sizeof(*file) );
file->handle = handle;
}
TRACE(crtdll, "file %s mode %s got handle %d file %p\n",
path,mode,handle,file);
return file;
}
/*********************************************************************
* fread (CRTDLL.377)
*/
DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT32 size, INT32 nmemb, CRTDLL_FILE *file)
{
#if 0
int i=0;
void *temp=ptr;
/* If we would honour CR/LF <-> LF translation, we could do it like this.
We should keep track of all files opened, and probably files with \
known binary extensions must be unchanged */
while ( (i < (nmemb*size)) && (ret==1)) {
ret=fread(temp,1,1,file);
TRACE(crtdll, "got %c 0x%02x ret %d\n",
(isalpha(*(unsigned char*)temp))? *(unsigned char*)temp:
' ',*(unsigned char*)temp, ret);
if (*(unsigned char*)temp != 0xd) { /* skip CR */
temp++;
i++;
}
else
TRACE(crtdll, "skipping ^M\n");
}
TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n",
nmemb,size,file,ptr,);
if(i!=nmemb)
WARN(crtdll, " failed!\n");
return i;
#else
DWORD ret;
TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n",
nmemb,size,file,ptr);
if (!ReadFile( file->handle, ptr, size * nmemb, &ret, NULL ))
WARN(crtdll, " failed!\n");
return ret / size;
#endif
}
/*********************************************************************
* freopen (CRTDLL.379)
*
* BUGS
* Unimplemented
*/
DWORD __cdecl CRTDLL_freopen(LPCSTR path, LPCSTR mode, LPVOID stream)
{
FIXME(crtdll, ":(%s,%s,%p): stub\n", path, mode, stream);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*********************************************************************
* fscanf (CRTDLL.381)
*/
INT32 __cdecl CRTDLL_fscanf( CRTDLL_FILE *stream, LPSTR format, ... )
{
#if 0
va_list valist;
INT32 res;
va_start( valist, format );
#ifdef HAVE_VFSCANF
res = vfscanf( xlat_file_ptr(stream), format, valist );
#endif
va_end( valist );
return res;
#endif
FIXME(crtdll,"broken\n");
return 0;
}
/*********************************************************************
* fseek (CRTDLL.382)
*/
LONG __cdecl CRTDLL_fseek( CRTDLL_FILE *file, LONG offset, INT32 whence)
{
TRACE(crtdll, "file %p to 0x%08lx pos %s\n",
file,offset,(whence==SEEK_SET)?"SEEK_SET":
(whence==SEEK_CUR)?"SEEK_CUR":
(whence==SEEK_END)?"SEEK_END":"UNKNOWN");
if (SetFilePointer( file->handle, offset, NULL, whence ) != 0xffffffff)
return 0;
WARN(crtdll, " failed!\n");
return -1;
}
/*********************************************************************
* fsetpos (CRTDLL.383)
*/
INT32 __cdecl CRTDLL_fsetpos( CRTDLL_FILE *file, INT32 *pos )
{
TRACE(crtdll, "file %p pos %d\n", file, *pos );
return CRTDLL_fseek(file, *pos, SEEK_SET);
}
/*********************************************************************
* ftell (CRTDLL.384)
*/
LONG __cdecl CRTDLL_ftell( CRTDLL_FILE *file )
{
return SetFilePointer( file->handle, 0, NULL, SEEK_CUR );
}
/*********************************************************************
* fwrite (CRTDLL.386)
*/
DWORD __cdecl CRTDLL_fwrite( LPVOID ptr, INT32 size, INT32 nmemb, CRTDLL_FILE *file )
{
DWORD ret;
TRACE(crtdll, "0x%08x items of size %d to file %p from %p\n",
nmemb,size,file,ptr);
if (!WriteFile( file->handle, ptr, size * nmemb, &ret, NULL ))
WARN(crtdll, " failed!\n");
return ret / size;
}
/*********************************************************************
* setbuf (CRTDLL.452)
*/
INT32 __cdecl CRTDLL_setbuf(CRTDLL_FILE *file, LPSTR buf)
{
TRACE(crtdll, "(file %p buf %p)\n", file, buf);
/* this doesn't work:"void value not ignored as it ought to be"
return setbuf(file,buf);
*/
/* FIXME: no buffering for now */
return 0;
}
/*********************************************************************
* _open_osfhandle (CRTDLL.240)
*/
HFILE32 __cdecl CRTDLL__open_osfhandle(LONG osfhandle, INT32 flags)
{
HFILE32 handle;
switch (osfhandle) {
case STD_INPUT_HANDLE :
case 0 :
handle=0;
break;
case STD_OUTPUT_HANDLE:
case 1:
handle=1;
break;
case STD_ERROR_HANDLE:
case 2:
handle=2;
break;
default:
return (-1);
}
TRACE(crtdll, "(handle %08lx,flags %d) return %d\n",
osfhandle,flags,handle);
return handle;
}
/*********************************************************************
* srand (CRTDLL.460)
*/
void __cdecl CRTDLL_srand(DWORD seed)
{
/* FIXME: should of course be thread? process? local */
srand(seed);
}
/*********************************************************************
* vfprintf (CRTDLL.373)
*/
INT32 __cdecl CRTDLL_vfprintf( CRTDLL_FILE *file, LPSTR format, va_list args )
{
char buffer[1024]; /* FIXME... */
vsprintf( buffer, format, args );
return CRTDLL_fwrite( buffer, 1, strlen(buffer), file );
}
/*********************************************************************
* fprintf (CRTDLL.373)
*/
INT32 __cdecl CRTDLL_fprintf( CRTDLL_FILE *file, LPSTR format, ... )
{
va_list valist;
INT32 res;
va_start( valist, format );
res = CRTDLL_vfprintf( file, format, valist );
va_end( valist );
return res;
}
/*********************************************************************
* time (CRTDLL.488)
*/
time_t __cdecl CRTDLL_time(time_t *timeptr)
{
time_t curtime = time(NULL);
if (timeptr)
*timeptr = curtime;
return curtime;
}
/*********************************************************************
* (CRTDLL.350)
*/
clock_t __cdecl CRTDLL_clock(void)
{
struct tms alltimes;
clock_t res;
times(&alltimes);
res = alltimes.tms_utime + alltimes.tms_stime+
alltimes.tms_cutime + alltimes.tms_cstime;
/* Fixme: We need some symbolic representation
for (Hostsystem_)CLOCKS_PER_SEC
and (Emulated_system_)CLOCKS_PER_SEC
10 holds only for Windows/Linux_i86)
*/
return 10*res;
}
/*********************************************************************
* _isatty (CRTDLL.137)
*/
BOOL32 __cdecl CRTDLL__isatty(DWORD x)
{
TRACE(crtdll,"(%ld)\n",x);
return TRUE;
}
/*********************************************************************
* _write (CRTDLL.332)
*/
INT32 __cdecl CRTDLL__write(INT32 fd,LPCVOID buf,UINT32 count)
{
INT32 len=0;
if (fd == -1)
len = -1;
else if (fd<=2)
len = (UINT32)write(fd,buf,(LONG)count);
else
len = _lwrite32(fd,buf,count);
TRACE(crtdll,"%d/%d byte to dfh %d from %p,\n",
len,count,fd,buf);
return len;
}
/*********************************************************************
* _cexit (CRTDLL.49)
*
* FIXME: What the heck is the difference between
* FIXME _c_exit (CRTDLL.47)
* FIXME _cexit (CRTDLL.49)
* FIXME _exit (CRTDLL.87)
* FIXME exit (CRTDLL.359)
*
* atexit-processing comes to mind -- MW.
*
*/
void __cdecl CRTDLL__cexit(INT32 ret)
{
TRACE(crtdll,"(%d)\n",ret);
ExitProcess(ret);
}
/*********************************************************************
* exit (CRTDLL.359)
*/
void __cdecl CRTDLL_exit(DWORD ret)
{
TRACE(crtdll,"(%ld)\n",ret);
ExitProcess(ret);
}
/*********************************************************************
* _abnormal_termination (CRTDLL.36)
*/
INT32 __cdecl CRTDLL__abnormal_termination(void)
{
TRACE(crtdll,"(void)\n");
return 0;
}
/*********************************************************************
* _access (CRTDLL.37)
*/
INT32 __cdecl CRTDLL__access(LPCSTR filename, INT32 mode)
{
DWORD attr = GetFileAttributes32A(filename);
if (attr == -1)
{
if (GetLastError() == ERROR_INVALID_ACCESS)
errno = EACCES;
else
errno = ENOENT;
return -1;
}
if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
{
errno = EACCES;
return -1;
}
else
return 0;
}
/*********************************************************************
* fflush (CRTDLL.365)
*/
INT32 __cdecl CRTDLL_fflush( CRTDLL_FILE *file )
{
return FlushFileBuffers( file->handle ) ? 0 : -1;
}
/*********************************************************************
* rand (CRTDLL.446)
*/
INT32 __cdecl CRTDLL_rand()
{
return rand();
}
/*********************************************************************
* putchar (CRTDLL.442)
*/
void __cdecl CRTDLL_putchar( INT32 x )
{
putchar(x);
}
/*********************************************************************
* fputc (CRTDLL.374)
*/
INT32 __cdecl CRTDLL_fputc( INT32 c, CRTDLL_FILE *file )
{
char ch = (char)c;
DWORD res;
TRACE(crtdll, "%c to file %p\n",c,file);
if (!WriteFile( file->handle, &ch, 1, &res, NULL )) return -1;
return c;
}
/*********************************************************************
* fputs (CRTDLL.375)
*/
INT32 __cdecl CRTDLL_fputs( LPCSTR s, CRTDLL_FILE *file )
{
DWORD res;
TRACE(crtdll, "%s to file %p\n",s,file);
if (!WriteFile( file->handle, s, strlen(s), &res, NULL )) return -1;
return res;
}
/*********************************************************************
* puts (CRTDLL.443)
*/
INT32 __cdecl CRTDLL_puts(LPCSTR s)
{
TRACE(crtdll, "%s \n",s);
return puts(s);
}
/*********************************************************************
* putc (CRTDLL.441)
*/
INT32 __cdecl CRTDLL_putc( INT32 c, CRTDLL_FILE *file )
{
return CRTDLL_fputc( c, file );
}
/*********************************************************************
* fgetc (CRTDLL.366)
*/
INT32 __cdecl CRTDLL_fgetc( CRTDLL_FILE *file )
{
DWORD res;
char ch;
if (!ReadFile( file->handle, &ch, 1, &res, NULL )) return -1;
return ch;
}
/*********************************************************************
* getc (CRTDLL.388)
*/
INT32 __cdecl CRTDLL_getc( CRTDLL_FILE *file )
{
return CRTDLL_fgetc( file );
}
/*********************************************************************
* fgets (CRTDLL.368)
*/
CHAR* __cdecl CRTDLL_fgets( LPSTR s, INT32 size, CRTDLL_FILE *file )
{
int cc;
LPSTR buf_start = s;
/* BAD, for the whole WINE process blocks... just done this way to test
* windows95's ftp.exe.
*/
for(cc = CRTDLL_fgetc(file); cc != EOF && cc != '\n'; cc = CRTDLL_fgetc(file))
if (cc != '\r')
{
if (--size <= 0) break;
*s++ = (char)cc;
}
*s = '\0';
TRACE(crtdll,"got '%s'\n", buf_start);
return buf_start;
}
/*********************************************************************
* gets (CRTDLL.391)
*/
LPSTR __cdecl CRTDLL_gets(LPSTR buf)
{
int cc;
LPSTR buf_start = buf;
/* BAD, for the whole WINE process blocks... just done this way to test
* windows95's ftp.exe.
*/
for(cc = fgetc(stdin); cc != EOF && cc != '\n'; cc = fgetc(stdin))
if(cc != '\r') *buf++ = (char)cc;
*buf = '\0';
TRACE(crtdll,"got '%s'\n", buf_start);
return buf_start;
}
/*********************************************************************
* _rotl (CRTDLL.259)
*/
UINT32 __cdecl CRTDLL__rotl(UINT32 x,INT32 shift)
{
unsigned int ret = (x >> shift)|( x >>((sizeof(x))-shift));
TRACE(crtdll, "got 0x%08x rot %d ret 0x%08x\n",
x,shift,ret);
return ret;
}
/*********************************************************************
* _lrotl (CRTDLL.176)
*/
DWORD __cdecl CRTDLL__lrotl(DWORD x,INT32 shift)
{
unsigned long ret = (x >> shift)|( x >>((sizeof(x))-shift));
TRACE(crtdll, "got 0x%08lx rot %d ret 0x%08lx\n",
x,shift,ret);
return ret;
}
/*********************************************************************
* _mbsicmp (CRTDLL.204)
*/
int __cdecl CRTDLL__mbsicmp(unsigned char *x,unsigned char *y)
{
do {
if (!*x)
return !!*y;
if (!*y)
return !!*x;
/* FIXME: MBCS handling... */
if (*x!=*y)
return 1;
x++;
y++;
} while (1);
}
/*********************************************************************
* _mbsinc (CRTDLL.205)
*/
unsigned char * __cdecl CRTDLL__mbsinc(unsigned char *x)
{
/* FIXME: mbcs */
return x++;
}
/*********************************************************************
* vsprintf (CRTDLL.500)
*/
INT32 __cdecl CRTDLL_vsprintf( LPSTR buffer, LPCSTR spec, va_list args )
{
return wvsprintf32A( buffer, spec, args );
}
/*********************************************************************
* vswprintf (CRTDLL.501)
*/
INT32 __cdecl CRTDLL_vswprintf( LPWSTR buffer, LPCWSTR spec, va_list args )
{
return wvsprintf32W( buffer, spec, args );
}
/*********************************************************************
* _mbscpy (CRTDLL.200)
*/
unsigned char* __cdecl CRTDLL__mbscpy(unsigned char *x,unsigned char *y)
{
TRACE(crtdll,"CRTDLL_mbscpy %s and %s\n",x,y);
return strcpy(x,y);
}
/*********************************************************************
* _mbscat (CRTDLL.197)
*/
unsigned char* __cdecl CRTDLL__mbscat(unsigned char *x,unsigned char *y)
{
return strcat(x,y);
}
/*********************************************************************
* _strcmpi (CRTDLL.282) (CRTDLL.287)
*/
INT32 __cdecl CRTDLL__strcmpi( LPCSTR s1, LPCSTR s2 )
{
return lstrcmpi32A( s1, s2 );
}
/*********************************************************************
* _strnicmp (CRTDLL.293)
*/
INT32 __cdecl CRTDLL__strnicmp( LPCSTR s1, LPCSTR s2, INT32 n )
{
return lstrncmpi32A( s1, s2, n );
}
/*********************************************************************
* _strlwr (CRTDLL.293)
*
* convert a string in place to lowercase
*/
LPSTR __cdecl CRTDLL__strlwr(LPSTR x)
{
unsigned char *y =x;
TRACE(crtdll, "CRTDLL_strlwr got %s\n", x);
while (*y) {
if ((*y > 0x40) && (*y< 0x5b))
*y = *y + 0x20;
y++;
}
TRACE(crtdll, " returned %s\n", x);
return x;
}
/*********************************************************************
* system (CRTDLL.485)
*/
INT32 __cdecl CRTDLL_system(LPSTR x)
{
#define SYSBUF_LENGTH 1500
char buffer[SYSBUF_LENGTH];
unsigned char *y = x;
unsigned char *bp;
int i;
sprintf( buffer, "%s \"", Options.argv0 );
bp = buffer + strlen(buffer);
i = strlen(buffer) + strlen(x) +2;
/* Calculate needed buffer size to prevent overflow. */
while (*y) {
if (*y =='\\') i++;
y++;
}
/* If buffer too short, exit. */
if (i > SYSBUF_LENGTH) {
TRACE(crtdll,"_system buffer to small\n");
return 127;
}
y =x;
while (*y) {
*bp = *y;
bp++; y++;
if (*(y-1) =='\\') *bp++ = '\\';
}
/* Remove spaces from end of string. */
while (*(y-1) == ' ') {
bp--;y--;
}
*bp++ = '"';
*bp = 0;
TRACE(crtdll, "_system got '%s', executing '%s'\n",x,buffer);
return system(buffer);
}
/*********************************************************************
* _strupr (CRTDLL.300)
*/
LPSTR __cdecl CRTDLL__strupr(LPSTR x)
{
LPSTR y=x;
while (*y) {
*y=toupper(*y);
y++;
}
return x;
}
/*********************************************************************
* _wcsupr (CRTDLL.328)
*/
LPWSTR __cdecl CRTDLL__wcsupr(LPWSTR x)
{
LPWSTR y=x;
while (*y) {
*y=towupper(*y);
y++;
}
return x;
}
/*********************************************************************
* _wcslwr (CRTDLL.323)
*/
LPWSTR __cdecl CRTDLL__wcslwr(LPWSTR x)
{
LPWSTR y=x;
while (*y) {
*y=towlower(*y);
y++;
}
return x;
}
/*********************************************************************
* longjmp (CRTDLL.426)
*/
VOID __cdecl CRTDLL_longjmp(jmp_buf env, int val)
{
FIXME(crtdll,"CRTDLL_longjmp semistup, expect crash\n");
return longjmp(env, val);
}
/*********************************************************************
* malloc (CRTDLL.427)
*/
VOID* __cdecl CRTDLL_malloc(DWORD size)
{
return HeapAlloc(GetProcessHeap(),0,size);
}
/*********************************************************************
* new (CRTDLL.001)
*/
VOID* __cdecl CRTDLL_new(DWORD size)
{
VOID* result;
if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
(*new_handler)();
return result;
}
/*********************************************************************
* set_new_handler(CRTDLL.003)
*/
new_handler_type __cdecl CRTDLL_set_new_handler(new_handler_type func)
{
new_handler_type old_handler = new_handler;
new_handler = func;
return old_handler;
}
/*********************************************************************
* calloc (CRTDLL.350)
*/
VOID* __cdecl CRTDLL_calloc(DWORD size, DWORD count)
{
return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
}
/*********************************************************************
* realloc (CRTDLL.447)
*/
VOID* __cdecl CRTDLL_realloc( VOID *ptr, DWORD size )
{
return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
}
/*********************************************************************
* free (CRTDLL.427)
*/
VOID __cdecl CRTDLL_free(LPVOID ptr)
{
HeapFree(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* delete (CRTDLL.002)
*/
VOID __cdecl CRTDLL_delete(VOID* ptr)
{
HeapFree(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* _strdup (CRTDLL.285)
*/
LPSTR __cdecl CRTDLL__strdup(LPCSTR ptr)
{
return HEAP_strdupA(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* _wcsdup (CRTDLL.320)
*/
LPWSTR __cdecl CRTDLL__wcsdup(LPCWSTR ptr)
{
return HEAP_strdupW(GetProcessHeap(),0,ptr);
}
/*********************************************************************
* fclose (CRTDLL.362)
*/
INT32 __cdecl CRTDLL_fclose( CRTDLL_FILE *file )
{
TRACE(crtdll,"%p\n", file );
if (!CloseHandle( file->handle )) return -1;
HeapFree( GetProcessHeap(), 0, file );
return 0;
}
/*********************************************************************
* _unlink (CRTDLL.315)
*/
INT32 __cdecl CRTDLL__unlink(LPCSTR pathname)
{
int ret=0;
DOS_FULL_NAME full_name;
if (!DOSFS_GetFullName( pathname, FALSE, &full_name )) {
WARN(crtdll, "CRTDLL_unlink file %s bad name\n",pathname);
return EOF;
}
ret=unlink(full_name.long_name);
TRACE(crtdll,"(%s unix %s)\n",
pathname,full_name.long_name);
if(ret)
WARN(crtdll, " Failed!\n");
return ret;
}
/*********************************************************************
* rename (CRTDLL.449)
*/
INT32 __cdecl CRTDLL_rename(LPCSTR oldpath,LPCSTR newpath)
{
BOOL32 ok = MoveFileEx32A( oldpath, newpath, MOVEFILE_REPLACE_EXISTING );
return ok ? 0 : -1;
}
/*********************************************************************
* _stat (CRTDLL.280)
*/
struct win_stat
{
UINT16 win_st_dev;
UINT16 win_st_ino;
UINT16 win_st_mode;
INT16 win_st_nlink;
INT16 win_st_uid;
INT16 win_st_gid;
UINT32 win_st_rdev;
INT32 win_st_size;
INT32 win_st_atime;
INT32 win_st_mtime;
INT32 win_st_ctime;
};
int __cdecl CRTDLL__stat(const char * filename, struct win_stat * buf)
{
int ret=0;
DOS_FULL_NAME full_name;
struct stat mystat;
if (!DOSFS_GetFullName( filename, TRUE, &full_name ))
{
WARN(crtdll, "CRTDLL__stat filename %s bad name\n",filename);
return -1;
}
ret=stat(full_name.long_name,&mystat);
TRACE(crtdll,"CRTDLL__stat %s\n", filename);
if(ret)
WARN(crtdll, " Failed!\n");
/* FIXME: should check what Windows returns */
buf->win_st_dev = mystat.st_dev;
buf->win_st_ino = mystat.st_ino;
buf->win_st_mode = mystat.st_mode;
buf->win_st_nlink = mystat.st_nlink;
buf->win_st_uid = mystat.st_uid;
buf->win_st_gid = mystat.st_gid;
buf->win_st_rdev = mystat.st_rdev;
buf->win_st_size = mystat.st_size;
buf->win_st_atime = mystat.st_atime;
buf->win_st_mtime = mystat.st_mtime;
buf->win_st_ctime = mystat.st_ctime;
return ret;
}
/*********************************************************************
* _open (CRTDLL.239)
*/
HFILE32 __cdecl CRTDLL__open(LPCSTR path,INT32 flags)
{
DWORD access = 0, creation = 0;
HFILE32 ret;
/* FIXME:
the flags in lcc's header differ from the ones in Linux, e.g.
Linux: define O_APPEND 02000 (= 0x400)
lcc: define _O_APPEND 0x0008
so here a scheme to translate them
Probably lcc is wrong here, but at least a hack to get is going
*/
switch(flags & 3)
{
case O_RDONLY: access |= GENERIC_READ; break;
case O_WRONLY: access |= GENERIC_WRITE; break;
case O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
}
if (flags & 0x0100) /* O_CREAT */
{
if (flags & 0x0400) /* O_EXCL */
creation = CREATE_NEW;
else if (flags & 0x0200) /* O_TRUNC */
creation = CREATE_ALWAYS;
else
creation = OPEN_ALWAYS;
}
else /* no O_CREAT */
{
if (flags & 0x0200) /* O_TRUNC */
creation = TRUNCATE_EXISTING;
else
creation = OPEN_EXISTING;
}
if (flags & 0x0008) /* O_APPEND */
FIXME(crtdll, "O_APPEND not supported\n" );
if (flags & 0xf0f4)
TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags);
/* End Fixme */
ret = CreateFile32A( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL, -1 );
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x got handle %d\n", path,flags,ret);
return ret;
}
/*********************************************************************
* _close (CRTDLL.57)
*/
INT32 __cdecl CRTDLL__close(HFILE32 fd)
{
int ret=_lclose32(fd);
TRACE(crtdll,"(%d)\n",fd);
if(ret)
WARN(crtdll, " Failed!\n");
return ret;
}
/*********************************************************************
* feof (CRTDLL.363)
*/
INT32 __cdecl CRTDLL_feof( CRTDLL_FILE *file )
{
FIXME(crtdll,"stub\n" );
return 0;
}
/*********************************************************************
* setlocale (CRTDLL.453)
*/
LPSTR __cdecl CRTDLL_setlocale(INT32 category,LPCSTR locale)
{
LPSTR categorystr;
switch (category) {
case CRTDLL_LC_ALL: categorystr="LC_ALL";break;
case CRTDLL_LC_COLLATE: categorystr="LC_COLLATE";break;
case CRTDLL_LC_CTYPE: categorystr="LC_CTYPE";break;
case CRTDLL_LC_MONETARY: categorystr="LC_MONETARY";break;
case CRTDLL_LC_NUMERIC: categorystr="LC_NUMERIC";break;
case CRTDLL_LC_TIME: categorystr="LC_TIME";break;
default: categorystr = "UNKNOWN?";break;
}
FIXME(crtdll,"(%s,%s),stub!\n",categorystr,locale);
return "C";
}
/*********************************************************************
* wcscat (CRTDLL.503)
*/
LPWSTR __cdecl CRTDLL_wcscat( LPWSTR s1, LPCWSTR s2 )
{
return lstrcat32W( s1, s2 );
}
/*********************************************************************
* wcschr (CRTDLL.504)
*/
LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR str,WCHAR xchar)
{
LPCWSTR s;
s=str;
do {
if (*s==xchar)
return (LPWSTR)s;
} while (*s++);
return NULL;
}
/*********************************************************************
* wcscmp (CRTDLL.505)
*/
INT32 __cdecl CRTDLL_wcscmp( LPCWSTR s1, LPCWSTR s2 )
{
return lstrcmp32W( s1, s2 );
}
/*********************************************************************
* wcscpy (CRTDLL.507)
*/
LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR s1, LPCWSTR s2 )
{
return lstrcpy32W( s1, s2 );
}
/*********************************************************************
* wcscspn (CRTDLL.508)
*/
INT32 __cdecl CRTDLL_wcscspn(LPWSTR str,LPWSTR reject)
{
LPWSTR s,t;
s=str;
do {
t=reject;
while (*t) { if (*t==*s) break;t++;}
if (*t) break;
s++;
} while (*s);
return s-str; /* nr of wchars */
}
/*********************************************************************
* wcslen (CRTDLL.510)
*/
INT32 __cdecl CRTDLL_wcslen( LPCWSTR s )
{
return lstrlen32W( s );
}
/*********************************************************************
* wcsncat (CRTDLL.511)
*/
LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT32 n )
{
return lstrcatn32W( s1, s2, n );
}
/*********************************************************************
* wcsncmp (CRTDLL.512)
*/
INT32 __cdecl CRTDLL_wcsncmp( LPCWSTR s1, LPCWSTR s2, INT32 n )
{
return lstrncmp32W( s1, s2, n );
}
/*********************************************************************
* wcsncpy (CRTDLL.513)
*/
LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT32 n )
{
return lstrcpyn32W( s1, s2, n );
}
/*********************************************************************
* wcsspn (CRTDLL.516)
*/
INT32 __cdecl CRTDLL_wcsspn(LPWSTR str,LPWSTR accept)
{
LPWSTR s,t;
s=str;
do {
t=accept;
while (*t) { if (*t==*s) break;t++;}
if (!*t) break;
s++;
} while (*s);
return s-str; /* nr of wchars */
}
/*********************************************************************
* _wcsicmp (CRTDLL.321)
*/
DWORD __cdecl CRTDLL__wcsicmp( LPCWSTR s1, LPCWSTR s2 )
{
return lstrcmpi32W( s1, s2 );
}
/*********************************************************************
* _wcsicoll (CRTDLL.322)
*/
DWORD __cdecl CRTDLL__wcsicoll(LPCWSTR a1,LPCWSTR a2)
{
/* FIXME: handle collates */
return lstrcmpi32W(a1,a2);
}
/*********************************************************************
* _wcsnicmp (CRTDLL.324)
*/
DWORD __cdecl CRTDLL__wcsnicmp( LPCWSTR s1, LPCWSTR s2, INT32 len )
{
return lstrncmpi32W( s1, s2, len );
}
/*********************************************************************
* wcscoll (CRTDLL.506)
*/
DWORD __cdecl CRTDLL_wcscoll(LPWSTR a1,LPWSTR a2)
{
/* FIXME: handle collates */
return lstrcmp32W(a1,a2);
}
/*********************************************************************
* _wcsrev (CRTDLL.326)
*/
VOID __cdecl CRTDLL__wcsrev(LPWSTR s) {
LPWSTR e;
e=s;
while (*e)
e++;
while (s<e) {
WCHAR a;
a=*s;*s=*e;*e=a;
s++;e--;
}
}
/*********************************************************************
* wcsstr (CRTDLL.517)
*/
LPWSTR __cdecl CRTDLL_wcsstr(LPWSTR s,LPWSTR b)
{
LPWSTR x,y,c;
x=s;
while (*x) {
if (*x==*b) {
y=x;c=b;
while (*y && *c && *y==*c) { c++;y++; }
if (!*c)
return x;
}
x++;
}
return NULL;
}
/*********************************************************************
* wcstombs (CRTDLL.521)
*/
INT32 __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT32 len )
{
lstrcpynWtoA( dst, src, len );
return strlen(dst); /* FIXME: is this right? */
}
/*********************************************************************
* wcsrchr (CRTDLL.515)
*/
LPWSTR __cdecl CRTDLL_wcsrchr(LPWSTR str,WCHAR xchar)
{
LPWSTR s;
s=str+lstrlen32W(str);
do {
if (*s==xchar)
return s;
s--;
} while (s>=str);
return NULL;
}
/*********************************************************************
* _setmode (CRTDLL.265)
* FIXME: At present we ignore the request to translate CR/LF to LF.
*
* We allways translate when we read with fgets, we never do with fread
*
*/
INT32 __cdecl CRTDLL__setmode( INT32 fh,INT32 mode)
{
/* FIXME */
#define O_TEXT 0x4000
#define O_BINARY 0x8000
FIXME(crtdll, "on fhandle %d mode %s, STUB.\n",
fh,(mode=O_TEXT)?"O_TEXT":
(mode=O_BINARY)?"O_BINARY":"UNKNOWN");
return -1;
}
/*********************************************************************
* _fpreset (CRTDLL.107)
*/
VOID __cdecl CRTDLL__fpreset(void)
{
FIXME(crtdll," STUB.\n");
}
/*********************************************************************
* atexit (CRTDLL.345)
*/
INT32 __cdecl CRTDLL_atexit(LPVOID x)
{
FIXME(crtdll,"(%p), STUB.\n",x);
return 0; /* successful */
}
/*********************************************************************
* mblen (CRTDLL.428)
* FIXME: check multibyte support
*/
WCHAR __cdecl CRTDLL_mblen(CHAR *mb,INT32 size)
{
int ret=1;
if (!mb)
ret = 0;
else if ((size<1)||(!*(mb+1)))
ret = -1;
else if (!(*mb))
ret =0;
TRACE(crtdll,"CRTDLL_mlen %s for max %d bytes ret %d\n",mb,size,ret);
return ret;
}
/*********************************************************************
* mbstowcs (CRTDLL.429)
* FIXME: check multibyte support
*/
INT32 __cdecl CRTDLL_mbstowcs(LPWSTR wcs, LPCSTR mbs, INT32 size)
{
/* Slightly modified lstrcpynAtoW functions from memory/strings.c
* We need the number of characters transfered
* FIXME: No multibyte support yet
*/
LPWSTR p = wcs;
LPCSTR src= mbs;
int ret, n=size;
while ((n-- > 0) && *src) {
*p++ = (WCHAR)(unsigned char)*src++;
}
p++;
ret = (p -wcs);
TRACE(crtdll,"CRTDLL_mbstowcs %s for %d chars put %d wchars\n",
mbs,size,ret);
return ret;
}
/*********************************************************************
* mbtowc (CRTDLL.430)
* FIXME: check multibyte support
*/
WCHAR __cdecl CRTDLL_mbtowc(WCHAR* wc,CHAR* mb,INT32 size)
{
int ret;
if (!mb)
ret = 0;
else if (!wc)
ret =-1;
else
if ( (ret = mblen(mb,size)) != -1 )
{
if (ret <= sizeof(char))
*wc = (WCHAR) ((unsigned char)*mb);
else
ret= -1;
}
else
ret = -1;
TRACE(crtdll,"CRTDLL_mbtowc %s for %d chars\n",mb,size);
return ret;
}
/*********************************************************************
* _isctype (CRTDLL.138)
*/
BOOL32 __cdecl CRTDLL__isctype(CHAR x,CHAR type)
{
if ((type & CRTDLL_SPACE) && isspace(x))
return TRUE;
if ((type & CRTDLL_PUNCT) && ispunct(x))
return TRUE;
if ((type & CRTDLL_LOWER) && islower(x))
return TRUE;
if ((type & CRTDLL_UPPER) && isupper(x))
return TRUE;
if ((type & CRTDLL_ALPHA) && isalpha(x))
return TRUE;
if ((type & CRTDLL_DIGIT) && isdigit(x))
return TRUE;
if ((type & CRTDLL_CONTROL) && iscntrl(x))
return TRUE;
/* check CRTDLL_LEADBYTE */
return FALSE;
}
/*********************************************************************
* _chdrive (CRTDLL.52)
*
* newdir [I] drive to change to, A=1
*
*/
BOOL32 __cdecl CRTDLL__chdrive(INT32 newdrive)
{
/* FIXME: generates errnos */
return DRIVE_SetCurrentDrive(newdrive-1);
}
/*********************************************************************
* _chdir (CRTDLL.51)
*/
INT32 __cdecl CRTDLL__chdir(LPCSTR newdir)
{
if (!SetCurrentDirectory32A(newdir))
return 1;
return 0;
}
/*********************************************************************
* _fullpath (CRTDLL.114)
*/
LPSTR __cdecl CRTDLL__fullpath(LPSTR buf, LPCSTR name, INT32 size)
{
DOS_FULL_NAME full_name;
if (!buf)
{
size = 256;
if(!(buf = CRTDLL_malloc(size))) return NULL;
}
if (!DOSFS_GetFullName( name, FALSE, &full_name )) return NULL;
lstrcpyn32A(buf,full_name.short_name,size);
TRACE(crtdll,"CRTDLL_fullpath got %s\n",buf);
return buf;
}
/*********************************************************************
* _splitpath (CRTDLL.279)
*/
VOID __cdecl CRTDLL__splitpath(LPCSTR path, LPSTR drive, LPSTR directory, LPSTR filename, LPSTR extension )
{
/* drive includes :
directory includes leading and trailing (forward and backward slashes)
filename without dot and slashes
extension with leading dot
*/
char * drivechar,*dirchar,*namechar;
TRACE(crtdll,"CRTDLL__splitpath got %s\n",path);
drivechar = strchr(path,':');
dirchar = strrchr(path,'/');
namechar = strrchr(path,'\\');
dirchar = MAX(dirchar,namechar);
if (dirchar)
namechar = strrchr(dirchar,'.');
else
namechar = strrchr(path,'.');
if (drive)
{
*drive = 0x00;
if (drivechar)
{
strncat(drive,path,drivechar-path+1);
path = drivechar+1;
}
}
if (directory)
{
*directory = 0x00;
if (dirchar)
{
strncat(directory,path,dirchar-path+1);
path = dirchar+1;
}
}
if (filename)
{
*filename = 0x00;
if (namechar)
{
strncat(filename,path,namechar-path);
if (extension)
{
*extension = 0x00;
strcat(extension,namechar);
}
}
}
TRACE(crtdll,"CRTDLL__splitpath found %s %s %s %s\n",drive,directory,filename,extension);
}
/*********************************************************************
* _getcwd (CRTDLL.120)
*/
CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT32 size)
{
char test[1];
int len;
len = size;
if (!buf) {
if (size < 0) /* allocate as big as nescessary */
len =GetCurrentDirectory32A(1,test) + 1;
if(!(buf = CRTDLL_malloc(len)))
{
/* set error to OutOfRange */
return( NULL );
}
}
size = len;
if(!(len =GetCurrentDirectory32A(len,buf)))
{
return NULL;
}
if (len > size)
{
/* set error to ERANGE */
TRACE(crtdll,"CRTDLL_getcwd buffer to small\n");
return NULL;
}
return buf;
}
/*********************************************************************
* _getdcwd (CRTDLL.121)
*/
CHAR* __cdecl CRTDLL__getdcwd(INT32 drive,LPSTR buf, INT32 size)
{
char test[1];
int len;
FIXME(crtdll,"(\"%c:\",%s,%d)\n",drive+'A',buf,size);
len = size;
if (!buf) {
if (size < 0) /* allocate as big as nescessary */
len =GetCurrentDirectory32A(1,test) + 1;
if(!(buf = CRTDLL_malloc(len)))
{
/* set error to OutOfRange */
return( NULL );
}
}
size = len;
if(!(len =GetCurrentDirectory32A(len,buf)))
{
return NULL;
}
if (len > size)
{
/* set error to ERANGE */
TRACE(crtdll,"buffer to small\n");
return NULL;
}
return buf;
}
/*********************************************************************
* _getdrive (CRTDLL.124)
*
* Return current drive, 1 for A, 2 for B
*/
INT32 __cdecl CRTDLL__getdrive(VOID)
{
return DRIVE_GetCurrentDrive() + 1;
}
/*********************************************************************
* _mkdir (CRTDLL.234)
*/
INT32 __cdecl CRTDLL__mkdir(LPCSTR newdir)
{
if (!CreateDirectory32A(newdir,NULL))
return -1;
return 0;
}
/*********************************************************************
* remove (CRTDLL.448)
*/
INT32 __cdecl CRTDLL_remove(LPCSTR file)
{
if (!DeleteFile32A(file))
return -1;
return 0;
}
/*********************************************************************
* _errno (CRTDLL.52)
* Yes, this is a function.
*/
LPINT32 __cdecl CRTDLL__errno()
{
static int crtdllerrno;
/* FIXME: we should set the error at the failing function call time */
crtdllerrno = LastErrorToErrno(GetLastError());
return &crtdllerrno;
}
/*********************************************************************
* _tempnam (CRTDLL.305)
*
*/
LPSTR __cdecl CRTDLL__tempnam(LPCSTR dir, LPCSTR prefix)
{
char *ret;
DOS_FULL_NAME tempname;
if ((ret = tempnam(dir,prefix))==NULL) {
WARN(crtdll, "Unable to get unique filename\n");
return NULL;
}
if (!DOSFS_GetFullName(ret,FALSE,&tempname))
{
TRACE(crtdll, "Wrong path?\n");
return NULL;
}
free(ret);
if ((ret = CRTDLL_malloc(strlen(tempname.short_name)+1)) == NULL) {
WARN(crtdll, "CRTDL_malloc for shortname failed\n");
return NULL;
}
if ((ret = strcpy(ret,tempname.short_name)) == NULL) {
WARN(crtdll, "Malloc for shortname failed\n");
return NULL;
}
TRACE(crtdll,"dir %s prefix %s got %s\n",
dir,prefix,ret);
return ret;
}
/*********************************************************************
* tmpnam (CRTDLL.490)
*
* lcclnk from lcc-win32 relies on a terminating dot in the name returned
*
*/
LPSTR __cdecl CRTDLL_tmpnam(LPSTR s)
{
char *ret;
if ((ret =tmpnam(s))== NULL) {
WARN(crtdll, "Unable to get unique filename\n");
return NULL;
}
if (!DOSFS_GetFullName(ret,FALSE,&CRTDLL_tmpname))
{
TRACE(crtdll, "Wrong path?\n");
return NULL;
}
strcat(CRTDLL_tmpname.short_name,".");
TRACE(crtdll,"for buf %p got %s\n",
s,CRTDLL_tmpname.short_name);
TRACE(crtdll,"long got %s\n",
CRTDLL_tmpname.long_name);
if ( s != NULL)
return strcpy(s,CRTDLL_tmpname.short_name);
else
return CRTDLL_tmpname.short_name;
}
/*********************************************************************
* _itoa (CRTDLL.165)
*/
LPSTR __cdecl CRTDLL__itoa(INT32 x,LPSTR buf,INT32 buflen)
{
wsnprintf32A(buf,buflen,"%d",x);
return buf;
}
/*********************************************************************
* _ltoa (CRTDLL.180)
*/
LPSTR __cdecl CRTDLL__ltoa(long x,LPSTR buf,INT32 radix)
{
switch(radix) {
case 2: FIXME(crtdll, "binary format not implemented !\n");
break;
case 8: wsnprintf32A(buf,0x80,"%o",x);
break;
case 10: wsnprintf32A(buf,0x80,"%d",x);
break;
case 16: wsnprintf32A(buf,0x80,"%x",x);
break;
default: FIXME(crtdll, "radix %d not implemented !\n", radix);
}
return buf;
}
/*********************************************************************
* _ultoa (CRTDLL.311)
*/
LPSTR __cdecl CRTDLL__ultoa(long x,LPSTR buf,INT32 radix)
{
switch(radix) {
case 2: FIXME(crtdll, "binary format not implemented !\n");
break;
case 8: wsnprintf32A(buf,0x80,"%lo",x);
break;
case 10: wsnprintf32A(buf,0x80,"%ld",x);
break;
case 16: wsnprintf32A(buf,0x80,"%lx",x);
break;
default: FIXME(crtdll, "radix %d not implemented !\n", radix);
}
return buf;
}
typedef VOID (*sig_handler_type)(VOID);
/*********************************************************************
* signal (CRTDLL.455)
*/
VOID __cdecl CRTDLL_signal(int sig, sig_handler_type ptr)
{
FIXME(crtdll, "(%d %p):stub.\n", sig, ptr);
}
/*********************************************************************
* _ftol (CRTDLL.113)
*/
LONG __cdecl CRTDLL__ftol(double fl) {
return (LONG)fl;
}
/*********************************************************************
* _sleep (CRTDLL.267)
*/
VOID __cdecl CRTDLL__sleep(unsigned long timeout)
{
TRACE(crtdll,"CRTDLL__sleep for %ld milliseconds\n",timeout);
Sleep((timeout)?timeout:1);
}
/*********************************************************************
* getenv (CRTDLL.437)
*/
LPSTR __cdecl CRTDLL_getenv(const char *name)
{
LPSTR environ = GetEnvironmentStrings32A();
LPSTR pp,pos = NULL;
unsigned int length;
for (pp = environ; (*pp); pp = pp + strlen(pp) +1)
{
pos =strchr(pp,'=');
if (pos)
length = pos -pp;
else
length = strlen(pp);
if (!strncmp(pp,name,length)) break;
}
if ((pp)&& (pos))
{
pp = pos+1;
TRACE(crtdll,"got %s\n",pp);
}
FreeEnvironmentStrings32A( environ );
return pp;
}
/*********************************************************************
* _mbsrchr (CRTDLL.223)
*/
LPSTR __cdecl CRTDLL__mbsrchr(LPSTR s,CHAR x) {
/* FIXME: handle multibyte strings */
return strrchr(s,x);
}
/*********************************************************************
* _memicmp (CRTDLL.233)(NTDLL.868)
* A stringcompare, without \0 check
* RETURNS
* -1:if first string is alphabetically before second string
* 1:if second '' '' '' '' first ''
* 0:if both are equal.
*/
INT32 __cdecl CRTDLL__memicmp(
LPCSTR s1, /* [in] first string */
LPCSTR s2, /* [in] second string */
DWORD len /* [in] length to compare */
) {
int i;
for (i=0;i<len;i++) {
if (tolower(s1[i])<tolower(s2[i]))
return -1;
if (tolower(s1[i])>tolower(s2[i]))
return 1;
}
return 0;
}
/*********************************************************************
* __dllonexit (CRTDLL.25)
*/
VOID __cdecl CRTDLL__dllonexit ()
{
FIXME(crtdll,"stub\n");
}
/*********************************************************************
* wcstok (CRTDLL.519)
* Like strtok, but for wide character strings. s is modified, yes.
*/
LPWSTR CRTDLL_wcstok(LPWSTR s,LPCWSTR delim) {
static LPWSTR nexttok = NULL;
LPWSTR x,ret;
if (!s)
s = nexttok;
if (!s)
return NULL;
x = s;
while (*x && !CRTDLL_wcschr(delim,*x))
x++;
ret = nexttok;
if (*x) {
*x='\0';
nexttok = x+1;
} else
nexttok = NULL;
return ret;
}
/*********************************************************************
* wcstol (CRTDLL.520)
* Like strtol, but for wide character strings.
*/
INT32 CRTDLL_wcstol(LPWSTR s,LPWSTR *end,INT32 base) {
LPSTR sA = HEAP_strdupWtoA(GetProcessHeap(),0,s),endA;
INT32 ret = strtol(sA,&endA,base);
HeapFree(GetProcessHeap(),0,sA);
if (end) *end = s+(endA-sA); /* pointer magic checked. */
return ret;
}
/*********************************************************************
* strdate (CRTDLL.283)
*/
LPSTR __cdecl CRTDLL__strdate (LPSTR date)
{ FIXME (crtdll,"%p stub\n", date);
return 0;
}
/*********************************************************************
* strtime (CRTDLL.299)
*/
LPSTR __cdecl CRTDLL__strtime (LPSTR date)
{ FIXME (crtdll,"%p stub\n", date);
return 0;
}