msvcrt: Added _lock_file/_unlock_file implementation.
[wine/testsucceed.git] / dlls / msvcrt / file.c
blobee95c28d326bbdabec8d62e305fce0c5b0e2a5ef
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 #include <time.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <sys/types.h>
40 #include "windef.h"
41 #include "winbase.h"
42 #include "winternl.h"
43 #include "msvcrt.h"
44 #include "mtdll.h"
46 #include "wine/unicode.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
52 /* for stat mode, permissions apply to all,owner and group */
53 #define ALL_S_IREAD (MSVCRT__S_IREAD | (MSVCRT__S_IREAD >> 3) | (MSVCRT__S_IREAD >> 6))
54 #define ALL_S_IWRITE (MSVCRT__S_IWRITE | (MSVCRT__S_IWRITE >> 3) | (MSVCRT__S_IWRITE >> 6))
55 #define ALL_S_IEXEC (MSVCRT__S_IEXEC | (MSVCRT__S_IEXEC >> 3) | (MSVCRT__S_IEXEC >> 6))
57 /* _access() bit flags FIXME: incomplete */
58 #define MSVCRT_W_OK 0x02
59 #define MSVCRT_R_OK 0x04
61 /* values for wxflag in file descriptor */
62 #define WX_OPEN 0x01
63 #define WX_ATEOF 0x02
64 #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */
65 #define WX_READCR 0x08 /* underlying file is at \r */
66 #define WX_DONTINHERIT 0x10
67 #define WX_APPEND 0x20
68 #define WX_TEXT 0x80
70 /* FIXME: this should be allocated dynamically */
71 #define MSVCRT_MAX_FILES 2048
72 #define MSVCRT_FD_BLOCK_SIZE 64
74 /* ioinfo structure size is different in msvcrXX.dll's */
75 typedef struct {
76 HANDLE handle;
77 unsigned char wxflag;
78 char unk1;
79 BOOL crit_init;
80 CRITICAL_SECTION crit;
81 } ioinfo;
83 /*********************************************************************
84 * __pioinfo (MSVCRT.@)
85 * array of pointers to ioinfo arrays [64]
87 ioinfo * MSVCRT___pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 };
89 /*********************************************************************
90 * __badioinfo (MSVCRT.@)
92 ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
94 static int MSVCRT_fdstart = 3; /* first unallocated fd */
95 static int MSVCRT_fdend = 3; /* highest allocated fd */
97 typedef struct {
98 MSVCRT_FILE file;
99 CRITICAL_SECTION crit;
100 } file_crit;
102 MSVCRT_FILE MSVCRT__iob[_IOB_ENTRIES] = { { 0 } };
103 static file_crit* MSVCRT_fstream[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE];
104 static int MSVCRT_max_streams = 512, MSVCRT_stream_idx;
106 /* INTERNAL: process umask */
107 static int MSVCRT_umask = 0;
109 /* INTERNAL: static data for tmpnam and _wtmpname functions */
110 static int tmpnam_unique;
111 static char MSVCRT_tmpname[MAX_PATH];
112 static MSVCRT_wchar_t MSVCRT_wtmpname[MAX_PATH];
114 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
115 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
116 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
117 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
119 #define TOUL(x) (ULONGLONG)(x)
120 static const ULONGLONG WCEXE = TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
121 static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
122 static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
123 static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
125 /* This critical section protects the tables MSVCRT___pioinfo and MSVCRT_fstreams,
126 * and their related indexes, MSVCRT_fdstart, MSVCRT_fdend,
127 * and MSVCRT_stream_idx, from race conditions.
128 * It doesn't protect against race conditions manipulating the underlying files
129 * or flags; doing so would probably be better accomplished with per-file
130 * protection, rather than locking the whole table for every change.
132 static CRITICAL_SECTION MSVCRT_file_cs;
133 #define LOCK_FILES() do { EnterCriticalSection(&MSVCRT_file_cs); } while (0)
134 #define UNLOCK_FILES() do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0)
136 static void msvcrt_stat64_to_stat(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat *buf)
138 buf->st_dev = buf64->st_dev;
139 buf->st_ino = buf64->st_ino;
140 buf->st_mode = buf64->st_mode;
141 buf->st_nlink = buf64->st_nlink;
142 buf->st_uid = buf64->st_uid;
143 buf->st_gid = buf64->st_gid;
144 buf->st_rdev = buf64->st_rdev;
145 buf->st_size = buf64->st_size;
146 buf->st_atime = buf64->st_atime;
147 buf->st_mtime = buf64->st_mtime;
148 buf->st_ctime = buf64->st_ctime;
151 static void msvcrt_stat64_to_stati64(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stati64 *buf)
153 buf->st_dev = buf64->st_dev;
154 buf->st_ino = buf64->st_ino;
155 buf->st_mode = buf64->st_mode;
156 buf->st_nlink = buf64->st_nlink;
157 buf->st_uid = buf64->st_uid;
158 buf->st_gid = buf64->st_gid;
159 buf->st_rdev = buf64->st_rdev;
160 buf->st_size = buf64->st_size;
161 buf->st_atime = buf64->st_atime;
162 buf->st_mtime = buf64->st_mtime;
163 buf->st_ctime = buf64->st_ctime;
166 static void time_to_filetime( MSVCRT___time64_t time, FILETIME *ft )
168 /* 1601 to 1970 is 369 years plus 89 leap days */
169 static const __int64 secs_1601_to_1970 = ((369 * 365 + 89) * (__int64)86400);
171 __int64 ticks = (time + secs_1601_to_1970) * 10000000;
172 ft->dwHighDateTime = ticks >> 32;
173 ft->dwLowDateTime = ticks;
176 static inline ioinfo* msvcrt_get_ioinfo(int fd)
178 ioinfo *ret = NULL;
179 if(fd < MSVCRT_MAX_FILES)
180 ret = MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE];
181 if(!ret)
182 return &MSVCRT___badioinfo;
184 return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
187 static inline MSVCRT_FILE* msvcrt_get_file(int i)
189 file_crit *ret;
191 if(i >= MSVCRT_max_streams)
192 return NULL;
194 if(i < _IOB_ENTRIES)
195 return &MSVCRT__iob[i];
197 ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE];
198 if(!ret) {
199 MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(file_crit));
200 if(!MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE]) {
201 ERR("out of memory");
202 *MSVCRT__errno() = MSVCRT_ENOMEM;
203 return NULL;
206 ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] + (i%MSVCRT_FD_BLOCK_SIZE);
207 } else
208 ret += i%MSVCRT_FD_BLOCK_SIZE;
210 return &ret->file;
213 static inline BOOL msvcrt_is_valid_fd(int fd)
215 return fd >= 0 && fd < MSVCRT_fdend && (msvcrt_get_ioinfo(fd)->wxflag & WX_OPEN);
218 /* INTERNAL: Get the HANDLE for a fd
219 * This doesn't lock the table, because a failure will result in
220 * INVALID_HANDLE_VALUE being returned, which should be handled correctly. If
221 * it returns a valid handle which is about to be closed, a subsequent call
222 * will fail, most likely in a sane way.
224 static HANDLE msvcrt_fdtoh(int fd)
226 if (!msvcrt_is_valid_fd(fd))
228 WARN(":fd (%d) - no handle!\n",fd);
229 *MSVCRT___doserrno() = 0;
230 *MSVCRT__errno() = MSVCRT_EBADF;
231 return INVALID_HANDLE_VALUE;
233 if (msvcrt_get_ioinfo(fd)->handle == INVALID_HANDLE_VALUE)
234 FIXME("returning INVALID_HANDLE_VALUE for %d\n", fd);
235 return msvcrt_get_ioinfo(fd)->handle;
238 /* INTERNAL: free a file entry fd */
239 static void msvcrt_free_fd(int fd)
241 HANDLE old_handle;
242 ioinfo *fdinfo;
244 LOCK_FILES();
245 fdinfo = msvcrt_get_ioinfo(fd);
246 old_handle = fdinfo->handle;
247 if(fdinfo != &MSVCRT___badioinfo)
249 fdinfo->handle = INVALID_HANDLE_VALUE;
250 fdinfo->wxflag = 0;
252 TRACE(":fd (%d) freed\n",fd);
253 if (fd < 3) /* don't use 0,1,2 for user files */
255 switch (fd)
257 case 0:
258 if (GetStdHandle(STD_INPUT_HANDLE) == old_handle) SetStdHandle(STD_INPUT_HANDLE, 0);
259 break;
260 case 1:
261 if (GetStdHandle(STD_OUTPUT_HANDLE) == old_handle) SetStdHandle(STD_OUTPUT_HANDLE, 0);
262 break;
263 case 2:
264 if (GetStdHandle(STD_ERROR_HANDLE) == old_handle) SetStdHandle(STD_ERROR_HANDLE, 0);
265 break;
268 else
270 if (fd == MSVCRT_fdend - 1)
271 MSVCRT_fdend--;
272 if (fd < MSVCRT_fdstart)
273 MSVCRT_fdstart = fd;
275 UNLOCK_FILES();
278 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
279 /* caller must hold the files lock */
280 static int msvcrt_alloc_fd_from(HANDLE hand, int flag, int fd)
282 ioinfo *fdinfo;
284 if (fd >= MSVCRT_MAX_FILES)
286 WARN(":files exhausted!\n");
287 *MSVCRT__errno() = MSVCRT_ENFILE;
288 return -1;
291 fdinfo = msvcrt_get_ioinfo(fd);
292 if(fdinfo == &MSVCRT___badioinfo) {
293 int i;
295 MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo));
296 if(!MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE]) {
297 WARN(":out of memory!\n");
298 *MSVCRT__errno() = MSVCRT_ENOMEM;
299 return -1;
302 for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
303 MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][i].handle = INVALID_HANDLE_VALUE;
305 fdinfo = msvcrt_get_ioinfo(fd);
308 fdinfo->handle = hand;
309 fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT));
311 /* locate next free slot */
312 if (fd == MSVCRT_fdstart && fd == MSVCRT_fdend)
313 MSVCRT_fdstart = MSVCRT_fdend + 1;
314 else
315 while (MSVCRT_fdstart < MSVCRT_fdend &&
316 msvcrt_get_ioinfo(MSVCRT_fdstart)->handle != INVALID_HANDLE_VALUE)
317 MSVCRT_fdstart++;
318 /* update last fd in use */
319 if (fd >= MSVCRT_fdend)
320 MSVCRT_fdend = fd + 1;
321 TRACE("fdstart is %d, fdend is %d\n", MSVCRT_fdstart, MSVCRT_fdend);
323 switch (fd)
325 case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break;
326 case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
327 case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break;
330 return fd;
333 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
334 static int msvcrt_alloc_fd(HANDLE hand, int flag)
336 int ret;
338 LOCK_FILES();
339 TRACE(":handle (%p) allocating fd (%d)\n",hand,MSVCRT_fdstart);
340 ret = msvcrt_alloc_fd_from(hand, flag, MSVCRT_fdstart);
341 UNLOCK_FILES();
342 return ret;
345 /* INTERNAL: Allocate a FILE* for an fd slot */
346 /* caller must hold the files lock */
347 static MSVCRT_FILE* msvcrt_alloc_fp(void)
349 unsigned int i;
350 MSVCRT_FILE *file;
352 for (i = 3; i < MSVCRT_max_streams; i++)
354 file = msvcrt_get_file(i);
355 if (!file)
356 return NULL;
358 if (file->_flag == 0)
360 if (i == MSVCRT_stream_idx) MSVCRT_stream_idx++;
361 return file;
365 return NULL;
368 /* INTERNAL: initialize a FILE* from an open fd */
369 static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags)
371 TRACE(":fd (%d) allocating FILE*\n",fd);
372 if (!msvcrt_is_valid_fd(fd))
374 WARN(":invalid fd %d\n",fd);
375 *MSVCRT___doserrno() = 0;
376 *MSVCRT__errno() = MSVCRT_EBADF;
377 return -1;
379 memset(file, 0, sizeof(*file));
380 file->_file = fd;
381 file->_flag = stream_flags;
383 if(file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
384 InitializeCriticalSection(&((file_crit*)file)->crit);
386 TRACE(":got FILE* (%p)\n",file);
387 return 0;
390 /* INTERNAL: Create an inheritance data block (for spawned process)
391 * The inheritance block is made of:
392 * 00 int nb of file descriptor (NBFD)
393 * 04 char file flags (wxflag): repeated for each fd
394 * 4+NBFD HANDLE file handle: repeated for each fd
396 unsigned msvcrt_create_io_inherit_block(WORD *size, BYTE **block)
398 int fd;
399 char* wxflag_ptr;
400 HANDLE* handle_ptr;
401 ioinfo* fdinfo;
403 *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend;
404 *block = MSVCRT_calloc(*size, 1);
405 if (!*block)
407 *size = 0;
408 return FALSE;
410 wxflag_ptr = (char*)*block + sizeof(unsigned);
411 handle_ptr = (HANDLE*)(wxflag_ptr + MSVCRT_fdend * sizeof(char));
413 *(unsigned*)*block = MSVCRT_fdend;
414 for (fd = 0; fd < MSVCRT_fdend; fd++)
416 /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
417 fdinfo = msvcrt_get_ioinfo(fd);
418 if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN)
420 *wxflag_ptr = fdinfo->wxflag;
421 *handle_ptr = fdinfo->handle;
423 else
425 *wxflag_ptr = 0;
426 *handle_ptr = INVALID_HANDLE_VALUE;
428 wxflag_ptr++; handle_ptr++;
430 return TRUE;
433 /* INTERNAL: Set up all file descriptors,
434 * as well as default streams (stdin, stderr and stdout)
436 void msvcrt_init_io(void)
438 STARTUPINFOA si;
439 int i;
440 ioinfo *fdinfo;
442 InitializeCriticalSection(&MSVCRT_file_cs);
443 MSVCRT_file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs");
444 GetStartupInfoA(&si);
445 if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
447 BYTE* wxflag_ptr;
448 HANDLE* handle_ptr;
449 unsigned int count;
451 count = *(unsigned*)si.lpReserved2;
452 wxflag_ptr = si.lpReserved2 + sizeof(unsigned);
453 handle_ptr = (HANDLE*)(wxflag_ptr + count);
455 count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1));
456 count = min(count, MSVCRT_MAX_FILES);
457 for (i = 0; i < count; i++)
459 if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
460 msvcrt_alloc_fd_from(*handle_ptr, *wxflag_ptr, i);
462 wxflag_ptr++; handle_ptr++;
464 MSVCRT_fdend = max( 3, count );
465 for (MSVCRT_fdstart = 3; MSVCRT_fdstart < MSVCRT_fdend; MSVCRT_fdstart++)
466 if (msvcrt_get_ioinfo(MSVCRT_fdstart)->handle == INVALID_HANDLE_VALUE) break;
469 if(!MSVCRT___pioinfo[0])
470 msvcrt_alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3);
472 fdinfo = msvcrt_get_ioinfo(0);
473 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
475 HANDLE std = GetStdHandle(STD_INPUT_HANDLE);
476 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
477 GetCurrentProcess(), &fdinfo->handle,
478 0, TRUE, DUPLICATE_SAME_ACCESS))
479 fdinfo->wxflag = WX_OPEN | WX_TEXT;
482 fdinfo = msvcrt_get_ioinfo(1);
483 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
485 HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
486 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
487 GetCurrentProcess(), &fdinfo->handle,
488 0, TRUE, DUPLICATE_SAME_ACCESS))
489 fdinfo->wxflag = WX_OPEN | WX_TEXT;
492 fdinfo = msvcrt_get_ioinfo(2);
493 if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
495 HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
496 if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
497 GetCurrentProcess(), &fdinfo->handle,
498 0, TRUE, DUPLICATE_SAME_ACCESS))
499 fdinfo->wxflag = WX_OPEN | WX_TEXT;
502 TRACE(":handles (%p)(%p)(%p)\n", msvcrt_get_ioinfo(0)->handle,
503 msvcrt_get_ioinfo(1)->handle, msvcrt_get_ioinfo(2)->handle);
505 memset(MSVCRT__iob,0,3*sizeof(MSVCRT_FILE));
506 for (i = 0; i < 3; i++)
508 /* FILE structs for stdin/out/err are static and never deleted */
509 MSVCRT__iob[i]._file = i;
510 MSVCRT__iob[i]._tmpfname = NULL;
511 MSVCRT__iob[i]._flag = (i == 0) ? MSVCRT__IOREAD : MSVCRT__IOWRT;
513 MSVCRT_stream_idx = 3;
516 /* INTERNAL: Flush stdio file buffer */
517 static int msvcrt_flush_buffer(MSVCRT_FILE* file)
519 if(file->_bufsiz) {
520 int cnt=file->_ptr-file->_base;
521 if(cnt>0 && MSVCRT__write(file->_file, file->_base, cnt) != cnt) {
522 file->_flag |= MSVCRT__IOERR;
523 return MSVCRT_EOF;
525 file->_ptr=file->_base;
526 file->_cnt=file->_bufsiz;
528 return 0;
531 /* INTERNAL: Allocate stdio file buffer */
532 static void msvcrt_alloc_buffer(MSVCRT_FILE* file)
534 file->_base = MSVCRT_calloc(MSVCRT_BUFSIZ,1);
535 if(file->_base) {
536 file->_bufsiz = MSVCRT_BUFSIZ;
537 file->_flag |= MSVCRT__IOMYBUF;
538 } else {
539 file->_base = (char*)(&file->_charbuf);
540 /* put here 2 ??? */
541 file->_bufsiz = sizeof(file->_charbuf);
543 file->_ptr = file->_base;
544 file->_cnt = 0;
547 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
548 static int msvcrt_int_to_base32(int num, char *str)
550 char *p;
551 int n = num;
552 int digits = 0;
554 while (n != 0)
556 n >>= 5;
557 digits++;
559 p = str + digits;
560 *p = 0;
561 while (--p >= str)
563 *p = (num & 31) + '0';
564 if (*p > '9')
565 *p += ('a' - '0' - 10);
566 num >>= 5;
569 return digits;
572 /* INTERNAL: wide character version of msvcrt_int_to_base32 */
573 static int msvcrt_int_to_base32_w(int num, MSVCRT_wchar_t *str)
575 MSVCRT_wchar_t *p;
576 int n = num;
577 int digits = 0;
579 while (n != 0)
581 n >>= 5;
582 digits++;
584 p = str + digits;
585 *p = 0;
586 while (--p >= str)
588 *p = (num & 31) + '0';
589 if (*p > '9')
590 *p += ('a' - '0' - 10);
591 num >>= 5;
594 return digits;
597 /*********************************************************************
598 * __iob_func(MSVCRT.@)
600 MSVCRT_FILE * CDECL MSVCRT___iob_func(void)
602 return &MSVCRT__iob[0];
605 /*********************************************************************
606 * _access (MSVCRT.@)
608 int CDECL MSVCRT__access(const char *filename, int mode)
610 DWORD attr = GetFileAttributesA(filename);
612 TRACE("(%s,%d) %d\n",filename,mode,attr);
614 if (!filename || attr == INVALID_FILE_ATTRIBUTES)
616 msvcrt_set_errno(GetLastError());
617 return -1;
619 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
621 msvcrt_set_errno(ERROR_ACCESS_DENIED);
622 return -1;
624 return 0;
627 /*********************************************************************
628 * _access_s (MSVCRT.@)
630 int CDECL _access_s(const char *filename, int mode)
632 if (!MSVCRT_CHECK_PMT(filename != NULL) ||
633 !MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0))
635 *MSVCRT__errno() = MSVCRT_EINVAL;
636 return -1;
639 return MSVCRT__access(filename, mode);
642 /*********************************************************************
643 * _waccess (MSVCRT.@)
645 int CDECL _waccess(const MSVCRT_wchar_t *filename, int mode)
647 DWORD attr = GetFileAttributesW(filename);
649 TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr);
651 if (!filename || attr == INVALID_FILE_ATTRIBUTES)
653 msvcrt_set_errno(GetLastError());
654 return -1;
656 if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
658 msvcrt_set_errno(ERROR_ACCESS_DENIED);
659 return -1;
661 return 0;
664 /*********************************************************************
665 * _waccess_s (MSVCRT.@)
667 int CDECL _waccess_s(const MSVCRT_wchar_t *filename, int mode)
669 if (!MSVCRT_CHECK_PMT(filename != NULL) ||
670 !MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0))
672 *MSVCRT__errno() = MSVCRT_EINVAL;
673 return -1;
676 return _waccess(filename, mode);
679 /*********************************************************************
680 * _chmod (MSVCRT.@)
682 int CDECL MSVCRT__chmod(const char *path, int flags)
684 DWORD oldFlags = GetFileAttributesA(path);
686 if (oldFlags != INVALID_FILE_ATTRIBUTES)
688 DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
689 oldFlags | FILE_ATTRIBUTE_READONLY;
691 if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
692 return 0;
694 msvcrt_set_errno(GetLastError());
695 return -1;
698 /*********************************************************************
699 * _wchmod (MSVCRT.@)
701 int CDECL _wchmod(const MSVCRT_wchar_t *path, int flags)
703 DWORD oldFlags = GetFileAttributesW(path);
705 if (oldFlags != INVALID_FILE_ATTRIBUTES)
707 DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
708 oldFlags | FILE_ATTRIBUTE_READONLY;
710 if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
711 return 0;
713 msvcrt_set_errno(GetLastError());
714 return -1;
717 /*********************************************************************
718 * _unlink (MSVCRT.@)
720 int CDECL MSVCRT__unlink(const char *path)
722 TRACE("%s\n",debugstr_a(path));
723 if(DeleteFileA(path))
724 return 0;
725 TRACE("failed (%d)\n",GetLastError());
726 msvcrt_set_errno(GetLastError());
727 return -1;
730 /*********************************************************************
731 * _wunlink (MSVCRT.@)
733 int CDECL _wunlink(const MSVCRT_wchar_t *path)
735 TRACE("(%s)\n",debugstr_w(path));
736 if(DeleteFileW(path))
737 return 0;
738 TRACE("failed (%d)\n",GetLastError());
739 msvcrt_set_errno(GetLastError());
740 return -1;
743 /* _flushall calls MSVCRT_fflush which calls _flushall */
744 int CDECL MSVCRT_fflush(MSVCRT_FILE* file);
746 /*********************************************************************
747 * _flushall (MSVCRT.@)
749 int CDECL _flushall(void)
751 int i, num_flushed = 0;
752 MSVCRT_FILE *file;
754 LOCK_FILES();
755 for (i = 3; i < MSVCRT_stream_idx; i++) {
756 file = msvcrt_get_file(i);
758 if (file->_flag)
760 if(file->_flag & MSVCRT__IOWRT) {
761 MSVCRT_fflush(file);
762 num_flushed++;
766 UNLOCK_FILES();
768 TRACE(":flushed (%d) handles\n",num_flushed);
769 return num_flushed;
772 /*********************************************************************
773 * fflush (MSVCRT.@)
775 int CDECL MSVCRT_fflush(MSVCRT_FILE* file)
777 if(!file) {
778 _flushall();
779 } else if(file->_flag & MSVCRT__IOWRT) {
780 int res=msvcrt_flush_buffer(file);
781 return res;
783 return 0;
786 /*********************************************************************
787 * _close (MSVCRT.@)
789 int CDECL MSVCRT__close(int fd)
791 HANDLE hand;
792 int ret;
794 LOCK_FILES();
795 hand = msvcrt_fdtoh(fd);
796 TRACE(":fd (%d) handle (%p)\n",fd,hand);
797 if (hand == INVALID_HANDLE_VALUE)
798 ret = -1;
799 else if (!CloseHandle(hand))
801 WARN(":failed-last error (%d)\n",GetLastError());
802 msvcrt_set_errno(GetLastError());
803 ret = -1;
805 else
807 msvcrt_free_fd(fd);
808 ret = 0;
810 UNLOCK_FILES();
811 TRACE(":ok\n");
812 return ret;
815 /*********************************************************************
816 * _commit (MSVCRT.@)
818 int CDECL _commit(int fd)
820 HANDLE hand = msvcrt_fdtoh(fd);
822 TRACE(":fd (%d) handle (%p)\n",fd,hand);
823 if (hand == INVALID_HANDLE_VALUE)
824 return -1;
826 if (!FlushFileBuffers(hand))
828 if (GetLastError() == ERROR_INVALID_HANDLE)
830 /* FlushFileBuffers fails for console handles
831 * so we ignore this error.
833 return 0;
835 TRACE(":failed-last error (%d)\n",GetLastError());
836 msvcrt_set_errno(GetLastError());
837 return -1;
839 TRACE(":ok\n");
840 return 0;
843 /*********************************************************************
844 * _dup2 (MSVCRT.@)
845 * NOTES
846 * MSDN isn't clear on this point, but the remarks for _pipe
847 * indicate file descriptors duplicated with _dup and _dup2 are always
848 * inheritable.
850 int CDECL MSVCRT__dup2(int od, int nd)
852 int ret;
854 TRACE("(od=%d, nd=%d)\n", od, nd);
855 LOCK_FILES();
856 if (nd < MSVCRT_MAX_FILES && nd >= 0 && msvcrt_is_valid_fd(od))
858 HANDLE handle;
860 if (DuplicateHandle(GetCurrentProcess(), msvcrt_get_ioinfo(od)->handle,
861 GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
863 int wxflag = msvcrt_get_ioinfo(od)->wxflag & ~MSVCRT__O_NOINHERIT;
865 if (msvcrt_is_valid_fd(nd))
866 MSVCRT__close(nd);
867 ret = msvcrt_alloc_fd_from(handle, wxflag, nd);
868 if (ret == -1)
870 CloseHandle(handle);
871 *MSVCRT__errno() = MSVCRT_EMFILE;
873 else
875 /* _dup2 returns 0, not nd, on success */
876 ret = 0;
879 else
881 ret = -1;
882 msvcrt_set_errno(GetLastError());
885 else
887 *MSVCRT__errno() = MSVCRT_EBADF;
888 ret = -1;
890 UNLOCK_FILES();
891 return ret;
894 /*********************************************************************
895 * _dup (MSVCRT.@)
897 int CDECL MSVCRT__dup(int od)
899 int fd, ret;
901 LOCK_FILES();
902 fd = MSVCRT_fdstart;
903 if (MSVCRT__dup2(od, fd) == 0)
904 ret = fd;
905 else
906 ret = -1;
907 UNLOCK_FILES();
908 return ret;
911 /*********************************************************************
912 * _eof (MSVCRT.@)
914 int CDECL _eof(int fd)
916 DWORD curpos,endpos;
917 LONG hcurpos,hendpos;
918 HANDLE hand = msvcrt_fdtoh(fd);
920 TRACE(":fd (%d) handle (%p)\n",fd,hand);
922 if (hand == INVALID_HANDLE_VALUE)
923 return -1;
925 if (msvcrt_get_ioinfo(fd)->wxflag & WX_ATEOF) return TRUE;
927 /* Otherwise we do it the hard way */
928 hcurpos = hendpos = 0;
929 curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT);
930 endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
932 if (curpos == endpos && hcurpos == hendpos)
934 /* FIXME: shouldn't WX_ATEOF be set here? */
935 return TRUE;
938 SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
939 return FALSE;
942 /*********************************************************************
943 * _fcloseall (MSVCRT.@)
945 int CDECL MSVCRT__fcloseall(void)
947 int num_closed = 0, i;
948 MSVCRT_FILE *file;
950 LOCK_FILES();
951 for (i = 3; i < MSVCRT_stream_idx; i++) {
952 file = msvcrt_get_file(i);
954 if (file->_flag && !MSVCRT_fclose(file))
955 num_closed++;
957 UNLOCK_FILES();
959 TRACE(":closed (%d) handles\n",num_closed);
960 return num_closed;
963 /* free everything on process exit */
964 void msvcrt_free_io(void)
966 int i;
968 MSVCRT__fcloseall();
969 /* The Win32 _fcloseall() function explicitly doesn't close stdin,
970 * stdout, and stderr (unlike GNU), so we need to fclose() them here
971 * or they won't get flushed.
973 MSVCRT_fclose(&MSVCRT__iob[0]);
974 MSVCRT_fclose(&MSVCRT__iob[1]);
975 MSVCRT_fclose(&MSVCRT__iob[2]);
977 for(i=0; i<sizeof(MSVCRT___pioinfo)/sizeof(MSVCRT___pioinfo[0]); i++)
978 MSVCRT_free(MSVCRT___pioinfo[i]);
980 for(i=0; i<sizeof(MSVCRT_fstream)/sizeof(MSVCRT_fstream[0]); i++)
981 MSVCRT_free(MSVCRT_fstream[i]);
983 MSVCRT_file_cs.DebugInfo->Spare[0] = 0;
984 DeleteCriticalSection(&MSVCRT_file_cs);
987 /*********************************************************************
988 * _lseeki64 (MSVCRT.@)
990 __int64 CDECL MSVCRT__lseeki64(int fd, __int64 offset, int whence)
992 HANDLE hand = msvcrt_fdtoh(fd);
993 LARGE_INTEGER ofs;
995 TRACE(":fd (%d) handle (%p)\n",fd,hand);
996 if (hand == INVALID_HANDLE_VALUE)
997 return -1;
999 if (whence < 0 || whence > 2)
1001 *MSVCRT__errno() = MSVCRT_EINVAL;
1002 return -1;
1005 TRACE(":fd (%d) to %s pos %s\n",
1006 fd,wine_dbgstr_longlong(offset),
1007 (whence==SEEK_SET)?"SEEK_SET":
1008 (whence==SEEK_CUR)?"SEEK_CUR":
1009 (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
1011 /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
1012 * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
1013 ofs.QuadPart = offset;
1014 if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
1015 GetLastError() == ERROR_SUCCESS)
1017 msvcrt_get_ioinfo(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF);
1018 /* FIXME: What if we seek _to_ EOF - is EOF set? */
1020 return ofs.QuadPart;
1022 TRACE(":error-last error (%d)\n",GetLastError());
1023 msvcrt_set_errno(GetLastError());
1024 return -1;
1027 /*********************************************************************
1028 * _lseek (MSVCRT.@)
1030 LONG CDECL MSVCRT__lseek(int fd, LONG offset, int whence)
1032 return MSVCRT__lseeki64(fd, offset, whence);
1035 /*********************************************************************
1036 * _lock_file (MSVCRT.@)
1038 void CDECL MSVCRT__lock_file(MSVCRT_FILE *file)
1040 if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1041 _lock(_STREAM_LOCKS+(file-MSVCRT__iob));
1042 else
1043 EnterCriticalSection(&((file_crit*)file)->crit);
1046 /*********************************************************************
1047 * _unlock_file (MSVCRT.@)
1049 void CDECL MSVCRT__unlock_file(MSVCRT_FILE *file)
1051 if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1052 _unlock(_STREAM_LOCKS+(file-MSVCRT__iob));
1053 else
1054 LeaveCriticalSection(&((file_crit*)file)->crit);
1057 /*********************************************************************
1058 * _locking (MSVCRT.@)
1060 * This is untested; the underlying LockFile doesn't work yet.
1062 int CDECL MSVCRT__locking(int fd, int mode, LONG nbytes)
1064 BOOL ret;
1065 DWORD cur_locn;
1066 HANDLE hand = msvcrt_fdtoh(fd);
1068 TRACE(":fd (%d) handle (%p)\n",fd,hand);
1069 if (hand == INVALID_HANDLE_VALUE)
1070 return -1;
1072 if (mode < 0 || mode > 4)
1074 *MSVCRT__errno() = MSVCRT_EINVAL;
1075 return -1;
1078 TRACE(":fd (%d) by 0x%08x mode %s\n",
1079 fd,nbytes,(mode==MSVCRT__LK_UNLCK)?"_LK_UNLCK":
1080 (mode==MSVCRT__LK_LOCK)?"_LK_LOCK":
1081 (mode==MSVCRT__LK_NBLCK)?"_LK_NBLCK":
1082 (mode==MSVCRT__LK_RLCK)?"_LK_RLCK":
1083 (mode==MSVCRT__LK_NBRLCK)?"_LK_NBRLCK":
1084 "UNKNOWN");
1086 if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
1088 FIXME ("Seek failed\n");
1089 *MSVCRT__errno() = MSVCRT_EINVAL; /* FIXME */
1090 return -1;
1092 if (mode == MSVCRT__LK_LOCK || mode == MSVCRT__LK_RLCK)
1094 int nretry = 10;
1095 ret = 1; /* just to satisfy gcc */
1096 while (nretry--)
1098 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
1099 if (ret) break;
1100 Sleep(1);
1103 else if (mode == MSVCRT__LK_UNLCK)
1104 ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
1105 else
1106 ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
1107 /* FIXME - what about error settings? */
1108 return ret ? 0 : -1;
1111 /*********************************************************************
1112 * _fseeki64 (MSVCRT.@)
1114 int CDECL MSVCRT__fseeki64(MSVCRT_FILE* file, __int64 offset, int whence)
1116 /* Flush output if needed */
1117 if(file->_flag & MSVCRT__IOWRT)
1118 msvcrt_flush_buffer(file);
1120 if(whence == SEEK_CUR && file->_flag & MSVCRT__IOREAD ) {
1121 offset -= file->_cnt;
1122 if (msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
1123 /* Black magic correction for CR removal */
1124 int i;
1125 for (i=0; i<file->_cnt; i++) {
1126 if (file->_ptr[i] == '\n')
1127 offset--;
1129 /* Black magic when reading CR at buffer boundary*/
1130 if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_READCR)
1131 offset--;
1134 /* Discard buffered input */
1135 file->_cnt = 0;
1136 file->_ptr = file->_base;
1137 /* Reset direction of i/o */
1138 if(file->_flag & MSVCRT__IORW) {
1139 file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
1141 /* Clear end of file flag */
1142 file->_flag &= ~MSVCRT__IOEOF;
1143 return (MSVCRT__lseeki64(file->_file,offset,whence) == -1)?-1:0;
1146 /*********************************************************************
1147 * fseek (MSVCRT.@)
1149 int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
1151 return MSVCRT__fseeki64( file, offset, whence );
1154 /*********************************************************************
1155 * _chsize (MSVCRT.@)
1157 int CDECL MSVCRT__chsize(int fd, MSVCRT_long size)
1159 LONG cur, pos;
1160 HANDLE handle;
1161 BOOL ret = FALSE;
1163 TRACE("(fd=%d, size=%d)\n", fd, size);
1165 LOCK_FILES();
1167 handle = msvcrt_fdtoh(fd);
1168 if (handle != INVALID_HANDLE_VALUE)
1170 /* save the current file pointer */
1171 cur = MSVCRT__lseek(fd, 0, SEEK_CUR);
1172 if (cur >= 0)
1174 pos = MSVCRT__lseek(fd, size, SEEK_SET);
1175 if (pos >= 0)
1177 ret = SetEndOfFile(handle);
1178 if (!ret) msvcrt_set_errno(GetLastError());
1181 /* restore the file pointer */
1182 MSVCRT__lseek(fd, cur, SEEK_SET);
1186 UNLOCK_FILES();
1187 return ret ? 0 : -1;
1190 /*********************************************************************
1191 * clearerr (MSVCRT.@)
1193 void CDECL MSVCRT_clearerr(MSVCRT_FILE* file)
1195 TRACE(":file (%p) fd (%d)\n",file,file->_file);
1196 file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
1199 /*********************************************************************
1200 * rewind (MSVCRT.@)
1202 void CDECL MSVCRT_rewind(MSVCRT_FILE* file)
1204 TRACE(":file (%p) fd (%d)\n",file,file->_file);
1205 MSVCRT_fseek(file, 0L, SEEK_SET);
1206 MSVCRT_clearerr(file);
1209 static int msvcrt_get_flags(const MSVCRT_wchar_t* mode, int *open_flags, int* stream_flags)
1211 int plus = strchrW(mode, '+') != NULL;
1213 switch(*mode++)
1215 case 'R': case 'r':
1216 *open_flags = plus ? MSVCRT__O_RDWR : MSVCRT__O_RDONLY;
1217 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOREAD;
1218 break;
1219 case 'W': case 'w':
1220 *open_flags = MSVCRT__O_CREAT | MSVCRT__O_TRUNC | (plus ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1221 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1222 break;
1223 case 'A': case 'a':
1224 *open_flags = MSVCRT__O_CREAT | MSVCRT__O_APPEND | (plus ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1225 *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1226 break;
1227 default:
1228 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1229 *MSVCRT__errno() = MSVCRT_EINVAL;
1230 return -1;
1233 while (*mode)
1234 switch (*mode++)
1236 case 'B': case 'b':
1237 *open_flags |= MSVCRT__O_BINARY;
1238 *open_flags &= ~MSVCRT__O_TEXT;
1239 break;
1240 case 'T': case 't':
1241 *open_flags |= MSVCRT__O_TEXT;
1242 *open_flags &= ~MSVCRT__O_BINARY;
1243 break;
1244 case '+':
1245 case ' ':
1246 break;
1247 default:
1248 FIXME(":unknown flag %c not supported\n",mode[-1]);
1250 return 0;
1253 /*********************************************************************
1254 * _fdopen (MSVCRT.@)
1256 MSVCRT_FILE* CDECL MSVCRT__fdopen(int fd, const char *mode)
1258 MSVCRT_FILE *ret;
1259 MSVCRT_wchar_t *modeW = NULL;
1261 if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
1263 ret = MSVCRT__wfdopen(fd, modeW);
1265 MSVCRT_free(modeW);
1266 return ret;
1269 /*********************************************************************
1270 * _wfdopen (MSVCRT.@)
1272 MSVCRT_FILE* CDECL MSVCRT__wfdopen(int fd, const MSVCRT_wchar_t *mode)
1274 int open_flags, stream_flags;
1275 MSVCRT_FILE* file;
1277 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
1279 LOCK_FILES();
1280 if (!(file = msvcrt_alloc_fp()))
1281 file = NULL;
1282 else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
1284 file->_flag = 0;
1285 file = NULL;
1287 else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
1288 UNLOCK_FILES();
1290 return file;
1293 /*********************************************************************
1294 * _filelength (MSVCRT.@)
1296 LONG CDECL MSVCRT__filelength(int fd)
1298 LONG curPos = MSVCRT__lseek(fd, 0, SEEK_CUR);
1299 if (curPos != -1)
1301 LONG endPos = MSVCRT__lseek(fd, 0, SEEK_END);
1302 if (endPos != -1)
1304 if (endPos != curPos)
1305 MSVCRT__lseek(fd, curPos, SEEK_SET);
1306 return endPos;
1309 return -1;
1312 /*********************************************************************
1313 * _filelengthi64 (MSVCRT.@)
1315 __int64 CDECL MSVCRT__filelengthi64(int fd)
1317 __int64 curPos = MSVCRT__lseeki64(fd, 0, SEEK_CUR);
1318 if (curPos != -1)
1320 __int64 endPos = MSVCRT__lseeki64(fd, 0, SEEK_END);
1321 if (endPos != -1)
1323 if (endPos != curPos)
1324 MSVCRT__lseeki64(fd, curPos, SEEK_SET);
1325 return endPos;
1328 return -1;
1331 /*********************************************************************
1332 * _fileno (MSVCRT.@)
1334 int CDECL MSVCRT__fileno(MSVCRT_FILE* file)
1336 TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
1337 return file->_file;
1340 /*********************************************************************
1341 * _fstat64 (MSVCRT.@)
1343 int CDECL MSVCRT__fstat64(int fd, struct MSVCRT__stat64* buf)
1345 DWORD dw;
1346 DWORD type;
1347 BY_HANDLE_FILE_INFORMATION hfi;
1348 HANDLE hand = msvcrt_fdtoh(fd);
1350 TRACE(":fd (%d) stat (%p)\n",fd,buf);
1351 if (hand == INVALID_HANDLE_VALUE)
1352 return -1;
1354 if (!buf)
1356 WARN(":failed-NULL buf\n");
1357 msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1358 return -1;
1361 memset(&hfi, 0, sizeof(hfi));
1362 memset(buf, 0, sizeof(struct MSVCRT__stat64));
1363 type = GetFileType(hand);
1364 if (type == FILE_TYPE_PIPE)
1366 buf->st_dev = buf->st_rdev = fd;
1367 buf->st_mode = S_IFIFO;
1368 buf->st_nlink = 1;
1370 else if (type == FILE_TYPE_CHAR)
1372 buf->st_dev = buf->st_rdev = fd;
1373 buf->st_mode = S_IFCHR;
1374 buf->st_nlink = 1;
1376 else /* FILE_TYPE_DISK etc. */
1378 if (!GetFileInformationByHandle(hand, &hfi))
1380 WARN(":failed-last error (%d)\n",GetLastError());
1381 msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1382 return -1;
1384 buf->st_mode = S_IFREG | 0444;
1385 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1386 buf->st_mode |= 0222;
1387 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
1388 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
1389 buf->st_atime = dw;
1390 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
1391 buf->st_mtime = buf->st_ctime = dw;
1392 buf->st_nlink = hfi.nNumberOfLinks;
1394 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes,
1395 buf->st_mode);
1396 return 0;
1399 /*********************************************************************
1400 * _fstati64 (MSVCRT.@)
1402 int CDECL MSVCRT__fstati64(int fd, struct MSVCRT__stati64* buf)
1404 int ret;
1405 struct MSVCRT__stat64 buf64;
1407 ret = MSVCRT__fstat64(fd, &buf64);
1408 if (!ret)
1409 msvcrt_stat64_to_stati64(&buf64, buf);
1410 return ret;
1413 /*********************************************************************
1414 * _fstat (MSVCRT.@)
1416 int CDECL MSVCRT__fstat(int fd, struct MSVCRT__stat* buf)
1417 { int ret;
1418 struct MSVCRT__stat64 buf64;
1420 ret = MSVCRT__fstat64(fd, &buf64);
1421 if (!ret)
1422 msvcrt_stat64_to_stat(&buf64, buf);
1423 return ret;
1426 /*********************************************************************
1427 * _futime64 (MSVCRT.@)
1429 int CDECL _futime64(int fd, struct MSVCRT___utimbuf64 *t)
1431 HANDLE hand = msvcrt_fdtoh(fd);
1432 FILETIME at, wt;
1434 if (!t)
1436 time_to_filetime( MSVCRT__time64(NULL), &at );
1437 wt = at;
1439 else
1441 time_to_filetime( t->actime, &at );
1442 time_to_filetime( t->modtime, &wt );
1445 if (!SetFileTime(hand, NULL, &at, &wt))
1447 msvcrt_set_errno(GetLastError());
1448 return -1 ;
1450 return 0;
1453 /*********************************************************************
1454 * _futime32 (MSVCRT.@)
1456 int CDECL _futime32(int fd, struct MSVCRT___utimbuf32 *t)
1458 struct MSVCRT___utimbuf64 t64;
1459 t64.actime = t->actime;
1460 t64.modtime = t->modtime;
1461 return _futime64( fd, &t64 );
1464 /*********************************************************************
1465 * _futime (MSVCRT.@)
1467 #ifdef _WIN64
1468 int CDECL _futime(int fd, struct MSVCRT___utimbuf64 *t)
1470 return _futime64( fd, t );
1472 #else
1473 int CDECL _futime(int fd, struct MSVCRT___utimbuf32 *t)
1475 return _futime32( fd, t );
1477 #endif
1479 /*********************************************************************
1480 * _get_osfhandle (MSVCRT.@)
1482 MSVCRT_intptr_t CDECL _get_osfhandle(int fd)
1484 HANDLE hand = msvcrt_fdtoh(fd);
1485 TRACE(":fd (%d) handle (%p)\n",fd,hand);
1487 return (MSVCRT_intptr_t)hand;
1490 /*********************************************************************
1491 * _isatty (MSVCRT.@)
1493 int CDECL _isatty(int fd)
1495 HANDLE hand = msvcrt_fdtoh(fd);
1497 TRACE(":fd (%d) handle (%p)\n",fd,hand);
1498 if (hand == INVALID_HANDLE_VALUE)
1499 return 0;
1501 return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
1504 /*********************************************************************
1505 * _mktemp (MSVCRT.@)
1507 char * CDECL _mktemp(char *pattern)
1509 int numX = 0;
1510 char *retVal = pattern;
1511 int id;
1512 char letter = 'a';
1514 while(*pattern)
1515 numX = (*pattern++ == 'X')? numX + 1 : 0;
1516 if (numX < 5)
1517 return NULL;
1518 pattern--;
1519 id = GetCurrentProcessId();
1520 numX = 6;
1521 while(numX--)
1523 int tempNum = id / 10;
1524 *pattern-- = id - (tempNum * 10) + '0';
1525 id = tempNum;
1527 pattern++;
1530 *pattern = letter++;
1531 if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES &&
1532 GetLastError() == ERROR_FILE_NOT_FOUND)
1533 return retVal;
1534 } while(letter <= 'z');
1535 return NULL;
1538 /*********************************************************************
1539 * _wmktemp (MSVCRT.@)
1541 MSVCRT_wchar_t * CDECL _wmktemp(MSVCRT_wchar_t *pattern)
1543 int numX = 0;
1544 MSVCRT_wchar_t *retVal = pattern;
1545 int id;
1546 MSVCRT_wchar_t letter = 'a';
1548 while(*pattern)
1549 numX = (*pattern++ == 'X')? numX + 1 : 0;
1550 if (numX < 5)
1551 return NULL;
1552 pattern--;
1553 id = GetCurrentProcessId();
1554 numX = 6;
1555 while(numX--)
1557 int tempNum = id / 10;
1558 *pattern-- = id - (tempNum * 10) + '0';
1559 id = tempNum;
1561 pattern++;
1564 if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES &&
1565 GetLastError() == ERROR_FILE_NOT_FOUND)
1566 return retVal;
1567 *pattern = letter++;
1568 } while(letter != '|');
1569 return NULL;
1572 static unsigned split_oflags(unsigned oflags)
1574 int wxflags = 0;
1575 unsigned unsupp; /* until we support everything */
1577 if (oflags & MSVCRT__O_APPEND) wxflags |= WX_APPEND;
1578 if (oflags & MSVCRT__O_BINARY) {/* Nothing to do */}
1579 else if (oflags & MSVCRT__O_TEXT) wxflags |= WX_TEXT;
1580 else if (*__p__fmode() & MSVCRT__O_BINARY) {/* Nothing to do */}
1581 else wxflags |= WX_TEXT; /* default to TEXT*/
1582 if (oflags & MSVCRT__O_NOINHERIT) wxflags |= WX_DONTINHERIT;
1584 if ((unsupp = oflags & ~(
1585 MSVCRT__O_BINARY|MSVCRT__O_TEXT|MSVCRT__O_APPEND|
1586 MSVCRT__O_TRUNC|MSVCRT__O_EXCL|MSVCRT__O_CREAT|
1587 MSVCRT__O_RDWR|MSVCRT__O_WRONLY|MSVCRT__O_TEMPORARY|
1588 MSVCRT__O_NOINHERIT|
1589 MSVCRT__O_SEQUENTIAL|MSVCRT__O_RANDOM|MSVCRT__O_SHORT_LIVED
1591 ERR(":unsupported oflags 0x%04x\n",unsupp);
1593 return wxflags;
1596 /*********************************************************************
1597 * _pipe (MSVCRT.@)
1599 int CDECL MSVCRT__pipe(int *pfds, unsigned int psize, int textmode)
1601 int ret = -1;
1602 SECURITY_ATTRIBUTES sa;
1603 HANDLE readHandle, writeHandle;
1605 if (!pfds)
1607 *MSVCRT__errno() = MSVCRT_EINVAL;
1608 return -1;
1611 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1612 sa.bInheritHandle = !(textmode & MSVCRT__O_NOINHERIT);
1613 sa.lpSecurityDescriptor = NULL;
1614 if (CreatePipe(&readHandle, &writeHandle, &sa, psize))
1616 unsigned int wxflags = split_oflags(textmode);
1617 int fd;
1619 LOCK_FILES();
1620 fd = msvcrt_alloc_fd(readHandle, wxflags);
1621 if (fd != -1)
1623 pfds[0] = fd;
1624 fd = msvcrt_alloc_fd(writeHandle, wxflags);
1625 if (fd != -1)
1627 pfds[1] = fd;
1628 ret = 0;
1630 else
1632 MSVCRT__close(pfds[0]);
1633 CloseHandle(writeHandle);
1634 *MSVCRT__errno() = MSVCRT_EMFILE;
1637 else
1639 CloseHandle(readHandle);
1640 CloseHandle(writeHandle);
1641 *MSVCRT__errno() = MSVCRT_EMFILE;
1643 UNLOCK_FILES();
1645 else
1646 msvcrt_set_errno(GetLastError());
1648 return ret;
1651 /*********************************************************************
1652 * _sopen_s (MSVCRT.@)
1654 int CDECL MSVCRT__sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
1656 DWORD access = 0, creation = 0, attrib;
1657 DWORD sharing;
1658 int wxflag;
1659 HANDLE hand;
1660 SECURITY_ATTRIBUTES sa;
1662 TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
1663 fd, path, oflags, shflags, pmode);
1665 if (!fd)
1667 MSVCRT_INVALID_PMT("null out fd pointer");
1668 *MSVCRT__errno() = MSVCRT_EINVAL;
1669 return MSVCRT_EINVAL;
1672 *fd = -1;
1673 wxflag = split_oflags(oflags);
1674 switch (oflags & (MSVCRT__O_RDONLY | MSVCRT__O_WRONLY | MSVCRT__O_RDWR))
1676 case MSVCRT__O_RDONLY: access |= GENERIC_READ; break;
1677 case MSVCRT__O_WRONLY: access |= GENERIC_WRITE; break;
1678 case MSVCRT__O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
1681 if (oflags & MSVCRT__O_CREAT)
1683 if(pmode & ~(MSVCRT__S_IREAD | MSVCRT__S_IWRITE))
1684 FIXME(": pmode 0x%04x ignored\n", pmode);
1685 else
1686 WARN(": pmode 0x%04x ignored\n", pmode);
1688 if (oflags & MSVCRT__O_EXCL)
1689 creation = CREATE_NEW;
1690 else if (oflags & MSVCRT__O_TRUNC)
1691 creation = CREATE_ALWAYS;
1692 else
1693 creation = OPEN_ALWAYS;
1695 else /* no MSVCRT__O_CREAT */
1697 if (oflags & MSVCRT__O_TRUNC)
1698 creation = TRUNCATE_EXISTING;
1699 else
1700 creation = OPEN_EXISTING;
1703 switch( shflags )
1705 case MSVCRT__SH_DENYRW:
1706 sharing = 0L;
1707 break;
1708 case MSVCRT__SH_DENYWR:
1709 sharing = FILE_SHARE_READ;
1710 break;
1711 case MSVCRT__SH_DENYRD:
1712 sharing = FILE_SHARE_WRITE;
1713 break;
1714 case MSVCRT__SH_DENYNO:
1715 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
1716 break;
1717 default:
1718 ERR( "Unhandled shflags 0x%x\n", shflags );
1719 return MSVCRT_EINVAL;
1721 attrib = FILE_ATTRIBUTE_NORMAL;
1723 if (oflags & MSVCRT__O_TEMPORARY)
1725 attrib |= FILE_FLAG_DELETE_ON_CLOSE;
1726 access |= DELETE;
1727 sharing |= FILE_SHARE_DELETE;
1730 sa.nLength = sizeof( SECURITY_ATTRIBUTES );
1731 sa.lpSecurityDescriptor = NULL;
1732 sa.bInheritHandle = (oflags & MSVCRT__O_NOINHERIT) ? FALSE : TRUE;
1734 hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
1735 if (hand == INVALID_HANDLE_VALUE) {
1736 WARN(":failed-last error (%d)\n", GetLastError());
1737 msvcrt_set_errno(GetLastError());
1738 return *MSVCRT__errno();
1741 *fd = msvcrt_alloc_fd(hand, wxflag);
1743 TRACE(":fd (%d) handle (%p)\n", *fd, hand);
1744 return 0;
1747 /*********************************************************************
1748 * _sopen (MSVCRT.@)
1750 int CDECL MSVCRT__sopen( const char *path, int oflags, int shflags, ... )
1752 int pmode;
1753 int fd;
1755 if (oflags & MSVCRT__O_CREAT)
1757 __ms_va_list ap;
1759 __ms_va_start(ap, shflags);
1760 pmode = va_arg(ap, int);
1761 __ms_va_end(ap);
1763 else
1764 pmode = 0;
1766 MSVCRT__sopen_s(&fd, path, oflags, shflags, pmode);
1767 return fd;
1770 /*********************************************************************
1771 * _wsopen_s (MSVCRT.@)
1773 int CDECL MSVCRT__wsopen_s( int *fd, const MSVCRT_wchar_t* path, int oflags, int shflags, int pmode )
1775 DWORD access = 0, creation = 0, attrib;
1776 SECURITY_ATTRIBUTES sa;
1777 DWORD sharing;
1778 int wxflag;
1779 HANDLE hand;
1781 TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
1782 fd, debugstr_w(path), oflags, shflags, pmode);
1784 if (!fd)
1786 MSVCRT_INVALID_PMT("null out fd pointer");
1787 *MSVCRT__errno() = MSVCRT_EINVAL;
1788 return MSVCRT_EINVAL;
1791 *fd = -1;
1792 wxflag = split_oflags(oflags);
1793 switch (oflags & (MSVCRT__O_RDONLY | MSVCRT__O_WRONLY | MSVCRT__O_RDWR))
1795 case MSVCRT__O_RDONLY: access |= GENERIC_READ; break;
1796 case MSVCRT__O_WRONLY: access |= GENERIC_WRITE; break;
1797 case MSVCRT__O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
1800 if (oflags & MSVCRT__O_CREAT)
1802 if(pmode & ~(MSVCRT__S_IREAD | MSVCRT__S_IWRITE))
1803 FIXME(": pmode 0x%04x ignored\n", pmode);
1804 else
1805 WARN(": pmode 0x%04x ignored\n", pmode);
1807 if (oflags & MSVCRT__O_EXCL)
1808 creation = CREATE_NEW;
1809 else if (oflags & MSVCRT__O_TRUNC)
1810 creation = CREATE_ALWAYS;
1811 else
1812 creation = OPEN_ALWAYS;
1814 else /* no MSVCRT__O_CREAT */
1816 if (oflags & MSVCRT__O_TRUNC)
1817 creation = TRUNCATE_EXISTING;
1818 else
1819 creation = OPEN_EXISTING;
1822 switch( shflags )
1824 case MSVCRT__SH_DENYRW:
1825 sharing = 0L;
1826 break;
1827 case MSVCRT__SH_DENYWR:
1828 sharing = FILE_SHARE_READ;
1829 break;
1830 case MSVCRT__SH_DENYRD:
1831 sharing = FILE_SHARE_WRITE;
1832 break;
1833 case MSVCRT__SH_DENYNO:
1834 sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
1835 break;
1836 default:
1837 ERR( "Unhandled shflags 0x%x\n", shflags );
1838 return MSVCRT_EINVAL;
1840 attrib = FILE_ATTRIBUTE_NORMAL;
1842 if (oflags & MSVCRT__O_TEMPORARY)
1844 attrib |= FILE_FLAG_DELETE_ON_CLOSE;
1845 access |= DELETE;
1846 sharing |= FILE_SHARE_DELETE;
1849 sa.nLength = sizeof( SECURITY_ATTRIBUTES );
1850 sa.lpSecurityDescriptor = NULL;
1851 sa.bInheritHandle = (oflags & MSVCRT__O_NOINHERIT) ? FALSE : TRUE;
1853 hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
1855 if (hand == INVALID_HANDLE_VALUE) {
1856 WARN(":failed-last error (%d)\n",GetLastError());
1857 msvcrt_set_errno(GetLastError());
1858 msvcrt_set_errno(GetLastError());
1859 return *MSVCRT__errno();
1862 *fd = msvcrt_alloc_fd(hand, wxflag);
1864 TRACE(":fd (%d) handle (%p)\n", *fd, hand);
1865 return 0;
1868 /*********************************************************************
1869 * _wsopen (MSVCRT.@)
1871 int CDECL MSVCRT__wsopen( const MSVCRT_wchar_t *path, int oflags, int shflags, ... )
1873 int pmode;
1874 int fd;
1876 if (oflags & MSVCRT__O_CREAT)
1878 __ms_va_list ap;
1880 __ms_va_start(ap, shflags);
1881 pmode = va_arg(ap, int);
1882 __ms_va_end(ap);
1884 else
1885 pmode = 0;
1887 MSVCRT__wsopen_s(&fd, path, oflags, shflags, pmode);
1888 return fd;
1891 /*********************************************************************
1892 * _open (MSVCRT.@)
1894 int CDECL MSVCRT__open( const char *path, int flags, ... )
1896 __ms_va_list ap;
1898 if (flags & MSVCRT__O_CREAT)
1900 int pmode;
1901 __ms_va_start(ap, flags);
1902 pmode = va_arg(ap, int);
1903 __ms_va_end(ap);
1904 return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO, pmode );
1906 else
1907 return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO);
1910 /*********************************************************************
1911 * _wopen (MSVCRT.@)
1913 int CDECL _wopen(const MSVCRT_wchar_t *path,int flags,...)
1915 __ms_va_list ap;
1917 if (flags & MSVCRT__O_CREAT)
1919 int pmode;
1920 __ms_va_start(ap, flags);
1921 pmode = va_arg(ap, int);
1922 __ms_va_end(ap);
1923 return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO, pmode );
1925 else
1926 return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO);
1929 /*********************************************************************
1930 * _creat (MSVCRT.@)
1932 int CDECL MSVCRT__creat(const char *path, int flags)
1934 int usedFlags = (flags & MSVCRT__O_TEXT)| MSVCRT__O_CREAT| MSVCRT__O_WRONLY| MSVCRT__O_TRUNC;
1935 return MSVCRT__open(path, usedFlags);
1938 /*********************************************************************
1939 * _wcreat (MSVCRT.@)
1941 int CDECL _wcreat(const MSVCRT_wchar_t *path, int flags)
1943 int usedFlags = (flags & MSVCRT__O_TEXT)| MSVCRT__O_CREAT| MSVCRT__O_WRONLY| MSVCRT__O_TRUNC;
1944 return _wopen(path, usedFlags);
1947 /*********************************************************************
1948 * _open_osfhandle (MSVCRT.@)
1950 int CDECL _open_osfhandle(MSVCRT_intptr_t handle, int oflags)
1952 int fd;
1954 /* MSVCRT__O_RDONLY (0) always matches, so set the read flag
1955 * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
1956 * file, so set the write flag. It also only sets MSVCRT__O_TEXT if it wants
1957 * text - it never sets MSVCRT__O_BINARY.
1959 /* don't let split_oflags() decide the mode if no mode is passed */
1960 if (!(oflags & (MSVCRT__O_BINARY | MSVCRT__O_TEXT)))
1961 oflags |= MSVCRT__O_BINARY;
1963 fd = msvcrt_alloc_fd((HANDLE)handle, split_oflags(oflags));
1964 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags);
1965 return fd;
1968 /*********************************************************************
1969 * _rmtmp (MSVCRT.@)
1971 int CDECL _rmtmp(void)
1973 int num_removed = 0, i;
1974 MSVCRT_FILE *file;
1976 LOCK_FILES();
1977 for (i = 3; i < MSVCRT_stream_idx; i++) {
1978 file = msvcrt_get_file(i);
1980 if (file->_tmpfname)
1982 MSVCRT_fclose(file);
1983 num_removed++;
1986 UNLOCK_FILES();
1988 if (num_removed)
1989 TRACE(":removed (%d) temp files\n",num_removed);
1990 return num_removed;
1993 /*********************************************************************
1994 * (internal) read_i
1996 * When reading \r as last character in text mode, read() positions
1997 * the file pointer on the \r character while getc() goes on to
1998 * the following \n
2000 static int read_i(int fd, void *buf, unsigned int count)
2002 DWORD num_read;
2003 char *bufstart = buf;
2004 HANDLE hand = msvcrt_fdtoh(fd);
2005 ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
2007 if (count == 0)
2008 return 0;
2010 if (fdinfo->wxflag & WX_READEOF) {
2011 fdinfo->wxflag |= WX_ATEOF;
2012 TRACE("already at EOF, returning 0\n");
2013 return 0;
2015 /* Don't trace small reads, it gets *very* annoying */
2016 if (count > 4)
2017 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
2018 if (hand == INVALID_HANDLE_VALUE)
2019 return -1;
2021 /* Reading single bytes in O_TEXT mode makes things slow
2022 * So read big chunks
2024 if (ReadFile(hand, bufstart, count, &num_read, NULL))
2026 if (count != 0 && num_read == 0)
2028 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
2029 TRACE(":EOF %s\n",debugstr_an(buf,num_read));
2031 else if (fdinfo->wxflag & WX_TEXT)
2033 DWORD i, j;
2034 if (bufstart[num_read-1] == '\r')
2036 if(count == 1)
2038 fdinfo->wxflag &= ~WX_READCR;
2039 ReadFile(hand, bufstart, 1, &num_read, NULL);
2041 else
2043 fdinfo->wxflag |= WX_READCR;
2044 num_read--;
2047 else
2048 fdinfo->wxflag &= ~WX_READCR;
2049 for (i=0, j=0; i<num_read; i++)
2051 /* in text mode, a ctrl-z signals EOF */
2052 if (bufstart[i] == 0x1a)
2054 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
2055 TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
2056 break;
2058 /* in text mode, strip \r if followed by \n.
2059 * BUG: should save state across calls somehow, so CR LF that
2060 * straddles buffer boundary gets recognized properly?
2062 if ((bufstart[i] != '\r')
2063 || ((i+1) < num_read && bufstart[i+1] != '\n'))
2064 bufstart[j++] = bufstart[i];
2066 num_read = j;
2069 else
2071 if (GetLastError() == ERROR_BROKEN_PIPE)
2073 TRACE(":end-of-pipe\n");
2074 fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
2075 return 0;
2077 else
2079 TRACE(":failed-last error (%d)\n",GetLastError());
2080 return -1;
2084 if (count > 4)
2085 TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
2086 return num_read;
2089 /*********************************************************************
2090 * _read (MSVCRT.@)
2092 int CDECL MSVCRT__read(int fd, void *buf, unsigned int count)
2094 int num_read;
2095 num_read = read_i(fd, buf, count);
2096 return num_read;
2099 /*********************************************************************
2100 * _setmode (MSVCRT.@)
2102 int CDECL _setmode(int fd,int mode)
2104 int ret = msvcrt_get_ioinfo(fd)->wxflag & WX_TEXT ? MSVCRT__O_TEXT : MSVCRT__O_BINARY;
2105 if (mode & (~(MSVCRT__O_TEXT|MSVCRT__O_BINARY)))
2106 FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode);
2107 if ((mode & MSVCRT__O_TEXT) == MSVCRT__O_TEXT)
2108 msvcrt_get_ioinfo(fd)->wxflag |= WX_TEXT;
2109 else
2110 msvcrt_get_ioinfo(fd)->wxflag &= ~WX_TEXT;
2111 return ret;
2114 /*********************************************************************
2115 * _stat64 (MSVCRT.@)
2117 int CDECL MSVCRT_stat64(const char* path, struct MSVCRT__stat64 * buf)
2119 DWORD dw;
2120 WIN32_FILE_ATTRIBUTE_DATA hfi;
2121 unsigned short mode = ALL_S_IREAD;
2122 int plen;
2124 TRACE(":file (%s) buf(%p)\n",path,buf);
2126 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi))
2128 TRACE("failed (%d)\n",GetLastError());
2129 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
2130 return -1;
2133 memset(buf,0,sizeof(struct MSVCRT__stat64));
2135 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
2136 Bon 011120: This FIXME seems incorrect
2137 Also a letter as first char isn't enough to be classified
2138 as a drive letter
2140 if (isalpha(*path)&& (*(path+1)==':'))
2141 buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
2142 else
2143 buf->st_dev = buf->st_rdev = _getdrive() - 1;
2145 plen = strlen(path);
2147 /* Dir, or regular file? */
2148 if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
2149 (path[plen-1] == '\\'))
2150 mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
2151 else
2153 mode |= MSVCRT__S_IFREG;
2154 /* executable? */
2155 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
2157 unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) |
2158 (tolower(path[plen-3]) << 16);
2159 if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
2160 mode |= ALL_S_IEXEC;
2164 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
2165 mode |= ALL_S_IWRITE;
2167 buf->st_mode = mode;
2168 buf->st_nlink = 1;
2169 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
2170 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
2171 buf->st_atime = dw;
2172 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
2173 buf->st_mtime = buf->st_ctime = dw;
2174 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
2175 (int)(buf->st_size >> 32),(int)buf->st_size,
2176 (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
2177 return 0;
2180 /*********************************************************************
2181 * _stati64 (MSVCRT.@)
2183 int CDECL MSVCRT_stati64(const char* path, struct MSVCRT__stati64 * buf)
2185 int ret;
2186 struct MSVCRT__stat64 buf64;
2188 ret = MSVCRT_stat64(path, &buf64);
2189 if (!ret)
2190 msvcrt_stat64_to_stati64(&buf64, buf);
2191 return ret;
2194 /*********************************************************************
2195 * _stat (MSVCRT.@)
2197 int CDECL MSVCRT_stat(const char* path, struct MSVCRT__stat * buf)
2198 { int ret;
2199 struct MSVCRT__stat64 buf64;
2201 ret = MSVCRT_stat64( path, &buf64);
2202 if (!ret)
2203 msvcrt_stat64_to_stat(&buf64, buf);
2204 return ret;
2207 /*********************************************************************
2208 * _wstat64 (MSVCRT.@)
2210 int CDECL MSVCRT__wstat64(const MSVCRT_wchar_t* path, struct MSVCRT__stat64 * buf)
2212 DWORD dw;
2213 WIN32_FILE_ATTRIBUTE_DATA hfi;
2214 unsigned short mode = ALL_S_IREAD;
2215 int plen;
2217 TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf);
2219 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi))
2221 TRACE("failed (%d)\n",GetLastError());
2222 msvcrt_set_errno(ERROR_FILE_NOT_FOUND);
2223 return -1;
2226 memset(buf,0,sizeof(struct MSVCRT__stat64));
2228 /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
2229 if (MSVCRT_iswalpha(*path))
2230 buf->st_dev = buf->st_rdev = toupperW(*path - 'A'); /* drive num */
2231 else
2232 buf->st_dev = buf->st_rdev = _getdrive() - 1;
2234 plen = strlenW(path);
2236 /* Dir, or regular file? */
2237 if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
2238 (path[plen-1] == '\\'))
2239 mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
2240 else
2242 mode |= MSVCRT__S_IFREG;
2243 /* executable? */
2244 if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */
2246 ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) |
2247 ((ULONGLONG)tolowerW(path[plen-3]) << 32);
2248 if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM)
2249 mode |= ALL_S_IEXEC;
2253 if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
2254 mode |= ALL_S_IWRITE;
2256 buf->st_mode = mode;
2257 buf->st_nlink = 1;
2258 buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
2259 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
2260 buf->st_atime = dw;
2261 RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
2262 buf->st_mtime = buf->st_ctime = dw;
2263 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
2264 (int)(buf->st_size >> 32),(int)buf->st_size,
2265 (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
2266 return 0;
2269 /*********************************************************************
2270 * _wstati64 (MSVCRT.@)
2272 int CDECL MSVCRT__wstati64(const MSVCRT_wchar_t* path, struct MSVCRT__stati64 * buf)
2274 int ret;
2275 struct MSVCRT__stat64 buf64;
2277 ret = MSVCRT__wstat64(path, &buf64);
2278 if (!ret)
2279 msvcrt_stat64_to_stati64(&buf64, buf);
2280 return ret;
2283 /*********************************************************************
2284 * _wstat (MSVCRT.@)
2286 int CDECL MSVCRT__wstat(const MSVCRT_wchar_t* path, struct MSVCRT__stat * buf)
2288 int ret;
2289 struct MSVCRT__stat64 buf64;
2291 ret = MSVCRT__wstat64( path, &buf64 );
2292 if (!ret) msvcrt_stat64_to_stat(&buf64, buf);
2293 return ret;
2296 /*********************************************************************
2297 * _tell (MSVCRT.@)
2299 MSVCRT_long CDECL MSVCRT__tell(int fd)
2301 return MSVCRT__lseek(fd, 0, SEEK_CUR);
2304 /*********************************************************************
2305 * _telli64 (MSVCRT.@)
2307 __int64 CDECL _telli64(int fd)
2309 return MSVCRT__lseeki64(fd, 0, SEEK_CUR);
2312 /*********************************************************************
2313 * _tempnam (MSVCRT.@)
2315 char * CDECL _tempnam(const char *dir, const char *prefix)
2317 char tmpbuf[MAX_PATH];
2318 const char *tmp_dir = MSVCRT_getenv("TMP");
2320 if (tmp_dir) dir = tmp_dir;
2322 TRACE("dir (%s) prefix (%s)\n",dir,prefix);
2323 if (GetTempFileNameA(dir,prefix,0,tmpbuf))
2325 TRACE("got name (%s)\n",tmpbuf);
2326 DeleteFileA(tmpbuf);
2327 return _strdup(tmpbuf);
2329 TRACE("failed (%d)\n",GetLastError());
2330 return NULL;
2333 /*********************************************************************
2334 * _wtempnam (MSVCRT.@)
2336 MSVCRT_wchar_t * CDECL _wtempnam(const MSVCRT_wchar_t *dir, const MSVCRT_wchar_t *prefix)
2338 MSVCRT_wchar_t tmpbuf[MAX_PATH];
2340 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
2341 if (GetTempFileNameW(dir,prefix,0,tmpbuf))
2343 TRACE("got name (%s)\n",debugstr_w(tmpbuf));
2344 DeleteFileW(tmpbuf);
2345 return _wcsdup(tmpbuf);
2347 TRACE("failed (%d)\n",GetLastError());
2348 return NULL;
2351 /*********************************************************************
2352 * _umask (MSVCRT.@)
2354 int CDECL MSVCRT__umask(int umask)
2356 int old_umask = MSVCRT_umask;
2357 TRACE("(%d)\n",umask);
2358 MSVCRT_umask = umask;
2359 return old_umask;
2362 /*********************************************************************
2363 * _utime64 (MSVCRT.@)
2365 int CDECL _utime64(const char* path, struct MSVCRT___utimbuf64 *t)
2367 int fd = MSVCRT__open(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
2369 if (fd > 0)
2371 int retVal = _futime64(fd, t);
2372 MSVCRT__close(fd);
2373 return retVal;
2375 return -1;
2378 /*********************************************************************
2379 * _utime32 (MSVCRT.@)
2381 int CDECL _utime32(const char* path, struct MSVCRT___utimbuf32 *t)
2383 struct MSVCRT___utimbuf64 t64;
2384 t64.actime = t->actime;
2385 t64.modtime = t->modtime;
2386 return _utime64( path, &t64 );
2389 /*********************************************************************
2390 * _utime (MSVCRT.@)
2392 #ifdef _WIN64
2393 int CDECL _utime(const char* path, struct MSVCRT___utimbuf64 *t)
2395 return _utime64( path, t );
2397 #else
2398 int CDECL _utime(const char* path, struct MSVCRT___utimbuf32 *t)
2400 return _utime32( path, t );
2402 #endif
2404 /*********************************************************************
2405 * _wutime64 (MSVCRT.@)
2407 int CDECL _wutime64(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
2409 int fd = _wopen(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
2411 if (fd > 0)
2413 int retVal = _futime64(fd, t);
2414 MSVCRT__close(fd);
2415 return retVal;
2417 return -1;
2420 /*********************************************************************
2421 * _wutime32 (MSVCRT.@)
2423 int CDECL _wutime32(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
2425 struct MSVCRT___utimbuf64 t64;
2426 t64.actime = t->actime;
2427 t64.modtime = t->modtime;
2428 return _wutime64( path, &t64 );
2431 /*********************************************************************
2432 * _wutime (MSVCRT.@)
2434 #ifdef _WIN64
2435 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
2437 return _wutime64( path, t );
2439 #else
2440 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
2442 return _wutime32( path, t );
2444 #endif
2446 /*********************************************************************
2447 * _write (MSVCRT.@)
2449 int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count)
2451 DWORD num_written;
2452 HANDLE hand = msvcrt_fdtoh(fd);
2454 /* Don't trace small writes, it gets *very* annoying */
2455 #if 0
2456 if (count > 32)
2457 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
2458 #endif
2459 if (hand == INVALID_HANDLE_VALUE)
2461 *MSVCRT__errno() = MSVCRT_EBADF;
2462 return -1;
2465 /* If appending, go to EOF */
2466 if (msvcrt_get_ioinfo(fd)->wxflag & WX_APPEND)
2467 MSVCRT__lseek(fd, 0, FILE_END);
2469 if (!(msvcrt_get_ioinfo(fd)->wxflag & WX_TEXT))
2471 if (WriteFile(hand, buf, count, &num_written, NULL)
2472 && (num_written == count))
2473 return num_written;
2474 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
2475 hand, GetLastError());
2476 *MSVCRT__errno() = MSVCRT_ENOSPC;
2478 else
2480 unsigned int i, j, nr_lf;
2481 char *p = NULL;
2482 const char *q;
2483 const char *s = buf, *buf_start = buf;
2484 /* find number of \n ( without preceding \r ) */
2485 for ( nr_lf=0,i = 0; i <count; i++)
2487 if (s[i]== '\n')
2489 nr_lf++;
2490 /*if ((i >1) && (s[i-1] == '\r')) nr_lf--; */
2493 if (nr_lf)
2495 if ((q = p = MSVCRT_malloc(count + nr_lf)))
2497 for (s = buf, i = 0, j = 0; i < count; i++)
2499 if (s[i]== '\n')
2501 p[j++] = '\r';
2502 /*if ((i >1) && (s[i-1] == '\r'))j--;*/
2504 p[j++] = s[i];
2507 else
2509 FIXME("Malloc failed\n");
2510 nr_lf =0;
2511 q = buf;
2514 else
2515 q = buf;
2517 if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf))
2519 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
2520 fd, hand, GetLastError(), num_written);
2521 *MSVCRT__errno() = MSVCRT_ENOSPC;
2522 if(nr_lf)
2523 MSVCRT_free(p);
2524 return s - buf_start;
2526 else
2528 if(nr_lf)
2529 MSVCRT_free(p);
2530 return count;
2533 return -1;
2536 /*********************************************************************
2537 * _putw (MSVCRT.@)
2539 int CDECL MSVCRT__putw(int val, MSVCRT_FILE* file)
2541 int len;
2542 len = MSVCRT__write(file->_file, &val, sizeof(val));
2543 if (len == sizeof(val)) return val;
2544 file->_flag |= MSVCRT__IOERR;
2545 return MSVCRT_EOF;
2548 /*********************************************************************
2549 * fclose (MSVCRT.@)
2551 int CDECL MSVCRT_fclose(MSVCRT_FILE* file)
2553 int r, flag;
2555 flag = file->_flag;
2556 MSVCRT_free(file->_tmpfname);
2557 file->_tmpfname = NULL;
2558 /* flush stdio buffers */
2559 if(file->_flag & MSVCRT__IOWRT)
2560 MSVCRT_fflush(file);
2561 if(file->_flag & MSVCRT__IOMYBUF)
2562 MSVCRT_free(file->_base);
2564 r=MSVCRT__close(file->_file);
2566 file->_flag = 0;
2567 if(file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
2568 DeleteCriticalSection(&((file_crit*)file)->crit);
2570 if(file == msvcrt_get_file(MSVCRT_stream_idx-1)) {
2571 while(MSVCRT_stream_idx>3 && !file->_flag) {
2572 MSVCRT_stream_idx--;
2573 file = msvcrt_get_file(MSVCRT_stream_idx-1);
2577 return ((r == -1) || (flag & MSVCRT__IOERR) ? MSVCRT_EOF : 0);
2580 /*********************************************************************
2581 * feof (MSVCRT.@)
2583 int CDECL MSVCRT_feof(MSVCRT_FILE* file)
2585 return file->_flag & MSVCRT__IOEOF;
2588 /*********************************************************************
2589 * ferror (MSVCRT.@)
2591 int CDECL MSVCRT_ferror(MSVCRT_FILE* file)
2593 return file->_flag & MSVCRT__IOERR;
2596 /*********************************************************************
2597 * _filbuf (MSVCRT.@)
2599 int CDECL MSVCRT__filbuf(MSVCRT_FILE* file)
2601 /* Allocate buffer if needed */
2602 if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF) ) {
2603 msvcrt_alloc_buffer(file);
2605 if(!(file->_flag & MSVCRT__IOREAD)) {
2606 if(file->_flag & MSVCRT__IORW) {
2607 file->_flag |= MSVCRT__IOREAD;
2608 } else {
2609 return MSVCRT_EOF;
2612 if(file->_flag & MSVCRT__IONBF) {
2613 unsigned char c;
2614 int r;
2615 if ((r = read_i(file->_file,&c,1)) != 1) {
2616 file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
2617 return MSVCRT_EOF;
2619 return c;
2620 } else {
2621 file->_cnt = read_i(file->_file, file->_base, file->_bufsiz);
2622 if(file->_cnt<=0) {
2623 file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
2624 file->_cnt = 0;
2625 return MSVCRT_EOF;
2627 file->_cnt--;
2628 file->_ptr = file->_base+1;
2629 return *(unsigned char *)file->_base;
2633 /*********************************************************************
2634 * fgetc (MSVCRT.@)
2636 int CDECL MSVCRT_fgetc(MSVCRT_FILE* file)
2638 unsigned char *i;
2639 unsigned int j;
2640 if (file->_cnt>0) {
2641 file->_cnt--;
2642 i = (unsigned char *)file->_ptr++;
2643 j = *i;
2644 } else
2645 j = MSVCRT__filbuf(file);
2646 return j;
2649 /*********************************************************************
2650 * _fgetchar (MSVCRT.@)
2652 int CDECL _fgetchar(void)
2654 return MSVCRT_fgetc(MSVCRT_stdin);
2657 /*********************************************************************
2658 * fgets (MSVCRT.@)
2660 char * CDECL MSVCRT_fgets(char *s, int size, MSVCRT_FILE* file)
2662 int cc = MSVCRT_EOF;
2663 char * buf_start = s;
2665 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
2666 file,file->_file,s,size);
2668 while ((size >1) && (cc = MSVCRT_fgetc(file)) != MSVCRT_EOF && cc != '\n')
2670 *s++ = (char)cc;
2671 size --;
2673 if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
2675 TRACE(":nothing read\n");
2676 return NULL;
2678 if ((cc != MSVCRT_EOF) && (size > 1))
2679 *s++ = cc;
2680 *s = '\0';
2681 TRACE(":got %s\n", debugstr_a(buf_start));
2682 return buf_start;
2685 /*********************************************************************
2686 * fgetwc (MSVCRT.@)
2688 * In MSVCRT__O_TEXT mode, multibyte characters are read from the file, dropping
2689 * the CR from CR/LF combinations
2691 MSVCRT_wint_t CDECL MSVCRT_fgetwc(MSVCRT_FILE* file)
2693 int c;
2695 if (!(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT))
2697 MSVCRT_wchar_t wc;
2698 unsigned int i;
2699 int j;
2700 char *chp, *wcp;
2701 wcp = (char *)&wc;
2702 for(i=0; i<sizeof(wc); i++)
2704 if (file->_cnt>0)
2706 file->_cnt--;
2707 chp = file->_ptr++;
2708 wcp[i] = *chp;
2710 else
2712 j = MSVCRT__filbuf(file);
2713 if(file->_cnt<=0)
2715 file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
2716 file->_cnt = 0;
2717 return MSVCRT_WEOF;
2719 wcp[i] = j;
2722 return wc;
2725 c = MSVCRT_fgetc(file);
2726 if ((get_locale()->locinfo->mb_cur_max > 1) && MSVCRT_isleadbyte(c))
2728 FIXME("Treat Multibyte characters\n");
2730 if (c == MSVCRT_EOF)
2731 return MSVCRT_WEOF;
2732 else
2733 return (MSVCRT_wint_t)c;
2736 /*********************************************************************
2737 * _getw (MSVCRT.@)
2739 int CDECL MSVCRT__getw(MSVCRT_FILE* file)
2741 char *ch;
2742 int i, k;
2743 unsigned int j;
2744 ch = (char *)&i;
2745 for (j=0; j<sizeof(int); j++) {
2746 k = MSVCRT_fgetc(file);
2747 if (k == MSVCRT_EOF) {
2748 file->_flag |= MSVCRT__IOEOF;
2749 return EOF;
2751 ch[j] = k;
2753 return i;
2756 /*********************************************************************
2757 * getwc (MSVCRT.@)
2759 MSVCRT_wint_t CDECL MSVCRT_getwc(MSVCRT_FILE* file)
2761 return MSVCRT_fgetwc(file);
2764 /*********************************************************************
2765 * _fgetwchar (MSVCRT.@)
2767 MSVCRT_wint_t CDECL _fgetwchar(void)
2769 return MSVCRT_fgetwc(MSVCRT_stdin);
2772 /*********************************************************************
2773 * getwchar (MSVCRT.@)
2775 MSVCRT_wint_t CDECL MSVCRT_getwchar(void)
2777 return _fgetwchar();
2780 /*********************************************************************
2781 * fgetws (MSVCRT.@)
2783 MSVCRT_wchar_t * CDECL MSVCRT_fgetws(MSVCRT_wchar_t *s, int size, MSVCRT_FILE* file)
2785 int cc = MSVCRT_WEOF;
2786 MSVCRT_wchar_t * buf_start = s;
2788 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
2789 file,file->_file,s,size);
2791 while ((size >1) && (cc = MSVCRT_fgetwc(file)) != MSVCRT_WEOF && cc != '\n')
2793 *s++ = (char)cc;
2794 size --;
2796 if ((cc == MSVCRT_WEOF) && (s == buf_start)) /* If nothing read, return 0*/
2798 TRACE(":nothing read\n");
2799 return NULL;
2801 if ((cc != MSVCRT_WEOF) && (size > 1))
2802 *s++ = cc;
2803 *s = 0;
2804 TRACE(":got %s\n", debugstr_w(buf_start));
2805 return buf_start;
2808 /*********************************************************************
2809 * fwrite (MSVCRT.@)
2811 MSVCRT_size_t CDECL MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
2813 MSVCRT_size_t wrcnt=size * nmemb;
2814 int written = 0;
2815 if (size == 0)
2816 return 0;
2817 if(file->_cnt) {
2818 int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
2819 memcpy(file->_ptr, ptr, pcnt);
2820 file->_cnt -= pcnt;
2821 file->_ptr += pcnt;
2822 written = pcnt;
2823 wrcnt -= pcnt;
2824 ptr = (const char*)ptr + pcnt;
2825 } else if(!(file->_flag & MSVCRT__IOWRT)) {
2826 if(file->_flag & MSVCRT__IORW) {
2827 file->_flag |= MSVCRT__IOWRT;
2828 } else
2829 return 0;
2831 if(wrcnt) {
2832 /* Flush buffer */
2833 int res=msvcrt_flush_buffer(file);
2834 if(!res) {
2835 int pwritten = MSVCRT__write(file->_file, ptr, wrcnt);
2836 if (pwritten <= 0)
2838 file->_flag |= MSVCRT__IOERR;
2839 pwritten=0;
2841 written += pwritten;
2844 return written / size;
2847 /*********************************************************************
2848 * fputwc (MSVCRT.@)
2850 MSVCRT_wint_t CDECL MSVCRT_fputwc(MSVCRT_wint_t wc, MSVCRT_FILE* file)
2852 MSVCRT_wchar_t mwc=wc;
2853 if (MSVCRT_fwrite( &mwc, sizeof(mwc), 1, file) != 1)
2854 return MSVCRT_WEOF;
2855 return wc;
2858 /*********************************************************************
2859 * _fputwchar (MSVCRT.@)
2861 MSVCRT_wint_t CDECL _fputwchar(MSVCRT_wint_t wc)
2863 return MSVCRT_fputwc(wc, MSVCRT_stdout);
2866 /*********************************************************************
2867 * _wfsopen (MSVCRT.@)
2869 MSVCRT_FILE * CDECL MSVCRT__wfsopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, int share)
2871 MSVCRT_FILE* file;
2872 int open_flags, stream_flags, fd;
2874 TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
2876 /* map mode string to open() flags. "man fopen" for possibilities. */
2877 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
2878 return NULL;
2880 LOCK_FILES();
2881 fd = MSVCRT__wsopen(path, open_flags, share, MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
2882 if (fd < 0)
2883 file = NULL;
2884 else if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags)
2885 != -1)
2886 TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
2887 else if (file)
2889 file->_flag = 0;
2890 file = NULL;
2893 TRACE(":got (%p)\n",file);
2894 if (fd >= 0 && !file)
2895 MSVCRT__close(fd);
2896 UNLOCK_FILES();
2897 return file;
2900 /*********************************************************************
2901 * _fsopen (MSVCRT.@)
2903 MSVCRT_FILE * CDECL MSVCRT__fsopen(const char *path, const char *mode, int share)
2905 MSVCRT_FILE *ret;
2906 MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
2908 if (path && !(pathW = msvcrt_wstrdupa(path))) {
2909 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
2910 *MSVCRT__errno() = MSVCRT_EINVAL;
2911 return NULL;
2913 if (mode && !(modeW = msvcrt_wstrdupa(mode)))
2915 MSVCRT_free(pathW);
2916 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
2917 *MSVCRT__errno() = MSVCRT_EINVAL;
2918 return NULL;
2921 ret = MSVCRT__wfsopen(pathW, modeW, share);
2923 MSVCRT_free(pathW);
2924 MSVCRT_free(modeW);
2925 return ret;
2928 /*********************************************************************
2929 * fopen (MSVCRT.@)
2931 MSVCRT_FILE * CDECL MSVCRT_fopen(const char *path, const char *mode)
2933 return MSVCRT__fsopen( path, mode, MSVCRT__SH_DENYNO );
2936 /*********************************************************************
2937 * fopen_s (MSVCRT.@)
2939 int CDECL MSVCRT_fopen_s(MSVCRT_FILE** pFile,
2940 const char *filename, const char *mode)
2942 if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
2943 !MSVCRT_CHECK_PMT(mode != NULL)) {
2944 *MSVCRT__errno() = MSVCRT_EINVAL;
2945 return MSVCRT_EINVAL;
2948 *pFile = MSVCRT_fopen(filename, mode);
2950 if(!*pFile)
2951 return *MSVCRT__errno();
2952 return 0;
2955 /*********************************************************************
2956 * _wfopen (MSVCRT.@)
2958 MSVCRT_FILE * CDECL MSVCRT__wfopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode)
2960 return MSVCRT__wfsopen( path, mode, MSVCRT__SH_DENYNO );
2963 /*********************************************************************
2964 * _wfopen_s (MSVCRT.@)
2966 int CDECL MSVCRT__wfopen_s(MSVCRT_FILE** pFile, const MSVCRT_wchar_t *filename,
2967 const MSVCRT_wchar_t *mode)
2969 if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
2970 !MSVCRT_CHECK_PMT(mode != NULL)) {
2971 *MSVCRT__errno() = MSVCRT_EINVAL;
2972 return MSVCRT_EINVAL;
2975 *pFile = MSVCRT__wfopen(filename, mode);
2977 if(!*pFile)
2978 return *MSVCRT__errno();
2979 return 0;
2982 /* MSVCRT_fputc calls MSVCRT__flsbuf which calls MSVCRT_fputc */
2983 int CDECL MSVCRT__flsbuf(int c, MSVCRT_FILE* file);
2985 /*********************************************************************
2986 * fputc (MSVCRT.@)
2988 int CDECL MSVCRT_fputc(int c, MSVCRT_FILE* file)
2990 if(file->_cnt>0) {
2991 *file->_ptr++=c;
2992 file->_cnt--;
2993 if (c == '\n')
2995 int res = msvcrt_flush_buffer(file);
2996 return res ? res : c;
2998 else
2999 return c & 0xff;
3000 } else {
3001 return MSVCRT__flsbuf(c, file);
3005 /*********************************************************************
3006 * _flsbuf (MSVCRT.@)
3008 int CDECL MSVCRT__flsbuf(int c, MSVCRT_FILE* file)
3010 /* Flush output buffer */
3011 if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) {
3012 msvcrt_alloc_buffer(file);
3014 if(!(file->_flag & MSVCRT__IOWRT)) {
3015 if(file->_flag & MSVCRT__IORW) {
3016 file->_flag |= MSVCRT__IOWRT;
3017 } else {
3018 return MSVCRT_EOF;
3021 if(file->_bufsiz) {
3022 int res=msvcrt_flush_buffer(file);
3023 return res?res : MSVCRT_fputc(c, file);
3024 } else {
3025 unsigned char cc=c;
3026 int len;
3027 /* set _cnt to 0 for unbuffered FILEs */
3028 file->_cnt = 0;
3029 len = MSVCRT__write(file->_file, &cc, 1);
3030 if (len == 1) return c & 0xff;
3031 file->_flag |= MSVCRT__IOERR;
3032 return MSVCRT_EOF;
3036 /*********************************************************************
3037 * _fputchar (MSVCRT.@)
3039 int CDECL _fputchar(int c)
3041 return MSVCRT_fputc(c, MSVCRT_stdout);
3044 /*********************************************************************
3045 * fread (MSVCRT.@)
3047 MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
3048 { MSVCRT_size_t rcnt=size * nmemb;
3049 MSVCRT_size_t read=0;
3050 int pread=0;
3052 if(!rcnt)
3053 return 0;
3055 /* first buffered data */
3056 if(file->_cnt>0) {
3057 int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
3058 memcpy(ptr, file->_ptr, pcnt);
3059 file->_cnt -= pcnt;
3060 file->_ptr += pcnt;
3061 read += pcnt ;
3062 rcnt -= pcnt ;
3063 ptr = (char*)ptr + pcnt;
3064 } else if(!(file->_flag & MSVCRT__IOREAD )) {
3065 if(file->_flag & MSVCRT__IORW) {
3066 file->_flag |= MSVCRT__IOREAD;
3067 } else
3068 return 0;
3070 while(rcnt>0)
3072 int i;
3073 /* Fill the buffer on small reads.
3074 * TODO: Use a better buffering strategy.
3076 if (!file->_cnt && size*nmemb <= MSVCRT_BUFSIZ/2 && !(file->_flag & MSVCRT__IONBF)) {
3077 if (file->_bufsiz == 0) {
3078 msvcrt_alloc_buffer(file);
3080 file->_cnt = MSVCRT__read(file->_file, file->_base, file->_bufsiz);
3081 file->_ptr = file->_base;
3082 i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
3083 /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
3084 if (i > 0 && i < file->_cnt) {
3085 msvcrt_get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF;
3086 file->_flag &= ~MSVCRT__IOEOF;
3088 if (i > 0) {
3089 memcpy(ptr, file->_ptr, i);
3090 file->_cnt -= i;
3091 file->_ptr += i;
3093 } else {
3094 i = MSVCRT__read(file->_file,ptr, rcnt);
3096 pread += i;
3097 rcnt -= i;
3098 ptr = (char *)ptr+i;
3099 /* expose feof condition in the flags
3100 * MFC tests file->_flag for feof, and doesn't call feof())
3102 if (msvcrt_get_ioinfo(file->_file)->wxflag & WX_ATEOF)
3103 file->_flag |= MSVCRT__IOEOF;
3104 else if (i == -1)
3106 file->_flag |= MSVCRT__IOERR;
3107 pread = 0;
3108 rcnt = 0;
3110 if (i < 1) break;
3112 read+=pread;
3113 return read / size;
3116 /*********************************************************************
3117 * _wfreopen (MSVCRT.@)
3120 MSVCRT_FILE* CDECL MSVCRT__wfreopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, MSVCRT_FILE* file)
3122 int open_flags, stream_flags, fd;
3124 TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file);
3126 LOCK_FILES();
3127 if (!file || ((fd = file->_file) < 0) || fd > MSVCRT_fdend)
3128 file = NULL;
3129 else
3131 MSVCRT_fclose(file);
3132 /* map mode string to open() flags. "man fopen" for possibilities. */
3133 if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
3134 file = NULL;
3135 else
3137 fd = _wopen(path, open_flags, MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
3138 if (fd < 0)
3139 file = NULL;
3140 else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
3142 file->_flag = 0;
3143 WARN(":failed-last error (%d)\n",GetLastError());
3144 msvcrt_set_errno(GetLastError());
3145 file = NULL;
3149 UNLOCK_FILES();
3150 return file;
3153 /*********************************************************************
3154 * freopen (MSVCRT.@)
3157 MSVCRT_FILE* CDECL MSVCRT_freopen(const char *path, const char *mode, MSVCRT_FILE* file)
3159 MSVCRT_FILE *ret;
3160 MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
3162 if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
3163 if (mode && !(modeW = msvcrt_wstrdupa(mode)))
3165 MSVCRT_free(pathW);
3166 return NULL;
3169 ret = MSVCRT__wfreopen(pathW, modeW, file);
3171 MSVCRT_free(pathW);
3172 MSVCRT_free(modeW);
3173 return ret;
3176 /*********************************************************************
3177 * fsetpos (MSVCRT.@)
3179 int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
3181 /* Note that all this has been lifted 'as is' from fseek */
3182 if(file->_flag & MSVCRT__IOWRT)
3183 msvcrt_flush_buffer(file);
3185 /* Discard buffered input */
3186 file->_cnt = 0;
3187 file->_ptr = file->_base;
3189 /* Reset direction of i/o */
3190 if(file->_flag & MSVCRT__IORW) {
3191 file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
3194 return (MSVCRT__lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0;
3197 /*********************************************************************
3198 * _ftelli64 (MSVCRT.@)
3200 __int64 CDECL MSVCRT__ftelli64(MSVCRT_FILE* file)
3202 /* TODO: just call fgetpos and return lower half of result */
3203 int off=0;
3204 __int64 pos;
3205 pos = _telli64(file->_file);
3206 if(pos == -1) return -1;
3207 if(file->_bufsiz) {
3208 if( file->_flag & MSVCRT__IOWRT ) {
3209 off = file->_ptr - file->_base;
3210 } else {
3211 off = -file->_cnt;
3212 if (msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
3213 /* Black magic correction for CR removal */
3214 int i;
3215 for (i=0; i<file->_cnt; i++) {
3216 if (file->_ptr[i] == '\n')
3217 off--;
3219 /* Black magic when reading CR at buffer boundary*/
3220 if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_READCR)
3221 off--;
3225 return off + pos;
3228 /*********************************************************************
3229 * ftell (MSVCRT.@)
3231 LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
3233 return MSVCRT__ftelli64(file);
3236 /*********************************************************************
3237 * fgetpos (MSVCRT.@)
3239 int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
3241 int off=0;
3242 *pos = MSVCRT__lseeki64(file->_file,0,SEEK_CUR);
3243 if(*pos == -1) return -1;
3244 if(file->_bufsiz) {
3245 if( file->_flag & MSVCRT__IOWRT ) {
3246 off = file->_ptr - file->_base;
3247 } else {
3248 off = -file->_cnt;
3249 if (msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
3250 /* Black magic correction for CR removal */
3251 int i;
3252 for (i=0; i<file->_cnt; i++) {
3253 if (file->_ptr[i] == '\n')
3254 off--;
3256 /* Black magic when reading CR at buffer boundary*/
3257 if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_READCR)
3258 off--;
3262 *pos += off;
3263 return 0;
3266 /*********************************************************************
3267 * fputs (MSVCRT.@)
3269 int CDECL MSVCRT_fputs(const char *s, MSVCRT_FILE* file)
3271 MSVCRT_size_t i, len = strlen(s);
3272 if (!(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT))
3273 return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
3274 for (i=0; i<len; i++)
3275 if (MSVCRT_fputc(s[i], file) == MSVCRT_EOF)
3276 return MSVCRT_EOF;
3277 return 0;
3280 /*********************************************************************
3281 * fputws (MSVCRT.@)
3283 int CDECL MSVCRT_fputws(const MSVCRT_wchar_t *s, MSVCRT_FILE* file)
3285 MSVCRT_size_t i, len = strlenW(s);
3286 if (!(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT))
3287 return MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
3288 for (i=0; i<len; i++)
3290 if ((s[i] == '\n') && (MSVCRT_fputc('\r', file) == MSVCRT_EOF))
3291 return MSVCRT_WEOF;
3292 if (MSVCRT_fputwc(s[i], file) == MSVCRT_WEOF)
3293 return MSVCRT_WEOF;
3295 return 0;
3298 /*********************************************************************
3299 * getchar (MSVCRT.@)
3301 int CDECL MSVCRT_getchar(void)
3303 return MSVCRT_fgetc(MSVCRT_stdin);
3306 /*********************************************************************
3307 * getc (MSVCRT.@)
3309 int CDECL MSVCRT_getc(MSVCRT_FILE* file)
3311 return MSVCRT_fgetc(file);
3314 /*********************************************************************
3315 * gets (MSVCRT.@)
3317 char * CDECL MSVCRT_gets(char *buf)
3319 int cc;
3320 char * buf_start = buf;
3322 for(cc = MSVCRT_fgetc(MSVCRT_stdin); cc != MSVCRT_EOF && cc != '\n';
3323 cc = MSVCRT_fgetc(MSVCRT_stdin))
3324 if(cc != '\r') *buf++ = (char)cc;
3326 *buf = '\0';
3328 TRACE("got '%s'\n", buf_start);
3329 return buf_start;
3332 /*********************************************************************
3333 * _getws (MSVCRT.@)
3335 MSVCRT_wchar_t* CDECL MSVCRT__getws(MSVCRT_wchar_t* buf)
3337 MSVCRT_wint_t cc;
3338 MSVCRT_wchar_t* ws = buf;
3340 for (cc = MSVCRT_fgetwc(MSVCRT_stdin); cc != MSVCRT_WEOF && cc != '\n';
3341 cc = MSVCRT_fgetwc(MSVCRT_stdin))
3343 if (cc != '\r')
3344 *buf++ = (MSVCRT_wchar_t)cc;
3346 *buf = '\0';
3348 TRACE("got %s\n", debugstr_w(ws));
3349 return ws;
3352 /*********************************************************************
3353 * putc (MSVCRT.@)
3355 int CDECL MSVCRT_putc(int c, MSVCRT_FILE* file)
3357 return MSVCRT_fputc(c, file);
3360 /*********************************************************************
3361 * putchar (MSVCRT.@)
3363 int CDECL MSVCRT_putchar(int c)
3365 return MSVCRT_fputc(c, MSVCRT_stdout);
3368 /*********************************************************************
3369 * _putwch (MSVCRT.@)
3371 int CDECL MSVCRT__putwch(int c)
3373 return MSVCRT_fputwc(c, MSVCRT_stdout);
3376 /*********************************************************************
3377 * puts (MSVCRT.@)
3379 int CDECL MSVCRT_puts(const char *s)
3381 MSVCRT_size_t len = strlen(s);
3382 if (MSVCRT_fwrite(s,sizeof(*s),len,MSVCRT_stdout) != len) return MSVCRT_EOF;
3383 return MSVCRT_fwrite("\n",1,1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
3386 /*********************************************************************
3387 * _putws (MSVCRT.@)
3389 int CDECL _putws(const MSVCRT_wchar_t *s)
3391 static const MSVCRT_wchar_t nl = '\n';
3392 MSVCRT_size_t len = strlenW(s);
3393 if (MSVCRT_fwrite(s,sizeof(*s),len,MSVCRT_stdout) != len) return MSVCRT_EOF;
3394 return MSVCRT_fwrite(&nl,sizeof(nl),1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
3397 /*********************************************************************
3398 * remove (MSVCRT.@)
3400 int CDECL MSVCRT_remove(const char *path)
3402 TRACE("(%s)\n",path);
3403 if (DeleteFileA(path))
3404 return 0;
3405 TRACE(":failed (%d)\n",GetLastError());
3406 msvcrt_set_errno(GetLastError());
3407 return -1;
3410 /*********************************************************************
3411 * _wremove (MSVCRT.@)
3413 int CDECL _wremove(const MSVCRT_wchar_t *path)
3415 TRACE("(%s)\n",debugstr_w(path));
3416 if (DeleteFileW(path))
3417 return 0;
3418 TRACE(":failed (%d)\n",GetLastError());
3419 msvcrt_set_errno(GetLastError());
3420 return -1;
3423 /*********************************************************************
3424 * rename (MSVCRT.@)
3426 int CDECL MSVCRT_rename(const char *oldpath,const char *newpath)
3428 TRACE(":from %s to %s\n",oldpath,newpath);
3429 if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
3430 return 0;
3431 TRACE(":failed (%d)\n",GetLastError());
3432 msvcrt_set_errno(GetLastError());
3433 return -1;
3436 /*********************************************************************
3437 * _wrename (MSVCRT.@)
3439 int CDECL _wrename(const MSVCRT_wchar_t *oldpath,const MSVCRT_wchar_t *newpath)
3441 TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
3442 if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
3443 return 0;
3444 TRACE(":failed (%d)\n",GetLastError());
3445 msvcrt_set_errno(GetLastError());
3446 return -1;
3449 /*********************************************************************
3450 * setvbuf (MSVCRT.@)
3452 int CDECL MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size)
3454 /* TODO: Check if file busy */
3455 if(file->_bufsiz) {
3456 MSVCRT_free(file->_base);
3457 file->_bufsiz = 0;
3458 file->_cnt = 0;
3460 if(mode == MSVCRT__IOFBF) {
3461 file->_flag &= ~MSVCRT__IONBF;
3462 file->_base = file->_ptr = buf;
3463 if(buf) {
3464 file->_bufsiz = size;
3466 } else {
3467 file->_flag |= MSVCRT__IONBF;
3469 return 0;
3472 /*********************************************************************
3473 * setbuf (MSVCRT.@)
3475 void CDECL MSVCRT_setbuf(MSVCRT_FILE* file, char *buf)
3477 MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, MSVCRT_BUFSIZ);
3480 /*********************************************************************
3481 * tmpnam (MSVCRT.@)
3483 char * CDECL MSVCRT_tmpnam(char *s)
3485 char tmpstr[16];
3486 char *p;
3487 int count, size;
3488 if (s == 0)
3489 s = MSVCRT_tmpname;
3490 msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr);
3491 p = s + sprintf(s, "\\s%s.", tmpstr);
3492 for (count = 0; count < MSVCRT_TMP_MAX; count++)
3494 size = msvcrt_int_to_base32(tmpnam_unique++, tmpstr);
3495 memcpy(p, tmpstr, size);
3496 if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES &&
3497 GetLastError() == ERROR_FILE_NOT_FOUND)
3498 break;
3500 return s;
3503 /*********************************************************************
3504 * _wtmpnam (MSVCRT.@)
3506 MSVCRT_wchar_t * MSVCRT_wtmpnam(MSVCRT_wchar_t *s)
3508 static const MSVCRT_wchar_t format[] = {'\\','s','%','s','.',0};
3509 MSVCRT_wchar_t tmpstr[16];
3510 MSVCRT_wchar_t *p;
3511 int count, size;
3512 if (s == 0)
3513 s = MSVCRT_wtmpname;
3514 msvcrt_int_to_base32_w(GetCurrentProcessId(), tmpstr);
3515 p = s + MSVCRT__snwprintf(s, MAX_PATH, format, tmpstr);
3516 for (count = 0; count < MSVCRT_TMP_MAX; count++)
3518 size = msvcrt_int_to_base32_w(tmpnam_unique++, tmpstr);
3519 memcpy(p, tmpstr, size*sizeof(MSVCRT_wchar_t));
3520 if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES &&
3521 GetLastError() == ERROR_FILE_NOT_FOUND)
3522 break;
3524 return s;
3527 /*********************************************************************
3528 * tmpfile (MSVCRT.@)
3530 MSVCRT_FILE* CDECL MSVCRT_tmpfile(void)
3532 char *filename = MSVCRT_tmpnam(NULL);
3533 int fd;
3534 MSVCRT_FILE* file = NULL;
3536 LOCK_FILES();
3537 fd = MSVCRT__open(filename, MSVCRT__O_CREAT | MSVCRT__O_BINARY | MSVCRT__O_RDWR | MSVCRT__O_TEMPORARY);
3538 if (fd != -1 && (file = msvcrt_alloc_fp()))
3540 if (msvcrt_init_fp(file, fd, MSVCRT__O_RDWR) == -1)
3542 file->_flag = 0;
3543 file = NULL;
3545 else file->_tmpfname = _strdup(filename);
3547 UNLOCK_FILES();
3548 return file;
3551 static int puts_clbk_file_a(void *file, int len, const char *str)
3553 return MSVCRT_fwrite(str, sizeof(char), len, file);
3556 static int puts_clbk_file_w(void *file, int len, const MSVCRT_wchar_t *str)
3558 return MSVCRT_fwrite(str, sizeof(MSVCRT_wchar_t), len, file);
3561 /*********************************************************************
3562 * vfprintf (MSVCRT.@)
3564 int CDECL MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
3566 return pf_printf_a(puts_clbk_file_a, file, format, NULL, FALSE, FALSE, arg_clbk_valist, NULL, &valist);
3569 /*********************************************************************
3570 * vfprintf_s (MSVCRT.@)
3572 int CDECL MSVCRT_vfprintf_s(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
3574 if(!MSVCRT_CHECK_PMT(file != NULL)) {
3575 *MSVCRT__errno() = MSVCRT_EINVAL;
3576 return -1;
3579 return pf_printf_a(puts_clbk_file_a, file, format, NULL, FALSE, TRUE, arg_clbk_valist, NULL, &valist);
3582 /*********************************************************************
3583 * vfwprintf (MSVCRT.@)
3585 int CDECL MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
3587 return pf_printf_w(puts_clbk_file_w, file, format, NULL, FALSE, FALSE, arg_clbk_valist, NULL, &valist);
3590 /*********************************************************************
3591 * vfwprintf_s (MSVCRT.@)
3593 int CDECL MSVCRT_vfwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
3595 if(!MSVCRT_CHECK_PMT( file != NULL)) {
3596 *MSVCRT__errno() = MSVCRT_EINVAL;
3597 return -1;
3600 return pf_printf_w(puts_clbk_file_w, file, format, NULL, FALSE, TRUE, arg_clbk_valist, NULL, &valist);
3603 /*********************************************************************
3604 * vprintf (MSVCRT.@)
3606 int CDECL MSVCRT_vprintf(const char *format, __ms_va_list valist)
3608 return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
3611 /*********************************************************************
3612 * vprintf_s (MSVCRT.@)
3614 int CDECL MSVCRT_vprintf_s(const char *format, __ms_va_list valist)
3616 return MSVCRT_vfprintf_s(MSVCRT_stdout,format,valist);
3619 /*********************************************************************
3620 * vwprintf (MSVCRT.@)
3622 int CDECL MSVCRT_vwprintf(const MSVCRT_wchar_t *format, __ms_va_list valist)
3624 return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
3627 /*********************************************************************
3628 * vwprintf_s (MSVCRT.@)
3630 int CDECL MSVCRT_vwprintf_s(const MSVCRT_wchar_t *format, __ms_va_list valist)
3632 return MSVCRT_vfwprintf_s(MSVCRT_stdout,format,valist);
3635 /*********************************************************************
3636 * fprintf (MSVCRT.@)
3638 int CDECL MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
3640 __ms_va_list valist;
3641 int res;
3642 __ms_va_start(valist, format);
3643 res = MSVCRT_vfprintf(file, format, valist);
3644 __ms_va_end(valist);
3645 return res;
3648 /*********************************************************************
3649 * fprintf_s (MSVCRT.@)
3651 int CDECL MSVCRT_fprintf_s(MSVCRT_FILE* file, const char *format, ...)
3653 __ms_va_list valist;
3654 int res;
3655 __ms_va_start(valist, format);
3656 res = MSVCRT_vfprintf_s(file, format, valist);
3657 __ms_va_end(valist);
3658 return res;
3661 /*********************************************************************
3662 * fwprintf (MSVCRT.@)
3664 int CDECL MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
3666 __ms_va_list valist;
3667 int res;
3668 __ms_va_start(valist, format);
3669 res = MSVCRT_vfwprintf(file, format, valist);
3670 __ms_va_end(valist);
3671 return res;
3674 /*********************************************************************
3675 * fwprintf_s (MSVCRT.@)
3677 int CDECL MSVCRT_fwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
3679 __ms_va_list valist;
3680 int res;
3681 __ms_va_start(valist, format);
3682 res = MSVCRT_vfwprintf_s(file, format, valist);
3683 __ms_va_end(valist);
3684 return res;
3687 /*********************************************************************
3688 * printf (MSVCRT.@)
3690 int CDECL MSVCRT_printf(const char *format, ...)
3692 __ms_va_list valist;
3693 int res;
3694 __ms_va_start(valist, format);
3695 res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
3696 __ms_va_end(valist);
3697 return res;
3700 /*********************************************************************
3701 * printf_s (MSVCRT.@)
3703 int CDECL MSVCRT_printf_s(const char *format, ...)
3705 __ms_va_list valist;
3706 int res;
3707 __ms_va_start(valist, format);
3708 res = MSVCRT_vprintf_s(format, valist);
3709 __ms_va_end(valist);
3710 return res;
3713 /*********************************************************************
3714 * ungetc (MSVCRT.@)
3716 int CDECL MSVCRT_ungetc(int c, MSVCRT_FILE * file)
3718 if (c == MSVCRT_EOF)
3719 return MSVCRT_EOF;
3720 if(file->_bufsiz == 0) {
3721 msvcrt_alloc_buffer(file);
3722 file->_ptr++;
3724 if(file->_ptr>file->_base) {
3725 file->_ptr--;
3726 *file->_ptr=c;
3727 file->_cnt++;
3728 MSVCRT_clearerr(file);
3729 return c;
3731 return MSVCRT_EOF;
3734 /*********************************************************************
3735 * ungetwc (MSVCRT.@)
3737 MSVCRT_wint_t CDECL MSVCRT_ungetwc(MSVCRT_wint_t wc, MSVCRT_FILE * file)
3739 MSVCRT_wchar_t mwc = wc;
3740 char * pp = (char *)&mwc;
3741 int i;
3742 for(i=sizeof(MSVCRT_wchar_t)-1;i>=0;i--) {
3743 if(pp[i] != MSVCRT_ungetc(pp[i],file))
3744 return MSVCRT_WEOF;
3746 return mwc;
3749 /*********************************************************************
3750 * wprintf (MSVCRT.@)
3752 int CDECL MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
3754 __ms_va_list valist;
3755 int res;
3756 __ms_va_start(valist, format);
3757 res = MSVCRT_vwprintf(format, valist);
3758 __ms_va_end(valist);
3759 return res;
3762 /*********************************************************************
3763 * wprintf_s (MSVCRT.@)
3765 int CDECL MSVCRT_wprintf_s(const MSVCRT_wchar_t *format, ...)
3767 __ms_va_list valist;
3768 int res;
3769 __ms_va_start(valist, format);
3770 res = MSVCRT_vwprintf_s(format, valist);
3771 __ms_va_end(valist);
3772 return res;
3775 /*********************************************************************
3776 * _getmaxstdio (MSVCRT.@)
3778 int CDECL _getmaxstdio(void)
3780 return MSVCRT_max_streams;
3783 /*********************************************************************
3784 * _setmaxstdio (MSVCRT.@)
3786 int CDECL _setmaxstdio(int newmax)
3788 TRACE("%d\n", newmax);
3790 if(newmax<_IOB_ENTRIES || newmax>MSVCRT_MAX_FILES || newmax<MSVCRT_stream_idx)
3791 return -1;
3793 MSVCRT_max_streams = newmax;
3794 return MSVCRT_max_streams;