ntdll: Move a few file functions to the Unix library.
[wine.git] / dlls / msvcrt / file.c
blob825d442bfa8e6cece6c076f895072ce9c9585382
1 /*
2 * msvcrt.dll file functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 * Copyright 2004 Eric Pouech
9 * Copyright 2004 Juan Lang
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 * TODO
26 * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED
29 #include "config.h"
30 #include "wine/port.h"
32 #define __iob_func mingw___iob_func
33 #include <stdarg.h>
34 #include <stdio.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <sys/types.h>
39 #include <limits.h>
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winternl.h"
44 #include "msvcrt.h"
45 #include "mtdll.h"
47 #include "wine/unicode.h"
49 #include "wine/debug.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
53 /* for stat mode, permissions apply to all,owner and group */
54 #define ALL_S_IREAD (MSVCRT__S_IREAD | (MSVCRT__S_IREAD >> 3) | (MSVCRT__S_IREAD >> 6))
55 #define ALL_S_IWRITE (MSVCRT__S_IWRITE | (MSVCRT__S_IWRITE >> 3) | (MSVCRT__S_IWRITE >> 6))
56 #define ALL_S_IEXEC (MSVCRT__S_IEXEC | (MSVCRT__S_IEXEC >> 3) | (MSVCRT__S_IEXEC >> 6))
58 /* _access() bit flags FIXME: incomplete */
59 #define MSVCRT_W_OK 0x02
60 #define MSVCRT_R_OK 0x04
62 /* values for wxflag in file descriptor */
63 #define WX_OPEN 0x01
64 #define WX_ATEOF 0x02
65 #define WX_READNL 0x04 /* read started with \n */
66 #define WX_PIPE 0x08
67 #define WX_DONTINHERIT 0x10
68 #define WX_APPEND 0x20
69 #define WX_TTY 0x40
70 #define WX_TEXT 0x80
72 /* values for exflag - it's used differently in msvcr90.dll*/
73 #define EF_UTF8 0x01
74 #define EF_UTF16 0x02
75 #define EF_CRIT_INIT 0x04
76 #define EF_UNK_UNICODE 0x08
78 static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
79 static char utf16_bom[2] = { 0xff, 0xfe };
81 /* FIXME: this should be allocated dynamically */
82 #define MSVCRT_MAX_FILES 2048
83 #define MSVCRT_FD_BLOCK_SIZE 32
85 #define MSVCRT_INTERNAL_BUFSIZ 4096
87 /* ioinfo structure size is different in msvcrXX.dll's */
88 typedef struct {
89 HANDLE handle;
90 unsigned char wxflag;
91 char lookahead[3];
92 int exflag;
93 CRITICAL_SECTION crit;
94 #if _MSVCR_VER >= 80
95 char textmode : 7;
96 char unicode : 1;
97 char pipech2[2];
98 __int64 startpos;
99 BOOL utf8translations;
100 #endif
101 #if _MSVCR_VER >= 90
102 char dbcsBuffer;
103 BOOL dbcsBufferUsed;
104 #endif
105 } ioinfo;
107 /*********************************************************************
108 * __pioinfo (MSVCRT.@)
109 * array of pointers to ioinfo arrays [32]
111 ioinfo * MSVCRT___pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 };
113 /*********************************************************************
114 * __badioinfo (MSVCRT.@)
116 ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
118 typedef struct {
119 MSVCRT_FILE file;
120 CRITICAL_SECTION crit;
121 } file_crit;
123 MSVCRT_FILE MSVCRT__iob[_IOB_ENTRIES] = { { 0 } };
124 static file_crit* MSVCRT_fstream[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE];
125 static int MSVCRT_max_streams = 512, MSVCRT_stream_idx;
127 /* INTERNAL: process umask */
128 static int MSVCRT_umask = 0;
130 /* INTERNAL: static data for tmpnam and _wtmpname functions */
131 static int tmpnam_unique;
132 static int tmpnam_s_unique;
134 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
135 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
136 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
137 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
139 #define TOUL(x) (ULONGLONG)(x)
140 static const ULONGLONG WCEXE = TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
141 static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
142 static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
143 static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
145 /* This critical section protects the MSVCRT_fstreams table
146 * and MSVCRT_stream_idx from race conditions. It also
147 * protects fd critical sections creation code.
149 static CRITICAL_SECTION MSVCRT_file_cs;
150 static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug =
152 0, 0, &MSVCRT_file_cs,
153 { &MSVCRT_file_cs_debug.ProcessLocksList, &MSVCRT_file_cs_debug.ProcessLocksList },
154 0, 0, { (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs") }
156 static CRITICAL_SECTION MSVCRT_file_cs = { &MSVCRT_file_cs_debug, -1, 0, 0, 0, 0 };
157 #define LOCK_FILES() do { EnterCriticalSection(&MSVCRT_file_cs); } while (0)
158 #define UNLOCK_FILES() do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0)
160 static void msvcrt_stat64_to_stat(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat *buf)
162 buf->st_dev = buf64->st_dev;
163 buf->st_ino = buf64->st_ino;
164 buf->st_mode = buf64->st_mode;
165 buf->st_nlink = buf64->st_nlink;
166 buf->st_uid = buf64->st_uid;
167 buf->st_gid = buf64->st_gid;
168 buf->st_rdev = buf64->st_rdev;
169 buf->st_size = buf64->st_size;
170 buf->st_atime = buf64->st_atime;
171 buf->st_mtime = buf64->st_mtime;
172 buf->st_ctime = buf64->st_ctime;
175 static void msvcrt_stat64_to_stati64(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stati64 *buf)
177 buf->st_dev = buf64->st_dev;
178 buf->st_ino = buf64->st_ino;
179 buf->st_mode = buf64->st_mode;
180 buf->st_nlink = buf64->st_nlink;
181 buf->st_uid = buf64->st_uid;
182 buf->st_gid = buf64->st_gid;
183 buf->st_rdev = buf64->st_rdev;
184 buf->st_size = buf64->st_size;
185 buf->st_atime = buf64->st_atime;
186 buf->st_mtime = buf64->st_mtime;
187 buf->st_ctime = buf64->st_ctime;
190 static void msvcrt_stat64_to_stat32(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat32 *buf)
192 buf->st_dev = buf64->st_dev;
193 buf->st_ino = buf64->st_ino;
194 buf->st_mode = buf64->st_mode;
195 buf->st_nlink = buf64->st_nlink;
196 buf->st_uid = buf64->st_uid;
197 buf->st_gid = buf64->st_gid;
198 buf->st_rdev = buf64->st_rdev;
199 buf->st_size = buf64->st_size;
200 buf->st_atime = buf64->st_atime;
201 buf->st_mtime = buf64->st_mtime;
202 buf->st_ctime = buf64->st_ctime;
205 static void msvcrt_stat64_to_stat64i32(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat64i32 *buf)
207 buf->st_dev = buf64->st_dev;
208 buf->st_ino = buf64->st_ino;
209 buf->st_mode = buf64->st_mode;
210 buf->st_nlink = buf64->st_nlink;
211 buf->st_uid = buf64->st_uid;
212 buf->st_gid = buf64->st_gid;
213 buf->st_rdev = buf64->st_rdev;
214 buf->st_size = buf64->st_size;
215 buf->st_atime = buf64->st_atime;
216 buf->st_mtime = buf64->st_mtime;
217 buf->st_ctime = buf64->st_ctime;
220 static void msvcrt_stat64_to_stat32i64(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat32i64 *buf)
222 buf->st_dev = buf64->st_dev;
223 buf->st_ino = buf64->st_ino;
224 buf->st_mode = buf64->st_mode;
225 buf->st_nlink = buf64->st_nlink;
226 buf->st_uid = buf64->st_uid;
227 buf->st_gid = buf64->st_gid;
228 buf->st_rdev = buf64->st_rdev;
229 buf->st_size = buf64->st_size;
230 buf->st_atime = buf64->st_atime;
231 buf->st_mtime = buf64->st_mtime;
232 buf->st_ctime = buf64->st_ctime;
235 static void time_to_filetime( MSVCRT___time64_t time, FILETIME *ft )
237 /* 1601 to 1970 is 369 years plus 89 leap days */
238 static const __int64 secs_1601_to_1970 = ((369 * 365 + 89) * (__int64)86400);
240 __int64 ticks = (time + secs_1601_to_1970) * 10000000;
241 ft->dwHighDateTime = ticks >> 32;
242 ft->dwLowDateTime = ticks;
245 static inline ioinfo* get_ioinfo_nolock(int fd)
247 ioinfo *ret = NULL;
248 if(fd>=0 && fd<MSVCRT_MAX_FILES)
249 ret = MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE];
250 if(!ret)
251 return &MSVCRT___badioinfo;
253 return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
256 static inline void init_ioinfo_cs(ioinfo *info)
258 if(!(info->exflag & EF_CRIT_INIT)) {
259 LOCK_FILES();
260 if(!(info->exflag & EF_CRIT_INIT)) {
261 InitializeCriticalSection(&info->crit);
262 info->exflag |= EF_CRIT_INIT;
264 UNLOCK_FILES();
268 static inline ioinfo* get_ioinfo(int fd)
270 ioinfo *ret = get_ioinfo_nolock(fd);
271 if(ret == &MSVCRT___badioinfo)
272 return ret;
273 init_ioinfo_cs(ret);
274 EnterCriticalSection(&ret->crit);
275 return ret;
278 static inline BOOL alloc_pioinfo_block(int fd)
280 ioinfo *block;
281 int i;
283 if(fd<0 || fd>=MSVCRT_MAX_FILES)
285 *MSVCRT__errno() = MSVCRT_ENFILE;
286 return FALSE;
289 block = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo));
290 if(!block)
292 WARN(":out of memory!\n");
293 *MSVCRT__errno() = MSVCRT_ENOMEM;
294 return FALSE;
296 for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
297 block[i].handle = INVALID_HANDLE_VALUE;
298 if(InterlockedCompareExchangePointer((void**)&MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE], block, NULL))
299 MSVCRT_free(block);
300 return TRUE;
303 static inline ioinfo* get_ioinfo_alloc_fd(int fd)
305 ioinfo *ret;
307 ret = get_ioinfo(fd);
308 if(ret != &MSVCRT___badioinfo)
309 return ret;
311 if(!alloc_pioinfo_block(fd))
312 return &MSVCRT___badioinfo;
314 return get_ioinfo(fd);
317 static inline ioinfo* get_ioinfo_alloc(int *fd)
319 int i;
321 *fd = -1;
322 for(i=0; i<MSVCRT_MAX_FILES; i++)
324 ioinfo *info = get_ioinfo_nolock(i);
326 if(info == &MSVCRT___badioinfo)
328 if(!alloc_pioinfo_block(i))
329 return &MSVCRT___badioinfo;
330 info = get_ioinfo_nolock(i);
333 init_ioinfo_cs(info);
334 if(TryEnterCriticalSection(&info->crit))
336 if(info->handle == INVALID_HANDLE_VALUE)
338 *fd = i;
339 return info;
341 LeaveCriticalSection(&info->crit);
345 WARN(":files exhausted!\n");
346 *MSVCRT__errno() = MSVCRT_ENFILE;
347 return &MSVCRT___badioinfo;
350 static inline void release_ioinfo(ioinfo *info)
352 if(info!=&MSVCRT___badioinfo && info->exflag & EF_CRIT_INIT)
353 LeaveCriticalSection(&info->crit);
356 static inline MSVCRT_FILE* msvcrt_get_file(int i)
358 file_crit *ret;
360 if(i >= MSVCRT_max_streams)
361 return NULL;
363 if(i < _IOB_ENTRIES)
364 return &MSVCRT__iob[i];
366 ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE];
367 if(!ret) {
368 MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(file_crit));
369 if(!MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE]) {
370 ERR("out of memory\n");
371 *MSVCRT__errno() = MSVCRT_ENOMEM;
372 return NULL;
375 ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] + (i%MSVCRT_FD_BLOCK_SIZE);
376 } else
377 ret += i%MSVCRT_FD_BLOCK_SIZE;
379 return &ret->file;
382 /* INTERNAL: free a file entry fd */
383 static void msvcrt_free_fd(int fd)
385 ioinfo *fdinfo = get_ioinfo(fd);
387 if(fdinfo != &MSVCRT___badioinfo)
389 fdinfo->handle = INVALID_HANDLE_VALUE;
390 fdinfo->wxflag = 0;
392 TRACE(":fd (%d) freed\n",fd);
394 if (fd < 3)
396 switch (fd)
398 case 0:
399 SetStdHandle(STD_INPUT_HANDLE, 0);
400 break;
401 case 1:
402 SetStdHandle(STD_OUTPUT_HANDLE, 0);
403 break;
404 case 2:
405 SetStdHandle(STD_ERROR_HANDLE, 0);
406 break;
409 release_ioinfo(fdinfo);
412 static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
414 fdinfo->handle = hand;
415 fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_TTY));
416 fdinfo->lookahead[0] = '\n';
417 fdinfo->lookahead[1] = '\n';
418 fdinfo->lookahead[2] = '\n';
419 fdinfo->exflag &= EF_CRIT_INIT;
421 if (hand == MSVCRT_NO_CONSOLE) hand = 0;
422 switch (fdinfo-MSVCRT___pioinfo[0])
424 case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break;
425 case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
426 case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break;
430 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
431 static int msvcrt_alloc_fd(HANDLE hand, int flag)
433 int fd;
434 ioinfo *info = get_ioinfo_alloc(&fd);
436 TRACE(":handle (%p) allocating fd (%d)\n", hand, fd);
438 if(info == &MSVCRT___badioinfo)
439 return -1;
441 msvcrt_set_fd(info, hand, flag);
442 release_ioinfo(info);
443 return fd;
446 /* INTERNAL: Allocate a FILE* for an fd slot */
447 /* caller must hold the files lock */
448 static MSVCRT_FILE* msvcrt_alloc_fp(void)
450 int i;
451 MSVCRT_FILE *file;
453 for (i = 3; i < MSVCRT_max_streams; i++)
455 file = msvcrt_get_file(i);
456 if (!file)
457 return NULL;
459 if (file->_flag == 0)
461 if (i == MSVCRT_stream_idx)
463 if (file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
465 InitializeCriticalSection(&((file_crit*)file)->crit);
466 ((file_crit*)file)->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_crit.crit");
468 MSVCRT_stream_idx++;
470 return file;
474 return NULL;
477 /* INTERNAL: initialize a FILE* from an open fd */
478 static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags)
480 TRACE(":fd (%d) allocating FILE*\n",fd);
481 if (!(get_ioinfo_nolock(fd)->wxflag & WX_OPEN))
483 WARN(":invalid fd %d\n",fd);
484 *MSVCRT___doserrno() = 0;
485 *MSVCRT__errno() = MSVCRT_EBADF;
486 return -1;
488 file->_ptr = file->_base = NULL;
489 file->_cnt = 0;
490 file->_file = fd;
491 file->_flag = stream_flags;
492 file->_tmpfname = NULL;
494 TRACE(":got FILE* (%p)\n",file);
495 return 0;
498 /* INTERNAL: Create an inheritance data block (for spawned process)
499 * The inheritance block is made of:
500 * 00 int nb of file descriptor (NBFD)
501 * 04 char file flags (wxflag): repeated for each fd
502 * 4+NBFD HANDLE file handle: repeated for each fd
504 unsigned msvcrt_create_io_inherit_block(WORD *size, BYTE **block)
506 int fd, last_fd;
507 char* wxflag_ptr;
508 HANDLE* handle_ptr;
509 ioinfo* fdinfo;
511 for (last_fd=MSVCRT_MAX_FILES-1; last_fd>=0; last_fd--)
512 if (get_ioinfo_nolock(last_fd)->handle != INVALID_HANDLE_VALUE)
513 break;
514 last_fd++;
516 *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * last_fd;
517 *block = MSVCRT_calloc(1, *size);
518 if (!*block)
520 *size = 0;
521 return FALSE;
523 wxflag_ptr = (char*)*block + sizeof(unsigned);
524 handle_ptr = (HANDLE*)(wxflag_ptr + last_fd);
526 *(unsigned*)*block = last_fd;
527 for (fd = 0; fd < last_fd; fd++)
529 /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
530 fdinfo = get_ioinfo(fd);
531 if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN)
533 *wxflag_ptr = fdinfo->wxflag;
534 *handle_ptr = fdinfo->handle;
536 else
538 *wxflag_ptr = 0;
539 *handle_ptr = INVALID_HANDLE_VALUE;
541 release_ioinfo(fdinfo);
542 wxflag_ptr++; handle_ptr++;
544 return TRUE;
547 /* INTERNAL: Set up all file descriptors,
548 * as well as default streams (stdin, stderr and stdout)
550 void msvcrt_init_io(void)
552 STARTUPINFOA si;
553 int i;
554 ioinfo *fdinfo;
556 GetStartupInfoA(&si);
557 if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
559 BYTE* wxflag_ptr;
560 HANDLE* handle_ptr;
561 unsigned int count;
563 count = *(unsigned*)si.lpReserved2;
564 wxflag_ptr = si.lpReserved2 + sizeof(unsigned);
565 handle_ptr = (HANDLE*)(wxflag_ptr + count);
567 count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1));
568 count = min(count, MSVCRT_MAX_FILES);
569 for (i = 0; i < count; i++)
571 if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
573 fdinfo = get_ioinfo_alloc_fd(i);
574 if(fdinfo != &MSVCRT___badioinfo)
575 msvcrt_set_fd(fdinfo, *handle_ptr, *wxflag_ptr);
576 release_ioinfo(fdinfo);
579 wxflag_ptr++; handle_ptr++;
583 fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDIN_FILENO);
584 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
585 HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
586 DWORD flags = WX_OPEN | WX_TEXT;
587 DWORD type = GetFileType(h);
589 if (type == FILE_TYPE_UNKNOWN) {
590 h = MSVCRT_NO_CONSOLE;
591 flags |= WX_TTY;
592 } else if ((type & 0xf) == FILE_TYPE_CHAR) {
593 flags |= WX_TTY;
594 } else if ((type & 0xf) == FILE_TYPE_PIPE) {
595 flags |= WX_PIPE;
598 msvcrt_set_fd(fdinfo, h, flags);
600 release_ioinfo(fdinfo);
602 fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDOUT_FILENO);
603 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
604 HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
605 DWORD flags = WX_OPEN | WX_TEXT;
606 DWORD type = GetFileType(h);
608 if (type == FILE_TYPE_UNKNOWN) {
609 h = MSVCRT_NO_CONSOLE;
610 flags |= WX_TTY;
611 } else if ((type & 0xf) == FILE_TYPE_CHAR) {
612 flags |= WX_TTY;
613 } else if ((type & 0xf) == FILE_TYPE_PIPE) {
614 flags |= WX_PIPE;
617 msvcrt_set_fd(fdinfo, h, flags);
619 release_ioinfo(fdinfo);
621 fdinfo = get_ioinfo_alloc_fd(MSVCRT_STDERR_FILENO);
622 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
623 HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
624 DWORD flags = WX_OPEN | WX_TEXT;
625 DWORD type = GetFileType(h);
627 if (type == FILE_TYPE_UNKNOWN) {
628 h = MSVCRT_NO_CONSOLE;
629 flags |= WX_TTY;
630 } else if ((type & 0xf) == FILE_TYPE_CHAR) {
631 flags |= WX_TTY;
632 } else if ((type & 0xf) == FILE_TYPE_PIPE) {
633 flags |= WX_PIPE;
636 msvcrt_set_fd(fdinfo, h, flags);
638 release_ioinfo(fdinfo);
640 TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo_nolock(MSVCRT_STDIN_FILENO)->handle,
641 get_ioinfo_nolock(MSVCRT_STDOUT_FILENO)->handle,
642 get_ioinfo_nolock(MSVCRT_STDERR_FILENO)->handle);
644 memset(MSVCRT__iob,0,3*sizeof(MSVCRT_FILE));
645 for (i = 0; i < 3; i++)
647 /* FILE structs for stdin/out/err are static and never deleted */
648 MSVCRT__iob[i]._file = get_ioinfo_nolock(i)->handle == MSVCRT_NO_CONSOLE ?
649 MSVCRT_NO_CONSOLE_FD : i;
650 MSVCRT__iob[i]._tmpfname = NULL;
651 MSVCRT__iob[i]._flag = (i == 0) ? MSVCRT__IOREAD : MSVCRT__IOWRT;
653 MSVCRT_stream_idx = 3;
656 /* INTERNAL: Flush stdio file buffer */
657 static int msvcrt_flush_buffer(MSVCRT_FILE* file)
659 if((file->_flag & (MSVCRT__IOREAD|MSVCRT__IOWRT)) == MSVCRT__IOWRT &&
660 file->_flag & (MSVCRT__IOMYBUF|MSVCRT__USERBUF)) {
661 int cnt=file->_ptr-file->_base;
662 if(cnt>0 && MSVCRT__write(file->_file, file->_base, cnt) != cnt) {
663 file->_flag |= MSVCRT__IOERR;
664 return MSVCRT_EOF;
667 if(file->_flag & MSVCRT__IORW)
668 file->_flag &= ~MSVCRT__IOWRT;
671 file->_ptr=file->_base;
672 file->_cnt=0;
673 return 0;
676 /*********************************************************************
677 * _isatty (MSVCRT.@)
679 int CDECL MSVCRT__isatty(int fd)
681 TRACE(":fd (%d)\n",fd);
683 return get_ioinfo_nolock(fd)->wxflag & WX_TTY;
686 /* INTERNAL: Allocate stdio file buffer */
687 static BOOL msvcrt_alloc_buffer(MSVCRT_FILE* file)
689 if((file->_file==MSVCRT_STDOUT_FILENO || file->_file==MSVCRT_STDERR_FILENO)
690 && MSVCRT__isatty(file->_file))
691 return FALSE;
693 file->_base = MSVCRT_calloc(1, MSVCRT_INTERNAL_BUFSIZ);
694 if(file->_base) {
695 file->_bufsiz = MSVCRT_INTERNAL_BUFSIZ;
696 file->_flag |= MSVCRT__IOMYBUF;
697 } else {
698 file->_base = (char*)(&file->_charbuf);
699 file->_bufsiz = 2;
700 file->_flag |= MSVCRT__IONBF;
702 file->_ptr = file->_base;
703 file->_cnt = 0;
704 return TRUE;
707 /* INTERNAL: Allocate temporary buffer for stdout and stderr */
708 static BOOL add_std_buffer(MSVCRT_FILE *file)
710 static char buffers[2][MSVCRT_BUFSIZ];
712 if((file->_file!=MSVCRT_STDOUT_FILENO && file->_file!=MSVCRT_STDERR_FILENO)
713 || (file->_flag & (MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF))
714 || !MSVCRT__isatty(file->_file))
715 return FALSE;
717 file->_ptr = file->_base = buffers[file->_file == MSVCRT_STDOUT_FILENO ? 0 : 1];
718 file->_bufsiz = file->_cnt = MSVCRT_BUFSIZ;
719 file->_flag |= MSVCRT__USERBUF;
720 return TRUE;
723 /* INTERNAL: Removes temporary buffer from stdout or stderr */
724 /* Only call this function when add_std_buffer returned TRUE */
725 static void remove_std_buffer(MSVCRT_FILE *file)
727 msvcrt_flush_buffer(file);
728 file->_ptr = file->_base = NULL;
729 file->_bufsiz = file->_cnt = 0;
730 file->_flag &= ~MSVCRT__USERBUF;
733 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
734 static int msvcrt_int_to_base32(int num, char *str)
736 char *p;
737 int n = num;
738 int digits = 0;
740 while (n != 0)
742 n >>= 5;
743 digits++;
745 p = str + digits;
746 *p = 0;
747 while (--p >= str)
749 *p = (num & 31) + '0';
750 if (*p > '9')
751 *p += ('a' - '0' - 10);
752 num >>= 5;
755 return digits;
758 /* INTERNAL: wide character version of msvcrt_int_to_base32 */
759 static int msvcrt_int_to_base32_w(int num, MSVCRT_wchar_t *str)
761 MSVCRT_wchar_t *p;
762 int n = num;
763 int digits = 0;
765 while (n != 0)
767 n >>= 5;
768 digits++;
770 p = str + digits;
771 *p = 0;
772 while (--p >= str)
774 *p = (num & 31) + '0';
775 if (*p > '9')
776 *p += ('a' - '0' - 10);
777 num >>= 5;
780 return digits;
783 /*********************************************************************
784 * __iob_func (MSVCRT.@)
786 #undef __iob_func
787 MSVCRT_FILE * CDECL __iob_func(void)
789 return &MSVCRT__iob[0];
792 #if _MSVCR_VER >= 140
793 /*********************************************************************
794 * __acrt_iob_func(UCRTBASE.@)
796 MSVCRT_FILE * CDECL MSVCRT___acrt_iob_func(unsigned idx)
798 return &MSVCRT__iob[idx];
800 #endif
802 /*********************************************************************
803 * _access (MSVCRT.@)
805 int CDECL MSVCRT__access(const char *filename, int mode)
807 DWORD attr = GetFileAttributesA(filename);
809 TRACE("(%s,%d) %d\n",filename,mode,attr);
811 if (!filename || attr == INVALID_FILE_ATTRIBUTES)
813 msvcrt_set_errno(GetLastError());
814 return -1;
816 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
818 msvcrt_set_errno(ERROR_ACCESS_DENIED);
819 return -1;
821 return 0;
824 /*********************************************************************
825 * _access_s (MSVCRT.@)
827 int CDECL MSVCRT__access_s(const char *filename, int mode)
829 if (!MSVCRT_CHECK_PMT(filename != NULL)) return *MSVCRT__errno();
830 if (!MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0)) return *MSVCRT__errno();
832 if (MSVCRT__access(filename, mode) == -1)
833 return *MSVCRT__errno();
834 return 0;
837 /*********************************************************************
838 * _waccess (MSVCRT.@)
840 int CDECL MSVCRT__waccess(const MSVCRT_wchar_t *filename, int mode)
842 DWORD attr = GetFileAttributesW(filename);
844 TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr);
846 if (!filename || attr == INVALID_FILE_ATTRIBUTES)
848 msvcrt_set_errno(GetLastError());
849 return -1;
851 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
853 msvcrt_set_errno(ERROR_ACCESS_DENIED);
854 return -1;
856 return 0;
859 /*********************************************************************
860 * _waccess_s (MSVCRT.@)
862 int CDECL MSVCRT__waccess_s(const MSVCRT_wchar_t *filename, int mode)
864 if (!MSVCRT_CHECK_PMT(filename != NULL)) return *MSVCRT__errno();
865 if (!MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0)) return *MSVCRT__errno();
867 if (MSVCRT__waccess(filename, mode) == -1)
868 return *MSVCRT__errno();
869 return 0;
872 /*********************************************************************
873 * _chmod (MSVCRT.@)
875 int CDECL MSVCRT__chmod(const char *path, int flags)
877 DWORD oldFlags = GetFileAttributesA(path);
879 if (oldFlags != INVALID_FILE_ATTRIBUTES)
881 DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
882 oldFlags | FILE_ATTRIBUTE_READONLY;
884 if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
885 return 0;
887 msvcrt_set_errno(GetLastError());
888 return -1;
891 /*********************************************************************
892 * _wchmod (MSVCRT.@)
894 int CDECL MSVCRT__wchmod(const MSVCRT_wchar_t *path, int flags)
896 DWORD oldFlags = GetFileAttributesW(path);
898 if (oldFlags != INVALID_FILE_ATTRIBUTES)
900 DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
901 oldFlags | FILE_ATTRIBUTE_READONLY;
903 if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
904 return 0;
906 msvcrt_set_errno(GetLastError());
907 return -1;
910 /*********************************************************************
911 * _unlink (MSVCRT.@)
913 int CDECL MSVCRT__unlink(const char *path)
915 TRACE("%s\n",debugstr_a(path));
916 if(DeleteFileA(path))
917 return 0;
918 TRACE("failed (%d)\n",GetLastError());
919 msvcrt_set_errno(GetLastError());
920 return -1;
923 /*********************************************************************
924 * _wunlink (MSVCRT.@)
926 int CDECL MSVCRT__wunlink(const MSVCRT_wchar_t *path)
928 TRACE("(%s)\n",debugstr_w(path));
929 if(DeleteFileW(path))
930 return 0;
931 TRACE("failed (%d)\n",GetLastError());
932 msvcrt_set_errno(GetLastError());
933 return -1;
936 /*********************************************************************
937 * _commit (MSVCRT.@)
939 int CDECL MSVCRT__commit(int fd)
941 ioinfo *info = get_ioinfo(fd);
942 int ret;
944 TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
946 if (info->handle == INVALID_HANDLE_VALUE)
947 ret = -1;
948 else if (!FlushFileBuffers(info->handle))
950 if (GetLastError() == ERROR_INVALID_HANDLE)
952 /* FlushFileBuffers fails for console handles
953 * so we ignore this error.
955 ret = 0;
957 else
959 TRACE(":failed-last error (%d)\n",GetLastError());
960 msvcrt_set_errno(GetLastError());
961 ret = -1;
964 else
966 TRACE(":ok\n");
967 ret = 0;
970 release_ioinfo(info);
971 return ret;
974 /* flush_all_buffers calls MSVCRT_fflush which calls flush_all_buffers */
975 int CDECL MSVCRT_fflush(MSVCRT_FILE* file);
977 /* INTERNAL: Flush all stream buffer */
978 static int msvcrt_flush_all_buffers(int mask)
980 int i, num_flushed = 0;
981 MSVCRT_FILE *file;
983 LOCK_FILES();
984 for (i = 0; i < MSVCRT_stream_idx; i++) {
985 file = msvcrt_get_file(i);
987 if (file->_flag)
989 if(file->_flag & mask) {
990 MSVCRT_fflush(file);
991 num_flushed++;
995 UNLOCK_FILES();
997 TRACE(":flushed (%d) handles\n",num_flushed);
998 return num_flushed;
1001 /*********************************************************************
1002 * _flushall (MSVCRT.@)
1004 int CDECL MSVCRT__flushall(void)
1006 return msvcrt_flush_all_buffers(MSVCRT__IOWRT | MSVCRT__IOREAD);
1009 /*********************************************************************
1010 * fflush (MSVCRT.@)
1012 int CDECL MSVCRT_fflush(MSVCRT_FILE* file)
1014 int ret;
1016 if(!file) {
1017 msvcrt_flush_all_buffers(MSVCRT__IOWRT);
1018 ret = 0;
1019 } else {
1020 MSVCRT__lock_file(file);
1021 ret = MSVCRT__fflush_nolock(file);
1022 MSVCRT__unlock_file(file);
1025 return ret;
1028 /*********************************************************************
1029 * _fflush_nolock (MSVCRT.@)
1031 int CDECL MSVCRT__fflush_nolock(MSVCRT_FILE* file)
1033 int res;
1035 if(!file) {
1036 msvcrt_flush_all_buffers(MSVCRT__IOWRT);
1037 return 0;
1040 res = msvcrt_flush_buffer(file);
1041 if(!res && (file->_flag & MSVCRT__IOCOMMIT))
1042 res = MSVCRT__commit(file->_file) ? MSVCRT_EOF : 0;
1043 return res;
1046 /*********************************************************************
1047 * _close (MSVCRT.@)
1049 int CDECL MSVCRT__close(int fd)
1051 ioinfo *info = get_ioinfo(fd);
1052 int ret;
1054 TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1056 if (fd == MSVCRT_NO_CONSOLE_FD) {
1057 *MSVCRT__errno() = MSVCRT_EBADF;
1058 ret = -1;
1059 } else if (!MSVCRT_CHECK_PMT_ERR(info->wxflag & WX_OPEN, MSVCRT_EBADF)) {
1060 ret = -1;
1061 } else if (fd == MSVCRT_STDOUT_FILENO &&
1062 info->handle == get_ioinfo_nolock(MSVCRT_STDERR_FILENO)->handle) {
1063 msvcrt_free_fd(fd);
1064 ret = 0;
1065 } else if (fd == MSVCRT_STDERR_FILENO &&
1066 info->handle == get_ioinfo_nolock(MSVCRT_STDOUT_FILENO)->handle) {
1067 msvcrt_free_fd(fd);
1068 ret = 0;
1069 } else {
1070 ret = CloseHandle(info->handle) ? 0 : -1;
1071 msvcrt_free_fd(fd);
1072 if (ret) {
1073 WARN(":failed-last error (%d)\n",GetLastError());
1074 msvcrt_set_errno(GetLastError());
1077 release_ioinfo(info);
1078 return ret;
1081 /*********************************************************************
1082 * _dup2 (MSVCRT.@)
1083 * NOTES
1084 * MSDN isn't clear on this point, but the remarks for _pipe
1085 * indicate file descriptors duplicated with _dup and _dup2 are always
1086 * inheritable.
1088 int CDECL MSVCRT__dup2(int od, int nd)
1090 ioinfo *info_od, *info_nd;
1091 int ret;
1093 TRACE("(od=%d, nd=%d)\n", od, nd);
1095 if (od < nd)
1097 info_od = get_ioinfo(od);
1098 info_nd = get_ioinfo_alloc_fd(nd);
1100 else
1102 info_nd = get_ioinfo_alloc_fd(nd);
1103 info_od = get_ioinfo(od);
1106 if (info_nd == &MSVCRT___badioinfo)
1108 ret = -1;
1110 else if (info_od->wxflag & WX_OPEN)
1112 HANDLE handle;
1114 if (DuplicateHandle(GetCurrentProcess(), info_od->handle,
1115 GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
1117 int wxflag = info_od->wxflag & ~MSVCRT__O_NOINHERIT;
1119 if (info_nd->wxflag & WX_OPEN)
1120 MSVCRT__close(nd);
1122 msvcrt_set_fd(info_nd, handle, wxflag);
1123 /* _dup2 returns 0, not nd, on success */
1124 ret = 0;
1126 else
1128 ret = -1;
1129 msvcrt_set_errno(GetLastError());
1132 else
1134 *MSVCRT__errno() = MSVCRT_EBADF;
1135 ret = -1;
1138 release_ioinfo(info_od);
1139 release_ioinfo(info_nd);
1140 return ret;
1143 /*********************************************************************
1144 * _dup (MSVCRT.@)
1146 int CDECL MSVCRT__dup(int od)
1148 int fd, ret;
1149 ioinfo *info = get_ioinfo_alloc(&fd);
1151 if (MSVCRT__dup2(od, fd) == 0)
1152 ret = fd;
1153 else
1154 ret = -1;
1155 release_ioinfo(info);
1156 return ret;
1159 /*********************************************************************
1160 * _eof (MSVCRT.@)
1162 int CDECL MSVCRT__eof(int fd)
1164 ioinfo *info = get_ioinfo(fd);
1165 DWORD curpos,endpos;
1166 LONG hcurpos,hendpos;
1168 TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1170 if (info->handle == INVALID_HANDLE_VALUE)
1172 release_ioinfo(info);
1173 return -1;
1176 if (info->wxflag & WX_ATEOF)
1178 release_ioinfo(info);
1179 return TRUE;
1182 /* Otherwise we do it the hard way */
1183 hcurpos = hendpos = 0;
1184 curpos = SetFilePointer(info->handle, 0, &hcurpos, FILE_CURRENT);
1185 endpos = SetFilePointer(info->handle, 0, &hendpos, FILE_END);
1187 if (curpos == endpos && hcurpos == hendpos)
1189 /* FIXME: shouldn't WX_ATEOF be set here? */
1190 release_ioinfo(info);
1191 return TRUE;
1194 SetFilePointer(info->handle, curpos, &hcurpos, FILE_BEGIN);
1195 release_ioinfo(info);
1196 return FALSE;
1199 /*********************************************************************
1200 * _fcloseall (MSVCRT.@)
1202 int CDECL MSVCRT__fcloseall(void)
1204 int num_closed = 0, i;
1205 MSVCRT_FILE *file;
1207 LOCK_FILES();
1208 for (i = 3; i < MSVCRT_stream_idx; i++) {
1209 file = msvcrt_get_file(i);
1211 if (file->_flag && !MSVCRT_fclose(file))
1212 num_closed++;
1214 UNLOCK_FILES();
1216 TRACE(":closed (%d) handles\n",num_closed);
1217 return num_closed;
1220 /* free everything on process exit */
1221 void msvcrt_free_io(void)
1223 unsigned int i;
1224 int j;
1226 MSVCRT__flushall();
1227 MSVCRT__fcloseall();
1229 for(i=0; i<ARRAY_SIZE(MSVCRT___pioinfo); i++)
1231 if(!MSVCRT___pioinfo[i])
1232 continue;
1234 for(j=0; j<MSVCRT_FD_BLOCK_SIZE; j++)
1236 if(MSVCRT___pioinfo[i][j].exflag & EF_CRIT_INIT)
1237 DeleteCriticalSection(&MSVCRT___pioinfo[i][j].crit);
1239 MSVCRT_free(MSVCRT___pioinfo[i]);
1242 for(j=0; j<MSVCRT_stream_idx; j++)
1244 MSVCRT_FILE *file = msvcrt_get_file(j);
1245 if(file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
1247 ((file_crit*)file)->crit.DebugInfo->Spare[0] = 0;
1248 DeleteCriticalSection(&((file_crit*)file)->crit);
1252 for(i=0; i<ARRAY_SIZE(MSVCRT_fstream); i++)
1253 MSVCRT_free(MSVCRT_fstream[i]);
1256 /*********************************************************************
1257 * _lseeki64 (MSVCRT.@)
1259 __int64 CDECL MSVCRT__lseeki64(int fd, __int64 offset, int whence)
1261 ioinfo *info = get_ioinfo(fd);
1262 LARGE_INTEGER ofs;
1264 TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1266 if (info->handle == INVALID_HANDLE_VALUE)
1268 *MSVCRT__errno() = MSVCRT_EBADF;
1269 release_ioinfo(info);
1270 return -1;
1273 if (whence < 0 || whence > 2)
1275 release_ioinfo(info);
1276 *MSVCRT__errno() = MSVCRT_EINVAL;
1277 return -1;
1280 TRACE(":fd (%d) to %s pos %s\n",
1281 fd,wine_dbgstr_longlong(offset),
1282 (whence==MSVCRT_SEEK_SET)?"SEEK_SET":
1283 (whence==MSVCRT_SEEK_CUR)?"SEEK_CUR":
1284 (whence==MSVCRT_SEEK_END)?"SEEK_END":"UNKNOWN");
1286 /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
1287 * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
1288 ofs.QuadPart = offset;
1289 if ((ofs.u.LowPart = SetFilePointer(info->handle, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
1290 GetLastError() == ERROR_SUCCESS)
1292 info->wxflag &= ~WX_ATEOF;
1293 /* FIXME: What if we seek _to_ EOF - is EOF set? */
1295 release_ioinfo(info);
1296 return ofs.QuadPart;
1298 release_ioinfo(info);
1299 TRACE(":error-last error (%d)\n",GetLastError());
1300 msvcrt_set_errno(GetLastError());
1301 return -1;
1304 /*********************************************************************
1305 * _lseek (MSVCRT.@)
1307 LONG CDECL MSVCRT__lseek(int fd, LONG offset, int whence)
1309 return MSVCRT__lseeki64(fd, offset, whence);
1312 /*********************************************************************
1313 * _lock_file (MSVCRT.@)
1315 void CDECL MSVCRT__lock_file(MSVCRT_FILE *file)
1317 if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1318 _lock(_STREAM_LOCKS+(file-MSVCRT__iob));
1319 else
1320 EnterCriticalSection(&((file_crit*)file)->crit);
1323 /*********************************************************************
1324 * _unlock_file (MSVCRT.@)
1326 void CDECL MSVCRT__unlock_file(MSVCRT_FILE *file)
1328 if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1329 _unlock(_STREAM_LOCKS+(file-MSVCRT__iob));
1330 else
1331 LeaveCriticalSection(&((file_crit*)file)->crit);
1334 /*********************************************************************
1335 * _locking (MSVCRT.@)
1337 * This is untested; the underlying LockFile doesn't work yet.
1339 int CDECL MSVCRT__locking(int fd, int mode, LONG nbytes)
1341 ioinfo *info = get_ioinfo(fd);
1342 BOOL ret;
1343 DWORD cur_locn;
1345 TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1346 if (info->handle == INVALID_HANDLE_VALUE)
1348 release_ioinfo(info);
1349 return -1;
1352 if (mode < 0 || mode > 4)
1354 release_ioinfo(info);
1355 *MSVCRT__errno() = MSVCRT_EINVAL;
1356 return -1;
1359 TRACE(":fd (%d) by 0x%08x mode %s\n",
1360 fd,nbytes,(mode==MSVCRT__LK_UNLCK)?"_LK_UNLCK":
1361 (mode==MSVCRT__LK_LOCK)?"_LK_LOCK":
1362 (mode==MSVCRT__LK_NBLCK)?"_LK_NBLCK":
1363 (mode==MSVCRT__LK_RLCK)?"_LK_RLCK":
1364 (mode==MSVCRT__LK_NBRLCK)?"_LK_NBRLCK":
1365 "UNKNOWN");
1367 if ((cur_locn = SetFilePointer(info->handle, 0L, NULL, FILE_CURRENT)) == INVALID_SET_FILE_POINTER)
1369 release_ioinfo(info);
1370 FIXME ("Seek failed\n");
1371 *MSVCRT__errno() = MSVCRT_EINVAL; /* FIXME */
1372 return -1;
1374 if (mode == MSVCRT__LK_LOCK || mode == MSVCRT__LK_RLCK)
1376 int nretry = 10;
1377 ret = 1; /* just to satisfy gcc */
1378 while (nretry--)
1380 ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1381 if (ret) break;
1382 Sleep(1);
1385 else if (mode == MSVCRT__LK_UNLCK)
1386 ret = UnlockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1387 else
1388 ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1389 /* FIXME - what about error settings? */
1390 release_ioinfo(info);
1391 return ret ? 0 : -1;
1394 /*********************************************************************
1395 * _fseeki64 (MSVCRT.@)
1397 int CDECL MSVCRT__fseeki64(MSVCRT_FILE* file, __int64 offset, int whence)
1399 int ret;
1401 MSVCRT__lock_file(file);
1402 ret = MSVCRT__fseeki64_nolock(file, offset, whence);
1403 MSVCRT__unlock_file(file);
1405 return ret;
1408 /*********************************************************************
1409 * _fseeki64_nolock (MSVCRT.@)
1411 int CDECL MSVCRT__fseeki64_nolock(MSVCRT_FILE* file, __int64 offset, int whence)
1413 int ret;
1415 if(whence == MSVCRT_SEEK_CUR && file->_flag & MSVCRT__IOREAD ) {
1416 whence = MSVCRT_SEEK_SET;
1417 offset += MSVCRT__ftelli64_nolock(file);
1420 /* Flush output if needed */
1421 msvcrt_flush_buffer(file);
1422 /* Reset direction of i/o */
1423 if(file->_flag & MSVCRT__IORW) {
1424 file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
1426 /* Clear end of file flag */
1427 file->_flag &= ~MSVCRT__IOEOF;
1428 ret = (MSVCRT__lseeki64(file->_file,offset,whence) == -1)?-1:0;
1430 return ret;
1433 /*********************************************************************
1434 * fseek (MSVCRT.@)
1436 int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
1438 return MSVCRT__fseeki64( file, offset, whence );
1441 /*********************************************************************
1442 * _fseek_nolock (MSVCRT.@)
1444 int CDECL MSVCRT__fseek_nolock(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
1446 return MSVCRT__fseeki64_nolock( file, offset, whence );
1449 /*********************************************************************
1450 * _chsize_s (MSVCRT.@)
1452 int CDECL MSVCRT__chsize_s(int fd, __int64 size)
1454 ioinfo *info;
1455 __int64 cur, pos;
1456 BOOL ret = FALSE;
1458 TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size));
1460 if (!MSVCRT_CHECK_PMT(size >= 0)) return MSVCRT_EINVAL;
1463 info = get_ioinfo(fd);
1464 if (info->handle != INVALID_HANDLE_VALUE)
1466 /* save the current file pointer */
1467 cur = MSVCRT__lseeki64(fd, 0, MSVCRT_SEEK_CUR);
1468 if (cur >= 0)
1470 pos = MSVCRT__lseeki64(fd, size, MSVCRT_SEEK_SET);
1471 if (pos >= 0)
1473 ret = SetEndOfFile(info->handle);
1474 if (!ret) msvcrt_set_errno(GetLastError());
1477 /* restore the file pointer */
1478 MSVCRT__lseeki64(fd, cur, MSVCRT_SEEK_SET);
1482 release_ioinfo(info);
1483 return ret ? 0 : *MSVCRT__errno();
1486 /*********************************************************************
1487 * _chsize (MSVCRT.@)
1489 int CDECL MSVCRT__chsize(int fd, MSVCRT_long size)
1491 /* _chsize_s returns errno on failure but _chsize should return -1 */
1492 return MSVCRT__chsize_s( fd, size ) == 0 ? 0 : -1;
1495 /*********************************************************************
1496 * clearerr (MSVCRT.@)
1498 void CDECL MSVCRT_clearerr(MSVCRT_FILE* file)
1500 TRACE(":file (%p) fd (%d)\n",file,file->_file);
1502 MSVCRT__lock_file(file);
1503 file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
1504 MSVCRT__unlock_file(file);
1507 /*********************************************************************
1508 * clearerr_s (MSVCRT.@)
1510 int CDECL MSVCRT_clearerr_s(MSVCRT_FILE* file)
1512 TRACE(":file (%p)\n",file);
1514 if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
1516 MSVCRT__lock_file(file);
1517 file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
1518 MSVCRT__unlock_file(file);
1519 return 0;
1522 /*********************************************************************
1523 * rewind (MSVCRT.@)
1525 void CDECL MSVCRT_rewind(MSVCRT_FILE* file)
1527 TRACE(":file (%p) fd (%d)\n",file,file->_file);
1529 MSVCRT__lock_file(file);
1530 MSVCRT__fseek_nolock(file, 0L, MSVCRT_SEEK_SET);
1531 MSVCRT_clearerr(file);
1532 MSVCRT__unlock_file(file);
1535 static int msvcrt_get_flags(const MSVCRT_wchar_t* mode, int *open_flags, int* stream_flags)
1537 int plus = strchrW(mode, '+') != NULL;
1539 TRACE("%s\n", debugstr_w(mode));
1541 while(*mode == ' ') mode++;
1543 switch(*mode++)
1545 case 'R': case 'r':
1546 *open_flags = plus ? MSVCRT__O_RDWR : MSVCRT__O_RDONLY;
1547 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOREAD;
1548 break;
1549 case 'W': case 'w':
1550 *open_flags = MSVCRT__O_CREAT | MSVCRT__O_TRUNC | (plus ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1551 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1552 break;
1553 case 'A': case 'a':
1554 *open_flags = MSVCRT__O_CREAT | MSVCRT__O_APPEND | (plus ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1555 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1556 break;
1557 default:
1558 MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL);
1559 return -1;
1562 *stream_flags |= MSVCRT__commode;
1564 while (*mode && *mode!=',')
1565 switch (*mode++)
1567 case 'B': case 'b':
1568 *open_flags |= MSVCRT__O_BINARY;
1569 *open_flags &= ~MSVCRT__O_TEXT;
1570 break;
1571 case 't':
1572 *open_flags |= MSVCRT__O_TEXT;
1573 *open_flags &= ~MSVCRT__O_BINARY;
1574 break;
1575 case 'D':
1576 *open_flags |= MSVCRT__O_TEMPORARY;
1577 break;
1578 case 'T':
1579 *open_flags |= MSVCRT__O_SHORT_LIVED;
1580 break;
1581 case 'c':
1582 *stream_flags |= MSVCRT__IOCOMMIT;
1583 break;
1584 case 'n':
1585 *stream_flags &= ~MSVCRT__IOCOMMIT;
1586 break;
1587 case 'N':
1588 *open_flags |= MSVCRT__O_NOINHERIT;
1589 break;
1590 case '+':
1591 case ' ':
1592 case 'a':
1593 case 'w':
1594 break;
1595 case 'S':
1596 case 'R':
1597 FIXME("ignoring cache optimization flag: %c\n", mode[-1]);
1598 break;
1599 default:
1600 ERR("incorrect mode flag: %c\n", mode[-1]);
1601 break;
1604 if(*mode == ',')
1606 static const WCHAR ccs[] = {'c','c','s'};
1607 static const WCHAR utf8[] = {'u','t','f','-','8'};
1608 static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'};
1609 static const WCHAR unicode[] = {'u','n','i','c','o','d','e'};
1611 mode++;
1612 while(*mode == ' ') mode++;
1613 if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, ARRAY_SIZE(ccs))))
1614 return -1;
1615 mode += ARRAY_SIZE(ccs);
1616 while(*mode == ' ') mode++;
1617 if(!MSVCRT_CHECK_PMT(*mode == '='))
1618 return -1;
1619 mode++;
1620 while(*mode == ' ') mode++;
1622 if(!strncmpiW(utf8, mode, ARRAY_SIZE(utf8)))
1624 *open_flags |= MSVCRT__O_U8TEXT;
1625 mode += ARRAY_SIZE(utf8);
1627 else if(!strncmpiW(utf16le, mode, ARRAY_SIZE(utf16le)))
1629 *open_flags |= MSVCRT__O_U16TEXT;
1630 mode += ARRAY_SIZE(utf16le);
1632 else if(!strncmpiW(unicode, mode, ARRAY_SIZE(unicode)))
1634 *open_flags |= MSVCRT__O_WTEXT;
1635 mode += ARRAY_SIZE(unicode);
1637 else
1639 MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL);
1640 return -1;
1643 while(*mode == ' ') mode++;
1646 if(!MSVCRT_CHECK_PMT(*mode == 0))
1647 return -1;
1648 return 0;
1651 /*********************************************************************
1652 * _fdopen (MSVCRT.@)
1654 MSVCRT_FILE* CDECL MSVCRT__fdopen(int fd, const char *mode)
1656 MSVCRT_FILE *ret;
1657 MSVCRT_wchar_t *modeW = NULL;
1659 if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
1661 ret = MSVCRT__wfdopen(fd, modeW);
1663 MSVCRT_free(modeW);
1664 return ret;
1667 /*********************************************************************
1668 * _wfdopen (MSVCRT.@)
1670 MSVCRT_FILE* CDECL MSVCRT__wfdopen(int fd, const MSVCRT_wchar_t *mode)
1672 int open_flags, stream_flags;
1673 MSVCRT_FILE* file;
1675 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
1677 LOCK_FILES();
1678 if (!(file = msvcrt_alloc_fp()))
1679 file = NULL;
1680 else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
1682 file->_flag = 0;
1683 file = NULL;
1685 else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
1686 UNLOCK_FILES();
1688 return file;
1691 /*********************************************************************
1692 * _filelength (MSVCRT.@)
1694 LONG CDECL MSVCRT__filelength(int fd)
1696 LONG curPos = MSVCRT__lseek(fd, 0, MSVCRT_SEEK_CUR);
1697 if (curPos != -1)
1699 LONG endPos = MSVCRT__lseek(fd, 0, MSVCRT_SEEK_END);
1700 if (endPos != -1)
1702 if (endPos != curPos)
1703 MSVCRT__lseek(fd, curPos, MSVCRT_SEEK_SET);
1704 return endPos;
1707 return -1;
1710 /*********************************************************************
1711 * _filelengthi64 (MSVCRT.@)
1713 __int64 CDECL MSVCRT__filelengthi64(int fd)
1715 __int64 curPos = MSVCRT__lseeki64(fd, 0, MSVCRT_SEEK_CUR);
1716 if (curPos != -1)
1718 __int64 endPos = MSVCRT__lseeki64(fd, 0, MSVCRT_SEEK_END);
1719 if (endPos != -1)
1721 if (endPos != curPos)
1722 MSVCRT__lseeki64(fd, curPos, MSVCRT_SEEK_SET);
1723 return endPos;
1726 return -1;
1729 /*********************************************************************
1730 * _fileno (MSVCRT.@)
1732 int CDECL MSVCRT__fileno(MSVCRT_FILE* file)
1734 TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
1735 return file->_file;
1738 /*********************************************************************
1739 * _fstat64 (MSVCRT.@)
1741 int CDECL MSVCRT__fstat64(int fd, struct MSVCRT__stat64* buf)
1743 ioinfo *info = get_ioinfo(fd);
1744 DWORD dw;
1745 DWORD type;
1746 BY_HANDLE_FILE_INFORMATION hfi;
1748 TRACE(":fd (%d) stat (%p)\n", fd, buf);
1749 if (info->handle == INVALID_HANDLE_VALUE)
1751 release_ioinfo(info);
1752 return -1;
1755 if (!buf)
1757 WARN(":failed-NULL buf\n");
1758 msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1759 release_ioinfo(info);
1760 return -1;
1763 memset(&hfi, 0, sizeof(hfi));
1764 memset(buf, 0, sizeof(struct MSVCRT__stat64));
1765 type = GetFileType(info->handle);
1766 if (type == FILE_TYPE_PIPE)
1768 buf->st_dev = buf->st_rdev = fd;
1769 buf->st_mode = MSVCRT__S_IFIFO;
1770 buf->st_nlink = 1;
1772 else if (type == FILE_TYPE_CHAR)
1774 buf->st_dev = buf->st_rdev = fd;
1775 buf->st_mode = MSVCRT__S_IFCHR;
1776 buf->st_nlink = 1;
1778 else /* FILE_TYPE_DISK etc. */
1780 if (!GetFileInformationByHandle(info->handle, &hfi))
1782 WARN(":failed-last error (%d)\n",GetLastError());
1783 msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1784 release_ioinfo(info);
1785 return -1;
1787 buf->st_mode = MSVCRT__S_IFREG | 0444;
1788 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1789 buf->st_mode |= 0222;
1790 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
1791 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
1792 buf->st_atime = dw;
1793 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
1794 buf->st_mtime = buf->st_ctime = dw;
1795 buf->st_nlink = hfi.nNumberOfLinks;
1797 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes,
1798 buf->st_mode);
1799 release_ioinfo(info);
1800 return 0;
1803 /*********************************************************************
1804 * _fstati64 (MSVCRT.@)
1806 int CDECL MSVCRT__fstati64(int fd, struct MSVCRT__stati64* buf)
1808 int ret;
1809 struct MSVCRT__stat64 buf64;
1811 ret = MSVCRT__fstat64(fd, &buf64);
1812 if (!ret)
1813 msvcrt_stat64_to_stati64(&buf64, buf);
1814 return ret;
1817 /*********************************************************************
1818 * _fstat (MSVCRT.@)
1820 int CDECL MSVCRT__fstat(int fd, struct MSVCRT__stat* buf)
1821 { int ret;
1822 struct MSVCRT__stat64 buf64;
1824 ret = MSVCRT__fstat64(fd, &buf64);
1825 if (!ret)
1826 msvcrt_stat64_to_stat(&buf64, buf);
1827 return ret;
1830 /*********************************************************************
1831 * _fstat32 (MSVCR80.@)
1833 int CDECL MSVCRT__fstat32(int fd, struct MSVCRT__stat32* buf)
1835 int ret;
1836 struct MSVCRT__stat64 buf64;
1838 ret = MSVCRT__fstat64(fd, &buf64);
1839 if (!ret)
1840 msvcrt_stat64_to_stat32(&buf64, buf);
1841 return ret;
1844 /*********************************************************************
1845 * _fstat32i64 (MSVCR80.@)
1847 int CDECL MSVCRT__fstat32i64(int fd, struct MSVCRT__stat32i64* buf)
1849 int ret;
1850 struct MSVCRT__stat64 buf64;
1852 ret = MSVCRT__fstat64(fd, &buf64);
1853 if (!ret)
1854 msvcrt_stat64_to_stat32i64(&buf64, buf);
1855 return ret;
1858 /*********************************************************************
1859 * _fstat64i32 (MSVCR80.@)
1861 int CDECL MSVCRT__fstat64i32(int fd, struct MSVCRT__stat64i32* buf)
1863 int ret;
1864 struct MSVCRT__stat64 buf64;
1866 ret = MSVCRT__fstat64(fd, &buf64);
1867 if (!ret)
1868 msvcrt_stat64_to_stat64i32(&buf64, buf);
1869 return ret;
1872 /*********************************************************************
1873 * _futime64 (MSVCRT.@)
1875 int CDECL _futime64(int fd, struct MSVCRT___utimbuf64 *t)
1877 ioinfo *info = get_ioinfo(fd);
1878 FILETIME at, wt;
1880 if (!t)
1882 time_to_filetime( MSVCRT__time64(NULL), &at );
1883 wt = at;
1885 else
1887 time_to_filetime( t->actime, &at );
1888 time_to_filetime( t->modtime, &wt );
1891 if (!SetFileTime(info->handle, NULL, &at, &wt))
1893 release_ioinfo(info);
1894 msvcrt_set_errno(GetLastError());
1895 return -1 ;
1897 release_ioinfo(info);
1898 return 0;
1901 /*********************************************************************
1902 * _futime32 (MSVCRT.@)
1904 int CDECL _futime32(int fd, struct MSVCRT___utimbuf32 *t)
1906 if (t)
1908 struct MSVCRT___utimbuf64 t64;
1909 t64.actime = t->actime;
1910 t64.modtime = t->modtime;
1911 return _futime64( fd, &t64 );
1913 else
1914 return _futime64( fd, NULL );
1917 /*********************************************************************
1918 * _futime (MSVCRT.@)
1920 #ifdef _WIN64
1921 int CDECL _futime(int fd, struct MSVCRT___utimbuf64 *t)
1923 return _futime64( fd, t );
1925 #else
1926 int CDECL _futime(int fd, struct MSVCRT___utimbuf32 *t)
1928 return _futime32( fd, t );
1930 #endif
1932 /*********************************************************************
1933 * _get_osfhandle (MSVCRT.@)
1935 MSVCRT_intptr_t CDECL MSVCRT__get_osfhandle(int fd)
1937 HANDLE hand = get_ioinfo_nolock(fd)->handle;
1938 TRACE(":fd (%d) handle (%p)\n",fd,hand);
1940 if(hand == INVALID_HANDLE_VALUE)
1941 *MSVCRT__errno() = MSVCRT_EBADF;
1942 return (MSVCRT_intptr_t)hand;
1945 /*********************************************************************
1946 * _mktemp_s (MSVCRT.@)
1948 int CDECL MSVCRT__mktemp_s(char *pattern, MSVCRT_size_t size)
1950 DWORD len, xno, id;
1952 if(!MSVCRT_CHECK_PMT(pattern!=NULL))
1953 return MSVCRT_EINVAL;
1955 for(len=0; len<size; len++)
1956 if(!pattern[len])
1957 break;
1958 if(!MSVCRT_CHECK_PMT(len!=size && len>=6)) {
1959 if(size)
1960 pattern[0] = 0;
1961 return MSVCRT_EINVAL;
1964 for(xno=1; xno<=6; xno++)
1965 if(!MSVCRT_CHECK_PMT(pattern[len-xno] == 'X'))
1966 return MSVCRT_EINVAL;
1968 id = GetCurrentProcessId();
1969 for(xno=1; xno<6; xno++) {
1970 pattern[len-xno] = id%10 + '0';
1971 id /= 10;
1974 for(pattern[len-6]='a'; pattern[len-6]<='z'; pattern[len-6]++) {
1975 if(GetFileAttributesA(pattern) == INVALID_FILE_ATTRIBUTES)
1976 return 0;
1979 pattern[0] = 0;
1980 *MSVCRT__errno() = MSVCRT_EEXIST;
1981 return MSVCRT_EEXIST;
1984 /*********************************************************************
1985 * _mktemp (MSVCRT.@)
1987 char * CDECL MSVCRT__mktemp(char *pattern)
1989 int numX = 0;
1990 char *retVal = pattern;
1991 int id;
1992 char letter = 'a';
1994 if(!pattern)
1995 return NULL;
1997 while(*pattern)
1998 numX = (*pattern++ == 'X')? numX + 1 : 0;
1999 if (numX < 6)
2000 return NULL;
2001 pattern--;
2002 id = GetCurrentProcessId();
2003 numX = 6;
2004 while(numX--)
2006 int tempNum = id / 10;
2007 *pattern-- = id - (tempNum * 10) + '0';
2008 id = tempNum;
2010 pattern++;
2013 *pattern = letter++;
2014 if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES)
2015 return retVal;
2016 } while(letter <= 'z');
2017 return NULL;
2020 /*********************************************************************
2021 * _wmktemp_s (MSVCRT.@)
2023 int CDECL MSVCRT__wmktemp_s(MSVCRT_wchar_t *pattern, MSVCRT_size_t size)
2025 DWORD len, xno, id;
2027 if(!MSVCRT_CHECK_PMT(pattern!=NULL))
2028 return MSVCRT_EINVAL;
2030 for(len=0; len<size; len++)
2031 if(!pattern[len])
2032 break;
2033 if(!MSVCRT_CHECK_PMT(len!=size && len>=6)) {
2034 if(size)
2035 pattern[0] = 0;
2036 return MSVCRT_EINVAL;
2039 for(xno=1; xno<=6; xno++)
2040 if(!MSVCRT_CHECK_PMT(pattern[len-xno] == 'X'))
2041 return MSVCRT_EINVAL;
2043 id = GetCurrentProcessId();
2044 for(xno=1; xno<6; xno++) {
2045 pattern[len-xno] = id%10 + '0';
2046 id /= 10;
2049 for(pattern[len-6]='a'; pattern[len-6]<='z'; pattern[len-6]++) {
2050 if(GetFileAttributesW(pattern) == INVALID_FILE_ATTRIBUTES)
2051 return 0;
2054 pattern[0] = 0;
2055 *MSVCRT__errno() = MSVCRT_EEXIST;
2056 return MSVCRT_EEXIST;
2059 /*********************************************************************
2060 * _wmktemp (MSVCRT.@)
2062 MSVCRT_wchar_t * CDECL MSVCRT__wmktemp(MSVCRT_wchar_t *pattern)
2064 int numX = 0;
2065 MSVCRT_wchar_t *retVal = pattern;
2066 int id;
2067 MSVCRT_wchar_t letter = 'a';
2069 if(!pattern)
2070 return NULL;
2072 while(*pattern)
2073 numX = (*pattern++ == 'X')? numX + 1 : 0;
2074 if (numX < 6)
2075 return NULL;
2076 pattern--;
2077 id = GetCurrentProcessId();
2078 numX = 6;
2079 while(numX--)
2081 int tempNum = id / 10;
2082 *pattern-- = id - (tempNum * 10) + '0';
2083 id = tempNum;
2085 pattern++;
2088 if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES)
2089 return retVal;
2090 *pattern = letter++;
2091 } while(letter != '|');
2092 return NULL;
2095 static unsigned split_oflags(unsigned oflags)
2097 int wxflags = 0;
2098 unsigned unsupp; /* until we support everything */
2100 if (oflags & MSVCRT__O_APPEND) wxflags |= WX_APPEND;
2101 if (oflags & MSVCRT__O_BINARY) {/* Nothing to do */}
2102 else if (oflags & MSVCRT__O_TEXT) wxflags |= WX_TEXT;
2103 else if (oflags & MSVCRT__O_WTEXT) wxflags |= WX_TEXT;
2104 else if (oflags & MSVCRT__O_U16TEXT) wxflags |= WX_TEXT;
2105 else if (oflags & MSVCRT__O_U8TEXT) wxflags |= WX_TEXT;
2106 else if (*MSVCRT___p__fmode() & MSVCRT__O_BINARY) {/* Nothing to do */}
2107 else wxflags |= WX_TEXT; /* default to TEXT*/
2108 if (oflags & MSVCRT__O_NOINHERIT) wxflags |= WX_DONTINHERIT;
2110 if ((unsupp = oflags & ~(
2111 MSVCRT__O_BINARY|MSVCRT__O_TEXT|MSVCRT__O_APPEND|
2112 MSVCRT__O_TRUNC|MSVCRT__O_EXCL|MSVCRT__O_CREAT|
2113 MSVCRT__O_RDWR|MSVCRT__O_WRONLY|MSVCRT__O_TEMPORARY|
2114 MSVCRT__O_NOINHERIT|
2115 MSVCRT__O_SEQUENTIAL|MSVCRT__O_RANDOM|MSVCRT__O_SHORT_LIVED|
2116 MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT
2118 ERR(":unsupported oflags 0x%04x\n",unsupp);
2120 return wxflags;
2123 /*********************************************************************
2124 * _pipe (MSVCRT.@)
2126 int CDECL MSVCRT__pipe(int *pfds, unsigned int psize, int textmode)
2128 int ret = -1;
2129 SECURITY_ATTRIBUTES sa;
2130 HANDLE readHandle, writeHandle;
2132 if (!pfds)
2134 *MSVCRT__errno() = MSVCRT_EINVAL;
2135 return -1;
2138 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2139 sa.bInheritHandle = !(textmode & MSVCRT__O_NOINHERIT);
2140 sa.lpSecurityDescriptor = NULL;
2141 if (CreatePipe(&readHandle, &writeHandle, &sa, psize))
2143 unsigned int wxflags = split_oflags(textmode);
2144 int fd;
2146 fd = msvcrt_alloc_fd(readHandle, wxflags|WX_PIPE);
2147 if (fd != -1)
2149 pfds[0] = fd;
2150 fd = msvcrt_alloc_fd(writeHandle, wxflags|WX_PIPE);
2151 if (fd != -1)
2153 pfds[1] = fd;
2154 ret = 0;
2156 else
2158 MSVCRT__close(pfds[0]);
2159 CloseHandle(writeHandle);
2160 *MSVCRT__errno() = MSVCRT_EMFILE;
2163 else
2165 CloseHandle(readHandle);
2166 CloseHandle(writeHandle);
2167 *MSVCRT__errno() = MSVCRT_EMFILE;
2170 else
2171 msvcrt_set_errno(GetLastError());
2173 return ret;
2176 static int check_bom(HANDLE h, int oflags, BOOL seek)
2178 char bom[sizeof(utf8_bom)];
2179 DWORD r;
2181 oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
2183 if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
2184 return oflags;
2186 if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
2187 oflags |= MSVCRT__O_U8TEXT;
2188 }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
2189 if (seek && r>2)
2190 SetFilePointer(h, 2, NULL, FILE_BEGIN);
2191 oflags |= MSVCRT__O_U16TEXT;
2192 }else if (seek) {
2193 SetFilePointer(h, 0, NULL, FILE_BEGIN);
2196 return oflags;
2199 /*********************************************************************
2200 * _wsopen_dispatch (UCRTBASE.@)
2202 int CDECL MSVCRT__wsopen_dispatch( const MSVCRT_wchar_t* path, int oflags, int shflags, int pmode,
2203 int *fd, int secure )
2205 DWORD access = 0, creation = 0, attrib;
2206 SECURITY_ATTRIBUTES sa;
2207 DWORD sharing, type;
2208 int wxflag;
2209 HANDLE hand;
2211 TRACE("path: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x fd*: %p secure: %d\n",
2212 debugstr_w(path), oflags, shflags, pmode, fd, secure);
2214 if (!MSVCRT_CHECK_PMT( fd != NULL )) return MSVCRT_EINVAL;
2216 *fd = -1;
2217 wxflag = split_oflags(oflags);
2218 switch (oflags & (MSVCRT__O_RDONLY | MSVCRT__O_WRONLY | MSVCRT__O_RDWR))
2220 case MSVCRT__O_RDONLY: access |= GENERIC_READ; break;
2221 case MSVCRT__O_WRONLY: access |= GENERIC_WRITE; break;
2222 case MSVCRT__O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
2225 if (oflags & MSVCRT__O_CREAT)
2227 if (secure && !MSVCRT_CHECK_PMT(!(pmode & ~(MSVCRT__S_IREAD | MSVCRT__S_IWRITE))))
2228 return MSVCRT_EINVAL;
2230 if (oflags & MSVCRT__O_EXCL)
2231 creation = CREATE_NEW;
2232 else if (oflags & MSVCRT__O_TRUNC)
2233 creation = CREATE_ALWAYS;
2234 else
2235 creation = OPEN_ALWAYS;
2237 else /* no MSVCRT__O_CREAT */
2239 if (oflags & MSVCRT__O_TRUNC)
2240 creation = TRUNCATE_EXISTING;
2241 else
2242 creation = OPEN_EXISTING;
2245 switch( shflags )
2247 case MSVCRT__SH_DENYRW:
2248 sharing = 0L;
2249 break;
2250 case MSVCRT__SH_DENYWR:
2251 sharing = FILE_SHARE_READ;
2252 break;
2253 case MSVCRT__SH_DENYRD:
2254 sharing = FILE_SHARE_WRITE;
2255 break;
2256 case MSVCRT__SH_DENYNO:
2257 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
2258 break;
2259 default:
2260 ERR( "Unhandled shflags 0x%x\n", shflags );
2261 return MSVCRT_EINVAL;
2264 if (!(pmode & ~MSVCRT_umask & MSVCRT__S_IWRITE))
2265 attrib = FILE_ATTRIBUTE_READONLY;
2266 else
2267 attrib = FILE_ATTRIBUTE_NORMAL;
2269 if (oflags & MSVCRT__O_TEMPORARY)
2271 attrib |= FILE_FLAG_DELETE_ON_CLOSE;
2272 access |= DELETE;
2273 sharing |= FILE_SHARE_DELETE;
2276 sa.nLength = sizeof( SECURITY_ATTRIBUTES );
2277 sa.lpSecurityDescriptor = NULL;
2278 sa.bInheritHandle = !(oflags & MSVCRT__O_NOINHERIT);
2280 if ((oflags&(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
2281 && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
2282 && !(access&GENERIC_READ))
2284 hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
2285 &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
2286 if (hand != INVALID_HANDLE_VALUE)
2288 oflags = check_bom(hand, oflags, FALSE);
2289 CloseHandle(hand);
2291 else
2292 oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
2295 hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
2296 if (hand == INVALID_HANDLE_VALUE) {
2297 WARN(":failed-last error (%d)\n",GetLastError());
2298 msvcrt_set_errno(GetLastError());
2299 return *MSVCRT__errno();
2302 if (oflags & (MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
2304 if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
2305 || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
2306 || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
2308 if (oflags & MSVCRT__O_U8TEXT)
2310 DWORD written = 0, tmp;
2312 while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
2313 sizeof(utf8_bom)-written, &tmp, NULL))
2314 written += tmp;
2315 if (written != sizeof(utf8_bom)) {
2316 WARN("error writing BOM\n");
2317 CloseHandle(hand);
2318 msvcrt_set_errno(GetLastError());
2319 return *MSVCRT__errno();
2322 else
2324 DWORD written = 0, tmp;
2326 while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
2327 sizeof(utf16_bom)-written, &tmp, NULL))
2328 written += tmp;
2329 if (written != sizeof(utf16_bom))
2331 WARN("error writing BOM\n");
2332 CloseHandle(hand);
2333 msvcrt_set_errno(GetLastError());
2334 return *MSVCRT__errno();
2338 else if (access & GENERIC_READ)
2339 oflags = check_bom(hand, oflags, TRUE);
2342 type = GetFileType(hand);
2343 if (type == FILE_TYPE_CHAR)
2344 wxflag |= WX_TTY;
2345 else if (type == FILE_TYPE_PIPE)
2346 wxflag |= WX_PIPE;
2348 *fd = msvcrt_alloc_fd(hand, wxflag);
2349 if (*fd == -1)
2350 return *MSVCRT__errno();
2352 if (oflags & MSVCRT__O_WTEXT)
2353 get_ioinfo_nolock(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
2354 else if (oflags & MSVCRT__O_U16TEXT)
2355 get_ioinfo_nolock(*fd)->exflag |= EF_UTF16;
2356 else if (oflags & MSVCRT__O_U8TEXT)
2357 get_ioinfo_nolock(*fd)->exflag |= EF_UTF8;
2359 TRACE(":fd (%d) handle (%p)\n", *fd, hand);
2360 return 0;
2364 /*********************************************************************
2365 * _wsopen_s (MSVCRT.@)
2367 int CDECL MSVCRT__wsopen_s( int *fd, const MSVCRT_wchar_t* path, int oflags, int shflags, int pmode )
2369 return MSVCRT__wsopen_dispatch( path, oflags, shflags, pmode, fd, 1 );
2372 /*********************************************************************
2373 * _wsopen (MSVCRT.@)
2375 int WINAPIV MSVCRT__wsopen( const MSVCRT_wchar_t *path, int oflags, int shflags, ... )
2377 int pmode;
2378 int fd;
2380 if (oflags & MSVCRT__O_CREAT)
2382 __ms_va_list ap;
2384 __ms_va_start(ap, shflags);
2385 pmode = va_arg(ap, int);
2386 __ms_va_end(ap);
2388 else
2389 pmode = 0;
2391 return MSVCRT__wsopen_dispatch(path, oflags, shflags, pmode, &fd, 0) ? -1 : fd;
2395 /*********************************************************************
2396 * _sopen_dispatch (UCRTBASE.@)
2398 int CDECL MSVCRT__sopen_dispatch( const char *path, int oflags, int shflags,
2399 int pmode, int *fd, int secure)
2401 MSVCRT_wchar_t *pathW;
2402 int ret;
2404 if (!MSVCRT_CHECK_PMT(fd != NULL))
2405 return MSVCRT_EINVAL;
2406 *fd = -1;
2407 if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path))))
2408 return MSVCRT_EINVAL;
2410 ret = MSVCRT__wsopen_dispatch(pathW, oflags, shflags, pmode, fd, secure);
2411 MSVCRT_free(pathW);
2412 return ret;
2415 /*********************************************************************
2416 * _sopen_s (MSVCRT.@)
2418 int CDECL MSVCRT__sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
2420 return MSVCRT__sopen_dispatch(path, oflags, shflags, pmode, fd, 1);
2423 /*********************************************************************
2424 * _sopen (MSVCRT.@)
2426 int WINAPIV MSVCRT__sopen( const char *path, int oflags, int shflags, ... )
2428 int pmode;
2429 int fd;
2431 if (oflags & MSVCRT__O_CREAT)
2433 __ms_va_list ap;
2435 __ms_va_start(ap, shflags);
2436 pmode = va_arg(ap, int);
2437 __ms_va_end(ap);
2439 else
2440 pmode = 0;
2442 return MSVCRT__sopen_dispatch(path, oflags, shflags, pmode, &fd, 0) ? -1 : fd;
2445 /*********************************************************************
2446 * _open (MSVCRT.@)
2448 int WINAPIV MSVCRT__open( const char *path, int flags, ... )
2450 __ms_va_list ap;
2452 if (flags & MSVCRT__O_CREAT)
2454 int pmode;
2455 __ms_va_start(ap, flags);
2456 pmode = va_arg(ap, int);
2457 __ms_va_end(ap);
2458 return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO, pmode );
2460 else
2461 return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO);
2464 /*********************************************************************
2465 * _wopen (MSVCRT.@)
2467 int WINAPIV MSVCRT__wopen(const MSVCRT_wchar_t *path,int flags,...)
2469 __ms_va_list ap;
2471 if (flags & MSVCRT__O_CREAT)
2473 int pmode;
2474 __ms_va_start(ap, flags);
2475 pmode = va_arg(ap, int);
2476 __ms_va_end(ap);
2477 return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO, pmode );
2479 else
2480 return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO);
2483 /*********************************************************************
2484 * _creat (MSVCRT.@)
2486 int CDECL MSVCRT__creat(const char *path, int pmode)
2488 int flags = MSVCRT__O_CREAT | MSVCRT__O_TRUNC | MSVCRT__O_RDWR;
2489 return MSVCRT__open(path, flags, pmode);
2492 /*********************************************************************
2493 * _wcreat (MSVCRT.@)
2495 int CDECL MSVCRT__wcreat(const MSVCRT_wchar_t *path, int pmode)
2497 int flags = MSVCRT__O_CREAT | MSVCRT__O_TRUNC | MSVCRT__O_RDWR;
2498 return MSVCRT__wopen(path, flags, pmode);
2501 /*********************************************************************
2502 * _open_osfhandle (MSVCRT.@)
2504 int CDECL MSVCRT__open_osfhandle(MSVCRT_intptr_t handle, int oflags)
2506 DWORD flags;
2507 int fd;
2509 /* MSVCRT__O_RDONLY (0) always matches, so set the read flag
2510 * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
2511 * file, so set the write flag. It also only sets MSVCRT__O_TEXT if it wants
2512 * text - it never sets MSVCRT__O_BINARY.
2514 /* don't let split_oflags() decide the mode if no mode is passed */
2515 if (!(oflags & (MSVCRT__O_BINARY | MSVCRT__O_TEXT)))
2516 oflags |= MSVCRT__O_BINARY;
2518 flags = GetFileType((HANDLE)handle);
2519 if (flags==FILE_TYPE_UNKNOWN && GetLastError()!=NO_ERROR)
2521 msvcrt_set_errno(GetLastError());
2522 return -1;
2525 if (flags == FILE_TYPE_CHAR)
2526 flags = WX_TTY;
2527 else if (flags == FILE_TYPE_PIPE)
2528 flags = WX_PIPE;
2529 else
2530 flags = 0;
2531 flags |= split_oflags(oflags);
2533 fd = msvcrt_alloc_fd((HANDLE)handle, flags);
2534 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, flags);
2535 return fd;
2538 /*********************************************************************
2539 * _rmtmp (MSVCRT.@)
2541 int CDECL MSVCRT__rmtmp(void)
2543 int num_removed = 0, i;
2544 MSVCRT_FILE *file;
2546 LOCK_FILES();
2547 for (i = 3; i < MSVCRT_stream_idx; i++) {
2548 file = msvcrt_get_file(i);
2550 if (file->_tmpfname)
2552 MSVCRT_fclose(file);
2553 num_removed++;
2556 UNLOCK_FILES();
2558 if (num_removed)
2559 TRACE(":removed (%d) temp files\n",num_removed);
2560 return num_removed;
2563 static inline int get_utf8_char_len(char ch)
2565 if((ch&0xf8) == 0xf0)
2566 return 4;
2567 else if((ch&0xf0) == 0xe0)
2568 return 3;
2569 else if((ch&0xe0) == 0xc0)
2570 return 2;
2571 return 1;
2574 /*********************************************************************
2575 * (internal) read_utf8
2577 static int read_utf8(ioinfo *fdinfo, MSVCRT_wchar_t *buf, unsigned int count)
2579 HANDLE hand = fdinfo->handle;
2580 char min_buf[4], *readbuf, lookahead;
2581 DWORD readbuf_size, pos=0, num_read=1, char_len, i, j;
2583 /* make the buffer big enough to hold at least one character */
2584 /* read bytes have to fit to output and lookahead buffers */
2585 count /= 2;
2586 readbuf_size = count < 4 ? 4 : count;
2587 if(readbuf_size<=4 || !(readbuf = MSVCRT_malloc(readbuf_size))) {
2588 readbuf_size = 4;
2589 readbuf = min_buf;
2592 if(fdinfo->lookahead[0] != '\n') {
2593 readbuf[pos++] = fdinfo->lookahead[0];
2594 fdinfo->lookahead[0] = '\n';
2596 if(fdinfo->lookahead[1] != '\n') {
2597 readbuf[pos++] = fdinfo->lookahead[1];
2598 fdinfo->lookahead[1] = '\n';
2600 if(fdinfo->lookahead[2] != '\n') {
2601 readbuf[pos++] = fdinfo->lookahead[2];
2602 fdinfo->lookahead[2] = '\n';
2607 /* NOTE: this case is broken in native dll, reading
2608 * sometimes fails when small buffer is passed
2610 if(count < 4) {
2611 if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) {
2612 if (GetLastError() == ERROR_BROKEN_PIPE) {
2613 fdinfo->wxflag |= WX_ATEOF;
2614 return 0;
2615 }else {
2616 msvcrt_set_errno(GetLastError());
2617 return -1;
2619 }else if(!num_read) {
2620 fdinfo->wxflag |= WX_ATEOF;
2621 return 0;
2622 }else {
2623 pos++;
2626 char_len = get_utf8_char_len(readbuf[0]);
2627 if(char_len>pos) {
2628 if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL))
2629 pos += num_read;
2632 if(readbuf[0] == '\n')
2633 fdinfo->wxflag |= WX_READNL;
2634 else
2635 fdinfo->wxflag &= ~WX_READNL;
2637 if(readbuf[0] == 0x1a) {
2638 fdinfo->wxflag |= WX_ATEOF;
2639 return 0;
2642 if(readbuf[0] == '\r') {
2643 if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1)
2644 buf[0] = '\r';
2645 else if(lookahead == '\n')
2646 buf[0] = '\n';
2647 else {
2648 buf[0] = '\r';
2649 if(fdinfo->wxflag & (WX_PIPE | WX_TTY))
2650 fdinfo->lookahead[0] = lookahead;
2651 else
2652 SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2654 return 2;
2657 if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2658 msvcrt_set_errno(GetLastError());
2659 return -1;
2662 return num_read*2;
2665 if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) {
2666 if(pos) {
2667 num_read = 0;
2668 }else if(GetLastError() == ERROR_BROKEN_PIPE) {
2669 fdinfo->wxflag |= WX_ATEOF;
2670 if (readbuf != min_buf) MSVCRT_free(readbuf);
2671 return 0;
2672 }else {
2673 msvcrt_set_errno(GetLastError());
2674 if (readbuf != min_buf) MSVCRT_free(readbuf);
2675 return -1;
2677 }else if(!pos && !num_read) {
2678 fdinfo->wxflag |= WX_ATEOF;
2679 if (readbuf != min_buf) MSVCRT_free(readbuf);
2680 return 0;
2683 pos += num_read;
2684 if(readbuf[0] == '\n')
2685 fdinfo->wxflag |= WX_READNL;
2686 else
2687 fdinfo->wxflag &= ~WX_READNL;
2689 /* Find first byte of last character (may be incomplete) */
2690 for(i=pos-1; i>0 && i>pos-4; i--)
2691 if((readbuf[i]&0xc0) != 0x80)
2692 break;
2693 char_len = get_utf8_char_len(readbuf[i]);
2694 if(char_len+i <= pos)
2695 i += char_len;
2697 if(fdinfo->wxflag & (WX_PIPE | WX_TTY)) {
2698 if(i < pos)
2699 fdinfo->lookahead[0] = readbuf[i];
2700 if(i+1 < pos)
2701 fdinfo->lookahead[1] = readbuf[i+1];
2702 if(i+2 < pos)
2703 fdinfo->lookahead[2] = readbuf[i+2];
2704 }else if(i < pos) {
2705 SetFilePointer(fdinfo->handle, i-pos, NULL, FILE_CURRENT);
2707 pos = i;
2709 for(i=0, j=0; i<pos; i++) {
2710 if(readbuf[i] == 0x1a) {
2711 fdinfo->wxflag |= WX_ATEOF;
2712 break;
2715 /* strip '\r' if followed by '\n' */
2716 if(readbuf[i] == '\r' && i+1==pos) {
2717 if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) {
2718 readbuf[j++] = '\r';
2719 }else if(lookahead == '\n' && j==0) {
2720 readbuf[j++] = '\n';
2721 }else {
2722 if(lookahead != '\n')
2723 readbuf[j++] = '\r';
2725 if(fdinfo->wxflag & (WX_PIPE | WX_TTY))
2726 fdinfo->lookahead[0] = lookahead;
2727 else
2728 SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2730 }else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') {
2731 readbuf[j++] = readbuf[i];
2734 pos = j;
2736 if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2737 msvcrt_set_errno(GetLastError());
2738 if (readbuf != min_buf) MSVCRT_free(readbuf);
2739 return -1;
2742 if (readbuf != min_buf) MSVCRT_free(readbuf);
2743 return num_read*2;
2746 /*********************************************************************
2747 * (internal) read_i
2749 * When reading \r as last character in text mode, read() positions
2750 * the file pointer on the \r character while getc() goes on to
2751 * the following \n
2753 static int read_i(int fd, ioinfo *fdinfo, void *buf, unsigned int count)
2755 DWORD num_read, utf16;
2756 char *bufstart = buf;
2758 if (count == 0)
2759 return 0;
2761 if (fdinfo->wxflag & WX_ATEOF) {
2762 TRACE("already at EOF, returning 0\n");
2763 return 0;
2765 /* Don't trace small reads, it gets *very* annoying */
2766 if (count > 4)
2767 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n", fd, fdinfo->handle, buf, count);
2768 if (fdinfo->handle == INVALID_HANDLE_VALUE)
2770 *MSVCRT__errno() = MSVCRT_EBADF;
2771 return -1;
2774 utf16 = (fdinfo->exflag & EF_UTF16) != 0;
2775 if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
2777 *MSVCRT__errno() = MSVCRT_EINVAL;
2778 return -1;
2781 if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
2782 return read_utf8(fdinfo, buf, count);
2784 if (fdinfo->lookahead[0]!='\n' || ReadFile(fdinfo->handle, bufstart, count, &num_read, NULL))
2786 if (fdinfo->lookahead[0] != '\n')
2788 bufstart[0] = fdinfo->lookahead[0];
2789 fdinfo->lookahead[0] = '\n';
2791 if (utf16)
2793 bufstart[1] = fdinfo->lookahead[1];
2794 fdinfo->lookahead[1] = '\n';
2797 if(count>1+utf16 && ReadFile(fdinfo->handle, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
2798 num_read += 1+utf16;
2799 else
2800 num_read = 1+utf16;
2803 if(utf16 && (num_read&1))
2805 /* msvcr90 uses uninitialized value from the buffer in this case */
2806 /* msvcrt ignores additional data */
2807 ERR("got odd number of bytes in UTF16 mode\n");
2808 num_read--;
2811 if (count != 0 && num_read == 0)
2813 fdinfo->wxflag |= WX_ATEOF;
2814 TRACE(":EOF %s\n",debugstr_an(buf,num_read));
2816 else if (fdinfo->wxflag & WX_TEXT)
2818 DWORD i, j;
2820 if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
2821 fdinfo->wxflag |= WX_READNL;
2822 else
2823 fdinfo->wxflag &= ~WX_READNL;
2825 for (i=0, j=0; i<num_read; i+=1+utf16)
2827 /* in text mode, a ctrl-z signals EOF */
2828 if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
2830 fdinfo->wxflag |= WX_ATEOF;
2831 TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
2832 break;
2835 /* in text mode, strip \r if followed by \n */
2836 if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
2838 char lookahead[2];
2839 DWORD len;
2841 lookahead[1] = '\n';
2842 if (ReadFile(fdinfo->handle, lookahead, 1+utf16, &len, NULL) && len)
2844 if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
2846 bufstart[j++] = '\n';
2847 if(utf16) bufstart[j++] = 0;
2849 else
2851 if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
2853 bufstart[j++] = '\r';
2854 if(utf16) bufstart[j++] = 0;
2857 if (fdinfo->wxflag & (WX_PIPE | WX_TTY))
2859 if (lookahead[0]=='\n' && (!utf16 || !lookahead[1]))
2861 bufstart[j++] = '\n';
2862 if (utf16) bufstart[j++] = 0;
2864 else
2866 fdinfo->lookahead[0] = lookahead[0];
2867 fdinfo->lookahead[1] = lookahead[1];
2870 else
2871 SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
2874 else
2876 bufstart[j++] = '\r';
2877 if(utf16) bufstart[j++] = 0;
2880 else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
2881 || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
2883 bufstart[j++] = bufstart[i];
2884 if(utf16) bufstart[j++] = bufstart[i+1];
2887 num_read = j;
2890 else
2892 if (GetLastError() == ERROR_BROKEN_PIPE)
2894 TRACE(":end-of-pipe\n");
2895 fdinfo->wxflag |= WX_ATEOF;
2896 return 0;
2898 else
2900 TRACE(":failed-last error (%d)\n",GetLastError());
2901 msvcrt_set_errno(GetLastError());
2902 return -1;
2906 if (count > 4)
2907 TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
2908 return num_read;
2911 /*********************************************************************
2912 * _read (MSVCRT.@)
2914 int CDECL MSVCRT__read(int fd, void *buf, unsigned int count)
2916 ioinfo *info;
2917 int num_read;
2919 if(fd == MSVCRT_NO_CONSOLE_FD) {
2920 *MSVCRT__errno() = MSVCRT_EBADF;
2921 return -1;
2924 info = get_ioinfo(fd);
2925 num_read = read_i(fd, info, buf, count);
2926 release_ioinfo(info);
2927 return num_read;
2930 /*********************************************************************
2931 * _setmode (MSVCRT.@)
2933 int CDECL MSVCRT__setmode(int fd,int mode)
2935 ioinfo *info = get_ioinfo(fd);
2936 int ret = info->wxflag & WX_TEXT ? MSVCRT__O_TEXT : MSVCRT__O_BINARY;
2937 if(ret==MSVCRT__O_TEXT && (info->exflag & (EF_UTF8|EF_UTF16)))
2938 ret = MSVCRT__O_WTEXT;
2940 if(mode!=MSVCRT__O_TEXT && mode!=MSVCRT__O_BINARY && mode!=MSVCRT__O_WTEXT
2941 && mode!=MSVCRT__O_U16TEXT && mode!=MSVCRT__O_U8TEXT) {
2942 *MSVCRT__errno() = MSVCRT_EINVAL;
2943 release_ioinfo(info);
2944 return -1;
2947 if(info == &MSVCRT___badioinfo) {
2948 *MSVCRT__errno() = MSVCRT_EBADF;
2949 return MSVCRT_EOF;
2952 if(mode == MSVCRT__O_BINARY) {
2953 info->wxflag &= ~WX_TEXT;
2954 info->exflag &= ~(EF_UTF8|EF_UTF16);
2955 release_ioinfo(info);
2956 return ret;
2959 info->wxflag |= WX_TEXT;
2960 if(mode == MSVCRT__O_TEXT)
2961 info->exflag &= ~(EF_UTF8|EF_UTF16);
2962 else if(mode == MSVCRT__O_U8TEXT)
2963 info->exflag = (info->exflag & ~EF_UTF16) | EF_UTF8;
2964 else
2965 info->exflag = (info->exflag & ~EF_UTF8) | EF_UTF16;
2967 release_ioinfo(info);
2968 return ret;
2971 /*********************************************************************
2972 * _stat64 (MSVCRT.@)
2974 int CDECL MSVCRT_stat64(const char* path, struct MSVCRT__stat64 * buf)
2976 DWORD dw;
2977 WIN32_FILE_ATTRIBUTE_DATA hfi;
2978 unsigned short mode = ALL_S_IREAD;
2979 int plen;
2981 TRACE(":file (%s) buf(%p)\n",path,buf);
2983 plen = strlen(path);
2984 while (plen && path[plen-1]==' ')
2985 plen--;
2987 if (plen==2 && path[1]==':')
2989 *MSVCRT__errno() = MSVCRT_ENOENT;
2990 return -1;
2993 #if _MSVCR_VER<140
2994 if (plen>=2 && path[plen-2]!=':' && (path[plen-1]=='\\' || path[plen-1]=='/'))
2996 *MSVCRT__errno() = MSVCRT_ENOENT;
2997 return -1;
2999 #endif
3001 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi))
3003 TRACE("failed (%d)\n",GetLastError());
3004 *MSVCRT__errno() = MSVCRT_ENOENT;
3005 return -1;
3008 memset(buf,0,sizeof(struct MSVCRT__stat64));
3010 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
3011 Bon 011120: This FIXME seems incorrect
3012 Also a letter as first char isn't enough to be classified
3013 as a drive letter
3015 if (isalpha(*path)&& (*(path+1)==':'))
3016 buf->st_dev = buf->st_rdev = MSVCRT__toupper_l(*path, NULL) - 'A'; /* drive num */
3017 else
3018 buf->st_dev = buf->st_rdev = MSVCRT__getdrive() - 1;
3020 /* Dir, or regular file? */
3021 if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
3022 mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
3023 else
3025 mode |= MSVCRT__S_IFREG;
3026 /* executable? */
3027 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
3029 unsigned int ext = MSVCRT__tolower_l(path[plen-1], NULL) |
3030 (MSVCRT__tolower_l(path[plen-2], NULL) << 8) |
3031 (MSVCRT__tolower_l(path[plen-3], NULL) << 16);
3032 if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
3033 mode |= ALL_S_IEXEC;
3037 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
3038 mode |= ALL_S_IWRITE;
3040 buf->st_mode = mode;
3041 buf->st_nlink = 1;
3042 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
3043 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
3044 buf->st_atime = dw;
3045 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
3046 buf->st_mtime = buf->st_ctime = dw;
3047 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
3048 (int)(buf->st_size >> 32),(int)buf->st_size,
3049 (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
3050 return 0;
3053 /*********************************************************************
3054 * _stati64 (MSVCRT.@)
3056 int CDECL MSVCRT_stati64(const char* path, struct MSVCRT__stati64 * buf)
3058 int ret;
3059 struct MSVCRT__stat64 buf64;
3061 ret = MSVCRT_stat64(path, &buf64);
3062 if (!ret)
3063 msvcrt_stat64_to_stati64(&buf64, buf);
3064 return ret;
3067 /*********************************************************************
3068 * _stat (MSVCRT.@)
3070 int CDECL MSVCRT_stat(const char* path, struct MSVCRT__stat * buf)
3072 int ret;
3073 struct MSVCRT__stat64 buf64;
3075 ret = MSVCRT_stat64( path, &buf64);
3076 if (!ret)
3077 msvcrt_stat64_to_stat(&buf64, buf);
3078 return ret;
3081 #if _MSVCR_VER >= 80
3083 /*********************************************************************
3084 * _stat32 (MSVCR80.@)
3086 int CDECL MSVCRT__stat32(const char *path, struct MSVCRT__stat32 *buf)
3088 int ret;
3089 struct MSVCRT__stat64 buf64;
3091 ret = MSVCRT_stat64(path, &buf64);
3092 if (!ret)
3093 msvcrt_stat64_to_stat32(&buf64, buf);
3094 return ret;
3097 /*********************************************************************
3098 * _stat32i64 (MSVCR80.@)
3100 int CDECL MSVCRT__stat32i64(const char *path, struct MSVCRT__stat32i64 *buf)
3102 int ret;
3103 struct MSVCRT__stat64 buf64;
3105 ret = MSVCRT_stat64(path, &buf64);
3106 if (!ret)
3107 msvcrt_stat64_to_stat32i64(&buf64, buf);
3108 return ret;
3111 /*********************************************************************
3112 * _stat64i32 (MSVCR80.@)
3114 int CDECL MSVCRT__stat64i32(const char* path, struct MSVCRT__stat64i32 *buf)
3116 int ret;
3117 struct MSVCRT__stat64 buf64;
3119 ret = MSVCRT_stat64(path, &buf64);
3120 if (!ret)
3121 msvcrt_stat64_to_stat64i32(&buf64, buf);
3122 return ret;
3125 #endif /* _MSVCR_VER >= 80 */
3127 /*********************************************************************
3128 * _wstat64 (MSVCRT.@)
3130 int CDECL MSVCRT__wstat64(const MSVCRT_wchar_t* path, struct MSVCRT__stat64 * buf)
3132 DWORD dw;
3133 WIN32_FILE_ATTRIBUTE_DATA hfi;
3134 unsigned short mode = ALL_S_IREAD;
3135 int plen;
3137 TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf);
3139 plen = strlenW(path);
3140 while (plen && path[plen-1]==' ')
3141 plen--;
3143 if (plen==2 && path[1]==':')
3145 *MSVCRT__errno() = MSVCRT_ENOENT;
3146 return -1;
3149 #if _MSVCR_VER<140
3150 if (plen>=2 && path[plen-2]!=':' && (path[plen-1]=='\\' || path[plen-1]=='/'))
3152 *MSVCRT__errno() = MSVCRT_ENOENT;
3153 return -1;
3155 #endif
3157 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi))
3159 TRACE("failed (%d)\n",GetLastError());
3160 *MSVCRT__errno() = MSVCRT_ENOENT;
3161 return -1;
3164 memset(buf,0,sizeof(struct MSVCRT__stat64));
3166 /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
3167 if (MSVCRT_iswalpha(*path) && path[1] == ':')
3168 buf->st_dev = buf->st_rdev = toupperW(*path) - 'A'; /* drive num */
3169 else
3170 buf->st_dev = buf->st_rdev = MSVCRT__getdrive() - 1;
3172 /* Dir, or regular file? */
3173 if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
3174 mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
3175 else
3177 mode |= MSVCRT__S_IFREG;
3178 /* executable? */
3179 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
3181 ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) |
3182 ((ULONGLONG)tolowerW(path[plen-3]) << 32);
3183 if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM)
3184 mode |= ALL_S_IEXEC;
3188 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
3189 mode |= ALL_S_IWRITE;
3191 buf->st_mode = mode;
3192 buf->st_nlink = 1;
3193 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
3194 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
3195 buf->st_atime = dw;
3196 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
3197 buf->st_mtime = buf->st_ctime = dw;
3198 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
3199 (int)(buf->st_size >> 32),(int)buf->st_size,
3200 (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
3201 return 0;
3204 /*********************************************************************
3205 * _wstati64 (MSVCRT.@)
3207 int CDECL MSVCRT__wstati64(const MSVCRT_wchar_t* path, struct MSVCRT__stati64 * buf)
3209 int ret;
3210 struct MSVCRT__stat64 buf64;
3212 ret = MSVCRT__wstat64(path, &buf64);
3213 if (!ret)
3214 msvcrt_stat64_to_stati64(&buf64, buf);
3215 return ret;
3218 /*********************************************************************
3219 * _wstat (MSVCRT.@)
3221 int CDECL MSVCRT__wstat(const MSVCRT_wchar_t* path, struct MSVCRT__stat * buf)
3223 int ret;
3224 struct MSVCRT__stat64 buf64;
3226 ret = MSVCRT__wstat64( path, &buf64 );
3227 if (!ret) msvcrt_stat64_to_stat(&buf64, buf);
3228 return ret;
3231 #if _MSVCR_VER >= 80
3233 /*********************************************************************
3234 * _wstat32 (MSVCR80.@)
3236 int CDECL MSVCRT__wstat32(const MSVCRT_wchar_t *path, struct MSVCRT__stat32 *buf)
3238 int ret;
3239 struct MSVCRT__stat64 buf64;
3241 ret = MSVCRT__wstat64(path, &buf64);
3242 if (!ret)
3243 msvcrt_stat64_to_stat32(&buf64, buf);
3244 return ret;
3247 /*********************************************************************
3248 * _wstat32i64 (MSVCR80.@)
3250 int CDECL MSVCRT__wstat32i64(const MSVCRT_wchar_t *path, struct MSVCRT__stat32i64 *buf)
3252 int ret;
3253 struct MSVCRT__stat64 buf64;
3255 ret = MSVCRT__wstat64(path, &buf64);
3256 if (!ret)
3257 msvcrt_stat64_to_stat32i64(&buf64, buf);
3258 return ret;
3261 /*********************************************************************
3262 * _wstat64i32 (MSVCR80.@)
3264 int CDECL MSVCRT__wstat64i32(const MSVCRT_wchar_t *path, struct MSVCRT__stat64i32 *buf)
3266 int ret;
3267 struct MSVCRT__stat64 buf64;
3269 ret = MSVCRT__wstat64(path, &buf64);
3270 if (!ret)
3271 msvcrt_stat64_to_stat64i32(&buf64, buf);
3272 return ret;
3275 #endif /* _MSVCR_VER >= 80 */
3277 /*********************************************************************
3278 * _tell (MSVCRT.@)
3280 MSVCRT_long CDECL MSVCRT__tell(int fd)
3282 return MSVCRT__lseek(fd, 0, MSVCRT_SEEK_CUR);
3285 /*********************************************************************
3286 * _telli64 (MSVCRT.@)
3288 __int64 CDECL _telli64(int fd)
3290 return MSVCRT__lseeki64(fd, 0, MSVCRT_SEEK_CUR);
3293 /*********************************************************************
3294 * _tempnam (MSVCRT.@)
3296 char * CDECL MSVCRT__tempnam(const char *dir, const char *prefix)
3298 char tmpbuf[MAX_PATH];
3299 const char *tmp_dir = MSVCRT_getenv("TMP");
3301 if (tmp_dir) dir = tmp_dir;
3303 TRACE("dir (%s) prefix (%s)\n",dir,prefix);
3304 if (GetTempFileNameA(dir,prefix,0,tmpbuf))
3306 TRACE("got name (%s)\n",tmpbuf);
3307 DeleteFileA(tmpbuf);
3308 return MSVCRT__strdup(tmpbuf);
3310 TRACE("failed (%d)\n",GetLastError());
3311 return NULL;
3314 /*********************************************************************
3315 * _wtempnam (MSVCRT.@)
3317 MSVCRT_wchar_t * CDECL MSVCRT__wtempnam(const MSVCRT_wchar_t *dir, const MSVCRT_wchar_t *prefix)
3319 static const MSVCRT_wchar_t tmpW[] = {'T','M','P',0};
3320 MSVCRT_wchar_t tmpbuf[MAX_PATH];
3321 const MSVCRT_wchar_t *tmp_dir = MSVCRT__wgetenv(tmpW);
3323 if (tmp_dir) dir = tmp_dir;
3325 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
3326 if (GetTempFileNameW(dir,prefix,0,tmpbuf))
3328 TRACE("got name (%s)\n",debugstr_w(tmpbuf));
3329 DeleteFileW(tmpbuf);
3330 return MSVCRT__wcsdup(tmpbuf);
3332 TRACE("failed (%d)\n",GetLastError());
3333 return NULL;
3336 /*********************************************************************
3337 * _umask (MSVCRT.@)
3339 int CDECL MSVCRT__umask(int umask)
3341 int old_umask = MSVCRT_umask;
3342 TRACE("(%d)\n",umask);
3343 MSVCRT_umask = umask;
3344 return old_umask;
3347 /*********************************************************************
3348 * _utime64 (MSVCRT.@)
3350 int CDECL _utime64(const char* path, struct MSVCRT___utimbuf64 *t)
3352 int fd = MSVCRT__open(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
3354 if (fd > 0)
3356 int retVal = _futime64(fd, t);
3357 MSVCRT__close(fd);
3358 return retVal;
3360 return -1;
3363 /*********************************************************************
3364 * _utime32 (MSVCRT.@)
3366 int CDECL _utime32(const char* path, struct MSVCRT___utimbuf32 *t)
3368 if (t)
3370 struct MSVCRT___utimbuf64 t64;
3371 t64.actime = t->actime;
3372 t64.modtime = t->modtime;
3373 return _utime64( path, &t64 );
3375 else
3376 return _utime64( path, NULL );
3379 /*********************************************************************
3380 * _utime (MSVCRT.@)
3382 #ifdef _WIN64
3383 int CDECL _utime(const char* path, struct MSVCRT___utimbuf64 *t)
3385 return _utime64( path, t );
3387 #else
3388 int CDECL _utime(const char* path, struct MSVCRT___utimbuf32 *t)
3390 return _utime32( path, t );
3392 #endif
3394 /*********************************************************************
3395 * _wutime64 (MSVCRT.@)
3397 int CDECL _wutime64(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
3399 int fd = MSVCRT__wopen(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
3401 if (fd > 0)
3403 int retVal = _futime64(fd, t);
3404 MSVCRT__close(fd);
3405 return retVal;
3407 return -1;
3410 /*********************************************************************
3411 * _wutime32 (MSVCRT.@)
3413 int CDECL _wutime32(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
3415 if (t)
3417 struct MSVCRT___utimbuf64 t64;
3418 t64.actime = t->actime;
3419 t64.modtime = t->modtime;
3420 return _wutime64( path, &t64 );
3422 else
3423 return _wutime64( path, NULL );
3426 /*********************************************************************
3427 * _wutime (MSVCRT.@)
3429 #ifdef _WIN64
3430 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
3432 return _wutime64( path, t );
3434 #else
3435 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
3437 return _wutime32( path, t );
3439 #endif
3441 /*********************************************************************
3442 * _write (MSVCRT.@)
3444 int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count)
3446 DWORD num_written;
3447 ioinfo *info = get_ioinfo(fd);
3448 HANDLE hand = info->handle;
3450 /* Don't trace small writes, it gets *very* annoying */
3451 #if 0
3452 if (count > 32)
3453 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
3454 #endif
3455 if (hand == INVALID_HANDLE_VALUE || fd == MSVCRT_NO_CONSOLE_FD)
3457 *MSVCRT__errno() = MSVCRT_EBADF;
3458 release_ioinfo(info);
3459 return -1;
3462 if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
3464 *MSVCRT__errno() = MSVCRT_EINVAL;
3465 release_ioinfo(info);
3466 return -1;
3469 /* If appending, go to EOF */
3470 if (info->wxflag & WX_APPEND)
3471 MSVCRT__lseek(fd, 0, FILE_END);
3473 if (!(info->wxflag & WX_TEXT))
3475 if (WriteFile(hand, buf, count, &num_written, NULL)
3476 && (num_written == count))
3478 release_ioinfo(info);
3479 return num_written;
3481 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
3482 hand, GetLastError());
3483 msvcrt_set_errno(GetLastError());
3485 else
3487 unsigned int i, j, nr_lf, size;
3488 char *p = NULL;
3489 const char *q;
3490 const char *s = buf;
3492 if (!(info->exflag & (EF_UTF8|EF_UTF16)))
3494 /* find number of \n */
3495 for (nr_lf=0, i=0; i<count; i++)
3496 if (s[i] == '\n')
3497 nr_lf++;
3498 if (nr_lf)
3500 size = count+nr_lf;
3501 if ((q = p = MSVCRT_malloc(size)))
3503 for (s = buf, i = 0, j = 0; i < count; i++)
3505 if (s[i] == '\n')
3506 p[j++] = '\r';
3507 p[j++] = s[i];
3510 else
3512 FIXME("Malloc failed\n");
3513 nr_lf = 0;
3514 size = count;
3515 q = buf;
3518 else
3520 size = count;
3521 q = buf;
3524 else if (info->exflag & EF_UTF16)
3526 for (nr_lf=0, i=0; i<count; i+=2)
3527 if (s[i]=='\n' && s[i+1]==0)
3528 nr_lf += 2;
3529 if (nr_lf)
3531 size = count+nr_lf;
3532 if ((q = p = MSVCRT_malloc(size)))
3534 for (s=buf, i=0, j=0; i<count; i++)
3536 if (s[i]=='\n' && s[i+1]==0)
3538 p[j++] = '\r';
3539 p[j++] = 0;
3541 p[j++] = s[i++];
3542 p[j++] = s[i];
3545 else
3547 FIXME("Malloc failed\n");
3548 nr_lf = 0;
3549 size = count;
3550 q = buf;
3553 else
3555 size = count;
3556 q = buf;
3559 else
3561 DWORD conv_len;
3563 for(nr_lf=0, i=0; i<count; i+=2)
3564 if (s[i]=='\n' && s[i+1]==0)
3565 nr_lf++;
3567 conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
3568 if(!conv_len) {
3569 msvcrt_set_errno(GetLastError());
3570 MSVCRT_free(p);
3571 release_ioinfo(info);
3572 return -1;
3575 size = conv_len+nr_lf;
3576 if((p = MSVCRT_malloc(count+nr_lf*2+size)))
3578 for (s=buf, i=0, j=0; i<count; i++)
3580 if (s[i]=='\n' && s[i+1]==0)
3582 p[j++] = '\r';
3583 p[j++] = 0;
3585 p[j++] = s[i++];
3586 p[j++] = s[i];
3588 q = p+count+nr_lf*2;
3589 WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
3590 p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
3592 else
3594 FIXME("Malloc failed\n");
3595 nr_lf = 0;
3596 size = count;
3597 q = buf;
3601 if (!WriteFile(hand, q, size, &num_written, NULL))
3602 num_written = -1;
3603 release_ioinfo(info);
3604 MSVCRT_free(p);
3605 if (num_written != size)
3607 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
3608 fd, hand, GetLastError(), num_written);
3609 msvcrt_set_errno(GetLastError());
3610 return -1;
3612 return count;
3615 release_ioinfo(info);
3616 return -1;
3619 /*********************************************************************
3620 * _putw (MSVCRT.@)
3622 int CDECL MSVCRT__putw(int val, MSVCRT_FILE* file)
3624 int len;
3626 MSVCRT__lock_file(file);
3627 len = MSVCRT__write(file->_file, &val, sizeof(val));
3628 if (len == sizeof(val)) {
3629 MSVCRT__unlock_file(file);
3630 return val;
3633 file->_flag |= MSVCRT__IOERR;
3634 MSVCRT__unlock_file(file);
3635 return MSVCRT_EOF;
3638 /*********************************************************************
3639 * fclose (MSVCRT.@)
3641 int CDECL MSVCRT_fclose(MSVCRT_FILE* file)
3643 int ret;
3645 MSVCRT__lock_file(file);
3646 ret = MSVCRT__fclose_nolock(file);
3647 MSVCRT__unlock_file(file);
3649 return ret;
3652 /*********************************************************************
3653 * _fclose_nolock (MSVCRT.@)
3655 int CDECL MSVCRT__fclose_nolock(MSVCRT_FILE* file)
3657 int r, flag;
3659 if(!(file->_flag & (MSVCRT__IOREAD | MSVCRT__IOWRT | MSVCRT__IORW)))
3661 file->_flag = 0;
3662 return MSVCRT_EOF;
3665 flag = file->_flag;
3666 MSVCRT_free(file->_tmpfname);
3667 file->_tmpfname = NULL;
3668 /* flush stdio buffers */
3669 if(file->_flag & MSVCRT__IOWRT)
3670 MSVCRT__fflush_nolock(file);
3671 if(file->_flag & MSVCRT__IOMYBUF)
3672 MSVCRT_free(file->_base);
3674 r=MSVCRT__close(file->_file);
3675 file->_flag = 0;
3677 return ((r == -1) || (flag & MSVCRT__IOERR) ? MSVCRT_EOF : 0);
3680 /*********************************************************************
3681 * feof (MSVCRT.@)
3683 int CDECL MSVCRT_feof(MSVCRT_FILE* file)
3685 return file->_flag & MSVCRT__IOEOF;
3688 /*********************************************************************
3689 * ferror (MSVCRT.@)
3691 int CDECL MSVCRT_ferror(MSVCRT_FILE* file)
3693 return file->_flag & MSVCRT__IOERR;
3696 /*********************************************************************
3697 * _filbuf (MSVCRT.@)
3699 int CDECL MSVCRT__filbuf(MSVCRT_FILE* file)
3701 unsigned char c;
3703 if(file->_flag & MSVCRT__IOSTRG)
3704 return MSVCRT_EOF;
3706 /* Allocate buffer if needed */
3707 if(!(file->_flag & (MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF)))
3708 msvcrt_alloc_buffer(file);
3710 if(!(file->_flag & MSVCRT__IOREAD)) {
3711 if(file->_flag & MSVCRT__IORW)
3712 file->_flag |= MSVCRT__IOREAD;
3713 else
3714 return MSVCRT_EOF;
3717 if(!(file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF))) {
3718 int r;
3719 if ((r = MSVCRT__read(file->_file,&c,1)) != 1) {
3720 file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
3721 return MSVCRT_EOF;
3724 return c;
3725 } else {
3726 file->_cnt = MSVCRT__read(file->_file, file->_base, file->_bufsiz);
3727 if(file->_cnt<=0) {
3728 file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
3729 file->_cnt = 0;
3730 return MSVCRT_EOF;
3733 file->_cnt--;
3734 file->_ptr = file->_base+1;
3735 c = *(unsigned char *)file->_base;
3736 return c;
3740 /*********************************************************************
3741 * fgetc (MSVCRT.@)
3743 int CDECL MSVCRT_fgetc(MSVCRT_FILE* file)
3745 int ret;
3747 MSVCRT__lock_file(file);
3748 ret = MSVCRT__fgetc_nolock(file);
3749 MSVCRT__unlock_file(file);
3751 return ret;
3754 /*********************************************************************
3755 * _fgetc_nolock (MSVCRT.@)
3757 int CDECL MSVCRT__fgetc_nolock(MSVCRT_FILE* file)
3759 unsigned char *i;
3760 unsigned int j;
3762 if (file->_cnt>0) {
3763 file->_cnt--;
3764 i = (unsigned char *)file->_ptr++;
3765 j = *i;
3766 } else
3767 j = MSVCRT__filbuf(file);
3769 return j;
3772 /*********************************************************************
3773 * _fgetchar (MSVCRT.@)
3775 int CDECL MSVCRT__fgetchar(void)
3777 return MSVCRT_fgetc(MSVCRT_stdin);
3780 /*********************************************************************
3781 * fgets (MSVCRT.@)
3783 char * CDECL MSVCRT_fgets(char *s, int size, MSVCRT_FILE* file)
3785 int cc = MSVCRT_EOF;
3786 char * buf_start = s;
3788 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3789 file,file->_file,s,size);
3791 MSVCRT__lock_file(file);
3793 while ((size >1) && (cc = MSVCRT__fgetc_nolock(file)) != MSVCRT_EOF && cc != '\n')
3795 *s++ = (char)cc;
3796 size --;
3798 if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
3800 TRACE(":nothing read\n");
3801 MSVCRT__unlock_file(file);
3802 return NULL;
3804 if ((cc != MSVCRT_EOF) && (size > 1))
3805 *s++ = cc;
3806 *s = '\0';
3807 TRACE(":got %s\n", debugstr_a(buf_start));
3808 MSVCRT__unlock_file(file);
3809 return buf_start;
3812 /*********************************************************************
3813 * fgetwc (MSVCRT.@)
3815 MSVCRT_wint_t CDECL MSVCRT_fgetwc(MSVCRT_FILE* file)
3817 MSVCRT_wint_t ret;
3819 MSVCRT__lock_file(file);
3820 ret = MSVCRT__fgetwc_nolock(file);
3821 MSVCRT__unlock_file(file);
3823 return ret;
3826 /*********************************************************************
3827 * _fgetwc_nolock (MSVCRT.@)
3829 MSVCRT_wint_t CDECL MSVCRT__fgetwc_nolock(MSVCRT_FILE* file)
3831 MSVCRT_wint_t ret;
3832 int ch;
3834 if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
3835 || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
3836 char *p;
3838 for(p=(char*)&ret; (MSVCRT_wint_t*)p<&ret+1; p++) {
3839 ch = MSVCRT__fgetc_nolock(file);
3840 if(ch == MSVCRT_EOF) {
3841 ret = MSVCRT_WEOF;
3842 break;
3844 *p = (char)ch;
3846 }else {
3847 char mbs[MSVCRT_MB_LEN_MAX];
3848 int len = 0;
3850 ch = MSVCRT__fgetc_nolock(file);
3851 if(ch != MSVCRT_EOF) {
3852 mbs[0] = (char)ch;
3853 if(MSVCRT_isleadbyte((unsigned char)mbs[0])) {
3854 ch = MSVCRT__fgetc_nolock(file);
3855 if(ch != MSVCRT_EOF) {
3856 mbs[1] = (char)ch;
3857 len = 2;
3859 }else {
3860 len = 1;
3864 if(!len || MSVCRT_mbtowc(&ret, mbs, len)==-1)
3865 ret = MSVCRT_WEOF;
3868 return ret;
3871 /*********************************************************************
3872 * _getw (MSVCRT.@)
3874 int CDECL MSVCRT__getw(MSVCRT_FILE* file)
3876 char *ch;
3877 int i, k;
3878 unsigned int j;
3879 ch = (char *)&i;
3881 MSVCRT__lock_file(file);
3882 for (j=0; j<sizeof(int); j++) {
3883 k = MSVCRT__fgetc_nolock(file);
3884 if (k == MSVCRT_EOF) {
3885 file->_flag |= MSVCRT__IOEOF;
3886 MSVCRT__unlock_file(file);
3887 return MSVCRT_EOF;
3889 ch[j] = k;
3892 MSVCRT__unlock_file(file);
3893 return i;
3896 /*********************************************************************
3897 * getwc (MSVCRT.@)
3899 MSVCRT_wint_t CDECL MSVCRT_getwc(MSVCRT_FILE* file)
3901 return MSVCRT_fgetwc(file);
3904 /*********************************************************************
3905 * _fgetwchar (MSVCRT.@)
3907 MSVCRT_wint_t CDECL MSVCRT__fgetwchar(void)
3909 return MSVCRT_fgetwc(MSVCRT_stdin);
3912 /*********************************************************************
3913 * getwchar (MSVCRT.@)
3915 MSVCRT_wint_t CDECL MSVCRT_getwchar(void)
3917 return MSVCRT__fgetwchar();
3920 /*********************************************************************
3921 * fgetws (MSVCRT.@)
3923 MSVCRT_wchar_t * CDECL MSVCRT_fgetws(MSVCRT_wchar_t *s, int size, MSVCRT_FILE* file)
3925 MSVCRT_wint_t cc = MSVCRT_WEOF;
3926 MSVCRT_wchar_t * buf_start = s;
3928 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3929 file,file->_file,s,size);
3931 MSVCRT__lock_file(file);
3933 while ((size >1) && (cc = MSVCRT__fgetwc_nolock(file)) != MSVCRT_WEOF && cc != '\n')
3935 *s++ = cc;
3936 size --;
3938 if ((cc == MSVCRT_WEOF) && (s == buf_start)) /* If nothing read, return 0*/
3940 TRACE(":nothing read\n");
3941 MSVCRT__unlock_file(file);
3942 return NULL;
3944 if ((cc != MSVCRT_WEOF) && (size > 1))
3945 *s++ = cc;
3946 *s = 0;
3947 TRACE(":got %s\n", debugstr_w(buf_start));
3948 MSVCRT__unlock_file(file);
3949 return buf_start;
3952 /*********************************************************************
3953 * _flsbuf (MSVCRT.@)
3955 int CDECL MSVCRT__flsbuf(int c, MSVCRT_FILE* file)
3957 /* Flush output buffer */
3958 if(!(file->_flag & (MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF))) {
3959 msvcrt_alloc_buffer(file);
3962 if(!(file->_flag & MSVCRT__IOWRT)) {
3963 if(!(file->_flag & MSVCRT__IORW)) {
3964 file->_flag |= MSVCRT__IOERR;
3965 *MSVCRT__errno() = MSVCRT_EBADF;
3966 return MSVCRT_EOF;
3968 file->_flag |= MSVCRT__IOWRT;
3970 if(file->_flag & MSVCRT__IOREAD) {
3971 if(!(file->_flag & MSVCRT__IOEOF)) {
3972 file->_flag |= MSVCRT__IOERR;
3973 return MSVCRT_EOF;
3975 file->_cnt = 0;
3976 file->_ptr = file->_base;
3977 file->_flag &= ~(MSVCRT__IOREAD | MSVCRT__IOEOF);
3980 if(file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF)) {
3981 int res = 0;
3983 if(file->_cnt <= 0) {
3984 res = msvcrt_flush_buffer(file);
3985 if(res)
3986 return res;
3987 file->_flag |= MSVCRT__IOWRT;
3988 file->_cnt=file->_bufsiz;
3990 *file->_ptr++ = c;
3991 file->_cnt--;
3992 return c&0xff;
3993 } else {
3994 unsigned char cc=c;
3995 int len;
3996 /* set _cnt to 0 for unbuffered FILEs */
3997 file->_cnt = 0;
3998 len = MSVCRT__write(file->_file, &cc, 1);
3999 if (len == 1)
4000 return c & 0xff;
4001 file->_flag |= MSVCRT__IOERR;
4002 return MSVCRT_EOF;
4006 /*********************************************************************
4007 * fwrite (MSVCRT.@)
4009 MSVCRT_size_t CDECL MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
4011 MSVCRT_size_t ret;
4013 MSVCRT__lock_file(file);
4014 ret = MSVCRT__fwrite_nolock(ptr, size, nmemb, file);
4015 MSVCRT__unlock_file(file);
4017 return ret;
4020 /*********************************************************************
4021 * _fwrite_nolock (MSVCRT.@)
4023 MSVCRT_size_t CDECL MSVCRT__fwrite_nolock(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
4025 MSVCRT_size_t wrcnt=size * nmemb;
4026 int written = 0;
4027 if (size == 0)
4028 return 0;
4030 while(wrcnt) {
4031 if(file->_cnt < 0) {
4032 WARN("negative file->_cnt value in %p\n", file);
4033 file->_flag |= MSVCRT__IOERR;
4034 break;
4035 } else if(file->_cnt) {
4036 int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
4037 memcpy(file->_ptr, ptr, pcnt);
4038 file->_cnt -= pcnt;
4039 file->_ptr += pcnt;
4040 written += pcnt;
4041 wrcnt -= pcnt;
4042 ptr = (const char*)ptr + pcnt;
4043 } else if((file->_flag & MSVCRT__IONBF)
4044 || ((file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF)) && wrcnt >= file->_bufsiz)
4045 || (!(file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF)) && wrcnt >= MSVCRT_INTERNAL_BUFSIZ)) {
4046 MSVCRT_size_t pcnt;
4047 int bufsiz;
4049 if(file->_flag & MSVCRT__IONBF)
4050 bufsiz = 1;
4051 else if(!(file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF)))
4052 bufsiz = MSVCRT_INTERNAL_BUFSIZ;
4053 else
4054 bufsiz = file->_bufsiz;
4056 pcnt = (wrcnt / bufsiz) * bufsiz;
4058 if(msvcrt_flush_buffer(file) == MSVCRT_EOF)
4059 break;
4061 if(MSVCRT__write(file->_file, ptr, pcnt) <= 0) {
4062 file->_flag |= MSVCRT__IOERR;
4063 break;
4065 written += pcnt;
4066 wrcnt -= pcnt;
4067 ptr = (const char*)ptr + pcnt;
4068 } else {
4069 if(MSVCRT__flsbuf(*(const char*)ptr, file) == MSVCRT_EOF)
4070 break;
4071 written++;
4072 wrcnt--;
4073 ptr = (const char*)ptr + 1;
4077 return written / size;
4080 /*********************************************************************
4081 * fputwc (MSVCRT.@)
4083 MSVCRT_wint_t CDECL MSVCRT_fputwc(MSVCRT_wint_t wc, MSVCRT_FILE* file)
4085 MSVCRT_wint_t ret;
4087 MSVCRT__lock_file(file);
4088 ret = MSVCRT__fputwc_nolock(wc, file);
4089 MSVCRT__unlock_file(file);
4091 return ret;
4094 /*********************************************************************
4095 * _fputwc_nolock (MSVCRT.@)
4097 MSVCRT_wint_t CDECL MSVCRT__fputwc_nolock(MSVCRT_wint_t wc, MSVCRT_FILE* file)
4099 MSVCRT_wchar_t mwc=wc;
4100 ioinfo *fdinfo;
4101 MSVCRT_wint_t ret;
4103 fdinfo = get_ioinfo_nolock(file->_file);
4105 if((fdinfo->wxflag&WX_TEXT) && !(fdinfo->exflag&(EF_UTF8|EF_UTF16))) {
4106 char buf[MSVCRT_MB_LEN_MAX];
4107 int char_len;
4109 char_len = MSVCRT_wctomb(buf, mwc);
4110 if(char_len!=-1 && MSVCRT__fwrite_nolock(buf, char_len, 1, file)==1)
4111 ret = wc;
4112 else
4113 ret = MSVCRT_WEOF;
4114 }else if(MSVCRT__fwrite_nolock(&mwc, sizeof(mwc), 1, file) == 1) {
4115 ret = wc;
4116 }else {
4117 ret = MSVCRT_WEOF;
4120 return ret;
4123 /*********************************************************************
4124 * _fputwchar (MSVCRT.@)
4126 MSVCRT_wint_t CDECL MSVCRT__fputwchar(MSVCRT_wint_t wc)
4128 return MSVCRT_fputwc(wc, MSVCRT_stdout);
4131 /*********************************************************************
4132 * _wfsopen (MSVCRT.@)
4134 MSVCRT_FILE * CDECL MSVCRT__wfsopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, int share)
4136 MSVCRT_FILE* file;
4137 int open_flags, stream_flags, fd;
4139 TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
4141 /* map mode string to open() flags. "man fopen" for possibilities. */
4142 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
4143 return NULL;
4145 LOCK_FILES();
4146 fd = MSVCRT__wsopen(path, open_flags, share, MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
4147 if (fd < 0)
4148 file = NULL;
4149 else if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags)
4150 != -1)
4151 TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
4152 else if (file)
4154 file->_flag = 0;
4155 file = NULL;
4158 TRACE(":got (%p)\n",file);
4159 if (fd >= 0 && !file)
4160 MSVCRT__close(fd);
4161 UNLOCK_FILES();
4162 return file;
4165 /*********************************************************************
4166 * _fsopen (MSVCRT.@)
4168 MSVCRT_FILE * CDECL MSVCRT__fsopen(const char *path, const char *mode, int share)
4170 MSVCRT_FILE *ret;
4171 MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
4173 if (path && !(pathW = msvcrt_wstrdupa(path))) {
4174 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
4175 *MSVCRT__errno() = MSVCRT_EINVAL;
4176 return NULL;
4178 if (mode && !(modeW = msvcrt_wstrdupa(mode)))
4180 MSVCRT_free(pathW);
4181 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
4182 *MSVCRT__errno() = MSVCRT_EINVAL;
4183 return NULL;
4186 ret = MSVCRT__wfsopen(pathW, modeW, share);
4188 MSVCRT_free(pathW);
4189 MSVCRT_free(modeW);
4190 return ret;
4193 /*********************************************************************
4194 * fopen (MSVCRT.@)
4196 MSVCRT_FILE * CDECL MSVCRT_fopen(const char *path, const char *mode)
4198 return MSVCRT__fsopen( path, mode, MSVCRT__SH_DENYNO );
4201 /*********************************************************************
4202 * fopen_s (MSVCRT.@)
4204 int CDECL MSVCRT_fopen_s(MSVCRT_FILE** pFile,
4205 const char *filename, const char *mode)
4207 if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
4208 if (!MSVCRT_CHECK_PMT(filename != NULL)) return MSVCRT_EINVAL;
4209 if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
4211 *pFile = MSVCRT_fopen(filename, mode);
4213 if(!*pFile)
4214 return *MSVCRT__errno();
4215 return 0;
4218 /*********************************************************************
4219 * _wfopen (MSVCRT.@)
4221 MSVCRT_FILE * CDECL MSVCRT__wfopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode)
4223 return MSVCRT__wfsopen( path, mode, MSVCRT__SH_DENYNO );
4226 /*********************************************************************
4227 * _wfopen_s (MSVCRT.@)
4229 int CDECL MSVCRT__wfopen_s(MSVCRT_FILE** pFile, const MSVCRT_wchar_t *filename,
4230 const MSVCRT_wchar_t *mode)
4232 if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
4233 if (!MSVCRT_CHECK_PMT(filename != NULL)) return MSVCRT_EINVAL;
4234 if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
4236 *pFile = MSVCRT__wfopen(filename, mode);
4238 if(!*pFile)
4239 return *MSVCRT__errno();
4240 return 0;
4243 /*********************************************************************
4244 * fputc (MSVCRT.@)
4246 int CDECL MSVCRT_fputc(int c, MSVCRT_FILE* file)
4248 int ret;
4250 MSVCRT__lock_file(file);
4251 ret = MSVCRT__fputc_nolock(c, file);
4252 MSVCRT__unlock_file(file);
4254 return ret;
4257 /*********************************************************************
4258 * _fputc_nolock (MSVCRT.@)
4260 int CDECL MSVCRT__fputc_nolock(int c, MSVCRT_FILE* file)
4262 int res;
4264 if(file->_cnt>0) {
4265 *file->_ptr++=c;
4266 file->_cnt--;
4267 if (c == '\n')
4269 res = msvcrt_flush_buffer(file);
4270 return res ? res : c;
4272 else {
4273 return c & 0xff;
4275 } else {
4276 res = MSVCRT__flsbuf(c, file);
4277 return res;
4281 /*********************************************************************
4282 * _fputchar (MSVCRT.@)
4284 int CDECL MSVCRT__fputchar(int c)
4286 return MSVCRT_fputc(c, MSVCRT_stdout);
4289 /*********************************************************************
4290 * fread (MSVCRT.@)
4292 MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
4294 MSVCRT_size_t ret;
4296 MSVCRT__lock_file(file);
4297 ret = MSVCRT__fread_nolock(ptr, size, nmemb, file);
4298 MSVCRT__unlock_file(file);
4300 return ret;
4303 /*********************************************************************
4304 * _fread_nolock (MSVCRT.@)
4306 MSVCRT_size_t CDECL MSVCRT__fread_nolock(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
4308 MSVCRT_size_t rcnt=size * nmemb;
4309 MSVCRT_size_t read=0;
4310 MSVCRT_size_t pread=0;
4312 if(!rcnt)
4313 return 0;
4315 /* first buffered data */
4316 if(file->_cnt>0) {
4317 int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
4318 memcpy(ptr, file->_ptr, pcnt);
4319 file->_cnt -= pcnt;
4320 file->_ptr += pcnt;
4321 read += pcnt ;
4322 rcnt -= pcnt ;
4323 ptr = (char*)ptr + pcnt;
4324 } else if(!(file->_flag & MSVCRT__IOREAD )) {
4325 if(file->_flag & MSVCRT__IORW) {
4326 file->_flag |= MSVCRT__IOREAD;
4327 } else {
4328 return 0;
4332 if(rcnt>0 && !(file->_flag & (MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF)))
4333 msvcrt_alloc_buffer(file);
4335 while(rcnt>0)
4337 int i;
4338 if (!file->_cnt && rcnt<file->_bufsiz && (file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF))) {
4339 i = MSVCRT__read(file->_file, file->_base, file->_bufsiz);
4340 file->_ptr = file->_base;
4341 if (i != -1) {
4342 file->_cnt = i;
4343 if (i > rcnt) i = rcnt;
4345 /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
4346 if (i > 0 && i < file->_cnt) {
4347 get_ioinfo_nolock(file->_file)->wxflag &= ~WX_ATEOF;
4348 file->_flag &= ~MSVCRT__IOEOF;
4350 if (i > 0) {
4351 memcpy(ptr, file->_ptr, i);
4352 file->_cnt -= i;
4353 file->_ptr += i;
4355 } else if (rcnt > INT_MAX) {
4356 i = MSVCRT__read(file->_file, ptr, INT_MAX);
4357 } else if (rcnt < (file->_bufsiz ? file->_bufsiz : MSVCRT_INTERNAL_BUFSIZ)) {
4358 i = MSVCRT__read(file->_file, ptr, rcnt);
4359 } else {
4360 i = MSVCRT__read(file->_file, ptr, rcnt - rcnt % (file->_bufsiz ? file->_bufsiz : MSVCRT_INTERNAL_BUFSIZ));
4362 pread += i;
4363 rcnt -= i;
4364 ptr = (char *)ptr+i;
4365 /* expose feof condition in the flags
4366 * MFC tests file->_flag for feof, and doesn't call feof())
4368 if (get_ioinfo_nolock(file->_file)->wxflag & WX_ATEOF)
4369 file->_flag |= MSVCRT__IOEOF;
4370 else if (i == -1)
4372 file->_flag |= MSVCRT__IOERR;
4373 pread = 0;
4374 rcnt = 0;
4376 if (i < 1) break;
4378 read+=pread;
4379 return read / size;
4382 #if _MSVCR_VER >= 80
4384 /*********************************************************************
4385 * fread_s (MSVCR80.@)
4387 MSVCRT_size_t CDECL MSVCRT_fread_s(void *buf, MSVCRT_size_t buf_size, MSVCRT_size_t elem_size,
4388 MSVCRT_size_t count, MSVCRT_FILE *stream)
4390 MSVCRT_size_t ret;
4392 if(!MSVCRT_CHECK_PMT(stream != NULL)) {
4393 if(buf && buf_size)
4394 memset(buf, 0, buf_size);
4395 return 0;
4397 if(!elem_size || !count) return 0;
4399 MSVCRT__lock_file(stream);
4400 ret = MSVCRT__fread_nolock_s(buf, buf_size, elem_size, count, stream);
4401 MSVCRT__unlock_file(stream);
4403 return ret;
4406 /*********************************************************************
4407 * _fread_nolock_s (MSVCR80.@)
4409 MSVCRT_size_t CDECL MSVCRT__fread_nolock_s(void *buf, MSVCRT_size_t buf_size, MSVCRT_size_t elem_size,
4410 MSVCRT_size_t count, MSVCRT_FILE *stream)
4412 size_t bytes_left, buf_pos;
4414 TRACE("(%p %lu %lu %lu %p)\n", buf, buf_size, elem_size, count, stream);
4416 if(!MSVCRT_CHECK_PMT(stream != NULL)) {
4417 if(buf && buf_size)
4418 memset(buf, 0, buf_size);
4419 return 0;
4421 if(!elem_size || !count) return 0;
4422 if(!MSVCRT_CHECK_PMT(buf != NULL)) return 0;
4423 if(!MSVCRT_CHECK_PMT(MSVCRT_SIZE_MAX/count >= elem_size)) return 0;
4425 bytes_left = elem_size*count;
4426 buf_pos = 0;
4427 while(bytes_left) {
4428 if(stream->_cnt > 0) {
4429 size_t size = bytes_left<stream->_cnt ? bytes_left : stream->_cnt;
4431 if(!MSVCRT_CHECK_PMT_ERR(size <= buf_size-buf_pos, MSVCRT_ERANGE)) {
4432 memset(buf, 0, buf_size);
4433 return 0;
4436 MSVCRT__fread_nolock((char*)buf+buf_pos, 1, size, stream);
4437 buf_pos += size;
4438 bytes_left -= size;
4439 }else {
4440 int c = MSVCRT__filbuf(stream);
4442 if(c == MSVCRT_EOF)
4443 break;
4445 if(!MSVCRT_CHECK_PMT_ERR(buf_size != buf_pos, MSVCRT_ERANGE)) {
4446 memset(buf, 0, buf_size);
4447 return 0;
4450 ((char*)buf)[buf_pos++] = c;
4451 bytes_left--;
4455 return buf_pos/elem_size;
4458 #endif /* _MSVCR_VER >= 80 */
4460 /*********************************************************************
4461 * _wfreopen (MSVCRT.@)
4464 MSVCRT_FILE* CDECL MSVCRT__wfreopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, MSVCRT_FILE* file)
4466 int open_flags, stream_flags, fd;
4468 TRACE(":path (%s) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file ? file->_file : -1);
4470 LOCK_FILES();
4471 if (!file || ((fd = file->_file) < 0))
4472 file = NULL;
4473 else
4475 MSVCRT_fclose(file);
4476 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
4477 file = NULL;
4478 else if((fd = MSVCRT__wopen(path, open_flags, MSVCRT__S_IREAD | MSVCRT__S_IWRITE)) < 0)
4479 file = NULL;
4480 else if(msvcrt_init_fp(file, fd, stream_flags) == -1)
4482 file->_flag = 0;
4483 file = NULL;
4486 UNLOCK_FILES();
4487 return file;
4490 /*********************************************************************
4491 * _wfreopen_s (MSVCRT.@)
4493 int CDECL MSVCRT__wfreopen_s(MSVCRT_FILE** pFile,
4494 const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, MSVCRT_FILE* file)
4496 if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
4497 if (!MSVCRT_CHECK_PMT(path != NULL)) return MSVCRT_EINVAL;
4498 if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
4499 if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
4501 *pFile = MSVCRT__wfreopen(path, mode, file);
4503 if(!*pFile)
4504 return *MSVCRT__errno();
4505 return 0;
4508 /*********************************************************************
4509 * freopen (MSVCRT.@)
4512 MSVCRT_FILE* CDECL MSVCRT_freopen(const char *path, const char *mode, MSVCRT_FILE* file)
4514 MSVCRT_FILE *ret;
4515 MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
4517 if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
4518 if (mode && !(modeW = msvcrt_wstrdupa(mode)))
4520 MSVCRT_free(pathW);
4521 return NULL;
4524 ret = MSVCRT__wfreopen(pathW, modeW, file);
4526 MSVCRT_free(pathW);
4527 MSVCRT_free(modeW);
4528 return ret;
4531 /*********************************************************************
4532 * freopen_s (MSVCRT.@)
4534 int CDECL MSVCRT_freopen_s(MSVCRT_FILE** pFile,
4535 const char *path, const char *mode, MSVCRT_FILE* file)
4537 if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
4538 if (!MSVCRT_CHECK_PMT(path != NULL)) return MSVCRT_EINVAL;
4539 if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
4540 if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
4542 *pFile = MSVCRT_freopen(path, mode, file);
4544 if(!*pFile)
4545 return *MSVCRT__errno();
4546 return 0;
4549 /*********************************************************************
4550 * fsetpos (MSVCRT.@)
4552 int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
4554 int ret;
4556 MSVCRT__lock_file(file);
4557 msvcrt_flush_buffer(file);
4559 /* Reset direction of i/o */
4560 if(file->_flag & MSVCRT__IORW) {
4561 file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
4564 ret = (MSVCRT__lseeki64(file->_file,*pos,MSVCRT_SEEK_SET) == -1) ? -1 : 0;
4565 MSVCRT__unlock_file(file);
4566 return ret;
4569 /*********************************************************************
4570 * _ftelli64 (MSVCRT.@)
4572 __int64 CDECL MSVCRT__ftelli64(MSVCRT_FILE* file)
4574 __int64 ret;
4576 MSVCRT__lock_file(file);
4577 ret = MSVCRT__ftelli64_nolock(file);
4578 MSVCRT__unlock_file(file);
4580 return ret;
4583 /*********************************************************************
4584 * _ftelli64_nolock (MSVCRT.@)
4586 __int64 CDECL MSVCRT__ftelli64_nolock(MSVCRT_FILE* file)
4588 __int64 pos;
4590 pos = _telli64(file->_file);
4591 if(pos == -1)
4592 return -1;
4593 if(file->_flag & (MSVCRT__IOMYBUF | MSVCRT__USERBUF)) {
4594 if(file->_flag & MSVCRT__IOWRT) {
4595 pos += file->_ptr - file->_base;
4597 if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
4598 char *p;
4600 for(p=file->_base; p<file->_ptr; p++)
4601 if(*p == '\n')
4602 pos++;
4604 } else if(!file->_cnt) { /* nothing to do */
4605 } else if(MSVCRT__lseeki64(file->_file, 0, MSVCRT_SEEK_END)==pos) {
4606 int i;
4608 pos -= file->_cnt;
4609 if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
4610 for(i=0; i<file->_cnt; i++)
4611 if(file->_ptr[i] == '\n')
4612 pos--;
4614 } else {
4615 char *p;
4617 if(MSVCRT__lseeki64(file->_file, pos, MSVCRT_SEEK_SET) != pos)
4618 return -1;
4620 pos -= file->_bufsiz;
4621 pos += file->_ptr - file->_base;
4623 if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
4624 if(get_ioinfo_nolock(file->_file)->wxflag & WX_READNL)
4625 pos--;
4627 for(p=file->_base; p<file->_ptr; p++)
4628 if(*p == '\n')
4629 pos++;
4634 return pos;
4637 /*********************************************************************
4638 * ftell (MSVCRT.@)
4640 LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
4642 return MSVCRT__ftelli64(file);
4645 #if _MSVCR_VER >= 80
4646 /*********************************************************************
4647 * _ftell_nolock (MSVCR80.@)
4649 LONG CDECL MSVCRT__ftell_nolock(MSVCRT_FILE* file)
4651 return MSVCRT__ftelli64_nolock(file);
4653 #endif
4655 /*********************************************************************
4656 * fgetpos (MSVCRT.@)
4658 int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
4660 *pos = MSVCRT__ftelli64(file);
4661 if(*pos == -1)
4662 return -1;
4663 return 0;
4666 /*********************************************************************
4667 * fputs (MSVCRT.@)
4669 int CDECL MSVCRT_fputs(const char *s, MSVCRT_FILE* file)
4671 MSVCRT_size_t len = strlen(s);
4672 int ret;
4674 MSVCRT__lock_file(file);
4675 ret = MSVCRT__fwrite_nolock(s, sizeof(*s), len, file) == len ? 0 : MSVCRT_EOF;
4676 MSVCRT__unlock_file(file);
4677 return ret;
4680 /*********************************************************************
4681 * fputws (MSVCRT.@)
4683 int CDECL MSVCRT_fputws(const MSVCRT_wchar_t *s, MSVCRT_FILE* file)
4685 MSVCRT_size_t i, len = strlenW(s);
4686 BOOL tmp_buf;
4687 int ret;
4689 MSVCRT__lock_file(file);
4690 if (!(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
4691 ret = MSVCRT__fwrite_nolock(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
4692 MSVCRT__unlock_file(file);
4693 return ret;
4696 tmp_buf = add_std_buffer(file);
4697 for (i=0; i<len; i++) {
4698 if(MSVCRT__fputwc_nolock(s[i], file) == MSVCRT_WEOF) {
4699 if(tmp_buf) remove_std_buffer(file);
4700 MSVCRT__unlock_file(file);
4701 return MSVCRT_WEOF;
4705 if(tmp_buf) remove_std_buffer(file);
4706 MSVCRT__unlock_file(file);
4707 return 0;
4710 /*********************************************************************
4711 * getchar (MSVCRT.@)
4713 int CDECL MSVCRT_getchar(void)
4715 return MSVCRT_fgetc(MSVCRT_stdin);
4718 /*********************************************************************
4719 * getc (MSVCRT.@)
4721 int CDECL MSVCRT_getc(MSVCRT_FILE* file)
4723 return MSVCRT_fgetc(file);
4726 /*********************************************************************
4727 * gets_s (MSVCR80.@)
4729 char * CDECL MSVCRT_gets_s(char *buf, MSVCRT_size_t len)
4731 char *buf_start = buf;
4732 int cc;
4734 if (!MSVCRT_CHECK_PMT(buf != NULL)) return NULL;
4735 if (!MSVCRT_CHECK_PMT(len != 0)) return NULL;
4737 MSVCRT__lock_file(MSVCRT_stdin);
4738 for(cc = MSVCRT__fgetc_nolock(MSVCRT_stdin);
4739 len != 0 && cc != MSVCRT_EOF && cc != '\n';
4740 cc = MSVCRT__fgetc_nolock(MSVCRT_stdin))
4742 if (cc != '\r')
4744 *buf++ = (char)cc;
4745 len--;
4748 MSVCRT__unlock_file(MSVCRT_stdin);
4750 if (!len)
4752 *buf_start = 0;
4753 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
4754 return NULL;
4757 if ((cc == MSVCRT_EOF) && (buf_start == buf))
4759 TRACE(":nothing read\n");
4760 return NULL;
4762 *buf = '\0';
4764 TRACE("got '%s'\n", buf_start);
4765 return buf_start;
4768 /*********************************************************************
4769 * gets (MSVCRT.@)
4771 char * CDECL MSVCRT_gets(char *buf)
4773 return MSVCRT_gets_s(buf, -1);
4776 /*********************************************************************
4777 * _getws (MSVCRT.@)
4779 MSVCRT_wchar_t* CDECL MSVCRT__getws(MSVCRT_wchar_t* buf)
4781 MSVCRT_wint_t cc;
4782 MSVCRT_wchar_t* ws = buf;
4784 MSVCRT__lock_file(MSVCRT_stdin);
4785 for (cc = MSVCRT__fgetwc_nolock(MSVCRT_stdin); cc != MSVCRT_WEOF && cc != '\n';
4786 cc = MSVCRT__fgetwc_nolock(MSVCRT_stdin))
4788 if (cc != '\r')
4789 *buf++ = (MSVCRT_wchar_t)cc;
4791 MSVCRT__unlock_file(MSVCRT_stdin);
4793 if ((cc == MSVCRT_WEOF) && (ws == buf))
4795 TRACE(":nothing read\n");
4796 return NULL;
4798 *buf = '\0';
4800 TRACE("got %s\n", debugstr_w(ws));
4801 return ws;
4804 /*********************************************************************
4805 * putc (MSVCRT.@)
4807 int CDECL MSVCRT_putc(int c, MSVCRT_FILE* file)
4809 return MSVCRT_fputc(c, file);
4812 /*********************************************************************
4813 * putchar (MSVCRT.@)
4815 int CDECL MSVCRT_putchar(int c)
4817 return MSVCRT_fputc(c, MSVCRT_stdout);
4820 /*********************************************************************
4821 * puts (MSVCRT.@)
4823 int CDECL MSVCRT_puts(const char *s)
4825 MSVCRT_size_t len = strlen(s);
4826 int ret;
4828 MSVCRT__lock_file(MSVCRT_stdout);
4829 if(MSVCRT__fwrite_nolock(s, sizeof(*s), len, MSVCRT_stdout) != len) {
4830 MSVCRT__unlock_file(MSVCRT_stdout);
4831 return MSVCRT_EOF;
4834 ret = MSVCRT__fwrite_nolock("\n",1,1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
4835 MSVCRT__unlock_file(MSVCRT_stdout);
4836 return ret;
4839 /*********************************************************************
4840 * _putws (MSVCRT.@)
4842 int CDECL MSVCRT__putws(const MSVCRT_wchar_t *s)
4844 int ret;
4846 MSVCRT__lock_file(MSVCRT_stdout);
4847 ret = MSVCRT_fputws(s, MSVCRT_stdout);
4848 if(ret >= 0)
4849 ret = MSVCRT__fputwc_nolock('\n', MSVCRT_stdout);
4850 MSVCRT__unlock_file(MSVCRT_stdout);
4851 return ret >= 0 ? 0 : MSVCRT_WEOF;
4854 /*********************************************************************
4855 * remove (MSVCRT.@)
4857 int CDECL MSVCRT_remove(const char *path)
4859 TRACE("(%s)\n",path);
4860 if (DeleteFileA(path))
4861 return 0;
4862 TRACE(":failed (%d)\n",GetLastError());
4863 msvcrt_set_errno(GetLastError());
4864 return -1;
4867 /*********************************************************************
4868 * _wremove (MSVCRT.@)
4870 int CDECL MSVCRT__wremove(const MSVCRT_wchar_t *path)
4872 TRACE("(%s)\n",debugstr_w(path));
4873 if (DeleteFileW(path))
4874 return 0;
4875 TRACE(":failed (%d)\n",GetLastError());
4876 msvcrt_set_errno(GetLastError());
4877 return -1;
4880 /*********************************************************************
4881 * rename (MSVCRT.@)
4883 int CDECL MSVCRT_rename(const char *oldpath,const char *newpath)
4885 TRACE(":from %s to %s\n",oldpath,newpath);
4886 if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
4887 return 0;
4888 TRACE(":failed (%d)\n",GetLastError());
4889 msvcrt_set_errno(GetLastError());
4890 return -1;
4893 /*********************************************************************
4894 * _wrename (MSVCRT.@)
4896 int CDECL MSVCRT__wrename(const MSVCRT_wchar_t *oldpath,const MSVCRT_wchar_t *newpath)
4898 TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
4899 if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
4900 return 0;
4901 TRACE(":failed (%d)\n",GetLastError());
4902 msvcrt_set_errno(GetLastError());
4903 return -1;
4906 /*********************************************************************
4907 * setvbuf (MSVCRT.@)
4909 int CDECL MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size)
4911 if(!MSVCRT_CHECK_PMT(file != NULL)) return -1;
4912 if(!MSVCRT_CHECK_PMT(mode==MSVCRT__IONBF || mode==MSVCRT__IOFBF || mode==MSVCRT__IOLBF)) return -1;
4913 if(!MSVCRT_CHECK_PMT(mode==MSVCRT__IONBF || (size>=2 && size<=INT_MAX))) return -1;
4915 MSVCRT__lock_file(file);
4917 MSVCRT__fflush_nolock(file);
4918 if(file->_flag & MSVCRT__IOMYBUF)
4919 MSVCRT_free(file->_base);
4920 file->_flag &= ~(MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF);
4921 file->_cnt = 0;
4923 if(mode == MSVCRT__IONBF) {
4924 file->_flag |= MSVCRT__IONBF;
4925 file->_base = file->_ptr = (char*)&file->_charbuf;
4926 file->_bufsiz = 2;
4927 }else if(buf) {
4928 file->_base = file->_ptr = buf;
4929 file->_flag |= MSVCRT__USERBUF;
4930 file->_bufsiz = size;
4931 }else {
4932 file->_base = file->_ptr = MSVCRT_malloc(size);
4933 if(!file->_base) {
4934 file->_bufsiz = 0;
4935 MSVCRT__unlock_file(file);
4936 return -1;
4939 file->_flag |= MSVCRT__IOMYBUF;
4940 file->_bufsiz = size;
4942 MSVCRT__unlock_file(file);
4943 return 0;
4946 /*********************************************************************
4947 * setbuf (MSVCRT.@)
4949 void CDECL MSVCRT_setbuf(MSVCRT_FILE* file, char *buf)
4951 MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, MSVCRT_BUFSIZ);
4954 static int tmpnam_helper(char *s, MSVCRT_size_t size, int *tmpnam_unique, int tmp_max)
4956 char tmpstr[8];
4957 char *p = s;
4958 int digits;
4960 if (!MSVCRT_CHECK_PMT(s != NULL)) return MSVCRT_EINVAL;
4962 if (size < 3) {
4963 if (size) *s = 0;
4964 *MSVCRT__errno() = MSVCRT_ERANGE;
4965 return MSVCRT_ERANGE;
4967 *p++ = '\\';
4968 *p++ = 's';
4969 size -= 2;
4970 digits = msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr);
4971 if (digits+1 > size) {
4972 *s = 0;
4973 *MSVCRT__errno() = MSVCRT_ERANGE;
4974 return MSVCRT_ERANGE;
4976 memcpy(p, tmpstr, digits*sizeof(tmpstr[0]));
4977 p += digits;
4978 *p++ = '.';
4979 size -= digits+1;
4981 while(1) {
4982 while ((digits = *tmpnam_unique)+1 < tmp_max) {
4983 if (InterlockedCompareExchange(tmpnam_unique, digits+1, digits) == digits)
4984 break;
4987 digits = msvcrt_int_to_base32(digits, tmpstr);
4988 if (digits+1 > size) {
4989 *s = 0;
4990 *MSVCRT__errno() = MSVCRT_ERANGE;
4991 return MSVCRT_ERANGE;
4993 memcpy(p, tmpstr, digits*sizeof(tmpstr[0]));
4994 p[digits] = 0;
4996 if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES &&
4997 GetLastError() == ERROR_FILE_NOT_FOUND)
4998 break;
5000 return 0;
5003 int CDECL MSVCRT_tmpnam_s(char *s, MSVCRT_size_t size)
5005 return tmpnam_helper(s, size, &tmpnam_s_unique, MSVCRT_TMP_MAX_S);
5008 /*********************************************************************
5009 * tmpnam (MSVCRT.@)
5011 char * CDECL MSVCRT_tmpnam(char *s)
5013 if (!s) {
5014 thread_data_t *data = msvcrt_get_thread_data();
5016 if(!data->tmpnam_buffer)
5017 data->tmpnam_buffer = MSVCRT_malloc(MAX_PATH);
5019 s = data->tmpnam_buffer;
5022 return tmpnam_helper(s, -1, &tmpnam_unique, MSVCRT_TMP_MAX) ? NULL : s;
5025 static int wtmpnam_helper(MSVCRT_wchar_t *s, MSVCRT_size_t size, int *tmpnam_unique, int tmp_max)
5027 MSVCRT_wchar_t tmpstr[8];
5028 MSVCRT_wchar_t *p = s;
5029 int digits;
5031 if (!MSVCRT_CHECK_PMT(s != NULL)) return MSVCRT_EINVAL;
5033 if (size < 3) {
5034 if (size) *s = 0;
5035 *MSVCRT__errno() = MSVCRT_ERANGE;
5036 return MSVCRT_ERANGE;
5038 *p++ = '\\';
5039 *p++ = 's';
5040 size -= 2;
5041 digits = msvcrt_int_to_base32_w(GetCurrentProcessId(), tmpstr);
5042 if (digits+1 > size) {
5043 *s = 0;
5044 *MSVCRT__errno() = MSVCRT_ERANGE;
5045 return MSVCRT_ERANGE;
5047 memcpy(p, tmpstr, digits*sizeof(tmpstr[0]));
5048 p += digits;
5049 *p++ = '.';
5050 size -= digits+1;
5052 while(1) {
5053 while ((digits = *tmpnam_unique)+1 < tmp_max) {
5054 if (InterlockedCompareExchange(tmpnam_unique, digits+1, digits) == digits)
5055 break;
5058 digits = msvcrt_int_to_base32_w(digits, tmpstr);
5059 if (digits+1 > size) {
5060 *s = 0;
5061 *MSVCRT__errno() = MSVCRT_ERANGE;
5062 return MSVCRT_ERANGE;
5064 memcpy(p, tmpstr, digits*sizeof(tmpstr[0]));
5065 p[digits] = 0;
5067 if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES &&
5068 GetLastError() == ERROR_FILE_NOT_FOUND)
5069 break;
5071 return 0;
5074 /*********************************************************************
5075 * _wtmpnam_s (MSVCRT.@)
5077 int CDECL MSVCRT__wtmpnam_s(MSVCRT_wchar_t *s, MSVCRT_size_t size)
5079 return wtmpnam_helper(s, size, &tmpnam_s_unique, MSVCRT_TMP_MAX_S);
5082 /*********************************************************************
5083 * _wtmpnam (MSVCRT.@)
5085 MSVCRT_wchar_t * CDECL MSVCRT__wtmpnam(MSVCRT_wchar_t *s)
5087 if (!s) {
5088 thread_data_t *data = msvcrt_get_thread_data();
5090 if(!data->wtmpnam_buffer)
5091 data->wtmpnam_buffer = MSVCRT_malloc(sizeof(MSVCRT_wchar_t[MAX_PATH]));
5093 s = data->wtmpnam_buffer;
5096 return wtmpnam_helper(s, -1, &tmpnam_unique, MSVCRT_TMP_MAX) ? NULL : s;
5099 /*********************************************************************
5100 * tmpfile (MSVCRT.@)
5102 MSVCRT_FILE* CDECL MSVCRT_tmpfile(void)
5104 char *filename = MSVCRT__tempnam(",", "t");
5105 int fd;
5106 MSVCRT_FILE* file = NULL;
5108 LOCK_FILES();
5109 fd = MSVCRT__open(filename, MSVCRT__O_CREAT | MSVCRT__O_BINARY | MSVCRT__O_RDWR | MSVCRT__O_TEMPORARY,
5110 MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
5111 if (fd != -1 && (file = msvcrt_alloc_fp()))
5113 if (msvcrt_init_fp(file, fd, MSVCRT__IORW) == -1)
5115 file->_flag = 0;
5116 file = NULL;
5118 else file->_tmpfname = MSVCRT__strdup(filename);
5121 if(fd != -1 && !file)
5122 MSVCRT__close(fd);
5123 MSVCRT_free(filename);
5124 UNLOCK_FILES();
5125 return file;
5128 /*********************************************************************
5129 * tmpfile_s (MSVCRT.@)
5131 int CDECL MSVCRT_tmpfile_s(MSVCRT_FILE** file)
5133 if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
5135 *file = MSVCRT_tmpfile();
5136 return 0;
5139 static int puts_clbk_file_a(void *file, int len, const char *str)
5141 return MSVCRT_fwrite(str, sizeof(char), len, file);
5144 static int puts_clbk_file_w(void *file, int len, const MSVCRT_wchar_t *str)
5146 int i, ret;
5148 MSVCRT__lock_file(file);
5150 if(!(get_ioinfo_nolock(((MSVCRT_FILE*)file)->_file)->wxflag & WX_TEXT)) {
5151 ret = MSVCRT__fwrite_nolock(str, sizeof(MSVCRT_wchar_t), len, file);
5152 MSVCRT__unlock_file(file);
5153 return ret;
5156 for(i=0; i<len; i++) {
5157 if(MSVCRT__fputwc_nolock(str[i], file) == MSVCRT_WEOF) {
5158 MSVCRT__unlock_file(file);
5159 return -1;
5163 MSVCRT__unlock_file(file);
5164 return len;
5167 static int vfprintf_helper(DWORD options, MSVCRT_FILE* file, const char *format,
5168 MSVCRT__locale_t locale, __ms_va_list valist)
5170 printf_arg args_ctx[MSVCRT__ARGMAX+1];
5171 BOOL tmp_buf;
5172 int ret;
5174 if(!MSVCRT_CHECK_PMT( file != NULL )) return -1;
5175 if(!MSVCRT_CHECK_PMT( format != NULL )) return -1;
5177 if(options & MSVCRT_PRINTF_POSITIONAL_PARAMS) {
5178 memset(args_ctx, 0, sizeof(args_ctx));
5179 ret = create_positional_ctx_a(args_ctx, format, valist);
5180 if(ret < 0) {
5181 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
5182 *MSVCRT__errno() = MSVCRT_EINVAL;
5183 return ret;
5184 } else if(!ret)
5185 options &= ~MSVCRT_PRINTF_POSITIONAL_PARAMS;
5188 MSVCRT__lock_file(file);
5189 tmp_buf = add_std_buffer(file);
5190 ret = pf_printf_a(puts_clbk_file_a, file, format, locale, options,
5191 options & MSVCRT_PRINTF_POSITIONAL_PARAMS ? arg_clbk_positional : arg_clbk_valist,
5192 options & MSVCRT_PRINTF_POSITIONAL_PARAMS ? args_ctx : NULL, &valist);
5193 if(tmp_buf) remove_std_buffer(file);
5194 MSVCRT__unlock_file(file);
5196 return ret;
5199 static int vfwprintf_helper(DWORD options, MSVCRT_FILE* file, const MSVCRT_wchar_t *format,
5200 MSVCRT__locale_t locale, __ms_va_list valist)
5202 printf_arg args_ctx[MSVCRT__ARGMAX+1];
5203 BOOL tmp_buf;
5204 int ret;
5206 if(!MSVCRT_CHECK_PMT( file != NULL )) return -1;
5207 if(!MSVCRT_CHECK_PMT( format != NULL )) return -1;
5209 if(options & MSVCRT_PRINTF_POSITIONAL_PARAMS) {
5210 memset(args_ctx, 0, sizeof(args_ctx));
5211 ret = create_positional_ctx_w(args_ctx, format, valist);
5212 if(ret < 0) {
5213 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
5214 *MSVCRT__errno() = MSVCRT_EINVAL;
5215 return ret;
5216 } else if(!ret)
5217 options &= ~MSVCRT_PRINTF_POSITIONAL_PARAMS;
5220 MSVCRT__lock_file(file);
5221 tmp_buf = add_std_buffer(file);
5222 ret = pf_printf_w(puts_clbk_file_w, file, format, locale, options,
5223 options & MSVCRT_PRINTF_POSITIONAL_PARAMS ? arg_clbk_positional : arg_clbk_valist,
5224 options & MSVCRT_PRINTF_POSITIONAL_PARAMS ? args_ctx : NULL, &valist);
5225 if(tmp_buf) remove_std_buffer(file);
5226 MSVCRT__unlock_file(file);
5228 return ret;
5231 /*********************************************************************
5232 * _vfprintf_s_l (MSVCRT.@)
5234 int CDECL MSVCRT__vfprintf_s_l(MSVCRT_FILE* file, const char *format,
5235 MSVCRT__locale_t locale, __ms_va_list valist)
5237 return vfprintf_helper(MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, file, format, locale, valist);
5240 /*********************************************************************
5241 * _vfwprintf_s_l (MSVCRT.@)
5243 int CDECL MSVCRT__vfwprintf_s_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format,
5244 MSVCRT__locale_t locale, __ms_va_list valist)
5246 return vfwprintf_helper(MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER, file, format, locale, valist);
5249 /*********************************************************************
5250 * vfprintf (MSVCRT.@)
5252 int CDECL MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
5254 return vfprintf_helper(0, file, format, NULL, valist);
5257 /*********************************************************************
5258 * vfprintf_s (MSVCRT.@)
5260 int CDECL MSVCRT_vfprintf_s(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
5262 return MSVCRT__vfprintf_s_l(file, format, NULL, valist);
5265 /*********************************************************************
5266 * vfwprintf (MSVCRT.@)
5268 int CDECL MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
5270 return vfwprintf_helper(0, file, format, NULL, valist);
5273 /*********************************************************************
5274 * vfwprintf_s (MSVCRT.@)
5276 int CDECL MSVCRT_vfwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
5278 return MSVCRT__vfwprintf_s_l(file, format, NULL, valist);
5281 #if _MSVCR_VER >= 140
5283 /*********************************************************************
5284 * __stdio_common_vfprintf (UCRTBASE.@)
5286 int CDECL MSVCRT__stdio_common_vfprintf(unsigned __int64 options, MSVCRT_FILE *file, const char *format,
5287 MSVCRT__locale_t locale, __ms_va_list valist)
5289 if (options & ~UCRTBASE_PRINTF_MASK)
5290 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
5292 return vfprintf_helper(options & UCRTBASE_PRINTF_MASK, file, format, locale, valist);
5295 /*********************************************************************
5296 * __stdio_common_vfprintf_s (UCRTBASE.@)
5298 int CDECL MSVCRT__stdio_common_vfprintf_s(unsigned __int64 options, MSVCRT_FILE *file, const char *format,
5299 MSVCRT__locale_t locale, __ms_va_list valist)
5301 if (options & ~UCRTBASE_PRINTF_MASK)
5302 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
5304 return vfprintf_helper((options & UCRTBASE_PRINTF_MASK) | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
5305 file, format, locale, valist);
5308 /*********************************************************************
5309 * __stdio_common_vfwprintf (UCRTBASE.@)
5311 int CDECL MSVCRT__stdio_common_vfwprintf(unsigned __int64 options, MSVCRT_FILE *file, const MSVCRT_wchar_t *format,
5312 MSVCRT__locale_t locale, __ms_va_list valist)
5314 if (options & ~UCRTBASE_PRINTF_MASK)
5315 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
5317 return vfwprintf_helper(options & UCRTBASE_PRINTF_MASK, file, format, locale, valist);
5320 /*********************************************************************
5321 * __stdio_common_vfwprintf_s (UCRTBASE.@)
5323 int CDECL MSVCRT__stdio_common_vfwprintf_s(unsigned __int64 options, MSVCRT_FILE *file, const MSVCRT_wchar_t *format,
5324 MSVCRT__locale_t locale, __ms_va_list valist)
5326 if (options & ~UCRTBASE_PRINTF_MASK)
5327 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
5329 return vfwprintf_helper((options & UCRTBASE_PRINTF_MASK) | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
5330 file, format, locale, valist);
5333 #endif /* _MSVCR_VER >= 140 */
5335 /*********************************************************************
5336 * _vfprintf_l (MSVCRT.@)
5338 int CDECL MSVCRT__vfprintf_l(MSVCRT_FILE* file, const char *format,
5339 MSVCRT__locale_t locale, __ms_va_list valist)
5341 return vfprintf_helper(0, file, format, locale, valist);
5344 /*********************************************************************
5345 * _vfwprintf_l (MSVCRT.@)
5347 int CDECL MSVCRT__vfwprintf_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format,
5348 MSVCRT__locale_t locale, __ms_va_list valist)
5350 return vfwprintf_helper(0, file, format, locale, valist);
5353 /*********************************************************************
5354 * _vfprintf_p_l (MSVCRT.@)
5356 int CDECL MSVCRT__vfprintf_p_l(MSVCRT_FILE* file, const char *format,
5357 MSVCRT__locale_t locale, __ms_va_list valist)
5359 return vfprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
5360 file, format, locale, valist);
5363 /*********************************************************************
5364 * _vfprintf_p (MSVCRT.@)
5366 int CDECL MSVCRT__vfprintf_p(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
5368 return MSVCRT__vfprintf_p_l(file, format, NULL, valist);
5371 /*********************************************************************
5372 * _vfwprintf_p_l (MSVCRT.@)
5374 int CDECL MSVCRT__vfwprintf_p_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format,
5375 MSVCRT__locale_t locale, __ms_va_list valist)
5377 return vfwprintf_helper(MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
5378 file, format, locale, valist);
5381 /*********************************************************************
5382 * _vfwprintf_p (MSVCRT.@)
5384 int CDECL MSVCRT__vfwprintf_p(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
5386 return MSVCRT__vfwprintf_p_l(file, format, NULL, valist);
5389 /*********************************************************************
5390 * vprintf (MSVCRT.@)
5392 int CDECL MSVCRT_vprintf(const char *format, __ms_va_list valist)
5394 return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
5397 /*********************************************************************
5398 * vprintf_s (MSVCRT.@)
5400 int CDECL MSVCRT_vprintf_s(const char *format, __ms_va_list valist)
5402 return MSVCRT_vfprintf_s(MSVCRT_stdout,format,valist);
5405 /*********************************************************************
5406 * vwprintf (MSVCRT.@)
5408 int CDECL MSVCRT_vwprintf(const MSVCRT_wchar_t *format, __ms_va_list valist)
5410 return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
5413 /*********************************************************************
5414 * vwprintf_s (MSVCRT.@)
5416 int CDECL MSVCRT_vwprintf_s(const MSVCRT_wchar_t *format, __ms_va_list valist)
5418 return MSVCRT_vfwprintf_s(MSVCRT_stdout,format,valist);
5421 /*********************************************************************
5422 * fprintf (MSVCRT.@)
5424 int WINAPIV MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
5426 __ms_va_list valist;
5427 int res;
5428 __ms_va_start(valist, format);
5429 res = MSVCRT_vfprintf(file, format, valist);
5430 __ms_va_end(valist);
5431 return res;
5434 /*********************************************************************
5435 * fprintf_s (MSVCRT.@)
5437 int WINAPIV MSVCRT_fprintf_s(MSVCRT_FILE* file, const char *format, ...)
5439 __ms_va_list valist;
5440 int res;
5441 __ms_va_start(valist, format);
5442 res = MSVCRT_vfprintf_s(file, format, valist);
5443 __ms_va_end(valist);
5444 return res;
5447 /*********************************************************************
5448 * fwprintf (MSVCRT.@)
5450 int WINAPIV MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
5452 __ms_va_list valist;
5453 int res;
5454 __ms_va_start(valist, format);
5455 res = MSVCRT_vfwprintf(file, format, valist);
5456 __ms_va_end(valist);
5457 return res;
5460 /*********************************************************************
5461 * fwprintf_s (MSVCRT.@)
5463 int WINAPIV MSVCRT_fwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
5465 __ms_va_list valist;
5466 int res;
5467 __ms_va_start(valist, format);
5468 res = MSVCRT_vfwprintf_s(file, format, valist);
5469 __ms_va_end(valist);
5470 return res;
5473 /*********************************************************************
5474 * _fwprintf_l (MSVCRT.@)
5476 int WINAPIV MSVCRT__fwprintf_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
5478 __ms_va_list valist;
5479 int res;
5480 __ms_va_start(valist, locale);
5481 res = MSVCRT__vfwprintf_l(file, format, locale, valist);
5482 __ms_va_end(valist);
5483 return res;
5486 /*********************************************************************
5487 * printf (MSVCRT.@)
5489 int WINAPIV MSVCRT_printf(const char *format, ...)
5491 __ms_va_list valist;
5492 int res;
5493 __ms_va_start(valist, format);
5494 res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
5495 __ms_va_end(valist);
5496 return res;
5499 /*********************************************************************
5500 * printf_s (MSVCRT.@)
5502 int WINAPIV MSVCRT_printf_s(const char *format, ...)
5504 __ms_va_list valist;
5505 int res;
5506 __ms_va_start(valist, format);
5507 res = MSVCRT_vprintf_s(format, valist);
5508 __ms_va_end(valist);
5509 return res;
5512 /*********************************************************************
5513 * ungetc (MSVCRT.@)
5515 int CDECL MSVCRT_ungetc(int c, MSVCRT_FILE * file)
5517 int ret;
5519 if(!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EOF;
5521 MSVCRT__lock_file(file);
5522 ret = MSVCRT__ungetc_nolock(c, file);
5523 MSVCRT__unlock_file(file);
5525 return ret;
5528 /*********************************************************************
5529 * _ungetc_nolock (MSVCRT.@)
5531 int CDECL MSVCRT__ungetc_nolock(int c, MSVCRT_FILE * file)
5533 if(!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EOF;
5535 if (c == MSVCRT_EOF || !(file->_flag&MSVCRT__IOREAD ||
5536 (file->_flag&MSVCRT__IORW && !(file->_flag&MSVCRT__IOWRT))))
5537 return MSVCRT_EOF;
5539 if((!(file->_flag & (MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF))
5540 && msvcrt_alloc_buffer(file))
5541 || (!file->_cnt && file->_ptr==file->_base))
5542 file->_ptr++;
5544 if(file->_ptr>file->_base) {
5545 file->_ptr--;
5546 if(file->_flag & MSVCRT__IOSTRG) {
5547 if(*file->_ptr != c) {
5548 file->_ptr++;
5549 return MSVCRT_EOF;
5551 }else {
5552 *file->_ptr = c;
5554 file->_cnt++;
5555 file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
5556 file->_flag |= MSVCRT__IOREAD;
5557 return c;
5560 return MSVCRT_EOF;
5563 /*********************************************************************
5564 * ungetwc (MSVCRT.@)
5566 MSVCRT_wint_t CDECL MSVCRT_ungetwc(MSVCRT_wint_t wc, MSVCRT_FILE * file)
5568 MSVCRT_wint_t ret;
5570 if(!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_WEOF;
5572 MSVCRT__lock_file(file);
5573 ret = MSVCRT__ungetwc_nolock(wc, file);
5574 MSVCRT__unlock_file(file);
5576 return ret;
5579 /*********************************************************************
5580 * _ungetwc_nolock (MSVCRT.@)
5582 MSVCRT_wint_t CDECL MSVCRT__ungetwc_nolock(MSVCRT_wint_t wc, MSVCRT_FILE * file)
5584 MSVCRT_wchar_t mwc = wc;
5586 if(!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_WEOF;
5587 if (wc == MSVCRT_WEOF)
5588 return MSVCRT_WEOF;
5590 if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
5591 || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
5592 unsigned char * pp = (unsigned char *)&mwc;
5593 int i;
5595 for(i=sizeof(MSVCRT_wchar_t)-1;i>=0;i--) {
5596 if(pp[i] != MSVCRT__ungetc_nolock(pp[i],file))
5597 return MSVCRT_WEOF;
5599 }else {
5600 char mbs[MSVCRT_MB_LEN_MAX];
5601 int len;
5603 len = MSVCRT_wctomb(mbs, mwc);
5604 if(len == -1)
5605 return MSVCRT_WEOF;
5607 for(len--; len>=0; len--) {
5608 if(mbs[len] != MSVCRT__ungetc_nolock(mbs[len], file))
5609 return MSVCRT_WEOF;
5613 return mwc;
5616 /*********************************************************************
5617 * wprintf (MSVCRT.@)
5619 int WINAPIV MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
5621 __ms_va_list valist;
5622 int res;
5623 __ms_va_start(valist, format);
5624 res = MSVCRT_vwprintf(format, valist);
5625 __ms_va_end(valist);
5626 return res;
5629 /*********************************************************************
5630 * wprintf_s (MSVCRT.@)
5632 int WINAPIV MSVCRT_wprintf_s(const MSVCRT_wchar_t *format, ...)
5634 __ms_va_list valist;
5635 int res;
5636 __ms_va_start(valist, format);
5637 res = MSVCRT_vwprintf_s(format, valist);
5638 __ms_va_end(valist);
5639 return res;
5642 /*********************************************************************
5643 * _getmaxstdio (MSVCRT.@)
5645 int CDECL MSVCRT__getmaxstdio(void)
5647 return MSVCRT_max_streams;
5650 /*********************************************************************
5651 * _setmaxstdio (MSVCRT.@)
5653 int CDECL MSVCRT__setmaxstdio(int newmax)
5655 TRACE("%d\n", newmax);
5657 if(newmax<_IOB_ENTRIES || newmax>MSVCRT_MAX_FILES || newmax<MSVCRT_stream_idx)
5658 return -1;
5660 MSVCRT_max_streams = newmax;
5661 return MSVCRT_max_streams;
5664 #if _MSVCR_VER >= 140
5665 /*********************************************************************
5666 * _get_stream_buffer_pointers (UCRTBASE.@)
5668 int CDECL MSVCRT__get_stream_buffer_pointers(MSVCRT_FILE *file, char*** base,
5669 char*** ptr, int** count)
5671 if (base)
5672 *base = &file->_base;
5673 if (ptr)
5674 *ptr = &file->_ptr;
5675 if (count)
5676 *count = &file->_cnt;
5677 return 0;
5679 #endif