ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

file.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS CRT library
00003  * LICENSE:         LGPL - See COPYING in the top level directory
00004  * FILE:            lib/sdk/crt/stdio/file.c
00005  * PURPOSE:         File CRT functions
00006  * PROGRAMMERS:     Wine team
00007  *                  Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org)
00008  */
00009 
00010 /*
00011  * msvcrt.dll file functions
00012  *
00013  * Copyright 1996,1998 Marcus Meissner
00014  * Copyright 1996 Jukka Iivonen
00015  * Copyright 1997,2000 Uwe Bonnes
00016  * Copyright 2000 Jon Griffiths
00017  * Copyright 2004 Eric Pouech
00018  * Copyright 2004 Juan Lang
00019  *
00020  * This library is free software; you can redistribute it and/or
00021  * modify it under the terms of the GNU Lesser General Public
00022  * License as published by the Free Software Foundation; either
00023  * version 2.1 of the License, or (at your option) any later version.
00024  *
00025  * This library is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028  * Lesser General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU Lesser General Public
00031  * License along with this library; if not, write to the Free Software
00032  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00033  *
00034  * TODO
00035  * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED
00036  */
00037 
00038 #include <precomp.h>
00039 #include "wine/unicode.h"
00040 
00041 #include <sys/utime.h>
00042 #include <direct.h>
00043 
00044 int *__p__fmode(void);
00045 int *__p___mb_cur_max(void);
00046 
00047 #ifdef feof
00048 #undef feof
00049 #endif
00050 #ifdef _fileno
00051 #undef _fileno
00052 #endif
00053 #ifdef ferror
00054 #undef ferror
00055 #endif
00056 #ifdef clearerr
00057 #undef clearerr
00058 #endif
00059 
00060 #undef getc
00061 #undef getwc
00062 #undef getchar
00063 #undef getwchar
00064 #undef putc
00065 #undef putwc
00066 #undef putchar
00067 #undef putwchar
00068 
00069 #undef vprintf
00070 #undef vwprintf
00071 
00072 /* _access() bit flags FIXME: incomplete */
00073 /* defined in crt/io.h */
00074 
00075 /* values for wxflag in file descriptor */
00076 #define WX_OPEN           0x01
00077 #define WX_ATEOF          0x02
00078 #define WX_READEOF        0x04  /* like ATEOF, but for underlying file rather than buffer */
00079 #define WX_READCR         0x08  /* underlying file is at \r */
00080 #define WX_DONTINHERIT    0x10
00081 #define WX_APPEND         0x20
00082 #define WX_TEXT           0x80
00083 
00084 /* FIXME: this should be allocated dynamically */
00085 #define MAX_FILES 2048
00086 #define FD_BLOCK_SIZE 64
00087 
00088 typedef struct {
00089     HANDLE              handle;
00090     unsigned char       wxflag;
00091     char                unk1;
00092     BOOL                crit_init;
00093     CRITICAL_SECTION    crit;
00094 } ioinfo;
00095 
00096 /*********************************************************************
00097  *      __pioinfo (MSVCRT.@)
00098  * array of pointers to ioinfo arrays [64]
00099  */
00100 ioinfo * __pioinfo[MAX_FILES/FD_BLOCK_SIZE] = { 0 };
00101 
00102 /*********************************************************************
00103  *      __badioinfo (MSVCRT.@)
00104  */
00105 ioinfo __badioinfo = { INVALID_HANDLE_VALUE, WX_TEXT };
00106 
00107 static int fdstart = 3; /* first unallocated fd */
00108 static int fdend = 3; /* highest allocated fd */
00109 
00110 typedef struct {
00111     FILE file;
00112     CRITICAL_SECTION crit;
00113 } file_crit;
00114 
00115 FILE _iob[_IOB_ENTRIES] = { { 0 } };
00116 static file_crit* fstream[MAX_FILES/FD_BLOCK_SIZE] = { NULL };
00117 static int max_streams = 512, stream_idx;
00118 
00119 /* INTERNAL: process umask */
00120 static int MSVCRT_umask = 0;
00121 
00122 /* INTERNAL: static data for tmpnam and _wtmpname functions */
00123 static int tmpnam_unique;
00124 
00125 /* This critical section protects the tables __pioinfo and fstreams,
00126  * and their related indexes, fdstart, fdend,
00127  * and stream_idx, from race conditions.
00128  * It doesn't protect against race conditions manipulating the underlying files
00129  * or flags; doing so would probably be better accomplished with per-file
00130  * protection, rather than locking the whole table for every change.
00131  */
00132 static CRITICAL_SECTION file_cs;
00133 #define LOCK_FILES()    do { EnterCriticalSection(&file_cs); } while (0)
00134 #define UNLOCK_FILES()  do { LeaveCriticalSection(&file_cs); } while (0)
00135 
00136 static inline ioinfo* get_ioinfo(int fd)
00137 {
00138     ioinfo *ret = NULL;
00139     if(fd < MAX_FILES)
00140         ret = __pioinfo[fd/FD_BLOCK_SIZE];
00141     if(!ret)
00142         return &__badioinfo;
00143 
00144     return ret + (fd%FD_BLOCK_SIZE);
00145 }
00146 
00147 static inline FILE* get_file(int i)
00148 {
00149     file_crit *ret;
00150 
00151     if(i >= max_streams)
00152         return NULL;
00153 
00154     if(i < _IOB_ENTRIES)
00155         return &_iob[i];
00156 
00157     ret = fstream[i/FD_BLOCK_SIZE];
00158     if(!ret) {
00159         fstream[i/FD_BLOCK_SIZE] = calloc(FD_BLOCK_SIZE, sizeof(file_crit));
00160         if(!fstream[i/FD_BLOCK_SIZE]) {
00161             ERR("out of memory\n");
00162             *_errno() = ENOMEM;
00163             return NULL;
00164         }
00165 
00166         ret = fstream[i/FD_BLOCK_SIZE] + (i%FD_BLOCK_SIZE);
00167     } else
00168         ret += i%FD_BLOCK_SIZE;
00169 
00170     return &ret->file;
00171 }
00172 
00173 static inline BOOL is_valid_fd(int fd)
00174 {
00175     return fd >= 0 && fd < fdend && (get_ioinfo(fd)->wxflag & WX_OPEN);
00176 }
00177 
00178 /* INTERNAL: Get the HANDLE for a fd
00179  * This doesn't lock the table, because a failure will result in
00180  * INVALID_HANDLE_VALUE being returned, which should be handled correctly.  If
00181  * it returns a valid handle which is about to be closed, a subsequent call
00182  * will fail, most likely in a sane way.
00183  */
00184 /*static*/ HANDLE fdtoh(int fd)
00185 {
00186   if (!is_valid_fd(fd))
00187   {
00188     WARN(":fd (%d) - no handle!\n",fd);
00189     *__doserrno() = 0;
00190     *_errno() = EBADF;
00191     return INVALID_HANDLE_VALUE;
00192   }
00193   //if (get_ioinfo(fd)->handle == INVALID_HANDLE_VALUE)
00194       //FIXME("returning INVALID_HANDLE_VALUE for %d\n", fd);
00195   return get_ioinfo(fd)->handle;
00196 }
00197 
00198 /* INTERNAL: free a file entry fd */
00199 static void free_fd(int fd)
00200 {
00201   HANDLE old_handle;
00202   ioinfo *fdinfo;
00203 
00204   LOCK_FILES();
00205   fdinfo = get_ioinfo(fd);
00206   old_handle = fdinfo->handle;
00207   if(fdinfo != &__badioinfo)
00208   {
00209     fdinfo->handle = INVALID_HANDLE_VALUE;
00210     fdinfo->wxflag = 0;
00211   }
00212   TRACE(":fd (%d) freed\n",fd);
00213   if (fd < 3) /* don't use 0,1,2 for user files */
00214   {
00215     switch (fd)
00216     {
00217     case 0:
00218         if (GetStdHandle(STD_INPUT_HANDLE) == old_handle) SetStdHandle(STD_INPUT_HANDLE, 0);
00219         break;
00220     case 1:
00221         if (GetStdHandle(STD_OUTPUT_HANDLE) == old_handle) SetStdHandle(STD_OUTPUT_HANDLE, 0);
00222         break;
00223     case 2:
00224         if (GetStdHandle(STD_ERROR_HANDLE) == old_handle) SetStdHandle(STD_ERROR_HANDLE, 0);
00225         break;
00226     }
00227   }
00228   else
00229   {
00230     if (fd == fdend - 1)
00231       fdend--;
00232     if (fd < fdstart)
00233       fdstart = fd;
00234   }
00235   UNLOCK_FILES();
00236 }
00237 
00238 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
00239 /* caller must hold the files lock */
00240 static int alloc_fd_from(HANDLE hand, int flag, int fd)
00241 {
00242   ioinfo *fdinfo;
00243 
00244   if (fd >= MAX_FILES)
00245   {
00246     WARN(":files exhausted!\n");
00247     *_errno() = ENFILE;
00248     return -1;
00249   }
00250 
00251   fdinfo = get_ioinfo(fd);
00252   if(fdinfo == &__badioinfo) {
00253     int i;
00254 
00255     __pioinfo[fd/FD_BLOCK_SIZE] = calloc(FD_BLOCK_SIZE, sizeof(ioinfo));
00256     if(!__pioinfo[fd/FD_BLOCK_SIZE]) {
00257       WARN(":out of memory!\n");
00258       *_errno() = ENOMEM;
00259       return -1;
00260     }
00261 
00262     for(i=0; i<FD_BLOCK_SIZE; i++)
00263       __pioinfo[fd/FD_BLOCK_SIZE][i].handle = INVALID_HANDLE_VALUE;
00264 
00265     fdinfo = get_ioinfo(fd);
00266   }
00267 
00268   fdinfo->handle = hand;
00269   fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT));
00270 
00271   /* locate next free slot */
00272   if (fd == fdstart && fd == fdend)
00273     fdstart = fdend + 1;
00274   else
00275     while (fdstart < fdend &&
00276       get_ioinfo(fdstart)->handle != INVALID_HANDLE_VALUE)
00277       fdstart++;
00278   /* update last fd in use */
00279   if (fd >= fdend)
00280     fdend = fd + 1;
00281   TRACE("fdstart is %d, fdend is %d\n", fdstart, fdend);
00282 
00283   switch (fd)
00284   {
00285   case 0: SetStdHandle(STD_INPUT_HANDLE,  hand); break;
00286   case 1: SetStdHandle(STD_OUTPUT_HANDLE, hand); break;
00287   case 2: SetStdHandle(STD_ERROR_HANDLE,  hand); break;
00288   }
00289 
00290   return fd;
00291 }
00292 
00293 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
00294 /*static*/ int alloc_fd(HANDLE hand, int flag)
00295 {
00296   int ret;
00297 
00298   LOCK_FILES();
00299   TRACE(":handle (%p) allocating fd (%d)\n",hand,fdstart);
00300   ret = alloc_fd_from(hand, flag, fdstart);
00301   UNLOCK_FILES();
00302   return ret;
00303 }
00304 
00305 /* INTERNAL: Allocate a FILE* for an fd slot */
00306 /* caller must hold the files lock */
00307 static FILE* alloc_fp(void)
00308 {
00309   unsigned int i;
00310   FILE *file;
00311 
00312   for (i = 3; i < max_streams; i++)
00313   {
00314     file = get_file(i);
00315     if (!file)
00316       return NULL;
00317 
00318     if (file->_flag == 0)
00319     {
00320       if (i == stream_idx) stream_idx++;
00321       return file;
00322     }
00323   }
00324 
00325   return NULL;
00326 }
00327 
00328 /* INTERNAL: initialize a FILE* from an open fd */
00329 static int init_fp(FILE* file, int fd, unsigned stream_flags)
00330 {
00331   TRACE(":fd (%d) allocating FILE*\n",fd);
00332   if (!is_valid_fd(fd))
00333   {
00334     WARN(":invalid fd %d\n",fd);
00335     *__doserrno() = 0;
00336     *_errno() = EBADF;
00337     return -1;
00338   }
00339   memset(file, 0, sizeof(*file));
00340   file->_file = fd;
00341   file->_flag = stream_flags;
00342 
00343   if(file<_iob || file>=_iob+_IOB_ENTRIES)
00344       InitializeCriticalSection(&((file_crit*)file)->crit);
00345 
00346   TRACE(":got FILE* (%p)\n",file);
00347   return 0;
00348 }
00349 
00350 /* INTERNAL: Create an inheritance data block (for spawned process)
00351  * The inheritance block is made of:
00352  *      00      int     nb of file descriptor (NBFD)
00353  *      04      char    file flags (wxflag): repeated for each fd
00354  *      4+NBFD  HANDLE  file handle: repeated for each fd
00355  */
00356 unsigned create_io_inherit_block(WORD *size, BYTE **block)
00357 {
00358   int         fd;
00359   char*       wxflag_ptr;
00360   HANDLE*     handle_ptr;
00361   ioinfo*     fdinfo;
00362 
00363   *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * fdend;
00364   *block = calloc(*size, 1);
00365   if (!*block)
00366   {
00367     *size = 0;
00368     return FALSE;
00369   }
00370   wxflag_ptr = (char*)*block + sizeof(unsigned);
00371   handle_ptr = (HANDLE*)(wxflag_ptr + fdend * sizeof(char));
00372 
00373   *(unsigned*)*block = fdend;
00374   for (fd = 0; fd < fdend; fd++)
00375   {
00376     /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
00377     fdinfo = get_ioinfo(fd);
00378     if ((fdinfo->wxflag & (WX_OPEN | WX_DONTINHERIT)) == WX_OPEN)
00379     {
00380       *wxflag_ptr = fdinfo->wxflag;
00381       *handle_ptr = fdinfo->handle;
00382     }
00383     else
00384     {
00385       *wxflag_ptr = 0;
00386       *handle_ptr = INVALID_HANDLE_VALUE;
00387     }
00388     wxflag_ptr++; handle_ptr++;
00389   } 
00390   return TRUE;
00391 }
00392 
00393 /* INTERNAL: Set up all file descriptors, 
00394  * as well as default streams (stdin, stderr and stdout) 
00395  */
00396 void msvcrt_init_io(void)
00397 {
00398   STARTUPINFOA  si;
00399   int           i;
00400   ioinfo        *fdinfo;
00401 
00402   InitializeCriticalSection(&file_cs);
00403   file_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": file_cs");
00404   GetStartupInfoA(&si);
00405   if (si.cbReserved2 >= sizeof(unsigned int) && si.lpReserved2 != NULL)
00406   {
00407     BYTE*       wxflag_ptr;
00408     HANDLE*     handle_ptr;
00409     unsigned int count;
00410 
00411     count = *(unsigned*)si.lpReserved2;
00412     wxflag_ptr = si.lpReserved2 + sizeof(unsigned);
00413     handle_ptr = (HANDLE*)(wxflag_ptr + count);
00414 
00415     count = min(count, (si.cbReserved2 - sizeof(unsigned)) / (sizeof(HANDLE) + 1));
00416     count = min(count, MAX_FILES);
00417     for (i = 0; i < count; i++)
00418     {
00419       if ((*wxflag_ptr & WX_OPEN) && *handle_ptr != INVALID_HANDLE_VALUE)
00420         alloc_fd_from(*handle_ptr, *wxflag_ptr, i);
00421 
00422       wxflag_ptr++; handle_ptr++;
00423     }
00424     fdend = max( 3, count );
00425     for (fdstart = 3; fdstart < fdend; fdstart++)
00426         if (get_ioinfo(fdstart)->handle == INVALID_HANDLE_VALUE) break;
00427   }
00428 
00429   if(!__pioinfo[0])
00430       alloc_fd_from(INVALID_HANDLE_VALUE, 0, 3);
00431 
00432   fdinfo = get_ioinfo(0);
00433   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
00434   {
00435       HANDLE std = GetStdHandle(STD_INPUT_HANDLE);
00436 #ifndef __REACTOS__
00437       if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
00438                                                          GetCurrentProcess(), &fdinfo->handle,
00439                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
00440 #else
00441           fdinfo->handle = std;
00442 #endif
00443           fdinfo->wxflag = WX_OPEN | WX_TEXT;
00444   }
00445 
00446   fdinfo = get_ioinfo(1);
00447   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
00448   {
00449       HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
00450 #ifndef __REACTOS__
00451       if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
00452                                                          GetCurrentProcess(), &fdinfo->handle,
00453                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
00454 #else
00455           fdinfo->handle = std;
00456 #endif
00457           fdinfo->wxflag = WX_OPEN | WX_TEXT;
00458   }
00459 
00460   fdinfo = get_ioinfo(2);
00461   if (!(fdinfo->wxflag & WX_OPEN) || fdinfo->handle == INVALID_HANDLE_VALUE)
00462   {
00463       HANDLE std = GetStdHandle(STD_ERROR_HANDLE);
00464 #ifndef __REACTOS__
00465       if (std != INVALID_HANDLE_VALUE && DuplicateHandle(GetCurrentProcess(), std,
00466                                                          GetCurrentProcess(), &fdinfo->handle,
00467                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
00468 #else
00469           fdinfo->handle = std;
00470 #endif
00471           fdinfo->wxflag = WX_OPEN | WX_TEXT;
00472   }
00473 
00474   TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo(0)->handle,
00475     get_ioinfo(1)->handle, get_ioinfo(2)->handle);
00476 
00477   memset(_iob,0,3*sizeof(FILE));
00478   for (i = 0; i < 3; i++)
00479   {
00480     /* FILE structs for stdin/out/err are static and never deleted */
00481     _iob[i]._file = i;
00482     _iob[i]._tmpfname = NULL;
00483     _iob[i]._flag = (i == 0) ? _IOREAD : _IOWRT;
00484   }
00485   stream_idx = 3;
00486 }
00487 
00488 /* INTERNAL: Flush stdio file buffer */
00489 static int flush_buffer(FILE* file)
00490 {
00491   if(file->_bufsiz) {
00492         int cnt=file->_ptr-file->_base;
00493         if(cnt>0 && _write(file->_file, file->_base, cnt) != cnt) {
00494             file->_flag |= _IOERR;
00495             return EOF;
00496         }
00497         file->_ptr=file->_base;
00498         file->_cnt=file->_bufsiz;
00499   }
00500   return 0;
00501 }
00502 
00503 /* INTERNAL: Allocate stdio file buffer */
00504 /*static*/ void alloc_buffer(FILE* file)
00505 {
00506     file->_base = calloc(BUFSIZ,1);
00507     if(file->_base) {
00508         file->_bufsiz = BUFSIZ;
00509         file->_flag |= _IOMYBUF;
00510     } else {
00511         file->_base = (char*)(&file->_charbuf);
00512         /* put here 2 ??? */
00513         file->_bufsiz = sizeof(file->_charbuf);
00514     }
00515     file->_ptr = file->_base;
00516     file->_cnt = 0;
00517 }
00518 
00519 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
00520 static int int_to_base32(int num, char *str)
00521 {
00522   char *p;
00523   int n = num;
00524   int digits = 0;
00525 
00526   while (n != 0)
00527   {
00528     n >>= 5;
00529     digits++;
00530   }
00531   p = str + digits;
00532   *p = 0;
00533   while (--p >= str)
00534   {
00535     *p = (num & 31) + '0';
00536     if (*p > '9')
00537       *p += ('a' - '0' - 10);
00538     num >>= 5;
00539   }
00540 
00541   return digits;
00542 }
00543 
00544 /* INTERNAL: wide character version of int_to_base32 */
00545 static int int_to_base32_w(int num, wchar_t *str)
00546 {
00547     wchar_t *p;
00548     int n = num;
00549     int digits = 0;
00550 
00551     while (n != 0)
00552     {
00553         n >>= 5;
00554         digits++;
00555     }
00556     p = str + digits;
00557     *p = 0;
00558     while (--p >= str)
00559     {
00560         *p = (num & 31) + '0';
00561         if (*p > '9')
00562             *p += ('a' - '0' - 10);
00563         num >>= 5;
00564     }
00565 
00566     return digits;
00567 }
00568 
00569 /* INTERNAL: Create a wide string from an ascii string */
00570 wchar_t *msvcrt_wstrdupa(const char *str)
00571 {
00572   const unsigned int len = strlen(str) + 1 ;
00573   wchar_t *wstr = malloc(len* sizeof (wchar_t));
00574   if (!wstr)
00575     return NULL;
00576    MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len);
00577   return wstr;
00578 }
00579 
00580 /*********************************************************************
00581  *      __iob_func(MSVCRT.@)
00582  */
00583 FILE * CDECL __iob_func(void)
00584 {
00585  return &_iob[0];
00586 }
00587 
00588 /*********************************************************************
00589  *      _access (MSVCRT.@)
00590  */
00591 int CDECL _access(const char *filename, int mode)
00592 {
00593   DWORD attr = GetFileAttributesA(filename);
00594 
00595   TRACE("(%s,%d) %d\n",filename,mode,attr);
00596 
00597   if (!filename || attr == INVALID_FILE_ATTRIBUTES)
00598   {
00599     _dosmaperr(GetLastError());
00600     return -1;
00601   }
00602   if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
00603   {
00604     _set_errno(ERROR_ACCESS_DENIED);
00605     return -1;
00606   }
00607   return 0;
00608 }
00609 
00610 /*********************************************************************
00611  *      _access_s (MSVCRT.@)
00612  */
00613 int CDECL _access_s(const char *filename, int mode)
00614 {
00615   if (!MSVCRT_CHECK_PMT(filename != NULL) ||
00616       !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0))
00617   {
00618      _set_errno(EINVAL);
00619      return -1;
00620   }
00621 
00622   return _access(filename, mode);
00623 }
00624 
00625 /*********************************************************************
00626  *      _waccess (MSVCRT.@)
00627  */
00628 int CDECL _waccess(const wchar_t *filename, int mode)
00629 {
00630   DWORD attr = GetFileAttributesW(filename);
00631 
00632   TRACE("(%s,%d) %d\n",debugstr_w(filename),mode,attr);
00633 
00634   if (!filename || attr == INVALID_FILE_ATTRIBUTES)
00635   {
00636     _dosmaperr(GetLastError());
00637     return -1;
00638   }
00639   if ((attr & FILE_ATTRIBUTE_READONLY) && (mode & W_OK))
00640   {
00641     _set_errno(ERROR_ACCESS_DENIED);
00642     return -1;
00643   }
00644   return 0;
00645 }
00646 
00647 /*********************************************************************
00648  *      _waccess_s (MSVCRT.@)
00649  */
00650 int CDECL _waccess_s(const wchar_t *filename, int mode)
00651 {
00652   if (!MSVCRT_CHECK_PMT(filename != NULL) ||
00653       !MSVCRT_CHECK_PMT((mode & ~(R_OK | W_OK)) == 0))
00654   {
00655      *_errno() = EINVAL;
00656      return -1;
00657   }
00658 
00659   return _waccess(filename, mode);
00660 }
00661 
00662 /*********************************************************************
00663  *      _chmod (MSVCRT.@)
00664  */
00665 int CDECL _chmod(const char *path, int flags)
00666 {
00667   DWORD oldFlags = GetFileAttributesA(path);
00668 
00669   if (oldFlags != INVALID_FILE_ATTRIBUTES)
00670   {
00671     DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
00672       oldFlags | FILE_ATTRIBUTE_READONLY;
00673 
00674     if (newFlags == oldFlags || SetFileAttributesA(path, newFlags))
00675       return 0;
00676   }
00677   _dosmaperr(GetLastError());
00678   return -1;
00679 }
00680 
00681 /*********************************************************************
00682  *      _wchmod (MSVCRT.@)
00683  */
00684 int CDECL _wchmod(const wchar_t *path, int flags)
00685 {
00686   DWORD oldFlags = GetFileAttributesW(path);
00687 
00688   if (oldFlags != INVALID_FILE_ATTRIBUTES)
00689   {
00690     DWORD newFlags = (flags & _S_IWRITE)? oldFlags & ~FILE_ATTRIBUTE_READONLY:
00691       oldFlags | FILE_ATTRIBUTE_READONLY;
00692 
00693     if (newFlags == oldFlags || SetFileAttributesW(path, newFlags))
00694       return 0;
00695   }
00696   _dosmaperr(GetLastError());
00697   return -1;
00698 }
00699 
00700 /*********************************************************************
00701  *      _unlink (MSVCRT.@)
00702  */
00703 int CDECL _unlink(const char *path)
00704 {
00705   TRACE("%s\n",debugstr_a(path));
00706   if(DeleteFileA(path))
00707     return 0;
00708   TRACE("failed (%d)\n",GetLastError());
00709   _dosmaperr(GetLastError());
00710   return -1;
00711 }
00712 
00713 /*********************************************************************
00714  *      _wunlink (MSVCRT.@)
00715  */
00716 int CDECL _wunlink(const wchar_t *path)
00717 {
00718   TRACE("(%s)\n",debugstr_w(path));
00719   if(DeleteFileW(path))
00720     return 0;
00721   TRACE("failed (%d)\n",GetLastError());
00722   _dosmaperr(GetLastError());
00723   return -1;
00724 }
00725 
00726 /* _flushall calls fflush which calls _flushall */
00727 int CDECL fflush(FILE* file);
00728 
00729 /*********************************************************************
00730  *      _flushall (MSVCRT.@)
00731  */
00732 int CDECL _flushall(void)
00733 {
00734   int i, num_flushed = 0;
00735   FILE *file;
00736 
00737   LOCK_FILES();
00738   for (i = 3; i < stream_idx; i++) {
00739     file = get_file(i);
00740 
00741     if (file->_flag)
00742     {
00743       if(file->_flag & _IOWRT) {
00744     fflush(file);
00745         num_flushed++;
00746       }
00747     }
00748   }
00749   UNLOCK_FILES();
00750 
00751   TRACE(":flushed (%d) handles\n",num_flushed);
00752   return num_flushed;
00753 }
00754 
00755 /*********************************************************************
00756  *      fflush (MSVCRT.@)
00757  */
00758 int CDECL fflush(FILE* file)
00759 {
00760     if(!file) {
00761         _flushall();
00762     } else if(file->_flag & _IOWRT) {
00763         int res;
00764 
00765         _lock_file(file);
00766         res = flush_buffer(file);
00767         _unlock_file(file);
00768 
00769         return res;
00770     }
00771     return 0;
00772 }
00773 
00774 /*********************************************************************
00775  *      _close (MSVCRT.@)
00776  */
00777 int CDECL _close(int fd)
00778 {
00779   HANDLE hand;
00780   int ret;
00781 
00782   LOCK_FILES();
00783   hand = fdtoh(fd);
00784   TRACE(":fd (%d) handle (%p)\n",fd,hand);
00785   if (hand == INVALID_HANDLE_VALUE)
00786     ret = -1;
00787   else if (!CloseHandle(hand))
00788   {
00789     WARN(":failed-last error (%d)\n",GetLastError());
00790     _dosmaperr(GetLastError());
00791     ret = -1;
00792   }
00793   else
00794   {
00795     free_fd(fd);
00796     ret = 0;
00797   }
00798   UNLOCK_FILES();
00799   TRACE(":ok\n");
00800   return ret;
00801 }
00802 
00803 /*********************************************************************
00804  *      _commit (MSVCRT.@)
00805  */
00806 int CDECL _commit(int fd)
00807 {
00808   HANDLE hand = fdtoh(fd);
00809 
00810   TRACE(":fd (%d) handle (%p)\n",fd,hand);
00811   if (hand == INVALID_HANDLE_VALUE)
00812     return -1;
00813 
00814   if (!FlushFileBuffers(hand))
00815   {
00816     if (GetLastError() == ERROR_INVALID_HANDLE)
00817     {
00818       /* FlushFileBuffers fails for console handles
00819        * so we ignore this error.
00820        */
00821       return 0;
00822     }
00823     TRACE(":failed-last error (%d)\n",GetLastError());
00824     _dosmaperr(GetLastError());
00825     return -1;
00826   }
00827   TRACE(":ok\n");
00828   return 0;
00829 }
00830 
00831 /*********************************************************************
00832  *      _dup2 (MSVCRT.@)
00833  * NOTES
00834  * MSDN isn't clear on this point, but the remarks for _pipe
00835  * indicate file descriptors duplicated with _dup and _dup2 are always
00836  * inheritable.
00837  */
00838 int CDECL _dup2(int od, int nd)
00839 {
00840   int ret;
00841 
00842   TRACE("(od=%d, nd=%d)\n", od, nd);
00843   LOCK_FILES();
00844   if (nd < MAX_FILES && nd >= 0 && is_valid_fd(od))
00845   {
00846     HANDLE handle;
00847 
00848     if (DuplicateHandle(GetCurrentProcess(), get_ioinfo(od)->handle,
00849      GetCurrentProcess(), &handle, 0, TRUE, DUPLICATE_SAME_ACCESS))
00850     {
00851       int wxflag = get_ioinfo(od)->wxflag & ~_O_NOINHERIT;
00852 
00853       if (is_valid_fd(nd))
00854         _close(nd);
00855       ret = alloc_fd_from(handle, wxflag, nd);
00856       if (ret == -1)
00857       {
00858         CloseHandle(handle);
00859         *_errno() = EMFILE;
00860       }
00861       else
00862       {
00863         /* _dup2 returns 0, not nd, on success */
00864         ret = 0;
00865       }
00866     }
00867     else
00868     {
00869       ret = -1;
00870       _dosmaperr(GetLastError());
00871     }
00872   }
00873   else
00874   {
00875     *_errno() = EBADF;
00876     ret = -1;
00877   }
00878   UNLOCK_FILES();
00879   return ret;
00880 }
00881 
00882 /*********************************************************************
00883  *      _dup (MSVCRT.@)
00884  */
00885 int CDECL _dup(int od)
00886 {
00887   int fd, ret;
00888 
00889   LOCK_FILES();
00890   fd = fdstart;
00891   if (_dup2(od, fd) == 0)
00892     ret = fd;
00893   else
00894     ret = -1;
00895   UNLOCK_FILES();
00896   return ret;
00897 }
00898 
00899 /*********************************************************************
00900  *      _eof (MSVCRT.@)
00901  */
00902 int CDECL _eof(int fd)
00903 {
00904   DWORD curpos,endpos;
00905   LONG hcurpos,hendpos;
00906   HANDLE hand = fdtoh(fd);
00907 
00908   TRACE(":fd (%d) handle (%p)\n",fd,hand);
00909 
00910   if (hand == INVALID_HANDLE_VALUE)
00911     return -1;
00912 
00913   if (get_ioinfo(fd)->wxflag & WX_ATEOF) return TRUE;
00914 
00915   /* Otherwise we do it the hard way */
00916   hcurpos = hendpos = 0;
00917   curpos = SetFilePointer(hand, 0, &hcurpos, FILE_CURRENT);
00918   endpos = SetFilePointer(hand, 0, &hendpos, FILE_END);
00919 
00920   if (curpos == endpos && hcurpos == hendpos)
00921   {
00922     /* FIXME: shouldn't WX_ATEOF be set here? */
00923     return TRUE;
00924   }
00925 
00926   SetFilePointer(hand, curpos, &hcurpos, FILE_BEGIN);
00927   return FALSE;
00928 }
00929 
00930 /*********************************************************************
00931  *      _fcloseall (MSVCRT.@)
00932  */
00933 int CDECL _fcloseall(void)
00934 {
00935   int num_closed = 0, i;
00936   FILE *file;
00937 
00938   LOCK_FILES();
00939   for (i = 3; i < stream_idx; i++) {
00940     file = get_file(i);
00941 
00942     if (file->_flag && !fclose(file))
00943       num_closed++;
00944   }
00945   UNLOCK_FILES();
00946 
00947   TRACE(":closed (%d) handles\n",num_closed);
00948   return num_closed;
00949 }
00950 
00951 /* free everything on process exit */
00952 void msvcrt_free_io(void)
00953 {
00954     int i;
00955 
00956     _fcloseall();
00957     /* The Win32 _fcloseall() function explicitly doesn't close stdin,
00958      * stdout, and stderr (unlike GNU), so we need to fclose() them here
00959      * or they won't get flushed.
00960      */
00961     fclose(&_iob[0]);
00962     fclose(&_iob[1]);
00963     fclose(&_iob[2]);
00964 
00965     for(i=0; i<sizeof(__pioinfo)/sizeof(__pioinfo[0]); i++)
00966         free(__pioinfo[i]);
00967 
00968     for(i=0; i<sizeof(fstream)/sizeof(fstream[0]); i++)
00969         free(fstream[i]);
00970 
00971     file_cs.DebugInfo->Spare[0] = 0;
00972     DeleteCriticalSection(&file_cs);
00973 }
00974 
00975 /*********************************************************************
00976  *      _lseeki64 (MSVCRT.@)
00977  */
00978 __int64 CDECL _lseeki64(int fd, __int64 offset, int whence)
00979 {
00980   HANDLE hand = fdtoh(fd);
00981   LARGE_INTEGER ofs;
00982 
00983   TRACE(":fd (%d) handle (%p)\n",fd,hand);
00984   if (hand == INVALID_HANDLE_VALUE)
00985     return -1;
00986 
00987   if (whence < 0 || whence > 2)
00988   {
00989     *_errno() = EINVAL;
00990     return -1;
00991   }
00992 
00993   TRACE(":fd (%d) to %s pos %s\n",
00994         fd,wine_dbgstr_longlong(offset),
00995         (whence==SEEK_SET)?"SEEK_SET":
00996         (whence==SEEK_CUR)?"SEEK_CUR":
00997         (whence==SEEK_END)?"SEEK_END":"UNKNOWN");
00998 
00999   /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
01000    * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
01001   ofs.QuadPart = offset;
01002   if ((ofs.u.LowPart = SetFilePointer(hand, ofs.u.LowPart, &ofs.u.HighPart, whence)) != INVALID_SET_FILE_POINTER ||
01003       GetLastError() == ERROR_SUCCESS)
01004   {
01005     get_ioinfo(fd)->wxflag &= ~(WX_ATEOF|WX_READEOF);
01006     /* FIXME: What if we seek _to_ EOF - is EOF set? */
01007 
01008     return ofs.QuadPart;
01009   }
01010   TRACE(":error-last error (%d)\n",GetLastError());
01011   _dosmaperr(GetLastError());
01012   return -1;
01013 }
01014 
01015 /*********************************************************************
01016  *      _lseek (MSVCRT.@)
01017  */
01018 LONG CDECL _lseek(int fd, LONG offset, int whence)
01019 {
01020     return _lseeki64(fd, offset, whence);
01021 }
01022 
01023 /*********************************************************************
01024  *              _lock_file (MSVCRT.@)
01025  */
01026 void CDECL _lock_file(FILE *file)
01027 {
01028     if(file>=_iob && file<_iob+_IOB_ENTRIES)
01029         _lock(_STREAM_LOCKS+(file-_iob));
01030     /* ReactOS: string streams dont need to be locked */
01031     else if(!(file->_flag & _IOSTRG))
01032         EnterCriticalSection(&((file_crit*)file)->crit);
01033 }
01034 
01035 /*********************************************************************
01036  *              _unlock_file (MSVCRT.@)
01037  */
01038 void CDECL _unlock_file(FILE *file)
01039 {
01040     if(file>=_iob && file<_iob+_IOB_ENTRIES)
01041         _unlock(_STREAM_LOCKS+(file-_iob));
01042     /* ReactOS: string streams dont need to be locked */
01043     else if(!(file->_flag & _IOSTRG))
01044         LeaveCriticalSection(&((file_crit*)file)->crit);
01045 
01046 }
01047 
01048 /*********************************************************************
01049  *      _locking (MSVCRT.@)
01050  *
01051  * This is untested; the underlying LockFile doesn't work yet.
01052  */
01053 int CDECL _locking(int fd, int mode, LONG nbytes)
01054 {
01055   BOOL ret;
01056   DWORD cur_locn;
01057   HANDLE hand = fdtoh(fd);
01058 
01059   TRACE(":fd (%d) handle (%p)\n",fd,hand);
01060   if (hand == INVALID_HANDLE_VALUE)
01061     return -1;
01062 
01063   if (mode < 0 || mode > 4)
01064   {
01065     *_errno() = EINVAL;
01066     return -1;
01067   }
01068 
01069   TRACE(":fd (%d) by 0x%08x mode %s\n",
01070         fd,nbytes,(mode==_LK_UNLCK)?"_LK_UNLCK":
01071         (mode==_LK_LOCK)?"_LK_LOCK":
01072         (mode==_LK_NBLCK)?"_LK_NBLCK":
01073         (mode==_LK_RLCK)?"_LK_RLCK":
01074         (mode==_LK_NBRLCK)?"_LK_NBRLCK":
01075                           "UNKNOWN");
01076 
01077   if ((cur_locn = SetFilePointer(hand, 0L, NULL, SEEK_CUR)) == INVALID_SET_FILE_POINTER)
01078   {
01079     FIXME ("Seek failed\n");
01080     *_errno() = EINVAL; /* FIXME */
01081     return -1;
01082   }
01083   if (mode == _LK_LOCK || mode == _LK_RLCK)
01084   {
01085     int nretry = 10;
01086     ret = 1; /* just to satisfy gcc */
01087     while (nretry--)
01088     {
01089       ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
01090       if (ret) break;
01091       Sleep(1);
01092     }
01093   }
01094   else if (mode == _LK_UNLCK)
01095     ret = UnlockFile(hand, cur_locn, 0L, nbytes, 0L);
01096   else
01097     ret = LockFile(hand, cur_locn, 0L, nbytes, 0L);
01098   /* FIXME - what about error settings? */
01099   return ret ? 0 : -1;
01100 }
01101 
01102 /*********************************************************************
01103  *      _fseeki64 (MSVCRT.@)
01104  */
01105 int CDECL _fseeki64(FILE* file, __int64 offset, int whence)
01106 {
01107   int ret;
01108 
01109   _lock_file(file);
01110   /* Flush output if needed */
01111   if(file->_flag & _IOWRT)
01112     flush_buffer(file);
01113 
01114   if(whence == SEEK_CUR && file->_flag & _IOREAD ) {
01115     offset -= file->_cnt;
01116     if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
01117         /* Black magic correction for CR removal */
01118         int i;
01119         for (i=0; i<file->_cnt; i++) {
01120             if (file->_ptr[i] == '\n')
01121                 offset--;
01122         }
01123         /* Black magic when reading CR at buffer boundary*/
01124         if(get_ioinfo(file->_file)->wxflag & WX_READCR)
01125             offset--;
01126     }
01127   }
01128   /* Discard buffered input */
01129   file->_cnt = 0;
01130   file->_ptr = file->_base;
01131   /* Reset direction of i/o */
01132   if(file->_flag & _IORW) {
01133         file->_flag &= ~(_IOREAD|_IOWRT);
01134   }
01135   /* Clear end of file flag */
01136   file->_flag &= ~_IOEOF;
01137   ret = (_lseeki64(file->_file,offset,whence) == -1)?-1:0;
01138 
01139   _unlock_file(file);
01140   return ret;
01141 }
01142 
01143 /*********************************************************************
01144  *      fseek (MSVCRT.@)
01145  */
01146 int CDECL fseek(FILE* file, long offset, int whence)
01147 {
01148     return _fseeki64( file, offset, whence );
01149 }
01150 
01151 /*********************************************************************
01152  *      _chsize (MSVCRT.@)
01153  */
01154 int CDECL _chsize(int fd, long size)
01155 {
01156     LONG cur, pos;
01157     HANDLE handle;
01158     BOOL ret = FALSE;
01159 
01160     TRACE("(fd=%d, size=%d)\n", fd, size);
01161 
01162     LOCK_FILES();
01163 
01164     handle = fdtoh(fd);
01165     if (handle != INVALID_HANDLE_VALUE)
01166     {
01167         /* save the current file pointer */
01168         cur = _lseek(fd, 0, SEEK_CUR);
01169         if (cur >= 0)
01170         {
01171             pos = _lseek(fd, size, SEEK_SET);
01172             if (pos >= 0)
01173             {
01174                 ret = SetEndOfFile(handle);
01175                 if (!ret) _dosmaperr(GetLastError());
01176             }
01177 
01178             /* restore the file pointer */
01179             _lseek(fd, cur, SEEK_SET);
01180         }
01181     }
01182 
01183     UNLOCK_FILES();
01184     return ret ? 0 : -1;
01185 }
01186 
01187 /*********************************************************************
01188  *      clearerr (MSVCRT.@)
01189  */
01190 void CDECL clearerr(FILE* file)
01191 {
01192   TRACE(":file (%p) fd (%d)\n",file,file->_file);
01193 
01194   _lock_file(file);
01195   file->_flag &= ~(_IOERR | _IOEOF);
01196   _unlock_file(file);
01197 }
01198 
01199 /*********************************************************************
01200  *      rewind (MSVCRT.@)
01201  */
01202 void CDECL rewind(FILE* file)
01203 {
01204   TRACE(":file (%p) fd (%d)\n",file,file->_file);
01205 
01206   _lock_file(file);
01207   fseek(file, 0L, SEEK_SET);
01208   clearerr(file);
01209   _unlock_file(file);
01210 }
01211 
01212 static int get_flags(const wchar_t* mode, int *open_flags, int* stream_flags)
01213 {
01214   int plus = strchrW(mode, '+') != NULL;
01215 
01216   switch(*mode++)
01217   {
01218   case 'R': case 'r':
01219     *open_flags = plus ? _O_RDWR : _O_RDONLY;
01220     *stream_flags = plus ? _IORW : _IOREAD;
01221     break;
01222   case 'W': case 'w':
01223     *open_flags = _O_CREAT | _O_TRUNC | (plus  ? _O_RDWR : _O_WRONLY);
01224     *stream_flags = plus ? _IORW : _IOWRT;
01225     break;
01226   case 'A': case 'a':
01227     *open_flags = _O_CREAT | _O_APPEND | (plus  ? _O_RDWR : _O_WRONLY);
01228     *stream_flags = plus ? _IORW : _IOWRT;
01229     break;
01230   default:
01231     _invalid_parameter(NULL, NULL, NULL, 0, 0);
01232     *_errno() = EINVAL;
01233     return -1;
01234   }
01235 
01236   while (*mode)
01237     switch (*mode++)
01238     {
01239     case 'B': case 'b':
01240       *open_flags |=  _O_BINARY;
01241       *open_flags &= ~_O_TEXT;
01242       break;
01243     case 'T': case 't':
01244       *open_flags |=  _O_TEXT;
01245       *open_flags &= ~_O_BINARY;
01246       break;
01247     case '+':
01248     case ' ':
01249       break;
01250     default:
01251       FIXME(":unknown flag %c not supported\n",mode[-1]);
01252     }
01253   return 0;
01254 }
01255 
01256 /*********************************************************************
01257  *      _fdopen (MSVCRT.@)
01258  */
01259 FILE* CDECL _fdopen(int fd, const char *mode)
01260 {
01261     FILE *ret;
01262     wchar_t *modeW = NULL;
01263 
01264     if (mode && !(modeW = msvcrt_wstrdupa(mode))) return NULL;
01265 
01266     ret = _wfdopen(fd, modeW);
01267 
01268     free(modeW);
01269     return ret;
01270 }
01271 
01272 /*********************************************************************
01273  *      _wfdopen (MSVCRT.@)
01274  */
01275 FILE* CDECL _wfdopen(int fd, const wchar_t *mode)
01276 {
01277   int open_flags, stream_flags;
01278   FILE* file;
01279 
01280   if (get_flags(mode, &open_flags, &stream_flags) == -1) return NULL;
01281 
01282   LOCK_FILES();
01283   if (!(file = alloc_fp()))
01284     file = NULL;
01285   else if (init_fp(file, fd, stream_flags) == -1)
01286   {
01287     file->_flag = 0;
01288     file = NULL;
01289   }
01290   else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
01291   UNLOCK_FILES();
01292 
01293   return file;
01294 }
01295 
01296 /*********************************************************************
01297  *      _filelength (MSVCRT.@)
01298  */
01299 LONG CDECL _filelength(int fd)
01300 {
01301   LONG curPos = _lseek(fd, 0, SEEK_CUR);
01302   if (curPos != -1)
01303   {
01304     LONG endPos = _lseek(fd, 0, SEEK_END);
01305     if (endPos != -1)
01306     {
01307       if (endPos != curPos)
01308         _lseek(fd, curPos, SEEK_SET);
01309       return endPos;
01310     }
01311   }
01312   return -1;
01313 }
01314 
01315 /*********************************************************************
01316  *      _filelengthi64 (MSVCRT.@)
01317  */
01318 __int64 CDECL _filelengthi64(int fd)
01319 {
01320   __int64 curPos = _lseeki64(fd, 0, SEEK_CUR);
01321   if (curPos != -1)
01322   {
01323     __int64 endPos = _lseeki64(fd, 0, SEEK_END);
01324     if (endPos != -1)
01325     {
01326       if (endPos != curPos)
01327         _lseeki64(fd, curPos, SEEK_SET);
01328       return endPos;
01329     }
01330   }
01331   return -1;
01332 }
01333 
01334 /*********************************************************************
01335  *      _fileno (MSVCRT.@)
01336  */
01337 int CDECL _fileno(FILE* file)
01338 {
01339   TRACE(":FILE* (%p) fd (%d)\n",file,file->_file);
01340   return file->_file;
01341 }
01342 
01343 /*********************************************************************
01344  *      _get_osfhandle (MSVCRT.@)
01345  */
01346 intptr_t CDECL _get_osfhandle(int fd)
01347 {
01348   HANDLE hand = fdtoh(fd);
01349   TRACE(":fd (%d) handle (%p)\n",fd,hand);
01350 
01351   return (intptr_t)hand;
01352 }
01353 
01354 /*********************************************************************
01355  *      _isatty (MSVCRT.@)
01356  */
01357 int CDECL _isatty(int fd)
01358 {
01359   HANDLE hand = fdtoh(fd);
01360 
01361   TRACE(":fd (%d) handle (%p)\n",fd,hand);
01362   if (hand == INVALID_HANDLE_VALUE)
01363     return 0;
01364 
01365   return GetFileType(hand) == FILE_TYPE_CHAR? 1 : 0;
01366 }
01367 
01368 /*********************************************************************
01369  *      _mktemp (MSVCRT.@)
01370  */
01371 char * CDECL _mktemp(char *pattern)
01372 {
01373   int numX = 0;
01374   char *retVal = pattern;
01375   int id;
01376   char letter = 'a';
01377 
01378   while(*pattern)
01379     numX = (*pattern++ == 'X')? numX + 1 : 0;
01380   if (numX < 5)
01381     return NULL;
01382   pattern--;
01383   id = GetCurrentProcessId();
01384   numX = 6;
01385   while(numX--)
01386   {
01387     int tempNum = id / 10;
01388     *pattern-- = id - (tempNum * 10) + '0';
01389     id = tempNum;
01390   }
01391   pattern++;
01392   do
01393   {
01394     *pattern = letter++;
01395     if (GetFileAttributesA(retVal) == INVALID_FILE_ATTRIBUTES &&
01396         GetLastError() == ERROR_FILE_NOT_FOUND)
01397       return retVal;
01398   } while(letter <= 'z');
01399   return NULL;
01400 }
01401 
01402 /*********************************************************************
01403  *      _wmktemp (MSVCRT.@)
01404  */
01405 wchar_t * CDECL _wmktemp(wchar_t *pattern)
01406 {
01407   int numX = 0;
01408   wchar_t *retVal = pattern;
01409   int id;
01410   wchar_t letter = 'a';
01411 
01412   while(*pattern)
01413     numX = (*pattern++ == 'X')? numX + 1 : 0;
01414   if (numX < 5)
01415     return NULL;
01416   pattern--;
01417   id = GetCurrentProcessId();
01418   numX = 6;
01419   while(numX--)
01420   {
01421     int tempNum = id / 10;
01422     *pattern-- = id - (tempNum * 10) + '0';
01423     id = tempNum;
01424   }
01425   pattern++;
01426   do
01427   {
01428     if (GetFileAttributesW(retVal) == INVALID_FILE_ATTRIBUTES &&
01429         GetLastError() == ERROR_FILE_NOT_FOUND)
01430       return retVal;
01431     *pattern = letter++;
01432   } while(letter != '|');
01433   return NULL;
01434 }
01435 
01436 /*static*/ unsigned split_oflags(unsigned oflags)
01437 {
01438     int         wxflags = 0;
01439     unsigned unsupp; /* until we support everything */
01440 
01441     if (oflags & _O_APPEND)              wxflags |= WX_APPEND;
01442     if (oflags & _O_BINARY)              {/* Nothing to do */}
01443     else if (oflags & _O_TEXT)           wxflags |= WX_TEXT;
01444     else if (*__p__fmode() & _O_BINARY)  {/* Nothing to do */}
01445     else                                        wxflags |= WX_TEXT; /* default to TEXT*/
01446     if (oflags & _O_NOINHERIT)           wxflags |= WX_DONTINHERIT;
01447 
01448     if ((unsupp = oflags & ~(
01449                     _O_BINARY|_O_TEXT|_O_APPEND|
01450                     _O_TRUNC|_O_EXCL|_O_CREAT|
01451                     _O_RDWR|_O_WRONLY|_O_TEMPORARY|
01452                     _O_NOINHERIT|
01453                     _O_SEQUENTIAL|_O_RANDOM|_O_SHORT_LIVED
01454                     )))
01455         ERR(":unsupported oflags 0x%04x\n",unsupp);
01456 
01457     return wxflags;
01458 }
01459 
01460 /*********************************************************************
01461  *              _pipe (MSVCRT.@)
01462  */
01463 int CDECL _pipe(int *pfds, unsigned int psize, int textmode)
01464 {
01465   int ret = -1;
01466   SECURITY_ATTRIBUTES sa;
01467   HANDLE readHandle, writeHandle;
01468 
01469   if (!pfds)
01470   {
01471     *_errno() = EINVAL;
01472     return -1;
01473   }
01474 
01475   sa.nLength = sizeof(SECURITY_ATTRIBUTES);
01476   sa.bInheritHandle = !(textmode & _O_NOINHERIT);
01477   sa.lpSecurityDescriptor = NULL;
01478   if (CreatePipe(&readHandle, &writeHandle, &sa, psize))
01479   {
01480     unsigned int wxflags = split_oflags(textmode);
01481     int fd;
01482 
01483     LOCK_FILES();
01484     fd = alloc_fd(readHandle, wxflags);
01485     if (fd != -1)
01486     {
01487       pfds[0] = fd;
01488       fd = alloc_fd(writeHandle, wxflags);
01489       if (fd != -1)
01490       {
01491         pfds[1] = fd;
01492         ret = 0;
01493       }
01494       else
01495       {
01496         _close(pfds[0]);
01497         CloseHandle(writeHandle);
01498         *_errno() = EMFILE;
01499       }
01500     }
01501     else
01502     {
01503       CloseHandle(readHandle);
01504       CloseHandle(writeHandle);
01505       *_errno() = EMFILE;
01506     }
01507     UNLOCK_FILES();
01508   }
01509   else
01510     _dosmaperr(GetLastError());
01511 
01512   return ret;
01513 }
01514 
01515 /*********************************************************************
01516  *              _sopen_s (MSVCRT.@)
01517  */
01518 int CDECL _sopen_s( int *fd, const char *path, int oflags, int shflags, int pmode )
01519 {
01520   DWORD access = 0, creation = 0, attrib;
01521   DWORD sharing;
01522   int wxflag;
01523   HANDLE hand;
01524   SECURITY_ATTRIBUTES sa;
01525 
01526   TRACE("fd*: %p file: (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
01527         fd, path, oflags, shflags, pmode);
01528 
01529   if (!fd)
01530   {
01531     MSVCRT_INVALID_PMT("null out fd pointer");
01532     *_errno() = EINVAL;
01533     return EINVAL;
01534   }
01535 
01536   *fd = -1;
01537   wxflag = split_oflags(oflags);
01538   switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
01539   {
01540   case _O_RDONLY: access |= GENERIC_READ; break;
01541   case _O_WRONLY: access |= GENERIC_WRITE; break;
01542   case _O_RDWR:   access |= GENERIC_WRITE | GENERIC_READ; break;
01543   }
01544 
01545   if (oflags & _O_CREAT)
01546   {
01547     if(pmode & ~(_S_IREAD | _S_IWRITE))
01548       FIXME(": pmode 0x%04x ignored\n", pmode);
01549     else
01550       WARN(": pmode 0x%04x ignored\n", pmode);
01551 
01552     if (oflags & _O_EXCL)
01553       creation = CREATE_NEW;
01554     else if (oflags & _O_TRUNC)
01555       creation = CREATE_ALWAYS;
01556     else
01557       creation = OPEN_ALWAYS;
01558   }
01559   else  /* no _O_CREAT */
01560   {
01561     if (oflags & _O_TRUNC)
01562       creation = TRUNCATE_EXISTING;
01563     else
01564       creation = OPEN_EXISTING;
01565   }
01566   
01567   switch( shflags )
01568   {
01569     case _SH_DENYRW:
01570       sharing = 0L;
01571       break;
01572     case _SH_DENYWR:
01573       sharing = FILE_SHARE_READ;
01574       break;
01575     case _SH_DENYRD:
01576       sharing = FILE_SHARE_WRITE;
01577       break;
01578     case _SH_DENYNO:
01579       sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
01580       break;
01581     default:
01582       ERR( "Unhandled shflags 0x%x\n", shflags );
01583       return EINVAL;
01584   }
01585   attrib = FILE_ATTRIBUTE_NORMAL;
01586 
01587   if (oflags & _O_TEMPORARY)
01588   {
01589       attrib |= FILE_FLAG_DELETE_ON_CLOSE;
01590       access |= DELETE;
01591       sharing |= FILE_SHARE_DELETE;
01592   }
01593 
01594   sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
01595   sa.lpSecurityDescriptor = NULL;
01596   sa.bInheritHandle       = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
01597 
01598   hand = CreateFileA(path, access, sharing, &sa, creation, attrib, 0);
01599   if (hand == INVALID_HANDLE_VALUE)  {
01600     WARN(":failed-last error (%d)\n", GetLastError());
01601     _dosmaperr(GetLastError());
01602     return *_errno();
01603   }
01604 
01605   *fd = alloc_fd(hand, wxflag);
01606 
01607   TRACE(":fd (%d) handle (%p)\n", *fd, hand);
01608   return 0;
01609 }
01610 
01611 /*********************************************************************
01612  *              _sopen (MSVCRT.@)
01613  */
01614 int CDECL _sopen( const char *path, int oflags, int shflags, ... )
01615 {
01616   int pmode;
01617   int fd;
01618 
01619   if (oflags & _O_CREAT)
01620   {
01621     va_list ap;
01622 
01623     va_start(ap, shflags);
01624     pmode = va_arg(ap, int);
01625     va_end(ap);
01626   }
01627   else
01628     pmode = 0;
01629 
01630   _sopen_s(&fd, path, oflags, shflags, pmode);
01631   return fd;
01632 }
01633 
01634 /*********************************************************************
01635  *              _wsopen_s (MSVCRT.@)
01636  */
01637 int CDECL _wsopen_s( int *fd, const wchar_t* path, int oflags, int shflags, int pmode )
01638 {
01639   DWORD access = 0, creation = 0, attrib;
01640   SECURITY_ATTRIBUTES sa;
01641   DWORD sharing;
01642   int wxflag;
01643   HANDLE hand;
01644 
01645   TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
01646         fd, debugstr_w(path), oflags, shflags, pmode);
01647 
01648   if (!fd)
01649   {
01650     MSVCRT_INVALID_PMT("null out fd pointer");
01651     *_errno() = EINVAL;
01652     return EINVAL;
01653   }
01654 
01655   *fd = -1;
01656   wxflag = split_oflags(oflags);
01657   switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR))
01658   {
01659   case _O_RDONLY: access |= GENERIC_READ; break;
01660   case _O_WRONLY: access |= GENERIC_WRITE; break;
01661   case _O_RDWR:   access |= GENERIC_WRITE | GENERIC_READ; break;
01662   }
01663 
01664   if (oflags & _O_CREAT)
01665   {
01666     if(pmode & ~(_S_IREAD | _S_IWRITE))
01667       FIXME(": pmode 0x%04x ignored\n", pmode);
01668     else
01669       WARN(": pmode 0x%04x ignored\n", pmode);
01670 
01671     if (oflags & _O_EXCL)
01672       creation = CREATE_NEW;
01673     else if (oflags & _O_TRUNC)
01674       creation = CREATE_ALWAYS;
01675     else
01676       creation = OPEN_ALWAYS;
01677   }
01678   else  /* no _O_CREAT */
01679   {
01680     if (oflags & _O_TRUNC)
01681       creation = TRUNCATE_EXISTING;
01682     else
01683       creation = OPEN_EXISTING;
01684   }
01685 
01686   switch( shflags )
01687   {
01688     case _SH_DENYRW:
01689       sharing = 0L;
01690       break;
01691     case _SH_DENYWR:
01692       sharing = FILE_SHARE_READ;
01693       break;
01694     case _SH_DENYRD:
01695       sharing = FILE_SHARE_WRITE;
01696       break;
01697     case _SH_DENYNO:
01698       sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
01699       break;
01700     default:
01701       ERR( "Unhandled shflags 0x%x\n", shflags );
01702       return EINVAL;
01703   }
01704   attrib = FILE_ATTRIBUTE_NORMAL;
01705 
01706   if (oflags & _O_TEMPORARY)
01707   {
01708       attrib |= FILE_FLAG_DELETE_ON_CLOSE;
01709       access |= DELETE;
01710       sharing |= FILE_SHARE_DELETE;
01711   }
01712 
01713   sa.nLength              = sizeof( SECURITY_ATTRIBUTES );
01714   sa.lpSecurityDescriptor = NULL;
01715   sa.bInheritHandle       = (oflags & _O_NOINHERIT) ? FALSE : TRUE;
01716 
01717   hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
01718 
01719   if (hand == INVALID_HANDLE_VALUE)  {
01720     WARN(":failed-last error (%d)\n",GetLastError());
01721     _dosmaperr(GetLastError());
01722     return *_errno();
01723   }
01724 
01725   *fd = alloc_fd(hand, wxflag);
01726 
01727   TRACE(":fd (%d) handle (%p)\n", *fd, hand);
01728   return 0;
01729 }
01730 
01731 /*********************************************************************
01732  *              _wsopen (MSVCRT.@)
01733  */
01734 int CDECL _wsopen( const wchar_t *path, int oflags, int shflags, ... )
01735 {
01736   int pmode;
01737   int fd;
01738 
01739   if (oflags & _O_CREAT)
01740   {
01741     va_list ap;
01742 
01743     va_start(ap, shflags);
01744     pmode = va_arg(ap, int);
01745     va_end(ap);
01746   }
01747   else
01748     pmode = 0;
01749 
01750   _wsopen_s(&fd, path, oflags, shflags, pmode);
01751   return fd;
01752 }
01753 
01754 /*********************************************************************
01755  *              _open (MSVCRT.@)
01756  */
01757 int CDECL _open( const char *path, int flags, ... )
01758 {
01759   va_list ap;
01760 
01761   if (flags & _O_CREAT)
01762   {
01763     int pmode;
01764     va_start(ap, flags);
01765     pmode = va_arg(ap, int);
01766     va_end(ap);
01767     return _sopen( path, flags, _SH_DENYNO, pmode );
01768   }
01769   else
01770     return _sopen( path, flags, _SH_DENYNO);
01771 }
01772 
01773 /*********************************************************************
01774  *              _wopen (MSVCRT.@)
01775  */
01776 int CDECL _wopen(const wchar_t *path,int flags,...)
01777 {
01778   va_list ap;
01779 
01780   if (flags & _O_CREAT)
01781   {
01782     int pmode;
01783     va_start(ap, flags);
01784     pmode = va_arg(ap, int);
01785     va_end(ap);
01786     return _wsopen( path, flags, _SH_DENYNO, pmode );
01787   }
01788   else
01789     return _wsopen( path, flags, _SH_DENYNO);
01790 }
01791 
01792 /*********************************************************************
01793  *      _creat (MSVCRT.@)
01794  */
01795 int CDECL _creat(const char *path, int flags)
01796 {
01797   int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
01798   return _open(path, usedFlags);
01799 }
01800 
01801 /*********************************************************************
01802  *      _wcreat (MSVCRT.@)
01803  */
01804 int CDECL _wcreat(const wchar_t *path, int flags)
01805 {
01806   int usedFlags = (flags & _O_TEXT)| _O_CREAT| _O_WRONLY| _O_TRUNC;
01807   return _wopen(path, usedFlags);
01808 }
01809 
01810 /*********************************************************************
01811  *      _open_osfhandle (MSVCRT.@)
01812  */
01813 int CDECL _open_osfhandle(intptr_t handle, int oflags)
01814 {
01815   int fd;
01816 
01817   /* _O_RDONLY (0) always matches, so set the read flag
01818    * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
01819    * file, so set the write flag. It also only sets _O_TEXT if it wants
01820    * text - it never sets _O_BINARY.
01821    */
01822   /* don't let split_oflags() decide the mode if no mode is passed */
01823   if (!(oflags & (_O_BINARY | _O_TEXT)))
01824       oflags |= _O_BINARY;
01825 
01826   fd = alloc_fd((HANDLE)handle, split_oflags(oflags));
01827   TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle, fd, oflags);
01828   return fd;
01829 }
01830 
01831 /*********************************************************************
01832  *      _rmtmp (MSVCRT.@)
01833  */
01834 int CDECL _rmtmp(void)
01835 {
01836   int num_removed = 0, i;
01837   FILE *file;
01838 
01839   LOCK_FILES();
01840   for (i = 3; i < stream_idx; i++) {
01841     file = get_file(i);
01842 
01843     if (file->_tmpfname)
01844     {
01845       fclose(file);
01846       num_removed++;
01847     }
01848   }
01849   UNLOCK_FILES();
01850 
01851   if (num_removed)
01852     TRACE(":removed (%d) temp files\n",num_removed);
01853   return num_removed;
01854 }
01855 
01856 /*********************************************************************
01857  * (internal) read_i
01858  *
01859  * When reading \r as last character in text mode, read() positions
01860  * the file pointer on the \r character while getc() goes on to
01861  * the following \n
01862  */
01863 static int read_i(int fd, void *buf, unsigned int count)
01864 {
01865   DWORD num_read;
01866   char *bufstart = buf;
01867   HANDLE hand = fdtoh(fd);
01868   ioinfo *fdinfo = get_ioinfo(fd);
01869 
01870   if (count == 0)
01871     return 0;
01872 
01873   if (fdinfo->wxflag & WX_READEOF) {
01874      fdinfo->wxflag |= WX_ATEOF;
01875      TRACE("already at EOF, returning 0\n");
01876      return 0;
01877   }
01878   /* Don't trace small reads, it gets *very* annoying */
01879   if (count > 4)
01880     TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
01881   if (hand == INVALID_HANDLE_VALUE)
01882     return -1;
01883 
01884   /* Reading single bytes in O_TEXT mode makes things slow
01885    * So read big chunks
01886    */
01887     if (ReadFile(hand, bufstart, count, &num_read, NULL))
01888     {
01889         if (count != 0 && num_read == 0)
01890         {
01891             fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
01892             TRACE(":EOF %s\n",debugstr_an(buf,num_read));
01893         }
01894         else if (fdinfo->wxflag & WX_TEXT)
01895         {
01896             DWORD i, j;
01897             if (bufstart[num_read-1] == '\r')
01898             {
01899                 if(count == 1)
01900                 {
01901                     fdinfo->wxflag  &=  ~WX_READCR;
01902                     ReadFile(hand, bufstart, 1, &num_read, NULL);
01903                 }
01904                 else
01905                 {
01906                     fdinfo->wxflag  |= WX_READCR;
01907                     num_read--;
01908                 }
01909             }
01910         else
01911           fdinfo->wxflag  &=  ~WX_READCR;
01912             for (i=0, j=0; i<num_read; i++)
01913             {
01914                 /* in text mode, a ctrl-z signals EOF */
01915                 if (bufstart[i] == 0x1a)
01916                 {
01917                     fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
01918                     TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
01919                     break;
01920                 }
01921                 /* in text mode, strip \r if followed by \n.
01922                  * BUG: should save state across calls somehow, so CR LF that
01923                  * straddles buffer boundary gets recognized properly?
01924                  */
01925         if ((bufstart[i] != '\r')
01926                 ||  ((i+1) < num_read && bufstart[i+1] != '\n'))
01927             bufstart[j++] = bufstart[i];
01928             }
01929             num_read = j;
01930         }
01931     }
01932     else
01933     {
01934         if (GetLastError() == ERROR_BROKEN_PIPE)
01935         {
01936             TRACE(":end-of-pipe\n");
01937             fdinfo->wxflag |= (WX_ATEOF|WX_READEOF);
01938             return 0;
01939         }
01940         else
01941         {
01942             TRACE(":failed-last error (%d)\n",GetLastError());
01943             return -1;
01944         }
01945     }
01946 
01947   if (count > 4)
01948       TRACE("(%u), %s\n",num_read,debugstr_an(buf, num_read));
01949   return num_read;
01950 }
01951 
01952 /*********************************************************************
01953  *      _read (MSVCRT.@)
01954  */
01955 int CDECL _read(int fd, void *buf, unsigned int count)
01956 {
01957   int num_read;
01958   num_read = read_i(fd, buf, count);
01959   return num_read;
01960 }
01961 
01962 /*********************************************************************
01963  *      _setmode (MSVCRT.@)
01964  */
01965 int CDECL _setmode(int fd,int mode)
01966 {
01967   int ret = get_ioinfo(fd)->wxflag & WX_TEXT ? _O_TEXT : _O_BINARY;
01968   if (mode & (~(_O_TEXT|_O_BINARY)))
01969     FIXME("fd (%d) mode (0x%08x) unknown\n",fd,mode);
01970   if ((mode & _O_TEXT) == _O_TEXT)
01971     get_ioinfo(fd)->wxflag |= WX_TEXT;
01972   else
01973     get_ioinfo(fd)->wxflag &= ~WX_TEXT;
01974   return ret;
01975 }
01976 
01977 /*********************************************************************
01978  *      _tell (MSVCRT.@)
01979  */
01980 long CDECL _tell(int fd)
01981 {
01982   return _lseek(fd, 0, SEEK_CUR);
01983 }
01984 
01985 /*********************************************************************
01986  *      _telli64 (MSVCRT.@)
01987  */
01988 __int64 CDECL _telli64(int fd)
01989 {
01990   return _lseeki64(fd, 0, SEEK_CUR);
01991 }
01992 
01993 /*********************************************************************
01994  *      _tempnam (MSVCRT.@)
01995  */
01996 char * CDECL _tempnam(const char *dir, const char *prefix)
01997 {
01998   char tmpbuf[MAX_PATH];
01999   const char *tmp_dir = getenv("TMP");
02000 
02001   if (tmp_dir) dir = tmp_dir;
02002 
02003   TRACE("dir (%s) prefix (%s)\n",dir,prefix);
02004   if (GetTempFileNameA(dir,prefix,0,tmpbuf))
02005   {
02006     TRACE("got name (%s)\n",tmpbuf);
02007     DeleteFileA(tmpbuf);
02008     return _strdup(tmpbuf);
02009   }
02010   TRACE("failed (%d)\n",GetLastError());
02011   return NULL;
02012 }
02013 
02014 /*********************************************************************
02015  *      _wtempnam (MSVCRT.@)
02016  */
02017 wchar_t * CDECL _wtempnam(const wchar_t *dir, const wchar_t *prefix)
02018 {
02019   wchar_t tmpbuf[MAX_PATH];
02020 
02021   TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir),debugstr_w(prefix));
02022   if (GetTempFileNameW(dir,prefix,0,tmpbuf))
02023   {
02024     TRACE("got name (%s)\n",debugstr_w(tmpbuf));
02025     DeleteFileW(tmpbuf);
02026     return _wcsdup(tmpbuf);
02027   }
02028   TRACE("failed (%d)\n",GetLastError());
02029   return NULL;
02030 }
02031 
02032 /*********************************************************************
02033  *      _umask (MSVCRT.@)
02034  */
02035 int CDECL _umask(int umask)
02036 {
02037   int old_umask = umask;
02038   TRACE("(%d)\n",umask);
02039   MSVCRT_umask = umask;
02040   return old_umask;
02041 }
02042 
02043 /*********************************************************************
02044  *      _write (MSVCRT.@)
02045  */
02046 int CDECL _write(int fd, const void* buf, unsigned int count)
02047 {
02048   DWORD num_written;
02049   HANDLE hand = fdtoh(fd);
02050 
02051   /* Don't trace small writes, it gets *very* annoying */
02052 #if 0
02053   if (count > 32)
02054     TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count);
02055 #endif
02056   if (hand == INVALID_HANDLE_VALUE)
02057     {
02058       *_errno() = EBADF;
02059       return -1;
02060     }
02061 
02062   /* If appending, go to EOF */
02063   if (get_ioinfo(fd)->wxflag & WX_APPEND)
02064     _lseek(fd, 0, FILE_END);
02065 
02066   if (!(get_ioinfo(fd)->wxflag & WX_TEXT))
02067     {
02068       if (WriteFile(hand, buf, count, &num_written, NULL)
02069       &&  (num_written == count))
02070     return num_written;
02071       TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd,
02072        hand, GetLastError());
02073       *_errno() = ENOSPC;
02074     }
02075   else
02076   {
02077       unsigned int i, j, nr_lf;
02078       char *p = NULL;
02079       const char *q;
02080       const char *s = buf, *buf_start = buf;
02081       /* find number of \n ( without preceding \r ) */
02082       for ( nr_lf=0,i = 0; i <count; i++)
02083       {
02084           if (s[i]== '\n')
02085           {
02086               nr_lf++;
02087               /*if ((i >1) && (s[i-1] == '\r')) nr_lf--; */
02088           }
02089       }
02090       if (nr_lf)
02091       {
02092           if ((q = p = malloc(count + nr_lf)))
02093           {
02094               for (s = buf, i = 0, j = 0; i < count; i++)
02095               {
02096                   if (s[i]== '\n')
02097                   {
02098                       p[j++] = '\r';
02099                       /*if ((i >1) && (s[i-1] == '\r'))j--;*/
02100                   }
02101                   p[j++] = s[i];
02102               }
02103           }
02104           else
02105           {
02106               FIXME("Malloc failed\n");
02107               nr_lf =0;
02108               q = buf;
02109           }
02110       }
02111       else
02112           q = buf;
02113 
02114       if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf))
02115       {
02116           TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
02117            fd, hand, GetLastError(), num_written);
02118           *_errno() = ENOSPC;
02119           if(nr_lf)
02120               free(p);
02121           return s - buf_start;
02122       }
02123       else
02124       {
02125           if(nr_lf)
02126               free(p);
02127           return count;
02128       }
02129   }
02130   return -1;
02131 }
02132 
02133 /*********************************************************************
02134  *      _putw (MSVCRT.@)
02135  */
02136 int CDECL _putw(int val, FILE* file)
02137 {
02138   int len;
02139 
02140   _lock_file(file);
02141   len = _write(file->_file, &val, sizeof(val));
02142   if (len == sizeof(val)) {
02143     _unlock_file(file);
02144     return val;
02145   }
02146 
02147   file->_flag |= _IOERR;
02148   _unlock_file(file);
02149   return EOF;
02150 }
02151 
02152 /*********************************************************************
02153  *      fclose (MSVCRT.@)
02154  */
02155 int CDECL fclose(FILE* file)
02156 {
02157   int r, flag;
02158 
02159   _lock_file(file);
02160   flag = file->_flag;
02161   free(file->_tmpfname);
02162   file->_tmpfname = NULL;
02163   /* flush stdio buffers */
02164   if(file->_flag & _IOWRT)
02165       fflush(file);
02166   if(file->_flag & _IOMYBUF)
02167       free(file->_base);
02168 
02169   r=_close(file->_file);
02170 
02171   file->_flag = 0;
02172   _unlock_file(file);
02173   if(file<_iob || file>=_iob+_IOB_ENTRIES)
02174       DeleteCriticalSection(&((file_crit*)file)->crit);
02175 
02176   if(file == get_file(stream_idx-1)) {
02177     while(stream_idx>3 && !file->_flag) {
02178       stream_idx--;
02179       file = get_file(stream_idx-1);
02180     }
02181   }
02182 
02183   return ((r == -1) || (flag & _IOERR) ? EOF : 0);
02184 }
02185 
02186 /*********************************************************************
02187  *      feof (MSVCRT.@)
02188  */
02189 int CDECL feof(FILE* file)
02190 {
02191     int ret;
02192 
02193     _lock_file(file);
02194     ret = file->_flag & _IOEOF;
02195     _unlock_file(file);
02196 
02197     return ret;
02198 }
02199 
02200 /*********************************************************************
02201  *      ferror (MSVCRT.@)
02202  */
02203 int CDECL ferror(FILE* file)
02204 {
02205     int ret;
02206 
02207     _lock_file(file);
02208     ret = file->_flag & _IOERR;
02209     _unlock_file(file);
02210 
02211     return ret;
02212 }
02213 
02214 /*********************************************************************
02215  *      _filbuf (MSVCRT.@)
02216  */
02217 int CDECL _filbuf(FILE* file)
02218 {
02219     unsigned char c;
02220     _lock_file(file);
02221 
02222     /* Allocate buffer if needed */
02223     if(file->_bufsiz == 0 && !(file->_flag & _IONBF))
02224         alloc_buffer(file);
02225 
02226     if(!(file->_flag & _IOREAD)) {
02227         if(file->_flag & _IORW)
02228             file->_flag |= _IOREAD;
02229         else {
02230             _unlock_file(file);
02231             return EOF;
02232         }
02233     }
02234 
02235     if(file->_flag & _IONBF) {
02236         int r;
02237         if ((r = read_i(file->_file,&c,1)) != 1) {
02238             file->_flag |= (r == 0) ? _IOEOF : _IOERR;
02239             _unlock_file(file);
02240             return EOF;
02241         }
02242 
02243         _unlock_file(file);
02244         return c;
02245     } else {
02246         file->_cnt = read_i(file->_file, file->_base, file->_bufsiz);
02247         if(file->_cnt<=0) {
02248             file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
02249             file->_cnt = 0;
02250             _unlock_file(file);
02251             return EOF;
02252         }
02253 
02254         file->_cnt--;
02255         file->_ptr = file->_base+1;
02256         c = *(unsigned char *)file->_base;
02257         _unlock_file(file);
02258         return c;
02259     }
02260 }
02261 
02262 /*********************************************************************
02263  *      fgetc (MSVCRT.@)
02264  */
02265 int CDECL fgetc(FILE* file)
02266 {
02267   unsigned char *i;
02268   unsigned int j;
02269 
02270   _lock_file(file);
02271   if (file->_cnt>0) {
02272     file->_cnt--;
02273     i = (unsigned char *)file->_ptr++;
02274     j = *i;
02275   } else
02276     j = _filbuf(file);
02277 
02278   _unlock_file(file);
02279   return j;
02280 }
02281 
02282 /*********************************************************************
02283  *      _fgetchar (MSVCRT.@)
02284  */
02285 int CDECL _fgetchar(void)
02286 {
02287   return fgetc(stdin);
02288 }
02289 
02290 /*********************************************************************
02291  *      fgets (MSVCRT.@)
02292  */
02293 char * CDECL fgets(char *s, int size, FILE* file)
02294 {
02295   int    cc = EOF;
02296   char * buf_start = s;
02297 
02298   TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
02299     file,file->_file,s,size);
02300 
02301   _lock_file(file);
02302 
02303   while ((size >1) && (cc = fgetc(file)) != EOF && cc != '\n')
02304     {
02305       *s++ = (char)cc;
02306       size --;
02307     }
02308   if ((cc == EOF) && (s == buf_start)) /* If nothing read, return 0*/
02309   {
02310     TRACE(":nothing read\n");
02311     _unlock_file(file);
02312     return NULL;
02313   }
02314   if ((cc != EOF) && (size > 1))
02315     *s++ = cc;
02316   *s = '\0';
02317   TRACE(":got %s\n", debugstr_a(buf_start));
02318   _unlock_file(file);
02319   return buf_start;
02320 }
02321 
02322 /*********************************************************************
02323  *      fgetwc (MSVCRT.@)
02324  *
02325  * In _O_TEXT mode, multibyte characters are read from the file, dropping
02326  * the CR from CR/LF combinations
02327  */
02328 wint_t CDECL fgetwc(FILE* file)
02329 {
02330   int c;
02331 
02332   _lock_file(file);
02333   if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT))
02334     {
02335       wchar_t wc;
02336       unsigned int i;
02337       int j;
02338       char *chp, *wcp;
02339       wcp = (char *)&wc;
02340       for(i=0; i<sizeof(wc); i++)
02341       {
02342         if (file->_cnt>0) 
02343         {
02344           file->_cnt--;
02345           chp = file->_ptr++;
02346           wcp[i] = *chp;
02347         } 
02348         else
02349         {
02350           j = _filbuf(file);
02351           if(file->_cnt<=0)
02352           {
02353             file->_flag |= (file->_cnt == 0) ? _IOEOF : _IOERR;
02354             file->_cnt = 0;
02355 
02356             _unlock_file(file);
02357             return WEOF;
02358           }
02359           wcp[i] = j;
02360         }
02361       }
02362 
02363       _unlock_file(file);
02364       return wc;
02365     }
02366     
02367   c = fgetc(file);
02368   if ((__mb_cur_max > 1) && isleadbyte(c))
02369     {
02370       FIXME("Treat Multibyte characters\n");
02371     }
02372 
02373   _unlock_file(file);
02374   if (c == EOF)
02375     return WEOF;
02376   else
02377     return (wint_t)c;
02378 }
02379 
02380 /*********************************************************************
02381  *      _getw (MSVCRT.@)
02382  */
02383 int CDECL _getw(FILE* file)
02384 {
02385   char *ch;
02386   int i, k;
02387   unsigned int j;
02388   ch = (char *)&i;
02389 
02390   _lock_file(file);
02391   for (j=0; j<sizeof(int); j++) {
02392     k = fgetc(file);
02393     if (k == EOF) {
02394       file->_flag |= _IOEOF;
02395       _unlock_file(file);
02396       return EOF;
02397     }
02398     ch[j] = k;
02399   }
02400 
02401   _unlock_file(file);
02402   return i;
02403 }
02404 
02405 /*********************************************************************
02406  *      getwc (MSVCRT.@)
02407  */
02408 wint_t CDECL getwc(FILE* file)
02409 {
02410   return fgetwc(file);
02411 }
02412 
02413 /*********************************************************************
02414  *      _fgetwchar (MSVCRT.@)
02415  */
02416 wint_t CDECL _fgetwchar(void)
02417 {
02418   return fgetwc(stdin);
02419 }
02420 
02421 /*********************************************************************
02422  *      getwchar (MSVCRT.@)
02423  */
02424 wint_t CDECL getwchar(void)
02425 {
02426   return _fgetwchar();
02427 }
02428 
02429 /*********************************************************************
02430  *              fgetws (MSVCRT.@)
02431  */
02432 wchar_t * CDECL fgetws(wchar_t *s, int size, FILE* file)
02433 {
02434   int    cc = WEOF;
02435   wchar_t * buf_start = s;
02436 
02437   TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
02438         file,file->_file,s,size);
02439 
02440   _lock_file(file);
02441 
02442   while ((size >1) && (cc = fgetwc(file)) != WEOF && cc != '\n')
02443     {
02444       *s++ = (char)cc;
02445       size --;
02446     }
02447   if ((cc == WEOF) && (s == buf_start)) /* If nothing read, return 0*/
02448   {
02449     TRACE(":nothing read\n");
02450     _unlock_file(file);
02451     return NULL;
02452   }
02453   if ((cc != WEOF) && (size > 1))
02454     *s++ = cc;
02455   *s = 0;
02456   TRACE(":got %s\n", debugstr_w(buf_start));
02457   _unlock_file(file);
02458   return buf_start;
02459 }
02460 
02461 /*********************************************************************
02462  *      fwrite (MSVCRT.@)
02463  */
02464 size_t CDECL fwrite(const void *ptr, size_t size, size_t nmemb, FILE* file)
02465 {
02466     size_t wrcnt=size * nmemb;
02467     int written = 0;
02468     if (size == 0)
02469         return 0;
02470 
02471     _lock_file(file);
02472     if(file->_cnt) {
02473         int pcnt=(file->_cnt>wrcnt)? wrcnt: file->_cnt;
02474         memcpy(file->_ptr, ptr, pcnt);
02475         file->_cnt -= pcnt;
02476         file->_ptr += pcnt;
02477         written = pcnt;
02478         wrcnt -= pcnt;
02479         ptr = (const char*)ptr + pcnt;
02480     } else if(!(file->_flag & _IOWRT)) {
02481         if(file->_flag & _IORW) {
02482             file->_flag |= _IOWRT;
02483         } else {
02484             _unlock_file(file);
02485             return 0;
02486         }
02487     }
02488     if(wrcnt) {
02489         /* Flush buffer */
02490         int res=flush_buffer(file);
02491         if(!res) {
02492             int pwritten = _write(file->_file, ptr, wrcnt);
02493             if (pwritten <= 0)
02494             {
02495                 file->_flag |= _IOERR;
02496                 pwritten=0;
02497             }
02498             written += pwritten;
02499         }
02500     }
02501 
02502     _unlock_file(file);
02503     return written / size;
02504 }
02505 
02506 /*********************************************************************
02507  *      fputwc (MSVCRT.@)
02508  */
02509 wint_t CDECL fputwc(wint_t wc, FILE* file)
02510 {
02511   wchar_t mwc=wc;
02512   if (fwrite( &mwc, sizeof(mwc), 1, file) != 1)
02513     return WEOF;
02514   return wc;
02515 }
02516 
02517 /*********************************************************************
02518  *      _fputwchar (MSVCRT.@)
02519  */
02520 wint_t CDECL _fputwchar(wint_t wc)
02521 {
02522   return fputwc(wc, stdout);
02523 }
02524 
02525 /*********************************************************************
02526  *      _wfsopen (MSVCRT.@)
02527  */
02528 FILE * CDECL _wfsopen(const wchar_t *path, const wchar_t *mode, int share)
02529 {
02530   FILE* file;
02531   int open_flags, stream_flags, fd;
02532 
02533   TRACE("(%s,%s)\n", debugstr_w(path), debugstr_w(mode));
02534 
02535   /* map mode string to open() flags. "man fopen" for possibilities. */
02536   if (get_flags(mode, &open_flags, &stream_flags) == -1)
02537       return NULL;
02538 
02539   LOCK_FILES();
02540   fd = _wsopen(path, open_flags, share, _S_IREAD | _S_IWRITE);
02541   if (fd < 0)
02542     file = NULL;
02543   else if ((file = alloc_fp()) && init_fp(file, fd, stream_flags)
02544    != -1)
02545     TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd, debugstr_w(mode), file);
02546   else if (file)
02547   {
02548     file->_flag = 0;
02549     file = NULL;
02550   }
02551 
02552   TRACE(":got (%p)\n",file);
02553   if (fd >= 0 && !file)
02554     _close(fd);
02555   UNLOCK_FILES();
02556   return file;
02557 }
02558 
02559 /*********************************************************************
02560  *      _fsopen (MSVCRT.@)
02561  */
02562 FILE * CDECL _fsopen(const char *path, const char *mode, int share)
02563 {
02564     FILE *ret;
02565     wchar_t *pathW = NULL, *modeW = NULL;
02566 
02567     if (path && !(pathW = msvcrt_wstrdupa(path))) {
02568         _invalid_parameter(NULL, NULL, NULL, 0, 0);
02569         *_errno() = EINVAL;
02570         return NULL;
02571     }
02572     if (mode && !(modeW = msvcrt_wstrdupa(mode)))
02573     {
02574         free(pathW);
02575         _invalid_parameter(NULL, NULL, NULL, 0, 0);
02576         *_errno() = EINVAL;
02577         return NULL;
02578     }
02579 
02580     ret = _wfsopen(pathW, modeW, share);
02581 
02582     free(pathW);
02583     free(modeW);
02584     return ret;
02585 }
02586 
02587 /*********************************************************************
02588  *      fopen (MSVCRT.@)
02589  */
02590 FILE * CDECL fopen(const char *path, const char *mode)
02591 {
02592     return _fsopen( path, mode, _SH_DENYNO );
02593 }
02594 
02595 /*********************************************************************
02596  *              fopen_s (MSVCRT.@)
02597  */
02598 int CDECL fopen_s(FILE** pFile,
02599         const char *filename, const char *mode)
02600 {
02601     if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
02602         !MSVCRT_CHECK_PMT(mode != NULL)) {
02603         *_errno() = EINVAL;
02604         return EINVAL;
02605     }
02606 
02607     *pFile = fopen(filename, mode);
02608 
02609     if(!*pFile)
02610         return *_errno();
02611     return 0;
02612 }
02613 
02614 /*********************************************************************
02615  *      _wfopen (MSVCRT.@)
02616  */
02617 FILE * CDECL _wfopen(const wchar_t *path, const wchar_t *mode)
02618 {
02619     return _wfsopen( path, mode, _SH_DENYNO );
02620 }
02621 
02622 /*********************************************************************
02623  *      _wfopen_s (MSVCRT.@)
02624  */
02625 int CDECL _wfopen_s(FILE** pFile, const wchar_t *filename,
02626         const wchar_t *mode)
02627 {
02628     if (!MSVCRT_CHECK_PMT(pFile != NULL) || !MSVCRT_CHECK_PMT(filename != NULL) ||
02629         !MSVCRT_CHECK_PMT(mode != NULL)) {
02630         *_errno() = EINVAL;
02631         return EINVAL;
02632     }
02633 
02634     *pFile = _wfopen(filename, mode);
02635 
02636     if(!*pFile)
02637         return *_errno();
02638     return 0;
02639 }
02640 
02641 /* fputc calls _flsbuf which calls fputc */
02642 int CDECL _flsbuf(int c, FILE* file);
02643 
02644 /*********************************************************************
02645  *      fputc (MSVCRT.@)
02646  */
02647 int CDECL fputc(int c, FILE* file)
02648 {
02649   int res;
02650 
02651   _lock_file(file);
02652   if(file->_cnt>0) {
02653     *file->_ptr++=c;
02654     file->_cnt--;
02655     if (c == '\n')
02656     {
02657       res = flush_buffer(file);
02658       _unlock_file(file);
02659       return res ? res : c;
02660     }
02661     else {
02662       _unlock_file(file);
02663       return c & 0xff;
02664     }
02665   } else {
02666     res = _flsbuf(c, file);
02667     _unlock_file(file);
02668     return res;
02669   }
02670 }
02671 
02672 /*********************************************************************
02673  *      _fputchar (MSVCRT.@)
02674  */
02675 int CDECL _fputchar(int c)
02676 {
02677   return fputc(c, stdout);
02678 }
02679 
02680 /*********************************************************************
02681  *      fread (MSVCRT.@)
02682  */
02683 size_t CDECL fread(void *ptr, size_t size, size_t nmemb, FILE* file)
02684 {
02685   size_t rcnt=size * nmemb;
02686   size_t read=0;
02687   int pread=0;
02688 
02689   if(!rcnt)
02690     return 0;
02691 
02692   _lock_file(file);
02693 
02694   /* first buffered data */
02695   if(file->_cnt>0) {
02696     int pcnt= (rcnt>file->_cnt)? file->_cnt:rcnt;
02697     memcpy(ptr, file->_ptr, pcnt);
02698     file->_cnt -= pcnt;
02699     file->_ptr += pcnt;
02700     read += pcnt ;
02701     rcnt -= pcnt ;
02702         ptr = (char*)ptr + pcnt;
02703   } else if(!(file->_flag & _IOREAD )) {
02704     if(file->_flag & _IORW) {
02705         file->_flag |= _IOREAD;
02706     } else {
02707         _unlock_file(file);
02708         return 0;
02709     }
02710   }
02711   while(rcnt>0)
02712   {
02713     int i;
02714     /* Fill the buffer on small reads.
02715      * TODO: Use a better buffering strategy.
02716      */
02717     if (!file->_cnt && size*nmemb <= BUFSIZ/2 && !(file->_flag & _IONBF)) {
02718       if (file->_bufsiz == 0) {
02719         alloc_buffer(file);
02720       }
02721       file->_cnt = _read(file->_file, file->_base, file->_bufsiz);
02722       file->_ptr = file->_base;
02723       i = (file->_cnt<rcnt) ? file->_cnt : rcnt;
02724       /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
02725       if (i > 0 && i < file->_cnt) {
02726         get_ioinfo(file->_file)->wxflag &= ~WX_ATEOF;
02727         file->_flag &= ~_IOEOF;
02728       }
02729       if (i > 0) {
02730         memcpy(ptr, file->_ptr, i);
02731         file->_cnt -= i;
02732         file->_ptr += i;
02733       }
02734     } else {
02735       i = _read(file->_file,ptr, rcnt);
02736     }
02737     pread += i;
02738     rcnt -= i;
02739     ptr = (char *)ptr+i;
02740     /* expose feof condition in the flags
02741      * MFC tests file->_flag for feof, and doesn't call feof())
02742      */
02743     if (get_ioinfo(file->_file)->wxflag & WX_ATEOF)
02744         file->_flag |= _IOEOF;
02745     else if (i == -1)
02746     {
02747         file->_flag |= _IOERR;
02748         pread = 0;
02749         rcnt = 0;
02750     }
02751     if (i < 1) break;
02752   }
02753   read+=pread;
02754   _unlock_file(file);
02755   return read / size;
02756 }
02757 
02758 /*********************************************************************
02759  *      _wfreopen (MSVCRT.@)
02760  *
02761  */
02762 FILE* CDECL _wfreopen(const wchar_t *path, const wchar_t *mode, FILE* file)
02763 {
02764   int open_flags, stream_flags, fd;
02765 
02766   TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n", debugstr_w(path), debugstr_w(mode), file, file->_file);
02767 
02768   LOCK_FILES();
02769   if (!file || ((fd = file->_file) < 0) || fd > fdend)
02770     file = NULL;
02771   else
02772   {
02773     fclose(file);
02774     /* map mode string to open() flags. "man fopen" for possibilities. */
02775     if (get_flags(mode, &open_flags, &stream_flags) == -1)
02776       file = NULL;
02777     else
02778     {
02779       fd = _wopen(path, open_flags, _S_IREAD | _S_IWRITE);
02780       if (fd < 0)
02781         file = NULL;
02782       else if (init_fp(file, fd, stream_flags) == -1)
02783       {
02784           file->_flag = 0;
02785           WARN(":failed-last error (%d)\n",GetLastError());
02786           _dosmaperr(GetLastError());
02787           file = NULL;
02788       }
02789     }
02790   }
02791   UNLOCK_FILES();
02792   return file;
02793 }
02794 
02795 /*********************************************************************
02796  *      freopen (MSVCRT.@)
02797  *
02798  */
02799 FILE* CDECL freopen(const char *path, const char *mode, FILE* file)
02800 {
02801     FILE *ret;
02802     wchar_t *pathW = NULL, *modeW = NULL;
02803 
02804     if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL;
02805     if (mode && !(modeW = msvcrt_wstrdupa(mode)))
02806     {
02807         free(pathW);
02808         return NULL;
02809     }
02810 
02811     ret = _wfreopen(pathW, modeW, file);
02812 
02813     free(pathW);
02814     free(modeW);
02815     return ret;
02816 }
02817 
02818 /*********************************************************************
02819  *      fsetpos (MSVCRT.@)
02820  */
02821 int CDECL fsetpos(FILE* file, const fpos_t *pos)
02822 {
02823   int ret;
02824 
02825   _lock_file(file);
02826   /* Note that all this has been lifted 'as is' from fseek */
02827   if(file->_flag & _IOWRT)
02828     flush_buffer(file);
02829 
02830   /* Discard buffered input */
02831   file->_cnt = 0;
02832   file->_ptr = file->_base;
02833   
02834   /* Reset direction of i/o */
02835   if(file->_flag & _IORW) {
02836         file->_flag &= ~(_IOREAD|_IOWRT);
02837   }
02838 
02839   ret = (_lseeki64(file->_file,*pos,SEEK_SET) == -1) ? -1 : 0;
02840   _unlock_file(file);
02841   return ret;
02842 }
02843 
02844 /*********************************************************************
02845  *      _ftelli64 (MSVCRT.@)
02846  */
02847 __int64 CDECL _ftelli64(FILE* file)
02848 {
02849     /* TODO: just call fgetpos and return lower half of result */
02850     int off=0;
02851     __int64 pos;
02852 
02853     _lock_file(file);
02854     pos = _telli64(file->_file);
02855     if(pos == -1) {
02856         _unlock_file(file);
02857         return -1;
02858     }
02859     if(file->_bufsiz)  {
02860         if( file->_flag & _IOWRT ) {
02861             off = file->_ptr - file->_base;
02862         } else {
02863             off = -file->_cnt;
02864             if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
02865                 /* Black magic correction for CR removal */
02866                 int i;
02867                 for (i=0; i<file->_cnt; i++) {
02868                     if (file->_ptr[i] == '\n')
02869                         off--;
02870                 }
02871                 /* Black magic when reading CR at buffer boundary*/
02872                 if(get_ioinfo(file->_file)->wxflag & WX_READCR)
02873                     off--;
02874             }
02875         }
02876     }
02877 
02878     _unlock_file(file);
02879     return off + pos;
02880 }
02881 
02882 /*********************************************************************
02883  *      ftell (MSVCRT.@)
02884  */
02885 LONG CDECL ftell(FILE* file)
02886 {
02887   return _ftelli64(file);
02888 }
02889 
02890 /*********************************************************************
02891  *      fgetpos (MSVCRT.@)
02892  */
02893 int CDECL fgetpos(FILE* file, fpos_t *pos)
02894 {
02895     int off=0;
02896 
02897     _lock_file(file);
02898     *pos = _lseeki64(file->_file,0,SEEK_CUR);
02899     if(*pos == -1) {
02900         _unlock_file(file);
02901         return -1;
02902     }
02903     if(file->_bufsiz)  {
02904         if( file->_flag & _IOWRT ) {
02905             off = file->_ptr - file->_base;
02906         } else {
02907             off = -file->_cnt;
02908             if (get_ioinfo(file->_file)->wxflag & WX_TEXT) {
02909                 /* Black magic correction for CR removal */
02910                 int i;
02911                 for (i=0; i<file->_cnt; i++) {
02912                     if (file->_ptr[i] == '\n')
02913                         off--;
02914                 }
02915                 /* Black magic when reading CR at buffer boundary*/
02916                 if(get_ioinfo(file->_file)->wxflag & WX_READCR)
02917                     off--;
02918             }
02919         }
02920     }
02921     *pos += off;
02922     _unlock_file(file);
02923     return 0;
02924 }
02925 
02926 /*********************************************************************
02927  *      fputs (MSVCRT.@)
02928  */
02929 int CDECL fputs(const char *s, FILE* file)
02930 {
02931     size_t i, len = strlen(s);
02932     int ret;
02933 
02934     _lock_file(file);
02935     if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
02936       ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF;
02937       _unlock_file(file);
02938       return ret;
02939     }
02940     for (i=0; i<len; i++)
02941       if (fputc(s[i], file) == EOF)  {
02942         _unlock_file(file);
02943         return EOF;
02944       }
02945 
02946     _unlock_file(file);
02947     return 0;
02948 }
02949 
02950 /*********************************************************************
02951  *      fputws (MSVCRT.@)
02952  */
02953 int CDECL fputws(const wchar_t *s, FILE* file)
02954 {
02955     size_t i, len = strlenW(s);
02956     int ret;
02957 
02958     _lock_file(file);
02959     if (!(get_ioinfo(file->_file)->wxflag & WX_TEXT)) {
02960         ret = fwrite(s,sizeof(*s),len,file) == len ? 0 : EOF;
02961         _unlock_file(file);
02962         return ret;
02963     }
02964     for (i=0; i<len; i++) {
02965         if (((s[i] == '\n') && (fputc('\r', file) == EOF))
02966                 || fputwc(s[i], file) == WEOF) {
02967             _unlock_file(file);
02968             return WEOF;
02969         }
02970     }
02971 
02972     _unlock_file(file);
02973     return 0;
02974 }
02975 
02976 /*********************************************************************
02977  *      getchar (MSVCRT.@)
02978  */
02979 int CDECL getchar(void)
02980 {
02981   return fgetc(stdin);
02982 }
02983 
02984 /*********************************************************************
02985  *      getc (MSVCRT.@)
02986  */
02987 int CDECL getc(FILE* file)
02988 {
02989   return fgetc(file);
02990 }
02991 
02992 /*********************************************************************
02993  *      gets (MSVCRT.@)
02994  */
02995 char * CDECL gets(char *buf)
02996 {
02997   int    cc;
02998   char * buf_start = buf;
02999 
03000   _lock_file(stdin);
03001   for(cc = fgetc(stdin); cc != EOF && cc != '\n';
03002       cc = fgetc(stdin))
03003   if(cc != '\r') *buf++ = (char)cc;
03004 
03005   *buf = '\0';
03006 
03007   TRACE("got '%s'\n", buf_start);
03008   _unlock_file(stdin);
03009   return buf_start;
03010 }
03011 
03012 /*********************************************************************
03013  *      _getws (MSVCRT.@)
03014  */
03015 wchar_t* CDECL _getws(wchar_t* buf)
03016 {
03017     wint_t cc;
03018     wchar_t* ws = buf;
03019 
03020     _lock_file(stdin);
03021     for (cc = fgetwc(stdin); cc != WEOF && cc != '\n';
03022          cc = fgetwc(stdin))
03023     {
03024         if (cc != '\r')
03025             *buf++ = (wchar_t)cc;
03026     }
03027     *buf = '\0';
03028 
03029     TRACE("got %s\n", debugstr_w(ws));
03030     _unlock_file(stdin);
03031     return ws;
03032 }
03033 
03034 /*********************************************************************
03035  *      putc (MSVCRT.@)
03036  */
03037 int CDECL putc(int c, FILE* file)
03038 {
03039   return fputc(c, file);
03040 }
03041 
03042 /*********************************************************************
03043  *      putchar (MSVCRT.@)
03044  */
03045 int CDECL putchar(int c)
03046 {
03047   return fputc(c, stdout);
03048 }
03049 
03050 /*********************************************************************
03051  *      _putwch (MSVCRT.@)
03052  */
03053 wint_t CDECL _putwch(wchar_t c)
03054 {
03055   return fputwc(c, stdout);
03056 }
03057 
03058 /*********************************************************************
03059  *      puts (MSVCRT.@)
03060  */
03061 int CDECL puts(const char *s)
03062 {
03063     size_t len = strlen(s);
03064     int ret;
03065 
03066     _lock_file(stdout);
03067     if(fwrite(s, sizeof(*s), len, stdout) != len) {
03068         _unlock_file(stdout);
03069         return EOF;
03070     }
03071 
03072     ret = fwrite("\n",1,1,stdout) == 1 ? 0 : EOF;
03073     _unlock_file(stdout);
03074     return ret;
03075 }
03076 
03077 /*********************************************************************
03078  *      _putws (MSVCRT.@)
03079  */
03080 int CDECL _putws(const wchar_t *s)
03081 {
03082     static const wchar_t nl = '\n';
03083     size_t len = strlenW(s);
03084     int ret;
03085 
03086     _lock_file(stdout);
03087     if(fwrite(s, sizeof(*s), len, stdout) != len) {
03088         _unlock_file(stdout);
03089         return EOF;
03090     }
03091 
03092     ret = fwrite(&nl,sizeof(nl),1,stdout) == 1 ? 0 : EOF;
03093     _unlock_file(stdout);
03094     return ret;
03095 }
03096 
03097 /*********************************************************************
03098  *      remove (MSVCRT.@)
03099  */
03100 int CDECL remove(const char *path)
03101 {
03102   TRACE("(%s)\n",path);
03103   if (DeleteFileA(path))
03104     return 0;
03105   TRACE(":failed (%d)\n",GetLastError());
03106   _dosmaperr(GetLastError());
03107   return -1;
03108 }
03109 
03110 /*********************************************************************
03111  *      _wremove (MSVCRT.@)
03112  */
03113 int CDECL _wremove(const wchar_t *path)
03114 {
03115   TRACE("(%s)\n",debugstr_w(path));
03116   if (DeleteFileW(path))
03117     return 0;
03118   TRACE(":failed (%d)\n",GetLastError());
03119   _dosmaperr(GetLastError());
03120   return -1;
03121 }
03122 
03123 /*********************************************************************
03124  *      rename (MSVCRT.@)
03125  */
03126 int CDECL rename(const char *oldpath,const char *newpath)
03127 {
03128   TRACE(":from %s to %s\n",oldpath,newpath);
03129   if (MoveFileExA(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
03130     return 0;
03131   TRACE(":failed (%d)\n",GetLastError());
03132   _dosmaperr(GetLastError());
03133   return -1;
03134 }
03135 
03136 /*********************************************************************
03137  *      _wrename (MSVCRT.@)
03138  */
03139 int CDECL _wrename(const wchar_t *oldpath,const wchar_t *newpath)
03140 {
03141   TRACE(":from %s to %s\n",debugstr_w(oldpath),debugstr_w(newpath));
03142   if (MoveFileExW(oldpath, newpath, MOVEFILE_COPY_ALLOWED))
03143     return 0;
03144   TRACE(":failed (%d)\n",GetLastError());
03145   _dosmaperr(GetLastError());
03146   return -1;
03147 }
03148 
03149 /*********************************************************************
03150  *      setvbuf (MSVCRT.@)
03151  */
03152 int CDECL setvbuf(FILE* file, char *buf, int mode, size_t size)
03153 {
03154   _lock_file(file);
03155   if(file->_bufsiz) {
03156     free(file->_base);
03157     file->_bufsiz = 0;
03158     file->_cnt = 0;
03159   }
03160   if(mode == _IOFBF) {
03161     file->_flag &= ~_IONBF;
03162     file->_base = file->_ptr = buf;
03163     if(buf) {
03164         file->_bufsiz = size;
03165     }
03166   } else {
03167     file->_flag |= _IONBF;
03168   }
03169   _unlock_file(file);
03170   return 0;
03171 }
03172 
03173 /*********************************************************************
03174  *      setbuf (MSVCRT.@)
03175  */
03176 void CDECL setbuf(FILE* file, char *buf)
03177 {
03178   setvbuf(file, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
03179 }
03180 
03181 /*********************************************************************
03182  *      tmpnam (MSVCRT.@)
03183  */
03184 char * CDECL tmpnam(char *s)
03185 {
03186   char tmpstr[16];
03187   char *p;
03188   int count, size;
03189 
03190   if (!s) {
03191     thread_data_t *data = msvcrt_get_thread_data();
03192 
03193     if(!data->tmpnam_buffer)
03194       data->tmpnam_buffer = malloc(MAX_PATH);
03195 
03196     s = data->tmpnam_buffer;
03197   }
03198 
03199   int_to_base32(GetCurrentProcessId(), tmpstr);
03200   p = s + sprintf(s, "\\s%s.", tmpstr);
03201   for (count = 0; count < TMP_MAX; count++)
03202   {
03203     size = int_to_base32(tmpnam_unique++, tmpstr);
03204     memcpy(p, tmpstr, size);
03205     if (GetFileAttributesA(s) == INVALID_FILE_ATTRIBUTES &&
03206         GetLastError() == ERROR_FILE_NOT_FOUND)
03207       break;
03208   }
03209   return s;
03210 }
03211 
03212 /*********************************************************************
03213  *              _wtmpnam (MSVCRT.@)
03214  */
03215 wchar_t * CDECL _wtmpnam(wchar_t *s)
03216 {
03217     static const wchar_t format[] = {'\\','s','%','s','.',0};
03218     wchar_t tmpstr[16];
03219     wchar_t *p;
03220     int count, size;
03221     if (!s) {
03222         thread_data_t *data = msvcrt_get_thread_data();
03223 
03224         if(!data->wtmpnam_buffer)
03225             data->wtmpnam_buffer = malloc(sizeof(wchar_t[MAX_PATH]));
03226 
03227         s = data->wtmpnam_buffer;
03228     }
03229 
03230     int_to_base32_w(GetCurrentProcessId(), tmpstr);
03231     p = s + _snwprintf(s, MAX_PATH, format, tmpstr);
03232     for (count = 0; count < TMP_MAX; count++)
03233     {
03234         size = int_to_base32_w(tmpnam_unique++, tmpstr);
03235         memcpy(p, tmpstr, size*sizeof(wchar_t));
03236         if (GetFileAttributesW(s) == INVALID_FILE_ATTRIBUTES &&
03237                 GetLastError() == ERROR_FILE_NOT_FOUND)
03238             break;
03239     }
03240     return s;
03241 }
03242 
03243 /*********************************************************************
03244  *      tmpfile (MSVCRT.@)
03245  */
03246 FILE* CDECL tmpfile(void)
03247 {
03248   char *filename = tmpnam(NULL);
03249   int fd;
03250   FILE* file = NULL;
03251 
03252   LOCK_FILES();
03253   fd = _open(filename, _O_CREAT | _O_BINARY | _O_RDWR | _O_TEMPORARY);
03254   if (fd != -1 && (file = alloc_fp()))
03255   {
03256     if (init_fp(file, fd, _O_RDWR) == -1)
03257     {
03258         file->_flag = 0;
03259         file = NULL;
03260     }
03261     else file->_tmpfname = _strdup(filename);
03262   }
03263   UNLOCK_FILES();
03264   return file;
03265 }
03266 
03267 /*********************************************************************
03268  *      ungetc (MSVCRT.@)
03269  */
03270 int CDECL ungetc(int c, FILE * file)
03271 {
03272     if (c == EOF)
03273         return EOF;
03274 
03275     _lock_file(file);
03276     if(file->_bufsiz == 0) {
03277         alloc_buffer(file);
03278         file->_ptr++;
03279     }
03280     if(file->_ptr>file->_base) {
03281         file->_ptr--;
03282         *file->_ptr=c;
03283         file->_cnt++;
03284         clearerr(file);
03285         _unlock_file(file);
03286         return c;
03287     }
03288 
03289     _unlock_file(file);
03290     return EOF;
03291 }
03292 
03293 /*********************************************************************
03294  *              ungetwc (MSVCRT.@)
03295  */
03296 wint_t CDECL ungetwc(wint_t wc, FILE * file)
03297 {
03298     wchar_t mwc = wc;
03299     char * pp = (char *)&mwc;
03300     int i;
03301 
03302     _lock_file(file);
03303     for(i=sizeof(wchar_t)-1;i>=0;i--) {
03304         if(pp[i] != ungetc(pp[i],file)) {
03305             _unlock_file(file);
03306             return WEOF;
03307         }
03308     }
03309 
03310     _unlock_file(file);
03311     return mwc;
03312 }
03313 
03314 
03315 
03316 /*********************************************************************
03317  *      _getmaxstdio (MSVCRT.@)
03318  */
03319 int CDECL _getmaxstdio(void)
03320 {
03321     return max_streams;
03322 }
03323 
03324 /*********************************************************************
03325  *      _setmaxstdio (MSVCRT.@)
03326  */
03327 int CDECL _setmaxstdio(int newmax)
03328 {
03329     TRACE("%d\n", newmax);
03330 
03331     if(newmax<_IOB_ENTRIES || newmax>MAX_FILES || newmax<stream_idx)
03332         return -1;
03333 
03334     max_streams = newmax;
03335     return max_streams;
03336 }

Generated on Sun May 27 2012 04:17:52 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.