1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00
wine/misc/crtdll.c
Alexandre Julliard ebfc0fee51 Release 980628
Sun Jun 28 18:37:02 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [if1632/signal.c] [miscemu/instr.c] [memory/virtual.c]
	Moved page-fault handling to INSTR_EmulateInstruction.

	* [scheduler/thread.c]
	Added locking and check for own thread in Suspend/ResumeThread.

Sat Jun 27 21:25:21 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [objects/dib.c] [objects/bitmap.c] [objects/oembitmap.c] 
	  [graphics/x11drv/bitblt.c] [include/bitmap.h]
	Improved DIB section handling using page fault handlers.
	(Note: This patch includes code contributed by Matthew J. Francis.)

	* [memory/virtual.c] [if1632/signal.c] [include/global.h]
	Page Fault handler support added.

	* [if1632/signal.c] [loader/signal.c] [tools/build.c] [misc/system.c]
	  [misc/winsock_dns.c] [include/sig_context.h] [include/thread.h]
	16-bit %fs handling improved: Always preserve 16-bit %fs value,
	always restore 32-bit %fs value for signal handlers.

	* [if1632/thunk.c] [loader/module.c] [misc/callback.c] [windows/user.c]
	  [loader/ne/resource.c] [include/callback.h] [include/module.h]
	  [if1632/kernel.spec] [if1632/wprocs.spec]
	Resource Handler function pointer stored as 16-bit SEGPTR.

	* [loader/task.c] [windows/win.c] [windows/winpos.c] [if1632/user.spec]
	  [if1632/kernel.spec] [loader/ne/module.c]
	Some minor incompatibilities fixed (Win32s relies on those):
	GetExePtr, IsWindow16 should set ES on return; WINPOS_SendNCCalcSize
	should cope with having the WINDOWPOS structure trashed;
	the OFSTRUCT in the NE module image should be placed *last*.

	* [include/windows.h]
	Missing prototype for FlushViewOfFile.

	* [loader/task.c]
	Bugfix: Command line should *not* start with a blank.
	
	* [loader/ne/segment.c]
	Bugfix: Fixups to offset 0 were never applied.

	* [misc/lstr.c]
	Use debugstr_a in OutputDebugString16.

	* [msdos/dpmi.c]
	Stub for int 31 BL=2f AX=7a20 (NetWare: Get VLM Call Address) added.

	* [msdos/int21.c]
	Stub for int 21 AX=440d CL=6f (get drive map information) added.

Fri Jun 26 18:08:30 1998  Rein Klazes <rklazes@casema.net>

	* [windows/winpos.c]
	Fix small buglet that mixed up maximized and minimized windows.

	* [include/x11drv.h] [objects/dc.c] [graphics/x11drv/pen.c]
	  [graphics/x11drv/graphics.c]
	Fix some bugs with lines joining styles. Draws rectangles
	with thick pens now correctly.

Fri Jun 26 16:22:23 1998  James Juran <jrj120@psu.edu>

	* [misc/shell.c]
	Fixed bug I introduced last release in InternalExtractIcon.

	* [win32/file.c]
	Added documentation for CreateFile32A.

	* [documentation/wine.man]
	Updated manpage.	

	* [ChangeLog]
	Added my entry from last release.

Fri Jun 26 13:33:30 1998  Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>

	* [graphics/psdrv/*] [if1632/wineps.spec] [include/psdrv.h]
	  [include/print.h] [objects/gdiobj.c]
	First stages of an internal Postscript driver. See
	graphics/psdrv/README . Should print text (badly) from win3.1 notepad,
	write and winword6.

	* [documentation/printing]
	Some notes on printing.

	* [controls/edit.c]
	Strip off WS_BORDER in WM_NCREATE, edit draws its own rectangle.
	EC_USEFONTINFO seems to be used as a left/right value for EM_SETMARGINS
	and not as an action as the docs say. This actually makes more sense.
	Scroll the caret back to zero after a WM_SETTEXT.

Fri Jun 26 10:56:25 1998  Marcus Meissner <marcus@jet.franken.de>

	* [if1632/snoop.c]
	Added win16 inter-dll snooping.

	* [win32/ordinals.c]
	KERNEL_485 is GetProcessDword.

	* [include/xmalloc.h][include/bitmap.h][misc/xmalloc.c]
	Added xcalloc so we 0 initialize XImages. 
	Fixes/Hides the 'junk around MOPYFish'.

	* [misc/ntdll.c]
	Some stubs added.

Thu Jun 25 15:22:43 1998  Adrian Harvey <adrian@select.com.au>

	* [scheduler/thread.c] 
	Implemented SuspendThread and ResumeThread.

Thu Jun 25 00:55:03 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/debug.h,dplay.h,dsound.h][multimedia/dsound.c,dplay.c]
	  [relay32/dplayx.spec,dplay.spec][multimedia/Makefile.in]
	  [documentation/status/directplay]
	Added preliminary support for DirectPlay & DirectPlayLobby. Moved the
	preliminary stubs put in the dsound files into two new files
	dplay.h and dplay.c.
	Added new debug channel (dplay) for this.
	Created new document to keep track of implementation.

	* [include/winioctl.h][win32/device.c]
	Added some framework in DeviceIoControl to, in the future, support
	the "builtin" windows dwIoControlCodes. Added new header file
	winioctl.h . 

	* [multimedia/mmsystem.c]
	Added slightly improved debugging information for PlaySound.

Wed Jun 24 12:00:00 1998  Juergen Schmied <juergen.schmied@metronet.de> 

	* [files/profile.c][graphics/x11drv/xfont.c][loader/module.c]
	Changed lstrcmpi32A to strcasecmp, lstrncmpi32A to strncasecmp,
	lstrcpy32A to strcpy, lstrlen32A to strlen, lstrcmp32A to strcmp
	because it's not necessary to support locale on such places.
	It causes a huge overhead and even fails sometimes 

	* [include/oleauto.h][include/winerror.h]
	Added some ole-related constants.

	* [misc/shell.c]
	SHELL32_DllGetClassObject, SHGetSpecialFolderLocation,
	SHGetPathFromIDList improved the stubs

	* [ole/folders.c]
	IShellFolder* functions rewrote the stubs so don't crash and give
	something sensible back, started implementation of.

	* [ole/typelib.c][relay32/oleaut32.spec]
	LoadTypeLib32, RegisterTypeLib stub.

	* [ole/ole2nls.c]
	Fixed a buffer overrun in CompareString32A.
	Test for a bad pointer in LCMapString32A (happens
	in winhlp32 while building a index for searching). 

	* [relay32/oleaut32.spec] [ole/typelib.c]
	Added stub for LoadTypeLib (ole32) to make excel95 happy.

Tue Jun 23 22:47:09 1998  Alex Priem <alexp@sci.kun.nl>

	* [files/profile.c] [relay32/kernel32.spec]
	Added WritePrivateProfileStructA, GetPrivateProfileStructA,
	GetPrivateProfileSectionNames16.

Tue Jun 23 01:34:43 1998  Pascal Cuoq <pcuoq@ens-lyon.fr>

	* [ole/ole2nls.c]
	GetStringTypeEx32A: Implemented CT_CTYPE2 and CT_CTYPE3 cases.
	LCMapString32A: Map final '\0' for '\0'-terminated strings.

	* [misc/shellord.c] [files/profile.c] [graphics/driver.c] 
	  [loader/module.c] [msdos/int21.c] [windows/driver.c] [files/drive.c]
	Changed lstrcmpi32A -> strcasecmp.  Should be OK in these places.

Sat Jun 20 23:40:00 1998  Bertho Stultiens <bertho@akhphd.au.dk>

	* [tools/wrc/]
	Wrc version 1.0.2 (20-Jun-1998). Please revert to 
	the file tools/wrc/CHANGES for details.

Sat Jun 20 14:58:00 1998  Marcel Baur  <mbaur@g26.ethz.ch>

	* [ole/ole2nls.c] [ole/nls/*]
	Added the first 57 nls files, most are not yet complete.

Wed Jun 17 11:16:54 1998  David Luyer <luyer@ucs.uwa.edu.au>

	* [relay32/relay386.c] [if1632/relay.c]
	Move debug_relay_(include|exclude)_list handling into
	seperate function RELAY_ShowDebugmsgsRelay().  Include
	checking of this for 16 bit calls (originally only
	32-bit calls).

	* [relay32/snoop.c] [misc/main.c]
	Add debug_snoop_(include|exclude)_list as per the relay stuff.
	Fix typo and add information on -debugmsg +/-relay=... in
	help on -debugmsg.  Refer to availability of snoop too.

Tue Jun 10 22:00:18 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [controls/header.c][include/header.h][include/commctrl.h]
	Added owner draw support.

	* [windows/nonclient.c][windows/sysmetics.c]
	Fixed menu bar height for Win95 look.
	Split NC_AdjustRect95() into NC_AdjustRectOuter95() and
	NC_AdjustRectInner95 to fix a menu bar bug.
	Improved Win95 look.

	* [controls/progress.c]
	Improved drawing code. Borders will be drawn by non-client code.

	* [controls/updown.c]
	Changed memory allocation and fixed some bugs.

	* [controls/toolbar.c]
	Fixed TB_BUTTONSTRUCTSIZE bug in MFC programs.
	Several improvements.

	* [misc/shell.c]
	Added stub for BrowseForFoldersA().

	* [misc/shellord.c]
	Added stub for SHELL32_147().

	* [controls/comctl32undoc.c]
	Minor changes.

	* [documentation/common_controls]
	New File: Documentation about development status, undocumented
	features and functions of the common controls.
1998-06-28 18:40:26 +00:00

1868 lines
46 KiB
C

/*
* The C RunTime DLL
*
* Implements C run-time functionality as known from UNIX.
*
* Copyright 1996 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
*/
/* FIXME: all the file handling is hopelessly broken -- AJ */
#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"
extern int FILE_GetUnixHandle( HFILE32 );
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 */
BYTE CRTDLL_iob[32*3]; /* FIXME */
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)();
/*********************************************************************
* _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)
*/
DWORD __cdecl CRTDLL__fdopen(INT32 handle, LPCSTR mode)
{
FILE *file;
switch (handle)
{
case 0 : file=stdin;
break;
case 1 : file=stdout;
break;
case 2 : file=stderr;
break;
default:
file=fdopen(handle,mode);
}
TRACE(crtdll, "open handle %d mode %s got file %p\n",
handle, mode, file);
return (DWORD)file;
}
static FILE *xlat_file_ptr(void *ptr)
{
unsigned long dif;
/* CRT sizeof(FILE) == 32 */
dif = ((char *)ptr - (char *)CRTDLL_iob) / 32;
switch(dif)
{
case 0: return stdin;
case 1: return stdout;
case 2: return stderr;
}
return (FILE*)ptr;
}
/*******************************************************************
* _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);
}
/*********************************************************************
* fopen (CRTDLL.372)
*/
DWORD __cdecl CRTDLL_fopen(LPCSTR path, LPCSTR mode)
{
FILE *file;
HFILE32 dos_fildes;
#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
INT32 flagmode=0;
int unix_fildes=0;
if ((strchr(mode,'r')&&strchr(mode,'a'))||
(strchr(mode,'r')&&strchr(mode,'w'))||
(strchr(mode,'w')&&strchr(mode,'a')))
return 0;
if (strstr(mode,"r+")) flagmode=O_RDWR;
else if (strchr(mode,'r')) flagmode = O_RDONLY;
else if (strstr(mode,"w+")) flagmode= O_RDWR | O_TRUNC | O_CREAT;
else if (strchr(mode,'w')) flagmode = O_WRONLY | O_TRUNC | O_CREAT;
else if (strstr(mode,"a+")) flagmode= O_RDWR | O_CREAT | O_APPEND;
else if (strchr(mode,'w')) flagmode = O_RDWR | O_CREAT | O_APPEND;
else if (strchr(mode,'b'))
TRACE(crtdll, "%s in BINARY mode\n",path);
dos_fildes=FILE_Open(path, flagmode);
unix_fildes=FILE_GetUnixHandle(dos_fildes);
file = fdopen(unix_fildes,mode);
TRACE(crtdll, "file %s mode %s got ufh %d dfh %d file %p\n",
path,mode,unix_fildes,dos_fildes,file);
return (DWORD)file;
}
/*********************************************************************
* fread (CRTDLL.377)
*/
DWORD __cdecl CRTDLL_fread(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile)
{
size_t ret=1;
FILE *file=xlat_file_ptr(vfile);
#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
ret=fread(ptr,size,nmemb,file);
TRACE(crtdll, "0x%08x items of size %d from file %p to %p\n",
nmemb,size,file,ptr);
if(ret!=nmemb)
WARN(crtdll, " failed!\n");
return ret;
#endif
}
/*********************************************************************
* fscanf (CRTDLL.381)
*/
INT32 __cdecl CRTDLL_fscanf( LPVOID stream, LPSTR format, ... )
{
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;
}
/*********************************************************************
* fseek (CRTDLL.382)
*/
LONG __cdecl CRTDLL_fseek(LPVOID stream, LONG offset, INT32 whence)
{
long ret;
ret=fseek(xlat_file_ptr(stream),offset,whence);
TRACE(crtdll, "file %p to 0x%08lx pos %s\n",
stream,offset,(whence==SEEK_SET)?"SEEK_SET":
(whence==SEEK_CUR)?"SEEK_CUR":
(whence==SEEK_END)?"SEEK_END":"UNKNOWN");
if(ret)
WARN(crtdll, " failed!\n");
return ret;
}
/*********************************************************************
* fsetpos (CRTDLL.383)
*/
INT32 __cdecl CRTDLL_fsetpos(LPVOID stream, fpos_t *pos)
{
TRACE(crtdll, "file %p\n", stream);
return fseek(xlat_file_ptr(stream), *pos, SEEK_SET);
}
/*********************************************************************
* ftell (CRTDLL.384)
*/
LONG __cdecl CRTDLL_ftell(LPVOID stream)
{
long ret;
ret=ftell(xlat_file_ptr(stream));
TRACE(crtdll, "file %p at 0x%08lx\n",
stream,ret);
return ret;
}
/*********************************************************************
* fwrite (CRTDLL.386)
*/
DWORD __cdecl CRTDLL_fwrite(LPVOID ptr, INT32 size, INT32 nmemb, LPVOID vfile)
{
size_t ret;
FILE *file=xlat_file_ptr(vfile);
ret=fwrite(ptr,size,nmemb,file);
TRACE(crtdll, "0x%08x items of size %d from %p to file %p\n",
nmemb,size,ptr,file);
if(ret!=nmemb)
WARN(crtdll, " Failed!\n");
return ret;
}
/*********************************************************************
* setbuf (CRTDLL.452)
*/
INT32 __cdecl CRTDLL_setbuf(LPVOID 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);
*/
setbuf(xlat_file_ptr(file),buf);
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);
}
/*********************************************************************
* fprintf (CRTDLL.373)
*/
INT32 __cdecl CRTDLL_fprintf( FILE *file, LPSTR format, ... )
{
va_list valist;
INT32 res;
va_start( valist, format );
res = vfprintf( xlat_file_ptr(file), format, valist );
va_end( valist );
return res;
}
/*********************************************************************
* vfprintf (CRTDLL.373)
*/
INT32 __cdecl CRTDLL_vfprintf( FILE *file, LPSTR format, va_list args )
{
return vfprintf( xlat_file_ptr(file), format, args );
}
/*********************************************************************
* 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(LPVOID stream)
{
int ret;
ret = fflush(xlat_file_ptr(stream));
TRACE(crtdll,"%p returnd %d\n",stream,ret);
if(ret)
WARN(crtdll, " Failed!\n");
return ret;
}
/*********************************************************************
* gets (CRTDLL.391)
*/
LPSTR __cdecl CRTDLL_gets(LPSTR buf)
{
char * ret;
/* BAD, for the whole WINE process blocks... just done this way to test
* windows95's ftp.exe.
*/
ret = gets(buf);
TRACE(crtdll,"got %s\n",ret);
return ret;
}
/*********************************************************************
* 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, FILE *stream )
{
TRACE(crtdll, "%c to file %p\n",c,stream);
return fputc(c,xlat_file_ptr(stream));
}
/*********************************************************************
* fputs (CRTDLL.375)
*/
INT32 __cdecl CRTDLL_fputs( LPCSTR s, FILE *stream )
{
TRACE(crtdll, "%s to file %p\n",s,stream);
return fputs(s,xlat_file_ptr(stream));
}
/*********************************************************************
* 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, FILE *stream)
{
TRACE(crtdll, " %c to file %p\n",c,stream);
return fputc(c,xlat_file_ptr(stream));
}
/*********************************************************************
* fgetc (CRTDLL.366)
*/
INT32 __cdecl CRTDLL_fgetc( FILE *stream )
{
int ret= fgetc(xlat_file_ptr(stream));
TRACE(crtdll, "got %d\n",ret);
return ret;
}
/*********************************************************************
* getc (CRTDLL.388)
*/
INT32 __cdecl CRTDLL_getc( FILE *stream )
{
int ret= fgetc(xlat_file_ptr(stream));
TRACE(crtdll, "got %d\n",ret);
return ret;
}
/*********************************************************************
* _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;
}
/*********************************************************************
* fgets (CRTDLL.368)
*/
CHAR* __cdecl CRTDLL_fgets(LPSTR s,INT32 size, LPVOID stream)
{
char * ret;
char * control_M;
ret=fgets(s, size,xlat_file_ptr(stream));
/*FIXME: Control with CRTDLL_setmode */
control_M= strrchr(s,'\r');
/*delete CR if we read a DOS File */
if (control_M)
{
*control_M='\n';
*(control_M+1)=0;
}
TRACE(crtdll, "got %s for %d chars from file %p\n",
s,size,stream);
if(ret)
WARN(crtdll, " Failed!\n");
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 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 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( FILE *stream )
{
int unix_handle;
HFILE32 dos_handle=1;
HFILE32 ret=EOF;
stream=xlat_file_ptr(stream);
unix_handle=fileno(stream);
if (unix_handle<4) ret= fclose(stream);
else {
while(FILE_GetUnixHandle(dos_handle) != unix_handle) dos_handle++;
fclose(stream);
ret = _lclose32( dos_handle);
}
TRACE(crtdll,"(%p) ufh %d dfh %d\n",
stream,unix_handle,dos_handle);
if(ret)
WARN(crtdll, " Failed!\n");
return ret;
}
/*********************************************************************
* _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)
{
HFILE32 ret=0;
int wineflags=0;
/* 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
*/
wineflags = (flags & 3);
if (flags & 0x0008 ) wineflags |= O_APPEND;
if (flags & 0x0100 ) wineflags |= O_CREAT;
if (flags & 0x0200 ) wineflags |= O_TRUNC;
if (flags & 0x0400 ) wineflags |= O_EXCL;
if (flags & 0xf0f4 )
TRACE(crtdll,"CRTDLL_open file unsupported flags 0x%04x\n",flags);
/* End Fixme */
ret = FILE_Open(path,wineflags);
TRACE(crtdll,"CRTDLL_open file %s mode 0x%04x (lccmode 0x%04x) got dfh %d\n",
path,wineflags,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( FILE *stream )
{
int ret;
ret=feof(xlat_file_ptr(stream));
TRACE(crtdll,"(%p) %s\n",stream,(ret)?"true":"false");
return ret;
}
/*********************************************************************
* 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 = NULL;
if (drivechar)
{
strncat(drive,path,drivechar-path+1);
path = drivechar+1;
}
}
if (directory)
{
*directory = NULL;
if (dirchar)
{
strncat(directory,path,dirchar-path+1);
path = dirchar+1;
}
}
if (filename)
{
*filename = NULL;
if (namechar)
{
strncat(filename,path,namechar-path);
if (extension)
{
*extension = NULL;
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;
}
/*********************************************************************
* _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;
}
/*********************************************************************
* _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;
}
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;
}