mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 13:13:00 +00:00
Sync with trunk r63343.
svn path=/branches/shell-experiments/; revision=63351
This commit is contained in:
commit
6600002283
423 changed files with 9605 additions and 124087 deletions
|
@ -156,6 +156,13 @@ static int tmpnam_unique;
|
|||
* protection, rather than locking the whole table for every change.
|
||||
*/
|
||||
static CRITICAL_SECTION file_cs;
|
||||
static CRITICAL_SECTION_DEBUG file_cs_debug =
|
||||
{
|
||||
0, 0, &file_cs,
|
||||
{ &file_cs_debug.ProcessLocksList, &file_cs_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": file_cs") }
|
||||
};
|
||||
static CRITICAL_SECTION file_cs = { &file_cs_debug, -1, 0, 0, 0, 0 };
|
||||
#define LOCK_FILES() do { EnterCriticalSection(&file_cs); } while (0)
|
||||
#define UNLOCK_FILES() do { LeaveCriticalSection(&file_cs); } while (0)
|
||||
|
||||
|
@ -429,8 +436,6 @@ void msvcrt_init_io(void)
|
|||
unsigned int i;
|
||||
ioinfo *fdinfo;
|
||||
|
||||
InitializeCriticalSection(&file_cs);
|
||||
file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_cs");
|
||||
GetStartupInfoA(&si);
|
||||
if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
|
||||
{
|
||||
|
@ -456,53 +461,36 @@ void msvcrt_init_io(void)
|
|||
if (get_ioinfo(fdstart)->handle == INVALID_HANDLE_VALUE) break;
|
||||
}
|
||||
|
||||
if(!__pioinfo[0])
|
||||
set_fd(INVALID_HANDLE_VALUE, 0, 3);
|
||||
fdinfo = get_ioinfo(STDIN_FILENO);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
|
||||
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
|
||||
DWORD type = GetFileType(h);
|
||||
|
||||
fdinfo = get_ioinfo(0);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HANDLE std = GetStdHandle(STD_INPUT_HANDLE);
|
||||
#ifndef __REACTOS__
|
||||
if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
|
||||
GetCurrentProcess(), &fdinfo->handle,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
#else
|
||||
fdinfo->handle = std;
|
||||
#endif
|
||||
fdinfo->wxflag = WX_OPEN | WX_TEXT;
|
||||
set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
|
||||
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDIN_FILENO);
|
||||
}
|
||||
|
||||
fdinfo = get_ioinfo(1);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
#ifndef __REACTOS__
|
||||
if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
|
||||
GetCurrentProcess(), &fdinfo->handle,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
#else
|
||||
fdinfo->handle = std;
|
||||
#endif
|
||||
fdinfo->wxflag = WX_OPEN | WX_TEXT;
|
||||
fdinfo = get_ioinfo(STDOUT_FILENO);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
|
||||
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD type = GetFileType(h);
|
||||
|
||||
set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
|
||||
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDOUT_FILENO);
|
||||
}
|
||||
|
||||
fdinfo = get_ioinfo(2);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
|
||||
#ifndef __REACTOS__
|
||||
if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
|
||||
GetCurrentProcess(), &fdinfo->handle,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
#else
|
||||
fdinfo->handle = std;
|
||||
#endif
|
||||
fdinfo->wxflag = WX_OPEN | WX_TEXT;
|
||||
fdinfo = get_ioinfo(STDERR_FILENO);
|
||||
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
|
||||
HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
|
||||
DWORD type = GetFileType(h);
|
||||
|
||||
set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_NOSEEK : 0)
|
||||
|((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDERR_FILENO);
|
||||
}
|
||||
|
||||
TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(0)->handle,
|
||||
get_ioinfo(1)->handle, get_ioinfo(2)->handle);
|
||||
TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(STDIN_FILENO)->handle,
|
||||
get_ioinfo(STDOUT_FILENO)->handle,
|
||||
get_ioinfo(STDERR_FILENO)->handle);
|
||||
|
||||
memset(_iob,0,3*sizeof(FILE));
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -530,20 +518,39 @@ static int flush_buffer(FILE* file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* INTERNAL: Allocate stdio file buffer */
|
||||
/*static*/ void alloc_buffer(FILE* file)
|
||||
/*********************************************************************
|
||||
* _isatty (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _isatty(int fd)
|
||||
{
|
||||
file->_base = calloc(BUFSIZ,1);
|
||||
if(file->_base) {
|
||||
file->_bufsiz = BUFSIZ;
|
||||
file->_flag |= _IOMYBUF;
|
||||
} else {
|
||||
file->_base = (char*)(&file->_charbuf);
|
||||
/* put here 2 ??? */
|
||||
file->_bufsiz = sizeof(file->_charbuf);
|
||||
}
|
||||
file->_ptr = file->_base;
|
||||
file->_cnt = 0;
|
||||
HANDLE hand = fdtoh(fd);
|
||||
|
||||
TRACE(":fd (%d) handle (%p)\n",fd,hand);
|
||||
if (hand == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
|
||||
}
|
||||
|
||||
/* INTERNAL: Allocate stdio file buffer */
|
||||
/*static*/ BOOL alloc_buffer(FILE* file)
|
||||
{
|
||||
if((file->_file==STDOUT_FILENO || file->_file==STDERR_FILENO)
|
||||
&& _isatty(file->_file))
|
||||
return FALSE;
|
||||
|
||||
file->_base = calloc(BUFSIZ,1);
|
||||
if(file->_base) {
|
||||
file->_bufsiz = BUFSIZ;
|
||||
file->_flag |= _IOMYBUF;
|
||||
} else {
|
||||
file->_base = (char*)(&file->_charbuf);
|
||||
/* put here 2 ??? */
|
||||
file->_bufsiz = sizeof(file->_charbuf);
|
||||
}
|
||||
file->_ptr = file->_base;
|
||||
file->_cnt = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
|
||||
|
@ -998,24 +1005,28 @@ int CDECL _fcloseall(void)
|
|||
/* free everything on process exit */
|
||||
void msvcrt_free_io(void)
|
||||
{
|
||||
int i;
|
||||
unsigned int i;
|
||||
int j;
|
||||
|
||||
_flushall();
|
||||
_fcloseall();
|
||||
/* The Win32 _fcloseall() function explicitly doesn't close stdin,
|
||||
* stdout, and stderr (unlike GNU), so we need to fclose() them here
|
||||
* or they won't get flushed.
|
||||
*/
|
||||
fclose(&_iob[0]);
|
||||
fclose(&_iob[1]);
|
||||
fclose(&_iob[2]);
|
||||
|
||||
for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++)
|
||||
free(__pioinfo[i]);
|
||||
|
||||
for(j=0; j<stream_idx; j++)
|
||||
{
|
||||
FILE *file = get_file(j);
|
||||
if(file<_iob || file>=_iob+_IOB_ENTRIES)
|
||||
{
|
||||
((file_crit*)file)->crit.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&((file_crit*)file)->crit);
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<sizeof(fstream)/sizeof(fstream[0]); i++)
|
||||
free(fstream[i]);
|
||||
|
||||
file_cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&file_cs);
|
||||
}
|
||||
|
||||
|
@ -1159,19 +1170,10 @@ int CDECL _fseeki64(FILE* file, __int64 offset, int whence)
|
|||
flush_buffer(file);
|
||||
|
||||
if(whence == SEEK_CUR && file->_flag & _IOREAD ) {
|
||||
offset -= file->_cnt;
|
||||
if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
|
||||
/* Black magic correction for CR removal */
|
||||
int i;
|
||||
for (i=0; i<file->_cnt; i++) {
|
||||
if (file->_ptr[i] == '\n')
|
||||
offset--;
|
||||
}
|
||||
/* Black magic when reading CR at buffer boundary*/
|
||||
if(get_ioinfo(file->_file)->wxflag & WX_READCR)
|
||||
offset--;
|
||||
}
|
||||
whence = SEEK_SET;
|
||||
offset += _ftelli64(file);
|
||||
}
|
||||
|
||||
/* Discard buffered input */
|
||||
file->_cnt = 0;
|
||||
file->_ptr = file->_base;
|
||||
|
@ -1196,15 +1198,17 @@ int CDECL fseek(FILE* file, long offset, int whence)
|
|||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _chsize (MSVCRT.@)
|
||||
* _chsize_s (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _chsize(int fd, long size)
|
||||
int CDECL _chsize_s(int fd, __int64 size)
|
||||
{
|
||||
LONG cur, pos;
|
||||
__int64 cur, pos;
|
||||
HANDLE handle;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(fd=%d, size=%d)\n", fd, size);
|
||||
TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size));
|
||||
|
||||
if (!MSVCRT_CHECK_PMT(size >= 0)) return EINVAL;
|
||||
|
||||
LOCK_FILES();
|
||||
|
||||
|
@ -1212,10 +1216,10 @@ int CDECL _chsize(int fd, long size)
|
|||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* save the current file pointer */
|
||||
cur = _lseek(fd, 0, SEEK_CUR);
|
||||
cur = _lseeki64(fd, 0, SEEK_CUR);
|
||||
if (cur >= 0)
|
||||
{
|
||||
pos = _lseek(fd, size, SEEK_SET);
|
||||
pos = _lseeki64(fd, size, SEEK_SET);
|
||||
if (pos >= 0)
|
||||
{
|
||||
ret = SetEndOfFile(handle);
|
||||
|
@ -1223,12 +1227,21 @@ int CDECL _chsize(int fd, long size)
|
|||
}
|
||||
|
||||
/* restore the file pointer */
|
||||
_lseek(fd, cur, SEEK_SET);
|
||||
_lseeki64(fd, cur, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_FILES();
|
||||
return ret ? 0 : -1;
|
||||
return ret ? 0 : *_errno();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _chsize (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _chsize(int fd, long size)
|
||||
{
|
||||
/* _chsize_s returns errno on failure but _chsize should return -1 */
|
||||
return _chsize_s( fd, size ) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -1470,20 +1483,6 @@ intptr_t CDECL _get_osfhandle(int fd)
|
|||
return (intptr_t)hand;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _isatty (MSVCRT.@)
|
||||
*/
|
||||
int CDECL _isatty(int fd)
|
||||
{
|
||||
HANDLE hand = fdtoh(fd);
|
||||
|
||||
TRACE(":fd (%d) handle (%p)\n",fd,hand);
|
||||
if (hand == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* _mktemp (MSVCRT.@)
|
||||
*/
|
||||
|
@ -1562,6 +1561,9 @@ wchar_t * CDECL _wmktemp(wchar_t *pattern)
|
|||
if (oflags & _O_APPEND) wxflags |= WX_APPEND;
|
||||
if (oflags & _O_BINARY) {/* Nothing to do */}
|
||||
else if (oflags & _O_TEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_WTEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_U16TEXT) wxflags |= WX_TEXT;
|
||||
else if (oflags & _O_U8TEXT) wxflags |= WX_TEXT;
|
||||
else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */}
|
||||
else wxflags |= WX_TEXT; /* default to TEXT*/
|
||||
if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT;
|
||||
|
@ -1571,7 +1573,8 @@ wchar_t * CDECL _wmktemp(wchar_t *pattern)
|
|||
_O_TRUNC|_O_EXCL|_O_CREAT|
|
||||
_O_RDWR|_O_WRONLY|_O_TEMPORARY|
|
||||
_O_NOINHERIT|
|
||||
_O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED
|
||||
_O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED|
|
||||
_O_WTEXT|_O_U16TEXT|_O_U8TEXT
|
||||
)))
|
||||
ERR(":unsupported oflags 0x%04x\n",unsupp);
|
||||
|
||||
|
@ -1821,11 +1824,11 @@ int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
|
|||
|
||||
if (oflags & _O_CREAT)
|
||||
{
|
||||
va_list ap;
|
||||
__ms_va_list ap;
|
||||
|
||||
va_start(ap, shflags);
|
||||
__ms_va_start(ap, shflags);
|
||||
pmode = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
__ms_va_end(ap);
|
||||
}
|
||||
else
|
||||
pmode = 0;
|
||||
|
@ -1839,94 +1842,15 @@ int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
|
|||
*/
|
||||
int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
|
||||
{
|
||||
DWORD access = 0, creation = 0, attrib;
|
||||
DWORD sharing;
|
||||
int wxflag;
|
||||
HANDLE hand;
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
wchar_t *pathW;
|
||||
int ret;
|
||||
|
||||
TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
|
||||
fd, path, oflags, shflags, pmode);
|
||||
if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path))))
|
||||
return EINVAL;
|
||||
|
||||
if (!fd)
|
||||
{
|
||||
MSVCRT_INVALID_PMT("null out fd pointer", EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*fd = -1;
|
||||
wxflag = split_oflags(oflags);
|
||||
switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
|
||||
{
|
||||
case _O_RDONLY: access |= GENERIC_READ; break;
|
||||
case _O_WRONLY: access |= GENERIC_WRITE; break;
|
||||
case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
|
||||
}
|
||||
|
||||
if (oflags & _O_CREAT)
|
||||
{
|
||||
if(pmode & ~(_S_IREAD | _S_IWRITE))
|
||||
FIXME(": pmode 0x%04x ignored\n", pmode);
|
||||
else
|
||||
WARN(": pmode 0x%04x ignored\n", pmode);
|
||||
|
||||
if (oflags & _O_EXCL)
|
||||
creation = CREATE_NEW;
|
||||
else if (oflags & _O_TRUNC)
|
||||
creation = CREATE_ALWAYS;
|
||||
else
|
||||
creation = OPEN_ALWAYS;
|
||||
}
|
||||
else /* no _O_CREAT */
|
||||
{
|
||||
if (oflags & _O_TRUNC)
|
||||
creation = TRUNCATE_EXISTING;
|
||||
else
|
||||
creation = OPEN_EXISTING;
|
||||
}
|
||||
|
||||
switch( shflags )
|
||||
{
|
||||
case _SH_DENYRW:
|
||||
sharing = 0L;
|
||||
break;
|
||||
case _SH_DENYWR:
|
||||
sharing = FILE_SHARE_READ;
|
||||
break;
|
||||
case _SH_DENYRD:
|
||||
sharing = FILE_SHARE_WRITE;
|
||||
break;
|
||||
case _SH_DENYNO:
|
||||
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
break;
|
||||
default:
|
||||
ERR( "Unhandled shflags 0x%x\n", shflags );
|
||||
return EINVAL;
|
||||
}
|
||||
attrib = FILE_ATTRIBUTE_NORMAL;
|
||||
|
||||
if (oflags & _O_TEMPORARY)
|
||||
{
|
||||
attrib |= FILE_FLAG_DELETE_ON_CLOSE;
|
||||
access |= DELETE;
|
||||
sharing |= FILE_SHARE_DELETE;
|
||||
}
|
||||
|
||||
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
sa.bInheritHandle = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
|
||||
|
||||
hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
|
||||
if (hand == INVALID_HANDLE_VALUE) {
|
||||
WARN(":failed-last error (%d)\n", GetLastError());
|
||||
_dosmaperr(GetLastError());
|
||||
return *_errno();
|
||||
}
|
||||
|
||||
*fd = alloc_fd(hand, wxflag);
|
||||
|
||||
TRACE(":fd (%d) handle (%p)\n", *fd, hand);
|
||||
return 0;
|
||||
ret = _wsopen_s(fd, pathW, oflags, shflags, pmode);
|
||||
free(pathW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -2070,6 +1994,190 @@ int CDECL _rmtmp(void)
|
|||
return num_removed;
|
||||
}
|
||||
|
||||
static inline int get_utf8_char_len(char ch)
|
||||
{
|
||||
if((ch&0xf8) == 0xf0)
|
||||
return 4;
|
||||
else if((ch&0xf0) == 0xe0)
|
||||
return 3;
|
||||
else if((ch&0xe0) == 0xc0)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* (internal) read_utf8
|
||||
*/
|
||||
static int read_utf8(int fd, wchar_t *buf, unsigned int count)
|
||||
{
|
||||
ioinfo *fdinfo = get_ioinfo(fd);
|
||||
HANDLE hand = fdinfo->handle;
|
||||
char min_buf[4], *readbuf, lookahead;
|
||||
DWORD readbuf_size, pos=0, num_read=1, char_len, i, j;
|
||||
|
||||
/* make the buffer big enough to hold at least one character */
|
||||
/* read bytes have to fit to output and lookahead buffers */
|
||||
count /= 2;
|
||||
readbuf_size = count < 4 ? 4 : count;
|
||||
if(readbuf_size<=4 || !(readbuf = malloc(readbuf_size))) {
|
||||
readbuf_size = 4;
|
||||
readbuf = min_buf;
|
||||
}
|
||||
|
||||
if(fdinfo->lookahead[0] != '\n') {
|
||||
readbuf[pos++] = fdinfo->lookahead[0];
|
||||
fdinfo->lookahead[0] = '\n';
|
||||
|
||||
if(fdinfo->lookahead[1] != '\n') {
|
||||
readbuf[pos++] = fdinfo->lookahead[1];
|
||||
fdinfo->lookahead[1] = '\n';
|
||||
|
||||
if(fdinfo->lookahead[2] != '\n') {
|
||||
readbuf[pos++] = fdinfo->lookahead[2];
|
||||
fdinfo->lookahead[2] = '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: this case is broken in native dll, reading
|
||||
* sometimes fails when small buffer is passed
|
||||
*/
|
||||
if(count < 4) {
|
||||
if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
return 0;
|
||||
}else {
|
||||
_dosmaperr(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}else if(!num_read) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
return 0;
|
||||
}else {
|
||||
pos++;
|
||||
}
|
||||
|
||||
char_len = get_utf8_char_len(readbuf[0]);
|
||||
if(char_len>pos) {
|
||||
if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL))
|
||||
pos += num_read;
|
||||
}
|
||||
|
||||
if(readbuf[0] == '\n')
|
||||
fdinfo->wxflag |= WX_READNL;
|
||||
else
|
||||
fdinfo->wxflag &= ~WX_READNL;
|
||||
|
||||
if(readbuf[0] == 0x1a) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(readbuf[0] == '\r') {
|
||||
if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1)
|
||||
buf[0] = '\r';
|
||||
else if(lookahead == '\n')
|
||||
buf[0] = '\n';
|
||||
else {
|
||||
buf[0] = '\r';
|
||||
if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
|
||||
fdinfo->lookahead[0] = lookahead;
|
||||
else
|
||||
SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
|
||||
_dosmaperr(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return num_read*2;
|
||||
}
|
||||
|
||||
if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) {
|
||||
if(pos) {
|
||||
num_read = 0;
|
||||
}else if(GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
if (readbuf != min_buf) free(readbuf);
|
||||
return 0;
|
||||
}else {
|
||||
_dosmaperr(GetLastError());
|
||||
if (readbuf != min_buf) free(readbuf);
|
||||
return -1;
|
||||
}
|
||||
}else if(!pos && !num_read) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
if (readbuf != min_buf) free(readbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos += num_read;
|
||||
if(readbuf[0] == '\n')
|
||||
fdinfo->wxflag |= WX_READNL;
|
||||
else
|
||||
fdinfo->wxflag &= ~WX_READNL;
|
||||
|
||||
/* Find first byte of last character (may be incomplete) */
|
||||
for(i=pos-1; i>0 && i>pos-4; i--)
|
||||
if((readbuf[i]&0xc0) != 0x80)
|
||||
break;
|
||||
char_len = get_utf8_char_len(readbuf[i]);
|
||||
if(char_len+i <= pos)
|
||||
i += char_len;
|
||||
|
||||
if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK)) {
|
||||
if(i < pos)
|
||||
fdinfo->lookahead[0] = readbuf[i];
|
||||
if(i+1 < pos)
|
||||
fdinfo->lookahead[1] = readbuf[i+1];
|
||||
if(i+2 < pos)
|
||||
fdinfo->lookahead[2] = readbuf[i+2];
|
||||
}else if(i < pos) {
|
||||
SetFilePointer(fdinfo->handle, i-pos, NULL, FILE_CURRENT);
|
||||
}
|
||||
pos = i;
|
||||
|
||||
for(i=0, j=0; i<pos; i++) {
|
||||
if(readbuf[i] == 0x1a) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
break;
|
||||
}
|
||||
|
||||
/* strip '\r' if followed by '\n' */
|
||||
if(readbuf[i] == '\r' && i+1==pos) {
|
||||
if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) {
|
||||
readbuf[j++] = '\r';
|
||||
}else if(lookahead == '\n' && j==0) {
|
||||
readbuf[j++] = '\n';
|
||||
}else {
|
||||
if(lookahead != '\n')
|
||||
readbuf[j++] = '\r';
|
||||
|
||||
if(fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
|
||||
fdinfo->lookahead[0] = lookahead;
|
||||
else
|
||||
SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
|
||||
}
|
||||
}else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') {
|
||||
readbuf[j++] = readbuf[i];
|
||||
}
|
||||
}
|
||||
pos = j;
|
||||
|
||||
if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
|
||||
_dosmaperr(GetLastError());
|
||||
if (readbuf != min_buf) free(readbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (readbuf != min_buf) free(readbuf);
|
||||
return num_read*2;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* (internal) read_i
|
||||
*
|
||||
|
@ -2079,69 +2187,139 @@ int CDECL _rmtmp(void)
|
|||
*/
|
||||
static int read_i(int fd, void *buf, unsigned int count)
|
||||
{
|
||||
DWORD num_read;
|
||||
char *bufstart = buf;
|
||||
HANDLE hand = fdtoh(fd);
|
||||
ioinfo *fdinfo = get_ioinfo(fd);
|
||||
DWORD num_read, utf16;
|
||||
char *bufstart = buf;
|
||||
HANDLE hand = fdtoh(fd);
|
||||
ioinfo *fdinfo = get_ioinfo(fd);
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (fdinfo->wxflag & WX_READEOF) {
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
TRACE("already at EOF, returning 0\n");
|
||||
return 0;
|
||||
}
|
||||
/* Don't trace small reads, it gets *very* annoying */
|
||||
if (count > 4)
|
||||
TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
|
||||
if (hand == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
|
||||
/* Reading single bytes in O_TEXT mode makes things slow
|
||||
* So read big chunks
|
||||
*/
|
||||
if (ReadFile(hand, bufstart, count, &num_read, NULL))
|
||||
if (fdinfo->wxflag & WX_ATEOF) {
|
||||
TRACE("already at EOF, returning 0\n");
|
||||
return 0;
|
||||
}
|
||||
/* Don't trace small reads, it gets *very* annoying */
|
||||
if (count > 4)
|
||||
TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
|
||||
if (hand == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
*_errno() = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
utf16 = (fdinfo->exflag & EF_UTF16) != 0;
|
||||
if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
|
||||
{
|
||||
*_errno() = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
|
||||
return read_utf8(fd, buf, count);
|
||||
|
||||
if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
|
||||
{
|
||||
if (fdinfo->lookahead[0] != '\n')
|
||||
{
|
||||
bufstart[0] = fdinfo->lookahead[0];
|
||||
fdinfo->lookahead[0] = '\n';
|
||||
|
||||
if (utf16)
|
||||
{
|
||||
bufstart[1] = fdinfo->lookahead[1];
|
||||
fdinfo->lookahead[1] = '\n';
|
||||
}
|
||||
|
||||
if(count>1+utf16 && ReadFile(hand, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
|
||||
num_read += 1+utf16;
|
||||
else
|
||||
num_read = 1+utf16;
|
||||
}
|
||||
|
||||
if(utf16 && (num_read&1))
|
||||
{
|
||||
/* msvcr90 uses uninitialized value from the buffer in this case */
|
||||
/* msvcrt ignores additional data */
|
||||
ERR("got odd number of bytes in UTF16 mode\n");
|
||||
num_read--;
|
||||
}
|
||||
|
||||
if (count != 0 && num_read == 0)
|
||||
{
|
||||
fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
TRACE(":EOF %s\n",debugstr_an(buf,num_read));
|
||||
}
|
||||
else if (fdinfo->wxflag & WX_TEXT)
|
||||
{
|
||||
DWORD i, j;
|
||||
if (bufstart[num_read-1] == '\r')
|
||||
{
|
||||
if(count == 1)
|
||||
{
|
||||
fdinfo->wxflag &= ~WX_READCR;
|
||||
ReadFile(hand, bufstart, 1, &num_read, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
fdinfo->wxflag |= WX_READCR;
|
||||
num_read--;
|
||||
}
|
||||
}
|
||||
else
|
||||
fdinfo->wxflag &= ~WX_READCR;
|
||||
for (i=0, j=0; i<num_read; i++)
|
||||
|
||||
if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
|
||||
fdinfo->wxflag |= WX_READNL;
|
||||
else
|
||||
fdinfo->wxflag &= ~WX_READNL;
|
||||
|
||||
for (i=0, j=0; i<num_read; i+=1+utf16)
|
||||
{
|
||||
/* in text mode, a ctrl-z signals EOF */
|
||||
if (bufstart[i] == 0x1a)
|
||||
if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
|
||||
{
|
||||
fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
|
||||
break;
|
||||
}
|
||||
/* in text mode, strip \r if followed by \n.
|
||||
* BUG: should save state across calls somehow, so CR LF that
|
||||
* straddles buffer boundary gets recognized properly?
|
||||
*/
|
||||
if ((bufstart[i] != '\r')
|
||||
|| ((i+1) < num_read && bufstart[i+1] != '\n'))
|
||||
bufstart[j++] = bufstart[i];
|
||||
|
||||
/* in text mode, strip \r if followed by \n */
|
||||
if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
|
||||
{
|
||||
char lookahead[2];
|
||||
DWORD len;
|
||||
|
||||
lookahead[1] = '\n';
|
||||
if (ReadFile(hand, lookahead, 1+utf16, &len, NULL) && len)
|
||||
{
|
||||
if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
|
||||
{
|
||||
bufstart[j++] = '\n';
|
||||
if(utf16) bufstart[j++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
|
||||
{
|
||||
bufstart[j++] = '\r';
|
||||
if(utf16) bufstart[j++] = 0;
|
||||
}
|
||||
|
||||
if (fdinfo->wxflag & (WX_PIPE | WX_NOSEEK))
|
||||
{
|
||||
if (lookahead[0]=='\n' && (!utf16 || !lookahead[1]))
|
||||
{
|
||||
bufstart[j++] = '\n';
|
||||
if (utf16) bufstart[j++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fdinfo->lookahead[0] = lookahead[0];
|
||||
fdinfo->lookahead[1] = lookahead[1];
|
||||
}
|
||||
}
|
||||
else
|
||||
SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufstart[j++] = '\r';
|
||||
if(utf16) bufstart[j++] = 0;
|
||||
}
|
||||
}
|
||||
else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
|
||||
|| (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
|
||||
{
|
||||
bufstart[j++] = bufstart[i];
|
||||
if(utf16) bufstart[j++] = bufstart[i+1];
|
||||
}
|
||||
}
|
||||
num_read = j;
|
||||
}
|
||||
|
@ -2151,7 +2329,7 @@ static int read_i(int fd, void *buf, unsigned int count)
|
|||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
TRACE(":end-of-pipe\n");
|
||||
fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
|
||||
fdinfo->wxflag |= WX_ATEOF;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -2161,9 +2339,9 @@ static int read_i(int fd, void *buf, unsigned int count)
|
|||
}
|
||||
}
|
||||
|
||||
if (count > 4)
|
||||
TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
|
||||
return num_read;
|
||||
if (count > 4)
|
||||
TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
|
||||
return num_read;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -2630,60 +2808,50 @@ char * CDECL fgets(char *s, int size, FILE* file)
|
|||
|
||||
/*********************************************************************
|
||||
* fgetwc (MSVCRT.@)
|
||||
*
|
||||
* In _O_TEXT mode, multibyte characters are read from the file, dropping
|
||||
* the CR from CR/LF combinations
|
||||
*/
|
||||
wint_t CDECL fgetwc(FILE* file)
|
||||
{
|
||||
int c;
|
||||
wint_t ret;
|
||||
int ch;
|
||||
|
||||
_lock_file(file);
|
||||
if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT))
|
||||
{
|
||||
wchar_t wc;
|
||||
unsigned int i;
|
||||
int j;
|
||||
char *chp, *wcp;
|
||||
wcp = (char *)&wc;
|
||||
for(i=0; i<sizeof(wc); i++)
|
||||
{
|
||||
if (file->_cnt>0)
|
||||
{
|
||||
file->_cnt--;
|
||||
chp = file->_ptr++;
|
||||
wcp[i] = *chp;
|
||||
_lock_file(file);
|
||||
|
||||
if((get_ioinfo(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
|
||||
|| !(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
|
||||
char *p;
|
||||
|
||||
for(p=(char*)&ret; (wint_t*)p<&ret+1; p++) {
|
||||
ch = fgetc(file);
|
||||
if(ch == EOF) {
|
||||
ret = WEOF;
|
||||
break;
|
||||
}
|
||||
*p = (char)ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = _filbuf(file);
|
||||
if(file->_cnt<=0)
|
||||
{
|
||||
file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
|
||||
file->_cnt = 0;
|
||||
}else {
|
||||
char mbs[MB_LEN_MAX];
|
||||
int len = 0;
|
||||
|
||||
_unlock_file(file);
|
||||
return WEOF;
|
||||
}
|
||||
wcp[i] = j;
|
||||
ch = fgetc(file);
|
||||
if(ch != EOF) {
|
||||
mbs[0] = (char)ch;
|
||||
if(isleadbyte((unsigned char)mbs[0])) {
|
||||
ch = fgetc(file);
|
||||
if(ch != EOF) {
|
||||
mbs[1] = (char)ch;
|
||||
len = 2;
|
||||
}
|
||||
}else {
|
||||
len = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_unlock_file(file);
|
||||
return wc;
|
||||
if(!len || mbtowc(&ret, mbs, len)==-1)
|
||||
ret = WEOF;
|
||||
}
|
||||
|
||||
c = fgetc(file);
|
||||
if ((__mb_cur_max > 1) && isleadbyte(c))
|
||||
{
|
||||
FIXME("Treat Multibyte characters\n");
|
||||
}
|
||||
|
||||
_unlock_file(file);
|
||||
if (c == EOF)
|
||||
return WEOF;
|
||||
else
|
||||
return (wint_t)c;
|
||||
_unlock_file(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -2935,11 +3103,9 @@ FILE * CDECL fopen(const char *path, const char *mode)
|
|||
int CDECL fopen_s(FILE** pFile,
|
||||
const char *filename, const char *mode)
|
||||
{
|
||||
if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
|
||||
!MSVCRT_CHECK_PMT(mode != NULL)) {
|
||||
*_errno() = EINVAL;
|
||||
return EINVAL;
|
||||
}
|
||||
if (!MSVCRT_CHECK_PMT(pFile != NULL)) return EINVAL;
|
||||
if (!MSVCRT_CHECK_PMT(filename != NULL)) return EINVAL;
|
||||
if (!MSVCRT_CHECK_PMT(mode != NULL)) return EINVAL;
|
||||
|
||||
*pFile = fopen(filename, mode);
|
||||
|
||||
|
@ -3048,13 +3214,8 @@ size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file)
|
|||
while(rcnt>0)
|
||||
{
|
||||
int i;
|
||||
/* Fill the buffer on small reads.
|
||||
* TODO: Use a better buffering strategy.
|
||||
*/
|
||||
if (!file->_cnt && size*nmemb <= BUFSIZ/2 && !(file->_flag & _IONBF)) {
|
||||
if (file->_bufsiz == 0) {
|
||||
alloc_buffer(file);
|
||||
}
|
||||
if (!file->_cnt && rcnt<BUFSIZ && !(file->_flag & _IONBF)
|
||||
&& (file->_bufsiz != 0 || alloc_buffer(file))) {
|
||||
file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
|
||||
file->_ptr = file->_base;
|
||||
i = ((unsigned int)file->_cnt<rcnt) ? file->_cnt : rcnt;
|
||||
|
@ -3068,8 +3229,12 @@ size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file)
|
|||
file->_cnt -= i;
|
||||
file->_ptr += i;
|
||||
}
|
||||
} else if (rcnt > UINT_MAX) {
|
||||
i = _read(file->_file, ptr, UINT_MAX);
|
||||
} else if (rcnt < BUFSIZ) {
|
||||
i = _read(file->_file, ptr, rcnt);
|
||||
} else {
|
||||
i = _read(file->_file,ptr, rcnt);
|
||||
i = _read(file->_file, ptr, rcnt - BUFSIZ/2);
|
||||
}
|
||||
pread += i;
|
||||
rcnt -= i;
|
||||
|
@ -3636,13 +3801,19 @@ int CDECL ungetc(int c, FILE * file)
|
|||
return EOF;
|
||||
|
||||
_lock_file(file);
|
||||
if(file->_bufsiz == 0) {
|
||||
alloc_buffer(file);
|
||||
if(file->_bufsiz == 0 && alloc_buffer(file))
|
||||
file->_ptr++;
|
||||
}
|
||||
if(file->_ptr>file->_base) {
|
||||
file->_ptr--;
|
||||
*file->_ptr=c;
|
||||
if(file->_flag & _IOSTRG) {
|
||||
if(*file->_ptr != c) {
|
||||
file->_ptr++;
|
||||
_unlock_file(file);
|
||||
return EOF;
|
||||
}
|
||||
}else {
|
||||
*file->_ptr = c;
|
||||
}
|
||||
file->_cnt++;
|
||||
clearerr(file);
|
||||
_unlock_file(file);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue