#include <precomp.h>
#include "wine/unicode.h"
+#include "internal/wine/msvcrt.h"
#include <sys/utime.h>
#include <direct.h>
/* values for exflag - it's used differently in msvcr90.dll*/
#define EF_UTF8 0x01
#define EF_UTF16 0x02
+#define EF_CRIT_INIT 0x04
#define EF_UNK_UNICODE 0x08
static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
#define MSVCRT_INTERNAL_BUFSIZ 4096
-/* ioinfo structure size is different in msvcrXX.dll's */
-typedef struct {
- HANDLE handle;
- unsigned char wxflag;
- char lookahead[3];
- int exflag;
- CRITICAL_SECTION crit;
-} ioinfo;
-
/*********************************************************************
* __pioinfo (MSVCRT.@)
* array of pointers to ioinfo arrays [32]
return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
}
-static inline ioinfo* get_ioinfo(int fd)
+/*static*/ inline ioinfo* get_ioinfo(int fd)
{
- ioinfo *ret = NULL;
- if(fd < MSVCRT_MAX_FILES)
- ret = __pioinfo[fd/MSVCRT_FD_BLOCK_SIZE];
- if(!ret)
+ ioinfo *ret = get_ioinfo_nolock(fd);
+ if(ret == &__badioinfo)
+ return ret;
+ if(!(ret->exflag & EF_CRIT_INIT)) {
+ LOCK_FILES();
+ if(!(ret->exflag & EF_CRIT_INIT)) {
+ InitializeCriticalSection(&ret->crit);
+ ret->exflag |= EF_CRIT_INIT;
+ }
+ UNLOCK_FILES();
+ }
+ EnterCriticalSection(&ret->crit);
+ return ret;
+}
+
+static inline BOOL alloc_pioinfo_block(int fd)
+{
+ ioinfo *block;
+ int i;
+
+ if(fd<0 || fd>=MSVCRT_MAX_FILES)
+ {
+ *_errno() = ENFILE;
+ return FALSE;
+ }
+
+ block = calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo));
+ if(!block)
+ {
+ WARN(":out of memory!\n");
+ *_errno() = ENOMEM;
+ return FALSE;
+ }
+ for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
+ block[i].handle = INVALID_HANDLE_VALUE;
+ if(InterlockedCompareExchangePointer((void**)&__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE], block, NULL))
+ free(block);
+ return TRUE;
+}
+
+static inline ioinfo* get_ioinfo_alloc_fd(int fd)
+{
+ ioinfo *ret, *info;
+
+ ret = get_ioinfo(fd);
+ if(ret != &__badioinfo)
+ {
+ LOCK_FILES();
+ /* locate next free slot */
+ if (fd == fdstart && fd == fdend)
+ fdstart = fdend + 1;
+ else if (fd == fdstart)
+ {
+ fdstart++;
+ while (fdstart < fdend &&
+ ((info = get_ioinfo_nolock(fdstart))->exflag & EF_CRIT_INIT))
+ {
+ if (TryEnterCriticalSection(&info->crit))
+ {
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ LeaveCriticalSection(&info->crit);
+ break;
+ }
+ LeaveCriticalSection(&info->crit);
+ }
+ fdstart++;
+ }
+ }
+ /* update last fd in use */
+ if (fd >= fdend)
+ fdend = fd + 1;
+ TRACE("fdstart is %d, fdend is %d\n", fdstart, fdend);
+ UNLOCK_FILES();
+ return ret;
+ }
+
+ if(!alloc_pioinfo_block(fd))
return &__badioinfo;
- return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
+ ret = get_ioinfo(fd);
+ if(ret == &__badioinfo)
+ return ret;
+
+ LOCK_FILES();
+ /* locate next free slot */
+ if (fd == fdstart && fd == fdend)
+ fdstart = fdend + 1;
+ else if (fd == fdstart)
+ {
+ fdstart++;
+ while (fdstart < fdend &&
+ ((info = get_ioinfo_nolock(fdstart))->exflag & EF_CRIT_INIT))
+ {
+ if (TryEnterCriticalSection(&info->crit))
+ {
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ LeaveCriticalSection(&info->crit);
+ break;
+ }
+ LeaveCriticalSection(&info->crit);
+ }
+ fdstart++;
+ }
+ }
+ /* update last fd in use */
+ if (fd >= fdend)
+ fdend = fd + 1;
+ TRACE("fdstart is %d, fdend is %d\n", fdstart, fdend);
+ UNLOCK_FILES();
+
+ return ret;
+}
+
+/*static*/ inline void release_ioinfo(ioinfo *info)
+{
+ if(info!=&__badioinfo && info->exflag & EF_CRIT_INIT)
+ LeaveCriticalSection(&info->crit);
}
static inline FILE* msvcrt_get_file(int i)
return &ret->file;
}
-static inline BOOL is_valid_fd(int fd)
-{
- return fd >= 0 && fd < fdend && (get_ioinfo(fd)->wxflag & WX_OPEN);
-}
-
-/* INTERNAL: Get the HANDLE for a fd
- * This doesn't lock the table, because a failure will result in
- * INVALID_HANDLE_VALUE being returned, which should be handled correctly. If
- * it returns a valid handle which is about to be closed, a subsequent call
- * will fail, most likely in a sane way.
- */
-/*static*/ HANDLE fdtoh(int fd)
-{
- if (!is_valid_fd(fd))
- {
- WARN(":fd (%d) - no handle!\n",fd);
- *__doserrno() = 0;
- *_errno() = EBADF;
- return INVALID_HANDLE_VALUE;
- }
- //if (get_ioinfo(fd)->handle == INVALID_HANDLE_VALUE)
- //FIXME("returning INVALID_HANDLE_VALUE for %d\n", fd);
- return get_ioinfo(fd)->handle;
-}
-
/* INTERNAL: free a file entry fd */
static void msvcrt_free_fd(int fd)
{
- ioinfo *fdinfo;
+ ioinfo *fdinfo = get_ioinfo(fd);
- LOCK_FILES();
- fdinfo = get_ioinfo(fd);
if(fdinfo != &__badioinfo)
{
fdinfo->handle = INVALID_HANDLE_VALUE;
break;
}
}
+ release_ioinfo(fdinfo);
+ LOCK_FILES();
if (fd == fdend - 1)
fdend--;
if (fd < fdstart)
UNLOCK_FILES();
}
-/* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
-/* caller must hold the files lock */
-static int msvcrt_set_fd(HANDLE hand, int flag, int fd)
+static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
{
- ioinfo *fdinfo;
-
- if (fd >= MSVCRT_MAX_FILES)
- {
- WARN(":files exhausted!\n");
- *_errno() = ENFILE;
- return -1;
- }
-
- fdinfo = get_ioinfo(fd);
- if(fdinfo == &__badioinfo) {
- int i;
-
- __pioinfo[fd/MSVCRT_FD_BLOCK_SIZE] = calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo));
- if(!__pioinfo[fd/MSVCRT_FD_BLOCK_SIZE]) {
- WARN(":out of memory!\n");
- *_errno() = ENOMEM;
- return -1;
- }
-
- for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
- __pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][i].handle = INVALID_HANDLE_VALUE;
-
- fdinfo = get_ioinfo(fd);
- }
-
fdinfo->handle = hand;
fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_TTY));
fdinfo->lookahead[0] = '\n';
fdinfo->lookahead[1] = '\n';
fdinfo->lookahead[2] = '\n';
- fdinfo->exflag = 0;
-
- /* locate next free slot */
- if (fd == fdstart && fd == fdend)
- fdstart = fdend + 1;
- else
- while (fdstart < fdend &&
- get_ioinfo(fdstart)->handle != INVALID_HANDLE_VALUE)
- fdstart++;
- /* update last fd in use */
- if (fd >= fdend)
- fdend = fd + 1;
- TRACE("fdstart is %d, fdend is %d\n", fdstart, fdend);
+ fdinfo->exflag &= EF_CRIT_INIT;
- switch (fd)
+ switch (fdinfo-__pioinfo[0])
{
case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break;
case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break;
}
-
- return fd;
}
/* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
/*static*/ int msvcrt_alloc_fd(HANDLE hand, int flag)
{
- int ret;
+ ioinfo *info;
+ int fd;
- LOCK_FILES();
- TRACE(":handle (%p) allocating fd (%d)\n",hand,fdstart);
- ret = msvcrt_set_fd(hand, flag, fdstart);
- UNLOCK_FILES();
- return ret;
+ LOCK_FILES();
+ fd = fdstart;
+ TRACE(":handle (%p) allocating fd (%d)\n", hand, fd);
+
+ if (fd >= MSVCRT_MAX_FILES)
+ {
+ UNLOCK_FILES();
+ WARN(":files exhausted!\n");
+ *_errno() = ENFILE;
+ return -1;
+ }
+
+ info = get_ioinfo_alloc_fd(fd);
+ UNLOCK_FILES();
+ if(info == &__badioinfo)
+ return -1;
+
+ msvcrt_set_fd(info, hand, flag);
+ release_ioinfo(info);
+ return fd;
}
/* INTERNAL: Allocate a FILE* for an fd slot */
static int msvcrt_init_fp(FILE* file, int fd, unsigned stream_flags)
{
TRACE(":fd (%d) allocating FILE*\n",fd);
- if (!is_valid_fd(fd))
+ if (!(get_ioinfo_nolock(fd)->wxflag & WX_OPEN))
{
WARN(":invalid fd %d\n",fd);
*__doserrno() = 0;
*/
unsigned create_io_inherit_block(WORD *size, BYTE **block)
{
- int fd;
+ int fd, last_fd;
char* wxflag_ptr;
HANDLE* handle_ptr;
ioinfo* fdinfo;
- *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * fdend;
+ for (last_fd=MSVCRT_MAX_FILES-1; last_fd>=0; last_fd--)
+ if (get_ioinfo_nolock(last_fd)->handle != INVALID_HANDLE_VALUE)
+ break;
+ last_fd++;
+
+ *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * last_fd;
*block = calloc(1, *size);
if (!*block)
{
return FALSE;
}
wxflag_ptr = (char*)*block + sizeof(unsigned);
- handle_ptr = (HANDLE*)(wxflag_ptr + fdend * sizeof(char));
+ handle_ptr = (HANDLE*)(wxflag_ptr + last_fd);
- *(unsigned*)*block = fdend;
- for (fd = 0; fd < fdend; fd++)
+ *(unsigned*)*block = last_fd;
+ for (fd = 0; fd < last_fd; fd++)
{
/* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
fdinfo = get_ioinfo(fd);
*wxflag_ptr = 0;
*handle_ptr = INVALID_HANDLE_VALUE;
}
+ release_ioinfo(fdinfo);
wxflag_ptr++; handle_ptr++;
}
return TRUE;
for (i = 0; i < count; i++)
{
if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
- msvcrt_set_fd(*handle_ptr, *wxflag_ptr, i);
+ {
+ fdinfo = get_ioinfo_alloc_fd(i);
+ if(fdinfo != &__badioinfo)
+ msvcrt_set_fd(fdinfo, *handle_ptr, *wxflag_ptr);
+ release_ioinfo(fdinfo);
+ }
wxflag_ptr++; handle_ptr++;
}
fdend = max( 3, count );
for (fdstart = 3; fdstart < fdend; fdstart++)
- if (get_ioinfo(fdstart)->handle == INVALID_HANDLE_VALUE) break;
+ if (get_ioinfo_nolock(fdstart)->handle == INVALID_HANDLE_VALUE) break;
}
- fdinfo = get_ioinfo(STDIN_FILENO);
+ fdinfo = get_ioinfo_alloc_fd(STDIN_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD type = GetFileType(h);
- msvcrt_set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
- |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDIN_FILENO);
+ msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
}
+ release_ioinfo(fdinfo);
- fdinfo = get_ioinfo(STDOUT_FILENO);
+ fdinfo = get_ioinfo_alloc_fd(STDOUT_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD type = GetFileType(h);
- msvcrt_set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
- |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDOUT_FILENO);
+ msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
}
+ release_ioinfo(fdinfo);
- fdinfo = get_ioinfo(STDERR_FILENO);
+ fdinfo = get_ioinfo_alloc_fd(STDERR_FILENO);
if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
DWORD type = GetFileType(h);
- msvcrt_set_fd(h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
- |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0), STDERR_FILENO);
+ msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
+ |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
}
+ release_ioinfo(fdinfo);
- TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(STDIN_FILENO)->handle,
- get_ioinfo(STDOUT_FILENO)->handle,
- get_ioinfo(STDERR_FILENO)->handle);
+ TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo_nolock(STDIN_FILENO)->handle,
+ get_ioinfo_nolock(STDOUT_FILENO)->handle,
+ get_ioinfo_nolock(STDERR_FILENO)->handle);
memset(_iob,0,3*sizeof(FILE));
for (i = 0; i < 3; i++)
*/
int CDECL _commit(int fd)
{
- HANDLE hand = fdtoh(fd);
-
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
- return -1;
+ ioinfo *info = get_ioinfo(fd);
+ int ret;
- if (!FlushFileBuffers(hand))
- {
- if (GetLastError() == ERROR_INVALID_HANDLE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (info->handle == INVALID_HANDLE_VALUE)
+ ret = -1;
+ else if (!FlushFileBuffers(info->handle))
{
- /* FlushFileBuffers fails for console handles
- * so we ignore this error.
- */
- return 0;
+ if (GetLastError() == ERROR_INVALID_HANDLE)
+ {
+ /* FlushFileBuffers fails for console handles
+ * so we ignore this error.
+ */
+ ret = 0;
+ }
+ else
+ {
+ TRACE(":failed-last error (%d)\n",GetLastError());
+ _dosmaperr(GetLastError());
+ ret = -1;
+ }
}
- TRACE(":failed-last error (%d)\n",GetLastError());
- _dosmaperr(GetLastError());
- return -1;
- }
- TRACE(":ok\n");
- return 0;
+ else
+ {
+ TRACE(":ok\n");
+ ret = 0;
+ }
+
+ release_ioinfo(info);
+ return ret;
}
/* _flushall calls fflush which calls _flushall */
_unlock_file(file);
return 0;
- }
+ }
return 0;
}
*/
int CDECL _close(int fd)
{
- HANDLE hand;
+ ioinfo *info = get_ioinfo(fd);
int ret;
LOCK_FILES();
- hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
- ret = -1;
- else if (!CloseHandle(hand))
- {
- WARN(":failed-last error (%d)\n",GetLastError());
- _dosmaperr(GetLastError());
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (!(info->wxflag & WX_OPEN)) {
ret = -1;
- }
- else
- {
+ } else {
+ ret = CloseHandle(info->handle) ? 0 : -1;
msvcrt_free_fd(fd);
- ret = 0;
+ if (ret) {
+ WARN(":failed-last error (%d)\n",GetLastError());
+ _dosmaperr(GetLastError());
+ ret = -1;
+ }
}
UNLOCK_FILES();
- TRACE(":ok\n");
+ release_ioinfo(info);
return ret;
}
*/
int CDECL _dup2(int od, int nd)
{
+ ioinfo *info_od, *info_nd;
int ret;
TRACE("(od=%d, nd=%d)\n", od, nd);
LOCK_FILES();
- if (nd < MSVCRT_MAX_FILES && nd >= 0 && is_valid_fd(od))
+
+ if (od < nd)
+ {
+ info_od = get_ioinfo(od);
+ info_nd = get_ioinfo_alloc_fd(nd);
+ }
+ else
+ {
+ info_nd = get_ioinfo_alloc_fd(nd);
+ info_od = get_ioinfo(od);
+ }
+
+ if (info_nd == &__badioinfo)
+ {
+ ret = -1;
+ }
+ else if (info_od->wxflag & WX_OPEN)
{
HANDLE handle;
- if (DuplicateHandle(GetCurrentProcess(), get_ioinfo(od)->handle,
+ if (DuplicateHandle(GetCurrentProcess(), info_od->handle,
GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
- int wxflag = get_ioinfo(od)->wxflag & ~_O_NOINHERIT;
+ int wxflag = info_od->wxflag & ~_O_NOINHERIT;
- if (is_valid_fd(nd))
+ if (info_nd->wxflag & WX_OPEN)
_close(nd);
- ret = msvcrt_set_fd(handle, wxflag, nd);
- if (ret == -1)
- {
- CloseHandle(handle);
- *_errno() = EMFILE;
- }
- else
- {
- /* _dup2 returns 0, not nd, on success */
- ret = 0;
- }
+
+ msvcrt_set_fd(info_nd, handle, wxflag);
+ /* _dup2 returns 0, not nd, on success */
+ ret = 0;
}
else
{
*_errno() = EBADF;
ret = -1;
}
+
+ release_ioinfo(info_od);
+ release_ioinfo(info_nd);
UNLOCK_FILES();
return ret;
}
*/
int CDECL _eof(int fd)
{
+ ioinfo *info = get_ioinfo(fd);
DWORD curpos,endpos;
LONG hcurpos,hendpos;
- HANDLE hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
- if (hand == INVALID_HANDLE_VALUE)
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
- if (get_ioinfo(fd)->wxflag & WX_ATEOF) return TRUE;
+ if (info->wxflag & WX_ATEOF)
+ {
+ release_ioinfo(info);
+ return TRUE;
+ }
/* Otherwise we do it the hard way */
hcurpos = hendpos = 0;
- curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT);
- endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
+ curpos = SetFilePointer(info->handle, 0, &hcurpos, FILE_CURRENT);
+ endpos = SetFilePointer(info->handle, 0, &hendpos, FILE_END);
if (curpos == endpos && hcurpos == hendpos)
{
/* FIXME: shouldn't WX_ATEOF be set here? */
+ release_ioinfo(info);
return TRUE;
}
- SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
+ SetFilePointer(info->handle, curpos, &hcurpos, FILE_BEGIN);
+ release_ioinfo(info);
return FALSE;
}
_fcloseall();
for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++)
+ {
+ if(!__pioinfo[i])
+ continue;
+
+ for(j=0; j<MSVCRT_FD_BLOCK_SIZE; j++)
+ {
+ if(__pioinfo[i][j].exflag & EF_CRIT_INIT)
+ DeleteCriticalSection(&__pioinfo[i][j].crit);
+ }
free(__pioinfo[i]);
+ }
for(j=0; j<MSVCRT_stream_idx; j++)
{
*/
__int64 CDECL _lseeki64(int fd, __int64 offset, int whence)
{
- HANDLE hand = fdtoh(fd);
+ ioinfo *info = get_ioinfo(fd);
LARGE_INTEGER ofs;
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
if (whence < 0 || whence > 2)
{
+ release_ioinfo(info);
*_errno() = EINVAL;
return -1;
}
/* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
* so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
ofs.QuadPart = offset;
- if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
+ if ((ofs.u.LowPart = SetFilePointer(info->handle, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
GetLastError() == ERROR_SUCCESS)
{
- get_ioinfo(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF);
+ info->wxflag &= ~(WX_ATEOF|WX_READEOF);
/* FIXME: What if we seek _to_ EOF - is EOF set? */
+ release_ioinfo(info);
return ofs.QuadPart;
}
+ release_ioinfo(info);
TRACE(":error-last error (%d)\n",GetLastError());
_dosmaperr(GetLastError());
return -1;
*/
int CDECL _locking(int fd, int mode, LONG nbytes)
{
+ ioinfo *info = get_ioinfo(fd);
BOOL ret;
DWORD cur_locn;
- HANDLE hand = fdtoh(fd);
- TRACE(":fd (%d) handle (%p)\n",fd,hand);
- if (hand == INVALID_HANDLE_VALUE)
+ TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
+ if (info->handle == INVALID_HANDLE_VALUE)
+ {
+ release_ioinfo(info);
return -1;
+ }
if (mode < 0 || mode > 4)
{
+ release_ioinfo(info);
*_errno() = EINVAL;
return -1;
}
(mode==_LK_NBRLCK)?"_LK_NBRLCK":
"UNKNOWN");
- if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
+ if ((cur_locn = SetFilePointer(info->handle, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
{
+ release_ioinfo(info);
FIXME ("Seek failed\n");
*_errno() = EINVAL; /* FIXME */
return -1;
ret = 1; /* just to satisfy gcc */
while (nretry--)
{
- ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
if (ret) break;
Sleep(1);
}
}
else if (mode == _LK_UNLCK)
- ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = UnlockFile(info->handle, cur_locn, 0L, nbytes, 0L);
else
- ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
+ ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
/* FIXME - what about error settings? */
+ release_ioinfo(info);
return ret ? 0 : -1;
}
*/
int CDECL _chsize_s(int fd, __int64 size)
{
+ ioinfo *info;
__int64 cur, pos;
- HANDLE handle;
BOOL ret = FALSE;
TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size));
if (!MSVCRT_CHECK_PMT(size >= 0)) return EINVAL;
- LOCK_FILES();
-
- handle = fdtoh(fd);
- if (handle != INVALID_HANDLE_VALUE)
+ info = get_ioinfo(fd);
+ if (info->handle != INVALID_HANDLE_VALUE)
{
/* save the current file pointer */
cur = _lseeki64(fd, 0, SEEK_CUR);
pos = _lseeki64(fd, size, SEEK_SET);
if (pos >= 0)
{
- ret = SetEndOfFile(handle);
+ ret = SetEndOfFile(info->handle);
if (!ret) _dosmaperr(GetLastError());
}
}
}
- UNLOCK_FILES();
+ release_ioinfo(info);
return ret ? 0 : *_errno();
}
*/
intptr_t CDECL _get_osfhandle(int fd)
{
- HANDLE hand = fdtoh(fd);
+ HANDLE hand = get_ioinfo_nolock(fd)->handle;
TRACE(":fd (%d) handle (%p)\n",fd,hand);
+ if(hand == INVALID_HANDLE_VALUE)
+ *_errno() = EBADF;
return (intptr_t)hand;
}
return *_errno();
if (oflags & _O_WTEXT)
- get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
+ get_ioinfo_nolock(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
else if (oflags & _O_U16TEXT)
- get_ioinfo(*fd)->exflag |= EF_UTF16;
+ get_ioinfo_nolock(*fd)->exflag |= EF_UTF16;
else if (oflags & _O_U8TEXT)
- get_ioinfo(*fd)->exflag |= EF_UTF8;
+ get_ioinfo_nolock(*fd)->exflag |= EF_UTF8;
TRACE(":fd (%d) handle (%p)\n", *fd, hand);
return 0;
/*********************************************************************
* (internal) read_utf8
*/
-static int read_utf8(int fd, wchar_t *buf, unsigned int count)
+static int read_utf8(ioinfo *fdinfo, 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;
* the file pointer on the \r character while getc() goes on to
* the following \n
*/
-static int read_i(int fd, void *buf, unsigned int count)
+static int read_i(int fd, ioinfo *fdinfo, void *buf, unsigned int count)
{
DWORD num_read, utf16;
char *bufstart = buf;
- HANDLE hand = fdtoh(fd);
- ioinfo *fdinfo = get_ioinfo(fd);
if (count == 0)
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)
+ TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n", fd, fdinfo->handle, buf, count);
+ if (fdinfo->handle == INVALID_HANDLE_VALUE)
{
*_errno() = EBADF;
return -1;
}
if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
- return read_utf8(fd, buf, count);
+ return read_utf8(fdinfo, buf, count);
- if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
+ if (fdinfo->lookahead[0]!='\n' || ReadFile(fdinfo->handle, bufstart, count, &num_read, NULL))
{
if (fdinfo->lookahead[0] != '\n')
{
fdinfo->lookahead[1] = '\n';
}
- if(count>1+utf16 && ReadFile(hand, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
+ if(count>1+utf16 && ReadFile(fdinfo->handle, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
num_read += 1+utf16;
else
num_read = 1+utf16;
DWORD len;
lookahead[1] = '\n';
- if (ReadFile(hand, lookahead, 1+utf16, &len, NULL) && len)
+ if (ReadFile(fdinfo->handle, lookahead, 1+utf16, &len, NULL) && len)
{
if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
{
*/
int CDECL _read(int fd, void *buf, unsigned int count)
{
- int num_read;
- num_read = read_i(fd, buf, count);
- return num_read;
+ ioinfo *info = get_ioinfo(fd);
+ int num_read = read_i(fd, info, buf, count);
+ release_ioinfo(info);
+ return num_read;
}
/*********************************************************************
*/
int CDECL _setmode(int fd,int mode)
{
- int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
- if(ret==_O_TEXT && (get_ioinfo(fd)->exflag & (EF_UTF8|EF_UTF16)))
+ ioinfo *info = get_ioinfo(fd);
+ int ret = info->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
+ if(ret==_O_TEXT && (info->exflag & (EF_UTF8|EF_UTF16)))
ret = _O_WTEXT;
if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT
&& mode!=_O_U16TEXT && mode!=_O_U8TEXT) {
*_errno() = EINVAL;
+ release_ioinfo(info);
return -1;
}
if(mode == _O_BINARY) {
- get_ioinfo(fd)->wxflag &= ~WX_TEXT;
- get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
+ info->wxflag &= ~WX_TEXT;
+ info->exflag &= ~(EF_UTF8|EF_UTF16);
+ release_ioinfo(info);
return ret;
}
- get_ioinfo(fd)->wxflag |= WX_TEXT;
+ info->wxflag |= WX_TEXT;
if(mode == _O_TEXT)
- get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
+ info->exflag &= ~(EF_UTF8|EF_UTF16);
else if(mode == _O_U8TEXT)
- get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF16) | EF_UTF8;
+ info->exflag = (info->exflag & ~EF_UTF16) | EF_UTF8;
else
- get_ioinfo(fd)->exflag = (get_ioinfo(fd)->exflag & ~EF_UTF8) | EF_UTF16;
+ info->exflag = (info->exflag & ~EF_UTF8) | EF_UTF16;
+ release_ioinfo(info);
return ret;
}
if (hand == INVALID_HANDLE_VALUE)
{
*_errno() = EBADF;
+ release_ioinfo(info);
return -1;
}
if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
{
*_errno() = EINVAL;
+ release_ioinfo(info);
return -1;
}
{
if (WriteFile(hand, buf, count, &num_written, NULL)
&& (num_written == count))
+ {
+ release_ioinfo(info);
return num_written;
+ }
TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
hand, GetLastError());
*_errno() = ENOSPC;
if(!conv_len) {
_dosmaperr(GetLastError());
free(p);
+ release_ioinfo(info);
return -1;
}
if (!WriteFile(hand, q, size, &num_written, NULL))
num_written = -1;
+ release_ioinfo(info);
if(p)
free(p);
if (num_written != size)
return count;
}
+ release_ioinfo(info);
return -1;
}
if(!(file->_flag & (_IOMYBUF | _USERBUF))) {
int r;
- if ((r = read_i(file->_file,&c,1)) != 1) {
+ if ((r = _read(file->_file,&c,1)) != 1) {
file->_flag |= (r == 0) ? _IOEOF : _IOERR;
_unlock_file(file);
return EOF;
_unlock_file(file);
return c;
} else {
- file->_cnt = read_i(file->_file, file->_base, file->_bufsiz);
+ file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
if(file->_cnt<=0) {
file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
file->_cnt = 0;
_lock_file(file);
- if((get_ioinfo(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
- || !(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
+ if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
+ || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
char *p;
for(p=(char*)&ret; (wint_t*)p<&ret+1; p++) {
/* If this is a real file stream (and not some temporary one for
sprintf-like functions), check whether it is opened in text mode.
In this case, we have to perform an implicit conversion to ANSI. */
- if (!(stream->_flag & _IOSTRG) && get_ioinfo(stream->_file)->wxflag & WX_TEXT)
+ if (!(stream->_flag & _IOSTRG) && get_ioinfo_nolock(stream->_file)->wxflag & WX_TEXT)
{
/* Convert to multibyte in text mode */
char mbc[MB_LEN_MAX];
i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
/* If the buffer fill reaches eof but fread wouldn't, clear eof. */
if (i > 0 && i < file->_cnt) {
- get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF;
+ get_ioinfo_nolock(file->_file)->wxflag &= ~WX_ATEOF;
file->_flag &= ~_IOEOF;
}
if (i > 0) {
/* expose feof condition in the flags
* MFC tests file->_flag for feof, and doesn't call feof())
*/
- if (get_ioinfo(file->_file)->wxflag & WX_ATEOF)
+ if (get_ioinfo_nolock(file->_file)->wxflag & WX_ATEOF)
file->_flag |= _IOEOF;
else if (i == -1)
{
if(file->_flag & _IOWRT) {
pos += file->_ptr - file->_base;
- if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
+ if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
char *p;
for(p=file->_base; p<file->_ptr; p++)
int i;
pos -= file->_cnt;
- if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
+ if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
for(i=0; i<file->_cnt; i++)
if(file->_ptr[i] == '\n')
pos--;
pos -= file->_bufsiz;
pos += file->_ptr - file->_base;
- if(get_ioinfo(file->_file)->wxflag & WX_TEXT) {
- if(get_ioinfo(file->_file)->wxflag & WX_READNL)
+ if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
+ if(get_ioinfo_nolock(file->_file)->wxflag & WX_READNL)
pos--;
for(p=file->_base; p<file->_ptr; p++)
int ret;
_lock_file(file);
- if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
+ if (!(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF;
_unlock_file(file);
return ret;
_lock_file(file);
- if((get_ioinfo(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
- || !(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
+ if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
+ || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
unsigned char * pp = (unsigned char *)&mwc;
int i;