- Implement console I/O
- Support temporary files, add tmpfile, rmtmp - spawn* functions: fix args, add cwait, searchenv
This commit is contained in:
parent
5c312198f6
commit
61e48c7af1
|
@ -9,6 +9,7 @@ LDDLLFLAGS = @LDDLLFLAGS@
|
|||
SYMBOLFILE = $(MODULE).tmp.o
|
||||
|
||||
C_SRCS = \
|
||||
console.c \
|
||||
crtdll_main.c \
|
||||
dir.c \
|
||||
exit.c \
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* CRTDLL console functions
|
||||
*
|
||||
* Copyright 2000 Jon Griffiths
|
||||
*
|
||||
* NOTES
|
||||
* Only a one byte ungetch buffer is implemented, as per MS docs.
|
||||
* Output is not redirectable using these functions, as per MS docs.
|
||||
*
|
||||
* FIXME:
|
||||
* There are several problems with the console input mechanism as
|
||||
* currently implemented in Wine. When these are ironed out the
|
||||
* getch() function will work correctly (gets() is currently fine).
|
||||
* The problem is that opening CONIN$ does not work, and
|
||||
* reading from STD_INPUT_HANDLE is line buffered.
|
||||
*/
|
||||
#include "crtdll.h"
|
||||
#include "wincon.h"
|
||||
|
||||
DEFAULT_DEBUG_CHANNEL(crtdll);
|
||||
|
||||
static HANDLE __CRTDLL_console_in = INVALID_HANDLE_VALUE;
|
||||
static HANDLE __CRTDLL_console_out = INVALID_HANDLE_VALUE;
|
||||
static int __CRTDLL_console_buffer = EOF;
|
||||
|
||||
|
||||
/* INTERNAL: Initialise console handles */
|
||||
VOID __CRTDLL_init_console(VOID)
|
||||
{
|
||||
TRACE(":Opening console handles\n");
|
||||
|
||||
__CRTDLL_console_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
/* FIXME: Should be initialised with:
|
||||
* CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ,
|
||||
* NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
|
||||
*/
|
||||
|
||||
__CRTDLL_console_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
|
||||
|
||||
if ((__CRTDLL_console_in == INVALID_HANDLE_VALUE) ||
|
||||
(__CRTDLL_console_out == INVALID_HANDLE_VALUE))
|
||||
WARN(":Console handle Initialisation FAILED!\n");
|
||||
}
|
||||
|
||||
/* INTERNAL: Free console handles */
|
||||
void __CRTDLL_free_console(void)
|
||||
{
|
||||
TRACE(":Closing console handles\n");
|
||||
CloseHandle(__CRTDLL_console_in);
|
||||
CloseHandle(__CRTDLL_console_out);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _cgets (CRTDLL.050)
|
||||
*
|
||||
* Get a string from CONIN$.
|
||||
*/
|
||||
LPSTR __cdecl CRTDLL__cgets(LPSTR str)
|
||||
{
|
||||
char *buf = str + 2;
|
||||
int c;
|
||||
str[1] = 0; /* Length */
|
||||
/* FIXME: No editing of string supported */
|
||||
do
|
||||
{
|
||||
if (str[1] >= str[0] || (str[1]++, c = CRTDLL__getche()) == EOF || c == '\n')
|
||||
{
|
||||
*buf = '\0';
|
||||
return str + 2;
|
||||
}
|
||||
*buf++ = c & 0xff;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _cputs (CRTDLL.065)
|
||||
*
|
||||
* Write a string to CONOUT$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__cputs(LPCSTR str)
|
||||
{
|
||||
DWORD count;
|
||||
if (WriteConsoleA(__CRTDLL_console_out, str, strlen(str), &count, NULL)
|
||||
&& count == 1)
|
||||
return 0;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _getch (CRTDLL.118)
|
||||
*
|
||||
* Get a character from CONIN$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__getch(VOID)
|
||||
{
|
||||
if (__CRTDLL_console_buffer != EOF)
|
||||
{
|
||||
INT retVal = __CRTDLL_console_buffer;
|
||||
__CRTDLL_console_buffer = EOF;
|
||||
return retVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
INPUT_RECORD ir;
|
||||
DWORD count;
|
||||
DWORD mode = 0;
|
||||
|
||||
GetConsoleMode(__CRTDLL_console_in, &mode);
|
||||
if(mode) SetConsoleMode(__CRTDLL_console_in, 0);
|
||||
|
||||
do {
|
||||
if (ReadConsoleInputA(__CRTDLL_console_in, &ir, 1, &count))
|
||||
{
|
||||
/* Only interested in ASCII chars */
|
||||
if (ir.EventType == KEY_EVENT &&
|
||||
ir.Event.KeyEvent.bKeyDown &&
|
||||
ir.Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
if(mode) SetConsoleMode(__CRTDLL_console_in, mode);
|
||||
return ir.Event.KeyEvent.uChar.AsciiChar;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while(1);
|
||||
if (mode) SetConsoleMode(__CRTDLL_console_in, mode);
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _getche (CRTDLL.119)
|
||||
*
|
||||
* Get a character from CONIN$ and echo it to CONOUT$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__getche(VOID)
|
||||
{
|
||||
INT res = CRTDLL__getch();
|
||||
if (res != EOF && CRTDLL__putch(res) != EOF)
|
||||
return res;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _kbhit (CRTDLL.169)
|
||||
*
|
||||
* Check if a character is waiting in CONIN$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__kbhit(VOID)
|
||||
{
|
||||
if (__CRTDLL_console_buffer != EOF)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
/* FIXME: There has to be a faster way than this in Win32.. */
|
||||
INPUT_RECORD *ir;
|
||||
DWORD count = 0;
|
||||
int retVal = 0, i;
|
||||
|
||||
GetNumberOfConsoleInputEvents(__CRTDLL_console_in, &count);
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
if (!(ir = CRTDLL_malloc(count * sizeof(INPUT_RECORD))))
|
||||
return 0;
|
||||
|
||||
if (!PeekConsoleInputA(__CRTDLL_console_in, ir, count, &count))
|
||||
return 0;
|
||||
|
||||
for(i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (ir[i].EventType == KEY_EVENT &&
|
||||
ir[i].Event.KeyEvent.bKeyDown &&
|
||||
ir[i].Event.KeyEvent.uChar.AsciiChar)
|
||||
{
|
||||
retVal = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CRTDLL_free(ir);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _putch (CRTDLL.250)
|
||||
*
|
||||
* Write a character to CONOUT$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__putch(INT c)
|
||||
{
|
||||
DWORD count;
|
||||
if (WriteConsoleA(__CRTDLL_console_out, &c, 1, &count, NULL) &&
|
||||
count == 1)
|
||||
return c;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _ungetch (CRTDLL.311)
|
||||
*
|
||||
* Un-get a character from CONIN$.
|
||||
*/
|
||||
INT __cdecl CRTDLL__ungetch(INT c)
|
||||
{
|
||||
if (c == EOF || __CRTDLL_console_buffer != EOF)
|
||||
return EOF;
|
||||
|
||||
return __CRTDLL_console_buffer = c;
|
||||
}
|
||||
|
|
@ -55,6 +55,8 @@
|
|||
#define _O_TEXT 0x4000
|
||||
#define _O_BINARY 0x8000
|
||||
|
||||
#define _O_TEMPORARY 0x0040 /* Will be closed and deleted on exit */
|
||||
|
||||
/* _access() bit flags FIXME: incomplete */
|
||||
#define W_OK 2
|
||||
|
||||
|
@ -246,7 +248,7 @@ typedef INT (__cdecl *comp_func)(LPCVOID, LPCVOID );
|
|||
|
||||
/* CRTDLL functions */
|
||||
|
||||
/* CRTDLL_dir.c */
|
||||
/* dir.c */
|
||||
INT __cdecl CRTDLL__chdir( LPCSTR newdir );
|
||||
BOOL __cdecl CRTDLL__chdrive( INT newdrive );
|
||||
INT __cdecl CRTDLL__findclose( DWORD hand );
|
||||
|
@ -259,7 +261,7 @@ INT __cdecl CRTDLL__getdrive( VOID );
|
|||
INT __cdecl CRTDLL__mkdir( LPCSTR newdir );
|
||||
INT __cdecl CRTDLL__rmdir( LPSTR dir );
|
||||
|
||||
/* CRTDLL_exit.c */
|
||||
/* exit.c */
|
||||
INT __cdecl CRTDLL__abnormal_termination( VOID );
|
||||
VOID __cdecl CRTDLL__amsg_exit( INT err );
|
||||
VOID __cdecl CRTDLL__assert( LPVOID str, LPVOID file, UINT line );
|
||||
|
@ -271,13 +273,14 @@ VOID __cdecl CRTDLL_abort( VOID );
|
|||
INT __cdecl CRTDLL_atexit( atexit_function x );
|
||||
atexit_function __cdecl CRTDLL__onexit( atexit_function func);
|
||||
|
||||
/* CRTDLL_file.c */
|
||||
/* file.c */
|
||||
CRTDLL_FILE* __cdecl CRTDLL__iob( VOID );
|
||||
CRTDLL_FILE* __cdecl CRTDLL__fsopen( LPCSTR path, LPCSTR mode, INT share );
|
||||
CRTDLL_FILE* __cdecl CRTDLL__fdopen( INT fd, LPCSTR mode );
|
||||
LPSTR __cdecl CRTDLL__mktemp( LPSTR pattern );
|
||||
CRTDLL_FILE* __cdecl CRTDLL_fopen( LPCSTR path, LPCSTR mode );
|
||||
CRTDLL_FILE* __cdecl CRTDLL_freopen( LPCSTR path,LPCSTR mode,CRTDLL_FILE* f );
|
||||
CRTDLL_FILE* __cdecl CRTDLL_tmpfile( void );
|
||||
INT __cdecl CRTDLL__fgetchar( VOID );
|
||||
DWORD __cdecl CRTDLL_fread( LPVOID ptr,INT size,INT nmemb,CRTDLL_FILE* file );
|
||||
INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* stream, LPSTR format, ... );
|
||||
|
@ -300,6 +303,7 @@ INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE* file, LPCSTR format,va_list args);
|
|||
INT __cdecl CRTDLL_fprintf( CRTDLL_FILE* file, LPCSTR format, ... );
|
||||
INT __cdecl CRTDLL__putw( INT val, CRTDLL_FILE* file );
|
||||
INT __cdecl CRTDLL__read( INT fd, LPVOID buf, UINT count );
|
||||
INT __cdecl CRTDLL__rmtmp( void );
|
||||
UINT __cdecl CRTDLL__write( INT fd,LPCVOID buf,UINT count );
|
||||
INT __cdecl CRTDLL__access( LPCSTR filename, INT mode );
|
||||
INT __cdecl CRTDLL_fflush( CRTDLL_FILE* file );
|
||||
|
@ -417,8 +421,9 @@ double __cdecl CRTDLL__y0( double x );
|
|||
double __cdecl CRTDLL__y1( double x );
|
||||
double __cdecl CRTDLL__yn( INT x, double y );
|
||||
double __cdecl CRTDLL__nextafter( double x, double y );
|
||||
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff);
|
||||
|
||||
/* CRTDLL_mem.c */
|
||||
/* memory.c */
|
||||
LPVOID __cdecl CRTDLL_new( DWORD size );
|
||||
VOID __cdecl CRTDLL_delete( LPVOID ptr );
|
||||
new_handler_type __cdecl CRTDLL_set_new_handler( new_handler_type func );
|
||||
|
@ -433,11 +438,15 @@ VOID __cdecl CRTDLL_free( LPVOID ptr );
|
|||
LPVOID __cdecl CRTDLL_malloc( DWORD size );
|
||||
LPVOID __cdecl CRTDLL_realloc( VOID *ptr, DWORD size );
|
||||
|
||||
/* CRTDLL_spawn.c */
|
||||
HANDLE __cdecl CRTDLL__spawnve( INT flags, LPSTR name, LPSTR *argv, LPSTR *envv);
|
||||
INT __cdecl CRTDLL_system( LPSTR x );
|
||||
/* spawn.c */
|
||||
HANDLE __cdecl CRTDLL__spawnv( INT flags, LPCSTR name, LPCSTR *argv);
|
||||
HANDLE __cdecl CRTDLL__spawnve( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
|
||||
HANDLE __cdecl CRTDLL__spawnvp( INT flags, LPCSTR name, LPCSTR *argv);
|
||||
HANDLE __cdecl CRTDLL__spawnvpe( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
|
||||
INT __cdecl CRTDLL_system( LPCSTR cmd );
|
||||
INT __cdecl CRTDLL__cwait( PINT status, INT pid, INT action );
|
||||
|
||||
/* CRTDLL_str.c */
|
||||
/* str.c */
|
||||
LPSTR __cdecl CRTDLL__strdec( LPSTR str1, LPSTR str2 );
|
||||
LPSTR __cdecl CRTDLL__strdup( LPCSTR ptr );
|
||||
LPSTR __cdecl CRTDLL__strinc( LPSTR str );
|
||||
|
@ -450,7 +459,7 @@ LONG __cdecl CRTDLL__strncnt( LPSTR str, LONG max );
|
|||
LPSTR __cdecl CRTDLL__strspnp( LPSTR str1, LPSTR str2 );
|
||||
VOID __cdecl CRTDLL__swab( LPSTR src, LPSTR dst, INT len );
|
||||
|
||||
/* CRTDLL_time.c */
|
||||
/* time.c */
|
||||
LPSTR __cdecl CRTDLL__strdate ( LPSTR date );
|
||||
LPSTR __cdecl CRTDLL__strtime ( LPSTR date );
|
||||
clock_t __cdecl CRTDLL_clock ( void );
|
||||
|
@ -483,10 +492,22 @@ INT __cdecl CRTDLL_iswspace( WCHAR wc );
|
|||
INT __cdecl CRTDLL_iswupper( WCHAR wc );
|
||||
INT __cdecl CRTDLL_iswxdigit( WCHAR wc );
|
||||
|
||||
/* console.c */
|
||||
LPSTR __cdecl CRTDLL__cgets( LPSTR str );
|
||||
INT __cdecl CRTDLL__cputs( LPCSTR str );
|
||||
INT __cdecl CRTDLL__getch( VOID );
|
||||
INT __cdecl CRTDLL__getche( VOID );
|
||||
INT __cdecl CRTDLL__kbhit( VOID );
|
||||
INT __cdecl CRTDLL__putch( INT c );
|
||||
INT __cdecl CRTDLL__ungetch( INT c );
|
||||
|
||||
|
||||
/* INTERNAL: Shared internal functions */
|
||||
void __CRTDLL__set_errno(ULONG err);
|
||||
LPSTR __CRTDLL__strndup(LPSTR buf, INT size);
|
||||
VOID __CRTDLL__init_io(VOID);
|
||||
VOID __CRTDLL_init_console(VOID);
|
||||
VOID __CRTDLL_free_console(VOID);
|
||||
|
||||
extern WORD CRTDLL_ctype [257];
|
||||
extern WORD __CRTDLL_current_ctype[257];
|
||||
|
|
|
@ -57,7 +57,7 @@ debug_channels (crtdll)
|
|||
@ cdecl _c_exit() CRTDLL__c_exit
|
||||
@ cdecl _cabs(long) CRTDLL__cabs
|
||||
@ cdecl _cexit() CRTDLL__cexit
|
||||
@ stub _cgets
|
||||
@ cdecl _cgets(str) CRTDLL__cgets
|
||||
@ cdecl _chdir(str) CRTDLL__chdir
|
||||
@ cdecl _chdrive(long) CRTDLL__chdrive
|
||||
@ cdecl _chgsign(double) CRTDLL__chgsign
|
||||
|
@ -72,11 +72,11 @@ debug_channels (crtdll)
|
|||
@ cdecl _copysign(double double) CRTDLL__copysign
|
||||
@ stub _cprintf
|
||||
@ stub _cpumode_dll
|
||||
@ stub _cputs
|
||||
@ cdecl _cputs(str) CRTDLL__cputs
|
||||
@ cdecl _creat(str long) CRTDLL__creat
|
||||
@ stub _cscanf
|
||||
@ extern _ctype CRTDLL_ctype
|
||||
@ stub _cwait
|
||||
@ cdecl _cwait(ptr long long) CRTDLL__cwait
|
||||
@ stub _daylight_dll
|
||||
@ stub _dup
|
||||
@ stub _dup2
|
||||
|
@ -125,8 +125,8 @@ debug_channels (crtdll)
|
|||
@ cdecl _futime(long ptr) CRTDLL__futime
|
||||
@ cdecl _gcvt(double long str) gcvt
|
||||
@ cdecl _get_osfhandle(long) CRTDLL__get_osfhandle
|
||||
@ stub _getch
|
||||
@ stub _getche
|
||||
@ cdecl _getch() CRTDLL__getch
|
||||
@ cdecl _getche() CRTDLL__getche
|
||||
@ cdecl _getcwd(ptr long) CRTDLL__getcwd
|
||||
@ cdecl _getdcwd(long ptr long) CRTDLL__getdcwd
|
||||
@ cdecl _getdiskfree(long ptr) CRTDLL__getdiskfree
|
||||
|
@ -177,7 +177,7 @@ debug_channels (crtdll)
|
|||
@ cdecl _j0(double) j0
|
||||
@ cdecl _j1(double) j1
|
||||
@ cdecl _jn(long double) jn
|
||||
@ stub _kbhit
|
||||
@ cdecl _kbhit() CRTDLL__kbhit
|
||||
@ cdecl _lfind(ptr ptr ptr long ptr) CRTDLL__lfind
|
||||
@ cdecl _loaddll(str) CRTDLL__loaddll
|
||||
@ cdecl _local_unwind2(ptr long) CRTDLL__local_unwind2
|
||||
|
@ -259,17 +259,17 @@ debug_channels (crtdll)
|
|||
@ stub _pipe
|
||||
@ stub _popen
|
||||
@ cdecl _purecall() CRTDLL__purecall
|
||||
@ stub _putch
|
||||
@ cdecl _putch(long) CRTDLL__putch
|
||||
@ stub _putenv
|
||||
@ cdecl _putw(long ptr) CRTDLL__putw
|
||||
@ stub _pwctype_dll
|
||||
@ cdecl _read(long ptr long) CRTDLL__read
|
||||
@ cdecl _rmdir(str) CRTDLL__rmdir
|
||||
@ stub _rmtmp
|
||||
@ cdecl _rmtmp() CRTDLL__rmtmp
|
||||
@ cdecl _rotl (long long) CRTDLL__rotl
|
||||
@ cdecl _rotr (long long) CRTDLL__rotr
|
||||
@ cdecl _scalb (double long) CRTDLL__scalb
|
||||
@ stub _searchenv
|
||||
@ cdecl _searchenv(str str str) CRTDLL__searchenv
|
||||
@ stub _seterrormode
|
||||
@ cdecl _setjmp (ptr) CRTDLL__setjmp
|
||||
@ cdecl _setmode(long long) CRTDLL__setmode
|
||||
|
@ -282,10 +282,10 @@ debug_channels (crtdll)
|
|||
@ stub _spawnle
|
||||
@ stub _spawnlp
|
||||
@ stub _spawnlpe
|
||||
@ stub _spawnv
|
||||
@ cdecl _spawnv(long str ptr) CRTDLL__spawnv
|
||||
@ cdecl _spawnve(long str ptr ptr) CRTDLL__spawnve
|
||||
@ stub _spawnvp
|
||||
@ stub _spawnvpe
|
||||
@ cdecl _spawnvp(long str ptr) CRTDLL__spawnvp
|
||||
@ cdecl _spawnvpe(long str ptr ptr) CRTDLL__spawnvpe
|
||||
@ cdecl _splitpath (str ptr ptr ptr ptr) CRTDLL__splitpath
|
||||
@ cdecl _stat (str ptr) CRTDLL__stat
|
||||
@ cdecl _statusfp() CRTDLL__statusfp
|
||||
|
@ -321,7 +321,7 @@ debug_channels (crtdll)
|
|||
@ forward _ultoa ntdll._ultoa
|
||||
@ cdecl _ultow(long str long) CRTDLL__ultow
|
||||
@ cdecl _umask(long) CRTDLL__umask
|
||||
@ stub _ungetch
|
||||
@ cdecl _ungetch(long) CRTDLL__ungetch
|
||||
@ cdecl _unlink(str) CRTDLL__unlink
|
||||
@ cdecl _unloaddll(long) CRTDLL__unloaddll
|
||||
@ cdecl _utime(str ptr) CRTDLL__utime
|
||||
|
@ -496,7 +496,7 @@ debug_channels (crtdll)
|
|||
@ cdecl tan(double) tan
|
||||
@ cdecl tanh(double) tanh
|
||||
@ cdecl time(ptr) CRTDLL_time
|
||||
@ stub tmpfile
|
||||
@ cdecl tmpfile() CRTDLL_tmpfile
|
||||
@ cdecl tmpnam(str) CRTDLL_tmpnam
|
||||
@ cdecl tolower(long) tolower
|
||||
@ cdecl toupper(long) toupper
|
||||
|
|
|
@ -124,9 +124,16 @@ BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
|
|||
|
||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||||
__CRTDLL__init_io();
|
||||
__CRTDLL_init_console();
|
||||
CRTDLL_setlocale( CRTDLL_LC_ALL, "C" );
|
||||
CRTDLL_HUGE_dll = HUGE_VAL;
|
||||
}
|
||||
else if (fdwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
CRTDLL__fcloseall();
|
||||
__CRTDLL_free_console();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1672,3 +1679,67 @@ double __cdecl CRTDLL__nextafter(double x, double y)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _searchenv (CRTDLL.260)
|
||||
*
|
||||
* Search CWD and each directory of an environment variable for
|
||||
* location of a file.
|
||||
*/
|
||||
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff)
|
||||
{
|
||||
LPSTR envVal, penv;
|
||||
char curPath[MAX_PATH];
|
||||
|
||||
*buff = '\0';
|
||||
|
||||
/* Try CWD first */
|
||||
if (GetFileAttributesA( file ) != 0xFFFFFFFF)
|
||||
{
|
||||
GetFullPathNameA( file, MAX_PATH, buff, NULL );
|
||||
/* Sigh. This error is *always* set, regardless of sucess */
|
||||
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search given environment variable */
|
||||
envVal = CRTDLL_getenv(env);
|
||||
if (!envVal)
|
||||
{
|
||||
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
penv = envVal;
|
||||
TRACE(":searching for %s in paths %s\n", file, envVal);
|
||||
|
||||
do
|
||||
{
|
||||
LPSTR end = penv;
|
||||
|
||||
while(*end && *end != ';') end++; /* Find end of next path */
|
||||
if (penv == end || !*penv)
|
||||
{
|
||||
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
strncpy(curPath, penv, end - penv);
|
||||
if (curPath[end - penv] != '/' || curPath[end - penv] != '\\')
|
||||
{
|
||||
curPath[end - penv] = '\\';
|
||||
curPath[end - penv + 1] = '\0';
|
||||
}
|
||||
else
|
||||
curPath[end - penv] = '\0';
|
||||
|
||||
strcat(curPath, file);
|
||||
TRACE("Checking for file %s\n", curPath);
|
||||
if (GetFileAttributesA( curPath ) != 0xFFFFFFFF)
|
||||
{
|
||||
strcpy(buff, curPath);
|
||||
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
|
||||
return; /* Found */
|
||||
}
|
||||
penv = *end ? end + 1 : end;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
DEFAULT_DEBUG_CHANNEL(crtdll);
|
||||
|
||||
/* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
|
||||
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft);
|
||||
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
|
||||
{
|
||||
DWORD dw;
|
||||
|
@ -28,7 +27,7 @@ static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
|
|||
/* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
|
||||
* attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
|
||||
*/
|
||||
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
|
||||
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
|
||||
ft->attrib = 0;
|
||||
else
|
||||
ft->attrib = fd->dwFileAttributes;
|
||||
|
@ -341,3 +340,4 @@ INT __cdecl CRTDLL__rmdir(LPSTR dir)
|
|||
__CRTDLL__set_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,8 +105,7 @@ VOID __cdecl CRTDLL__assert(LPVOID str, LPVOID file, UINT line)
|
|||
*/
|
||||
VOID __cdecl CRTDLL__c_exit(VOID)
|
||||
{
|
||||
FIXME("not calling CRTDLL cleanup\n");
|
||||
/* dont exit, return to caller */
|
||||
/* All cleanup is done on DLL detach; Return to caller */
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,8 +114,7 @@ VOID __cdecl CRTDLL__c_exit(VOID)
|
|||
*/
|
||||
VOID __cdecl CRTDLL__cexit(VOID)
|
||||
{
|
||||
FIXME("not calling CRTDLL cleanup\n");
|
||||
/* dont exit, return to caller */
|
||||
/* All cleanup is done on DLL detach; Return to caller */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ DEFAULT_DEBUG_CHANNEL(crtdll);
|
|||
HANDLE __CRTDLL_handles[CRTDLL_MAX_FILES];
|
||||
CRTDLL_FILE* __CRTDLL_files[CRTDLL_MAX_FILES];
|
||||
INT __CRTDLL_flags[CRTDLL_MAX_FILES];
|
||||
LPSTR __CRTDLL_tempfiles[CRTDLL_MAX_FILES];
|
||||
CRTDLL_FILE __CRTDLL_iob[3];
|
||||
|
||||
static int __CRTDLL_fdstart = 3; /* first unallocated fd */
|
||||
|
@ -182,6 +183,7 @@ VOID __CRTDLL__init_io(VOID)
|
|||
/* FILE structs for stdin/out/err are static and never deleted */
|
||||
__CRTDLL_files[i] = &__CRTDLL_iob[i];
|
||||
__CRTDLL_iob[i]._file = i;
|
||||
__CRTDLL_tempfiles[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,6 +263,14 @@ INT __cdecl CRTDLL__close(INT fd)
|
|||
__CRTDLL__set_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
if (__CRTDLL_tempfiles[fd])
|
||||
{
|
||||
TRACE("deleting temporary file '%s'\n",__CRTDLL_tempfiles[fd]);
|
||||
CRTDLL__unlink(__CRTDLL_tempfiles[fd]);
|
||||
CRTDLL_free(__CRTDLL_tempfiles[fd]);
|
||||
__CRTDLL_tempfiles[fd] = NULL;
|
||||
}
|
||||
|
||||
TRACE(":ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -361,7 +371,8 @@ INT __cdecl CRTDLL__fcloseall(VOID)
|
|||
num_closed++;
|
||||
}
|
||||
|
||||
TRACE(":closed (%d) handles\n",num_closed);
|
||||
if (num_closed)
|
||||
TRACE(":closed (%d) handles\n",num_closed);
|
||||
return num_closed;
|
||||
}
|
||||
|
||||
|
@ -792,12 +803,10 @@ INT __cdecl CRTDLL__open(LPCSTR path,INT flags)
|
|||
flags &= ~_O_TEXT;
|
||||
}
|
||||
|
||||
if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL|_O_CREAT|_O_RDWR))
|
||||
if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL
|
||||
|_O_CREAT|_O_RDWR|_O_TEMPORARY))
|
||||
TRACE(":unsupported flags 0x%04x\n",flags);
|
||||
|
||||
/* clear those pesky flags ;-) */
|
||||
flags &= (_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL|_O_CREAT|_O_RDWR);
|
||||
|
||||
hand = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, creation, FILE_ATTRIBUTE_NORMAL, -1);
|
||||
|
||||
|
@ -808,12 +817,17 @@ INT __cdecl CRTDLL__open(LPCSTR path,INT flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
fd = __CRTDLL__alloc_fd(hand,ioflag);
|
||||
fd = __CRTDLL__alloc_fd(hand, ioflag);
|
||||
|
||||
TRACE(":fd (%d) handle (%d)\n",fd, hand);
|
||||
|
||||
if (flags & _IOAPPEND && fd > 0)
|
||||
CRTDLL__lseek(fd, 0, FILE_END );
|
||||
if (fd > 0)
|
||||
{
|
||||
if (flags & _O_TEMPORARY)
|
||||
__CRTDLL_tempfiles[fd] = CRTDLL__strdup(path);
|
||||
if (ioflag & _IOAPPEND)
|
||||
CRTDLL__lseek(fd, 0, FILE_END );
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -843,6 +857,28 @@ INT __cdecl CRTDLL__putw(INT val, CRTDLL_FILE* file)
|
|||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _rmtmp (CRTDLL.256)
|
||||
*
|
||||
* Remove all temporary files created by tmpfile().
|
||||
*/
|
||||
INT __cdecl CRTDLL__rmtmp(void)
|
||||
{
|
||||
int num_removed = 0, i = 3;
|
||||
|
||||
while(i < __CRTDLL_fdend)
|
||||
if (__CRTDLL_tempfiles[i])
|
||||
{
|
||||
CRTDLL__close(i);
|
||||
num_removed++;
|
||||
}
|
||||
|
||||
if (num_removed)
|
||||
TRACE(":removed (%d) temp files\n",num_removed);
|
||||
return num_removed;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _read (CRTDLL.256)
|
||||
*
|
||||
|
@ -1630,6 +1666,24 @@ INT __cdecl CRTDLL_setbuf(CRTDLL_FILE* file, LPSTR buf)
|
|||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* tmpfile (CRTDLL.486)
|
||||
*
|
||||
* Create and return a temporary file.
|
||||
*/
|
||||
CRTDLL_FILE* __cdecl CRTDLL_tmpfile(void)
|
||||
{
|
||||
LPSTR filename = CRTDLL_tmpnam(NULL);
|
||||
int fd = CRTDLL__open(filename, _O_CREAT | _O_BINARY |
|
||||
_O_RDWR | _O_TEMPORARY);
|
||||
|
||||
if (fd != -1)
|
||||
return __CRTDLL__alloc_fp(fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* tmpnam (CRTDLL.490)
|
||||
*
|
||||
|
|
|
@ -60,8 +60,7 @@ extern INT CRTDLL_doserrno;
|
|||
|
||||
|
||||
/* INTERNAL: Spawn a child process */
|
||||
static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env);
|
||||
static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
|
||||
static int __CRTDLL__spawn(INT flags, LPCSTR exe, LPSTR args, LPSTR env)
|
||||
{
|
||||
STARTUPINFOA si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
@ -109,10 +108,9 @@ static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
|
|||
|
||||
|
||||
/* INTERNAL: Convert argv list to a single 'delim'-seperated string */
|
||||
static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim);
|
||||
static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
|
||||
static LPSTR __CRTDLL__argvtos(LPCSTR *arg, CHAR delim)
|
||||
{
|
||||
LPSTR *search = arg;
|
||||
LPCSTR *search = arg;
|
||||
LONG size = 0;
|
||||
LPSTR ret;
|
||||
|
||||
|
@ -145,40 +143,107 @@ static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
|
|||
|
||||
|
||||
/*********************************************************************
|
||||
* _spawnve (CRTDLL.274)
|
||||
* _cwait (CRTDLL.069)
|
||||
*
|
||||
* Wait for a spawned process to finish.
|
||||
*/
|
||||
INT __cdecl CRTDLL__cwait(PINT status, INT pid, INT action)
|
||||
{
|
||||
HANDLE hPid = (HANDLE)pid;
|
||||
|
||||
action = action; /* Remove warning */
|
||||
|
||||
if (!WaitForSingleObject(hPid, -1)) /* wait forvever */
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
DWORD stat;
|
||||
GetExitCodeProcess(hPid, &stat);
|
||||
*status = (INT)stat;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
CRTDLL_doserrno = GetLastError();
|
||||
|
||||
if (CRTDLL_doserrno == ERROR_INVALID_HANDLE)
|
||||
CRTDLL_errno = ECHILD;
|
||||
else
|
||||
__CRTDLL__set_errno(CRTDLL_doserrno);
|
||||
|
||||
return status ? *status = -1 : -1;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _spawnv (CRTDLL.273)
|
||||
*
|
||||
* Spawn a process.
|
||||
*
|
||||
*/
|
||||
HANDLE __cdecl CRTDLL__spawnve(INT flags, LPSTR name, LPSTR *argv, LPSTR *envv)
|
||||
HANDLE __cdecl CRTDLL__spawnv(INT flags, LPCSTR name, LPCSTR *argv)
|
||||
{
|
||||
return CRTDLL__spawnve(flags, name, argv, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _spawnve (CRTDLL.274)
|
||||
*
|
||||
* Spawn a process.
|
||||
*/
|
||||
HANDLE __cdecl CRTDLL__spawnve(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
|
||||
{
|
||||
LPSTR args = __CRTDLL__argvtos(argv,' ');
|
||||
LPSTR envs = __CRTDLL__argvtos(envv,0);
|
||||
LPSTR fullname = name;
|
||||
LPCSTR fullname = name;
|
||||
HANDLE ret = -1;
|
||||
|
||||
FIXME(":not translating name %s to locate program\n",fullname);
|
||||
TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
|
||||
|
||||
if (args)
|
||||
{
|
||||
HANDLE ret = __CRTDLL__spawn(flags, fullname, args, envs);
|
||||
ret = __CRTDLL__spawn(flags, fullname, args, envs);
|
||||
CRTDLL_free(args);
|
||||
CRTDLL_free(envs);
|
||||
return ret;
|
||||
}
|
||||
if (envs)
|
||||
CRTDLL_free(envs);
|
||||
|
||||
WARN(":No argv[0] passed - process will not be executed");
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _spawnvp (CRTDLL.275)
|
||||
*
|
||||
* Spawn a process.
|
||||
*/
|
||||
HANDLE __cdecl CRTDLL__spawnvp(INT flags, LPCSTR name, LPCSTR *argv)
|
||||
{
|
||||
return CRTDLL__spawnvpe(flags, name, argv, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* _spawnvpe (CRTDLL.276)
|
||||
*
|
||||
* Spawn a process.
|
||||
*/
|
||||
HANDLE __cdecl CRTDLL__spawnvpe(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
|
||||
{
|
||||
char fullname[MAX_PATH];
|
||||
|
||||
CRTDLL__searchenv(name, "PATH", fullname);
|
||||
return CRTDLL__spawnve(flags, fullname[0] ? fullname : name, argv, envv);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* system (CRTDLL.485)
|
||||
*
|
||||
* Spawn an O/S process.
|
||||
*/
|
||||
INT __cdecl CRTDLL_system(LPSTR x)
|
||||
INT __cdecl CRTDLL_system(LPCSTR cmd)
|
||||
{
|
||||
/* FIXME: should probably launch cmd interpreter in COMSPEC */
|
||||
return __CRTDLL__spawn(_P_WAIT, NULL, x, NULL);
|
||||
return __CRTDLL__spawn(_P_WAIT, cmd, NULL, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue