ReactOS  0.4.13-dev-257-gfabbd7c
file.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS CRT library
3  * LICENSE: LGPL - See COPYING in the top level directory
4  * FILE: lib/sdk/crt/stdio/file.c
5  * PURPOSE: File CRT functions
6  * PROGRAMMERS: Wine team
7  * Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org)
8  */
9 
10 /*********************************************
11  * This file contains ReactOS changes!!
12  * Don't blindly sync it with Wine code!
13  *
14  * If you break Unicode output on the console again, please update this counter:
15  * int hours_wasted_on_this = 42;
16  *********************************************/
17 
18 /*
19  * msvcrt.dll file functions
20  *
21  * Copyright 1996,1998 Marcus Meissner
22  * Copyright 1996 Jukka Iivonen
23  * Copyright 1997,2000 Uwe Bonnes
24  * Copyright 2000 Jon Griffiths
25  * Copyright 2004 Eric Pouech
26  * Copyright 2004 Juan Lang
27  *
28  * This library is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU Lesser General Public
30  * License as published by the Free Software Foundation; either
31  * version 2.1 of the License, or (at your option) any later version.
32  *
33  * This library is distributed in the hope that it will be useful,
34  * but WITHOUT ANY WARRANTY; without even the implied warranty of
35  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36  * Lesser General Public License for more details.
37  *
38  * You should have received a copy of the GNU Lesser General Public
39  * License along with this library; if not, write to the Free Software
40  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
41  *
42  * TODO
43  * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED
44  */
45 
46 #include <precomp.h>
47 #include "wine/unicode.h"
48 #include "internal/wine/msvcrt.h"
49 
50 #include <sys/utime.h>
51 #include <direct.h>
52 
53 int *__p__fmode(void);
54 int *__p___mb_cur_max(void);
55 
56 extern int _commode;
57 
58 #ifndef _IOCOMMIT
59 #define _IOCOMMIT 0x4000
60 #endif
61 
62 #ifdef feof
63 #undef feof
64 #endif
65 #ifdef _fileno
66 #undef _fileno
67 #endif
68 #ifdef ferror
69 #undef ferror
70 #endif
71 #ifdef clearerr
72 #undef clearerr
73 #endif
74 
75 #undef getc
76 #undef getwc
77 #undef getchar
78 #undef getwchar
79 #undef putc
80 #undef putwc
81 #undef putchar
82 #undef putwchar
83 
84 #undef vprintf
85 #undef vwprintf
86 
87 /* _access() bit flags FIXME: incomplete */
88 /* defined in crt/io.h */
89 
90 /* values for wxflag in file descriptor */
91 #define WX_OPEN 0x01
92 #define WX_ATEOF 0x02
93 #define WX_READNL 0x04 /* read started with \n */
94 #define WX_READEOF 0x04 /* like ATEOF, but for underlying file rather than buffer */
95 #define WX_PIPE 0x08
96 #define WX_READCR 0x08 /* underlying file is at \r */
97 #define WX_DONTINHERIT 0x10
98 #define WX_APPEND 0x20
99 #define WX_TTY 0x40
100 #define WX_TEXT 0x80
101 
102 /* values for exflag - it's used differently in msvcr90.dll*/
103 #define EF_UTF8 0x01
104 #define EF_UTF16 0x02
105 #define EF_CRIT_INIT 0x04
106 #define EF_UNK_UNICODE 0x08
107 
108 static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
109 static char utf16_bom[2] = { 0xff, 0xfe };
110 
111 /* FIXME: this should be allocated dynamically */
112 #define MSVCRT_MAX_FILES 2048
113 #define MSVCRT_FD_BLOCK_SIZE 32
114 
115 #define MSVCRT_INTERNAL_BUFSIZ 4096
116 
117 /*********************************************************************
118  * __pioinfo (MSVCRT.@)
119  * array of pointers to ioinfo arrays [32]
120  */
122 
123 /*********************************************************************
124  * __badioinfo (MSVCRT.@)
125  */
127 
128 typedef struct {
131 } file_crit;
132 
133 FILE _iob[_IOB_ENTRIES] = { { 0 } };
136 
137 /* INTERNAL: process umask */
138 static int MSVCRT_umask = 0;
139 
140 /* INTERNAL: static data for tmpnam and _wtmpname functions */
141 static int tmpnam_unique;
142 
143 /* This critical section protects the MSVCRT_fstreams table
144  * and MSVCRT_stream_idx from race conditions. It also
145  * protects fd critical sections creation code.
146  */
149 {
150  0, 0, &MSVCRT_file_cs,
152  0, 0, { (DWORD_PTR)(__FILE__ ": MSVCRT_file_cs") }
153 };
154 static CRITICAL_SECTION MSVCRT_file_cs = { &MSVCRT_file_cs_debug, -1, 0, 0, 0, 0 };
155 #define LOCK_FILES() do { EnterCriticalSection(&MSVCRT_file_cs); } while (0)
156 #define UNLOCK_FILES() do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0)
157 
158 static inline ioinfo* get_ioinfo_nolock(int fd)
159 {
160  ioinfo *ret = NULL;
161  if(fd>=0 && fd<MSVCRT_MAX_FILES)
163  if(!ret)
164  return &__badioinfo;
165 
166  return ret + (fd%MSVCRT_FD_BLOCK_SIZE);
167 }
168 
169 static inline void init_ioinfo_cs(ioinfo *info)
170 {
171  if(!(info->exflag & EF_CRIT_INIT)) {
172  LOCK_FILES();
173  if(!(info->exflag & EF_CRIT_INIT)) {
175  info->exflag |= EF_CRIT_INIT;
176  }
177  UNLOCK_FILES();
178  }
179 }
180 
182 {
184  if(ret == &__badioinfo)
185  return ret;
187  EnterCriticalSection(&ret->crit);
188  return ret;
189 }
190 
191 static inline BOOL alloc_pioinfo_block(int fd)
192 {
193  ioinfo *block;
194  int i;
195 
196  if(fd<0 || fd>=MSVCRT_MAX_FILES)
197  {
198  *_errno() = ENFILE;
199  return FALSE;
200  }
201 
203  if(!block)
204  {
205  WARN(":out of memory!\n");
206  *_errno() = ENOMEM;
207  return FALSE;
208  }
209  for(i=0; i<MSVCRT_FD_BLOCK_SIZE; i++)
212  free(block);
213  return TRUE;
214 }
215 
216 static inline ioinfo* get_ioinfo_alloc_fd(int fd)
217 {
218  ioinfo *ret;
219 
220  ret = get_ioinfo(fd);
221  if(ret != &__badioinfo)
222  return ret;
223 
224  if(!alloc_pioinfo_block(fd))
225  return &__badioinfo;
226 
227  return get_ioinfo(fd);
228 }
229 
230 static inline ioinfo* get_ioinfo_alloc(int *fd)
231 {
232  int i;
233 
234  *fd = -1;
235  for(i=0; i<MSVCRT_MAX_FILES; i++)
236  {
238 
239  if(info == &__badioinfo)
240  {
241  if(!alloc_pioinfo_block(i))
242  return &__badioinfo;
244  }
245 
247  if(TryEnterCriticalSection(&info->crit))
248  {
249  if(info->handle == INVALID_HANDLE_VALUE)
250  {
251  *fd = i;
252  return info;
253  }
254  LeaveCriticalSection(&info->crit);
255  }
256  }
257 
258  WARN(":files exhausted!\n");
259  *_errno() = ENFILE;
260  return &__badioinfo;
261 }
262 
264 {
265  if(info!=&__badioinfo && info->exflag & EF_CRIT_INIT)
266  LeaveCriticalSection(&info->crit);
267 }
268 
269 static inline FILE* msvcrt_get_file(int i)
270 {
271  file_crit *ret;
272 
273  if(i >= MSVCRT_max_streams)
274  return NULL;
275 
276  if(i < _IOB_ENTRIES)
277  return &_iob[i];
278 
280  if(!ret) {
283  ERR("out of memory\n");
284  *_errno() = ENOMEM;
285  return NULL;
286  }
287 
289  } else
291 
292  return &ret->file;
293 }
294 
295 /* INTERNAL: free a file entry fd */
296 static void msvcrt_free_fd(int fd)
297 {
298  ioinfo *fdinfo = get_ioinfo(fd);
299 
300  if(fdinfo != &__badioinfo)
301  {
302  fdinfo->handle = INVALID_HANDLE_VALUE;
303  fdinfo->wxflag = 0;
304  }
305  TRACE(":fd (%d) freed\n",fd);
306 
307  if (fd < 3)
308  {
309  switch (fd)
310  {
311  case 0:
313  break;
314  case 1:
316  break;
317  case 2:
319  break;
320  }
321  }
322  release_ioinfo(fdinfo);
323 }
324 
325 static void msvcrt_set_fd(ioinfo *fdinfo, HANDLE hand, int flag)
326 {
327  fdinfo->handle = hand;
328  fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT | WX_PIPE | WX_TTY));
329  fdinfo->lookahead[0] = '\n';
330  fdinfo->lookahead[1] = '\n';
331  fdinfo->lookahead[2] = '\n';
332  fdinfo->exflag &= EF_CRIT_INIT;
333 
334  switch (fdinfo-__pioinfo[0])
335  {
336  case 0: SetStdHandle(STD_INPUT_HANDLE, hand); break;
337  case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
338  case 2: SetStdHandle(STD_ERROR_HANDLE, hand); break;
339  }
340 }
341 
342 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
343 /*static*/ int msvcrt_alloc_fd(HANDLE hand, int flag)
344 {
345  int fd;
347 
348  TRACE(":handle (%p) allocating fd (%d)\n", hand, fd);
349 
350  if(info == &__badioinfo)
351  return -1;
352 
353  msvcrt_set_fd(info, hand, flag);
355  return fd;
356 }
357 
358 /* INTERNAL: Allocate a FILE* for an fd slot */
359 /* caller must hold the files lock */
360 static FILE* msvcrt_alloc_fp(void)
361 {
362  int i;
363  FILE *file;
364 
365  for (i = 3; i < MSVCRT_max_streams; i++)
366  {
368  if (!file)
369  return NULL;
370 
371  if (file->_flag == 0)
372  {
374  return file;
375  }
376  }
377 
378  return NULL;
379 }
380 
381 /* INTERNAL: initialize a FILE* from an open fd */
382 static int msvcrt_init_fp(FILE* file, int fd, unsigned stream_flags)
383 {
384  TRACE(":fd (%d) allocating FILE*\n",fd);
385  if (!(get_ioinfo_nolock(fd)->wxflag & WX_OPEN))
386  {
387  WARN(":invalid fd %d\n",fd);
388  *__doserrno() = 0;
389  *_errno() = EBADF;
390  return -1;
391  }
392  file->_ptr = file->_base = NULL;
393  file->_cnt = 0;
394  file->_file = fd;
395  file->_flag = stream_flags;
396  file->_tmpfname = NULL;
397 
400 
401  TRACE(":got FILE* (%p)\n",file);
402  return 0;
403 }
404 
405 /* INTERNAL: Create an inheritance data block (for spawned process)
406  * The inheritance block is made of:
407  * 00 int nb of file descriptor (NBFD)
408  * 04 char file flags (wxflag): repeated for each fd
409  * 4+NBFD HANDLE file handle: repeated for each fd
410  */
412 {
413  int fd, last_fd;
414  char* wxflag_ptr;
415  HANDLE* handle_ptr;
416  ioinfo* fdinfo;
417 
418  for (last_fd=MSVCRT_MAX_FILES-1; last_fd>=0; last_fd--)
420  break;
421  last_fd++;
422 
423  *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * last_fd;
424  *block = calloc(1, *size);
425  if (!*block)
426  {
427  *size = 0;
428  return FALSE;
429  }
430  wxflag_ptr = (char*)*block + sizeof(unsigned);
431  handle_ptr = (HANDLE*)(wxflag_ptr + last_fd);
432 
433  *(unsigned*)*block = last_fd;
434  for (fd = 0; fd < last_fd; fd++)
435  {
436  /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
437  fdinfo = get_ioinfo(fd);
438  if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN)
439  {
440  *wxflag_ptr = fdinfo->wxflag;
441  *handle_ptr = fdinfo->handle;
442  }
443  else
444  {
445  *wxflag_ptr = 0;
446  *handle_ptr = INVALID_HANDLE_VALUE;
447  }
448  release_ioinfo(fdinfo);
449  wxflag_ptr++; handle_ptr++;
450  }
451  return TRUE;
452 }
453 
454 /* INTERNAL: Set up all file descriptors,
455  * as well as default streams (stdin, stderr and stdout)
456  */
457 void msvcrt_init_io(void)
458 {
459  STARTUPINFOA si;
460  unsigned int i;
461  ioinfo *fdinfo;
462 
463  GetStartupInfoA(&si);
464  if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
465  {
466  BYTE* wxflag_ptr;
467  HANDLE* handle_ptr;
468  unsigned int count;
469 
470  count = *(unsigned*)si.lpReserved2;
471  wxflag_ptr = si.lpReserved2 + sizeof(unsigned);
472  handle_ptr = (HANDLE*)(wxflag_ptr + count);
473 
474  count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1));
476  for (i = 0; i < count; i++)
477  {
478  if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
479  {
480  fdinfo = get_ioinfo_alloc_fd(i);
481  if(fdinfo != &__badioinfo)
482  msvcrt_set_fd(fdinfo, *handle_ptr, *wxflag_ptr);
483  release_ioinfo(fdinfo);
484  }
485 
486  wxflag_ptr++; handle_ptr++;
487  }
488  }
489 
491  if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
493  DWORD type = GetFileType(h);
494 
495  msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
496  |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
497  }
498  release_ioinfo(fdinfo);
499 
501  if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
503  DWORD type = GetFileType(h);
504 
505  msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
506  |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
507  }
508  release_ioinfo(fdinfo);
509 
511  if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE) {
513  DWORD type = GetFileType(h);
514 
515  msvcrt_set_fd(fdinfo, h, WX_OPEN|WX_TEXT|((type&0xf)==FILE_TYPE_CHAR ? WX_TTY : 0)
516  |((type&0xf)==FILE_TYPE_PIPE ? WX_PIPE : 0));
517  }
518  release_ioinfo(fdinfo);
519 
520  TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo_nolock(STDIN_FILENO)->handle,
523 
524  memset(_iob,0,3*sizeof(FILE));
525  for (i = 0; i < 3; i++)
526  {
527  /* FILE structs for stdin/out/err are static and never deleted */
528  _iob[i]._file = i;
529  _iob[i]._tmpfname = NULL;
530  _iob[i]._flag = (i == 0) ? _IOREAD : _IOWRT;
531  }
532  MSVCRT_stream_idx = 3;
533 }
534 
535 /* INTERNAL: Flush stdio file buffer */
537 {
538  if((file->_flag & (_IOREAD|_IOWRT)) == _IOWRT &&
539  file->_flag & (_IOMYBUF|_USERBUF)) {
540  int cnt=file->_ptr-file->_base;
541  if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
542  file->_flag |= _IOERR;
543  return EOF;
544  }
545 
546  if(file->_flag & _IORW)
547  file->_flag &= ~_IOWRT;
548 
549 #ifdef __REACTOS__ /* CORE-11949 */
550  file->_ptr=file->_base;
551  file->_cnt=0;
552 #endif
553  }
554 
555 #ifndef __REACTOS__ /* CORE-11949 */
556  file->_ptr=file->_base;
557  file->_cnt=0;
558 #endif
559  return 0;
560 }
561 
562 /*********************************************************************
563  * _isatty (MSVCRT.@)
564  */
565 int CDECL _isatty(int fd)
566 {
567  TRACE(":fd (%d)\n",fd);
568 
569  return get_ioinfo_nolock(fd)->wxflag & WX_TTY;
570 }
571 
572 /* INTERNAL: Allocate stdio file buffer */
574 {
575  if((file->_file==STDOUT_FILENO || file->_file==STDERR_FILENO)
576  && _isatty(file->_file))
577  return FALSE;
578 
579  file->_base = calloc(1, MSVCRT_INTERNAL_BUFSIZ);
580  if(file->_base) {
581  file->_bufsiz = MSVCRT_INTERNAL_BUFSIZ;
582  file->_flag |= _IOMYBUF;
583  } else {
584  file->_base = (char*)(&file->_charbuf);
585  file->_bufsiz = 2;
586  file->_flag |= _IONBF;
587  }
588  file->_ptr = file->_base;
589  file->_cnt = 0;
590  return TRUE;
591 }
592 
593 /* INTERNAL: Allocate temporary buffer for stdout and stderr */
595 {
596  static char buffers[2][BUFSIZ];
597 
598  if((file->_file!=STDOUT_FILENO && file->_file!=STDERR_FILENO)
599  || (file->_flag & (_IONBF | _IOMYBUF | _USERBUF))
600  || !_isatty(file->_file))
601  return FALSE;
602 
603  file->_ptr = file->_base = buffers[file->_file == STDOUT_FILENO ? 0 : 1];
604  file->_bufsiz = file->_cnt = BUFSIZ;
605  file->_flag |= _USERBUF;
606  return TRUE;
607 }
608 
609 /* INTERNAL: Removes temporary buffer from stdout or stderr */
610 /* Only call this function when add_std_buffer returned TRUE */
612 {
614  file->_ptr = file->_base = NULL;
615  file->_bufsiz = file->_cnt = 0;
616  file->_flag &= ~_USERBUF;
617 }
618 
619 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
620 static int msvcrt_int_to_base32(int num, char *str)
621 {
622  char *p;
623  int n = num;
624  int digits = 0;
625 
626  while (n != 0)
627  {
628  n >>= 5;
629  digits++;
630  }
631  p = str + digits;
632  *p = 0;
633  while (--p >= str)
634  {
635  *p = (num & 31) + '0';
636  if (*p > '9')
637  *p += ('a' - '0' - 10);
638  num >>= 5;
639  }
640 
641  return digits;
642 }
643 
644 /* INTERNAL: wide character version of msvcrt_int_to_base32 */
645 static int msvcrt_int_to_base32_w(int num, wchar_t *str)
646 {
647  wchar_t *p;
648  int n = num;
649  int digits = 0;
650 
651  while (n != 0)
652  {
653  n >>= 5;
654  digits++;
655  }
656  p = str + digits;
657  *p = 0;
658  while (--p >= str)
659  {
660  *p = (num & 31) + '0';
661  if (*p > '9')
662  *p += ('a' - '0' - 10);
663  num >>= 5;
664  }
665 
666  return digits;
667 }
668 
669 /* INTERNAL: Create a wide string from an ascii string */
670 wchar_t *msvcrt_wstrdupa(const char *str)
671 {
672  const unsigned int len = strlen(str) + 1 ;
673  wchar_t *wstr = malloc(len* sizeof (wchar_t));
674  if (!wstr)
675  return NULL;
677  return wstr;
678 }
679 
680 /*********************************************************************
681  * __iob_func(MSVCRT.@)
682  */
684 {
685  return &_iob[0];
686 }
687 
688 /*********************************************************************
689  * _access (MSVCRT.@)
690  */
691 int CDECL _access(const char *filename, int mode)
692 {
694 
695  TRACE("(%s,%d) %d\n",filename,mode,attr);
696 
698  {
700  return -1;
701  }
702  if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
703  {
705  return -1;
706  }
707  return 0;
708 }
709 
710 /*********************************************************************
711  * _access_s (MSVCRT.@)
712  */
713 int CDECL _access_s(const char *filename, int mode)
714 {
715  if (!MSVCRT_CHECK_PMT(filename != NULL) ||
716  !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0))
717  {
719  return -1;
720  }
721 
722  return _access(filename, mode);
723 }
724 
725 /*********************************************************************
726  * _waccess (MSVCRT.@)
727  */
728 int CDECL _waccess(const wchar_t *filename, int mode)
729 {
731 
732  TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr);
733 
735  {
737  return -1;
738  }
739  if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
740  {
742  return -1;
743  }
744  return 0;
745 }
746 
747 /*********************************************************************
748  * _waccess_s (MSVCRT.@)
749  */
750 int CDECL _waccess_s(const wchar_t *filename, int mode)
751 {
752  if (!MSVCRT_CHECK_PMT(filename != NULL) ||
753  !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0))
754  {
755  *_errno() = EINVAL;
756  return -1;
757  }
758 
759  return _waccess(filename, mode);
760 }
761 
762 /*********************************************************************
763  * _chmod (MSVCRT.@)
764  */
765 int CDECL _chmod(const char *path, int flags)
766 {
767  DWORD oldFlags = GetFileAttributesA(path);
768 
769  if (oldFlags != INVALID_FILE_ATTRIBUTES)
770  {
771  DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
772  oldFlags | FILE_ATTRIBUTE_READONLY;
773 
774  if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
775  return 0;
776  }
778  return -1;
779 }
780 
781 /*********************************************************************
782  * _wchmod (MSVCRT.@)
783  */
784 int CDECL _wchmod(const wchar_t *path, int flags)
785 {
786  DWORD oldFlags = GetFileAttributesW(path);
787 
788  if (oldFlags != INVALID_FILE_ATTRIBUTES)
789  {
790  DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
791  oldFlags | FILE_ATTRIBUTE_READONLY;
792 
793  if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
794  return 0;
795  }
797  return -1;
798 }
799 
800 /*********************************************************************
801  * _unlink (MSVCRT.@)
802  */
803 int CDECL _unlink(const char *path)
804 {
805  TRACE("%s\n",debugstr_a(path));
806  if(DeleteFileA(path))
807  return 0;
808  TRACE("failed (%d)\n",GetLastError());
810  return -1;
811 }
812 
813 /*********************************************************************
814  * _wunlink (MSVCRT.@)
815  */
816 int CDECL _wunlink(const wchar_t *path)
817 {
818  TRACE("(%s)\n",debugstr_w(path));
819  if(DeleteFileW(path))
820  return 0;
821  TRACE("failed (%d)\n",GetLastError());
823  return -1;
824 }
825 
826 /*********************************************************************
827  * _commit (MSVCRT.@)
828  */
829 int CDECL _commit(int fd)
830 {
831  ioinfo *info = get_ioinfo(fd);
832  int ret;
833 
834  TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
835  if (info->handle == INVALID_HANDLE_VALUE)
836  ret = -1;
837  else if (!FlushFileBuffers(info->handle))
838  {
840  {
841  /* FlushFileBuffers fails for console handles
842  * so we ignore this error.
843  */
844  ret = 0;
845  }
846  else
847  {
848  TRACE(":failed-last error (%d)\n",GetLastError());
850  ret = -1;
851  }
852  }
853  else
854  {
855  TRACE(":ok\n");
856  ret = 0;
857  }
858 
860  return ret;
861 }
862 
863 /* _flushall calls fflush which calls _flushall */
864 int CDECL fflush(FILE* file);
865 
866 /* INTERNAL: Flush all stream buffer */
868 {
869  int i, num_flushed = 0;
870  FILE *file;
871 
872  LOCK_FILES();
873  for (i = 0; i < MSVCRT_stream_idx; i++) {
875 
876  if (file->_flag)
877  {
878  if(file->_flag & mask) {
879  fflush(file);
880  num_flushed++;
881  }
882  }
883  }
884  UNLOCK_FILES();
885 
886  TRACE(":flushed (%d) handles\n",num_flushed);
887  return num_flushed;
888 }
889 
890 /*********************************************************************
891  * _flushall (MSVCRT.@)
892  */
893 int CDECL _flushall(void)
894 {
896 }
897 
898 /*********************************************************************
899  * fflush (MSVCRT.@)
900  */
902 {
903  if(!file) {
905  } else if(file->_flag & _IOWRT) {
906  int res;
907 
908  _lock_file(file);
910  /* FIXME
911  if(!res && (file->_flag & _IOCOMMIT))
912  res = _commit(file->_file) ? EOF : 0;
913  */
915 
916  return res;
917  } else if(file->_flag & _IOREAD) {
918  _lock_file(file);
919  file->_cnt = 0;
920  file->_ptr = file->_base;
922 
923  return 0;
924  }
925  return 0;
926 }
927 
928 /*********************************************************************
929  * _close (MSVCRT.@)
930  */
931 int CDECL _close(int fd)
932 {
933  ioinfo *info = get_ioinfo(fd);
934  int ret;
935 
936  TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
937  if (!(info->wxflag & WX_OPEN)) {
938  ret = -1;
939  } else if (fd == STDOUT_FILENO &&
942  ret = 0;
943  } else if (fd == STDERR_FILENO &&
946  ret = 0;
947  } else {
948  ret = CloseHandle(info->handle) ? 0 : -1;
950  if (ret) {
951  WARN(":failed-last error (%d)\n",GetLastError());
953  ret = -1;
954  }
955  }
957  return ret;
958 }
959 
960 /*********************************************************************
961  * _dup2 (MSVCRT.@)
962  * NOTES
963  * MSDN isn't clear on this point, but the remarks for _pipe
964  * indicate file descriptors duplicated with _dup and _dup2 are always
965  * inheritable.
966  */
967 int CDECL _dup2(int od, int nd)
968 {
969  ioinfo *info_od, *info_nd;
970  int ret;
971 
972  TRACE("(od=%d, nd=%d)\n", od, nd);
973 
974  if (od < nd)
975  {
976  info_od = get_ioinfo(od);
977  info_nd = get_ioinfo_alloc_fd(nd);
978  }
979  else
980  {
981  info_nd = get_ioinfo_alloc_fd(nd);
982  info_od = get_ioinfo(od);
983  }
984 
985  if (info_nd == &__badioinfo)
986  {
987  ret = -1;
988  }
989  else if (info_od->wxflag & WX_OPEN)
990  {
991  HANDLE handle;
992 
993  if (DuplicateHandle(GetCurrentProcess(), info_od->handle,
995  {
996  int wxflag = info_od->wxflag & ~_O_NOINHERIT;
997 
998  if (info_nd->wxflag & WX_OPEN)
999  _close(nd);
1000 
1001  msvcrt_set_fd(info_nd, handle, wxflag);
1002  /* _dup2 returns 0, not nd, on success */
1003  ret = 0;
1004  }
1005  else
1006  {
1007  ret = -1;
1009  }
1010  }
1011  else
1012  {
1013  *_errno() = EBADF;
1014  ret = -1;
1015  }
1016 
1017  release_ioinfo(info_od);
1018  release_ioinfo(info_nd);
1019  return ret;
1020 }
1021 
1022 /*********************************************************************
1023  * _dup (MSVCRT.@)
1024  */
1025 int CDECL _dup(int od)
1026 {
1027  int fd, ret;
1029 
1030  if (_dup2(od, fd) == 0)
1031  ret = fd;
1032  else
1033  ret = -1;
1035  return ret;
1036 }
1037 
1038 /*********************************************************************
1039  * _eof (MSVCRT.@)
1040  */
1041 int CDECL _eof(int fd)
1042 {
1043  ioinfo *info = get_ioinfo(fd);
1044  DWORD curpos,endpos;
1045  LONG hcurpos,hendpos;
1046 
1047  TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1048 
1049  if (info->handle == INVALID_HANDLE_VALUE)
1050  {
1052  return -1;
1053  }
1054 
1055  if (info->wxflag & WX_ATEOF)
1056  {
1058  return TRUE;
1059  }
1060 
1061  /* Otherwise we do it the hard way */
1062  hcurpos = hendpos = 0;
1063  curpos = SetFilePointer(info->handle, 0, &hcurpos, FILE_CURRENT);
1064  endpos = SetFilePointer(info->handle, 0, &hendpos, FILE_END);
1065 
1066  if (curpos == endpos && hcurpos == hendpos)
1067  {
1068  /* FIXME: shouldn't WX_ATEOF be set here? */
1070  return TRUE;
1071  }
1072 
1073  SetFilePointer(info->handle, curpos, &hcurpos, FILE_BEGIN);
1075  return FALSE;
1076 }
1077 
1078 /*********************************************************************
1079  * _fcloseall (MSVCRT.@)
1080  */
1082 {
1083  int num_closed = 0, i;
1084  FILE *file;
1085 
1086  LOCK_FILES();
1087  for (i = 3; i < MSVCRT_stream_idx; i++) {
1088  file = msvcrt_get_file(i);
1089 
1090  if (file->_flag && !fclose(file))
1091  num_closed++;
1092  }
1093  UNLOCK_FILES();
1094 
1095  TRACE(":closed (%d) handles\n",num_closed);
1096  return num_closed;
1097 }
1098 
1099 /* free everything on process exit */
1100 void msvcrt_free_io(void)
1101 {
1102  unsigned int i;
1103  int j;
1104 
1105  _flushall();
1106  _fcloseall();
1107 
1108  for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++)
1109  {
1110  if(!__pioinfo[i])
1111  continue;
1112 
1113  for(j=0; j<MSVCRT_FD_BLOCK_SIZE; j++)
1114  {
1115  if(__pioinfo[i][j].exflag & EF_CRIT_INIT)
1117  }
1118  free(__pioinfo[i]);
1119  }
1120 
1121  for(j=0; j<MSVCRT_stream_idx; j++)
1122  {
1123  FILE *file = msvcrt_get_file(j);
1125  {
1126  ((file_crit*)file)->crit.DebugInfo->Spare[0] = 0;
1127  DeleteCriticalSection(&((file_crit*)file)->crit);
1128  }
1129  }
1130 
1131  for(i=0; i<sizeof(MSVCRT_fstream)/sizeof(MSVCRT_fstream[0]); i++)
1132  free(MSVCRT_fstream[i]);
1133 }
1134 
1135 /*********************************************************************
1136  * _lseeki64 (MSVCRT.@)
1137  */
1139 {
1140  ioinfo *info = get_ioinfo(fd);
1141  LARGE_INTEGER ofs;
1142 
1143  TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1144 
1145  if (info->handle == INVALID_HANDLE_VALUE)
1146  {
1148  return -1;
1149  }
1150 
1151  if (whence < 0 || whence > 2)
1152  {
1154  *_errno() = EINVAL;
1155  return -1;
1156  }
1157 
1158  TRACE(":fd (%d) to %s pos %s\n",
1160  (whence==SEEK_SET)?"SEEK_SET":
1161  (whence==SEEK_CUR)?"SEEK_CUR":
1162  (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
1163 
1164  /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
1165  * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
1166  ofs.QuadPart = offset;
1167  if ((ofs.u.LowPart = SetFilePointer(info->handle, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
1169  {
1170  info->wxflag &= ~(WX_ATEOF|WX_READEOF);
1171  /* FIXME: What if we seek _to_ EOF - is EOF set? */
1172 
1174  return ofs.QuadPart;
1175  }
1177  TRACE(":error-last error (%d)\n",GetLastError());
1179  return -1;
1180 }
1181 
1182 /*********************************************************************
1183  * _lseek (MSVCRT.@)
1184  */
1185 LONG CDECL _lseek(int fd, LONG offset, int whence)
1186 {
1187  return (LONG)_lseeki64(fd, offset, whence);
1188 }
1189 
1190 /*********************************************************************
1191  * _lock_file (MSVCRT.@)
1192  */
1194 {
1195  if(file>=_iob && file<_iob+_IOB_ENTRIES)
1197  /* ReactOS: string streams dont need to be locked */
1198  else if(!(file->_flag & _IOSTRG))
1199  EnterCriticalSection(&((file_crit*)file)->crit);
1200 }
1201 
1202 /*********************************************************************
1203  * _unlock_file (MSVCRT.@)
1204  */
1206 {
1207  if(file>=_iob && file<_iob+_IOB_ENTRIES)
1209  /* ReactOS: string streams dont need to be locked */
1210  else if(!(file->_flag & _IOSTRG))
1211  LeaveCriticalSection(&((file_crit*)file)->crit);
1212 
1213 }
1214 
1215 /*********************************************************************
1216  * _locking (MSVCRT.@)
1217  *
1218  * This is untested; the underlying LockFile doesn't work yet.
1219  */
1220 int CDECL _locking(int fd, int mode, LONG nbytes)
1221 {
1222  ioinfo *info = get_ioinfo(fd);
1223  BOOL ret;
1224  DWORD cur_locn;
1225 
1226  TRACE(":fd (%d) handle (%p)\n", fd, info->handle);
1227  if (info->handle == INVALID_HANDLE_VALUE)
1228  {
1230  return -1;
1231  }
1232 
1233  if (mode < 0 || mode > 4)
1234  {
1236  *_errno() = EINVAL;
1237  return -1;
1238  }
1239 
1240  TRACE(":fd (%d) by 0x%08x mode %s\n",
1241  fd,nbytes,(mode==_LK_UNLCK)?"_LK_UNLCK":
1242  (mode==_LK_LOCK)?"_LK_LOCK":
1243  (mode==_LK_NBLCK)?"_LK_NBLCK":
1244  (mode==_LK_RLCK)?"_LK_RLCK":
1245  (mode==_LK_NBRLCK)?"_LK_NBRLCK":
1246  "UNKNOWN");
1247 
1248  if ((cur_locn = SetFilePointer(info->handle, 0L, NULL, FILE_CURRENT)) == INVALID_SET_FILE_POINTER)
1249  {
1251  FIXME ("Seek failed\n");
1252  *_errno() = EINVAL; /* FIXME */
1253  return -1;
1254  }
1255  if (mode == _LK_LOCK || mode == _LK_RLCK)
1256  {
1257  int nretry = 10;
1258  ret = 1; /* just to satisfy gcc */
1259  while (nretry--)
1260  {
1261  ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1262  if (ret) break;
1263  Sleep(1);
1264  }
1265  }
1266  else if (mode == _LK_UNLCK)
1267  ret = UnlockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1268  else
1269  ret = LockFile(info->handle, cur_locn, 0L, nbytes, 0L);
1270  /* FIXME - what about error settings? */
1272  return ret ? 0 : -1;
1273 }
1274 
1275 /*********************************************************************
1276  * _fseeki64 (MSVCRT.@)
1277  */
1279 {
1280  int ret;
1281 
1282  _lock_file(file);
1283  /* Flush output if needed */
1284  if(file->_flag & _IOWRT)
1286 
1287  if(whence == SEEK_CUR && file->_flag & _IOREAD ) {
1288  whence = SEEK_SET;
1289  offset += _ftelli64(file);
1290  }
1291 
1292  /* Discard buffered input */
1293  file->_cnt = 0;
1294  file->_ptr = file->_base;
1295  /* Reset direction of i/o */
1296  if(file->_flag & _IORW) {
1297  file->_flag &= ~(_IOREAD|_IOWRT);
1298  }
1299  /* Clear end of file flag */
1300  file->_flag &= ~_IOEOF;
1301  ret = (_lseeki64(file->_file,offset,whence) == -1)?-1:0;
1302 
1303  _unlock_file(file);
1304  return ret;
1305 }
1306 
1307 /*********************************************************************
1308  * fseek (MSVCRT.@)
1309  */
1310 int CDECL fseek(FILE* file, long offset, int whence)
1311 {
1312  return _fseeki64( file, offset, whence );
1313 }
1314 
1315 /*********************************************************************
1316  * _chsize_s (MSVCRT.@)
1317  */
1319 {
1320  ioinfo *info;
1321  __int64 cur, pos;
1322  BOOL ret = FALSE;
1323 
1324  TRACE("(fd=%d, size=%s)\n", fd, wine_dbgstr_longlong(size));
1325 
1326  if (!MSVCRT_CHECK_PMT(size >= 0)) return EINVAL;
1327 
1328  info = get_ioinfo(fd);
1329  if (info->handle != INVALID_HANDLE_VALUE)
1330  {
1331  /* save the current file pointer */
1332  cur = _lseeki64(fd, 0, SEEK_CUR);
1333  if (cur >= 0)
1334  {
1335  pos = _lseeki64(fd, size, SEEK_SET);
1336  if (pos >= 0)
1337  {
1338  ret = SetEndOfFile(info->handle);
1339  if (!ret) _dosmaperr(GetLastError());
1340  }
1341 
1342  /* restore the file pointer */
1343  _lseeki64(fd, cur, SEEK_SET);
1344  }
1345  }
1346 
1348  return ret ? 0 : *_errno();
1349 }
1350 
1351 /*********************************************************************
1352  * _chsize (MSVCRT.@)
1353  */
1354 int CDECL _chsize(int fd, long size)
1355 {
1356  /* _chsize_s returns errno on failure but _chsize should return -1 */
1357  return _chsize_s( fd, size ) == 0 ? 0 : -1;
1358 }
1359 
1360 /*********************************************************************
1361  * clearerr (MSVCRT.@)
1362  */
1364 {
1365  TRACE(":file (%p) fd (%d)\n",file,file->_file);
1366 
1367  _lock_file(file);
1368  file->_flag &= ~(_IOERR | _IOEOF);
1369  _unlock_file(file);
1370 }
1371 
1372 /*********************************************************************
1373  * rewind (MSVCRT.@)
1374  */
1376 {
1377  TRACE(":file (%p) fd (%d)\n",file,file->_file);
1378 
1379  _lock_file(file);
1380  fseek(file, 0L, SEEK_SET);
1381  clearerr(file);
1382  _unlock_file(file);
1383 }
1384 
1385 static int msvcrt_get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
1386 {
1387  int plus = strchrW(mode, '+') != NULL;
1388 
1389  TRACE("%s\n", debugstr_w(mode));
1390 
1391  while(*mode == ' ') mode++;
1392 
1393  switch(*mode++)
1394  {
1395  case 'R': case 'r':
1396  *open_flags = plus ? _O_RDWR : _O_RDONLY;
1397  *stream_flags = plus ? _IORW : _IOREAD;
1398  break;
1399  case 'W': case 'w':
1400  *open_flags = _O_CREAT | _O_TRUNC | (plus ? _O_RDWR : _O_WRONLY);
1401  *stream_flags = plus ? _IORW : _IOWRT;
1402  break;
1403  case 'A': case 'a':
1404  *open_flags = _O_CREAT | _O_APPEND | (plus ? _O_RDWR : _O_WRONLY);
1405  *stream_flags = plus ? _IORW : _IOWRT;
1406  break;
1407  default:
1409  return -1;
1410  }
1411 
1412  *stream_flags |= _commode;
1413 
1414  while (*mode && *mode!=',')
1415  switch (*mode++)
1416  {
1417  case 'B': case 'b':
1418  *open_flags |= _O_BINARY;
1419  *open_flags &= ~_O_TEXT;
1420  break;
1421  case 't':
1422  *open_flags |= _O_TEXT;
1423  *open_flags &= ~_O_BINARY;
1424  break;
1425  case 'D':
1426  *open_flags |= _O_TEMPORARY;
1427  break;
1428  case 'T':
1429  *open_flags |= _O_SHORT_LIVED;
1430  break;
1431  case 'c':
1432  *stream_flags |= _IOCOMMIT;
1433  break;
1434  case 'n':
1435  *stream_flags &= ~_IOCOMMIT;
1436  break;
1437  case 'N':
1438  *open_flags |= _O_NOINHERIT;
1439  break;
1440  case '+':
1441  case ' ':
1442  case 'a':
1443  case 'w':
1444  break;
1445  case 'S':
1446  case 'R':
1447  FIXME("ignoring cache optimization flag: %c\n", mode[-1]);
1448  break;
1449  default:
1450  ERR("incorrect mode flag: %c\n", mode[-1]);
1451  break;
1452  }
1453 
1454  if(*mode == ',')
1455  {
1456  static const WCHAR ccs[] = {'c','c','s'};
1457  static const WCHAR utf8[] = {'u','t','f','-','8'};
1458  static const WCHAR utf16le[] = {'u','t','f','-','1','6','l','e'};
1459  static const WCHAR unicode[] = {'u','n','i','c','o','d','e'};
1460 
1461  mode++;
1462  while(*mode == ' ') mode++;
1463  if(!MSVCRT_CHECK_PMT(!strncmpW(ccs, mode, sizeof(ccs)/sizeof(ccs[0]))))
1464  return -1;
1465  mode += sizeof(ccs)/sizeof(ccs[0]);
1466  while(*mode == ' ') mode++;
1467  if(!MSVCRT_CHECK_PMT(*mode == '='))
1468  return -1;
1469  mode++;
1470  while(*mode == ' ') mode++;
1471 
1472  if(!strncmpiW(utf8, mode, sizeof(utf8)/sizeof(utf8[0])))
1473  {
1474  *open_flags |= _O_U8TEXT;
1475  mode += sizeof(utf8)/sizeof(utf8[0]);
1476  }
1477  else if(!strncmpiW(utf16le, mode, sizeof(utf16le)/sizeof(utf16le[0])))
1478  {
1479  *open_flags |= _O_U16TEXT;
1480  mode += sizeof(utf16le)/sizeof(utf16le[0]);
1481  }
1482  else if(!strncmpiW(unicode, mode, sizeof(unicode)/sizeof(unicode[0])))
1483  {
1484  *open_flags |= _O_WTEXT;
1485  mode += sizeof(unicode)/sizeof(unicode[0]);
1486  }
1487  else
1488  {
1490  return -1;
1491  }
1492 
1493  while(*mode == ' ') mode++;
1494  }
1495 
1496  if(!MSVCRT_CHECK_PMT(*mode == 0))
1497  return -1;
1498  return 0;
1499 }
1500 
1501 /*********************************************************************
1502  * _fdopen (MSVCRT.@)
1503  */
1504 FILE* CDECL _fdopen(int fd, const char *mode)
1505 {
1506  FILE *ret;
1507  wchar_t *modeW = NULL;
1508 
1509  if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
1510 
1511  ret = _wfdopen(fd, modeW);
1512 
1513  free(modeW);
1514  return ret;
1515 }
1516 
1517 /*********************************************************************
1518  * _wfdopen (MSVCRT.@)
1519  */
1520 FILE* CDECL _wfdopen(int fd, const wchar_t *mode)
1521 {
1522  int open_flags, stream_flags;
1523  FILE* file;
1524 
1525  if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
1526 
1527  LOCK_FILES();
1528  if (!(file = msvcrt_alloc_fp()))
1529  file = NULL;
1530  else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
1531  {
1532  file->_flag = 0;
1533  file = NULL;
1534  }
1535  else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
1536  UNLOCK_FILES();
1537 
1538  return file;
1539 }
1540 
1541 /*********************************************************************
1542  * _filelength (MSVCRT.@)
1543  */
1545 {
1546  LONG curPos = _lseek(fd, 0, SEEK_CUR);
1547  if (curPos != -1)
1548  {
1549  LONG endPos = _lseek(fd, 0, SEEK_END);
1550  if (endPos != -1)
1551  {
1552  if (endPos != curPos)
1553  _lseek(fd, curPos, SEEK_SET);
1554  return endPos;
1555  }
1556  }
1557  return -1;
1558 }
1559 
1560 /*********************************************************************
1561  * _filelengthi64 (MSVCRT.@)
1562  */
1564 {
1565  __int64 curPos = _lseeki64(fd, 0, SEEK_CUR);
1566  if (curPos != -1)
1567  {
1568  __int64 endPos = _lseeki64(fd, 0, SEEK_END);
1569  if (endPos != -1)
1570  {
1571  if (endPos != curPos)
1572  _lseeki64(fd, curPos, SEEK_SET);
1573  return endPos;
1574  }
1575  }
1576  return -1;
1577 }
1578 
1579 /*********************************************************************
1580  * _fileno (MSVCRT.@)
1581  */
1583 {
1584  TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
1585  return file->_file;
1586 }
1587 
1588 /*********************************************************************
1589  * _get_osfhandle (MSVCRT.@)
1590  */
1592 {
1593  HANDLE hand = get_ioinfo_nolock(fd)->handle;
1594  TRACE(":fd (%d) handle (%p)\n",fd,hand);
1595 
1596  if(hand == INVALID_HANDLE_VALUE)
1597  *_errno() = EBADF;
1598  return (intptr_t)hand;
1599 }
1600 
1601 /*********************************************************************
1602  * _mktemp (MSVCRT.@)
1603  */
1604 char * CDECL _mktemp(char *pattern)
1605 {
1606  int numX = 0;
1607  char *retVal = pattern;
1608  int id;
1609  char letter = 'a';
1610 
1611  if(!pattern)
1612  return NULL;
1613 
1614  while(*pattern)
1615  numX = (*pattern++ == 'X')? numX + 1 : 0;
1616  if (numX < 6)
1617  return NULL;
1618  pattern--;
1619  id = GetCurrentProcessId();
1620  numX = 6;
1621  while(numX--)
1622  {
1623  int tempNum = id / 10;
1624  *pattern-- = id - (tempNum * 10) + '0';
1625  id = tempNum;
1626  }
1627  pattern++;
1628  do
1629  {
1630  *pattern = letter++;
1632  return retVal;
1633  } while(letter <= 'z');
1634  return NULL;
1635 }
1636 
1637 /*********************************************************************
1638  * _wmktemp (MSVCRT.@)
1639  */
1640 wchar_t * CDECL _wmktemp(wchar_t *pattern)
1641 {
1642  int numX = 0;
1643  wchar_t *retVal = pattern;
1644  int id;
1645  wchar_t letter = 'a';
1646 
1647  while(*pattern)
1648  numX = (*pattern++ == 'X')? numX + 1 : 0;
1649  if (numX < 5)
1650  return NULL;
1651  pattern--;
1652  id = GetCurrentProcessId();
1653  numX = 6;
1654  while(numX--)
1655  {
1656  int tempNum = id / 10;
1657  *pattern-- = id - (tempNum * 10) + '0';
1658  id = tempNum;
1659  }
1660  pattern++;
1661  do
1662  {
1665  return retVal;
1666  *pattern = letter++;
1667  } while(letter != '|');
1668  return NULL;
1669 }
1670 
1671 /*static*/ unsigned split_oflags(unsigned oflags)
1672 {
1673  int wxflags = 0;
1674  unsigned unsupp; /* until we support everything */
1675 
1676  if (oflags & _O_APPEND) wxflags |= WX_APPEND;
1677  if (oflags & _O_BINARY) {/* Nothing to do */}
1678  else if (oflags & _O_TEXT) wxflags |= WX_TEXT;
1679  else if (oflags & _O_WTEXT) wxflags |= WX_TEXT;
1680  else if (oflags & _O_U16TEXT) wxflags |= WX_TEXT;
1681  else if (oflags & _O_U8TEXT) wxflags |= WX_TEXT;
1682  else if (*__p__fmode() & _O_BINARY) {/* Nothing to do */}
1683  else wxflags |= WX_TEXT; /* default to TEXT*/
1684  if (oflags & _O_NOINHERIT) wxflags |= WX_DONTINHERIT;
1685 
1686  if ((unsupp = oflags & ~(
1690  _O_NOINHERIT|
1693  )))
1694  ERR(":unsupported oflags 0x%04x\n",unsupp);
1695 
1696  return wxflags;
1697 }
1698 
1699 /*********************************************************************
1700  * _pipe (MSVCRT.@)
1701  */
1702 int CDECL _pipe(int *pfds, unsigned int psize, int textmode)
1703 {
1704  int ret = -1;
1706  HANDLE readHandle, writeHandle;
1707 
1708  if (!pfds)
1709  {
1710  *_errno() = EINVAL;
1711  return -1;
1712  }
1713 
1714  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1715  sa.bInheritHandle = !(textmode & _O_NOINHERIT);
1716  sa.lpSecurityDescriptor = NULL;
1717  if (CreatePipe(&readHandle, &writeHandle, &sa, psize))
1718  {
1719  unsigned int wxflags = split_oflags(textmode);
1720  int fd;
1721 
1722  fd = msvcrt_alloc_fd(readHandle, wxflags);
1723  if (fd != -1)
1724  {
1725  pfds[0] = fd;
1726  fd = msvcrt_alloc_fd(writeHandle, wxflags);
1727  if (fd != -1)
1728  {
1729  pfds[1] = fd;
1730  ret = 0;
1731  }
1732  else
1733  {
1734  _close(pfds[0]);
1735  CloseHandle(writeHandle);
1736  *_errno() = EMFILE;
1737  }
1738  }
1739  else
1740  {
1741  CloseHandle(readHandle);
1742  CloseHandle(writeHandle);
1743  *_errno() = EMFILE;
1744  }
1745  }
1746  else
1748 
1749  return ret;
1750 }
1751 
1752 static int check_bom(HANDLE h, int oflags, BOOL seek)
1753 {
1754  char bom[sizeof(utf8_bom)];
1755  DWORD r;
1756 
1757  oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
1758 
1759  if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
1760  return oflags;
1761 
1762  if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
1763  oflags |= _O_U8TEXT;
1764  }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
1765  if (seek && r>2)
1767  oflags |= _O_U16TEXT;
1768  }else if (seek) {
1770  }
1771 
1772  return oflags;
1773 }
1774 
1775 /*********************************************************************
1776  * _wsopen_s (MSVCRT.@)
1777  */
1778 int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode )
1779 {
1780  DWORD access = 0, creation = 0, attrib;
1782  DWORD sharing, type;
1783  int wxflag;
1784  HANDLE hand;
1785 
1786  TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
1787  fd, debugstr_w(path), oflags, shflags, pmode);
1788 
1789  if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL;
1790 
1791  *fd = -1;
1792  wxflag = split_oflags(oflags);
1793  switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
1794  {
1795  case _O_RDONLY: access |= GENERIC_READ; break;
1796  case _O_WRONLY: access |= GENERIC_WRITE; break;
1797  case _O_RDWR: access |= GENERIC_WRITE | GENERIC_READ; break;
1798  }
1799 
1800  if (oflags & _O_CREAT)
1801  {
1802  if(pmode & ~(_S_IREAD | _S_IWRITE))
1803  FIXME(": pmode 0x%04x ignored\n", pmode);
1804  else
1805  WARN(": pmode 0x%04x ignored\n", pmode);
1806 
1807  if (oflags & _O_EXCL)
1808  creation = CREATE_NEW;
1809  else if (oflags & _O_TRUNC)
1810  creation = CREATE_ALWAYS;
1811  else
1812  creation = OPEN_ALWAYS;
1813  }
1814  else /* no _O_CREAT */
1815  {
1816  if (oflags & _O_TRUNC)
1817  creation = TRUNCATE_EXISTING;
1818  else
1819  creation = OPEN_EXISTING;
1820  }
1821 
1822  switch( shflags )
1823  {
1824  case _SH_DENYRW:
1825  sharing = 0L;
1826  break;
1827  case _SH_DENYWR:
1829  break;
1830  case _SH_DENYRD:
1832  break;
1833  case _SH_DENYNO:
1835  break;
1836  default:
1837  ERR( "Unhandled shflags 0x%x\n", shflags );
1838  return EINVAL;
1839  }
1840  attrib = FILE_ATTRIBUTE_NORMAL;
1841 
1842  if (oflags & _O_TEMPORARY)
1843  {
1844  attrib |= FILE_FLAG_DELETE_ON_CLOSE;
1845  access |= DELETE;
1847  }
1848 
1849  sa.nLength = sizeof( SECURITY_ATTRIBUTES );
1850  sa.lpSecurityDescriptor = NULL;
1851  sa.bInheritHandle = !(oflags & _O_NOINHERIT);
1852 
1853  if ((oflags&(_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
1854  && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
1855  && !(access&GENERIC_READ))
1856  {
1859  if (hand != INVALID_HANDLE_VALUE)
1860  {
1861  oflags = check_bom(hand, oflags, FALSE);
1862  CloseHandle(hand);
1863  }
1864  else
1865  oflags &= ~(_O_WTEXT|_O_U16TEXT|_O_U8TEXT);
1866  }
1867 
1868  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
1869  if (hand == INVALID_HANDLE_VALUE) {
1870  WARN(":failed-last error (%d)\n",GetLastError());
1872  return *_errno();
1873  }
1874 
1875  if (oflags & (_O_WTEXT|_O_U16TEXT|_O_U8TEXT))
1876  {
1877  if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
1878  || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
1879  || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
1880  {
1881  if (oflags & _O_U8TEXT)
1882  {
1883  DWORD written = 0, tmp;
1884 
1885  while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
1886  sizeof(utf8_bom)-written, &tmp, NULL))
1887  written += tmp;
1888  if (written != sizeof(utf8_bom)) {
1889  WARN("error writing BOM\n");
1890  CloseHandle(hand);
1892  return *_errno();
1893  }
1894  }
1895  else
1896  {
1897  DWORD written = 0, tmp;
1898 
1899  while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
1900  sizeof(utf16_bom)-written, &tmp, NULL))
1901  written += tmp;
1902  if (written != sizeof(utf16_bom))
1903  {
1904  WARN("error writing BOM\n");
1905  CloseHandle(hand);
1907  return *_errno();
1908  }
1909  }
1910  }
1911  else if (access & GENERIC_READ)
1912  oflags = check_bom(hand, oflags, TRUE);
1913  }
1914 
1915  type = GetFileType(hand);
1916  if (type == FILE_TYPE_CHAR)
1917  wxflag |= WX_TTY;
1918  else if (type == FILE_TYPE_PIPE)
1919  wxflag |= WX_PIPE;
1920 
1921  *fd = msvcrt_alloc_fd(hand, wxflag);
1922  if (*fd == -1)
1923  return *_errno();
1924 
1925  if (oflags & _O_WTEXT)
1927  else if (oflags & _O_U16TEXT)
1929  else if (oflags & _O_U8TEXT)
1930  get_ioinfo_nolock(*fd)->exflag |= EF_UTF8;
1931 
1932  TRACE(":fd (%d) handle (%p)\n", *fd, hand);
1933  return 0;
1934 }
1935 
1936 /*********************************************************************
1937  * _wsopen (MSVCRT.@)
1938  */
1939 int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
1940 {
1941  int pmode;
1942  int fd;
1943 
1944  if (oflags & _O_CREAT)
1945  {
1946  __ms_va_list ap;
1947 
1948  __ms_va_start(ap, shflags);
1949  pmode = va_arg(ap, int);
1950  __ms_va_end(ap);
1951  }
1952  else
1953  pmode = 0;
1954 
1955  _wsopen_s(&fd, path, oflags, shflags, pmode);
1956  return fd;
1957 }
1958 
1959 /*********************************************************************
1960  * _sopen_s (MSVCRT.@)
1961  */
1962 int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
1963 {
1964  wchar_t *pathW;
1965  int ret;
1966 
1967  if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path))))
1968  return EINVAL;
1969 
1970  ret = _wsopen_s(fd, pathW, oflags, shflags, pmode);
1971  free(pathW);
1972  return ret;
1973 }
1974 
1975 /*********************************************************************
1976  * _sopen (MSVCRT.@)
1977  */
1978 int CDECL _sopen( const char *path, int oflags, int shflags, ... )
1979 {
1980  int pmode;
1981  int fd;
1982 
1983  if (oflags & _O_CREAT)
1984  {
1985  va_list ap;
1986 
1987  va_start(ap, shflags);
1988  pmode = va_arg(ap, int);
1989  va_end(ap);
1990  }
1991  else
1992  pmode = 0;
1993 
1994  _sopen_s(&fd, path, oflags, shflags, pmode);
1995  return fd;
1996 }
1997 
1998 /*********************************************************************
1999  * _open (MSVCRT.@)
2000  */
2001 int CDECL _open( const char *path, int flags, ... )
2002 {
2003  va_list ap;
2004 
2005  if (flags & _O_CREAT)
2006  {
2007  int pmode;
2008  va_start(ap, flags);
2009  pmode = va_arg(ap, int);
2010  va_end(ap);
2011  return _sopen( path, flags, _SH_DENYNO, pmode );
2012  }
2013  else
2014  return _sopen( path, flags, _SH_DENYNO);
2015 }
2016 
2017 /*********************************************************************
2018  * _wopen (MSVCRT.@)
2019  */
2020 int CDECL _wopen(const wchar_t *path,int flags,...)
2021 {
2022  va_list ap;
2023 
2024  if (flags & _O_CREAT)
2025  {
2026  int pmode;
2027  va_start(ap, flags);
2028  pmode = va_arg(ap, int);
2029  va_end(ap);
2030  return _wsopen( path, flags, _SH_DENYNO, pmode );
2031  }
2032  else
2033  return _wsopen( path, flags, _SH_DENYNO);
2034 }
2035 
2036 /*********************************************************************
2037  * _creat (MSVCRT.@)
2038  */
2039 int CDECL _creat(const char *path, int flags)
2040 {
2041  int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
2042  return _open(path, usedFlags);
2043 }
2044 
2045 /*********************************************************************
2046  * _wcreat (MSVCRT.@)
2047  */
2048 int CDECL _wcreat(const wchar_t *path, int flags)
2049 {
2050  int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
2051  return _wopen(path, usedFlags);
2052 }
2053 
2054 /*********************************************************************
2055  * _open_osfhandle (MSVCRT.@)
2056  */
2058 {
2059  DWORD flags;
2060  int fd;
2061 
2062  /* _O_RDONLY (0) always matches, so set the read flag
2063  * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
2064  * file, so set the write flag. It also only sets _O_TEXT if it wants
2065  * text - it never sets _O_BINARY.
2066  */
2067  /* don't let split_oflags() decide the mode if no mode is passed */
2068  if (!(oflags & (_O_BINARY | _O_TEXT)))
2069  oflags |= _O_BINARY;
2070 
2073  {
2075  return -1;
2076  }
2077 
2078  if (flags == FILE_TYPE_CHAR)
2079  flags = WX_TTY;
2080  else if (flags == FILE_TYPE_PIPE)
2081  flags = WX_PIPE;
2082  else
2083  flags = 0;
2084  flags |= split_oflags(oflags);
2085 
2087  TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, flags);
2088  return fd;
2089 }
2090 
2091 /*********************************************************************
2092  * _rmtmp (MSVCRT.@)
2093  */
2094 int CDECL _rmtmp(void)
2095 {
2096  int num_removed = 0, i;
2097  FILE *file;
2098 
2099  LOCK_FILES();
2100  for (i = 3; i < MSVCRT_stream_idx; i++) {
2101  file = msvcrt_get_file(i);
2102 
2103  if (file->_tmpfname)
2104  {
2105  fclose(file);
2106  num_removed++;
2107  }
2108  }
2109  UNLOCK_FILES();
2110 
2111  if (num_removed)
2112  TRACE(":removed (%d) temp files\n",num_removed);
2113  return num_removed;
2114 }
2115 
2116 static inline int get_utf8_char_len(char ch)
2117 {
2118  if((ch&0xf8) == 0xf0)
2119  return 4;
2120  else if((ch&0xf0) == 0xe0)
2121  return 3;
2122  else if((ch&0xe0) == 0xc0)
2123  return 2;
2124  return 1;
2125 }
2126 
2127 /*********************************************************************
2128  * (internal) read_utf8
2129  */
2130 static int read_utf8(ioinfo *fdinfo, wchar_t *buf, unsigned int count)
2131 {
2132  HANDLE hand = fdinfo->handle;
2133  char min_buf[4], *readbuf, lookahead;
2134  DWORD readbuf_size, pos=0, num_read=1, char_len, i, j;
2135 
2136  /* make the buffer big enough to hold at least one character */
2137  /* read bytes have to fit to output and lookahead buffers */
2138  count /= 2;
2139  readbuf_size = count < 4 ? 4 : count;
2140  if(readbuf_size<=4 || !(readbuf = malloc(readbuf_size))) {
2141  readbuf_size = 4;
2142  readbuf = min_buf;
2143  }
2144 
2145  if(fdinfo->lookahead[0] != '\n') {
2146  readbuf[pos++] = fdinfo->lookahead[0];
2147  fdinfo->lookahead[0] = '\n';
2148 
2149  if(fdinfo->lookahead[1] != '\n') {
2150  readbuf[pos++] = fdinfo->lookahead[1];
2151  fdinfo->lookahead[1] = '\n';
2152 
2153  if(fdinfo->lookahead[2] != '\n') {
2154  readbuf[pos++] = fdinfo->lookahead[2];
2155  fdinfo->lookahead[2] = '\n';
2156  }
2157  }
2158  }
2159 
2160  /* NOTE: this case is broken in native dll, reading
2161  * sometimes fails when small buffer is passed
2162  */
2163  if(count < 4) {
2164  if(!pos && !ReadFile(hand, readbuf, 1, &num_read, NULL)) {
2165  if (GetLastError() == ERROR_BROKEN_PIPE) {
2166  fdinfo->wxflag |= WX_ATEOF;
2167  return 0;
2168  }else {
2170  return -1;
2171  }
2172  }else if(!num_read) {
2173  fdinfo->wxflag |= WX_ATEOF;
2174  return 0;
2175  }else {
2176  pos++;
2177  }
2178 
2179  char_len = get_utf8_char_len(readbuf[0]);
2180  if(char_len>pos) {
2181  if(ReadFile(hand, readbuf+pos, char_len-pos, &num_read, NULL))
2182  pos += num_read;
2183  }
2184 
2185  if(readbuf[0] == '\n')
2186  fdinfo->wxflag |= WX_READNL;
2187  else
2188  fdinfo->wxflag &= ~WX_READNL;
2189 
2190  if(readbuf[0] == 0x1a) {
2191  fdinfo->wxflag |= WX_ATEOF;
2192  return 0;
2193  }
2194 
2195  if(readbuf[0] == '\r') {
2196  if(!ReadFile(hand, &lookahead, 1, &num_read, NULL) || num_read!=1)
2197  buf[0] = '\r';
2198  else if(lookahead == '\n')
2199  buf[0] = '\n';
2200  else {
2201  buf[0] = '\r';
2202  if(fdinfo->wxflag & (WX_PIPE | WX_TTY))
2203  fdinfo->lookahead[0] = lookahead;
2204  else
2205  SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2206  }
2207  return 2;
2208  }
2209 
2210  if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2212  return -1;
2213  }
2214 
2215  return num_read*2;
2216  }
2217 
2218  if(!ReadFile(hand, readbuf+pos, readbuf_size-pos, &num_read, NULL)) {
2219  if(pos) {
2220  num_read = 0;
2221  }else if(GetLastError() == ERROR_BROKEN_PIPE) {
2222  fdinfo->wxflag |= WX_ATEOF;
2223  if (readbuf != min_buf) free(readbuf);
2224  return 0;
2225  }else {
2227  if (readbuf != min_buf) free(readbuf);
2228  return -1;
2229  }
2230  }else if(!pos && !num_read) {
2231  fdinfo->wxflag |= WX_ATEOF;
2232  if (readbuf != min_buf) free(readbuf);
2233  return 0;
2234  }
2235 
2236  pos += num_read;
2237  if(readbuf[0] == '\n')
2238  fdinfo->wxflag |= WX_READNL;
2239  else
2240  fdinfo->wxflag &= ~WX_READNL;
2241 
2242  /* Find first byte of last character (may be incomplete) */
2243  for(i=pos-1; i>0 && i>pos-4; i--)
2244  if((readbuf[i]&0xc0) != 0x80)
2245  break;
2246  char_len = get_utf8_char_len(readbuf[i]);
2247  if(char_len+i <= pos)
2248  i += char_len;
2249 
2250  if(fdinfo->wxflag & (WX_PIPE | WX_TTY)) {
2251  if(i < pos)
2252  fdinfo->lookahead[0] = readbuf[i];
2253  if(i+1 < pos)
2254  fdinfo->lookahead[1] = readbuf[i+1];
2255  if(i+2 < pos)
2256  fdinfo->lookahead[2] = readbuf[i+2];
2257  }else if(i < pos) {
2259  }
2260  pos = i;
2261 
2262  for(i=0, j=0; i<pos; i++) {
2263  if(readbuf[i] == 0x1a) {
2264  fdinfo->wxflag |= WX_ATEOF;
2265  break;
2266  }
2267 
2268  /* strip '\r' if followed by '\n' */
2269  if(readbuf[i] == '\r' && i+1==pos) {
2270  if(fdinfo->lookahead[0] != '\n' || !ReadFile(hand, &lookahead, 1, &num_read, NULL) || !num_read) {
2271  readbuf[j++] = '\r';
2272  }else if(lookahead == '\n' && j==0) {
2273  readbuf[j++] = '\n';
2274  }else {
2275  if(lookahead != '\n')
2276  readbuf[j++] = '\r';
2277 
2278  if(fdinfo->wxflag & (WX_PIPE | WX_TTY))
2279  fdinfo->lookahead[0] = lookahead;
2280  else
2281  SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
2282  }
2283  }else if(readbuf[i]!='\r' || readbuf[i+1]!='\n') {
2284  readbuf[j++] = readbuf[i];
2285  }
2286  }
2287  pos = j;
2288 
2289  if(!(num_read = MultiByteToWideChar(CP_UTF8, 0, readbuf, pos, buf, count))) {
2291  if (readbuf != min_buf) free(readbuf);
2292  return -1;
2293  }
2294 
2295  if (readbuf != min_buf) free(readbuf);
2296  return num_read*2;
2297 }
2298 
2299 /*********************************************************************
2300  * (internal) read_i
2301  *
2302  * When reading \r as last character in text mode, read() positions
2303  * the file pointer on the \r character while getc() goes on to
2304  * the following \n
2305  */
2306 static int read_i(int fd, ioinfo *fdinfo, void *buf, unsigned int count)
2307 {
2308  DWORD num_read, utf16;
2309  char *bufstart = buf;
2310 
2311  if (count == 0)
2312  return 0;
2313 
2314  if (fdinfo->wxflag & WX_ATEOF) {
2315  TRACE("already at EOF, returning 0\n");
2316  return 0;
2317  }
2318  /* Don't trace small reads, it gets *very* annoying */
2319  if (count > 4)
2320  TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n", fd, fdinfo->handle, buf, count);
2321  if (fdinfo->handle == INVALID_HANDLE_VALUE)
2322  {
2323  *_errno() = EBADF;
2324  return -1;
2325  }
2326 
2327  utf16 = (fdinfo->exflag & EF_UTF16) != 0;
2328  if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
2329  {
2330  *_errno() = EINVAL;
2331  return -1;
2332  }
2333 
2334  if((fdinfo->wxflag&WX_TEXT) && (fdinfo->exflag&EF_UTF8))
2335  return read_utf8(fdinfo, buf, count);
2336 
2337  if (fdinfo->lookahead[0]!='\n' || ReadFile(fdinfo->handle, bufstart, count, &num_read, NULL))
2338  {
2339  if (fdinfo->lookahead[0] != '\n')
2340  {
2341  bufstart[0] = fdinfo->lookahead[0];
2342  fdinfo->lookahead[0] = '\n';
2343 
2344  if (utf16)
2345  {
2346  bufstart[1] = fdinfo->lookahead[1];
2347  fdinfo->lookahead[1] = '\n';
2348  }
2349 
2350  if(count>1+utf16 && ReadFile(fdinfo->handle, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
2351  num_read += 1+utf16;
2352  else
2353  num_read = 1+utf16;
2354  }
2355 
2356  if(utf16 && (num_read&1))
2357  {
2358  /* msvcr90 uses uninitialized value from the buffer in this case */
2359  /* msvcrt ignores additional data */
2360  ERR("got odd number of bytes in UTF16 mode\n");
2361  num_read--;
2362  }
2363 
2364  if (count != 0 && num_read == 0)
2365  {
2366  fdinfo->wxflag |= WX_ATEOF;
2367  TRACE(":EOF %s\n",debugstr_an(buf,num_read));
2368  }
2369  else if (fdinfo->wxflag & WX_TEXT)
2370  {
2371  DWORD i, j;
2372 
2373  if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
2374  fdinfo->wxflag |= WX_READNL;
2375  else
2376  fdinfo->wxflag &= ~WX_READNL;
2377 
2378  for (i=0, j=0; i<num_read; i+=1+utf16)
2379  {
2380  /* in text mode, a ctrl-z signals EOF */
2381  if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
2382  {
2383  fdinfo->wxflag |= WX_ATEOF;
2384  TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
2385  break;
2386  }
2387 
2388  /* in text mode, strip \r if followed by \n */
2389  if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
2390  {
2391  char lookahead[2];
2392  DWORD len;
2393 
2394  lookahead[1] = '\n';
2395  if (ReadFile(fdinfo->handle, lookahead, 1+utf16, &len, NULL) && len)
2396  {
2397  if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
2398  {
2399  bufstart[j++] = '\n';
2400  if(utf16) bufstart[j++] = 0;
2401  }
2402  else
2403  {
2404  if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
2405  {
2406  bufstart[j++] = '\r';
2407  if(utf16) bufstart[j++] = 0;
2408  }
2409 
2410  if (fdinfo->wxflag & (WX_PIPE | WX_TTY))
2411  {
2412  if (lookahead[0]=='\n' && (!utf16 || !lookahead[1]))
2413  {
2414  bufstart[j++] = '\n';
2415  if (utf16) bufstart[j++] = 0;
2416  }
2417  else
2418  {
2419  fdinfo->lookahead[0] = lookahead[0];
2420  fdinfo->lookahead[1] = lookahead[1];
2421  }
2422  }
2423  else
2424  SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
2425  }
2426  }
2427  else
2428  {
2429  bufstart[j++] = '\r';
2430  if(utf16) bufstart[j++] = 0;
2431  }
2432  }
2433  else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
2434  || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
2435  {
2436  bufstart[j++] = bufstart[i];
2437  if(utf16) bufstart[j++] = bufstart[i+1];
2438  }
2439  }
2440  num_read = j;
2441  }
2442  }
2443  else
2444  {
2446  {
2447  TRACE(":end-of-pipe\n");
2448  fdinfo->wxflag |= WX_ATEOF;
2449  return 0;
2450  }
2451  else
2452  {
2453  TRACE(":failed-last error (%d)\n",GetLastError());
2454  return -1;
2455  }
2456  }
2457 
2458  if (count > 4)
2459  TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
2460  return num_read;
2461 }
2462 
2463 /*********************************************************************
2464  * _read (MSVCRT.@)
2465  */
2466 int CDECL _read(int fd, void *buf, unsigned int count)
2467 {
2468  ioinfo *info = get_ioinfo(fd);
2469  int num_read = read_i(fd, info, buf, count);
2471  return num_read;
2472 }
2473 
2474 /*********************************************************************
2475  * _setmode (MSVCRT.@)
2476  */
2477 int CDECL _setmode(int fd,int mode)
2478 {
2479  ioinfo *info = get_ioinfo(fd);
2480  int ret = info->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
2481  if(ret==_O_TEXT && (info->exflag & (EF_UTF8|EF_UTF16)))
2482  ret = _O_WTEXT;
2483 
2484  if(mode!=_O_TEXT && mode!=_O_BINARY && mode!=_O_WTEXT
2485  && mode!=_O_U16TEXT && mode!=_O_U8TEXT) {
2486  *_errno() = EINVAL;
2488  return -1;
2489  }
2490 
2491  if(info == &__badioinfo) {
2492  *_errno() = EBADF;
2493  return EOF;
2494  }
2495 
2496  if(mode == _O_BINARY) {
2497  info->wxflag &= ~WX_TEXT;
2498  info->exflag &= ~(EF_UTF8|EF_UTF16);
2500  return ret;
2501  }
2502 
2503  info->wxflag |= WX_TEXT;
2504  if(mode == _O_TEXT)
2505  info->exflag &= ~(EF_UTF8|EF_UTF16);
2506  else if(mode == _O_U8TEXT)
2507  info->exflag = (info->exflag & ~EF_UTF16) | EF_UTF8;
2508  else
2509  info->exflag = (info->exflag & ~EF_UTF8) | EF_UTF16;
2510 
2512  return ret;
2513 
2514 }
2515 
2516 /*********************************************************************
2517  * _tell (MSVCRT.@)
2518  */
2519 long CDECL _tell(int fd)
2520 {
2521  return _lseek(fd, 0, SEEK_CUR);
2522 }
2523 
2524 /*********************************************************************
2525  * _telli64 (MSVCRT.@)
2526  */
2528 {
2529  return _lseeki64(fd, 0, SEEK_CUR);
2530 }
2531 
2532 /*********************************************************************
2533  * _tempnam (MSVCRT.@)
2534  */
2535 char * CDECL _tempnam(const char *dir, const char *prefix)
2536 {
2537  char tmpbuf[MAX_PATH];
2538  const char *tmp_dir = getenv("TMP");
2539 
2540  if (tmp_dir) dir = tmp_dir;
2541 
2542  TRACE("dir (%s) prefix (%s)\n",dir,prefix);
2543  if (GetTempFileNameA(dir,prefix,0,tmpbuf))
2544  {
2545  TRACE("got name (%s)\n",tmpbuf);
2546  DeleteFileA(tmpbuf);
2547  return _strdup(tmpbuf);
2548  }
2549  TRACE("failed (%d)\n",GetLastError());
2550  return NULL;
2551 }
2552 
2553 /*********************************************************************
2554  * _wtempnam (MSVCRT.@)
2555  */
2556 wchar_t * CDECL _wtempnam(const wchar_t *dir, const wchar_t *prefix)
2557 {
2558  wchar_t tmpbuf[MAX_PATH];
2559 
2560  TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
2561  if (GetTempFileNameW(dir,prefix,0,tmpbuf))
2562  {
2563  TRACE("got name (%s)\n",debugstr_w(tmpbuf));
2564  DeleteFileW(tmpbuf);
2565  return _wcsdup(tmpbuf);
2566  }
2567  TRACE("failed (%d)\n",GetLastError());
2568  return NULL;
2569 }
2570 
2571 /*********************************************************************
2572  * _umask (MSVCRT.@)
2573  */
2575 {
2576  int old_umask = MSVCRT_umask;
2577  TRACE("(%d)\n",umask);
2578  MSVCRT_umask = umask;
2579  return old_umask;
2580 }
2581 
2582 /*********************************************************************
2583  * _write (MSVCRT.@)
2584  */
2585 int CDECL _write(int fd, const void* buf, unsigned int count)
2586 {
2587  DWORD num_written;
2588  ioinfo *info = get_ioinfo(fd);
2589  HANDLE hand = info->handle;
2590 
2591  /* Don't trace small writes, it gets *very* annoying */
2592 #if 0
2593  if (count > 32)
2594  TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
2595 #endif
2596  if (hand == INVALID_HANDLE_VALUE)
2597  {
2598  *_errno() = EBADF;
2600  return -1;
2601  }
2602 
2603  if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1)
2604  {
2605  *_errno() = EINVAL;
2607  return -1;
2608  }
2609 
2610  /* If appending, go to EOF */
2611  if (info->wxflag & WX_APPEND)
2612  _lseek(fd, 0, FILE_END);
2613 
2614  if (!(info->wxflag & WX_TEXT))
2615  {
2616  if (WriteFile(hand, buf, count, &num_written, NULL)
2617  && (num_written == count))
2618  {
2620  return num_written;
2621  }
2622  TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
2623  hand, GetLastError());
2624  *_errno() = ENOSPC;
2625  }
2626  else
2627  {
2628  unsigned int i, j, nr_lf, size;
2629  char *p = NULL;
2630  const char *q;
2631  const char *s = buf, *buf_start = buf;
2632 
2633  if (!(info->exflag & (EF_UTF8|EF_UTF16)))
2634  {
2635  /* find number of \n */
2636  for (nr_lf=0, i=0; i<count; i++)
2637  if (s[i] == '\n')
2638  nr_lf++;
2639  if (nr_lf)
2640  {
2641  size = count+nr_lf;
2642  if ((q = p = malloc(size)))
2643  {
2644  for (s = buf, i = 0, j = 0; i < count; i++)
2645  {
2646  if (s[i] == '\n')
2647  p[j++] = '\r';
2648  p[j++] = s[i];
2649  }
2650  }
2651  else
2652  {
2653  FIXME("Malloc failed\n");
2654  nr_lf = 0;
2655  size = count;
2656  q = buf;
2657  }
2658  }
2659  else
2660  {
2661  size = count;
2662  q = buf;
2663  }
2664  }
2665  else if (info->exflag & EF_UTF16)
2666  {
2667  for (nr_lf=0, i=0; i<count; i+=2)
2668  if (s[i]=='\n' && s[i+1]==0)
2669  nr_lf += 2;
2670  if (nr_lf)
2671  {
2672  size = count+nr_lf;
2673  if ((q = p = malloc(size)))
2674  {
2675  for (s=buf, i=0, j=0; i<count; i++)
2676  {
2677  if (s[i]=='\n' && s[i+1]==0)
2678  {
2679  p[j++] = '\r';
2680  p[j++] = 0;
2681  }
2682  p[j++] = s[i++];
2683  p[j++] = s[i];
2684  }
2685  }
2686  else
2687  {
2688  FIXME("Malloc failed\n");
2689  nr_lf = 0;
2690  size = count;
2691  q = buf;
2692  }
2693  }
2694  else
2695  {
2696  size = count;
2697  q = buf;
2698  }
2699  }
2700  else
2701  {
2702  DWORD conv_len;
2703 
2704  for(nr_lf=0, i=0; i<count; i+=2)
2705  if (s[i]=='\n' && s[i+1]==0)
2706  nr_lf++;
2707 
2708  conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL);
2709  if(!conv_len) {
2711  free(p);
2713  return -1;
2714  }
2715 
2716  size = conv_len+nr_lf;
2717  if((p = malloc(count+nr_lf*2+size)))
2718  {
2719  for (s=buf, i=0, j=0; i<count; i++)
2720  {
2721  if (s[i]=='\n' && s[i+1]==0)
2722  {
2723  p[j++] = '\r';
2724  p[j++] = 0;
2725  }
2726  p[j++] = s[i++];
2727  p[j++] = s[i];
2728  }
2729  q = p+count+nr_lf*2;
2730  WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf,
2731  p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL);
2732  }
2733  else
2734  {
2735  FIXME("Malloc failed\n");
2736  nr_lf = 0;
2737  size = count;
2738  q = buf;
2739  }
2740  }
2741 
2742  if (!WriteFile(hand, q, size, &num_written, NULL))
2743  num_written = -1;
2745  if(p)
2746  free(p);
2747  if (num_written != size)
2748  {
2749  TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
2750  fd, hand, GetLastError(), num_written);
2751  *_errno() = ENOSPC;
2752  return s - buf_start;
2753  }
2754  return count;
2755  }
2756 
2758  return -1;
2759 }
2760 
2761 /*********************************************************************
2762  * _putw (MSVCRT.@)
2763  */
2765 {
2766  int len;
2767 
2768  _lock_file(file);
2769  len = _write(file->_file, &val, sizeof(val));
2770  if (len == sizeof(val)) {
2771  _unlock_file(file);
2772  return val;
2773  }
2774 
2775  file->_flag |= _IOERR;
2776  _unlock_file(file);
2777  return EOF;
2778 }
2779 
2780 /*********************************************************************
2781  * fclose (MSVCRT.@)
2782  */
2784 {
2785  int r, flag;
2786 
2787  _lock_file(file);
2788  flag = file->_flag;
2789  free(file->_tmpfname);
2790  file->_tmpfname = NULL;
2791  /* flush stdio buffers */
2792  if(file->_flag & _IOWRT)
2793  fflush(file);
2794  if(file->_flag & _IOMYBUF)
2795  free(file->_base);
2796 
2797  r=_close(file->_file);
2798 
2799  file->_flag = 0;
2800  _unlock_file(file);
2802  DeleteCriticalSection(&((file_crit*)file)->crit);
2803 
2805  while(MSVCRT_stream_idx>3 && !file->_flag) {
2808  }
2809  }
2810 
2811  return ((r == -1) || (flag & _IOERR) ? EOF : 0);
2812 }
2813 
2814 /*********************************************************************
2815  * feof (MSVCRT.@)
2816  */
2818 {
2819  return file->_flag & _IOEOF;
2820 }
2821 
2822 /*********************************************************************
2823  * ferror (MSVCRT.@)
2824  */
2826 {
2827  return file->_flag & _IOERR;
2828 }
2829 
2830 /*********************************************************************
2831  * _filbuf (MSVCRT.@)
2832  */
2834 {
2835  unsigned char c;
2836  _lock_file(file);
2837 
2838  if(file->_flag & _IOSTRG) {
2839  _unlock_file(file);
2840  return EOF;
2841  }
2842 
2843  /* Allocate buffer if needed */
2844  if(!(file->_flag & (_IONBF | _IOMYBUF | _USERBUF)))
2846 
2847  if(!(file->_flag & _IOREAD)) {
2848  if(file->_flag & _IORW)
2849  file->_flag |= _IOREAD;
2850  else {
2851  _unlock_file(file);
2852  return EOF;
2853  }
2854  }
2855 
2856  if(!(file->_flag & (_IOMYBUF | _USERBUF))) {
2857  int r;
2858  if ((r = _read(file->_file,&c,1)) != 1) {
2859  file->_flag |= (r == 0) ? _IOEOF : _IOERR;
2860  _unlock_file(file);
2861  return EOF;
2862  }
2863 
2864  _unlock_file(file);
2865  return c;
2866  } else {
2867  file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
2868  if(file->_cnt<=0) {
2869  file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
2870  file->_cnt = 0;
2871  _unlock_file(file);
2872  return EOF;
2873  }
2874 
2875  file->_cnt--;
2876  file->_ptr = file->_base+1;
2877  c = *(unsigned char *)file->_base;
2878  _unlock_file(file);
2879  return c;
2880  }
2881 }
2882 
2883 /*********************************************************************
2884  * fgetc (MSVCRT.@)
2885  */
2887 {
2888  unsigned char *i;
2889  unsigned int j;
2890 
2891  _lock_file(file);
2892  if (file->_cnt>0) {
2893  file->_cnt--;
2894  i = (unsigned char *)file->_ptr++;
2895  j = *i;
2896  } else
2897  j = _filbuf(file);
2898 
2899  _unlock_file(file);
2900  return j;
2901 }
2902 
2903 /*********************************************************************
2904  * _fgetchar (MSVCRT.@)
2905  */
2906 int CDECL _fgetchar(void)
2907 {
2908  return fgetc(stdin);
2909 }
2910 
2911 /*********************************************************************
2912  * fgets (MSVCRT.@)
2913  */
2914 char * CDECL fgets(char *s, int size, FILE* file)
2915 {
2916  int cc = EOF;
2917  char * buf_start = s;
2918 
2919  TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
2920  file,file->_file,s,size);
2921 
2922  _lock_file(file);
2923 
2924  while ((size >1) && (cc = fgetc(file)) != EOF && cc != '\n')
2925  {
2926  *s++ = (char)cc;
2927  size --;
2928  }
2929  if ((cc == EOF) && (s == buf_start)) /* If nothing read, return 0*/
2930  {
2931  TRACE(":nothing read\n");
2932  _unlock_file(file);
2933  return NULL;
2934  }
2935  if ((cc != EOF) && (size > 1))
2936  *s++ = cc;
2937  *s = '\0';
2938  TRACE(":got %s\n", debugstr_a(buf_start));
2939  _unlock_file(file);
2940  return buf_start;
2941 }
2942 
2943 /*********************************************************************
2944  * fgetwc (MSVCRT.@)
2945  */
2947 {
2948  wint_t ret;
2949  int ch;
2950 
2951  _lock_file(file);
2952 
2953  if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
2954  || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
2955  char *p;
2956 
2957  for(p=(char*)&ret; (wint_t*)p<&ret+1; p++) {
2958  ch = fgetc(file);
2959  if(ch == EOF) {
2960  ret = WEOF;
2961  break;
2962  }
2963  *p = (char)ch;
2964  }
2965  }else {
2966  char mbs[MB_LEN_MAX];
2967  int len = 0;
2968 
2969  ch = fgetc(file);
2970  if(ch != EOF) {
2971  mbs[0] = (char)ch;
2972  if(isleadbyte((unsigned char)mbs[0])) {
2973  ch = fgetc(file);
2974  if(ch != EOF) {
2975  mbs[1] = (char)ch;
2976  len = 2;
2977  }
2978  }else {
2979  len = 1;
2980  }
2981  }
2982 
2983  if(!len || mbtowc(&ret, mbs, len)==-1)
2984  ret = WEOF;
2985  }
2986 
2987  _unlock_file(file);
2988  return ret;
2989 }
2990 
2991 /*********************************************************************
2992  * _getw (MSVCRT.@)
2993  */
2995 {
2996  char *ch;
2997  int i, k;
2998  unsigned int j;
2999  ch = (char *)&i;
3000 
3001  _lock_file(file);
3002  for (j=0; j<sizeof(int); j++) {
3003  k = fgetc(file);
3004  if (k == EOF) {
3005  file->_flag |= _IOEOF;
3006  _unlock_file(file);
3007  return EOF;
3008  }
3009  ch[j] = k;
3010  }
3011 
3012  _unlock_file(file);
3013  return i;
3014 }
3015 
3016 /*********************************************************************
3017  * getwc (MSVCRT.@)
3018  */
3020 {
3021  return fgetwc(file);
3022 }
3023 
3024 /*********************************************************************
3025  * _fgetwchar (MSVCRT.@)
3026  */
3028 {
3029  return fgetwc(stdin);
3030 }
3031 
3032 /*********************************************************************
3033  * getwchar (MSVCRT.@)
3034  */
3036 {
3037  return _fgetwchar();
3038 }
3039 
3040 /*********************************************************************
3041  * fgetws (MSVCRT.@)
3042  */
3043 wchar_t * CDECL fgetws(wchar_t *s, int size, FILE* file)
3044 {
3045  int cc = WEOF;
3046  wchar_t * buf_start = s;
3047 
3048  TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3049  file,file->_file,s,size);
3050 
3051  _lock_file(file);
3052 
3053  while ((size >1) && (cc = fgetwc(file)) != WEOF && cc != '\n')
3054  {
3055  *s++ = (char)cc;
3056  size --;
3057  }
3058  if ((cc == WEOF) && (s == buf_start)) /* If nothing read, return 0*/
3059  {
3060  TRACE(":nothing read\n");
3061  _unlock_file(file);
3062  return NULL;
3063  }
3064  if ((cc != WEOF) && (size > 1))
3065  *s++ = cc;
3066  *s = 0;
3067  TRACE(":got %s\n", debugstr_w(buf_start));
3068  _unlock_file(file);
3069  return buf_start;
3070 }
3071 
3072 /*********************************************************************
3073  * fwrite (MSVCRT.@)
3074  */
3075 size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file)
3076 {
3077  size_t wrcnt=size * nmemb;
3078  int written = 0;
3079  if (size == 0)
3080  return 0;
3081 
3082  _lock_file(file);
3083 
3084  while(wrcnt) {
3085 #ifndef __REACTOS__
3086  if(file->_cnt < 0) {
3087  WARN("negative file->_cnt value in %p\n", file);
3088  file->_flag |= MSVCRT__IOERR;
3089  break;
3090  } else
3091 #endif
3092  if(file->_cnt) {
3093  int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
3094  memcpy(file->_ptr, ptr, pcnt);
3095  file->_cnt -= pcnt;
3096  file->_ptr += pcnt;
3097  written += pcnt;
3098  wrcnt -= pcnt;
3099  ptr = (const char*)ptr + pcnt;
3100  } else if((file->_flag & _IONBF)
3101  || ((file->_flag & (_IOMYBUF | _USERBUF)) && wrcnt >= file->_bufsiz)
3102  || (!(file->_flag & (_IOMYBUF | _USERBUF)) && wrcnt >= MSVCRT_INTERNAL_BUFSIZ)) {
3103  size_t pcnt;
3104  int bufsiz;
3105 
3106  if(file->_flag & _IONBF)
3107  bufsiz = 1;
3108  else if(!(file->_flag & (_IOMYBUF | _USERBUF)))
3109  bufsiz = MSVCRT_INTERNAL_BUFSIZ;
3110  else
3111  bufsiz = file->_bufsiz;
3112 
3113  pcnt = (wrcnt / bufsiz) * bufsiz;
3114 
3115  if(msvcrt_flush_buffer(file) == EOF)
3116  break;
3117 
3118  if(_write(file->_file, ptr, pcnt) <= 0) {
3119  file->_flag |= _IOERR;
3120  break;
3121  }
3122  written += pcnt;
3123  wrcnt -= pcnt;
3124  ptr = (const char*)ptr + pcnt;
3125  } else {
3126  if(_flsbuf(*(const char*)ptr, file) == EOF)
3127  break;
3128  written++;
3129  wrcnt--;
3130  ptr = (const char*)ptr + 1;
3131  }
3132  }
3133 
3134  _unlock_file(file);
3135  return written / size;
3136 }
3137 
3138 /*********************************************************************
3139  * fputwc (MSVCRT.@)
3140  * FORKED for ReactOS, don't sync with Wine!
3141  * References:
3142  * - http://jira.reactos.org/browse/CORE-6495
3143  * - http://bugs.winehq.org/show_bug.cgi?id=8598
3144  */
3146 {
3147  /* If this is a real file stream (and not some temporary one for
3148  sprintf-like functions), check whether it is opened in text mode.
3149  In this case, we have to perform an implicit conversion to ANSI. */
3150  if (!(stream->_flag & _IOSTRG) && get_ioinfo_nolock(stream->_file)->wxflag & WX_TEXT)
3151  {
3152  /* Convert to multibyte in text mode */
3153  char mbc[MB_LEN_MAX];
3154  int mb_return;
3155 
3156  mb_return = wctomb(mbc, c);
3157 
3158  if(mb_return == -1)
3159  return WEOF;
3160 
3161  /* Output all characters */
3162  if (fwrite(mbc, mb_return, 1, stream) != 1)
3163  return WEOF;
3164  }
3165  else
3166  {
3167  if (fwrite(&c, sizeof(c), 1, stream) != 1)
3168  return WEOF;
3169  }
3170 
3171  return c;
3172 }
3173 
3174 /*********************************************************************
3175  * _fputwchar (MSVCRT.@)
3176  */
3178 {
3179  return fputwc(wc, stdout);
3180 }
3181 
3182 /*********************************************************************
3183  * _wfsopen (MSVCRT.@)
3184  */
3185 FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share)
3186 {
3187  FILE* file;
3188  int open_flags, stream_flags, fd;
3189 
3190  TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
3191 
3192  /* map mode string to open() flags. "man fopen" for possibilities. */
3193  if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
3194  return NULL;
3195 
3196  LOCK_FILES();
3197  fd = _wsopen(path, open_flags, share, _S_IREAD | _S_IWRITE);
3198  if (fd < 0)
3199  file = NULL;
3200  else if ((file = msvcrt_alloc_fp()) && msvcrt_init_fp(file, fd, stream_flags)
3201  != -1)
3202  TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
3203  else if (file)
3204  {
3205  file->_flag = 0;
3206  file = NULL;
3207  }
3208 
3209  TRACE(":got (%p)\n",file);
3210  if (fd >= 0 && !file)
3211  _close(fd);
3212  UNLOCK_FILES();
3213  return file;
3214 }
3215 
3216 /*********************************************************************
3217  * _fsopen (MSVCRT.@)
3218  */
3219 FILE * CDECL _fsopen(const char *path, const char *mode, int share)
3220 {
3221  FILE *ret;
3222  wchar_t *pathW = NULL, *modeW = NULL;
3223 
3224  if (path && !(pathW = msvcrt_wstrdupa(path))) {
3225  _invalid_parameter(NULL, NULL, NULL, 0, 0);
3226  *_errno() = EINVAL;
3227  return NULL;
3228  }
3229  if (mode && !(modeW = msvcrt_wstrdupa(mode)))
3230  {
3231  free(pathW);
3232  _invalid_parameter(NULL, NULL, NULL, 0, 0);
3233  *_errno() = EINVAL;
3234  return NULL;
3235  }
3236 
3237  ret = _wfsopen(pathW, modeW, share);
3238 
3239  free(pathW);
3240  free(modeW);
3241  return ret;
3242 }
3243 
3244 /*********************************************************************
3245  * fopen (MSVCRT.@)
3246  */
3247 FILE * CDECL fopen(const char *path, const char *mode)
3248 {
3249  return _fsopen( path, mode, _SH_DENYNO );
3250 }
3251 
3252 /*********************************************************************
3253  * fopen_s (MSVCRT.@)
3254  */
3255 int CDECL fopen_s(FILE** pFile,
3256  const char *filename, const char *mode)
3257 {
3258  if (!MSVCRT_CHECK_PMT(pFile != NULL)) return EINVAL;
3259  if (!MSVCRT_CHECK_PMT(filename != NULL)) return EINVAL;
3260  if (!MSVCRT_CHECK_PMT(mode != NULL)) return EINVAL;
3261 
3262  *pFile = fopen(filename, mode);
3263 
3264  if(!*pFile)
3265  return *_errno();
3266  return 0;
3267 }
3268 
3269 /*********************************************************************
3270  * _wfopen (MSVCRT.@)
3271  */
3272 FILE * CDECL _wfopen(const wchar_t *path, const wchar_t *mode)
3273 {
3274  return _wfsopen( path, mode, _SH_DENYNO );
3275 }
3276 
3277 /*********************************************************************
3278  * _wfopen_s (MSVCRT.@)
3279  */
3280 int CDECL _wfopen_s(FILE** pFile, const wchar_t *filename,
3281  const wchar_t *mode)
3282 {
3283  if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
3284  !MSVCRT_CHECK_PMT(mode != NULL)) {
3285  *_errno() = EINVAL;
3286  return EINVAL;
3287  }
3288 
3289  *pFile = _wfopen(filename, mode);
3290 
3291  if(!*pFile)
3292  return *_errno();
3293  return 0;
3294 }
3295 
3296 /* fputc calls _flsbuf which calls fputc */
3297 int CDECL _flsbuf(int c, FILE* file);
3298 
3299 /*********************************************************************
3300  * fputc (MSVCRT.@)
3301  */
3302 int CDECL fputc(int c, FILE* file)
3303 {
3304  int res;
3305 
3306  _lock_file(file);
3307  if(file->_cnt>0) {
3308  *file->_ptr++=c;
3309  file->_cnt--;
3310  if (c == '\n')
3311  {
3313  _unlock_file(file);
3314  return res ? res : c;
3315  }
3316  else {
3317  _unlock_file(file);
3318  return c & 0xff;
3319  }
3320  } else {
3321  res = _flsbuf(c, file);
3322  _unlock_file(file);
3323  return res;
3324  }
3325 }
3326 
3327 /*********************************************************************
3328  * _fputchar (MSVCRT.@)
3329  */
3331 {
3332  return fputc(c, stdout);
3333 }
3334 
3335 /*********************************************************************
3336  * fread (MSVCRT.@)
3337  */
3338 size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file)
3339 {
3340  size_t rcnt=size * nmemb;
3341  size_t read=0;
3342  size_t pread=0;
3343 
3344  if(!rcnt)
3345  return 0;
3346 
3347  _lock_file(file);
3348 
3349  /* first buffered data */
3350  if(file->_cnt>0) {
3351  int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
3352  memcpy(ptr, file->_ptr, pcnt);
3353  file->_cnt -= pcnt;
3354  file->_ptr += pcnt;
3355  read += pcnt ;
3356  rcnt -= pcnt ;
3357  ptr = (char*)ptr + pcnt;
3358  } else if(!(file->_flag & _IOREAD )) {
3359  if(file->_flag & _IORW) {
3360  file->_flag |= _IOREAD;
3361  } else {
3362  _unlock_file(file);
3363  return 0;
3364  }
3365  }
3366 
3367  if(rcnt>0 && !(file->_flag & (_IONBF | _IOMYBUF | _USERBUF)))
3369 
3370  while(rcnt>0)
3371  {
3372  int i;
3373  if (!file->_cnt && rcnt<BUFSIZ && (file->_flag & (_IOMYBUF | _USERBUF))) {
3374  file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
3375  file->_ptr = file->_base;
3376  i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
3377  /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
3378  if (i > 0 && i < file->_cnt) {
3379  get_ioinfo_nolock(file->_file)->wxflag &= ~WX_ATEOF;
3380  file->_flag &= ~_IOEOF;
3381  }
3382  if (i > 0) {
3383  memcpy(ptr, file->_ptr, i);
3384  file->_cnt -= i;
3385  file->_ptr += i;
3386  }
3387  } else if (rcnt > INT_MAX) {
3388  i = _read(file->_file, ptr, INT_MAX);
3389  } else if (rcnt < BUFSIZ) {
3390  i = _read(file->_file, ptr, rcnt);
3391  } else {
3392  i = _read(file->_file, ptr, rcnt - BUFSIZ/2);
3393  }
3394  pread += i;
3395  rcnt -= i;
3396  ptr = (char *)ptr+i;
3397  /* expose feof condition in the flags
3398  * MFC tests file->_flag for feof, and doesn't call feof())
3399  */
3400  if (get_ioinfo_nolock(file->_file)->wxflag & WX_ATEOF)
3401  file->_flag |= _IOEOF;
3402  else if (i == -1)
3403  {
3404  file->_flag |= _IOERR;
3405  pread = 0;
3406  rcnt = 0;
3407  }
3408  if (i < 1) break;
3409  }
3410  read+=pread;
3411  _unlock_file(file);
3412  return read / size;
3413 }
3414 
3415 /*********************************************************************
3416  * _wfreopen (MSVCRT.@)
3417  *
3418  */
3419 FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode, FILE* file)
3420 {
3421  int open_flags, stream_flags, fd;
3422 
3423  TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file ? file->_file : -1);
3424 
3425  LOCK_FILES();
3426  if (!file || ((fd = file->_file) < 0))
3427  file = NULL;
3428  else
3429  {
3430  fclose(file);
3431  /* map mode string to open() flags. "man fopen" for possibilities. */
3432  if (msvcrt_get_flags(mode, &open_flags, &stream_flags) == -1)
3433  file = NULL;
3434  else
3435  {
3436  fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE);
3437  if (fd < 0)
3438  file = NULL;
3439  else if (msvcrt_init_fp(file, fd, stream_flags) == -1)
3440  {
3441  file->_flag = 0;
3442  WARN(":failed-last error (%d)\n",GetLastError());
3444  file = NULL;
3445  }
3446  }
3447  }
3448  UNLOCK_FILES();
3449  return file;
3450 }
3451 
3452 /*********************************************************************
3453  * freopen (MSVCRT.@)
3454  *
3455  */
3456 FILE* CDECL freopen(const char *path, const char *mode, FILE* file)
3457 {
3458  FILE *ret;
3459  wchar_t *pathW = NULL, *modeW = NULL;
3460 
3461  if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
3462  if (mode && !(modeW = msvcrt_wstrdupa(mode)))
3463  {
3464  free(pathW);
3465  return NULL;
3466  }
3467 
3468  ret = _wfreopen(pathW, modeW, file);
3469 
3470  free(pathW);
3471  free(modeW);
3472  return ret;
3473 }
3474 
3475 /*********************************************************************
3476  * fsetpos (MSVCRT.@)
3477  */
3479 {
3480  int ret;
3481 
3482  _lock_file(file);
3483  /* Note that all this has been lifted 'as is' from fseek */
3484  if(file->_flag & _IOWRT)
3486 
3487  /* Discard buffered input */
3488  file->_cnt = 0;
3489  file->_ptr = file->_base;
3490 
3491  /* Reset direction of i/o */
3492  if(file->_flag & _IORW) {
3493  file->_flag &= ~(_IOREAD|_IOWRT);
3494  }
3495 
3496  ret = (_lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0;
3497  _unlock_file(file);
3498  return ret;
3499 }
3500 
3501 /*********************************************************************
3502  * _ftelli64 (MSVCRT.@)
3503  */
3505 {
3506  __int64 pos;
3507 
3508  _lock_file(file);
3509  pos = _telli64(file->_file);
3510  if(pos == -1) {
3511  _unlock_file(file);
3512  return -1;
3513  }
3514  if(file->_flag & (_IOMYBUF | _USERBUF)) {
3515  if(file->_flag & _IOWRT) {
3516  pos += file->_ptr - file->_base;
3517 
3518  if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
3519  char *p;
3520 
3521  for(p=file->_base; p<file->_ptr; p++)
3522  if(*p == '\n')
3523  pos++;
3524  }
3525  } else if(!file->_cnt) { /* nothing to do */
3526  } else if(_lseeki64(file->_file, 0, SEEK_END)==pos) {
3527  int i;
3528 
3529  pos -= file->_cnt;
3530  if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
3531  for(i=0; i<file->_cnt; i++)
3532  if(file->_ptr[i] == '\n')
3533  pos--;
3534  }
3535  } else {
3536  char *p;
3537 
3538  if(_lseeki64(file->_file, pos, SEEK_SET) != pos) {
3539  _unlock_file(file);
3540  return -1;
3541  }
3542 
3543  pos -= file->_bufsiz;
3544  pos += file->_ptr - file->_base;
3545 
3546  if(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT) {
3547  if(get_ioinfo_nolock(file->_file)->wxflag & WX_READNL)
3548  pos--;
3549 
3550  for(p=file->_base; p<file->_ptr; p++)
3551  if(*p == '\n')
3552  pos++;
3553  }
3554  }
3555  }
3556 
3557  _unlock_file(file);
3558  return pos;
3559 }
3560 
3561 /*********************************************************************
3562  * ftell (MSVCRT.@)
3563  */
3565 {
3566  return (LONG)_ftelli64(file);
3567 }
3568 
3569 /*********************************************************************
3570  * fgetpos (MSVCRT.@)
3571  */
3573 {
3574  *pos = _ftelli64(file);
3575  if(*pos == -1)
3576  return -1;
3577  return 0;
3578 }
3579 
3580 /*********************************************************************
3581  * fputs (MSVCRT.@)
3582  */
3583 int CDECL fputs(const char *s, FILE* file)
3584 {
3585  size_t len = strlen(s);
3586  int ret;
3587 
3588  _lock_file(file);
3589  ret = fwrite(s, sizeof(*s), len, file) == len ? 0 : EOF;
3590  _unlock_file(file);
3591  return ret;
3592 }
3593 
3594 /*********************************************************************
3595  * fputws (MSVCRT.@)
3596  */
3597 int CDECL fputws(const wchar_t *s, FILE* file)
3598 {
3599  size_t i, len = strlenW(s);
3600  BOOL tmp_buf;
3601  int ret;
3602 
3603  _lock_file(file);
3604  if (!(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
3605  ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF;
3606  _unlock_file(file);
3607  return ret;
3608  }
3609 
3610  tmp_buf = add_std_buffer(file);
3611  for (i=0; i<len; i++) {
3612  if(fputwc(s[i], file) == WEOF) {
3613  if(tmp_buf) remove_std_buffer(file);
3614  _unlock_file(file);
3615  return WEOF;
3616  }
3617  }
3618 
3619  if(tmp_buf) remove_std_buffer(file);
3620  _unlock_file(file);
3621  return 0;
3622 }
3623 
3624 /*********************************************************************
3625  * getchar (MSVCRT.@)
3626  */
3627 int CDECL getchar(void)
3628 {
3629  return fgetc(stdin);
3630 }
3631 
3632 /*********************************************************************
3633  * getc (MSVCRT.@)
3634  */
3636 {
3637  return fgetc(file);
3638 }
3639 
3640 /*********************************************************************
3641  * gets (MSVCRT.@)
3642  */
3643 char * CDECL gets(char *buf)
3644 {
3645  int cc;
3646  char * buf_start = buf;
3647 
3648  _lock_file(stdin);
3649  for(cc = fgetc(stdin); cc != EOF && cc != '\n';
3650  cc = fgetc(stdin))
3651  if(cc != '\r') *buf++ = (char)cc;
3652 
3653  *buf = '\0';
3654 
3655  TRACE("got '%s'\n", buf_start);
3657  return buf_start;
3658 }
3659 
3660 /*********************************************************************
3661  * _getws (MSVCRT.@)
3662  */
3663 wchar_t* CDECL _getws(wchar_t* buf)
3664 {
3665  wint_t cc;
3666  wchar_t* ws = buf;
3667 
3668  _lock_file(stdin);
3669  for (cc = fgetwc(stdin); cc != WEOF && cc != '\n';
3670  cc = fgetwc(stdin))
3671  {
3672  if (cc != '\r')
3673  *buf++ = (wchar_t)cc;
3674  }
3675  *buf = '\0';
3676 
3677  TRACE("got %s\n", debugstr_w(ws));
3679  return ws;
3680 }
3681 
3682 /*********************************************************************
3683  * putc (MSVCRT.@)
3684  */
3685 int CDECL putc(int c, FILE* file)
3686 {
3687  return fputc(c, file);
3688 }
3689 
3690 /*********************************************************************
3691  * putchar (MSVCRT.@)
3692  */
3693 int CDECL putchar(int c)
3694 {
3695  return fputc(c, stdout);
3696 }
3697 
3698 /*********************************************************************
3699  * _putwch (MSVCRT.@)
3700  */
3702 {
3703  return fputwc(c, stdout);
3704 }
3705 
3706 /*********************************************************************
3707  * puts (MSVCRT.@)
3708  */
3709 int CDECL puts(const char *s)
3710 {
3711  size_t len = strlen(s);
3712  int ret;
3713 
3714  _lock_file(stdout);
3715  if(fwrite(s, sizeof(*s), len, stdout) != len) {
3717  return EOF;
3718  }
3719 
3720  ret = fwrite("\n",1,1,stdout) == 1 ? 0 : EOF;
3722  return ret;
3723 }
3724 
3725 /*********************************************************************
3726  * _putws (MSVCRT.@)
3727  */
3728 int CDECL _putws(const wchar_t *s)
3729 {
3730  static const wchar_t nl = '\n';
3731  size_t len = strlenW(s);
3732  int ret;
3733 
3734  _lock_file(stdout);
3735  if(fwrite(s, sizeof(*s), len, stdout) != len) {
3737  return EOF;
3738  }
3739 
3740  ret = fwrite(&nl,sizeof(nl),1,stdout) == 1 ? 0 : EOF;
3742  return ret;
3743 }
3744 
3745 /*********************************************************************
3746  * remove (MSVCRT.@)
3747  */
3748 int CDECL remove(const char *path)
3749 {
3750  TRACE("(%s)\n",path);
3751  if (DeleteFileA(path))
3752  return 0;
3753  TRACE(":failed (%d)\n",GetLastError());
3755  return -1;
3756 }
3757 
3758 /*********************************************************************
3759  * _wremove (MSVCRT.@)
3760  */
3761 int CDECL _wremove(const wchar_t *path)
3762 {
3763  TRACE("(%s)\n",debugstr_w(path));
3764  if (DeleteFileW(path))
3765  return 0;
3766  TRACE(":failed (%d)\n",GetLastError());
3768  return -1;
3769 }
3770 
3771 /*********************************************************************
3772  * rename (MSVCRT.@)
3773  */
3774 int CDECL rename(const char *oldpath,const char *newpath)
3775 {
3776  TRACE(":from %s to %s\n",oldpath,newpath);
3777  if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
3778  return 0;
3779  TRACE(":failed (%d)\n",GetLastError());
3781  return -1;
3782 }
3783 
3784 /*********************************************************************
3785  * _wrename (MSVCRT.@)
3786  */
3787 int CDECL _wrename(const wchar_t *oldpath,const wchar_t *newpath)
3788 {
3789  TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
3790  if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
3791  return 0;
3792  TRACE(":failed (%d)\n",GetLastError());
3794  return -1;
3795 }
3796 
3797 /*********************************************************************
3798  * setvbuf (MSVCRT.@)
3799  */
3800 int CDECL setvbuf(FILE* file, char *buf, int mode, size_t size)
3801 {
3802  if(!MSVCRT_CHECK_PMT(file != NULL)) return -1;
3803  if(!MSVCRT_CHECK_PMT(mode==_IONBF || mode==_IOFBF || mode==_IOLBF)) return -1;
3804  if(!MSVCRT_CHECK_PMT(mode==_IONBF || (size>=2 && size<=INT_MAX))) return -1;
3805 
3806  _lock_file(file);
3807 
3808  fflush(file);
3809  if(file->_flag & _IOMYBUF)
3810  free(file->_base);
3811  file->_flag &= ~(_IONBF | _IOMYBUF | _USERBUF);
3812  file->_cnt = 0;
3813 
3814  if(mode == _IONBF) {
3815  file->_flag |= _IONBF;
3816  file->_base = file->_ptr = (char*)&file->_charbuf;
3817  file->_bufsiz = 2;
3818  }else if(buf) {
3819  file->_base = file->_ptr = buf;
3820  file->_flag |= _USERBUF;
3821  file->_bufsiz = size;
3822  }else {
3823  file->_base = file->_ptr = malloc(size);
3824  if(!file->_base) {
3825  file->_bufsiz = 0;
3826  _unlock_file(file);
3827  return -1;
3828  }
3829 
3830  file->_flag |= _IOMYBUF;
3831  file->_bufsiz = size;
3832  }
3833  _unlock_file(file);
3834  return 0;
3835 }
3836 
3837 /*********************************************************************
3838  * setbuf (MSVCRT.@)
3839  */
3840 void CDECL setbuf(FILE* file, char *buf)
3841 {
3843 }
3844 
3845 /*********************************************************************
3846  * tmpnam (MSVCRT.@)
3847  */
3848 char * CDECL tmpnam(char *s)
3849 {
3850  char tmpstr[16];
3851  char *p;
3852  int count, size;
3853 
3854  if (!s) {
3856 
3857  if(!data->tmpnam_buffer)
3858  data->tmpnam_buffer = malloc(MAX_PATH);
3859 
3860  s = data->tmpnam_buffer;
3861  }
3862 
3864  p = s + sprintf(s, "\\s%s.", tmpstr);
3865  for (count = 0; count < TMP_MAX; count++)
3866  {
3868  memcpy(p, tmpstr, size);
3869  p[size] = '\0';
3872  break;
3873  }
3874  return s;
3875 }
3876 
3877 /*********************************************************************
3878  * _wtmpnam (MSVCRT.@)
3879  */
3880 wchar_t * CDECL _wtmpnam(wchar_t *s)
3881 {
3882  static const wchar_t format[] = {'\\','s','%','s','.',0};
3883  wchar_t tmpstr[16];
3884  wchar_t *p;
3885  int count, size;
3886  if (!s) {
3888 
3889  if(!data->wtmpnam_buffer)
3890  data->wtmpnam_buffer = malloc(sizeof(wchar_t[MAX_PATH]));
3891 
3892  s = data->wtmpnam_buffer;
3893  }
3894 
3896  p = s + _snwprintf(s, MAX_PATH, format, tmpstr);
3897  for (count = 0; count < TMP_MAX; count++)
3898  {
3900  memcpy(p, tmpstr, size*sizeof(wchar_t));
3901  p[size] = '\0';
3904  break;
3905  }
3906  return s;
3907 }
3908 
3909 /*********************************************************************
3910  * tmpfile (MSVCRT.@)
3911  */
3913 {
3914  char *filename = tmpnam(NULL);
3915  int fd;
3916  FILE* file = NULL;
3917 
3918  LOCK_FILES();
3920  _S_IREAD | _S_IWRITE);
3921  if (fd != -1 && (file = msvcrt_alloc_fp()))
3922  {
3923  if (msvcrt_init_fp(file, fd, _IORW) == -1)
3924  {
3925  file->_flag = 0;
3926  file = NULL;
3927  }
3928  else file->_tmpfname = _strdup(filename);
3929  }
3930 
3931  if(fd != -1 && !file)
3932  _close(fd);
3933  UNLOCK_FILES();
3934  return file;
3935 }
3936 
3937 /*********************************************************************
3938  * ungetc (MSVCRT.@)
3939  */
3940 int CDECL ungetc(int c, FILE * file)
3941 {
3942  if(!MSVCRT_CHECK_PMT(file != NULL)) return EOF;
3943 
3944  if (c == EOF || !(file->_flag&_IOREAD ||
3945  (file->_flag&_IORW && !(file->_flag&_IOWRT))))
3946  return EOF;
3947 
3948  _lock_file(file);
3949  if((!(file->_flag & (_IONBF | _IOMYBUF | _USERBUF))
3951  || (!file->_cnt && file->_ptr==file->_base))
3952  file->_ptr++;
3953 
3954  if(file->_ptr>file->_base) {
3955  file->_ptr--;
3956  if(file->_flag & _IOSTRG) {
3957  if(*file->_ptr != c) {
3958  file->_ptr++;
3959  _unlock_file(file);
3960  return EOF;
3961  }
3962  }else {
3963  *file->_ptr = c;
3964  }
3965  file->_cnt++;
3966  clearerr(file);
3967  file->_flag |= _IOREAD;
3968  _unlock_file(file);
3969  return c;
3970  }
3971 
3972  _unlock_file(file);
3973  return EOF;
3974 }
3975 
3976 /*********************************************************************
3977  * ungetwc (MSVCRT.@)
3978  */
3980 {
3981  wchar_t mwc = wc;
3982 
3983  if (wc == WEOF)
3984  return WEOF;
3985 
3986  _lock_file(file);
3987 
3988  if((get_ioinfo_nolock(file->_file)->exflag & (EF_UTF8 | EF_UTF16))
3989  || !(get_ioinfo_nolock(file->_file)->wxflag & WX_TEXT)) {
3990  unsigned char * pp = (unsigned char *)&mwc;
3991  int i;
3992 
3993  for(i=sizeof(wchar_t)-1;i>=0;i--) {
3994  if(pp[i] != ungetc(pp[i],file)) {
3995  _unlock_file(file);
3996  return WEOF;
3997  }
3998  }
3999  }else {
4000  char mbs[MB_LEN_MAX];
4001  int len;
4002 
4003  len = wctomb(mbs, mwc);
4004  if(len == -1) {
4005  _unlock_file(file);
4006  return WEOF;
4007  }
4008 
4009  for(len--; len>=0; len--) {
4010  if(mbs[len] != ungetc(mbs[len], file)) {
4011  _unlock_file(file);
4012  return WEOF;
4013  }
4014  }
4015  }
4016 
4017  _unlock_file(file);
4018  return mwc;
4019 }
4020 
4021 
4022 
4023 /*********************************************************************
4024  * _getmaxstdio (MSVCRT.@)
4025  */
4027 {
4028  return MSVCRT_max_streams;
4029 }
4030 
4031 /*********************************************************************
4032  * _setmaxstdio (MSVCRT.@)
4033  */
4034 int CDECL _setmaxstdio(int newmax)
4035 {
4036  TRACE("%d\n", newmax);
4037 
4038  if(newmax<_IOB_ENTRIES || newmax>MSVCRT_MAX_FILES || newmax<MSVCRT_stream_idx)
4039  return -1;
4040 
4041  MSVCRT_max_streams = newmax;
4042  return MSVCRT_max_streams;
4043 }
void _unlock(int locknum)
Definition: lock.c:126
static unsigned int block
Definition: xmlmemory.c:118
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:944
errno_t __cdecl _set_errno(_In_ int _Value)
#define _LK_NBRLCK
Definition: locking.h:19
#define wctomb(cp, wc)
Definition: wchar.h:161
#define MSVCRT_FD_BLOCK_SIZE
Definition: file.c:113
wchar_t *CDECL _wtempnam(const wchar_t *dir, const wchar_t *prefix)
Definition: file.c:2556
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define _USERBUF
Definition: stdio.h:137
#define SEEK_CUR
Definition: util.h:63
BOOL WINAPI MoveFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName OPTIONAL, IN DWORD dwFlags)
Definition: move.c:1093
static ULONG POBJECT_ATTRIBUTES PIO_STATUS_BLOCK ULONG sharing
Definition: pipe.c:68
LONG CDECL _filelength(int fd)
Definition: file.c:1544
int CDECL fsetpos(FILE *file, const fpos_t *pos)
Definition: file.c:3478
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
static const char __ms_va_list
Definition: printf.c:70
#define TRUE
Definition: types.h:120
const char * ws
Definition: skip_ws.cpp:7
int CDECL _wcreat(const wchar_t *path, int flags)
Definition: file.c:2048
#define _O_SHORT_LIVED
Definition: cabinet.h:49
int CDECL _waccess_s(const wchar_t *filename, int mode)
Definition: file.c:750
#define _lock
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
#define TMP_MAX
Definition: stdio.h:67
int CDECL getchar(void)
Definition: file.c:3627
#define _O_RDONLY
Definition: cabinet.h:37
#define INVALID_SET_FILE_POINTER
Definition: winbase.h:115
static ioinfo * get_ioinfo_nolock(int fd)
Definition: file.c:158
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK void ULONG PLARGE_INTEGER offset
Definition: file.c:88
int CDECL putc(int c, FILE *file)
Definition: file.c:3685
#define _S_IREAD
Definition: cabinet.h:34
_Must_inspect_result_ _Out_ LPSIZE psize
Definition: ntgdi.h:1569
__int64 CDECL _filelengthi64(int fd)
Definition: file.c:1563
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static BOOL alloc_pioinfo_block(int fd)
Definition: file.c:191
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
int CDECL _flsbuf(int c, FILE *file)
Definition: _flsbuf.c:14
static int MSVCRT_stream_idx
Definition: file.c:135
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:101
static int tmpnam_unique
Definition: file.c:141
#define INT_MAX
Definition: limits.h:40
int CDECL fseek(FILE *file, long offset, int whence)
Definition: file.c:1310
static void remove_std_buffer(FILE *file)
Definition: file.c:611
static void init_ioinfo_cs(ioinfo *info)
Definition: file.c:169
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: file.c:40
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define WX_DONTINHERIT
Definition: file.c:97
void CDECL _unlock_file(FILE *file)
Definition: file.c:1205
CRITICAL_SECTION crit
Definition: file.c:130
LONG CDECL ftell(FILE *file)
Definition: file.c:3564
static HANDLE
Definition: file.c:109
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define _STREAM_LOCKS
Definition: mtdll.h:65
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
char *CDECL _mktemp(char *pattern)
Definition: file.c:1604
#define CP_ACP
Definition: compat.h:99
Definition: arc.h:39
GLuint GLuint GLsizei count
Definition: gl.h:1545
static char utf8_bom[3]
Definition: file.c:108
_CRTIMP unsigned long *__cdecl __doserrno(void)
Definition: errno.c:27
#define _O_CREAT
Definition: cabinet.h:46
#define MOVEFILE_COPY_ALLOWED
Definition: filesup.h:29
#define free
Definition: debug_ros.c:5
ssize_t pread(int fd, void *buf, size_t count, off_t offset)
#define FILE_CURRENT
Definition: winbase.h:113
int CDECL _dup(int od)
Definition: file.c:1025
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1154
#define WARN(fmt,...)
Definition: debug.h:111
static int MSVCRT_umask
Definition: file.c:138
#define MSVCRT__IOERR
Definition: msvcrt.h:690
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
ioinfo __badioinfo
Definition: file.c:126
void CDECL setbuf(FILE *file, char *buf)
Definition: file.c:3840
#define MB_PRECOMPOSED
Definition: winnls.h:278
static int(__cdecl *p_fopen_s)(FILE **
int CDECL rename(const char *oldpath, const char *newpath)
Definition: file.c:3774
GLintptr offset
Definition: glext.h:5920
int CDECL _wopen(const wchar_t *path, int flags,...)
Definition: file.c:2020
#define EF_CRIT_INIT
Definition: file.c:105
int CDECL _fputchar(int c)
Definition: file.c:3330
wint_t CDECL fputwc(wchar_t c, FILE *stream)
Definition: file.c:3145
GLdouble n
Definition: glext.h:7729
int CDECL puts(const char *s)
Definition: file.c:3709
__MINGW_EXTENSION typedef __int64 fpos_t
Definition: stdio.h:116
VOID WINAPI GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo)
Definition: proc.c:1350
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
char *CDECL _tempnam(const char *dir, const char *prefix)
Definition: file.c:2535
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
static int MSVCRT_max_streams
Definition: file.c:135
static int fd
Definition: io.c:51
__int64 CDECL _telli64(int fd)
Definition: file.c:2527
FILE * stdin
int CDECL _pipe(int *pfds, unsigned int psize, int textmode)
Definition: file.c:1702
int CDECL putchar(int c)
Definition: file.c:3693
const GLuint * buffers
Definition: glext.h:5916
#define BUFSIZ
Definition: nsplookup.c:26
#define WX_PIPE
Definition: file.c:95
static CRITICAL_SECTION MSVCRT_file_cs
Definition: file.c:147
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:419
int CDECL _wrename(const wchar_t *oldpath, const wchar_t *newpath)
Definition: file.c:3787
#define _IOSTRG
Definition: stdio.h:135
char * _tmpfname
Definition: mbstring.h:27
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
int CDECL feof(FILE *file)
Definition: file.c:2817
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
int CDECL _isatty(int fd)
Definition: file.c:565
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define R_OK
Definition: io.h:171
#define WX_APPEND
Definition: file.c:98
#define FILE_TYPE_UNKNOWN
Definition: winbase.h:255
unsigned split_oflags(unsigned oflags)
Definition: file.c:1671
#define _strdup
Definition: debug_ros.c:7
const char * filename
Definition: ioapi.h:135
int CDECL _creat(const char *path, int flags)
Definition: file.c:2039
#define NO_ERROR
Definition: dderror.h:5
Definition: arc.h:36
int CDECL _setmode(int fd, int mode)
Definition: file.c:2477
unsigned create_io_inherit_block(WORD *size, BYTE **block)
Definition: file.c:411
ioinfo * __pioinfo[MSVCRT_MAX_FILES/MSVCRT_FD_BLOCK_SIZE]
Definition: file.c:121
#define _O_APPEND
Definition: cabinet.h:41
int CDECL _commit(int fd)
Definition: file.c:829
int CDECL _getw(FILE *file)
Definition: file.c:2994
Definition: arc.h:48
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define FILE_SHARE_READ
Definition: compat.h:125
FILE * stdout
#define STDIN_FILENO
Definition: syshdrs.h:88
WINE_UNICODE_INLINE int strncmpW(const WCHAR *str1, const WCHAR *str2, int n)
Definition: unicode.h:235
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
int CDECL fopen_s(FILE **pFile, const char *filename, const char *mode)
Definition: file.c:3255
static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug
Definition: file.c:148
#define _O_WTEXT
Definition: fcntl.h:20
int CDECL _sopen_s(int *fd, const char *path, int oflags, int shflags, int pmode)
Definition: file.c:1962
int CDECL _putw(int val, FILE *file)
Definition: file.c:2764
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
#define _SH_DENYNO
Definition: share.h:17
static int msvcrt_init_fp(FILE *file, int fd, unsigned stream_flags)
Definition: file.c:382
int CDECL _access_s(const char *filename, int mode)
Definition: file.c:713
struct _test_info info[]
Definition: SetCursorPos.c:19
FILE *CDECL _wfdopen(int fd, const wchar_t *mode)
Definition: file.c:1520
#define WX_TEXT
Definition: file.c:100
#define _IOFBF
Definition: stdio.h:128
static int msvcrt_int_to_base32_w(int num, wchar_t *str)
Definition: file.c:645
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define _O_RDWR
Definition: cabinet.h:39
#define _O_EXCL
Definition: cabinet.h:48
int CDECL getc(FILE *file)
Definition: file.c:3635
char lookahead[3]
Definition: file.c:43
static void msvcrt_free_fd(int fd)
Definition: file.c:296
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
int CDECL _chsize_s(int fd, __int64 size)
Definition: file.c:1318
int CDECL _rmtmp(void)
Definition: file.c:2094
#define _O_NOINHERIT
Definition: cabinet.h:45
#define WX_TTY
Definition: file.c:99
static int msvcrt_get_flags(const wchar_t *mode, int *open_flags, int *stream_flags)
Definition: file.c:1385
#define _IOERR
Definition: stdio.h:134
#define DUPLICATE_SAME_ACCESS
GLenum GLint GLuint mask
Definition: glext.h:6028
#define _IOB_ENTRIES
Definition: stdio.h:23
#define va_end(ap)
Definition: acmsvcex.h:90
#define _IOREAD
Definition: stdio.h:125
#define CP_UTF8
Definition: nls.h:20
BOOL WINAPI UnlockFile(IN HANDLE hFile, IN DWORD dwFileOffsetLow, IN DWORD dwFileOffsetHigh, IN DWORD nNumberOfBytesToUnlockLow, IN DWORD nNumberOfBytesToUnlockHigh)
Definition: lock.c:142
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
wchar_t * msvcrt_wstrdupa(const char *str)
Definition: file.c:670
#define FILE_TYPE_CHAR
Definition: winbase.h:257
int CDECL fputws(const wchar_t *s, FILE *file)
Definition: file.c:3597
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
FILE *CDECL tmpfile(void)
Definition: file.c:3912
#define GENERIC_WRITE
Definition: nt_native.h:90
int CDECL _read(int fd, void *buf, unsigned int count)
Definition: file.c:2466
#define debugstr_w
Definition: kernel32.h:32
HANDLE handle
Definition: file.c:41
#define FIXME(fmt,...)
Definition: debug.h:110
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
int CDECL fgetpos(FILE *file, fpos_t *pos)
Definition: file.c:3572
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
#define pp
Definition: hlsl.yy.c:978
int wint_t
Definition: _apple.h:38
int CDECL _filbuf(FILE *file)
Definition: file.c:2833
#define MSVCRT_INVALID_PMT(x)
Definition: mbstowcs_s.c:25
const WCHAR * str
Definition: arc.h:49
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
smooth NULL
Definition: ftsmooth.c:416
PBYTE lpReserved2
Definition: winbase.h:810
int exflag
Definition: file.c:44
unsigned char
Definition: typeof.h:29
static int get_utf8_char_len(char ch)
Definition: file.c:2116
__int64 CDECL _lseeki64(int fd, __int64 offset, int whence)
Definition: file.c:1138
int CDECL _wremove(const wchar_t *path)
Definition: file.c:3761
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
char * va_list
Definition: acmsvcex.h:78
BOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:926
#define _O_TRUNC
Definition: cabinet.h:47
#define _S_IWRITE
Definition: cabinet.h:33
#define STDOUT_FILENO
Definition: syshdrs.h:89
int CDECL _sopen(const char *path, int oflags, int shflags,...)
Definition: file.c:1978
unsigned int dir
Definition: maze.c:112
#define STD_INPUT_HANDLE
Definition: winbase.h:264
int CDECL _setmaxstdio(int newmax)
Definition: file.c:4034
#define _IOEOF
Definition: stdio.h:133
FILE *CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share)
Definition: file.c:3185
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
int msvcrt_alloc_fd(HANDLE hand, int flag)
Definition: file.c:343
#define _SH_DENYWR
Definition: share.h:15
int CDECL _umask(int umask)
Definition: file.c:2574
#define OPEN_EXISTING
Definition: compat.h:426
#define _O_U8TEXT
Definition: fcntl.h:22
GLuint GLfloat * val
Definition: glext.h:7180
#define UNLOCK_FILES()
Definition: file.c:156
static int msvcrt_int_to_base32(int num, char *str)
Definition: file.c:620
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
wchar_t *CDECL _wtmpnam(wchar_t *s)
Definition: file.c:3880
int CDECL _close(int fd)
Definition: file.c:931
#define SEEK_SET
Definition: jmemansi.c:26
unsigned char wxflag
Definition: file.c:42
#define TRACE(s)
Definition: solgame.cpp:4
int CDECL _fcloseall(void)
Definition: file.c:1081
GLsizeiptr size
Definition: glext.h:5919
#define _SH_DENYRW
Definition: share.h:14