mshtml: Addeed IHTMLDocument5::createAttribute implementation.
[wine] / dlls / msvcrt / file.c
1 /*
2  * msvcrt.dll file functions
3  *
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
10  *
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.
15  *
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.
20  *
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
24  *
25  * TODO
26  * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31
32 #include <stdarg.h>
33 #include <stdio.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <sys/types.h>
38
39 #include "windef.h"
40 #include "winbase.h"
41 #include "winternl.h"
42 #include "msvcrt.h"
43 #include "mtdll.h"
44
45 #include "wine/unicode.h"
46
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
50
51 /* for stat mode, permissions apply to all,owner and group */
52 #define ALL_S_IREAD  (MSVCRT__S_IREAD  | (MSVCRT__S_IREAD  >> 3) | (MSVCRT__S_IREAD  >> 6))
53 #define ALL_S_IWRITE (MSVCRT__S_IWRITE | (MSVCRT__S_IWRITE >> 3) | (MSVCRT__S_IWRITE >> 6))
54 #define ALL_S_IEXEC  (MSVCRT__S_IEXEC  | (MSVCRT__S_IEXEC  >> 3) | (MSVCRT__S_IEXEC  >> 6))
55
56 /* _access() bit flags FIXME: incomplete */
57 #define MSVCRT_W_OK      0x02
58 #define MSVCRT_R_OK      0x04
59
60 /* values for wxflag in file descriptor */
61 #define WX_OPEN           0x01
62 #define WX_ATEOF          0x02
63 #define WX_READNL         0x04  /* read started with \n */
64 #define WX_PIPE           0x08
65 #define WX_DONTINHERIT    0x10
66 #define WX_APPEND         0x20
67 #define WX_TEXT           0x80
68
69 /* values for exflag - it's used differently in msvcr90.dll*/
70 #define EF_UTF8           0x01
71 #define EF_UTF16          0x02
72 #define EF_CRIT_INIT      0x04
73 #define EF_UNK_UNICODE    0x08
74
75 static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
76 static char utf16_bom[2] = { 0xff, 0xfe };
77
78 /* FIXME: this should be allocated dynamically */
79 #define MSVCRT_MAX_FILES 2048
80 #define MSVCRT_FD_BLOCK_SIZE 32
81
82 /* ioinfo structure size is different in msvcrXX.dll's */
83 typedef struct {
84     HANDLE              handle;
85     unsigned char       wxflag;
86     char                lookahead[3];
87     int                 exflag;
88     CRITICAL_SECTION    crit;
89 } ioinfo;
90
91 /*********************************************************************
92  *              __pioinfo (MSVCRT.@)
93  * array of pointers to ioinfo arrays [32]
94  */
95 ioinfo * MSVCRT___pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE] = { 0 };
96
97 /*********************************************************************
98  *              __badioinfo (MSVCRT.@)
99  */
100 ioinfo MSVCRT___badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
101
102 static int MSVCRT_fdstart = 3; /* first unallocated fd */
103 static int MSVCRT_fdend = 3; /* highest allocated fd */
104
105 typedef struct {
106     MSVCRT_FILE file;
107     CRITICAL_SECTION crit;
108 } file_crit;
109
110 MSVCRT_FILE MSVCRT__iob[_IOB_ENTRIES] = { { 0 } };
111 static file_crit* MSVCRT_fstream[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE];
112 static int MSVCRT_max_streams = 512, MSVCRT_stream_idx;
113
114 /* INTERNAL: process umask */
115 static int MSVCRT_umask = 0;
116
117 /* INTERNAL: static data for tmpnam and _wtmpname functions */
118 static int tmpnam_unique;
119
120 static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e';
121 static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't';
122 static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd';
123 static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm';
124
125 #define TOUL(x) (ULONGLONG)(x)
126 static const ULONGLONG WCEXE = TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
127 static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
128 static const ULONGLONG WCCMD = TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
129 static const ULONGLONG WCCOM = TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
130
131 /* This critical section protects the tables MSVCRT___pioinfo and MSVCRT_fstreams,
132  * and their related indexes, MSVCRT_fdstart, MSVCRT_fdend,
133  * and MSVCRT_stream_idx, from race conditions.
134  * It doesn't protect against race conditions manipulating the underlying files
135  * or flags; doing so would probably be better accomplished with per-file
136  * protection, rather than locking the whole table for every change.
137  */
138 static CRITICAL_SECTION MSVCRT_file_cs;
139 static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug =
140 {
141     0, 0, &MSVCRT_file_cs,
142     { &MSVCRT_file_cs_debug.ProcessLocksList, &MSVCRT_file_cs_debug.ProcessLocksList },
143       0, 0, { (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs") }
144 };
145 static CRITICAL_SECTION MSVCRT_file_cs = { &MSVCRT_file_cs_debug, -1, 0, 0, 0, 0 };
146 #define LOCK_FILES()    do { EnterCriticalSection(&MSVCRT_file_cs); } while (0)
147 #define UNLOCK_FILES()  do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0)
148
149 static void msvcrt_stat64_to_stat(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stat *buf)
150 {
151     buf->st_dev   = buf64->st_dev;
152     buf->st_ino   = buf64->st_ino;
153     buf->st_mode  = buf64->st_mode;
154     buf->st_nlink = buf64->st_nlink;
155     buf->st_uid   = buf64->st_uid;
156     buf->st_gid   = buf64->st_gid;
157     buf->st_rdev  = buf64->st_rdev;
158     buf->st_size  = buf64->st_size;
159     buf->st_atime = buf64->st_atime;
160     buf->st_mtime = buf64->st_mtime;
161     buf->st_ctime = buf64->st_ctime;
162 }
163
164 static void msvcrt_stat64_to_stati64(const struct MSVCRT__stat64 *buf64, struct MSVCRT__stati64 *buf)
165 {
166     buf->st_dev   = buf64->st_dev;
167     buf->st_ino   = buf64->st_ino;
168     buf->st_mode  = buf64->st_mode;
169     buf->st_nlink = buf64->st_nlink;
170     buf->st_uid   = buf64->st_uid;
171     buf->st_gid   = buf64->st_gid;
172     buf->st_rdev  = buf64->st_rdev;
173     buf->st_size  = buf64->st_size;
174     buf->st_atime = buf64->st_atime;
175     buf->st_mtime = buf64->st_mtime;
176     buf->st_ctime = buf64->st_ctime;
177 }
178
179 static void time_to_filetime( MSVCRT___time64_t time, FILETIME *ft )
180 {
181     /* 1601 to 1970 is 369 years plus 89 leap days */
182     static const __int64 secs_1601_to_1970 = ((369 * 365 + 89) * (__int64)86400);
183
184     __int64 ticks = (time + secs_1601_to_1970) * 10000000;
185     ft->dwHighDateTime = ticks >> 32;
186     ft->dwLowDateTime = ticks;
187 }
188
189 static inline ioinfo* msvcrt_get_ioinfo(int fd)
190 {
191     ioinfo *ret = NULL;
192     if(fd < MSVCRT_MAX_FILES)
193         ret = MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE];
194     if(!ret)
195         return &MSVCRT___badioinfo;
196
197     return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
198 }
199
200 static inline MSVCRT_FILE* msvcrt_get_file(int i)
201 {
202     file_crit *ret;
203
204     if(i >= MSVCRT_max_streams)
205         return NULL;
206
207     if(i < _IOB_ENTRIES)
208         return &MSVCRT__iob[i];
209
210     ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE];
211     if(!ret) {
212         MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(file_crit));
213         if(!MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE]) {
214             ERR("out of memory\n");
215             *MSVCRT__errno() = MSVCRT_ENOMEM;
216             return NULL;
217         }
218
219         ret = MSVCRT_fstream[i/MSVCRT_FD_BLOCK_SIZE] + (i%MSVCRT_FD_BLOCK_SIZE);
220     } else
221         ret += i%MSVCRT_FD_BLOCK_SIZE;
222
223     return &ret->file;
224 }
225
226 static inline BOOL msvcrt_is_valid_fd(int fd)
227 {
228     return fd >= 0 && fd < MSVCRT_fdend && (msvcrt_get_ioinfo(fd)->wxflag & WX_OPEN);
229 }
230
231 /* INTERNAL: Get the HANDLE for a fd
232  * This doesn't lock the table, because a failure will result in
233  * INVALID_HANDLE_VALUE being returned, which should be handled correctly.  If
234  * it returns a valid handle which is about to be closed, a subsequent call
235  * will fail, most likely in a sane way.
236  */
237 static HANDLE msvcrt_fdtoh(int fd)
238 {
239   if (!msvcrt_is_valid_fd(fd))
240   {
241     WARN(":fd (%d) - no handle!\n",fd);
242     *MSVCRT___doserrno() = 0;
243     *MSVCRT__errno() = MSVCRT_EBADF;
244     return INVALID_HANDLE_VALUE;
245   }
246   if (msvcrt_get_ioinfo(fd)->handle == INVALID_HANDLE_VALUE)
247       WARN("returning INVALID_HANDLE_VALUE for %d\n", fd);
248   return msvcrt_get_ioinfo(fd)->handle;
249 }
250
251 /* INTERNAL: free a file entry fd */
252 static void msvcrt_free_fd(int fd)
253 {
254   HANDLE old_handle;
255   ioinfo *fdinfo;
256
257   LOCK_FILES();
258   fdinfo = msvcrt_get_ioinfo(fd);
259   old_handle = fdinfo->handle;
260   if(fdinfo != &MSVCRT___badioinfo)
261   {
262     fdinfo->handle = INVALID_HANDLE_VALUE;
263     fdinfo->wxflag = 0;
264   }
265   TRACE(":fd (%d) freed\n",fd);
266   if (fd < 3) /* don't use 0,1,2 for user files */
267   {
268     switch (fd)
269     {
270     case 0:
271         if (GetStdHandle(STD_INPUT_HANDLE) == old_handle) SetStdHandle(STD_INPUT_HANDLE, 0);
272         break;
273     case 1:
274         if (GetStdHandle(STD_OUTPUT_HANDLE) == old_handle) SetStdHandle(STD_OUTPUT_HANDLE, 0);
275         break;
276     case 2:
277         if (GetStdHandle(STD_ERROR_HANDLE) == old_handle) SetStdHandle(STD_ERROR_HANDLE, 0);
278         break;
279     }
280   }
281   else
282   {
283     if (fd == MSVCRT_fdend - 1)
284       MSVCRT_fdend--;
285     if (fd < MSVCRT_fdstart)
286       MSVCRT_fdstart = fd;
287   }
288   UNLOCK_FILES();
289 }
290
291 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
292 /* caller must hold the files lock */
293 static int msvcrt_alloc_fd_from(HANDLE hand, int flag, int fd)
294 {
295   ioinfo *fdinfo;
296
297   if (fd >= MSVCRT_MAX_FILES)
298   {
299     WARN(":files exhausted!\n");
300     *MSVCRT__errno() = MSVCRT_ENFILE;
301     return -1;
302   }
303
304   fdinfo = msvcrt_get_ioinfo(fd);
305   if(fdinfo == &MSVCRT___badioinfo) {
306     int i;
307
308     MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE, sizeof(ioinfo));
309     if(!MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE]) {
310       WARN(":out of memory!\n");
311       *MSVCRT__errno() = MSVCRT_ENOMEM;
312       return -1;
313     }
314
315     for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
316       MSVCRT___pioinfo[fd/MSVCRT_FD_BLOCK_SIZE][i].handle = INVALID_HANDLE_VALUE;
317
318     fdinfo = msvcrt_get_ioinfo(fd);
319   }
320
321   fdinfo->handle = hand;
322   fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE));
323   fdinfo->lookahead[0] = '\n';
324   fdinfo->lookahead[1] = '\n';
325   fdinfo->lookahead[2] = '\n';
326   fdinfo->exflag = 0;
327
328   /* locate next free slot */
329   if (fd == MSVCRT_fdstart && fd == MSVCRT_fdend)
330     MSVCRT_fdstart = MSVCRT_fdend + 1;
331   else
332     while (MSVCRT_fdstart < MSVCRT_fdend &&
333       msvcrt_get_ioinfo(MSVCRT_fdstart)->handle != INVALID_HANDLE_VALUE)
334       MSVCRT_fdstart++;
335   /* update last fd in use */
336   if (fd >= MSVCRT_fdend)
337     MSVCRT_fdend = fd + 1;
338   TRACE("fdstart is %d, fdend is %d\n", MSVCRT_fdstart, MSVCRT_fdend);
339
340   switch (fd)
341   {
342   case 0: SetStdHandle(STD_INPUT_HANDLE,  hand); break;
343   case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
344   case 2: SetStdHandle(STD_ERROR_HANDLE,  hand); break;
345   }
346
347   return fd;
348 }
349
350 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
351 static int msvcrt_alloc_fd(HANDLE hand, int flag)
352 {
353   int ret;
354
355   LOCK_FILES();
356   TRACE(":handle (%p) allocating fd (%d)\n",hand,MSVCRT_fdstart);
357   ret = msvcrt_alloc_fd_from(hand, flag, MSVCRT_fdstart);
358   UNLOCK_FILES();
359   return ret;
360 }
361
362 /* INTERNAL: Allocate a FILE* for an fd slot */
363 /* caller must hold the files lock */
364 static MSVCRT_FILE* msvcrt_alloc_fp(void)
365 {
366   int i;
367   MSVCRT_FILE *file;
368
369   for (i = 3; i < MSVCRT_max_streams; i++)
370   {
371     file = msvcrt_get_file(i);
372     if (!file)
373       return NULL;
374
375     if (file->_flag == 0)
376     {
377       if (i == MSVCRT_stream_idx)
378       {
379           if (file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
380           {
381               InitializeCriticalSection(&((file_crit*)file)->crit);
382               ((file_crit*)file)->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_crit.crit");
383           }
384           MSVCRT_stream_idx++;
385       }
386       return file;
387     }
388   }
389
390   return NULL;
391 }
392
393 /* INTERNAL: initialize a FILE* from an open fd */
394 static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags)
395 {
396   TRACE(":fd (%d) allocating FILE*\n",fd);
397   if (!msvcrt_is_valid_fd(fd))
398   {
399     WARN(":invalid fd %d\n",fd);
400     *MSVCRT___doserrno() = 0;
401     *MSVCRT__errno() = MSVCRT_EBADF;
402     return -1;
403   }
404   memset(file, 0, sizeof(*file));
405   file->_file = fd;
406   file->_flag = stream_flags;
407
408   TRACE(":got FILE* (%p)\n",file);
409   return 0;
410 }
411
412 /* INTERNAL: Create an inheritance data block (for spawned process)
413  * The inheritance block is made of:
414  *      00      int     nb of file descriptor (NBFD)
415  *      04      char    file flags (wxflag): repeated for each fd
416  *      4+NBFD  HANDLE  file handle: repeated for each fd
417  */
418 unsigned msvcrt_create_io_inherit_block(WORD *size, BYTE **block)
419 {
420   int         fd;
421   char*       wxflag_ptr;
422   HANDLE*     handle_ptr;
423   ioinfo*     fdinfo;
424
425   *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend;
426   *block = MSVCRT_calloc(*size, 1);
427   if (!*block)
428   {
429     *size = 0;
430     return FALSE;
431   }
432   wxflag_ptr = (char*)*block + sizeof(unsigned);
433   handle_ptr = (HANDLE*)(wxflag_ptr + MSVCRT_fdend * sizeof(char));
434
435   *(unsigned*)*block = MSVCRT_fdend;
436   for (fd = 0; fd < MSVCRT_fdend; fd++)
437   {
438     /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
439     fdinfo = msvcrt_get_ioinfo(fd);
440     if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN)
441     {
442       *wxflag_ptr = fdinfo->wxflag;
443       *handle_ptr = fdinfo->handle;
444     }
445     else
446     {
447       *wxflag_ptr = 0;
448       *handle_ptr = INVALID_HANDLE_VALUE;
449     }
450     wxflag_ptr++; handle_ptr++;
451   } 
452   return TRUE;
453 }
454
455 /* INTERNAL: Set up all file descriptors, 
456  * as well as default streams (stdin, stderr and stdout) 
457  */
458 void msvcrt_init_io(void)
459 {
460   STARTUPINFOA  si;
461   int           i;
462   ioinfo        *fdinfo;
463
464   GetStartupInfoA(&si);
465   if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
466   {
467     BYTE*       wxflag_ptr;
468     HANDLE*     handle_ptr;
469     unsigned int count;
470
471     count = *(unsigned*)si.lpReserved2;
472     wxflag_ptr = si.lpReserved2 + sizeof(unsigned);
473     handle_ptr = (HANDLE*)(wxflag_ptr + count);
474
475     count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1));
476     count = min(count, MSVCRT_MAX_FILES);
477     for (i = 0; i < count; i++)
478     {
479       if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
480         msvcrt_alloc_fd_from(*handle_ptr, *wxflag_ptr, i);
481
482       wxflag_ptr++; handle_ptr++;
483     }
484     MSVCRT_fdend = max( 3, count );
485     for (MSVCRT_fdstart = 3; MSVCRT_fdstart < MSVCRT_fdend; MSVCRT_fdstart++)
486         if (msvcrt_get_ioinfo(MSVCRT_fdstart)->handle == INVALID_HANDLE_VALUE) break;
487   }
488
489   if(!MSVCRT___pioinfo[0])
490       msvcrt_alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3);
491
492   fdinfo = msvcrt_get_ioinfo(0);
493   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
494   {
495       HANDLE std = GetStdHandle(STD_INPUT_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;
500       fdinfo->lookahead[0] = '\n';
501       fdinfo->lookahead[1] = '\n';
502       fdinfo->lookahead[2] = '\n';
503       fdinfo->exflag = 0;
504   }
505
506   fdinfo = msvcrt_get_ioinfo(1);
507   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
508   {
509       HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
510       if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
511                                                          GetCurrentProcess(), &fdinfo->handle,
512                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
513           fdinfo->wxflag = WX_OPEN | WX_TEXT;
514       fdinfo->lookahead[0] = '\n';
515       fdinfo->lookahead[1] = '\n';
516       fdinfo->lookahead[2] = '\n';
517       fdinfo->exflag = 0;
518   }
519
520   fdinfo = msvcrt_get_ioinfo(2);
521   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
522   {
523       HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
524       if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
525                                                          GetCurrentProcess(), &fdinfo->handle,
526                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
527           fdinfo->wxflag = WX_OPEN | WX_TEXT;
528       fdinfo->lookahead[0] = '\n';
529       fdinfo->lookahead[1] = '\n';
530       fdinfo->lookahead[2] = '\n';
531       fdinfo->exflag = 0;
532   }
533
534   TRACE(":handles (%p)(%p)(%p)\n", msvcrt_get_ioinfo(0)->handle,
535         msvcrt_get_ioinfo(1)->handle, msvcrt_get_ioinfo(2)->handle);
536
537   memset(MSVCRT__iob,0,3*sizeof(MSVCRT_FILE));
538   for (i = 0; i < 3; i++)
539   {
540     /* FILE structs for stdin/out/err are static and never deleted */
541     MSVCRT__iob[i]._file = i;
542     MSVCRT__iob[i]._tmpfname = NULL;
543     MSVCRT__iob[i]._flag = (i == 0) ? MSVCRT__IOREAD : MSVCRT__IOWRT;
544   }
545   MSVCRT_stream_idx = 3;
546 }
547
548 /* INTERNAL: Flush stdio file buffer */
549 static int msvcrt_flush_buffer(MSVCRT_FILE* file)
550 {
551   if(file->_bufsiz) {
552         int cnt=file->_ptr-file->_base;
553         if(cnt>0 && MSVCRT__write(file->_file, file->_base, cnt) != cnt) {
554             file->_flag |= MSVCRT__IOERR;
555             return MSVCRT_EOF;
556         }
557         file->_ptr=file->_base;
558         file->_cnt=file->_bufsiz;
559   }
560   return 0;
561 }
562
563 /*********************************************************************
564  *              _isatty (MSVCRT.@)
565  */
566 int CDECL MSVCRT__isatty(int fd)
567 {
568     HANDLE hand = msvcrt_fdtoh(fd);
569
570     TRACE(":fd (%d) handle (%p)\n",fd,hand);
571     if (hand == INVALID_HANDLE_VALUE)
572         return 0;
573
574     return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
575 }
576
577 /* INTERNAL: Allocate stdio file buffer */
578 static BOOL msvcrt_alloc_buffer(MSVCRT_FILE* file)
579 {
580     if((file->_file==MSVCRT_STDOUT_FILENO || file->_file==MSVCRT_STDERR_FILENO)
581             && MSVCRT__isatty(file->_file))
582         return FALSE;
583
584     file->_base = MSVCRT_calloc(MSVCRT_BUFSIZ,1);
585     if(file->_base) {
586         file->_bufsiz = MSVCRT_BUFSIZ;
587         file->_flag |= MSVCRT__IOMYBUF;
588     } else {
589         file->_base = (char*)(&file->_charbuf);
590         /* put here 2 ??? */
591         file->_bufsiz = sizeof(file->_charbuf);
592     }
593     file->_ptr = file->_base;
594     file->_cnt = 0;
595     return TRUE;
596 }
597
598 /* INTERNAL: Allocate temporary buffer for stdout and stderr */
599 static BOOL add_std_buffer(MSVCRT_FILE *file)
600 {
601     static char buffers[2][MSVCRT_BUFSIZ];
602
603     if((file->_file!=MSVCRT_STDOUT_FILENO && file->_file!=MSVCRT_STDERR_FILENO)
604             || !MSVCRT__isatty(file->_file) || file->_bufsiz)
605         return FALSE;
606
607     file->_ptr = file->_base = buffers[file->_file == MSVCRT_STDOUT_FILENO ? 0 : 1];
608     file->_bufsiz = file->_cnt = MSVCRT_BUFSIZ;
609     return TRUE;
610 }
611
612 /* INTERNAL: Removes temporary buffer from stdout or stderr */
613 /* Only call this function when add_std_buffer returned TRUE */
614 static void remove_std_buffer(MSVCRT_FILE *file)
615 {
616     msvcrt_flush_buffer(file);
617     file->_ptr = file->_base = NULL;
618     file->_bufsiz = file->_cnt = 0;
619 }
620
621 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
622 static int msvcrt_int_to_base32(int num, char *str)
623 {
624   char *p;
625   int n = num;
626   int digits = 0;
627
628   while (n != 0)
629   {
630     n >>= 5;
631     digits++;
632   }
633   p = str + digits;
634   *p = 0;
635   while (--p >= str)
636   {
637     *p = (num & 31) + '0';
638     if (*p > '9')
639       *p += ('a' - '0' - 10);
640     num >>= 5;
641   }
642
643   return digits;
644 }
645
646 /* INTERNAL: wide character version of msvcrt_int_to_base32 */
647 static int msvcrt_int_to_base32_w(int num, MSVCRT_wchar_t *str)
648 {
649     MSVCRT_wchar_t *p;
650     int n = num;
651     int digits = 0;
652
653     while (n != 0)
654     {
655         n >>= 5;
656         digits++;
657     }
658     p = str + digits;
659     *p = 0;
660     while (--p >= str)
661     {
662         *p = (num & 31) + '0';
663         if (*p > '9')
664             *p += ('a' - '0' - 10);
665         num >>= 5;
666     }
667
668     return digits;
669 }
670
671 /*********************************************************************
672  *              __iob_func(MSVCRT.@)
673  */
674 MSVCRT_FILE * CDECL MSVCRT___iob_func(void)
675 {
676  return &MSVCRT__iob[0];
677 }
678
679 /*********************************************************************
680  *              _access (MSVCRT.@)
681  */
682 int CDECL MSVCRT__access(const char *filename, int mode)
683 {
684   DWORD attr = GetFileAttributesA(filename);
685
686   TRACE("(%s,%d) %d\n",filename,mode,attr);
687
688   if (!filename || attr == INVALID_FILE_ATTRIBUTES)
689   {
690     msvcrt_set_errno(GetLastError());
691     return -1;
692   }
693   if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
694   {
695     msvcrt_set_errno(ERROR_ACCESS_DENIED);
696     return -1;
697   }
698   return 0;
699 }
700
701 /*********************************************************************
702  *              _access_s (MSVCRT.@)
703  */
704 int CDECL _access_s(const char *filename, int mode)
705 {
706   if (!MSVCRT_CHECK_PMT(filename != NULL)) return -1;
707   if (!MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0)) return -1;
708
709   return MSVCRT__access(filename, mode);
710 }
711
712 /*********************************************************************
713  *              _waccess (MSVCRT.@)
714  */
715 int CDECL MSVCRT__waccess(const MSVCRT_wchar_t *filename, int mode)
716 {
717   DWORD attr = GetFileAttributesW(filename);
718
719   TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr);
720
721   if (!filename || attr == INVALID_FILE_ATTRIBUTES)
722   {
723     msvcrt_set_errno(GetLastError());
724     return -1;
725   }
726   if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & MSVCRT_W_OK))
727   {
728     msvcrt_set_errno(ERROR_ACCESS_DENIED);
729     return -1;
730   }
731   return 0;
732 }
733
734 /*********************************************************************
735  *              _waccess_s (MSVCRT.@)
736  */
737 int CDECL _waccess_s(const MSVCRT_wchar_t *filename, int mode)
738 {
739   if (!MSVCRT_CHECK_PMT(filename != NULL)) return -1;
740   if (!MSVCRT_CHECK_PMT((mode & ~(MSVCRT_R_OK | MSVCRT_W_OK)) == 0)) return -1;
741
742   return MSVCRT__waccess(filename, mode);
743 }
744
745 /*********************************************************************
746  *              _chmod (MSVCRT.@)
747  */
748 int CDECL MSVCRT__chmod(const char *path, int flags)
749 {
750   DWORD oldFlags = GetFileAttributesA(path);
751
752   if (oldFlags != INVALID_FILE_ATTRIBUTES)
753   {
754     DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
755       oldFlags | FILE_ATTRIBUTE_READONLY;
756
757     if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
758       return 0;
759   }
760   msvcrt_set_errno(GetLastError());
761   return -1;
762 }
763
764 /*********************************************************************
765  *              _wchmod (MSVCRT.@)
766  */
767 int CDECL MSVCRT__wchmod(const MSVCRT_wchar_t *path, int flags)
768 {
769   DWORD oldFlags = GetFileAttributesW(path);
770
771   if (oldFlags != INVALID_FILE_ATTRIBUTES)
772   {
773     DWORD newFlags = (flags & MSVCRT__S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
774       oldFlags | FILE_ATTRIBUTE_READONLY;
775
776     if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
777       return 0;
778   }
779   msvcrt_set_errno(GetLastError());
780   return -1;
781 }
782
783 /*********************************************************************
784  *              _unlink (MSVCRT.@)
785  */
786 int CDECL MSVCRT__unlink(const char *path)
787 {
788   TRACE("%s\n",debugstr_a(path));
789   if(DeleteFileA(path))
790     return 0;
791   TRACE("failed (%d)\n",GetLastError());
792   msvcrt_set_errno(GetLastError());
793   return -1;
794 }
795
796 /*********************************************************************
797  *              _wunlink (MSVCRT.@)
798  */
799 int CDECL MSVCRT__wunlink(const MSVCRT_wchar_t *path)
800 {
801   TRACE("(%s)\n",debugstr_w(path));
802   if(DeleteFileW(path))
803     return 0;
804   TRACE("failed (%d)\n",GetLastError());
805   msvcrt_set_errno(GetLastError());
806   return -1;
807 }
808
809 /*********************************************************************
810  *              _commit (MSVCRT.@)
811  */
812 int CDECL MSVCRT__commit(int fd)
813 {
814     HANDLE hand = msvcrt_fdtoh(fd);
815
816     TRACE(":fd (%d) handle (%p)\n",fd,hand);
817     if (hand == INVALID_HANDLE_VALUE)
818         return -1;
819
820     if (!FlushFileBuffers(hand))
821     {
822         if (GetLastError() == ERROR_INVALID_HANDLE)
823         {
824             /* FlushFileBuffers fails for console handles
825              * so we ignore this error.
826              */
827             return 0;
828         }
829         TRACE(":failed-last error (%d)\n",GetLastError());
830         msvcrt_set_errno(GetLastError());
831         return -1;
832     }
833     TRACE(":ok\n");
834     return 0;
835 }
836
837 /* flush_all_buffers calls MSVCRT_fflush which calls flush_all_buffers */
838 int CDECL MSVCRT_fflush(MSVCRT_FILE* file);
839
840 /* INTERNAL: Flush all stream buffer */
841 static int msvcrt_flush_all_buffers(int mask)
842 {
843   int i, num_flushed = 0;
844   MSVCRT_FILE *file;
845
846   LOCK_FILES();
847   for (i = 3; i < MSVCRT_stream_idx; i++) {
848     file = msvcrt_get_file(i);
849
850     if (file->_flag)
851     {
852       if(file->_flag & mask) {
853         MSVCRT_fflush(file);
854         num_flushed++;
855       }
856     }
857   }
858   UNLOCK_FILES();
859
860   TRACE(":flushed (%d) handles\n",num_flushed);
861   return num_flushed;
862 }
863
864 /*********************************************************************
865  *              _flushall (MSVCRT.@)
866  */
867 int CDECL MSVCRT__flushall(void)
868 {
869     return msvcrt_flush_all_buffers(MSVCRT__IOWRT | MSVCRT__IOREAD);
870 }
871
872 /*********************************************************************
873  *              fflush (MSVCRT.@)
874  */
875 int CDECL MSVCRT_fflush(MSVCRT_FILE* file)
876 {
877     if(!file) {
878         msvcrt_flush_all_buffers(MSVCRT__IOWRT);
879     } else if(file->_flag & MSVCRT__IOWRT) {
880         int res;
881
882         MSVCRT__lock_file(file);
883         res = msvcrt_flush_buffer(file);
884
885         if(!res && (file->_flag & MSVCRT__IOCOMMIT))
886             res = MSVCRT__commit(file->_file) ? MSVCRT_EOF : 0;
887         MSVCRT__unlock_file(file);
888
889         return res;
890     } else if(file->_flag & MSVCRT__IOREAD) {
891         MSVCRT__lock_file(file);
892         file->_cnt = 0;
893         file->_ptr = file->_base;
894         MSVCRT__unlock_file(file);
895
896         return 0;
897     }
898     return 0;
899 }
900
901 /*********************************************************************
902  *              _close (MSVCRT.@)
903  */
904 int CDECL MSVCRT__close(int fd)
905 {
906   HANDLE hand;
907   int ret;
908
909   LOCK_FILES();
910   hand = msvcrt_fdtoh(fd);
911   TRACE(":fd (%d) handle (%p)\n",fd,hand);
912   if (!msvcrt_is_valid_fd(fd)) {
913     ret = -1;
914   } else {
915     msvcrt_free_fd(fd);
916     ret = CloseHandle(hand) ? 0 : -1;
917     if (ret) {
918       WARN(":failed-last error (%d)\n",GetLastError());
919       msvcrt_set_errno(GetLastError());
920     }
921   }
922   UNLOCK_FILES();
923   TRACE(":ok\n");
924   return ret;
925 }
926
927 /*********************************************************************
928  *              _dup2 (MSVCRT.@)
929  * NOTES
930  * MSDN isn't clear on this point, but the remarks for _pipe
931  * indicate file descriptors duplicated with _dup and _dup2 are always
932  * inheritable.
933  */
934 int CDECL MSVCRT__dup2(int od, int nd)
935 {
936   int ret;
937
938   TRACE("(od=%d, nd=%d)\n", od, nd);
939   LOCK_FILES();
940   if (nd < MSVCRT_MAX_FILES && nd >= 0 && msvcrt_is_valid_fd(od))
941   {
942     HANDLE handle;
943
944     if (DuplicateHandle(GetCurrentProcess(), msvcrt_get_ioinfo(od)->handle,
945      GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
946     {
947       int wxflag = msvcrt_get_ioinfo(od)->wxflag & ~MSVCRT__O_NOINHERIT;
948
949       if (msvcrt_is_valid_fd(nd))
950         MSVCRT__close(nd);
951       ret = msvcrt_alloc_fd_from(handle, wxflag, nd);
952       if (ret == -1)
953       {
954         CloseHandle(handle);
955         *MSVCRT__errno() = MSVCRT_EMFILE;
956       }
957       else
958       {
959         /* _dup2 returns 0, not nd, on success */
960         ret = 0;
961       }
962     }
963     else
964     {
965       ret = -1;
966       msvcrt_set_errno(GetLastError());
967     }
968   }
969   else
970   {
971     *MSVCRT__errno() = MSVCRT_EBADF;
972     ret = -1;
973   }
974   UNLOCK_FILES();
975   return ret;
976 }
977
978 /*********************************************************************
979  *              _dup (MSVCRT.@)
980  */
981 int CDECL MSVCRT__dup(int od)
982 {
983   int fd, ret;
984  
985   LOCK_FILES();
986   fd = MSVCRT_fdstart;
987   if (MSVCRT__dup2(od, fd) == 0)
988     ret = fd;
989   else
990     ret = -1;
991   UNLOCK_FILES();
992   return ret;
993 }
994
995 /*********************************************************************
996  *              _eof (MSVCRT.@)
997  */
998 int CDECL MSVCRT__eof(int fd)
999 {
1000   DWORD curpos,endpos;
1001   LONG hcurpos,hendpos;
1002   HANDLE hand = msvcrt_fdtoh(fd);
1003
1004   TRACE(":fd (%d) handle (%p)\n",fd,hand);
1005
1006   if (hand == INVALID_HANDLE_VALUE)
1007     return -1;
1008
1009   if (msvcrt_get_ioinfo(fd)->wxflag & WX_ATEOF) return TRUE;
1010
1011   /* Otherwise we do it the hard way */
1012   hcurpos = hendpos = 0;
1013   curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT);
1014   endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
1015
1016   if (curpos == endpos && hcurpos == hendpos)
1017   {
1018     /* FIXME: shouldn't WX_ATEOF be set here? */
1019     return TRUE;
1020   }
1021
1022   SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
1023   return FALSE;
1024 }
1025
1026 /*********************************************************************
1027  *              _fcloseall (MSVCRT.@)
1028  */
1029 int CDECL MSVCRT__fcloseall(void)
1030 {
1031   int num_closed = 0, i;
1032   MSVCRT_FILE *file;
1033
1034   LOCK_FILES();
1035   for (i = 3; i < MSVCRT_stream_idx; i++) {
1036     file = msvcrt_get_file(i);
1037
1038     if (file->_flag && !MSVCRT_fclose(file))
1039       num_closed++;
1040   }
1041   UNLOCK_FILES();
1042
1043   TRACE(":closed (%d) handles\n",num_closed);
1044   return num_closed;
1045 }
1046
1047 /* free everything on process exit */
1048 void msvcrt_free_io(void)
1049 {
1050     unsigned int i;
1051     int j;
1052
1053     MSVCRT__fcloseall();
1054     /* The Win32 _fcloseall() function explicitly doesn't close stdin,
1055      * stdout, and stderr (unlike GNU), so we need to fclose() them here
1056      * or they won't get flushed.
1057      */
1058     MSVCRT_fclose(&MSVCRT__iob[0]);
1059     MSVCRT_fclose(&MSVCRT__iob[1]);
1060     MSVCRT_fclose(&MSVCRT__iob[2]);
1061
1062     for(i=0; i<sizeof(MSVCRT___pioinfo)/sizeof(MSVCRT___pioinfo[0]); i++)
1063         MSVCRT_free(MSVCRT___pioinfo[i]);
1064
1065     for(j=0; j<MSVCRT_stream_idx; j++)
1066     {
1067         MSVCRT_FILE *file = msvcrt_get_file(j);
1068         if(file<MSVCRT__iob || file>=MSVCRT__iob+_IOB_ENTRIES)
1069         {
1070             ((file_crit*)file)->crit.DebugInfo->Spare[0] = 0;
1071             DeleteCriticalSection(&((file_crit*)file)->crit);
1072         }
1073     }
1074
1075     for(i=0; i<sizeof(MSVCRT_fstream)/sizeof(MSVCRT_fstream[0]); i++)
1076         MSVCRT_free(MSVCRT_fstream[i]);
1077
1078     DeleteCriticalSection(&MSVCRT_file_cs);
1079 }
1080
1081 /*********************************************************************
1082  *              _lseeki64 (MSVCRT.@)
1083  */
1084 __int64 CDECL MSVCRT__lseeki64(int fd, __int64 offset, int whence)
1085 {
1086   HANDLE hand = msvcrt_fdtoh(fd);
1087   LARGE_INTEGER ofs;
1088
1089   TRACE(":fd (%d) handle (%p)\n",fd,hand);
1090   if (hand == INVALID_HANDLE_VALUE)
1091     return -1;
1092
1093   if (whence < 0 || whence > 2)
1094   {
1095     *MSVCRT__errno() = MSVCRT_EINVAL;
1096     return -1;
1097   }
1098
1099   TRACE(":fd (%d) to %s pos %s\n",
1100         fd,wine_dbgstr_longlong(offset),
1101         (whence==SEEK_SET)?"SEEK_SET":
1102         (whence==SEEK_CUR)?"SEEK_CUR":
1103         (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
1104
1105   /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
1106    * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
1107   ofs.QuadPart = offset;
1108   if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
1109       GetLastError() == ERROR_SUCCESS)
1110   {
1111     msvcrt_get_ioinfo(fd)->wxflag &= ~WX_ATEOF;
1112     /* FIXME: What if we seek _to_ EOF - is EOF set? */
1113
1114     return ofs.QuadPart;
1115   }
1116   TRACE(":error-last error (%d)\n",GetLastError());
1117   msvcrt_set_errno(GetLastError());
1118   return -1;
1119 }
1120
1121 /*********************************************************************
1122  *              _lseek (MSVCRT.@)
1123  */
1124 LONG CDECL MSVCRT__lseek(int fd, LONG offset, int whence)
1125 {
1126     return MSVCRT__lseeki64(fd, offset, whence);
1127 }
1128
1129 /*********************************************************************
1130  *              _lock_file (MSVCRT.@)
1131  */
1132 void CDECL MSVCRT__lock_file(MSVCRT_FILE *file)
1133 {
1134     if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1135         _lock(_STREAM_LOCKS+(file-MSVCRT__iob));
1136     else
1137         EnterCriticalSection(&((file_crit*)file)->crit);
1138 }
1139
1140 /*********************************************************************
1141  *              _unlock_file (MSVCRT.@)
1142  */
1143 void CDECL MSVCRT__unlock_file(MSVCRT_FILE *file)
1144 {
1145     if(file>=MSVCRT__iob && file<MSVCRT__iob+_IOB_ENTRIES)
1146         _unlock(_STREAM_LOCKS+(file-MSVCRT__iob));
1147     else
1148         LeaveCriticalSection(&((file_crit*)file)->crit);
1149 }
1150
1151 /*********************************************************************
1152  *              _locking (MSVCRT.@)
1153  *
1154  * This is untested; the underlying LockFile doesn't work yet.
1155  */
1156 int CDECL MSVCRT__locking(int fd, int mode, LONG nbytes)
1157 {
1158   BOOL ret;
1159   DWORD cur_locn;
1160   HANDLE hand = msvcrt_fdtoh(fd);
1161
1162   TRACE(":fd (%d) handle (%p)\n",fd,hand);
1163   if (hand == INVALID_HANDLE_VALUE)
1164     return -1;
1165
1166   if (mode < 0 || mode > 4)
1167   {
1168     *MSVCRT__errno() = MSVCRT_EINVAL;
1169     return -1;
1170   }
1171
1172   TRACE(":fd (%d) by 0x%08x mode %s\n",
1173         fd,nbytes,(mode==MSVCRT__LK_UNLCK)?"_LK_UNLCK":
1174         (mode==MSVCRT__LK_LOCK)?"_LK_LOCK":
1175         (mode==MSVCRT__LK_NBLCK)?"_LK_NBLCK":
1176         (mode==MSVCRT__LK_RLCK)?"_LK_RLCK":
1177         (mode==MSVCRT__LK_NBRLCK)?"_LK_NBRLCK":
1178                           "UNKNOWN");
1179
1180   if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
1181   {
1182     FIXME ("Seek failed\n");
1183     *MSVCRT__errno() = MSVCRT_EINVAL; /* FIXME */
1184     return -1;
1185   }
1186   if (mode == MSVCRT__LK_LOCK || mode == MSVCRT__LK_RLCK)
1187   {
1188     int nretry = 10;
1189     ret = 1; /* just to satisfy gcc */
1190     while (nretry--)
1191     {
1192       ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
1193       if (ret) break;
1194       Sleep(1);
1195     }
1196   }
1197   else if (mode == MSVCRT__LK_UNLCK)
1198     ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
1199   else
1200     ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
1201   /* FIXME - what about error settings? */
1202   return ret ? 0 : -1;
1203 }
1204
1205 /*********************************************************************
1206  *              _fseeki64 (MSVCRT.@)
1207  */
1208 int CDECL MSVCRT__fseeki64(MSVCRT_FILE* file, __int64 offset, int whence)
1209 {
1210   int ret;
1211
1212   MSVCRT__lock_file(file);
1213   /* Flush output if needed */
1214   if(file->_flag & MSVCRT__IOWRT)
1215         msvcrt_flush_buffer(file);
1216
1217   if(whence == SEEK_CUR && file->_flag & MSVCRT__IOREAD ) {
1218       whence = SEEK_SET;
1219       offset += MSVCRT__ftelli64(file);
1220   }
1221
1222   /* Discard buffered input */
1223   file->_cnt = 0;
1224   file->_ptr = file->_base;
1225   /* Reset direction of i/o */
1226   if(file->_flag & MSVCRT__IORW) {
1227         file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
1228   }
1229   /* Clear end of file flag */
1230   file->_flag &= ~MSVCRT__IOEOF;
1231   ret = (MSVCRT__lseeki64(file->_file,offset,whence) == -1)?-1:0;
1232
1233   MSVCRT__unlock_file(file);
1234   return ret;
1235 }
1236
1237 /*********************************************************************
1238  *              fseek (MSVCRT.@)
1239  */
1240 int CDECL MSVCRT_fseek(MSVCRT_FILE* file, MSVCRT_long offset, int whence)
1241 {
1242     return MSVCRT__fseeki64( file, offset, whence );
1243 }
1244
1245 /*********************************************************************
1246  *              _chsize (MSVCRT.@)
1247  */
1248 int CDECL MSVCRT__chsize(int fd, MSVCRT_long size)
1249 {
1250     LONG cur, pos;
1251     HANDLE handle;
1252     BOOL ret = FALSE;
1253
1254     TRACE("(fd=%d, size=%d)\n", fd, size);
1255
1256     LOCK_FILES();
1257
1258     handle = msvcrt_fdtoh(fd);
1259     if (handle != INVALID_HANDLE_VALUE)
1260     {
1261         /* save the current file pointer */
1262         cur = MSVCRT__lseek(fd, 0, SEEK_CUR);
1263         if (cur >= 0)
1264         {
1265             pos = MSVCRT__lseek(fd, size, SEEK_SET);
1266             if (pos >= 0)
1267             {
1268                 ret = SetEndOfFile(handle);
1269                 if (!ret) msvcrt_set_errno(GetLastError());
1270             }
1271
1272             /* restore the file pointer */
1273             MSVCRT__lseek(fd, cur, SEEK_SET);
1274         }
1275     }
1276
1277     UNLOCK_FILES();
1278     return ret ? 0 : -1;
1279 }
1280
1281 /*********************************************************************
1282  *              clearerr (MSVCRT.@)
1283  */
1284 void CDECL MSVCRT_clearerr(MSVCRT_FILE* file)
1285 {
1286   TRACE(":file (%p) fd (%d)\n",file,file->_file);
1287
1288   MSVCRT__lock_file(file);
1289   file->_flag &= ~(MSVCRT__IOERR | MSVCRT__IOEOF);
1290   MSVCRT__unlock_file(file);
1291 }
1292
1293 /*********************************************************************
1294  *              rewind (MSVCRT.@)
1295  */
1296 void CDECL MSVCRT_rewind(MSVCRT_FILE* file)
1297 {
1298   TRACE(":file (%p) fd (%d)\n",file,file->_file);
1299
1300   MSVCRT__lock_file(file);
1301   MSVCRT_fseek(file, 0L, SEEK_SET);
1302   MSVCRT_clearerr(file);
1303   MSVCRT__unlock_file(file);
1304 }
1305
1306 static int msvcrt_get_flags(const MSVCRT_wchar_t* mode, int *open_flags, int* stream_flags)
1307 {
1308   int plus = strchrW(mode, '+') != NULL;
1309
1310   TRACE("%s\n", debugstr_w(mode));
1311
1312   while(*mode == ' ') mode++;
1313
1314   switch(*mode++)
1315   {
1316   case 'R': case 'r':
1317     *open_flags = plus ? MSVCRT__O_RDWR : MSVCRT__O_RDONLY;
1318     *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOREAD;
1319     break;
1320   case 'W': case 'w':
1321     *open_flags = MSVCRT__O_CREAT | MSVCRT__O_TRUNC | (plus  ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1322     *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1323     break;
1324   case 'A': case 'a':
1325     *open_flags = MSVCRT__O_CREAT | MSVCRT__O_APPEND | (plus  ? MSVCRT__O_RDWR : MSVCRT__O_WRONLY);
1326     *stream_flags = plus ? MSVCRT__IORW : MSVCRT__IOWRT;
1327     break;
1328   default:
1329     MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL);
1330     return -1;
1331   }
1332
1333   *stream_flags |= MSVCRT__commode;
1334
1335   while (*mode && *mode!=',')
1336     switch (*mode++)
1337     {
1338     case 'B': case 'b':
1339       *open_flags |=  MSVCRT__O_BINARY;
1340       *open_flags &= ~MSVCRT__O_TEXT;
1341       break;
1342     case 't':
1343       *open_flags |=  MSVCRT__O_TEXT;
1344       *open_flags &= ~MSVCRT__O_BINARY;
1345       break;
1346     case 'D':
1347       *open_flags |= MSVCRT__O_TEMPORARY;
1348       break;
1349     case 'T':
1350       *open_flags |= MSVCRT__O_SHORT_LIVED;
1351       break;
1352     case 'c':
1353       *stream_flags |= MSVCRT__IOCOMMIT;
1354       break;
1355     case 'n':
1356       *stream_flags &= ~MSVCRT__IOCOMMIT;
1357       break;
1358     case 'N':
1359       *open_flags |= MSVCRT__O_NOINHERIT;
1360       break;
1361     case '+':
1362     case ' ':
1363     case 'a':
1364     case 'w':
1365       break;
1366     case 'S':
1367     case 'R':
1368       FIXME("ignoring cache optimization flag: %c\n", mode[-1]);
1369       break;
1370     default:
1371       MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL);
1372       return -1;
1373     }
1374
1375   if(*mode == ',')
1376   {
1377     static const WCHAR ccs[] = {'c','c','s'};
1378     static const WCHAR utf8[] = {'u','t','f','-','8'};
1379     static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'};
1380     static const WCHAR unicode[] = {'u','n','i','c','o','d','e'};
1381
1382     mode++;
1383     while(*mode == ' ') mode++;
1384     if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0]))))
1385       return -1;
1386     mode += sizeof(ccs)/sizeof(ccs[0]);
1387     while(*mode == ' ') mode++;
1388     if(!MSVCRT_CHECK_PMT(*mode == '='))
1389         return -1;
1390     mode++;
1391     while(*mode == ' ') mode++;
1392
1393     if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0])))
1394     {
1395       *open_flags |= MSVCRT__O_U8TEXT;
1396       mode += sizeof(utf8)/sizeof(utf8[0]);
1397     }
1398     else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0])))
1399     {
1400       *open_flags |= MSVCRT__O_U16TEXT;
1401       mode += sizeof(utf16le)/sizeof(utf16le[0]);
1402     }
1403     else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0])))
1404     {
1405       *open_flags |= MSVCRT__O_WTEXT;
1406       mode += sizeof(unicode)/sizeof(unicode[0]);
1407     }
1408     else
1409     {
1410       MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL);
1411       return -1;
1412     }
1413
1414     while(*mode == ' ') mode++;
1415   }
1416
1417   if(!MSVCRT_CHECK_PMT(*mode == 0))
1418     return -1;
1419   return 0;
1420 }
1421
1422 /*********************************************************************
1423  *              _fdopen (MSVCRT.@)
1424  */
1425 MSVCRT_FILE* CDECL MSVCRT__fdopen(int fd, const char *mode)
1426 {
1427     MSVCRT_FILE *ret;
1428     MSVCRT_wchar_t *modeW = NULL;
1429
1430     if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
1431
1432     ret = MSVCRT__wfdopen(fd, modeW);
1433
1434     MSVCRT_free(modeW);
1435     return ret;
1436 }
1437
1438 /*********************************************************************
1439  *              _wfdopen (MSVCRT.@)
1440  */
1441 MSVCRT_FILE* CDECL MSVCRT__wfdopen(int fd, const MSVCRT_wchar_t *mode)
1442 {
1443   int open_flags, stream_flags;
1444   MSVCRT_FILE* file;
1445
1446   if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
1447
1448   LOCK_FILES();
1449   if (!(file = msvcrt_alloc_fp()))
1450     file = NULL;
1451   else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
1452   {
1453     file->_flag = 0;
1454     file = NULL;
1455   }
1456   else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
1457   UNLOCK_FILES();
1458
1459   return file;
1460 }
1461
1462 /*********************************************************************
1463  *              _filelength (MSVCRT.@)
1464  */
1465 LONG CDECL MSVCRT__filelength(int fd)
1466 {
1467   LONG curPos = MSVCRT__lseek(fd, 0, SEEK_CUR);
1468   if (curPos != -1)
1469   {
1470     LONG endPos = MSVCRT__lseek(fd, 0, SEEK_END);
1471     if (endPos != -1)
1472     {
1473       if (endPos != curPos)
1474         MSVCRT__lseek(fd, curPos, SEEK_SET);
1475       return endPos;
1476     }
1477   }
1478   return -1;
1479 }
1480
1481 /*********************************************************************
1482  *              _filelengthi64 (MSVCRT.@)
1483  */
1484 __int64 CDECL MSVCRT__filelengthi64(int fd)
1485 {
1486   __int64 curPos = MSVCRT__lseeki64(fd, 0, SEEK_CUR);
1487   if (curPos != -1)
1488   {
1489     __int64 endPos = MSVCRT__lseeki64(fd, 0, SEEK_END);
1490     if (endPos != -1)
1491     {
1492       if (endPos != curPos)
1493         MSVCRT__lseeki64(fd, curPos, SEEK_SET);
1494       return endPos;
1495     }
1496   }
1497   return -1;
1498 }
1499
1500 /*********************************************************************
1501  *              _fileno (MSVCRT.@)
1502  */
1503 int CDECL MSVCRT__fileno(MSVCRT_FILE* file)
1504 {
1505   TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
1506   return file->_file;
1507 }
1508
1509 /*********************************************************************
1510  *              _fstat64 (MSVCRT.@)
1511  */
1512 int CDECL MSVCRT__fstat64(int fd, struct MSVCRT__stat64* buf)
1513 {
1514   DWORD dw;
1515   DWORD type;
1516   BY_HANDLE_FILE_INFORMATION hfi;
1517   HANDLE hand = msvcrt_fdtoh(fd);
1518
1519   TRACE(":fd (%d) stat (%p)\n",fd,buf);
1520   if (hand == INVALID_HANDLE_VALUE)
1521     return -1;
1522
1523   if (!buf)
1524   {
1525     WARN(":failed-NULL buf\n");
1526     msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1527     return -1;
1528   }
1529
1530   memset(&hfi, 0, sizeof(hfi));
1531   memset(buf, 0, sizeof(struct MSVCRT__stat64));
1532   type = GetFileType(hand);
1533   if (type == FILE_TYPE_PIPE)
1534   {
1535     buf->st_dev = buf->st_rdev = fd;
1536     buf->st_mode = S_IFIFO;
1537     buf->st_nlink = 1;
1538   }
1539   else if (type == FILE_TYPE_CHAR)
1540   {
1541     buf->st_dev = buf->st_rdev = fd;
1542     buf->st_mode = S_IFCHR;
1543     buf->st_nlink = 1;
1544   }
1545   else /* FILE_TYPE_DISK etc. */
1546   {
1547     if (!GetFileInformationByHandle(hand, &hfi))
1548     {
1549       WARN(":failed-last error (%d)\n",GetLastError());
1550       msvcrt_set_errno(ERROR_INVALID_PARAMETER);
1551       return -1;
1552     }
1553     buf->st_mode = S_IFREG | 0444;
1554     if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1555       buf->st_mode |= 0222;
1556     buf->st_size  = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
1557     RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
1558     buf->st_atime = dw;
1559     RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
1560     buf->st_mtime = buf->st_ctime = dw;
1561     buf->st_nlink = hfi.nNumberOfLinks;
1562   }
1563   TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi.dwFileAttributes,
1564    buf->st_mode);
1565   return 0;
1566 }
1567
1568 /*********************************************************************
1569  *              _fstati64 (MSVCRT.@)
1570  */
1571 int CDECL MSVCRT__fstati64(int fd, struct MSVCRT__stati64* buf)
1572 {
1573   int ret;
1574   struct MSVCRT__stat64 buf64;
1575
1576   ret = MSVCRT__fstat64(fd, &buf64);
1577   if (!ret)
1578     msvcrt_stat64_to_stati64(&buf64, buf);
1579   return ret;
1580 }
1581
1582 /*********************************************************************
1583  *              _fstat (MSVCRT.@)
1584  */
1585 int CDECL MSVCRT__fstat(int fd, struct MSVCRT__stat* buf)
1586 { int ret;
1587   struct MSVCRT__stat64 buf64;
1588
1589   ret = MSVCRT__fstat64(fd, &buf64);
1590   if (!ret)
1591       msvcrt_stat64_to_stat(&buf64, buf);
1592   return ret;
1593 }
1594
1595 /*********************************************************************
1596  *              _futime64 (MSVCRT.@)
1597  */
1598 int CDECL _futime64(int fd, struct MSVCRT___utimbuf64 *t)
1599 {
1600   HANDLE hand = msvcrt_fdtoh(fd);
1601   FILETIME at, wt;
1602
1603   if (!t)
1604   {
1605       time_to_filetime( MSVCRT__time64(NULL), &at );
1606       wt = at;
1607   }
1608   else
1609   {
1610       time_to_filetime( t->actime, &at );
1611       time_to_filetime( t->modtime, &wt );
1612   }
1613
1614   if (!SetFileTime(hand, NULL, &at, &wt))
1615   {
1616     msvcrt_set_errno(GetLastError());
1617     return -1 ;
1618   }
1619   return 0;
1620 }
1621
1622 /*********************************************************************
1623  *              _futime32 (MSVCRT.@)
1624  */
1625 int CDECL _futime32(int fd, struct MSVCRT___utimbuf32 *t)
1626 {
1627     if (t)
1628     {
1629         struct MSVCRT___utimbuf64 t64;
1630         t64.actime = t->actime;
1631         t64.modtime = t->modtime;
1632         return _futime64( fd, &t64 );
1633     }
1634     else
1635         return _futime64( fd, NULL );
1636 }
1637
1638 /*********************************************************************
1639  *              _futime (MSVCRT.@)
1640  */
1641 #ifdef _WIN64
1642 int CDECL _futime(int fd, struct MSVCRT___utimbuf64 *t)
1643 {
1644     return _futime64( fd, t );
1645 }
1646 #else
1647 int CDECL _futime(int fd, struct MSVCRT___utimbuf32 *t)
1648 {
1649     return _futime32( fd, t );
1650 }
1651 #endif
1652
1653 /*********************************************************************
1654  *              _get_osfhandle (MSVCRT.@)
1655  */
1656 MSVCRT_intptr_t CDECL MSVCRT__get_osfhandle(int fd)
1657 {
1658   HANDLE hand = msvcrt_fdtoh(fd);
1659   TRACE(":fd (%d) handle (%p)\n",fd,hand);
1660
1661   return (MSVCRT_intptr_t)hand;
1662 }
1663
1664 /*********************************************************************
1665  *              _mktemp (MSVCRT.@)
1666  */
1667 char * CDECL MSVCRT__mktemp(char *pattern)
1668 {
1669   int numX = 0;
1670   char *retVal = pattern;
1671   int id;
1672   char letter = 'a';
1673
1674   while(*pattern)
1675     numX = (*pattern++ == 'X')? numX + 1 : 0;
1676   if (numX < 5)
1677     return NULL;
1678   pattern--;
1679   id = GetCurrentProcessId();
1680   numX = 6;
1681   while(numX--)
1682   {
1683     int tempNum = id / 10;
1684     *pattern-- = id - (tempNum * 10) + '0';
1685     id = tempNum;
1686   }
1687   pattern++;
1688   do
1689   {
1690     *pattern = letter++;
1691     if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES &&
1692         GetLastError() == ERROR_FILE_NOT_FOUND)
1693       return retVal;
1694   } while(letter <= 'z');
1695   return NULL;
1696 }
1697
1698 /*********************************************************************
1699  *              _wmktemp (MSVCRT.@)
1700  */
1701 MSVCRT_wchar_t * CDECL MSVCRT__wmktemp(MSVCRT_wchar_t *pattern)
1702 {
1703   int numX = 0;
1704   MSVCRT_wchar_t *retVal = pattern;
1705   int id;
1706   MSVCRT_wchar_t letter = 'a';
1707
1708   while(*pattern)
1709     numX = (*pattern++ == 'X')? numX + 1 : 0;
1710   if (numX < 5)
1711     return NULL;
1712   pattern--;
1713   id = GetCurrentProcessId();
1714   numX = 6;
1715   while(numX--)
1716   {
1717     int tempNum = id / 10;
1718     *pattern-- = id - (tempNum * 10) + '0';
1719     id = tempNum;
1720   }
1721   pattern++;
1722   do
1723   {
1724     if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES &&
1725         GetLastError() == ERROR_FILE_NOT_FOUND)
1726       return retVal;
1727     *pattern = letter++;
1728   } while(letter != '|');
1729   return NULL;
1730 }
1731
1732 static unsigned split_oflags(unsigned oflags)
1733 {
1734     int         wxflags = 0;
1735     unsigned unsupp; /* until we support everything */
1736
1737     if (oflags & MSVCRT__O_APPEND)              wxflags |= WX_APPEND;
1738     if (oflags & MSVCRT__O_BINARY)              {/* Nothing to do */}
1739     else if (oflags & MSVCRT__O_TEXT)           wxflags |= WX_TEXT;
1740     else if (oflags & MSVCRT__O_WTEXT)          wxflags |= WX_TEXT;
1741     else if (oflags & MSVCRT__O_U16TEXT)        wxflags |= WX_TEXT;
1742     else if (oflags & MSVCRT__O_U8TEXT)         wxflags |= WX_TEXT;
1743     else if (*__p__fmode() & MSVCRT__O_BINARY)  {/* Nothing to do */}
1744     else                                        wxflags |= WX_TEXT; /* default to TEXT*/
1745     if (oflags & MSVCRT__O_NOINHERIT)           wxflags |= WX_DONTINHERIT;
1746
1747     if ((unsupp = oflags & ~(
1748                     MSVCRT__O_BINARY|MSVCRT__O_TEXT|MSVCRT__O_APPEND|
1749                     MSVCRT__O_TRUNC|MSVCRT__O_EXCL|MSVCRT__O_CREAT|
1750                     MSVCRT__O_RDWR|MSVCRT__O_WRONLY|MSVCRT__O_TEMPORARY|
1751                     MSVCRT__O_NOINHERIT|
1752                     MSVCRT__O_SEQUENTIAL|MSVCRT__O_RANDOM|MSVCRT__O_SHORT_LIVED|
1753                     MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT
1754                     )))
1755         ERR(":unsupported oflags 0x%04x\n",unsupp);
1756
1757     return wxflags;
1758 }
1759
1760 /*********************************************************************
1761  *              _pipe (MSVCRT.@)
1762  */
1763 int CDECL MSVCRT__pipe(int *pfds, unsigned int psize, int textmode)
1764 {
1765   int ret = -1;
1766   SECURITY_ATTRIBUTES sa;
1767   HANDLE readHandle, writeHandle;
1768
1769   if (!pfds)
1770   {
1771     *MSVCRT__errno() = MSVCRT_EINVAL;
1772     return -1;
1773   }
1774
1775   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1776   sa.bInheritHandle = !(textmode & MSVCRT__O_NOINHERIT);
1777   sa.lpSecurityDescriptor = NULL;
1778   if (CreatePipe(&readHandle, &writeHandle, &sa, psize))
1779   {
1780     unsigned int wxflags = split_oflags(textmode);
1781     int fd;
1782
1783     LOCK_FILES();
1784     fd = msvcrt_alloc_fd(readHandle, wxflags|WX_PIPE);
1785     if (fd != -1)
1786     {
1787       pfds[0] = fd;
1788       fd = msvcrt_alloc_fd(writeHandle, wxflags|WX_PIPE);
1789       if (fd != -1)
1790       {
1791         pfds[1] = fd;
1792         ret = 0;
1793       }
1794       else
1795       {
1796         MSVCRT__close(pfds[0]);
1797         CloseHandle(writeHandle);
1798         *MSVCRT__errno() = MSVCRT_EMFILE;
1799       }
1800     }
1801     else
1802     {
1803       CloseHandle(readHandle);
1804       CloseHandle(writeHandle);
1805       *MSVCRT__errno() = MSVCRT_EMFILE;
1806     }
1807     UNLOCK_FILES();
1808   }
1809   else
1810     msvcrt_set_errno(GetLastError());
1811
1812   return ret;
1813 }
1814
1815 static int check_bom(HANDLE h, int oflags, BOOL seek)
1816 {
1817     char bom[sizeof(utf8_bom)];
1818     DWORD r;
1819
1820     oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
1821
1822     if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
1823         return oflags;
1824
1825     if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
1826         oflags |= MSVCRT__O_U8TEXT;
1827     }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
1828         if (seek && r>2)
1829             SetFilePointer(h, 2, NULL, FILE_BEGIN);
1830         oflags |= MSVCRT__O_U16TEXT;
1831     }else if (seek) {
1832         SetFilePointer(h, 0, NULL, FILE_BEGIN);
1833     }
1834
1835     return oflags;
1836 }
1837
1838 /*********************************************************************
1839  *              _wsopen_s (MSVCRT.@)
1840  */
1841 int CDECL MSVCRT__wsopen_s( int *fd, const MSVCRT_wchar_t* path, int oflags, int shflags, int pmode )
1842 {
1843   DWORD access = 0, creation = 0, attrib;
1844   SECURITY_ATTRIBUTES sa;
1845   DWORD sharing;
1846   int wxflag;
1847   HANDLE hand;
1848
1849   TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
1850         fd, debugstr_w(path), oflags, shflags, pmode);
1851
1852   if (!MSVCRT_CHECK_PMT( fd != NULL )) return MSVCRT_EINVAL;
1853
1854   *fd = -1;
1855   wxflag = split_oflags(oflags);
1856   switch (oflags & (MSVCRT__O_RDONLY | MSVCRT__O_WRONLY | MSVCRT__O_RDWR))
1857   {
1858   case MSVCRT__O_RDONLY: access |= GENERIC_READ; break;
1859   case MSVCRT__O_WRONLY: access |= GENERIC_WRITE; break;
1860   case MSVCRT__O_RDWR:   access |= GENERIC_WRITE | GENERIC_READ; break;
1861   }
1862
1863   if (oflags & MSVCRT__O_CREAT)
1864   {
1865     if(pmode & ~(MSVCRT__S_IREAD | MSVCRT__S_IWRITE))
1866       FIXME(": pmode 0x%04x ignored\n", pmode);
1867     else
1868       WARN(": pmode 0x%04x ignored\n", pmode);
1869
1870     if (oflags & MSVCRT__O_EXCL)
1871       creation = CREATE_NEW;
1872     else if (oflags & MSVCRT__O_TRUNC)
1873       creation = CREATE_ALWAYS;
1874     else
1875       creation = OPEN_ALWAYS;
1876   }
1877   else  /* no MSVCRT__O_CREAT */
1878   {
1879     if (oflags & MSVCRT__O_TRUNC)
1880       creation = TRUNCATE_EXISTING;
1881     else
1882       creation = OPEN_EXISTING;
1883   }
1884
1885   switch( shflags )
1886   {
1887     case MSVCRT__SH_DENYRW:
1888       sharing = 0L;
1889       break;
1890     case MSVCRT__SH_DENYWR:
1891       sharing = FILE_SHARE_READ;
1892       break;
1893     case MSVCRT__SH_DENYRD:
1894       sharing = FILE_SHARE_WRITE;
1895       break;
1896     case MSVCRT__SH_DENYNO:
1897       sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
1898       break;
1899     default:
1900       ERR( "Unhandled shflags 0x%x\n", shflags );
1901       return MSVCRT_EINVAL;
1902   }
1903   attrib = FILE_ATTRIBUTE_NORMAL;
1904
1905   if (oflags & MSVCRT__O_TEMPORARY)
1906   {
1907       attrib |= FILE_FLAG_DELETE_ON_CLOSE;
1908       access |= DELETE;
1909       sharing |= FILE_SHARE_DELETE;
1910   }
1911
1912   sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
1913   sa.lpSecurityDescriptor = NULL;
1914   sa.bInheritHandle       = !(oflags & MSVCRT__O_NOINHERIT);
1915
1916   if ((oflags&(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
1917           && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
1918           && !(access&GENERIC_READ))
1919   {
1920       hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1921               &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
1922       if (hand != INVALID_HANDLE_VALUE)
1923       {
1924           oflags = check_bom(hand, oflags, FALSE);
1925           CloseHandle(hand);
1926       }
1927       else
1928           oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
1929   }
1930
1931   hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
1932   if (hand == INVALID_HANDLE_VALUE)  {
1933     WARN(":failed-last error (%d)\n",GetLastError());
1934     msvcrt_set_errno(GetLastError());
1935     return *MSVCRT__errno();
1936   }
1937
1938   if (oflags & (MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
1939   {
1940       if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
1941                   || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
1942                   || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
1943       {
1944           if (oflags & MSVCRT__O_U8TEXT)
1945           {
1946               DWORD written = 0, tmp;
1947
1948               while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
1949                           sizeof(utf8_bom)-written, &tmp, NULL))
1950                   written += tmp;
1951               if (written != sizeof(utf8_bom)) {
1952                   WARN("error writing BOM\n");
1953                   CloseHandle(hand);
1954                   msvcrt_set_errno(GetLastError());
1955                   return *MSVCRT__errno();
1956               }
1957           }
1958           else
1959           {
1960               DWORD written = 0, tmp;
1961
1962               while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
1963                           sizeof(utf16_bom)-written, &tmp, NULL))
1964                   written += tmp;
1965               if (written != sizeof(utf16_bom))
1966               {
1967                   WARN("error writing BOM\n");
1968                   CloseHandle(hand);
1969                   msvcrt_set_errno(GetLastError());
1970                   return *MSVCRT__errno();
1971               }
1972           }
1973       }
1974       else if (access & GENERIC_READ)
1975           oflags = check_bom(hand, oflags, TRUE);
1976   }
1977
1978   *fd = msvcrt_alloc_fd(hand, wxflag);
1979   if (*fd == -1)
1980       return *MSVCRT__errno();
1981
1982   if (oflags & MSVCRT__O_WTEXT)
1983       msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
1984   else if (oflags & MSVCRT__O_U16TEXT)
1985       msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF16;
1986   else if (oflags & MSVCRT__O_U8TEXT)
1987       msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF8;
1988
1989   TRACE(":fd (%d) handle (%p)\n", *fd, hand);
1990   return 0;
1991 }
1992
1993 /*********************************************************************
1994  *              _wsopen (MSVCRT.@)
1995  */
1996 int CDECL MSVCRT__wsopen( const MSVCRT_wchar_t *path, int oflags, int shflags, ... )
1997 {
1998   int pmode;
1999   int fd;
2000
2001   if (oflags & MSVCRT__O_CREAT)
2002   {
2003     __ms_va_list ap;
2004
2005     __ms_va_start(ap, shflags);
2006     pmode = va_arg(ap, int);
2007     __ms_va_end(ap);
2008   }
2009   else
2010     pmode = 0;
2011
2012   MSVCRT__wsopen_s(&fd, path, oflags, shflags, pmode);
2013   return fd;
2014 }
2015
2016 /*********************************************************************
2017  *              _sopen_s (MSVCRT.@)
2018  */
2019 int CDECL MSVCRT__sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
2020 {
2021     MSVCRT_wchar_t *pathW;
2022     int ret;
2023
2024     if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path))))
2025         return MSVCRT_EINVAL;
2026
2027     ret = MSVCRT__wsopen_s(fd, pathW, oflags, shflags, pmode);
2028     MSVCRT_free(pathW);
2029     return ret;
2030 }
2031
2032 /*********************************************************************
2033  *              _sopen (MSVCRT.@)
2034  */
2035 int CDECL MSVCRT__sopen( const char *path, int oflags, int shflags, ... )
2036 {
2037   int pmode;
2038   int fd;
2039
2040   if (oflags & MSVCRT__O_CREAT)
2041   {
2042     __ms_va_list ap;
2043
2044     __ms_va_start(ap, shflags);
2045     pmode = va_arg(ap, int);
2046     __ms_va_end(ap);
2047   }
2048   else
2049     pmode = 0;
2050
2051   MSVCRT__sopen_s(&fd, path, oflags, shflags, pmode);
2052   return fd;
2053 }
2054
2055 /*********************************************************************
2056  *              _open (MSVCRT.@)
2057  */
2058 int CDECL MSVCRT__open( const char *path, int flags, ... )
2059 {
2060   __ms_va_list ap;
2061
2062   if (flags & MSVCRT__O_CREAT)
2063   {
2064     int pmode;
2065     __ms_va_start(ap, flags);
2066     pmode = va_arg(ap, int);
2067     __ms_va_end(ap);
2068     return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO, pmode );
2069   }
2070   else
2071     return MSVCRT__sopen( path, flags, MSVCRT__SH_DENYNO);
2072 }
2073
2074 /*********************************************************************
2075  *              _wopen (MSVCRT.@)
2076  */
2077 int CDECL MSVCRT__wopen(const MSVCRT_wchar_t *path,int flags,...)
2078 {
2079   __ms_va_list ap;
2080
2081   if (flags & MSVCRT__O_CREAT)
2082   {
2083     int pmode;
2084     __ms_va_start(ap, flags);
2085     pmode = va_arg(ap, int);
2086     __ms_va_end(ap);
2087     return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO, pmode );
2088   }
2089   else
2090     return MSVCRT__wsopen( path, flags, MSVCRT__SH_DENYNO);
2091 }
2092
2093 /*********************************************************************
2094  *              _creat (MSVCRT.@)
2095  */
2096 int CDECL MSVCRT__creat(const char *path, int flags)
2097 {
2098   int usedFlags = (flags & MSVCRT__O_TEXT)| MSVCRT__O_CREAT| MSVCRT__O_WRONLY| MSVCRT__O_TRUNC;
2099   return MSVCRT__open(path, usedFlags);
2100 }
2101
2102 /*********************************************************************
2103  *              _wcreat (MSVCRT.@)
2104  */
2105 int CDECL MSVCRT__wcreat(const MSVCRT_wchar_t *path, int flags)
2106 {
2107   int usedFlags = (flags & MSVCRT__O_TEXT)| MSVCRT__O_CREAT| MSVCRT__O_WRONLY| MSVCRT__O_TRUNC;
2108   return MSVCRT__wopen(path, usedFlags);
2109 }
2110
2111 /*********************************************************************
2112  *              _open_osfhandle (MSVCRT.@)
2113  */
2114 int CDECL MSVCRT__open_osfhandle(MSVCRT_intptr_t handle, int oflags)
2115 {
2116   int fd;
2117
2118   /* MSVCRT__O_RDONLY (0) always matches, so set the read flag
2119    * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
2120    * file, so set the write flag. It also only sets MSVCRT__O_TEXT if it wants
2121    * text - it never sets MSVCRT__O_BINARY.
2122    */
2123   /* don't let split_oflags() decide the mode if no mode is passed */
2124   if (!(oflags & (MSVCRT__O_BINARY | MSVCRT__O_TEXT)))
2125       oflags |= MSVCRT__O_BINARY;
2126
2127   fd = msvcrt_alloc_fd((HANDLE)handle, split_oflags(oflags));
2128   TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags);
2129   return fd;
2130 }
2131
2132 /*********************************************************************
2133  *              _rmtmp (MSVCRT.@)
2134  */
2135 int CDECL MSVCRT__rmtmp(void)
2136 {
2137   int num_removed = 0, i;
2138   MSVCRT_FILE *file;
2139
2140   LOCK_FILES();
2141   for (i = 3; i < MSVCRT_stream_idx; i++) {
2142     file = msvcrt_get_file(i);
2143
2144     if (file->_tmpfname)
2145     {
2146       MSVCRT_fclose(file);
2147       num_removed++;
2148     }
2149   }
2150   UNLOCK_FILES();
2151
2152   if (num_removed)
2153     TRACE(":removed (%d) temp files\n",num_removed);
2154   return num_removed;
2155 }
2156
2157 static inline int get_utf8_char_len(char ch)
2158 {
2159     if((ch&0xf8) == 0xf0)
2160         return 4;
2161     else if((ch&0xf0) == 0xe0)
2162         return 3;
2163     else if((ch&0xe0) == 0xc0)
2164         return 2;
2165     return 1;
2166 }
2167
2168 /*********************************************************************
2169  * (internal) read_utf8
2170  */
2171 static int read_utf8(int fd, MSVCRT_wchar_t *buf, unsigned int count)
2172 {
2173     ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
2174     HANDLE hand = fdinfo->handle;
2175     char min_buf[4], *readbuf, lookahead;
2176     DWORD readbuf_size, pos=0, num_read=1, char_len, i, j;
2177
2178     /* make the buffer big enough to hold at least one character */
2179     /* read bytes have to fit to output and lookahead buffers */
2180     count /= 2;
2181     readbuf_size = count < 4 ? 4 : count;
2182     if(readbuf_size<=4 || !(readbuf = MSVCRT_malloc(readbuf_size))) {
2183         readbuf_size = 4;
2184         readbuf = min_buf;
2185     }
2186
2187     if(fdinfo->lookahead[0] != '\n') {
2188         readbuf[pos++] = fdinfo->lookahead[0];
2189         fdinfo->lookahead[0] = '\n';
2190
2191         if(fdinfo->lookahead[1] != '\n') {
2192             readbuf[pos++] = fdinfo->lookahead[1];
2193             fdinfo->lookahead[1] = '\n';
2194
2195             if(fdinfo->lookahead[2] != '\n') {
2196                 readbuf[pos++] = fdinfo->lookahead[2];
2197                 fdinfo->lookahead[2] = '\n';
2198             }
2199         }
2200     }
2201
2202     /* NOTE: this case is broken in native dll, reading
2203      *        sometimes fails when small buffer is passed
2204      */
2205     if(count < 4) {
2206         if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) {
2207             if (GetLastError() == ERROR_BROKEN_PIPE) {
2208                 fdinfo->wxflag |= WX_ATEOF;
2209                 return 0;
2210             }else {
2211                 msvcrt_set_errno(GetLastError());
2212                 return -1;
2213             }
2214         }else if(!num_read) {
2215             fdinfo->wxflag |= WX_ATEOF;
2216             return 0;
2217         }else {
2218             pos++;
2219         }
2220
2221         char_len = get_utf8_char_len(readbuf[0]);
2222         if(char_len>pos) {
2223             if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL))
2224                 pos += num_read;
2225         }
2226
2227         if(readbuf[0] == '\n')
2228             fdinfo->wxflag |= WX_READNL;
2229         else
2230             fdinfo->wxflag &= ~WX_READNL;
2231
2232         if(readbuf[0] == 0x1a) {
2233             fdinfo->wxflag |= WX_ATEOF;
2234             return 0;
2235         }
2236
2237         if(readbuf[0] == '\r') {
2238             if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1)
2239                 buf[0] = '\r';
2240             else if(lookahead == '\n')
2241                 buf[0] = '\n';
2242             else {
2243                 buf[0] = '\r';
2244                 if(fdinfo->wxflag & WX_PIPE)
2245                     fdinfo->lookahead[0] = lookahead;
2246                 else
2247                     SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2248             }
2249             return 2;
2250         }
2251
2252         if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2253             msvcrt_set_errno(GetLastError());
2254             return -1;
2255         }
2256
2257         return num_read*2;
2258     }
2259
2260     if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) {
2261         if(pos) {
2262             num_read = 0;
2263         }else if(GetLastError() == ERROR_BROKEN_PIPE) {
2264             fdinfo->wxflag |= WX_ATEOF;
2265             if (readbuf != min_buf) MSVCRT_free(readbuf);
2266             return 0;
2267         }else {
2268             msvcrt_set_errno(GetLastError());
2269             if (readbuf != min_buf) MSVCRT_free(readbuf);
2270             return -1;
2271         }
2272     }else if(!pos && !num_read) {
2273         fdinfo->wxflag |= WX_ATEOF;
2274         if (readbuf != min_buf) MSVCRT_free(readbuf);
2275         return 0;
2276     }
2277
2278     pos += num_read;
2279     if(readbuf[0] == '\n')
2280         fdinfo->wxflag |= WX_READNL;
2281     else
2282         fdinfo->wxflag &= ~WX_READNL;
2283
2284     /* Find first byte of last character (may be incomplete) */
2285     for(i=pos-1; i>0 && i>pos-4; i--)
2286         if((readbuf[i]&0xc0) != 0x80)
2287             break;
2288     char_len = get_utf8_char_len(readbuf[i]);
2289     if(char_len+i <= pos)
2290         i += char_len;
2291
2292     if(fdinfo->wxflag & WX_PIPE) {
2293         if(i < pos)
2294             fdinfo->lookahead[0] = readbuf[i];
2295         if(i+1 < pos)
2296             fdinfo->lookahead[1] = readbuf[i+1];
2297         if(i+2 < pos)
2298             fdinfo->lookahead[2] = readbuf[i+2];
2299     }else if(i < pos) {
2300         SetFilePointer(fdinfo->handle, i-pos, NULL, FILE_CURRENT);
2301     }
2302     pos = i;
2303
2304     for(i=0, j=0; i<pos; i++) {
2305         if(readbuf[i] == 0x1a) {
2306             fdinfo->wxflag |= WX_ATEOF;
2307             break;
2308         }
2309
2310         /* strip '\r' if followed by '\n' */
2311         if(readbuf[i] == '\r' && i+1==pos) {
2312             if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) {
2313                 readbuf[j++] = '\r';
2314             }else if(lookahead == '\n' && j==0) {
2315                 readbuf[j++] = '\n';
2316             }else {
2317                 if(lookahead != '\n')
2318                     readbuf[j++] = '\r';
2319
2320                 if(fdinfo->wxflag & WX_PIPE)
2321                     fdinfo->lookahead[0] = lookahead;
2322                 else
2323                     SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2324             }
2325         }else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') {
2326             readbuf[j++] = readbuf[i];
2327         }
2328     }
2329     pos = j;
2330
2331     if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2332         msvcrt_set_errno(GetLastError());
2333         if (readbuf != min_buf) MSVCRT_free(readbuf);
2334         return -1;
2335     }
2336
2337     if (readbuf != min_buf) MSVCRT_free(readbuf);
2338     return num_read*2;
2339 }
2340
2341 /*********************************************************************
2342  * (internal) read_i
2343  *
2344  * When reading \r as last character in text mode, read() positions
2345  * the file pointer on the \r character while getc() goes on to
2346  * the following \n
2347  */
2348 static int read_i(int fd, void *buf, unsigned int count)
2349 {
2350     DWORD num_read, utf16;
2351     char *bufstart = buf;
2352     HANDLE hand = msvcrt_fdtoh(fd);
2353     ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
2354
2355     if (count == 0)
2356         return 0;
2357
2358     if (fdinfo->wxflag & WX_ATEOF) {
2359         TRACE("already at EOF, returning 0\n");
2360         return 0;
2361     }
2362     /* Don't trace small reads, it gets *very* annoying */
2363     if (count > 4)
2364         TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
2365     if (hand == INVALID_HANDLE_VALUE)
2366     {
2367         *MSVCRT__errno() = MSVCRT_EBADF;
2368         return -1;
2369     }
2370
2371     utf16 = (fdinfo->exflag & EF_UTF16) != 0;
2372     if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
2373     {
2374         *MSVCRT__errno() = MSVCRT_EINVAL;
2375         return -1;
2376     }
2377
2378     if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
2379         return read_utf8(fd, buf, count);
2380
2381     if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
2382     {
2383         if (fdinfo->lookahead[0] != '\n')
2384         {
2385             bufstart[0] = fdinfo->lookahead[0];
2386             fdinfo->lookahead[0] = '\n';
2387
2388             if (utf16)
2389             {
2390                 bufstart[1] =  fdinfo->lookahead[1];
2391                 fdinfo->lookahead[1] = '\n';
2392             }
2393
2394             if(count>1+utf16 && ReadFile(hand, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
2395                 num_read += 1+utf16;
2396             else
2397                 num_read = 1+utf16;
2398         }
2399
2400         if(utf16 && (num_read&1))
2401         {
2402             /* msvcr90 uses uninitialized value from the buffer in this case */
2403             /* msvcrt ignores additional data */
2404             ERR("got odd number of bytes in UTF16 mode\n");
2405             num_read--;
2406         }
2407
2408         if (count != 0 && num_read == 0)
2409         {
2410             fdinfo->wxflag |= WX_ATEOF;
2411             TRACE(":EOF %s\n",debugstr_an(buf,num_read));
2412         }
2413         else if (fdinfo->wxflag & WX_TEXT)
2414         {
2415             DWORD i, j;
2416
2417             if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
2418                 fdinfo->wxflag |= WX_READNL;
2419             else
2420                 fdinfo->wxflag &= ~WX_READNL;
2421
2422             for (i=0, j=0; i<num_read; i+=1+utf16)
2423             {
2424                 /* in text mode, a ctrl-z signals EOF */
2425                 if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
2426                 {
2427                     fdinfo->wxflag |= WX_ATEOF;
2428                     TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
2429                     break;
2430                 }
2431
2432                 /* in text mode, strip \r if followed by \n */
2433                 if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
2434                 {
2435                     char lookahead[2];
2436                     DWORD len;
2437
2438                     lookahead[1] = '\n';
2439                     if (ReadFile(hand, lookahead, 1+utf16, &len, NULL) && len)
2440                     {
2441                         if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
2442                         {
2443                             bufstart[j++] = '\n';
2444                             if(utf16) bufstart[j++] = 0;
2445                         }
2446                         else
2447                         {
2448                             if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
2449                             {
2450                                 bufstart[j++] = '\r';
2451                                 if(utf16) bufstart[j++] = 0;
2452                             }
2453
2454                             if (fdinfo->wxflag & WX_PIPE)
2455                             {
2456                                 fdinfo->lookahead[0] = lookahead[0];
2457                                 fdinfo->lookahead[1] = lookahead[1];
2458                             }
2459                             else
2460                                 SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
2461                         }
2462                     }
2463                     else
2464                     {
2465                         bufstart[j++] = '\r';
2466                         if(utf16) bufstart[j++] = 0;
2467                     }
2468                 }
2469                 else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
2470                         || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
2471                 {
2472                     bufstart[j++] = bufstart[i];
2473                     if(utf16) bufstart[j++] = bufstart[i+1];
2474                 }
2475             }
2476             num_read = j;
2477         }
2478     }
2479     else
2480     {
2481         if (GetLastError() == ERROR_BROKEN_PIPE)
2482         {
2483             TRACE(":end-of-pipe\n");
2484             fdinfo->wxflag |= WX_ATEOF;
2485             return 0;
2486         }
2487         else
2488         {
2489             TRACE(":failed-last error (%d)\n",GetLastError());
2490             return -1;
2491         }
2492     }
2493
2494     if (count > 4)
2495         TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
2496     return num_read;
2497 }
2498
2499 /*********************************************************************
2500  *              _read (MSVCRT.@)
2501  */
2502 int CDECL MSVCRT__read(int fd, void *buf, unsigned int count)
2503 {
2504   int num_read;
2505   num_read = read_i(fd, buf, count);
2506   return num_read;
2507 }
2508
2509 /*********************************************************************
2510  *              _setmode (MSVCRT.@)
2511  */
2512 int CDECL MSVCRT__setmode(int fd,int mode)
2513 {
2514     int ret = msvcrt_get_ioinfo(fd)->wxflag & WX_TEXT ? MSVCRT__O_TEXT : MSVCRT__O_BINARY;
2515     if(ret==MSVCRT__O_TEXT && (msvcrt_get_ioinfo(fd)->exflag & (EF_UTF8|EF_UTF16)))
2516         ret = MSVCRT__O_WTEXT;
2517
2518     if(mode!=MSVCRT__O_TEXT && mode!=MSVCRT__O_BINARY && mode!=MSVCRT__O_WTEXT
2519                 && mode!=MSVCRT__O_U16TEXT && mode!=MSVCRT__O_U8TEXT) {
2520         *MSVCRT__errno() = MSVCRT_EINVAL;
2521         return -1;
2522     }
2523
2524     if(mode == MSVCRT__O_BINARY) {
2525         msvcrt_get_ioinfo(fd)->wxflag &= ~WX_TEXT;
2526         msvcrt_get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
2527         return ret;
2528     }
2529
2530     msvcrt_get_ioinfo(fd)->wxflag |= WX_TEXT;
2531     if(mode == MSVCRT__O_TEXT)
2532         msvcrt_get_ioinfo(fd)->exflag &= ~(EF_UTF8|EF_UTF16);
2533     else if(mode == MSVCRT__O_U8TEXT)
2534         msvcrt_get_ioinfo(fd)->exflag = (msvcrt_get_ioinfo(fd)->exflag & ~EF_UTF16) | EF_UTF8;
2535     else
2536         msvcrt_get_ioinfo(fd)->exflag = (msvcrt_get_ioinfo(fd)->exflag & ~EF_UTF8) | EF_UTF16;
2537
2538     return ret;
2539 }
2540
2541 /*********************************************************************
2542  *              _stat64 (MSVCRT.@)
2543  */
2544 int CDECL MSVCRT_stat64(const char* path, struct MSVCRT__stat64 * buf)
2545 {
2546   DWORD dw;
2547   WIN32_FILE_ATTRIBUTE_DATA hfi;
2548   unsigned short mode = ALL_S_IREAD;
2549   int plen;
2550
2551   TRACE(":file (%s) buf(%p)\n",path,buf);
2552
2553   plen = strlen(path);
2554   while (plen && path[plen-1]==' ')
2555     plen--;
2556
2557   if (plen && (path[plen-1]=='\\' || path[plen-1]=='/'))
2558   {
2559     *MSVCRT__errno() = MSVCRT_ENOENT;
2560     return -1;
2561   }
2562
2563   if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi))
2564   {
2565       TRACE("failed (%d)\n",GetLastError());
2566       *MSVCRT__errno() = MSVCRT_ENOENT;
2567       return -1;
2568   }
2569
2570   memset(buf,0,sizeof(struct MSVCRT__stat64));
2571
2572   /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
2573      Bon 011120: This FIXME seems incorrect
2574                  Also a letter as first char isn't enough to be classified
2575                  as a drive letter
2576   */
2577   if (isalpha(*path)&& (*(path+1)==':'))
2578     buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */
2579   else
2580     buf->st_dev = buf->st_rdev = MSVCRT__getdrive() - 1;
2581
2582   /* Dir, or regular file? */
2583   if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2584     mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
2585   else
2586   {
2587     mode |= MSVCRT__S_IFREG;
2588     /* executable? */
2589     if (plen > 6 && path[plen-4] == '.')  /* shortest exe: "\x.exe" */
2590     {
2591       unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) |
2592                                  (tolower(path[plen-3]) << 16);
2593       if (ext == EXE || ext == BAT || ext == CMD || ext == COM)
2594           mode |= ALL_S_IEXEC;
2595     }
2596   }
2597
2598   if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
2599     mode |= ALL_S_IWRITE;
2600
2601   buf->st_mode  = mode;
2602   buf->st_nlink = 1;
2603   buf->st_size  = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
2604   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
2605   buf->st_atime = dw;
2606   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
2607   buf->st_mtime = buf->st_ctime = dw;
2608   TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
2609         (int)(buf->st_size >> 32),(int)buf->st_size,
2610         (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
2611   return 0;
2612 }
2613
2614 /*********************************************************************
2615  *              _stati64 (MSVCRT.@)
2616  */
2617 int CDECL MSVCRT_stati64(const char* path, struct MSVCRT__stati64 * buf)
2618 {
2619   int ret;
2620   struct MSVCRT__stat64 buf64;
2621
2622   ret = MSVCRT_stat64(path, &buf64);
2623   if (!ret)
2624     msvcrt_stat64_to_stati64(&buf64, buf);
2625   return ret;
2626 }
2627
2628 /*********************************************************************
2629  *              _stat (MSVCRT.@)
2630  */
2631 int CDECL MSVCRT_stat(const char* path, struct MSVCRT__stat * buf)
2632 { int ret;
2633   struct MSVCRT__stat64 buf64;
2634
2635   ret = MSVCRT_stat64( path, &buf64);
2636   if (!ret)
2637       msvcrt_stat64_to_stat(&buf64, buf);
2638   return ret;
2639 }
2640
2641 /*********************************************************************
2642  *              _wstat64 (MSVCRT.@)
2643  */
2644 int CDECL MSVCRT__wstat64(const MSVCRT_wchar_t* path, struct MSVCRT__stat64 * buf)
2645 {
2646   DWORD dw;
2647   WIN32_FILE_ATTRIBUTE_DATA hfi;
2648   unsigned short mode = ALL_S_IREAD;
2649   int plen;
2650
2651   TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf);
2652
2653   plen = strlenW(path);
2654   while (plen && path[plen-1]==' ')
2655     plen--;
2656
2657   if(plen && (path[plen-1]=='\\' || path[plen-1]=='/'))
2658   {
2659     *MSVCRT__errno() = MSVCRT_ENOENT;
2660     return -1;
2661   }
2662
2663   if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi))
2664   {
2665       TRACE("failed (%d)\n",GetLastError());
2666       *MSVCRT__errno() = MSVCRT_ENOENT;
2667       return -1;
2668   }
2669
2670   memset(buf,0,sizeof(struct MSVCRT__stat64));
2671
2672   /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
2673   if (MSVCRT_iswalpha(*path))
2674     buf->st_dev = buf->st_rdev = toupperW(*path - 'A'); /* drive num */
2675   else
2676     buf->st_dev = buf->st_rdev = MSVCRT__getdrive() - 1;
2677
2678   /* Dir, or regular file? */
2679   if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2680     mode |= (MSVCRT__S_IFDIR | ALL_S_IEXEC);
2681   else
2682   {
2683     mode |= MSVCRT__S_IFREG;
2684     /* executable? */
2685     if (plen > 6 && path[plen-4] == '.')  /* shortest exe: "\x.exe" */
2686     {
2687       ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) |
2688                                ((ULONGLONG)tolowerW(path[plen-3]) << 32);
2689       if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM)
2690         mode |= ALL_S_IEXEC;
2691     }
2692   }
2693
2694   if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
2695     mode |= ALL_S_IWRITE;
2696
2697   buf->st_mode  = mode;
2698   buf->st_nlink = 1;
2699   buf->st_size  = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow;
2700   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw);
2701   buf->st_atime = dw;
2702   RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw);
2703   buf->st_mtime = buf->st_ctime = dw;
2704   TRACE("%d %d 0x%08x%08x %d %d %d\n", buf->st_mode,buf->st_nlink,
2705         (int)(buf->st_size >> 32),(int)buf->st_size,
2706         (int)buf->st_atime,(int)buf->st_mtime,(int)buf->st_ctime);
2707   return 0;
2708 }
2709
2710 /*********************************************************************
2711  *              _wstati64 (MSVCRT.@)
2712  */
2713 int CDECL MSVCRT__wstati64(const MSVCRT_wchar_t* path, struct MSVCRT__stati64 * buf)
2714 {
2715   int ret;
2716   struct MSVCRT__stat64 buf64;
2717
2718   ret = MSVCRT__wstat64(path, &buf64);
2719   if (!ret)
2720     msvcrt_stat64_to_stati64(&buf64, buf);
2721   return ret;
2722 }
2723
2724 /*********************************************************************
2725  *              _wstat (MSVCRT.@)
2726  */
2727 int CDECL MSVCRT__wstat(const MSVCRT_wchar_t* path, struct MSVCRT__stat * buf)
2728 {
2729   int ret;
2730   struct MSVCRT__stat64 buf64;
2731
2732   ret = MSVCRT__wstat64( path, &buf64 );
2733   if (!ret) msvcrt_stat64_to_stat(&buf64, buf);
2734   return ret;
2735 }
2736
2737 /*********************************************************************
2738  *              _tell (MSVCRT.@)
2739  */
2740 MSVCRT_long CDECL MSVCRT__tell(int fd)
2741 {
2742   return MSVCRT__lseek(fd, 0, SEEK_CUR);
2743 }
2744
2745 /*********************************************************************
2746  *              _telli64 (MSVCRT.@)
2747  */
2748 __int64 CDECL _telli64(int fd)
2749 {
2750   return MSVCRT__lseeki64(fd, 0, SEEK_CUR);
2751 }
2752
2753 /*********************************************************************
2754  *              _tempnam (MSVCRT.@)
2755  */
2756 char * CDECL MSVCRT__tempnam(const char *dir, const char *prefix)
2757 {
2758   char tmpbuf[MAX_PATH];
2759   const char *tmp_dir = MSVCRT_getenv("TMP");
2760
2761   if (tmp_dir) dir = tmp_dir;
2762
2763   TRACE("dir (%s) prefix (%s)\n",dir,prefix);
2764   if (GetTempFileNameA(dir,prefix,0,tmpbuf))
2765   {
2766     TRACE("got name (%s)\n",tmpbuf);
2767     DeleteFileA(tmpbuf);
2768     return MSVCRT__strdup(tmpbuf);
2769   }
2770   TRACE("failed (%d)\n",GetLastError());
2771   return NULL;
2772 }
2773
2774 /*********************************************************************
2775  *              _wtempnam (MSVCRT.@)
2776  */
2777 MSVCRT_wchar_t * CDECL MSVCRT__wtempnam(const MSVCRT_wchar_t *dir, const MSVCRT_wchar_t *prefix)
2778 {
2779   static const MSVCRT_wchar_t tmpW[] = {'T','M','P',0};
2780   MSVCRT_wchar_t tmpbuf[MAX_PATH];
2781   const MSVCRT_wchar_t *tmp_dir = MSVCRT__wgetenv(tmpW);
2782
2783   if (tmp_dir) dir = tmp_dir;
2784
2785   TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
2786   if (GetTempFileNameW(dir,prefix,0,tmpbuf))
2787   {
2788     TRACE("got name (%s)\n",debugstr_w(tmpbuf));
2789     DeleteFileW(tmpbuf);
2790     return MSVCRT__wcsdup(tmpbuf);
2791   }
2792   TRACE("failed (%d)\n",GetLastError());
2793   return NULL;
2794 }
2795
2796 /*********************************************************************
2797  *              _umask (MSVCRT.@)
2798  */
2799 int CDECL MSVCRT__umask(int umask)
2800 {
2801   int old_umask = MSVCRT_umask;
2802   TRACE("(%d)\n",umask);
2803   MSVCRT_umask = umask;
2804   return old_umask;
2805 }
2806
2807 /*********************************************************************
2808  *              _utime64 (MSVCRT.@)
2809  */
2810 int CDECL _utime64(const char* path, struct MSVCRT___utimbuf64 *t)
2811 {
2812   int fd = MSVCRT__open(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
2813
2814   if (fd > 0)
2815   {
2816     int retVal = _futime64(fd, t);
2817     MSVCRT__close(fd);
2818     return retVal;
2819   }
2820   return -1;
2821 }
2822
2823 /*********************************************************************
2824  *              _utime32 (MSVCRT.@)
2825  */
2826 int CDECL _utime32(const char* path, struct MSVCRT___utimbuf32 *t)
2827 {
2828     if (t)
2829     {
2830         struct MSVCRT___utimbuf64 t64;
2831         t64.actime = t->actime;
2832         t64.modtime = t->modtime;
2833         return _utime64( path, &t64 );
2834     }
2835     else
2836         return _utime64( path, NULL );
2837 }
2838
2839 /*********************************************************************
2840  *              _utime (MSVCRT.@)
2841  */
2842 #ifdef _WIN64
2843 int CDECL _utime(const char* path, struct MSVCRT___utimbuf64 *t)
2844 {
2845     return _utime64( path, t );
2846 }
2847 #else
2848 int CDECL _utime(const char* path, struct MSVCRT___utimbuf32 *t)
2849 {
2850     return _utime32( path, t );
2851 }
2852 #endif
2853
2854 /*********************************************************************
2855  *              _wutime64 (MSVCRT.@)
2856  */
2857 int CDECL _wutime64(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
2858 {
2859   int fd = MSVCRT__wopen(path, MSVCRT__O_WRONLY | MSVCRT__O_BINARY);
2860
2861   if (fd > 0)
2862   {
2863     int retVal = _futime64(fd, t);
2864     MSVCRT__close(fd);
2865     return retVal;
2866   }
2867   return -1;
2868 }
2869
2870 /*********************************************************************
2871  *              _wutime32 (MSVCRT.@)
2872  */
2873 int CDECL _wutime32(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
2874 {
2875     if (t)
2876     {
2877         struct MSVCRT___utimbuf64 t64;
2878         t64.actime = t->actime;
2879         t64.modtime = t->modtime;
2880         return _wutime64( path, &t64 );
2881     }
2882     else
2883         return _wutime64( path, NULL );
2884 }
2885
2886 /*********************************************************************
2887  *              _wutime (MSVCRT.@)
2888  */
2889 #ifdef _WIN64
2890 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf64 *t)
2891 {
2892     return _wutime64( path, t );
2893 }
2894 #else
2895 int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t)
2896 {
2897     return _wutime32( path, t );
2898 }
2899 #endif
2900
2901 /*********************************************************************
2902  *              _write (MSVCRT.@)
2903  */
2904 int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count)
2905 {
2906     DWORD num_written;
2907     ioinfo *info = msvcrt_get_ioinfo(fd);
2908     HANDLE hand = info->handle;
2909
2910     /* Don't trace small writes, it gets *very* annoying */
2911 #if 0
2912     if (count > 32)
2913         TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
2914 #endif
2915     if (hand == INVALID_HANDLE_VALUE)
2916     {
2917         *MSVCRT__errno() = MSVCRT_EBADF;
2918         return -1;
2919     }
2920
2921     if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
2922     {
2923         *MSVCRT__errno() = MSVCRT_EINVAL;
2924         return -1;
2925     }
2926
2927     /* If appending, go to EOF */
2928     if (info->wxflag & WX_APPEND)
2929         MSVCRT__lseek(fd, 0, FILE_END);
2930
2931     if (!(info->wxflag & WX_TEXT))
2932     {
2933         if (WriteFile(hand, buf, count, &num_written, NULL)
2934                 &&  (num_written == count))
2935             return num_written;
2936         TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
2937                 hand, GetLastError());
2938         *MSVCRT__errno() = MSVCRT_ENOSPC;
2939     }
2940     else
2941     {
2942         unsigned int i, j, nr_lf, size;
2943         char *p = NULL;
2944         const char *q;
2945         const char *s = buf, *buf_start = buf;
2946
2947         if (!(info->exflag & (EF_UTF8|EF_UTF16)))
2948         {
2949             /* find number of \n */
2950             for (nr_lf=0, i=0; i<count; i++)
2951                 if (s[i] == '\n')
2952                     nr_lf++;
2953             if (nr_lf)
2954             {
2955                 size = count+nr_lf;
2956                 if ((q = p = MSVCRT_malloc(size)))
2957                 {
2958                     for (s = buf, i = 0, j = 0; i < count; i++)
2959                     {
2960                         if (s[i] == '\n')
2961                             p[j++] = '\r';
2962                         p[j++] = s[i];
2963                     }
2964                 }
2965                 else
2966                 {
2967                     FIXME("Malloc failed\n");
2968                     nr_lf = 0;
2969                     size = count;
2970                     q = buf;
2971                 }
2972             }
2973             else
2974             {
2975                 size = count;
2976                 q = buf;
2977             }
2978         }
2979         else if (info->exflag & EF_UTF16)
2980         {
2981             for (nr_lf=0, i=0; i<count; i+=2)
2982                 if (s[i]=='\n' && s[i+1]==0)
2983                     nr_lf += 2;
2984             if (nr_lf)
2985             {
2986                 size = count+nr_lf;
2987                 if ((q = p = MSVCRT_malloc(size)))
2988                 {
2989                     for (s=buf, i=0, j=0; i<count; i++)
2990                     {
2991                         if (s[i]=='\n' && s[i+1]==0)
2992                         {
2993                             p[j++] = '\r';
2994                             p[j++] = 0;
2995                         }
2996                         p[j++] = s[i++];
2997                         p[j++] = s[i];
2998                     }
2999                 }
3000                 else
3001                 {
3002                     FIXME("Malloc failed\n");
3003                     nr_lf = 0;
3004                     size = count;
3005                     q = buf;
3006                 }
3007             }
3008             else
3009             {
3010                 size = count;
3011                 q = buf;
3012             }
3013         }
3014         else
3015         {
3016             DWORD conv_len;
3017
3018             for(nr_lf=0, i=0; i<count; i+=2)
3019                 if (s[i]=='\n' && s[i+1]==0)
3020                     nr_lf++;
3021
3022             conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
3023             if(!conv_len) {
3024                 msvcrt_set_errno(GetLastError());
3025                 MSVCRT_free(p);
3026                 return -1;
3027             }
3028
3029             size = conv_len+nr_lf;
3030             if((p = MSVCRT_malloc(count+nr_lf*2+size)))
3031             {
3032                 for (s=buf, i=0, j=0; i<count; i++)
3033                 {
3034                     if (s[i]=='\n' && s[i+1]==0)
3035                     {
3036                         p[j++] = '\r';
3037                         p[j++] = 0;
3038                     }
3039                     p[j++] = s[i++];
3040                     p[j++] = s[i];
3041                 }
3042                 q = p+count+nr_lf*2;
3043                 WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
3044                         p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
3045             }
3046             else
3047             {
3048                 FIXME("Malloc failed\n");
3049                 nr_lf = 0;
3050                 size = count;
3051                 q = buf;
3052             }
3053         }
3054
3055         if (!WriteFile(hand, q, size, &num_written, NULL))
3056             num_written = -1;
3057         if(p)
3058             MSVCRT_free(p);
3059         if (num_written != size)
3060         {
3061             TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
3062                     fd, hand, GetLastError(), num_written);
3063             *MSVCRT__errno() = MSVCRT_ENOSPC;
3064             return s - buf_start;
3065         }
3066         return count;
3067     }
3068
3069     return -1;
3070 }
3071
3072 /*********************************************************************
3073  *              _putw (MSVCRT.@)
3074  */
3075 int CDECL MSVCRT__putw(int val, MSVCRT_FILE* file)
3076 {
3077   int len;
3078
3079   MSVCRT__lock_file(file);
3080   len = MSVCRT__write(file->_file, &val, sizeof(val));
3081   if (len == sizeof(val)) {
3082     MSVCRT__unlock_file(file);
3083     return val;
3084   }
3085
3086   file->_flag |= MSVCRT__IOERR;
3087   MSVCRT__unlock_file(file);
3088   return MSVCRT_EOF;
3089 }
3090
3091 /*********************************************************************
3092  *              fclose (MSVCRT.@)
3093  */
3094 int CDECL MSVCRT_fclose(MSVCRT_FILE* file)
3095 {
3096   int r, flag;
3097
3098   MSVCRT__lock_file(file);
3099   flag = file->_flag;
3100   MSVCRT_free(file->_tmpfname);
3101   file->_tmpfname = NULL;
3102   /* flush stdio buffers */
3103   if(file->_flag & MSVCRT__IOWRT)
3104       MSVCRT_fflush(file);
3105   if(file->_flag & MSVCRT__IOMYBUF)
3106       MSVCRT_free(file->_base);
3107
3108   r=MSVCRT__close(file->_file);
3109
3110   file->_flag = 0;
3111   MSVCRT__unlock_file(file);
3112
3113   return ((r == -1) || (flag & MSVCRT__IOERR) ? MSVCRT_EOF : 0);
3114 }
3115
3116 /*********************************************************************
3117  *              feof (MSVCRT.@)
3118  */
3119 int CDECL MSVCRT_feof(MSVCRT_FILE* file)
3120 {
3121     return file->_flag & MSVCRT__IOEOF;
3122 }
3123
3124 /*********************************************************************
3125  *              ferror (MSVCRT.@)
3126  */
3127 int CDECL MSVCRT_ferror(MSVCRT_FILE* file)
3128 {
3129     return file->_flag & MSVCRT__IOERR;
3130 }
3131
3132 /*********************************************************************
3133  *              _filbuf (MSVCRT.@)
3134  */
3135 int CDECL MSVCRT__filbuf(MSVCRT_FILE* file)
3136 {
3137     unsigned char c;
3138     MSVCRT__lock_file(file);
3139
3140     /* Allocate buffer if needed */
3141     if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF))
3142         msvcrt_alloc_buffer(file);
3143
3144     if(!(file->_flag & MSVCRT__IOREAD)) {
3145         if(file->_flag & MSVCRT__IORW)
3146             file->_flag |= MSVCRT__IOREAD;
3147         else {
3148             MSVCRT__unlock_file(file);
3149             return MSVCRT_EOF;
3150         }
3151     }
3152
3153     if(file->_flag & MSVCRT__IONBF) {
3154         int r;
3155         if ((r = read_i(file->_file,&c,1)) != 1) {
3156             file->_flag |= (r == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
3157             MSVCRT__unlock_file(file);
3158             return MSVCRT_EOF;
3159         }
3160
3161         MSVCRT__unlock_file(file);
3162         return c;
3163     } else {
3164         file->_cnt = read_i(file->_file, file->_base, file->_bufsiz);
3165         if(file->_cnt<=0) {
3166             file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
3167             file->_cnt = 0;
3168             MSVCRT__unlock_file(file);
3169             return MSVCRT_EOF;
3170         }
3171
3172         file->_cnt--;
3173         file->_ptr = file->_base+1;
3174         c = *(unsigned char *)file->_base;
3175         MSVCRT__unlock_file(file);
3176         return c;
3177     }
3178 }
3179
3180 /*********************************************************************
3181  *              fgetc (MSVCRT.@)
3182  */
3183 int CDECL MSVCRT_fgetc(MSVCRT_FILE* file)
3184 {
3185   unsigned char *i;
3186   unsigned int j;
3187
3188   MSVCRT__lock_file(file);
3189   if (file->_cnt>0) {
3190     file->_cnt--;
3191     i = (unsigned char *)file->_ptr++;
3192     j = *i;
3193   } else
3194     j = MSVCRT__filbuf(file);
3195
3196   MSVCRT__unlock_file(file);
3197   return j;
3198 }
3199
3200 /*********************************************************************
3201  *              _fgetchar (MSVCRT.@)
3202  */
3203 int CDECL MSVCRT__fgetchar(void)
3204 {
3205   return MSVCRT_fgetc(MSVCRT_stdin);
3206 }
3207
3208 /*********************************************************************
3209  *              fgets (MSVCRT.@)
3210  */
3211 char * CDECL MSVCRT_fgets(char *s, int size, MSVCRT_FILE* file)
3212 {
3213   int    cc = MSVCRT_EOF;
3214   char * buf_start = s;
3215
3216   TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3217         file,file->_file,s,size);
3218
3219   MSVCRT__lock_file(file);
3220
3221   while ((size >1) && (cc = MSVCRT_fgetc(file)) != MSVCRT_EOF && cc != '\n')
3222     {
3223       *s++ = (char)cc;
3224       size --;
3225     }
3226   if ((cc == MSVCRT_EOF) && (s == buf_start)) /* If nothing read, return 0*/
3227   {
3228     TRACE(":nothing read\n");
3229     MSVCRT__unlock_file(file);
3230     return NULL;
3231   }
3232   if ((cc != MSVCRT_EOF) && (size > 1))
3233     *s++ = cc;
3234   *s = '\0';
3235   TRACE(":got %s\n", debugstr_a(buf_start));
3236   MSVCRT__unlock_file(file);
3237   return buf_start;
3238 }
3239
3240 /*********************************************************************
3241  *              fgetwc (MSVCRT.@)
3242  *
3243  * In MSVCRT__O_TEXT mode, multibyte characters are read from the file, dropping
3244  * the CR from CR/LF combinations
3245  */
3246 MSVCRT_wint_t CDECL MSVCRT_fgetwc(MSVCRT_FILE* file)
3247 {
3248   int c;
3249
3250   MSVCRT__lock_file(file);
3251   if (!(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT))
3252     {
3253       MSVCRT_wchar_t wc;
3254       unsigned int i;
3255       int j;
3256       char *chp, *wcp;
3257       wcp = (char *)&wc;
3258       for(i=0; i<sizeof(wc); i++)
3259       {
3260         if (file->_cnt>0) 
3261         {
3262           file->_cnt--;
3263           chp = file->_ptr++;
3264           wcp[i] = *chp;
3265         } 
3266         else
3267         {
3268           j = MSVCRT__filbuf(file);
3269           if(file->_cnt<=0)
3270           {
3271             file->_flag |= (file->_cnt == 0) ? MSVCRT__IOEOF : MSVCRT__IOERR;
3272             file->_cnt = 0;
3273
3274             MSVCRT__unlock_file(file);
3275             return MSVCRT_WEOF;
3276           }
3277           wcp[i] = j;
3278         }
3279       }
3280
3281       MSVCRT__unlock_file(file);
3282       return wc;
3283     }
3284     
3285   c = MSVCRT_fgetc(file);
3286   if ((get_locinfo()->mb_cur_max > 1) && MSVCRT_isleadbyte(c))
3287     {
3288       FIXME("Treat Multibyte characters\n");
3289     }
3290
3291   MSVCRT__unlock_file(file);
3292   if (c == MSVCRT_EOF)
3293     return MSVCRT_WEOF;
3294   else
3295     return (MSVCRT_wint_t)c;
3296 }
3297
3298 /*********************************************************************
3299  *              _getw (MSVCRT.@)
3300  */
3301 int CDECL MSVCRT__getw(MSVCRT_FILE* file)
3302 {
3303   char *ch;
3304   int i, k;
3305   unsigned int j;
3306   ch = (char *)&i;
3307
3308   MSVCRT__lock_file(file);
3309   for (j=0; j<sizeof(int); j++) {
3310     k = MSVCRT_fgetc(file);
3311     if (k == MSVCRT_EOF) {
3312       file->_flag |= MSVCRT__IOEOF;
3313       MSVCRT__unlock_file(file);
3314       return EOF;
3315     }
3316     ch[j] = k;
3317   }
3318
3319   MSVCRT__unlock_file(file);
3320   return i;
3321 }
3322
3323 /*********************************************************************
3324  *              getwc (MSVCRT.@)
3325  */
3326 MSVCRT_wint_t CDECL MSVCRT_getwc(MSVCRT_FILE* file)
3327 {
3328   return MSVCRT_fgetwc(file);
3329 }
3330
3331 /*********************************************************************
3332  *              _fgetwchar (MSVCRT.@)
3333  */
3334 MSVCRT_wint_t CDECL MSVCRT__fgetwchar(void)
3335 {
3336   return MSVCRT_fgetwc(MSVCRT_stdin);
3337 }
3338
3339 /*********************************************************************
3340  *              getwchar (MSVCRT.@)
3341  */
3342 MSVCRT_wint_t CDECL MSVCRT_getwchar(void)
3343 {
3344   return MSVCRT__fgetwchar();
3345 }
3346
3347 /*********************************************************************
3348  *              fgetws (MSVCRT.@)
3349  */
3350 MSVCRT_wchar_t * CDECL MSVCRT_fgetws(MSVCRT_wchar_t *s, int size, MSVCRT_FILE* file)
3351 {
3352   int    cc = MSVCRT_WEOF;
3353   MSVCRT_wchar_t * buf_start = s;
3354
3355   TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3356         file,file->_file,s,size);
3357
3358   MSVCRT__lock_file(file);
3359
3360   while ((size >1) && (cc = MSVCRT_fgetwc(file)) != MSVCRT_WEOF && cc != '\n')
3361     {
3362       *s++ = (char)cc;
3363       size --;
3364     }
3365   if ((cc == MSVCRT_WEOF) && (s == buf_start)) /* If nothing read, return 0*/
3366   {
3367     TRACE(":nothing read\n");
3368     MSVCRT__unlock_file(file);
3369     return NULL;
3370   }
3371   if ((cc != MSVCRT_WEOF) && (size > 1))
3372     *s++ = cc;
3373   *s = 0;
3374   TRACE(":got %s\n", debugstr_w(buf_start));
3375   MSVCRT__unlock_file(file);
3376   return buf_start;
3377 }
3378
3379 /*********************************************************************
3380  *              fwrite (MSVCRT.@)
3381  */
3382 MSVCRT_size_t CDECL MSVCRT_fwrite(const void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
3383 {
3384     MSVCRT_size_t wrcnt=size * nmemb;
3385     int written = 0;
3386     if (size == 0)
3387         return 0;
3388
3389     MSVCRT__lock_file(file);
3390     if(file->_cnt) {
3391         int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
3392         memcpy(file->_ptr, ptr, pcnt);
3393         file->_cnt -= pcnt;
3394         file->_ptr += pcnt;
3395         written = pcnt;
3396         wrcnt -= pcnt;
3397         ptr = (const char*)ptr + pcnt;
3398     } else if(!(file->_flag & MSVCRT__IOWRT)) {
3399         if(file->_flag & MSVCRT__IORW) {
3400             file->_flag |= MSVCRT__IOWRT;
3401         } else {
3402             MSVCRT__unlock_file(file);
3403             return 0;
3404         }
3405     }
3406     if(wrcnt) {
3407         int res;
3408
3409         if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF))
3410             msvcrt_alloc_buffer(file);
3411
3412         /* Flush buffer */
3413         res=msvcrt_flush_buffer(file);
3414         if(!res) {
3415             int pwritten = MSVCRT__write(file->_file, ptr, wrcnt);
3416             if (pwritten <= 0)
3417             {
3418                 file->_flag |= MSVCRT__IOERR;
3419                 pwritten=0;
3420             }
3421             written += pwritten;
3422         }
3423     }
3424
3425     MSVCRT__unlock_file(file);
3426     return written / size;
3427 }
3428
3429 /*********************************************************************
3430  *              fputwc (MSVCRT.@)
3431  */
3432 MSVCRT_wint_t CDECL MSVCRT_fputwc(MSVCRT_wint_t wc, MSVCRT_FILE* file)
3433 {
3434     MSVCRT_wchar_t mwc=wc;
3435     ioinfo *fdinfo;
3436     MSVCRT_wint_t ret;
3437
3438     MSVCRT__lock_file(file);
3439     fdinfo = msvcrt_get_ioinfo(file->_file);
3440
3441     if((fdinfo->wxflag&WX_TEXT) && !(fdinfo->exflag&(EF_UTF8|EF_UTF16))) {
3442         char buf[MSVCRT_MB_LEN_MAX];
3443         int char_len;
3444
3445         char_len = MSVCRT_wctomb(buf, mwc);
3446         if(char_len!=-1 && MSVCRT_fwrite(buf, char_len, 1, file)==1)
3447             ret = wc;
3448         else
3449             ret = MSVCRT_WEOF;
3450     }else if(MSVCRT_fwrite(&mwc, sizeof(mwc), 1, file) == 1) {
3451         ret = wc;
3452     }else {
3453         ret = MSVCRT_WEOF;
3454     }
3455
3456     MSVCRT__unlock_file(file);
3457     return ret;
3458 }
3459
3460 /*********************************************************************
3461  *              _fputwchar (MSVCRT.@)
3462  */
3463 MSVCRT_wint_t CDECL MSVCRT__fputwchar(MSVCRT_wint_t wc)
3464 {
3465   return MSVCRT_fputwc(wc, MSVCRT_stdout);
3466 }
3467
3468 /*********************************************************************
3469  *              _wfsopen (MSVCRT.@)
3470  */
3471 MSVCRT_FILE * CDECL MSVCRT__wfsopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, int share)
3472 {
3473   MSVCRT_FILE* file;
3474   int open_flags, stream_flags, fd;
3475
3476   TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
3477
3478   /* map mode string to open() flags. "man fopen" for possibilities. */
3479   if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
3480       return NULL;
3481
3482   LOCK_FILES();
3483   fd = MSVCRT__wsopen(path, open_flags, share, MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
3484   if (fd < 0)
3485     file = NULL;
3486   else if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags)
3487    != -1)
3488     TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
3489   else if (file)
3490   {
3491     file->_flag = 0;
3492     file = NULL;
3493   }
3494
3495   TRACE(":got (%p)\n",file);
3496   if (fd >= 0 && !file)
3497     MSVCRT__close(fd);
3498   UNLOCK_FILES();
3499   return file;
3500 }
3501
3502 /*********************************************************************
3503  *              _fsopen (MSVCRT.@)
3504  */
3505 MSVCRT_FILE * CDECL MSVCRT__fsopen(const char *path, const char *mode, int share)
3506 {
3507     MSVCRT_FILE *ret;
3508     MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
3509
3510     if (path && !(pathW = msvcrt_wstrdupa(path))) {
3511         MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
3512         *MSVCRT__errno() = MSVCRT_EINVAL;
3513         return NULL;
3514     }
3515     if (mode && !(modeW = msvcrt_wstrdupa(mode)))
3516     {
3517         MSVCRT_free(pathW);
3518         MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
3519         *MSVCRT__errno() = MSVCRT_EINVAL;
3520         return NULL;
3521     }
3522
3523     ret = MSVCRT__wfsopen(pathW, modeW, share);
3524
3525     MSVCRT_free(pathW);
3526     MSVCRT_free(modeW);
3527     return ret;
3528 }
3529
3530 /*********************************************************************
3531  *              fopen (MSVCRT.@)
3532  */
3533 MSVCRT_FILE * CDECL MSVCRT_fopen(const char *path, const char *mode)
3534 {
3535     return MSVCRT__fsopen( path, mode, MSVCRT__SH_DENYNO );
3536 }
3537
3538 /*********************************************************************
3539  *              fopen_s (MSVCRT.@)
3540  */
3541 int CDECL MSVCRT_fopen_s(MSVCRT_FILE** pFile,
3542         const char *filename, const char *mode)
3543 {
3544     if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
3545     if (!MSVCRT_CHECK_PMT(filename != NULL)) return MSVCRT_EINVAL;
3546     if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
3547
3548     *pFile = MSVCRT_fopen(filename, mode);
3549
3550     if(!*pFile)
3551         return *MSVCRT__errno();
3552     return 0;
3553 }
3554
3555 /*********************************************************************
3556  *              _wfopen (MSVCRT.@)
3557  */
3558 MSVCRT_FILE * CDECL MSVCRT__wfopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode)
3559 {
3560     return MSVCRT__wfsopen( path, mode, MSVCRT__SH_DENYNO );
3561 }
3562
3563 /*********************************************************************
3564  *              _wfopen_s (MSVCRT.@)
3565  */
3566 int CDECL MSVCRT__wfopen_s(MSVCRT_FILE** pFile, const MSVCRT_wchar_t *filename,
3567         const MSVCRT_wchar_t *mode)
3568 {
3569     if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
3570     if (!MSVCRT_CHECK_PMT(filename != NULL)) return MSVCRT_EINVAL;
3571     if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
3572
3573     *pFile = MSVCRT__wfopen(filename, mode);
3574
3575     if(!*pFile)
3576         return *MSVCRT__errno();
3577     return 0;
3578 }
3579
3580 /*********************************************************************
3581  *              _flsbuf (MSVCRT.@)
3582  */
3583 int CDECL MSVCRT__flsbuf(int c, MSVCRT_FILE* file)
3584 {
3585     /* Flush output buffer */
3586     if(file->_bufsiz == 0 && !(file->_flag & MSVCRT__IONBF)) {
3587         msvcrt_alloc_buffer(file);
3588     }
3589     if(!(file->_flag & MSVCRT__IOWRT)) {
3590         if(file->_flag & MSVCRT__IORW)
3591             file->_flag |= MSVCRT__IOWRT;
3592         else
3593             return MSVCRT_EOF;
3594     }
3595     if(file->_bufsiz) {
3596         int res = 0;
3597
3598         if(file->_cnt <= 0)
3599             res = msvcrt_flush_buffer(file);
3600         if(!res) {
3601             *file->_ptr++ = c;
3602             file->_cnt--;
3603             res = msvcrt_flush_buffer(file);
3604         }
3605
3606         return res ? res : c&0xff;
3607     } else {
3608         unsigned char cc=c;
3609         int len;
3610         /* set _cnt to 0 for unbuffered FILEs */
3611         file->_cnt = 0;
3612         len = MSVCRT__write(file->_file, &cc, 1);
3613         if (len == 1)
3614             return c & 0xff;
3615         file->_flag |= MSVCRT__IOERR;
3616         return MSVCRT_EOF;
3617     }
3618 }
3619
3620 /*********************************************************************
3621  *              fputc (MSVCRT.@)
3622  */
3623 int CDECL MSVCRT_fputc(int c, MSVCRT_FILE* file)
3624 {
3625   int res;
3626
3627   MSVCRT__lock_file(file);
3628   if(file->_cnt>0) {
3629     *file->_ptr++=c;
3630     file->_cnt--;
3631     if (c == '\n')
3632     {
3633       res = msvcrt_flush_buffer(file);
3634       MSVCRT__unlock_file(file);
3635       return res ? res : c;
3636     }
3637     else {
3638       MSVCRT__unlock_file(file);
3639       return c & 0xff;
3640     }
3641   } else {
3642     res = MSVCRT__flsbuf(c, file);
3643     MSVCRT__unlock_file(file);
3644     return res;
3645   }
3646 }
3647
3648 /*********************************************************************
3649  *              _fputchar (MSVCRT.@)
3650  */
3651 int CDECL MSVCRT__fputchar(int c)
3652 {
3653   return MSVCRT_fputc(c, MSVCRT_stdout);
3654 }
3655
3656 /*********************************************************************
3657  *              fread (MSVCRT.@)
3658  */
3659 MSVCRT_size_t CDECL MSVCRT_fread(void *ptr, MSVCRT_size_t size, MSVCRT_size_t nmemb, MSVCRT_FILE* file)
3660 {
3661   MSVCRT_size_t rcnt=size * nmemb;
3662   MSVCRT_size_t read=0;
3663   int pread=0;
3664
3665   if(!rcnt)
3666         return 0;
3667
3668   MSVCRT__lock_file(file);
3669
3670   /* first buffered data */
3671   if(file->_cnt>0) {
3672         int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
3673         memcpy(ptr, file->_ptr, pcnt);
3674         file->_cnt -= pcnt;
3675         file->_ptr += pcnt;
3676         read += pcnt ;
3677         rcnt -= pcnt ;
3678         ptr = (char*)ptr + pcnt;
3679   } else if(!(file->_flag & MSVCRT__IOREAD )) {
3680         if(file->_flag & MSVCRT__IORW) {
3681                 file->_flag |= MSVCRT__IOREAD;
3682         } else {
3683         MSVCRT__unlock_file(file);
3684         return 0;
3685     }
3686   }
3687   while(rcnt>0)
3688   {
3689     int i;
3690     /* Fill the buffer on small reads.
3691      * TODO: Use a better buffering strategy.
3692      */
3693     if (!file->_cnt && size*nmemb <= MSVCRT_BUFSIZ/2 && !(file->_flag & MSVCRT__IONBF)
3694             && (file->_bufsiz != 0 || msvcrt_alloc_buffer(file))) {
3695       file->_cnt = MSVCRT__read(file->_file, file->_base, file->_bufsiz);
3696       file->_ptr = file->_base;
3697       i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
3698       /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
3699       if (i > 0 && i < file->_cnt) {
3700         msvcrt_get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF;
3701         file->_flag &= ~MSVCRT__IOEOF;
3702       }
3703       if (i > 0) {
3704         memcpy(ptr, file->_ptr, i);
3705         file->_cnt -= i;
3706         file->_ptr += i;
3707       }
3708     } else {
3709       i = MSVCRT__read(file->_file,ptr, rcnt);
3710     }
3711     pread += i;
3712     rcnt -= i;
3713     ptr = (char *)ptr+i;
3714     /* expose feof condition in the flags
3715      * MFC tests file->_flag for feof, and doesn't call feof())
3716      */
3717     if (msvcrt_get_ioinfo(file->_file)->wxflag & WX_ATEOF)
3718         file->_flag |= MSVCRT__IOEOF;
3719     else if (i == -1)
3720     {
3721         file->_flag |= MSVCRT__IOERR;
3722         pread = 0;
3723         rcnt = 0;
3724     }
3725     if (i < 1) break;
3726   }
3727   read+=pread;
3728   MSVCRT__unlock_file(file);
3729   return read / size;
3730 }
3731
3732 /*********************************************************************
3733  *              _wfreopen (MSVCRT.@)
3734  *
3735  */
3736 MSVCRT_FILE* CDECL MSVCRT__wfreopen(const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, MSVCRT_FILE* file)
3737 {
3738   int fd;
3739
3740   TRACE(":path (%s) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file);
3741
3742   LOCK_FILES();
3743   if (!file || ((fd = file->_file) < 0) || fd > MSVCRT_fdend)
3744     file = NULL;
3745   else
3746   {
3747     MSVCRT_fclose(file);
3748     file = MSVCRT__wfsopen(path, mode, MSVCRT__SH_DENYNO);
3749   }
3750   UNLOCK_FILES();
3751   return file;
3752 }
3753
3754 /*********************************************************************
3755  *      _wfreopen_s (MSVCRT.@)
3756  */
3757 int CDECL MSVCRT__wfreopen_s(MSVCRT_FILE** pFile,
3758         const MSVCRT_wchar_t *path, const MSVCRT_wchar_t *mode, MSVCRT_FILE* file)
3759 {
3760     if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
3761     if (!MSVCRT_CHECK_PMT(path != NULL)) return MSVCRT_EINVAL;
3762     if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
3763     if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
3764
3765     *pFile = MSVCRT__wfreopen(path, mode, file);
3766
3767     if(!*pFile)
3768         return *MSVCRT__errno();
3769     return 0;
3770 }
3771
3772 /*********************************************************************
3773  *      freopen (MSVCRT.@)
3774  *
3775  */
3776 MSVCRT_FILE* CDECL MSVCRT_freopen(const char *path, const char *mode, MSVCRT_FILE* file)
3777 {
3778     MSVCRT_FILE *ret;
3779     MSVCRT_wchar_t *pathW = NULL, *modeW = NULL;
3780
3781     if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
3782     if (mode && !(modeW = msvcrt_wstrdupa(mode)))
3783     {
3784         MSVCRT_free(pathW);
3785         return NULL;
3786     }
3787
3788     ret = MSVCRT__wfreopen(pathW, modeW, file);
3789
3790     MSVCRT_free(pathW);
3791     MSVCRT_free(modeW);
3792     return ret;
3793 }
3794
3795 /*********************************************************************
3796  *      freopen_s (MSVCRT.@)
3797  */
3798 int CDECL MSVCRT_freopen_s(MSVCRT_FILE** pFile,
3799         const char *path, const char *mode, MSVCRT_FILE* file)
3800 {
3801     if (!MSVCRT_CHECK_PMT(pFile != NULL)) return MSVCRT_EINVAL;
3802     if (!MSVCRT_CHECK_PMT(path != NULL)) return MSVCRT_EINVAL;
3803     if (!MSVCRT_CHECK_PMT(mode != NULL)) return MSVCRT_EINVAL;
3804     if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
3805
3806     *pFile = MSVCRT_freopen(path, mode, file);
3807
3808     if(!*pFile)
3809         return *MSVCRT__errno();
3810     return 0;
3811 }
3812
3813 /*********************************************************************
3814  *              fsetpos (MSVCRT.@)
3815  */
3816 int CDECL MSVCRT_fsetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
3817 {
3818   int ret;
3819
3820   MSVCRT__lock_file(file);
3821   /* Note that all this has been lifted 'as is' from fseek */
3822   if(file->_flag & MSVCRT__IOWRT)
3823         msvcrt_flush_buffer(file);
3824
3825   /* Discard buffered input */
3826   file->_cnt = 0;
3827   file->_ptr = file->_base;
3828   
3829   /* Reset direction of i/o */
3830   if(file->_flag & MSVCRT__IORW) {
3831         file->_flag &= ~(MSVCRT__IOREAD|MSVCRT__IOWRT);
3832   }
3833
3834   ret = (MSVCRT__lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0;
3835   MSVCRT__unlock_file(file);
3836   return ret;
3837 }
3838
3839 /*********************************************************************
3840  *              _ftelli64 (MSVCRT.@)
3841  */
3842 __int64 CDECL MSVCRT__ftelli64(MSVCRT_FILE* file)
3843 {
3844     __int64 pos;
3845
3846     MSVCRT__lock_file(file);
3847     pos = _telli64(file->_file);
3848     if(pos == -1) {
3849         MSVCRT__unlock_file(file);
3850         return -1;
3851     }
3852     if(file->_bufsiz)  {
3853         if(file->_flag & MSVCRT__IOWRT) {
3854             pos += file->_ptr - file->_base;
3855
3856             if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
3857                 char *p;
3858
3859                 for(p=file->_base; p<file->_ptr; p++)
3860                     if(*p == '\n')
3861                         pos++;
3862             }
3863         } else if(!file->_cnt) { /* nothing to do */
3864         } else if(MSVCRT__lseeki64(file->_file, 0, SEEK_END)==pos) {
3865             int i;
3866
3867             pos -= file->_cnt;
3868             if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
3869                 for(i=0; i<file->_cnt; i++)
3870                     if(file->_ptr[i] == '\n')
3871                         pos--;
3872             }
3873         } else {
3874             char *p;
3875
3876             if(MSVCRT__lseeki64(file->_file, pos, SEEK_SET) != pos) {
3877                 MSVCRT__unlock_file(file);
3878                 return -1;
3879             }
3880
3881             pos -= file->_bufsiz;
3882             pos += file->_ptr - file->_base;
3883
3884             if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT) {
3885                 if(msvcrt_get_ioinfo(file->_file)->wxflag & WX_READNL)
3886                     pos--;
3887
3888                 for(p=file->_base; p<file->_ptr; p++)
3889                     if(*p == '\n')
3890                         pos++;
3891             }
3892         }
3893     }
3894
3895     MSVCRT__unlock_file(file);
3896     return pos;
3897 }
3898
3899 /*********************************************************************
3900  *              ftell (MSVCRT.@)
3901  */
3902 LONG CDECL MSVCRT_ftell(MSVCRT_FILE* file)
3903 {
3904   return MSVCRT__ftelli64(file);
3905 }
3906
3907 /*********************************************************************
3908  *              fgetpos (MSVCRT.@)
3909  */
3910 int CDECL MSVCRT_fgetpos(MSVCRT_FILE* file, MSVCRT_fpos_t *pos)
3911 {
3912     *pos = MSVCRT__ftelli64(file);
3913     if(*pos == -1)
3914         return -1;
3915     return 0;
3916 }
3917
3918 /*********************************************************************
3919  *              fputs (MSVCRT.@)
3920  */
3921 int CDECL MSVCRT_fputs(const char *s, MSVCRT_FILE* file)
3922 {
3923     MSVCRT_size_t len = strlen(s);
3924     int ret;
3925
3926     MSVCRT__lock_file(file);
3927     ret = MSVCRT_fwrite(s, sizeof(*s), len, file) == len ? 0 : MSVCRT_EOF;
3928     MSVCRT__unlock_file(file);
3929     return ret;
3930 }
3931
3932 /*********************************************************************
3933  *              fputws (MSVCRT.@)
3934  */
3935 int CDECL MSVCRT_fputws(const MSVCRT_wchar_t *s, MSVCRT_FILE* file)
3936 {
3937     MSVCRT_size_t i, len = strlenW(s);
3938     BOOL tmp_buf;
3939     int ret;
3940
3941     MSVCRT__lock_file(file);
3942     if (!(msvcrt_get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
3943         ret = MSVCRT_fwrite(s,sizeof(*s),len,file) == len ? 0 : MSVCRT_EOF;
3944         MSVCRT__unlock_file(file);
3945         return ret;
3946     }
3947
3948     tmp_buf = add_std_buffer(file);
3949     for (i=0; i<len; i++) {
3950         if(MSVCRT_fputwc(s[i], file) == MSVCRT_WEOF) {
3951             if(tmp_buf) remove_std_buffer(file);
3952             MSVCRT__unlock_file(file);
3953             return MSVCRT_WEOF;
3954         }
3955     }
3956
3957     if(tmp_buf) remove_std_buffer(file);
3958     MSVCRT__unlock_file(file);
3959     return 0;
3960 }
3961
3962 /*********************************************************************
3963  *              getchar (MSVCRT.@)
3964  */
3965 int CDECL MSVCRT_getchar(void)
3966 {
3967   return MSVCRT_fgetc(MSVCRT_stdin);
3968 }
3969
3970 /*********************************************************************
3971  *              getc (MSVCRT.@)
3972  */
3973 int CDECL MSVCRT_getc(MSVCRT_FILE* file)
3974 {
3975   return MSVCRT_fgetc(file);
3976 }
3977
3978 /*********************************************************************
3979  *              gets (MSVCRT.@)
3980  */
3981 char * CDECL MSVCRT_gets(char *buf)
3982 {
3983   int    cc;
3984   char * buf_start = buf;
3985
3986   MSVCRT__lock_file(MSVCRT_stdin);
3987   for(cc = MSVCRT_fgetc(MSVCRT_stdin); cc != MSVCRT_EOF && cc != '\n';
3988       cc = MSVCRT_fgetc(MSVCRT_stdin))
3989   if(cc != '\r') *buf++ = (char)cc;
3990
3991   *buf = '\0';
3992
3993   TRACE("got '%s'\n", buf_start);
3994   MSVCRT__unlock_file(MSVCRT_stdin);
3995   return buf_start;
3996 }
3997
3998 /*********************************************************************
3999  *              _getws (MSVCRT.@)
4000  */
4001 MSVCRT_wchar_t* CDECL MSVCRT__getws(MSVCRT_wchar_t* buf)
4002 {
4003     MSVCRT_wint_t cc;
4004     MSVCRT_wchar_t* ws = buf;
4005
4006     MSVCRT__lock_file(MSVCRT_stdin);
4007     for (cc = MSVCRT_fgetwc(MSVCRT_stdin); cc != MSVCRT_WEOF && cc != '\n';
4008          cc = MSVCRT_fgetwc(MSVCRT_stdin))
4009     {
4010         if (cc != '\r')
4011             *buf++ = (MSVCRT_wchar_t)cc;
4012     }
4013     *buf = '\0';
4014
4015     TRACE("got %s\n", debugstr_w(ws));
4016     MSVCRT__unlock_file(MSVCRT_stdin);
4017     return ws;
4018 }
4019
4020 /*********************************************************************
4021  *              putc (MSVCRT.@)
4022  */
4023 int CDECL MSVCRT_putc(int c, MSVCRT_FILE* file)
4024 {
4025   return MSVCRT_fputc(c, file);
4026 }
4027
4028 /*********************************************************************
4029  *              putchar (MSVCRT.@)
4030  */
4031 int CDECL MSVCRT_putchar(int c)
4032 {
4033   return MSVCRT_fputc(c, MSVCRT_stdout);
4034 }
4035
4036 /*********************************************************************
4037  *              _putwch (MSVCRT.@)
4038  */
4039 int CDECL MSVCRT__putwch(int c)
4040 {
4041   return MSVCRT_fputwc(c, MSVCRT_stdout);
4042 }
4043
4044 /*********************************************************************
4045  *              puts (MSVCRT.@)
4046  */
4047 int CDECL MSVCRT_puts(const char *s)
4048 {
4049     MSVCRT_size_t len = strlen(s);
4050     int ret;
4051
4052     MSVCRT__lock_file(MSVCRT_stdout);
4053     if(MSVCRT_fwrite(s, sizeof(*s), len, MSVCRT_stdout) != len) {
4054         MSVCRT__unlock_file(MSVCRT_stdout);
4055         return MSVCRT_EOF;
4056     }
4057
4058     ret = MSVCRT_fwrite("\n",1,1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
4059     MSVCRT__unlock_file(MSVCRT_stdout);
4060     return ret;
4061 }
4062
4063 /*********************************************************************
4064  *              _putws (MSVCRT.@)
4065  */
4066 int CDECL MSVCRT__putws(const MSVCRT_wchar_t *s)
4067 {
4068     static const MSVCRT_wchar_t nl = '\n';
4069     MSVCRT_size_t len = strlenW(s);
4070     int ret;
4071
4072     MSVCRT__lock_file(MSVCRT_stdout);
4073     if(MSVCRT_fwrite(s, sizeof(*s), len, MSVCRT_stdout) != len) {
4074         MSVCRT__unlock_file(MSVCRT_stdout);
4075         return MSVCRT_EOF;
4076     }
4077
4078     ret = MSVCRT_fwrite(&nl,sizeof(nl),1,MSVCRT_stdout) == 1 ? 0 : MSVCRT_EOF;
4079     MSVCRT__unlock_file(MSVCRT_stdout);
4080     return ret;
4081 }
4082
4083 /*********************************************************************
4084  *              remove (MSVCRT.@)
4085  */
4086 int CDECL MSVCRT_remove(const char *path)
4087 {
4088   TRACE("(%s)\n",path);
4089   if (DeleteFileA(path))
4090     return 0;
4091   TRACE(":failed (%d)\n",GetLastError());
4092   msvcrt_set_errno(GetLastError());
4093   return -1;
4094 }
4095
4096 /*********************************************************************
4097  *              _wremove (MSVCRT.@)
4098  */
4099 int CDECL MSVCRT__wremove(const MSVCRT_wchar_t *path)
4100 {
4101   TRACE("(%s)\n",debugstr_w(path));
4102   if (DeleteFileW(path))
4103     return 0;
4104   TRACE(":failed (%d)\n",GetLastError());
4105   msvcrt_set_errno(GetLastError());
4106   return -1;
4107 }
4108
4109 /*********************************************************************
4110  *              rename (MSVCRT.@)
4111  */
4112 int CDECL MSVCRT_rename(const char *oldpath,const char *newpath)
4113 {
4114   TRACE(":from %s to %s\n",oldpath,newpath);
4115   if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
4116     return 0;
4117   TRACE(":failed (%d)\n",GetLastError());
4118   msvcrt_set_errno(GetLastError());
4119   return -1;
4120 }
4121
4122 /*********************************************************************
4123  *              _wrename (MSVCRT.@)
4124  */
4125 int CDECL MSVCRT__wrename(const MSVCRT_wchar_t *oldpath,const MSVCRT_wchar_t *newpath)
4126 {
4127   TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
4128   if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
4129     return 0;
4130   TRACE(":failed (%d)\n",GetLastError());
4131   msvcrt_set_errno(GetLastError());
4132   return -1;
4133 }
4134
4135 /*********************************************************************
4136  *              setvbuf (MSVCRT.@)
4137  */
4138 int CDECL MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size)
4139 {
4140   MSVCRT__lock_file(file);
4141   if(file->_bufsiz) {
4142         MSVCRT_free(file->_base);
4143         file->_bufsiz = 0;
4144         file->_cnt = 0;
4145   }
4146   if(mode == MSVCRT__IOFBF) {
4147         file->_flag &= ~MSVCRT__IONBF;
4148         file->_base = file->_ptr = buf;
4149         if(buf) {
4150                 file->_bufsiz = size;
4151         }
4152   } else {
4153         file->_flag |= MSVCRT__IONBF;
4154   }
4155   MSVCRT__unlock_file(file);
4156   return 0;
4157 }
4158
4159 /*********************************************************************
4160  *              setbuf (MSVCRT.@)
4161  */
4162 void CDECL MSVCRT_setbuf(MSVCRT_FILE* file, char *buf)
4163 {
4164   MSVCRT_setvbuf(file, buf, buf ? MSVCRT__IOFBF : MSVCRT__IONBF, MSVCRT_BUFSIZ);
4165 }
4166
4167 /*********************************************************************
4168  *              tmpnam (MSVCRT.@)
4169  */
4170 char * CDECL MSVCRT_tmpnam(char *s)
4171 {
4172   char tmpstr[16];
4173   char *p;
4174   int count, size;
4175
4176   if (!s) {
4177     thread_data_t *data = msvcrt_get_thread_data();
4178
4179     if(!data->tmpnam_buffer)
4180       data->tmpnam_buffer = MSVCRT_malloc(MAX_PATH);
4181
4182     s = data->tmpnam_buffer;
4183   }
4184
4185   msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr);
4186   p = s + sprintf(s, "\\s%s.", tmpstr);
4187   for (count = 0; count < MSVCRT_TMP_MAX; count++)
4188   {
4189     size = msvcrt_int_to_base32(tmpnam_unique++, tmpstr);
4190     memcpy(p, tmpstr, size);
4191     p[size] = '\0';
4192     if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES &&
4193         GetLastError() == ERROR_FILE_NOT_FOUND)
4194       break;
4195   }
4196   return s;
4197 }
4198
4199 /*********************************************************************
4200  *              _wtmpnam (MSVCRT.@)
4201  */
4202 MSVCRT_wchar_t * CDECL MSVCRT_wtmpnam(MSVCRT_wchar_t *s)
4203 {
4204     static const MSVCRT_wchar_t format[] = {'\\','s','%','s','.',0};
4205     MSVCRT_wchar_t tmpstr[16];
4206     MSVCRT_wchar_t *p;
4207     int count, size;
4208     if (!s) {
4209         thread_data_t *data = msvcrt_get_thread_data();
4210
4211         if(!data->wtmpnam_buffer)
4212             data->wtmpnam_buffer = MSVCRT_malloc(sizeof(MSVCRT_wchar_t[MAX_PATH]));
4213
4214         s = data->wtmpnam_buffer;
4215     }
4216
4217     msvcrt_int_to_base32_w(GetCurrentProcessId(), tmpstr);
4218     p = s + MSVCRT__snwprintf(s, MAX_PATH, format, tmpstr);
4219     for (count = 0; count < MSVCRT_TMP_MAX; count++)
4220     {
4221         size = msvcrt_int_to_base32_w(tmpnam_unique++, tmpstr);
4222         memcpy(p, tmpstr, size*sizeof(MSVCRT_wchar_t));
4223         p[size] = '\0';
4224         if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES &&
4225                 GetLastError() == ERROR_FILE_NOT_FOUND)
4226             break;
4227     }
4228     return s;
4229 }
4230
4231 /*********************************************************************
4232  *              tmpfile (MSVCRT.@)
4233  */
4234 MSVCRT_FILE* CDECL MSVCRT_tmpfile(void)
4235 {
4236   char *filename = MSVCRT_tmpnam(NULL);
4237   int fd;
4238   MSVCRT_FILE* file = NULL;
4239
4240   LOCK_FILES();
4241   fd = MSVCRT__open(filename, MSVCRT__O_CREAT | MSVCRT__O_BINARY | MSVCRT__O_RDWR | MSVCRT__O_TEMPORARY,
4242           MSVCRT__S_IREAD | MSVCRT__S_IWRITE);
4243   if (fd != -1 && (file = msvcrt_alloc_fp()))
4244   {
4245     if (msvcrt_init_fp(file, fd, MSVCRT__IORW) == -1)
4246     {
4247         file->_flag = 0;
4248         file = NULL;
4249     }
4250     else file->_tmpfname = MSVCRT__strdup(filename);
4251   }
4252
4253   if(fd != -1 && !file)
4254       MSVCRT__close(fd);
4255   UNLOCK_FILES();
4256   return file;
4257 }
4258
4259 /*********************************************************************
4260  *      tmpfile_s (MSVCRT.@)
4261  */
4262 int CDECL MSVCRT_tmpfile_s(MSVCRT_FILE** file)
4263 {
4264     if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL;
4265
4266     *file = MSVCRT_tmpfile();
4267     return 0;
4268 }
4269
4270 static int puts_clbk_file_a(void *file, int len, const char *str)
4271 {
4272     return MSVCRT_fwrite(str, sizeof(char), len, file);
4273 }
4274
4275 static int puts_clbk_file_w(void *file, int len, const MSVCRT_wchar_t *str)
4276 {
4277     int i, ret;
4278
4279     MSVCRT__lock_file(file);
4280
4281     if(!(msvcrt_get_ioinfo(((MSVCRT_FILE*)file)->_file)->wxflag & WX_TEXT)) {
4282         ret = MSVCRT_fwrite(str, sizeof(MSVCRT_wchar_t), len, file);
4283         MSVCRT__unlock_file(file);
4284         return ret;
4285     }
4286
4287     for(i=0; i<len; i++) {
4288         if(MSVCRT_fputwc(str[i], file) == MSVCRT_WEOF) {
4289             MSVCRT__unlock_file(file);
4290             return -1;
4291         }
4292     }
4293
4294     MSVCRT__unlock_file(file);
4295     return len;
4296 }
4297
4298 /*********************************************************************
4299  *              vfprintf (MSVCRT.@)
4300  */
4301 int CDECL MSVCRT_vfprintf(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
4302 {
4303     BOOL tmp_buf;
4304     int ret;
4305
4306     MSVCRT__lock_file(file);
4307     tmp_buf = add_std_buffer(file);
4308     ret = pf_printf_a(puts_clbk_file_a, file, format, NULL, FALSE, FALSE, arg_clbk_valist, NULL, &valist);
4309     if(tmp_buf) remove_std_buffer(file);
4310     MSVCRT__unlock_file(file);
4311
4312     return ret;
4313 }
4314
4315 /*********************************************************************
4316  *              vfprintf_s (MSVCRT.@)
4317  */
4318 int CDECL MSVCRT_vfprintf_s(MSVCRT_FILE* file, const char *format, __ms_va_list valist)
4319 {
4320     BOOL tmp_buf;
4321     int ret;
4322
4323     if(!MSVCRT_CHECK_PMT(file != NULL)) return -1;
4324
4325     MSVCRT__lock_file(file);
4326     tmp_buf = add_std_buffer(file);
4327     ret = pf_printf_a(puts_clbk_file_a, file, format, NULL, FALSE, TRUE, arg_clbk_valist, NULL, &valist);
4328     if(tmp_buf) remove_std_buffer(file);
4329     MSVCRT__unlock_file(file);
4330
4331     return ret;
4332 }
4333
4334 /*********************************************************************
4335  *              vfwprintf (MSVCRT.@)
4336  */
4337 int CDECL MSVCRT_vfwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
4338 {
4339     BOOL tmp_buf;
4340     int ret;
4341
4342     MSVCRT__lock_file(file);
4343     tmp_buf = add_std_buffer(file);
4344     ret = pf_printf_w(puts_clbk_file_w, file, format, NULL, FALSE, FALSE, arg_clbk_valist, NULL, &valist);
4345     if(tmp_buf) remove_std_buffer(file);
4346     MSVCRT__unlock_file(file);
4347
4348     return ret;
4349 }
4350
4351 /*********************************************************************
4352  *              vfwprintf_s (MSVCRT.@)
4353  */
4354 int CDECL MSVCRT_vfwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, __ms_va_list valist)
4355 {
4356     BOOL tmp_buf;
4357     int ret;
4358
4359     if (!MSVCRT_CHECK_PMT( file != NULL )) return -1;
4360
4361     MSVCRT__lock_file(file);
4362     tmp_buf = add_std_buffer(file);
4363     ret = pf_printf_w(puts_clbk_file_w, file, format, NULL, FALSE, TRUE, arg_clbk_valist, NULL, &valist);
4364     if(tmp_buf) remove_std_buffer(file);
4365     MSVCRT__unlock_file(file);
4366
4367     return ret;
4368 }
4369
4370 /*********************************************************************
4371  *              _vfwprintf_l (MSVCRT.@)
4372  */
4373 int CDECL MSVCRT__vfwprintf_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format,
4374         MSVCRT__locale_t locale, __ms_va_list valist)
4375 {
4376     BOOL tmp_buf;
4377     int ret;
4378
4379     if (!MSVCRT_CHECK_PMT( file != NULL )) return -1;
4380
4381     MSVCRT__lock_file(file);
4382     tmp_buf = add_std_buffer(file);
4383     ret = pf_printf_w(puts_clbk_file_w, file, format, locale, FALSE, FALSE, arg_clbk_valist, NULL, &valist);
4384     if(tmp_buf) remove_std_buffer(file);
4385     MSVCRT__unlock_file(file);
4386
4387     return ret;
4388 }
4389
4390 /*********************************************************************
4391  *              vprintf (MSVCRT.@)
4392  */
4393 int CDECL MSVCRT_vprintf(const char *format, __ms_va_list valist)
4394 {
4395   return MSVCRT_vfprintf(MSVCRT_stdout,format,valist);
4396 }
4397
4398 /*********************************************************************
4399  *              vprintf_s (MSVCRT.@)
4400  */
4401 int CDECL MSVCRT_vprintf_s(const char *format, __ms_va_list valist)
4402 {
4403   return MSVCRT_vfprintf_s(MSVCRT_stdout,format,valist);
4404 }
4405
4406 /*********************************************************************
4407  *              vwprintf (MSVCRT.@)
4408  */
4409 int CDECL MSVCRT_vwprintf(const MSVCRT_wchar_t *format, __ms_va_list valist)
4410 {
4411   return MSVCRT_vfwprintf(MSVCRT_stdout,format,valist);
4412 }
4413
4414 /*********************************************************************
4415  *              vwprintf_s (MSVCRT.@)
4416  */
4417 int CDECL MSVCRT_vwprintf_s(const MSVCRT_wchar_t *format, __ms_va_list valist)
4418 {
4419   return MSVCRT_vfwprintf_s(MSVCRT_stdout,format,valist);
4420 }
4421
4422 /*********************************************************************
4423  *              fprintf (MSVCRT.@)
4424  */
4425 int CDECL MSVCRT_fprintf(MSVCRT_FILE* file, const char *format, ...)
4426 {
4427     __ms_va_list valist;
4428     int res;
4429     __ms_va_start(valist, format);
4430     res = MSVCRT_vfprintf(file, format, valist);
4431     __ms_va_end(valist);
4432     return res;
4433 }
4434
4435 /*********************************************************************
4436  *              fprintf_s (MSVCRT.@)
4437  */
4438 int CDECL MSVCRT_fprintf_s(MSVCRT_FILE* file, const char *format, ...)
4439 {
4440     __ms_va_list valist;
4441     int res;
4442     __ms_va_start(valist, format);
4443     res = MSVCRT_vfprintf_s(file, format, valist);
4444     __ms_va_end(valist);
4445     return res;
4446 }
4447
4448 /*********************************************************************
4449  *              fwprintf (MSVCRT.@)
4450  */
4451 int CDECL MSVCRT_fwprintf(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
4452 {
4453     __ms_va_list valist;
4454     int res;
4455     __ms_va_start(valist, format);
4456     res = MSVCRT_vfwprintf(file, format, valist);
4457     __ms_va_end(valist);
4458     return res;
4459 }
4460
4461 /*********************************************************************
4462  *              fwprintf_s (MSVCRT.@)
4463  */
4464 int CDECL MSVCRT_fwprintf_s(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, ...)
4465 {
4466     __ms_va_list valist;
4467     int res;
4468     __ms_va_start(valist, format);
4469     res = MSVCRT_vfwprintf_s(file, format, valist);
4470     __ms_va_end(valist);
4471     return res;
4472 }
4473
4474 /*********************************************************************
4475  *              _fwprintf_l (MSVCRT.@)
4476  */
4477 int CDECL MSVCRT__fwprintf_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
4478 {
4479     __ms_va_list valist;
4480     int res;
4481     __ms_va_start(valist, locale);
4482     res = MSVCRT__vfwprintf_l(file, format, locale, valist);
4483     __ms_va_end(valist);
4484     return res;
4485 }
4486
4487 /*********************************************************************
4488  *              printf (MSVCRT.@)
4489  */
4490 int CDECL MSVCRT_printf(const char *format, ...)
4491 {
4492     __ms_va_list valist;
4493     int res;
4494     __ms_va_start(valist, format);
4495     res = MSVCRT_vfprintf(MSVCRT_stdout, format, valist);
4496     __ms_va_end(valist);
4497     return res;
4498 }
4499
4500 /*********************************************************************
4501  *              printf_s (MSVCRT.@)
4502  */
4503 int CDECL MSVCRT_printf_s(const char *format, ...)
4504 {
4505     __ms_va_list valist;
4506     int res;
4507     __ms_va_start(valist, format);
4508     res = MSVCRT_vprintf_s(format, valist);
4509     __ms_va_end(valist);
4510     return res;
4511 }
4512
4513 /*********************************************************************
4514  *              ungetc (MSVCRT.@)
4515  */
4516 int CDECL MSVCRT_ungetc(int c, MSVCRT_FILE * file)
4517 {
4518     if (c == MSVCRT_EOF)
4519         return MSVCRT_EOF;
4520
4521     MSVCRT__lock_file(file);
4522     if(file->_bufsiz == 0 && msvcrt_alloc_buffer(file))
4523         file->_ptr++;
4524     if(file->_ptr>file->_base) {
4525         file->_ptr--;
4526         *file->_ptr=c;
4527         file->_cnt++;
4528         MSVCRT_clearerr(file);
4529         MSVCRT__unlock_file(file);
4530         return c;
4531     }
4532
4533     MSVCRT__unlock_file(file);
4534     return MSVCRT_EOF;
4535 }
4536
4537 /*********************************************************************
4538  *              ungetwc (MSVCRT.@)
4539  */
4540 MSVCRT_wint_t CDECL MSVCRT_ungetwc(MSVCRT_wint_t wc, MSVCRT_FILE * file)
4541 {
4542     MSVCRT_wchar_t mwc = wc;
4543     unsigned char * pp = (unsigned char *)&mwc;
4544     int i;
4545
4546     if (wc == MSVCRT_WEOF)
4547         return MSVCRT_WEOF;
4548
4549     MSVCRT__lock_file(file);
4550     for(i=sizeof(MSVCRT_wchar_t)-1;i>=0;i--) {
4551         if(pp[i] != MSVCRT_ungetc(pp[i],file)) {
4552             MSVCRT__unlock_file(file);
4553             return MSVCRT_WEOF;
4554         }
4555     }
4556
4557     MSVCRT__unlock_file(file);
4558     return mwc;
4559 }
4560
4561 /*********************************************************************
4562  *              wprintf (MSVCRT.@)
4563  */
4564 int CDECL MSVCRT_wprintf(const MSVCRT_wchar_t *format, ...)
4565 {
4566     __ms_va_list valist;
4567     int res;
4568     __ms_va_start(valist, format);
4569     res = MSVCRT_vwprintf(format, valist);
4570     __ms_va_end(valist);
4571     return res;
4572 }
4573
4574 /*********************************************************************
4575  *              wprintf_s (MSVCRT.@)
4576  */
4577 int CDECL MSVCRT_wprintf_s(const MSVCRT_wchar_t *format, ...)
4578 {
4579     __ms_va_list valist;
4580     int res;
4581     __ms_va_start(valist, format);
4582     res = MSVCRT_vwprintf_s(format, valist);
4583     __ms_va_end(valist);
4584     return res;
4585 }
4586
4587 /*********************************************************************
4588  *              _getmaxstdio (MSVCRT.@)
4589  */
4590 int CDECL MSVCRT__getmaxstdio(void)
4591 {
4592     return MSVCRT_max_streams;
4593 }
4594
4595 /*********************************************************************
4596  *              _setmaxstdio (MSVCRT.@)
4597  */
4598 int CDECL MSVCRT__setmaxstdio(int newmax)
4599 {
4600     TRACE("%d\n", newmax);
4601
4602     if(newmax<_IOB_ENTRIES || newmax>MSVCRT_MAX_FILES || newmax<MSVCRT_stream_idx)
4603         return -1;
4604
4605     MSVCRT_max_streams = newmax;
4606     return MSVCRT_max_streams;
4607 }