2 * msvcrt.dll file functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 * Copyright 2004 Eric Pouech
9 * Copyright 2004 Juan Lang
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Use the file flag hints O_SEQUENTIAL, O_RANDOM, O_SHORT_LIVED
30 #include "wine/port.h"
37 #include <sys/types.h>
46 #include "wine/unicode.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
52 /* for stat mode, permissions apply to all,owner and group */
53 #define ALL_S_IREAD (MSVCRT__S_IREAD | (MSVCRT__S_IREAD >> 3) | (MSVCRT__S_IREAD >> 6))
54 #define ALL_S_IWRITE (MSVCRT__S_IWRITE | (MSVCRT__S_IWRITE >> 3) | (MSVCRT__S_IWRITE >> 6))
55 #define ALL_S_IEXEC (MSVCRT__S_IEXEC | (MSVCRT__S_IEXEC >> 3) | (MSVCRT__S_IEXEC >> 6))
57 /* _access() bit flags FIXME: incomplete */
58 #define MSVCRT_W_OK 0x02
59 #define MSVCRT_R_OK 0x04
61 /* values for wxflag in file descriptor */
64 #define WX_READNL 0x04 /* read started with \n */
66 #define WX_DONTINHERIT 0x10
67 #define WX_APPEND 0x20
71 /* values for exflag - it's used differently in msvcr90.dll*/
74 #define EF_CRIT_INIT 0x04
75 #define EF_UNK_UNICODE 0x08
77 static char utf8_bom
[3] = { 0xef, 0xbb, 0xbf };
78 static char utf16_bom
[2] = { 0xff, 0xfe };
80 /* FIXME: this should be allocated dynamically */
81 #define MSVCRT_MAX_FILES 2048
82 #define MSVCRT_FD_BLOCK_SIZE 32
84 #define MSVCRT_INTERNAL_BUFSIZ 4096
86 /* ioinfo structure size is different in msvcrXX.dll's */
92 CRITICAL_SECTION crit
;
98 BOOL utf8translations
;
106 /*********************************************************************
107 * __pioinfo (MSVCRT.@)
108 * array of pointers to ioinfo arrays [32]
110 ioinfo
* MSVCRT___pioinfo
[MSVCRT_MAX_FILES
/MSVCRT_FD_BLOCK_SIZE
] = { 0 };
112 /*********************************************************************
113 * __badioinfo (MSVCRT.@)
115 ioinfo MSVCRT___badioinfo
= { INVALID_HANDLE_VALUE
, WX_TEXT
};
117 static int MSVCRT_fdstart
= 3; /* first unallocated fd */
118 static int MSVCRT_fdend
= 3; /* highest allocated fd */
122 CRITICAL_SECTION crit
;
125 MSVCRT_FILE MSVCRT__iob
[_IOB_ENTRIES
] = { { 0 } };
126 static file_crit
* MSVCRT_fstream
[MSVCRT_MAX_FILES
/MSVCRT_FD_BLOCK_SIZE
];
127 static int MSVCRT_max_streams
= 512, MSVCRT_stream_idx
;
129 /* INTERNAL: process umask */
130 static int MSVCRT_umask
= 0;
132 /* INTERNAL: static data for tmpnam and _wtmpname functions */
133 static int tmpnam_unique
;
135 static const unsigned int EXE
= 'e' << 16 | 'x' << 8 | 'e';
136 static const unsigned int BAT
= 'b' << 16 | 'a' << 8 | 't';
137 static const unsigned int CMD
= 'c' << 16 | 'm' << 8 | 'd';
138 static const unsigned int COM
= 'c' << 16 | 'o' << 8 | 'm';
140 #define TOUL(x) (ULONGLONG)(x)
141 static const ULONGLONG WCEXE
= TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
142 static const ULONGLONG WCBAT
= TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
143 static const ULONGLONG WCCMD
= TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
144 static const ULONGLONG WCCOM
= TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
146 /* This critical section protects the tables MSVCRT___pioinfo and MSVCRT_fstreams,
147 * and their related indexes, MSVCRT_fdstart, MSVCRT_fdend,
148 * and MSVCRT_stream_idx, from race conditions.
149 * It doesn't protect against race conditions manipulating the underlying files
150 * or flags; doing so would probably be better accomplished with per-file
151 * protection, rather than locking the whole table for every change.
153 static CRITICAL_SECTION MSVCRT_file_cs
;
154 static CRITICAL_SECTION_DEBUG MSVCRT_file_cs_debug
=
156 0, 0, &MSVCRT_file_cs
,
157 { &MSVCRT_file_cs_debug
.ProcessLocksList
, &MSVCRT_file_cs_debug
.ProcessLocksList
},
158 0, 0, { (DWORD_PTR
)(__FILE__
": MSVCRT_file_cs") }
160 static CRITICAL_SECTION MSVCRT_file_cs
= { &MSVCRT_file_cs_debug
, -1, 0, 0, 0, 0 };
161 #define LOCK_FILES() do { EnterCriticalSection(&MSVCRT_file_cs); } while (0)
162 #define UNLOCK_FILES() do { LeaveCriticalSection(&MSVCRT_file_cs); } while (0)
164 static void msvcrt_stat64_to_stat(const struct MSVCRT__stat64
*buf64
, struct MSVCRT__stat
*buf
)
166 buf
->st_dev
= buf64
->st_dev
;
167 buf
->st_ino
= buf64
->st_ino
;
168 buf
->st_mode
= buf64
->st_mode
;
169 buf
->st_nlink
= buf64
->st_nlink
;
170 buf
->st_uid
= buf64
->st_uid
;
171 buf
->st_gid
= buf64
->st_gid
;
172 buf
->st_rdev
= buf64
->st_rdev
;
173 buf
->st_size
= buf64
->st_size
;
174 buf
->st_atime
= buf64
->st_atime
;
175 buf
->st_mtime
= buf64
->st_mtime
;
176 buf
->st_ctime
= buf64
->st_ctime
;
179 static void msvcrt_stat64_to_stati64(const struct MSVCRT__stat64
*buf64
, struct MSVCRT__stati64
*buf
)
181 buf
->st_dev
= buf64
->st_dev
;
182 buf
->st_ino
= buf64
->st_ino
;
183 buf
->st_mode
= buf64
->st_mode
;
184 buf
->st_nlink
= buf64
->st_nlink
;
185 buf
->st_uid
= buf64
->st_uid
;
186 buf
->st_gid
= buf64
->st_gid
;
187 buf
->st_rdev
= buf64
->st_rdev
;
188 buf
->st_size
= buf64
->st_size
;
189 buf
->st_atime
= buf64
->st_atime
;
190 buf
->st_mtime
= buf64
->st_mtime
;
191 buf
->st_ctime
= buf64
->st_ctime
;
194 static void msvcrt_stat64_to_stat32(const struct MSVCRT__stat64
*buf64
, struct MSVCRT__stat32
*buf
)
196 buf
->st_dev
= buf64
->st_dev
;
197 buf
->st_ino
= buf64
->st_ino
;
198 buf
->st_mode
= buf64
->st_mode
;
199 buf
->st_nlink
= buf64
->st_nlink
;
200 buf
->st_uid
= buf64
->st_uid
;
201 buf
->st_gid
= buf64
->st_gid
;
202 buf
->st_rdev
= buf64
->st_rdev
;
203 buf
->st_size
= buf64
->st_size
;
204 buf
->st_atime
= buf64
->st_atime
;
205 buf
->st_mtime
= buf64
->st_mtime
;
206 buf
->st_ctime
= buf64
->st_ctime
;
209 static void msvcrt_stat64_to_stat64i32(const struct MSVCRT__stat64
*buf64
, struct MSVCRT__stat64i32
*buf
)
211 buf
->st_dev
= buf64
->st_dev
;
212 buf
->st_ino
= buf64
->st_ino
;
213 buf
->st_mode
= buf64
->st_mode
;
214 buf
->st_nlink
= buf64
->st_nlink
;
215 buf
->st_uid
= buf64
->st_uid
;
216 buf
->st_gid
= buf64
->st_gid
;
217 buf
->st_rdev
= buf64
->st_rdev
;
218 buf
->st_size
= buf64
->st_size
;
219 buf
->st_atime
= buf64
->st_atime
;
220 buf
->st_mtime
= buf64
->st_mtime
;
221 buf
->st_ctime
= buf64
->st_ctime
;
224 static void msvcrt_stat64_to_stat32i64(const struct MSVCRT__stat64
*buf64
, struct MSVCRT__stat32i64
*buf
)
226 buf
->st_dev
= buf64
->st_dev
;
227 buf
->st_ino
= buf64
->st_ino
;
228 buf
->st_mode
= buf64
->st_mode
;
229 buf
->st_nlink
= buf64
->st_nlink
;
230 buf
->st_uid
= buf64
->st_uid
;
231 buf
->st_gid
= buf64
->st_gid
;
232 buf
->st_rdev
= buf64
->st_rdev
;
233 buf
->st_size
= buf64
->st_size
;
234 buf
->st_atime
= buf64
->st_atime
;
235 buf
->st_mtime
= buf64
->st_mtime
;
236 buf
->st_ctime
= buf64
->st_ctime
;
239 static void time_to_filetime( MSVCRT___time64_t time
, FILETIME
*ft
)
241 /* 1601 to 1970 is 369 years plus 89 leap days */
242 static const __int64 secs_1601_to_1970
= ((369 * 365 + 89) * (__int64
)86400);
244 __int64 ticks
= (time
+ secs_1601_to_1970
) * 10000000;
245 ft
->dwHighDateTime
= ticks
>> 32;
246 ft
->dwLowDateTime
= ticks
;
249 static inline ioinfo
* get_ioinfo_nolock(int fd
)
252 if(fd
>=0 && fd
<MSVCRT_MAX_FILES
)
253 ret
= MSVCRT___pioinfo
[fd
/MSVCRT_FD_BLOCK_SIZE
];
255 return &MSVCRT___badioinfo
;
257 return ret
+ (fd
%MSVCRT_FD_BLOCK_SIZE
);
260 static inline ioinfo
* get_ioinfo(int fd
)
262 ioinfo
*ret
= get_ioinfo_nolock(fd
);
263 if(!(ret
->exflag
& EF_CRIT_INIT
)) {
265 if(!(ret
->exflag
& EF_CRIT_INIT
)) {
266 InitializeCriticalSection(&ret
->crit
);
267 ret
->exflag
|= EF_CRIT_INIT
;
271 EnterCriticalSection(&ret
->crit
);
275 static inline void release_ioinfo(ioinfo
*info
)
277 if(info
->exflag
& EF_CRIT_INIT
)
278 LeaveCriticalSection(&info
->crit
);
281 static inline MSVCRT_FILE
* msvcrt_get_file(int i
)
285 if(i
>= MSVCRT_max_streams
)
289 return &MSVCRT__iob
[i
];
291 ret
= MSVCRT_fstream
[i
/MSVCRT_FD_BLOCK_SIZE
];
293 MSVCRT_fstream
[i
/MSVCRT_FD_BLOCK_SIZE
] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE
, sizeof(file_crit
));
294 if(!MSVCRT_fstream
[i
/MSVCRT_FD_BLOCK_SIZE
]) {
295 ERR("out of memory\n");
296 *MSVCRT__errno() = MSVCRT_ENOMEM
;
300 ret
= MSVCRT_fstream
[i
/MSVCRT_FD_BLOCK_SIZE
] + (i
%MSVCRT_FD_BLOCK_SIZE
);
302 ret
+= i
%MSVCRT_FD_BLOCK_SIZE
;
307 static inline BOOL
msvcrt_is_valid_fd(int fd
)
309 return fd
>= 0 && fd
< MSVCRT_fdend
&& (get_ioinfo_nolock(fd
)->wxflag
& WX_OPEN
);
312 /* INTERNAL: Get the HANDLE for a fd
313 * This doesn't lock the table, because a failure will result in
314 * INVALID_HANDLE_VALUE being returned, which should be handled correctly. If
315 * it returns a valid handle which is about to be closed, a subsequent call
316 * will fail, most likely in a sane way.
318 static HANDLE
msvcrt_fdtoh(int fd
)
320 if (!msvcrt_is_valid_fd(fd
))
322 WARN(":fd (%d) - no handle!\n",fd
);
323 *MSVCRT___doserrno() = 0;
324 *MSVCRT__errno() = MSVCRT_EBADF
;
325 return INVALID_HANDLE_VALUE
;
327 if (get_ioinfo_nolock(fd
)->handle
== INVALID_HANDLE_VALUE
)
328 WARN("returning INVALID_HANDLE_VALUE for %d\n", fd
);
329 return get_ioinfo_nolock(fd
)->handle
;
332 /* INTERNAL: free a file entry fd */
333 static void msvcrt_free_fd(int fd
)
335 ioinfo
*fdinfo
= get_ioinfo(fd
);
337 if(fdinfo
!= &MSVCRT___badioinfo
)
339 fdinfo
->handle
= INVALID_HANDLE_VALUE
;
342 TRACE(":fd (%d) freed\n",fd
);
349 SetStdHandle(STD_INPUT_HANDLE
, 0);
352 SetStdHandle(STD_OUTPUT_HANDLE
, 0);
355 SetStdHandle(STD_ERROR_HANDLE
, 0);
359 release_ioinfo(fdinfo
);
362 if (fd
== MSVCRT_fdend
- 1)
364 if (fd
< MSVCRT_fdstart
)
369 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE, starting from fd */
370 /* caller must hold the files lock */
371 static int msvcrt_set_fd(HANDLE hand
, int flag
, int fd
)
375 if (fd
>= MSVCRT_MAX_FILES
)
377 WARN(":files exhausted!\n");
378 *MSVCRT__errno() = MSVCRT_ENFILE
;
382 fdinfo
= get_ioinfo_nolock(fd
);
383 if(fdinfo
== &MSVCRT___badioinfo
) {
386 MSVCRT___pioinfo
[fd
/MSVCRT_FD_BLOCK_SIZE
] = MSVCRT_calloc(MSVCRT_FD_BLOCK_SIZE
, sizeof(ioinfo
));
387 if(!MSVCRT___pioinfo
[fd
/MSVCRT_FD_BLOCK_SIZE
]) {
388 WARN(":out of memory!\n");
389 *MSVCRT__errno() = MSVCRT_ENOMEM
;
393 for(i
=0; i
<MSVCRT_FD_BLOCK_SIZE
; i
++)
394 MSVCRT___pioinfo
[fd
/MSVCRT_FD_BLOCK_SIZE
][i
].handle
= INVALID_HANDLE_VALUE
;
396 fdinfo
= get_ioinfo_nolock(fd
);
399 fdinfo
->handle
= hand
;
400 fdinfo
->wxflag
= WX_OPEN
| (flag
& (WX_DONTINHERIT
| WX_APPEND
| WX_TEXT
| WX_PIPE
| WX_TTY
));
401 fdinfo
->lookahead
[0] = '\n';
402 fdinfo
->lookahead
[1] = '\n';
403 fdinfo
->lookahead
[2] = '\n';
404 if(!(fdinfo
->exflag
& EF_CRIT_INIT
))
405 InitializeCriticalSection(&fdinfo
->crit
);
406 fdinfo
->exflag
= EF_CRIT_INIT
;
408 /* locate next free slot */
409 if (fd
== MSVCRT_fdstart
&& fd
== MSVCRT_fdend
)
410 MSVCRT_fdstart
= MSVCRT_fdend
+ 1;
412 while (MSVCRT_fdstart
< MSVCRT_fdend
&&
413 get_ioinfo_nolock(MSVCRT_fdstart
)->handle
!= INVALID_HANDLE_VALUE
)
415 /* update last fd in use */
416 if (fd
>= MSVCRT_fdend
)
417 MSVCRT_fdend
= fd
+ 1;
418 TRACE("fdstart is %d, fdend is %d\n", MSVCRT_fdstart
, MSVCRT_fdend
);
422 case 0: SetStdHandle(STD_INPUT_HANDLE
, hand
); break;
423 case 1: SetStdHandle(STD_OUTPUT_HANDLE
, hand
); break;
424 case 2: SetStdHandle(STD_ERROR_HANDLE
, hand
); break;
430 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
431 static int msvcrt_alloc_fd(HANDLE hand
, int flag
)
436 TRACE(":handle (%p) allocating fd (%d)\n",hand
,MSVCRT_fdstart
);
437 ret
= msvcrt_set_fd(hand
, flag
, MSVCRT_fdstart
);
442 /* INTERNAL: Allocate a FILE* for an fd slot */
443 /* caller must hold the files lock */
444 static MSVCRT_FILE
* msvcrt_alloc_fp(void)
449 for (i
= 3; i
< MSVCRT_max_streams
; i
++)
451 file
= msvcrt_get_file(i
);
455 if (file
->_flag
== 0)
457 if (i
== MSVCRT_stream_idx
)
459 if (file
<MSVCRT__iob
|| file
>=MSVCRT__iob
+_IOB_ENTRIES
)
461 InitializeCriticalSection(&((file_crit
*)file
)->crit
);
462 ((file_crit
*)file
)->crit
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": file_crit.crit");
473 /* INTERNAL: initialize a FILE* from an open fd */
474 static int msvcrt_init_fp(MSVCRT_FILE
* file
, int fd
, unsigned stream_flags
)
476 TRACE(":fd (%d) allocating FILE*\n",fd
);
477 if (!msvcrt_is_valid_fd(fd
))
479 WARN(":invalid fd %d\n",fd
);
480 *MSVCRT___doserrno() = 0;
481 *MSVCRT__errno() = MSVCRT_EBADF
;
484 file
->_ptr
= file
->_base
= NULL
;
487 file
->_flag
= stream_flags
;
488 file
->_tmpfname
= NULL
;
490 TRACE(":got FILE* (%p)\n",file
);
494 /* INTERNAL: Create an inheritance data block (for spawned process)
495 * The inheritance block is made of:
496 * 00 int nb of file descriptor (NBFD)
497 * 04 char file flags (wxflag): repeated for each fd
498 * 4+NBFD HANDLE file handle: repeated for each fd
500 unsigned msvcrt_create_io_inherit_block(WORD
*size
, BYTE
**block
)
507 *size
= sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE
)) * MSVCRT_fdend
;
508 *block
= MSVCRT_calloc(*size
, 1);
514 wxflag_ptr
= (char*)*block
+ sizeof(unsigned);
515 handle_ptr
= (HANDLE
*)(wxflag_ptr
+ MSVCRT_fdend
* sizeof(char));
517 *(unsigned*)*block
= MSVCRT_fdend
;
518 for (fd
= 0; fd
< MSVCRT_fdend
; fd
++)
520 /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */
521 fdinfo
= get_ioinfo_nolock(fd
);
522 if ((fdinfo
->wxflag
& (WX_OPEN
| WX_DONTINHERIT
)) == WX_OPEN
)
524 *wxflag_ptr
= fdinfo
->wxflag
;
525 *handle_ptr
= fdinfo
->handle
;
530 *handle_ptr
= INVALID_HANDLE_VALUE
;
532 wxflag_ptr
++; handle_ptr
++;
537 /* INTERNAL: Set up all file descriptors,
538 * as well as default streams (stdin, stderr and stdout)
540 void msvcrt_init_io(void)
546 GetStartupInfoA(&si
);
547 if (si
.cbReserved2
>= sizeof(unsigned int) && si
.lpReserved2
!= NULL
)
553 count
= *(unsigned*)si
.lpReserved2
;
554 wxflag_ptr
= si
.lpReserved2
+ sizeof(unsigned);
555 handle_ptr
= (HANDLE
*)(wxflag_ptr
+ count
);
557 count
= min(count
, (si
.cbReserved2
- sizeof(unsigned)) / (sizeof(HANDLE
) + 1));
558 count
= min(count
, MSVCRT_MAX_FILES
);
559 for (i
= 0; i
< count
; i
++)
561 if ((*wxflag_ptr
& WX_OPEN
) && *handle_ptr
!= INVALID_HANDLE_VALUE
)
562 msvcrt_set_fd(*handle_ptr
, *wxflag_ptr
, i
);
564 wxflag_ptr
++; handle_ptr
++;
566 MSVCRT_fdend
= max( 3, count
);
567 for (MSVCRT_fdstart
= 3; MSVCRT_fdstart
< MSVCRT_fdend
; MSVCRT_fdstart
++)
568 if (get_ioinfo_nolock(MSVCRT_fdstart
)->handle
== INVALID_HANDLE_VALUE
) break;
571 fdinfo
= get_ioinfo_nolock(MSVCRT_STDIN_FILENO
);
572 if (!(fdinfo
->wxflag
& WX_OPEN
) || fdinfo
->handle
== INVALID_HANDLE_VALUE
) {
573 HANDLE h
= GetStdHandle(STD_INPUT_HANDLE
);
574 DWORD type
= GetFileType(h
);
576 msvcrt_set_fd(h
, WX_OPEN
|WX_TEXT
|((type
&0xf)==FILE_TYPE_CHAR
? WX_TTY
: 0)
577 |((type
&0xf)==FILE_TYPE_PIPE
? WX_PIPE
: 0), MSVCRT_STDIN_FILENO
);
580 fdinfo
= get_ioinfo_nolock(MSVCRT_STDOUT_FILENO
);
581 if (!(fdinfo
->wxflag
& WX_OPEN
) || fdinfo
->handle
== INVALID_HANDLE_VALUE
) {
582 HANDLE h
= GetStdHandle(STD_OUTPUT_HANDLE
);
583 DWORD type
= GetFileType(h
);
585 msvcrt_set_fd(h
, WX_OPEN
|WX_TEXT
|((type
&0xf)==FILE_TYPE_CHAR
? WX_TTY
: 0)
586 |((type
&0xf)==FILE_TYPE_PIPE
? WX_PIPE
: 0), MSVCRT_STDOUT_FILENO
);
589 fdinfo
= get_ioinfo_nolock(MSVCRT_STDERR_FILENO
);
590 if (!(fdinfo
->wxflag
& WX_OPEN
) || fdinfo
->handle
== INVALID_HANDLE_VALUE
) {
591 HANDLE h
= GetStdHandle(STD_ERROR_HANDLE
);
592 DWORD type
= GetFileType(h
);
594 msvcrt_set_fd(h
, WX_OPEN
|WX_TEXT
|((type
&0xf)==FILE_TYPE_CHAR
? WX_TTY
: 0)
595 |((type
&0xf)==FILE_TYPE_PIPE
? WX_PIPE
: 0), MSVCRT_STDERR_FILENO
);
598 TRACE(":handles (%p)(%p)(%p)\n", get_ioinfo_nolock(MSVCRT_STDIN_FILENO
)->handle
,
599 get_ioinfo_nolock(MSVCRT_STDOUT_FILENO
)->handle
,
600 get_ioinfo_nolock(MSVCRT_STDERR_FILENO
)->handle
);
602 memset(MSVCRT__iob
,0,3*sizeof(MSVCRT_FILE
));
603 for (i
= 0; i
< 3; i
++)
605 /* FILE structs for stdin/out/err are static and never deleted */
606 MSVCRT__iob
[i
]._file
= i
;
607 MSVCRT__iob
[i
]._tmpfname
= NULL
;
608 MSVCRT__iob
[i
]._flag
= (i
== 0) ? MSVCRT__IOREAD
: MSVCRT__IOWRT
;
610 MSVCRT_stream_idx
= 3;
613 /* INTERNAL: Flush stdio file buffer */
614 static int msvcrt_flush_buffer(MSVCRT_FILE
* file
)
616 if((file
->_flag
& (MSVCRT__IOREAD
|MSVCRT__IOWRT
)) == MSVCRT__IOWRT
&&
617 file
->_flag
& (MSVCRT__IOMYBUF
|MSVCRT__USERBUF
)) {
618 int cnt
=file
->_ptr
-file
->_base
;
619 if(cnt
>0 && MSVCRT__write(file
->_file
, file
->_base
, cnt
) != cnt
) {
620 file
->_flag
|= MSVCRT__IOERR
;
624 if(file
->_flag
& MSVCRT__IORW
)
625 file
->_flag
&= ~MSVCRT__IOWRT
;
628 file
->_ptr
=file
->_base
;
633 /*********************************************************************
636 int CDECL
MSVCRT__isatty(int fd
)
638 TRACE(":fd (%d)\n",fd
);
640 return get_ioinfo_nolock(fd
)->wxflag
& WX_TTY
;
643 /* INTERNAL: Allocate stdio file buffer */
644 static BOOL
msvcrt_alloc_buffer(MSVCRT_FILE
* file
)
646 if((file
->_file
==MSVCRT_STDOUT_FILENO
|| file
->_file
==MSVCRT_STDERR_FILENO
)
647 && MSVCRT__isatty(file
->_file
))
650 file
->_base
= MSVCRT_calloc(MSVCRT_INTERNAL_BUFSIZ
,1);
652 file
->_bufsiz
= MSVCRT_INTERNAL_BUFSIZ
;
653 file
->_flag
|= MSVCRT__IOMYBUF
;
655 file
->_base
= (char*)(&file
->_charbuf
);
657 file
->_flag
|= MSVCRT__IONBF
;
659 file
->_ptr
= file
->_base
;
664 /* INTERNAL: Allocate temporary buffer for stdout and stderr */
665 static BOOL
add_std_buffer(MSVCRT_FILE
*file
)
667 static char buffers
[2][MSVCRT_BUFSIZ
];
669 if((file
->_file
!=MSVCRT_STDOUT_FILENO
&& file
->_file
!=MSVCRT_STDERR_FILENO
)
670 || (file
->_flag
& (MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
))
671 || !MSVCRT__isatty(file
->_file
))
674 file
->_ptr
= file
->_base
= buffers
[file
->_file
== MSVCRT_STDOUT_FILENO
? 0 : 1];
675 file
->_bufsiz
= file
->_cnt
= MSVCRT_BUFSIZ
;
676 file
->_flag
|= MSVCRT__USERBUF
;
680 /* INTERNAL: Removes temporary buffer from stdout or stderr */
681 /* Only call this function when add_std_buffer returned TRUE */
682 static void remove_std_buffer(MSVCRT_FILE
*file
)
684 msvcrt_flush_buffer(file
);
685 file
->_ptr
= file
->_base
= NULL
;
686 file
->_bufsiz
= file
->_cnt
= 0;
687 file
->_flag
&= ~MSVCRT__USERBUF
;
690 /* INTERNAL: Convert integer to base32 string (0-9a-v), 0 becomes "" */
691 static int msvcrt_int_to_base32(int num
, char *str
)
706 *p
= (num
& 31) + '0';
708 *p
+= ('a' - '0' - 10);
715 /* INTERNAL: wide character version of msvcrt_int_to_base32 */
716 static int msvcrt_int_to_base32_w(int num
, MSVCRT_wchar_t
*str
)
731 *p
= (num
& 31) + '0';
733 *p
+= ('a' - '0' - 10);
740 /*********************************************************************
741 * __iob_func(MSVCRT.@)
743 MSVCRT_FILE
* CDECL
MSVCRT___iob_func(void)
745 return &MSVCRT__iob
[0];
748 /*********************************************************************
751 int CDECL
MSVCRT__access(const char *filename
, int mode
)
753 DWORD attr
= GetFileAttributesA(filename
);
755 TRACE("(%s,%d) %d\n",filename
,mode
,attr
);
757 if (!filename
|| attr
== INVALID_FILE_ATTRIBUTES
)
759 msvcrt_set_errno(GetLastError());
762 if ((attr
& FILE_ATTRIBUTE_READONLY
) && (mode
& MSVCRT_W_OK
))
764 msvcrt_set_errno(ERROR_ACCESS_DENIED
);
770 /*********************************************************************
771 * _access_s (MSVCRT.@)
773 int CDECL
MSVCRT__access_s(const char *filename
, int mode
)
775 if (!MSVCRT_CHECK_PMT(filename
!= NULL
)) return *MSVCRT__errno();
776 if (!MSVCRT_CHECK_PMT((mode
& ~(MSVCRT_R_OK
| MSVCRT_W_OK
)) == 0)) return *MSVCRT__errno();
778 if (MSVCRT__access(filename
, mode
) == -1)
779 return *MSVCRT__errno();
783 /*********************************************************************
784 * _waccess (MSVCRT.@)
786 int CDECL
MSVCRT__waccess(const MSVCRT_wchar_t
*filename
, int mode
)
788 DWORD attr
= GetFileAttributesW(filename
);
790 TRACE("(%s,%d) %d\n",debugstr_w(filename
),mode
,attr
);
792 if (!filename
|| attr
== INVALID_FILE_ATTRIBUTES
)
794 msvcrt_set_errno(GetLastError());
797 if ((attr
& FILE_ATTRIBUTE_READONLY
) && (mode
& MSVCRT_W_OK
))
799 msvcrt_set_errno(ERROR_ACCESS_DENIED
);
805 /*********************************************************************
806 * _waccess_s (MSVCRT.@)
808 int CDECL
MSVCRT__waccess_s(const MSVCRT_wchar_t
*filename
, int mode
)
810 if (!MSVCRT_CHECK_PMT(filename
!= NULL
)) return *MSVCRT__errno();
811 if (!MSVCRT_CHECK_PMT((mode
& ~(MSVCRT_R_OK
| MSVCRT_W_OK
)) == 0)) return *MSVCRT__errno();
813 if (MSVCRT__waccess(filename
, mode
) == -1)
814 return *MSVCRT__errno();
818 /*********************************************************************
821 int CDECL
MSVCRT__chmod(const char *path
, int flags
)
823 DWORD oldFlags
= GetFileAttributesA(path
);
825 if (oldFlags
!= INVALID_FILE_ATTRIBUTES
)
827 DWORD newFlags
= (flags
& MSVCRT__S_IWRITE
)? oldFlags
& ~FILE_ATTRIBUTE_READONLY
:
828 oldFlags
| FILE_ATTRIBUTE_READONLY
;
830 if (newFlags
== oldFlags
|| SetFileAttributesA(path
, newFlags
))
833 msvcrt_set_errno(GetLastError());
837 /*********************************************************************
840 int CDECL
MSVCRT__wchmod(const MSVCRT_wchar_t
*path
, int flags
)
842 DWORD oldFlags
= GetFileAttributesW(path
);
844 if (oldFlags
!= INVALID_FILE_ATTRIBUTES
)
846 DWORD newFlags
= (flags
& MSVCRT__S_IWRITE
)? oldFlags
& ~FILE_ATTRIBUTE_READONLY
:
847 oldFlags
| FILE_ATTRIBUTE_READONLY
;
849 if (newFlags
== oldFlags
|| SetFileAttributesW(path
, newFlags
))
852 msvcrt_set_errno(GetLastError());
856 /*********************************************************************
859 int CDECL
MSVCRT__unlink(const char *path
)
861 TRACE("%s\n",debugstr_a(path
));
862 if(DeleteFileA(path
))
864 TRACE("failed (%d)\n",GetLastError());
865 msvcrt_set_errno(GetLastError());
869 /*********************************************************************
870 * _wunlink (MSVCRT.@)
872 int CDECL
MSVCRT__wunlink(const MSVCRT_wchar_t
*path
)
874 TRACE("(%s)\n",debugstr_w(path
));
875 if(DeleteFileW(path
))
877 TRACE("failed (%d)\n",GetLastError());
878 msvcrt_set_errno(GetLastError());
882 /*********************************************************************
885 int CDECL
MSVCRT__commit(int fd
)
887 ioinfo
*info
= get_ioinfo(fd
);
890 TRACE(":fd (%d) handle (%p)\n", fd
, info
->handle
);
892 if (info
->handle
== INVALID_HANDLE_VALUE
)
894 else if (!FlushFileBuffers(info
->handle
))
896 if (GetLastError() == ERROR_INVALID_HANDLE
)
898 /* FlushFileBuffers fails for console handles
899 * so we ignore this error.
905 TRACE(":failed-last error (%d)\n",GetLastError());
906 msvcrt_set_errno(GetLastError());
916 release_ioinfo(info
);
920 /* flush_all_buffers calls MSVCRT_fflush which calls flush_all_buffers */
921 int CDECL
MSVCRT_fflush(MSVCRT_FILE
* file
);
923 /* INTERNAL: Flush all stream buffer */
924 static int msvcrt_flush_all_buffers(int mask
)
926 int i
, num_flushed
= 0;
930 for (i
= 0; i
< MSVCRT_stream_idx
; i
++) {
931 file
= msvcrt_get_file(i
);
935 if(file
->_flag
& mask
) {
943 TRACE(":flushed (%d) handles\n",num_flushed
);
947 /*********************************************************************
948 * _flushall (MSVCRT.@)
950 int CDECL
MSVCRT__flushall(void)
952 return msvcrt_flush_all_buffers(MSVCRT__IOWRT
| MSVCRT__IOREAD
);
955 /*********************************************************************
958 int CDECL
MSVCRT_fflush(MSVCRT_FILE
* file
)
963 msvcrt_flush_all_buffers(MSVCRT__IOWRT
);
966 MSVCRT__lock_file(file
);
967 ret
= MSVCRT__fflush_nolock(file
);
968 MSVCRT__unlock_file(file
);
974 /*********************************************************************
975 * _fflush_nolock (MSVCRT.@)
977 int CDECL
MSVCRT__fflush_nolock(MSVCRT_FILE
* file
)
982 msvcrt_flush_all_buffers(MSVCRT__IOWRT
);
986 res
= msvcrt_flush_buffer(file
);
987 if(!res
&& (file
->_flag
& MSVCRT__IOCOMMIT
))
988 res
= MSVCRT__commit(file
->_file
) ? MSVCRT_EOF
: 0;
992 /*********************************************************************
995 int CDECL
MSVCRT__close(int fd
)
997 ioinfo
*info
= get_ioinfo(fd
);
1001 TRACE(":fd (%d) handle (%p)\n", fd
, info
->handle
);
1002 if (!(info
->wxflag
& WX_OPEN
)) {
1005 ret
= CloseHandle(info
->handle
) ? 0 : -1;
1008 WARN(":failed-last error (%d)\n",GetLastError());
1009 msvcrt_set_errno(GetLastError());
1013 release_ioinfo(info
);
1017 /*********************************************************************
1020 * MSDN isn't clear on this point, but the remarks for _pipe
1021 * indicate file descriptors duplicated with _dup and _dup2 are always
1024 int CDECL
MSVCRT__dup2(int od
, int nd
)
1026 ioinfo
*info_od
, *info_nd
;
1029 TRACE("(od=%d, nd=%d)\n", od
, nd
);
1034 info_od
= get_ioinfo(od
);
1035 info_nd
= get_ioinfo(nd
);
1039 info_nd
= get_ioinfo(nd
);
1040 info_od
= get_ioinfo(od
);
1043 if (nd
< MSVCRT_MAX_FILES
&& nd
>= 0 && (info_od
->wxflag
& WX_OPEN
))
1047 if (DuplicateHandle(GetCurrentProcess(), info_od
->handle
,
1048 GetCurrentProcess(), &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
))
1050 int wxflag
= info_od
->wxflag
& ~MSVCRT__O_NOINHERIT
;
1052 if (info_nd
->wxflag
& WX_OPEN
)
1054 ret
= msvcrt_set_fd(handle
, wxflag
, nd
);
1057 CloseHandle(handle
);
1058 *MSVCRT__errno() = MSVCRT_EMFILE
;
1062 /* _dup2 returns 0, not nd, on success */
1069 msvcrt_set_errno(GetLastError());
1074 *MSVCRT__errno() = MSVCRT_EBADF
;
1078 release_ioinfo(info_od
);
1079 release_ioinfo(info_nd
);
1084 /*********************************************************************
1087 int CDECL
MSVCRT__dup(int od
)
1092 fd
= MSVCRT_fdstart
;
1093 if (MSVCRT__dup2(od
, fd
) == 0)
1101 /*********************************************************************
1104 int CDECL
MSVCRT__eof(int fd
)
1106 ioinfo
*info
= get_ioinfo(fd
);
1107 DWORD curpos
,endpos
;
1108 LONG hcurpos
,hendpos
;
1110 TRACE(":fd (%d) handle (%p)\n", fd
, info
->handle
);
1112 if (info
->handle
== INVALID_HANDLE_VALUE
)
1114 release_ioinfo(info
);
1118 if (info
->wxflag
& WX_ATEOF
)
1120 release_ioinfo(info
);
1124 /* Otherwise we do it the hard way */
1125 hcurpos
= hendpos
= 0;
1126 curpos
= SetFilePointer(info
->handle
, 0, &hcurpos
, FILE_CURRENT
);
1127 endpos
= SetFilePointer(info
->handle
, 0, &hendpos
, FILE_END
);
1129 if (curpos
== endpos
&& hcurpos
== hendpos
)
1131 /* FIXME: shouldn't WX_ATEOF be set here? */
1132 release_ioinfo(info
);
1136 SetFilePointer(info
->handle
, curpos
, &hcurpos
, FILE_BEGIN
);
1137 release_ioinfo(info
);
1141 /*********************************************************************
1142 * _fcloseall (MSVCRT.@)
1144 int CDECL
MSVCRT__fcloseall(void)
1146 int num_closed
= 0, i
;
1150 for (i
= 3; i
< MSVCRT_stream_idx
; i
++) {
1151 file
= msvcrt_get_file(i
);
1153 if (file
->_flag
&& !MSVCRT_fclose(file
))
1158 TRACE(":closed (%d) handles\n",num_closed
);
1162 /* free everything on process exit */
1163 void msvcrt_free_io(void)
1169 MSVCRT__fcloseall();
1171 for(i
=0; i
<sizeof(MSVCRT___pioinfo
)/sizeof(MSVCRT___pioinfo
[0]); i
++)
1173 if(!MSVCRT___pioinfo
[i
])
1176 for(j
=0; j
<MSVCRT_FD_BLOCK_SIZE
; j
++)
1178 if(MSVCRT___pioinfo
[i
][j
].exflag
& EF_CRIT_INIT
)
1179 DeleteCriticalSection(&MSVCRT___pioinfo
[i
][j
].crit
);
1181 MSVCRT_free(MSVCRT___pioinfo
[i
]);
1184 for(j
=0; j
<MSVCRT_stream_idx
; j
++)
1186 MSVCRT_FILE
*file
= msvcrt_get_file(j
);
1187 if(file
<MSVCRT__iob
|| file
>=MSVCRT__iob
+_IOB_ENTRIES
)
1189 ((file_crit
*)file
)->crit
.DebugInfo
->Spare
[0] = 0;
1190 DeleteCriticalSection(&((file_crit
*)file
)->crit
);
1194 for(i
=0; i
<sizeof(MSVCRT_fstream
)/sizeof(MSVCRT_fstream
[0]); i
++)
1195 MSVCRT_free(MSVCRT_fstream
[i
]);
1197 DeleteCriticalSection(&MSVCRT_file_cs
);
1200 /*********************************************************************
1201 * _lseeki64 (MSVCRT.@)
1203 __int64 CDECL
MSVCRT__lseeki64(int fd
, __int64 offset
, int whence
)
1205 ioinfo
*info
= get_ioinfo(fd
);
1208 TRACE(":fd (%d) handle (%p)\n", fd
, info
->handle
);
1210 if (info
->handle
== INVALID_HANDLE_VALUE
)
1212 release_ioinfo(info
);
1216 if (whence
< 0 || whence
> 2)
1218 release_ioinfo(info
);
1219 *MSVCRT__errno() = MSVCRT_EINVAL
;
1223 TRACE(":fd (%d) to %s pos %s\n",
1224 fd
,wine_dbgstr_longlong(offset
),
1225 (whence
==SEEK_SET
)?"SEEK_SET":
1226 (whence
==SEEK_CUR
)?"SEEK_CUR":
1227 (whence
==SEEK_END
)?"SEEK_END":"UNKNOWN");
1229 /* The MoleBox protection scheme expects msvcrt to use SetFilePointer only,
1230 * so a LARGE_INTEGER offset cannot be passed directly via SetFilePointerEx. */
1231 ofs
.QuadPart
= offset
;
1232 if ((ofs
.u
.LowPart
= SetFilePointer(info
->handle
, ofs
.u
.LowPart
, &ofs
.u
.HighPart
, whence
)) != INVALID_SET_FILE_POINTER
||
1233 GetLastError() == ERROR_SUCCESS
)
1235 info
->wxflag
&= ~WX_ATEOF
;
1236 /* FIXME: What if we seek _to_ EOF - is EOF set? */
1238 release_ioinfo(info
);
1239 return ofs
.QuadPart
;
1241 release_ioinfo(info
);
1242 TRACE(":error-last error (%d)\n",GetLastError());
1243 msvcrt_set_errno(GetLastError());
1247 /*********************************************************************
1250 LONG CDECL
MSVCRT__lseek(int fd
, LONG offset
, int whence
)
1252 return MSVCRT__lseeki64(fd
, offset
, whence
);
1255 /*********************************************************************
1256 * _lock_file (MSVCRT.@)
1258 void CDECL
MSVCRT__lock_file(MSVCRT_FILE
*file
)
1260 if(file
>=MSVCRT__iob
&& file
<MSVCRT__iob
+_IOB_ENTRIES
)
1261 _lock(_STREAM_LOCKS
+(file
-MSVCRT__iob
));
1263 EnterCriticalSection(&((file_crit
*)file
)->crit
);
1266 /*********************************************************************
1267 * _unlock_file (MSVCRT.@)
1269 void CDECL
MSVCRT__unlock_file(MSVCRT_FILE
*file
)
1271 if(file
>=MSVCRT__iob
&& file
<MSVCRT__iob
+_IOB_ENTRIES
)
1272 _unlock(_STREAM_LOCKS
+(file
-MSVCRT__iob
));
1274 LeaveCriticalSection(&((file_crit
*)file
)->crit
);
1277 /*********************************************************************
1278 * _locking (MSVCRT.@)
1280 * This is untested; the underlying LockFile doesn't work yet.
1282 int CDECL
MSVCRT__locking(int fd
, int mode
, LONG nbytes
)
1284 ioinfo
*info
= get_ioinfo(fd
);
1288 TRACE(":fd (%d) handle (%p)\n", fd
, info
->handle
);
1289 if (info
->handle
== INVALID_HANDLE_VALUE
)
1291 release_ioinfo(info
);
1295 if (mode
< 0 || mode
> 4)
1297 release_ioinfo(info
);
1298 *MSVCRT__errno() = MSVCRT_EINVAL
;
1302 TRACE(":fd (%d) by 0x%08x mode %s\n",
1303 fd
,nbytes
,(mode
==MSVCRT__LK_UNLCK
)?"_LK_UNLCK":
1304 (mode
==MSVCRT__LK_LOCK
)?"_LK_LOCK":
1305 (mode
==MSVCRT__LK_NBLCK
)?"_LK_NBLCK":
1306 (mode
==MSVCRT__LK_RLCK
)?"_LK_RLCK":
1307 (mode
==MSVCRT__LK_NBRLCK
)?"_LK_NBRLCK":
1310 if ((cur_locn
= SetFilePointer(info
->handle
, 0L, NULL
, SEEK_CUR
)) == INVALID_SET_FILE_POINTER
)
1312 release_ioinfo(info
);
1313 FIXME ("Seek failed\n");
1314 *MSVCRT__errno() = MSVCRT_EINVAL
; /* FIXME */
1317 if (mode
== MSVCRT__LK_LOCK
|| mode
== MSVCRT__LK_RLCK
)
1320 ret
= 1; /* just to satisfy gcc */
1323 ret
= LockFile(info
->handle
, cur_locn
, 0L, nbytes
, 0L);
1328 else if (mode
== MSVCRT__LK_UNLCK
)
1329 ret
= UnlockFile(info
->handle
, cur_locn
, 0L, nbytes
, 0L);
1331 ret
= LockFile(info
->handle
, cur_locn
, 0L, nbytes
, 0L);
1332 /* FIXME - what about error settings? */
1333 release_ioinfo(info
);
1334 return ret
? 0 : -1;
1337 /*********************************************************************
1338 * _fseeki64 (MSVCRT.@)
1340 int CDECL
MSVCRT__fseeki64(MSVCRT_FILE
* file
, __int64 offset
, int whence
)
1344 MSVCRT__lock_file(file
);
1345 ret
= MSVCRT__fseeki64_nolock(file
, offset
, whence
);
1346 MSVCRT__unlock_file(file
);
1351 /*********************************************************************
1352 * _fseeki64_nolock (MSVCRT.@)
1354 int CDECL
MSVCRT__fseeki64_nolock(MSVCRT_FILE
* file
, __int64 offset
, int whence
)
1358 if(whence
== SEEK_CUR
&& file
->_flag
& MSVCRT__IOREAD
) {
1360 offset
+= MSVCRT__ftelli64_nolock(file
);
1363 /* Flush output if needed */
1364 msvcrt_flush_buffer(file
);
1365 /* Reset direction of i/o */
1366 if(file
->_flag
& MSVCRT__IORW
) {
1367 file
->_flag
&= ~(MSVCRT__IOREAD
|MSVCRT__IOWRT
);
1369 /* Clear end of file flag */
1370 file
->_flag
&= ~MSVCRT__IOEOF
;
1371 ret
= (MSVCRT__lseeki64(file
->_file
,offset
,whence
) == -1)?-1:0;
1376 /*********************************************************************
1379 int CDECL
MSVCRT_fseek(MSVCRT_FILE
* file
, MSVCRT_long offset
, int whence
)
1381 return MSVCRT__fseeki64( file
, offset
, whence
);
1384 /*********************************************************************
1385 * _fseek_nolock (MSVCRT.@)
1387 int CDECL
MSVCRT__fseek_nolock(MSVCRT_FILE
* file
, MSVCRT_long offset
, int whence
)
1389 return MSVCRT__fseeki64_nolock( file
, offset
, whence
);
1392 /*********************************************************************
1393 * _chsize_s (MSVCRT.@)
1395 int CDECL
MSVCRT__chsize_s(int fd
, __int64 size
)
1401 TRACE("(fd=%d, size=%s)\n", fd
, wine_dbgstr_longlong(size
));
1403 if (!MSVCRT_CHECK_PMT(size
>= 0)) return MSVCRT_EINVAL
;
1406 info
= get_ioinfo(fd
);
1407 if (info
->handle
!= INVALID_HANDLE_VALUE
)
1409 /* save the current file pointer */
1410 cur
= MSVCRT__lseeki64(fd
, 0, SEEK_CUR
);
1413 pos
= MSVCRT__lseeki64(fd
, size
, SEEK_SET
);
1416 ret
= SetEndOfFile(info
->handle
);
1417 if (!ret
) msvcrt_set_errno(GetLastError());
1420 /* restore the file pointer */
1421 MSVCRT__lseeki64(fd
, cur
, SEEK_SET
);
1425 release_ioinfo(info
);
1426 return ret
? 0 : *MSVCRT__errno();
1429 /*********************************************************************
1430 * _chsize (MSVCRT.@)
1432 int CDECL
MSVCRT__chsize(int fd
, MSVCRT_long size
)
1434 /* _chsize_s returns errno on failure but _chsize should return -1 */
1435 return MSVCRT__chsize_s( fd
, size
) == 0 ? 0 : -1;
1438 /*********************************************************************
1439 * clearerr (MSVCRT.@)
1441 void CDECL
MSVCRT_clearerr(MSVCRT_FILE
* file
)
1443 TRACE(":file (%p) fd (%d)\n",file
,file
->_file
);
1445 MSVCRT__lock_file(file
);
1446 file
->_flag
&= ~(MSVCRT__IOERR
| MSVCRT__IOEOF
);
1447 MSVCRT__unlock_file(file
);
1450 /*********************************************************************
1453 void CDECL
MSVCRT_rewind(MSVCRT_FILE
* file
)
1455 TRACE(":file (%p) fd (%d)\n",file
,file
->_file
);
1457 MSVCRT__lock_file(file
);
1458 MSVCRT__fseek_nolock(file
, 0L, SEEK_SET
);
1459 MSVCRT_clearerr(file
);
1460 MSVCRT__unlock_file(file
);
1463 static int msvcrt_get_flags(const MSVCRT_wchar_t
* mode
, int *open_flags
, int* stream_flags
)
1465 int plus
= strchrW(mode
, '+') != NULL
;
1467 TRACE("%s\n", debugstr_w(mode
));
1469 while(*mode
== ' ') mode
++;
1474 *open_flags
= plus
? MSVCRT__O_RDWR
: MSVCRT__O_RDONLY
;
1475 *stream_flags
= plus
? MSVCRT__IORW
: MSVCRT__IOREAD
;
1478 *open_flags
= MSVCRT__O_CREAT
| MSVCRT__O_TRUNC
| (plus
? MSVCRT__O_RDWR
: MSVCRT__O_WRONLY
);
1479 *stream_flags
= plus
? MSVCRT__IORW
: MSVCRT__IOWRT
;
1482 *open_flags
= MSVCRT__O_CREAT
| MSVCRT__O_APPEND
| (plus
? MSVCRT__O_RDWR
: MSVCRT__O_WRONLY
);
1483 *stream_flags
= plus
? MSVCRT__IORW
: MSVCRT__IOWRT
;
1486 MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL
);
1490 *stream_flags
|= MSVCRT__commode
;
1492 while (*mode
&& *mode
!=',')
1496 *open_flags
|= MSVCRT__O_BINARY
;
1497 *open_flags
&= ~MSVCRT__O_TEXT
;
1500 *open_flags
|= MSVCRT__O_TEXT
;
1501 *open_flags
&= ~MSVCRT__O_BINARY
;
1504 *open_flags
|= MSVCRT__O_TEMPORARY
;
1507 *open_flags
|= MSVCRT__O_SHORT_LIVED
;
1510 *stream_flags
|= MSVCRT__IOCOMMIT
;
1513 *stream_flags
&= ~MSVCRT__IOCOMMIT
;
1516 *open_flags
|= MSVCRT__O_NOINHERIT
;
1525 FIXME("ignoring cache optimization flag: %c\n", mode
[-1]);
1528 ERR("incorrect mode flag: %c\n", mode
[-1]);
1534 static const WCHAR ccs
[] = {'c','c','s'};
1535 static const WCHAR utf8
[] = {'u','t','f','-','8'};
1536 static const WCHAR utf16le
[] = {'u','t','f','-','1','6','l','e'};
1537 static const WCHAR unicode
[] = {'u','n','i','c','o','d','e'};
1540 while(*mode
== ' ') mode
++;
1541 if(!MSVCRT_CHECK_PMT(!strncmpW(ccs
, mode
, sizeof(ccs
)/sizeof(ccs
[0]))))
1543 mode
+= sizeof(ccs
)/sizeof(ccs
[0]);
1544 while(*mode
== ' ') mode
++;
1545 if(!MSVCRT_CHECK_PMT(*mode
== '='))
1548 while(*mode
== ' ') mode
++;
1550 if(!strncmpiW(utf8
, mode
, sizeof(utf8
)/sizeof(utf8
[0])))
1552 *open_flags
|= MSVCRT__O_U8TEXT
;
1553 mode
+= sizeof(utf8
)/sizeof(utf8
[0]);
1555 else if(!strncmpiW(utf16le
, mode
, sizeof(utf16le
)/sizeof(utf16le
[0])))
1557 *open_flags
|= MSVCRT__O_U16TEXT
;
1558 mode
+= sizeof(utf16le
)/sizeof(utf16le
[0]);
1560 else if(!strncmpiW(unicode
, mode
, sizeof(unicode
)/sizeof(unicode
[0])))
1562 *open_flags
|= MSVCRT__O_WTEXT
;
1563 mode
+= sizeof(unicode
)/sizeof(unicode
[0]);
1567 MSVCRT_INVALID_PMT(0, MSVCRT_EINVAL
);
1571 while(*mode
== ' ') mode
++;
1574 if(!MSVCRT_CHECK_PMT(*mode
== 0))
1579 /*********************************************************************
1580 * _fdopen (MSVCRT.@)
1582 MSVCRT_FILE
* CDECL
MSVCRT__fdopen(int fd
, const char *mode
)
1585 MSVCRT_wchar_t
*modeW
= NULL
;
1587 if (mode
&& !(modeW
= msvcrt_wstrdupa(mode
))) return NULL
;
1589 ret
= MSVCRT__wfdopen(fd
, modeW
);
1595 /*********************************************************************
1596 * _wfdopen (MSVCRT.@)
1598 MSVCRT_FILE
* CDECL
MSVCRT__wfdopen(int fd
, const MSVCRT_wchar_t
*mode
)
1600 int open_flags
, stream_flags
;
1603 if (msvcrt_get_flags(mode
, &open_flags
, &stream_flags
) == -1) return NULL
;
1606 if (!(file
= msvcrt_alloc_fp()))
1608 else if (msvcrt_init_fp(file
, fd
, stream_flags
) == -1)
1613 else TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd
, debugstr_w(mode
), file
);
1619 /*********************************************************************
1620 * _filelength (MSVCRT.@)
1622 LONG CDECL
MSVCRT__filelength(int fd
)
1624 LONG curPos
= MSVCRT__lseek(fd
, 0, SEEK_CUR
);
1627 LONG endPos
= MSVCRT__lseek(fd
, 0, SEEK_END
);
1630 if (endPos
!= curPos
)
1631 MSVCRT__lseek(fd
, curPos
, SEEK_SET
);
1638 /*********************************************************************
1639 * _filelengthi64 (MSVCRT.@)
1641 __int64 CDECL
MSVCRT__filelengthi64(int fd
)
1643 __int64 curPos
= MSVCRT__lseeki64(fd
, 0, SEEK_CUR
);
1646 __int64 endPos
= MSVCRT__lseeki64(fd
, 0, SEEK_END
);
1649 if (endPos
!= curPos
)
1650 MSVCRT__lseeki64(fd
, curPos
, SEEK_SET
);
1657 /*********************************************************************
1658 * _fileno (MSVCRT.@)
1660 int CDECL
MSVCRT__fileno(MSVCRT_FILE
* file
)
1662 TRACE(":FILE* (%p) fd (%d)\n",file
,file
->_file
);
1666 /*********************************************************************
1667 * _fstat64 (MSVCRT.@)
1669 int CDECL
MSVCRT__fstat64(int fd
, struct MSVCRT__stat64
* buf
)
1671 ioinfo
*info
= get_ioinfo(fd
);
1674 BY_HANDLE_FILE_INFORMATION hfi
;
1676 TRACE(":fd (%d) stat (%p)\n", fd
, buf
);
1677 if (info
->handle
== INVALID_HANDLE_VALUE
)
1679 release_ioinfo(info
);
1685 WARN(":failed-NULL buf\n");
1686 msvcrt_set_errno(ERROR_INVALID_PARAMETER
);
1687 release_ioinfo(info
);
1691 memset(&hfi
, 0, sizeof(hfi
));
1692 memset(buf
, 0, sizeof(struct MSVCRT__stat64
));
1693 type
= GetFileType(info
->handle
);
1694 if (type
== FILE_TYPE_PIPE
)
1696 buf
->st_dev
= buf
->st_rdev
= fd
;
1697 buf
->st_mode
= S_IFIFO
;
1700 else if (type
== FILE_TYPE_CHAR
)
1702 buf
->st_dev
= buf
->st_rdev
= fd
;
1703 buf
->st_mode
= S_IFCHR
;
1706 else /* FILE_TYPE_DISK etc. */
1708 if (!GetFileInformationByHandle(info
->handle
, &hfi
))
1710 WARN(":failed-last error (%d)\n",GetLastError());
1711 msvcrt_set_errno(ERROR_INVALID_PARAMETER
);
1712 release_ioinfo(info
);
1715 buf
->st_mode
= S_IFREG
| 0444;
1716 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1717 buf
->st_mode
|= 0222;
1718 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
1719 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
1721 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
1722 buf
->st_mtime
= buf
->st_ctime
= dw
;
1723 buf
->st_nlink
= hfi
.nNumberOfLinks
;
1725 TRACE(":dwFileAttributes = 0x%x, mode set to 0x%x\n",hfi
.dwFileAttributes
,
1727 release_ioinfo(info
);
1731 /*********************************************************************
1732 * _fstati64 (MSVCRT.@)
1734 int CDECL
MSVCRT__fstati64(int fd
, struct MSVCRT__stati64
* buf
)
1737 struct MSVCRT__stat64 buf64
;
1739 ret
= MSVCRT__fstat64(fd
, &buf64
);
1741 msvcrt_stat64_to_stati64(&buf64
, buf
);
1745 /*********************************************************************
1748 int CDECL
MSVCRT__fstat(int fd
, struct MSVCRT__stat
* buf
)
1750 struct MSVCRT__stat64 buf64
;
1752 ret
= MSVCRT__fstat64(fd
, &buf64
);
1754 msvcrt_stat64_to_stat(&buf64
, buf
);
1758 /*********************************************************************
1759 * _fstat32 (MSVCR80.@)
1761 int CDECL
MSVCRT__fstat32(int fd
, struct MSVCRT__stat32
* buf
)
1764 struct MSVCRT__stat64 buf64
;
1766 ret
= MSVCRT__fstat64(fd
, &buf64
);
1768 msvcrt_stat64_to_stat32(&buf64
, buf
);
1772 /*********************************************************************
1773 * _fstat64i32 (MSVCR80.@)
1775 int CDECL
MSVCRT__fstat64i32(int fd
, struct MSVCRT__stat64i32
* buf
)
1778 struct MSVCRT__stat64 buf64
;
1780 ret
= MSVCRT__fstat64(fd
, &buf64
);
1782 msvcrt_stat64_to_stat64i32(&buf64
, buf
);
1786 /*********************************************************************
1787 * _futime64 (MSVCRT.@)
1789 int CDECL
_futime64(int fd
, struct MSVCRT___utimbuf64
*t
)
1791 ioinfo
*info
= get_ioinfo(fd
);
1796 time_to_filetime( MSVCRT__time64(NULL
), &at
);
1801 time_to_filetime( t
->actime
, &at
);
1802 time_to_filetime( t
->modtime
, &wt
);
1805 if (!SetFileTime(info
->handle
, NULL
, &at
, &wt
))
1807 release_ioinfo(info
);
1808 msvcrt_set_errno(GetLastError());
1811 release_ioinfo(info
);
1815 /*********************************************************************
1816 * _futime32 (MSVCRT.@)
1818 int CDECL
_futime32(int fd
, struct MSVCRT___utimbuf32
*t
)
1822 struct MSVCRT___utimbuf64 t64
;
1823 t64
.actime
= t
->actime
;
1824 t64
.modtime
= t
->modtime
;
1825 return _futime64( fd
, &t64
);
1828 return _futime64( fd
, NULL
);
1831 /*********************************************************************
1832 * _futime (MSVCRT.@)
1835 int CDECL
_futime(int fd
, struct MSVCRT___utimbuf64
*t
)
1837 return _futime64( fd
, t
);
1840 int CDECL
_futime(int fd
, struct MSVCRT___utimbuf32
*t
)
1842 return _futime32( fd
, t
);
1846 /*********************************************************************
1847 * _get_osfhandle (MSVCRT.@)
1849 MSVCRT_intptr_t CDECL
MSVCRT__get_osfhandle(int fd
)
1851 HANDLE hand
= msvcrt_fdtoh(fd
);
1852 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
1854 return (MSVCRT_intptr_t
)hand
;
1857 /*********************************************************************
1858 * _mktemp_s (MSVCRT.@)
1860 int CDECL
MSVCRT__mktemp_s(char *pattern
, MSVCRT_size_t size
)
1864 if(!MSVCRT_CHECK_PMT(pattern
!=NULL
))
1865 return MSVCRT_EINVAL
;
1867 for(len
=0; len
<size
; len
++)
1870 if(!MSVCRT_CHECK_PMT(len
!=size
&& len
>=6)) {
1873 return MSVCRT_EINVAL
;
1876 for(xno
=1; xno
<=6; xno
++)
1877 if(!MSVCRT_CHECK_PMT(pattern
[len
-xno
] == 'X'))
1878 return MSVCRT_EINVAL
;
1880 id
= GetCurrentProcessId();
1881 for(xno
=1; xno
<6; xno
++) {
1882 pattern
[len
-xno
] = id
%10 + '0';
1886 for(pattern
[len
-6]='a'; pattern
[len
-6]<='z'; pattern
[len
-6]++) {
1887 if(GetFileAttributesA(pattern
) == INVALID_FILE_ATTRIBUTES
)
1892 *MSVCRT__errno() = MSVCRT_EEXIST
;
1893 return MSVCRT_EEXIST
;
1896 /*********************************************************************
1897 * _mktemp (MSVCRT.@)
1899 char * CDECL
MSVCRT__mktemp(char *pattern
)
1902 char *retVal
= pattern
;
1910 numX
= (*pattern
++ == 'X')? numX
+ 1 : 0;
1914 id
= GetCurrentProcessId();
1918 int tempNum
= id
/ 10;
1919 *pattern
-- = id
- (tempNum
* 10) + '0';
1925 *pattern
= letter
++;
1926 if (GetFileAttributesA(retVal
) == INVALID_FILE_ATTRIBUTES
)
1928 } while(letter
<= 'z');
1932 /*********************************************************************
1933 * _wmktemp_s (MSVCRT.@)
1935 int CDECL
MSVCRT__wmktemp_s(MSVCRT_wchar_t
*pattern
, MSVCRT_size_t size
)
1939 if(!MSVCRT_CHECK_PMT(pattern
!=NULL
))
1940 return MSVCRT_EINVAL
;
1942 for(len
=0; len
<size
; len
++)
1945 if(!MSVCRT_CHECK_PMT(len
!=size
&& len
>=6)) {
1948 return MSVCRT_EINVAL
;
1951 for(xno
=1; xno
<=6; xno
++)
1952 if(!MSVCRT_CHECK_PMT(pattern
[len
-xno
] == 'X'))
1953 return MSVCRT_EINVAL
;
1955 id
= GetCurrentProcessId();
1956 for(xno
=1; xno
<6; xno
++) {
1957 pattern
[len
-xno
] = id
%10 + '0';
1961 for(pattern
[len
-6]='a'; pattern
[len
-6]<='z'; pattern
[len
-6]++) {
1962 if(GetFileAttributesW(pattern
) == INVALID_FILE_ATTRIBUTES
)
1967 *MSVCRT__errno() = MSVCRT_EEXIST
;
1968 return MSVCRT_EEXIST
;
1971 /*********************************************************************
1972 * _wmktemp (MSVCRT.@)
1974 MSVCRT_wchar_t
* CDECL
MSVCRT__wmktemp(MSVCRT_wchar_t
*pattern
)
1977 MSVCRT_wchar_t
*retVal
= pattern
;
1979 MSVCRT_wchar_t letter
= 'a';
1985 numX
= (*pattern
++ == 'X')? numX
+ 1 : 0;
1989 id
= GetCurrentProcessId();
1993 int tempNum
= id
/ 10;
1994 *pattern
-- = id
- (tempNum
* 10) + '0';
2000 if (GetFileAttributesW(retVal
) == INVALID_FILE_ATTRIBUTES
)
2002 *pattern
= letter
++;
2003 } while(letter
!= '|');
2007 static unsigned split_oflags(unsigned oflags
)
2010 unsigned unsupp
; /* until we support everything */
2012 if (oflags
& MSVCRT__O_APPEND
) wxflags
|= WX_APPEND
;
2013 if (oflags
& MSVCRT__O_BINARY
) {/* Nothing to do */}
2014 else if (oflags
& MSVCRT__O_TEXT
) wxflags
|= WX_TEXT
;
2015 else if (oflags
& MSVCRT__O_WTEXT
) wxflags
|= WX_TEXT
;
2016 else if (oflags
& MSVCRT__O_U16TEXT
) wxflags
|= WX_TEXT
;
2017 else if (oflags
& MSVCRT__O_U8TEXT
) wxflags
|= WX_TEXT
;
2018 else if (*__p__fmode() & MSVCRT__O_BINARY
) {/* Nothing to do */}
2019 else wxflags
|= WX_TEXT
; /* default to TEXT*/
2020 if (oflags
& MSVCRT__O_NOINHERIT
) wxflags
|= WX_DONTINHERIT
;
2022 if ((unsupp
= oflags
& ~(
2023 MSVCRT__O_BINARY
|MSVCRT__O_TEXT
|MSVCRT__O_APPEND
|
2024 MSVCRT__O_TRUNC
|MSVCRT__O_EXCL
|MSVCRT__O_CREAT
|
2025 MSVCRT__O_RDWR
|MSVCRT__O_WRONLY
|MSVCRT__O_TEMPORARY
|
2026 MSVCRT__O_NOINHERIT
|
2027 MSVCRT__O_SEQUENTIAL
|MSVCRT__O_RANDOM
|MSVCRT__O_SHORT_LIVED
|
2028 MSVCRT__O_WTEXT
|MSVCRT__O_U16TEXT
|MSVCRT__O_U8TEXT
2030 ERR(":unsupported oflags 0x%04x\n",unsupp
);
2035 /*********************************************************************
2038 int CDECL
MSVCRT__pipe(int *pfds
, unsigned int psize
, int textmode
)
2041 SECURITY_ATTRIBUTES sa
;
2042 HANDLE readHandle
, writeHandle
;
2046 *MSVCRT__errno() = MSVCRT_EINVAL
;
2050 sa
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
2051 sa
.bInheritHandle
= !(textmode
& MSVCRT__O_NOINHERIT
);
2052 sa
.lpSecurityDescriptor
= NULL
;
2053 if (CreatePipe(&readHandle
, &writeHandle
, &sa
, psize
))
2055 unsigned int wxflags
= split_oflags(textmode
);
2059 fd
= msvcrt_alloc_fd(readHandle
, wxflags
|WX_PIPE
);
2063 fd
= msvcrt_alloc_fd(writeHandle
, wxflags
|WX_PIPE
);
2071 MSVCRT__close(pfds
[0]);
2072 CloseHandle(writeHandle
);
2073 *MSVCRT__errno() = MSVCRT_EMFILE
;
2078 CloseHandle(readHandle
);
2079 CloseHandle(writeHandle
);
2080 *MSVCRT__errno() = MSVCRT_EMFILE
;
2085 msvcrt_set_errno(GetLastError());
2090 static int check_bom(HANDLE h
, int oflags
, BOOL seek
)
2092 char bom
[sizeof(utf8_bom
)];
2095 oflags
&= ~(MSVCRT__O_WTEXT
|MSVCRT__O_U16TEXT
|MSVCRT__O_U8TEXT
);
2097 if (!ReadFile(h
, bom
, sizeof(utf8_bom
), &r
, NULL
))
2100 if (r
==sizeof(utf8_bom
) && !memcmp(bom
, utf8_bom
, sizeof(utf8_bom
))) {
2101 oflags
|= MSVCRT__O_U8TEXT
;
2102 }else if (r
>=sizeof(utf16_bom
) && !memcmp(bom
, utf16_bom
, sizeof(utf16_bom
))) {
2104 SetFilePointer(h
, 2, NULL
, FILE_BEGIN
);
2105 oflags
|= MSVCRT__O_U16TEXT
;
2107 SetFilePointer(h
, 0, NULL
, FILE_BEGIN
);
2113 /*********************************************************************
2114 * _wsopen_s (MSVCRT.@)
2116 int CDECL
MSVCRT__wsopen_s( int *fd
, const MSVCRT_wchar_t
* path
, int oflags
, int shflags
, int pmode
)
2118 DWORD access
= 0, creation
= 0, attrib
;
2119 SECURITY_ATTRIBUTES sa
;
2120 DWORD sharing
, type
;
2124 TRACE("fd*: %p :file (%s) oflags: 0x%04x shflags: 0x%04x pmode: 0x%04x\n",
2125 fd
, debugstr_w(path
), oflags
, shflags
, pmode
);
2127 if (!MSVCRT_CHECK_PMT( fd
!= NULL
)) return MSVCRT_EINVAL
;
2130 wxflag
= split_oflags(oflags
);
2131 switch (oflags
& (MSVCRT__O_RDONLY
| MSVCRT__O_WRONLY
| MSVCRT__O_RDWR
))
2133 case MSVCRT__O_RDONLY
: access
|= GENERIC_READ
; break;
2134 case MSVCRT__O_WRONLY
: access
|= GENERIC_WRITE
; break;
2135 case MSVCRT__O_RDWR
: access
|= GENERIC_WRITE
| GENERIC_READ
; break;
2138 if (oflags
& MSVCRT__O_CREAT
)
2140 if(pmode
& ~(MSVCRT__S_IREAD
| MSVCRT__S_IWRITE
))
2141 FIXME(": pmode 0x%04x ignored\n", pmode
);
2143 if (oflags
& MSVCRT__O_EXCL
)
2144 creation
= CREATE_NEW
;
2145 else if (oflags
& MSVCRT__O_TRUNC
)
2146 creation
= CREATE_ALWAYS
;
2148 creation
= OPEN_ALWAYS
;
2150 else /* no MSVCRT__O_CREAT */
2152 if (oflags
& MSVCRT__O_TRUNC
)
2153 creation
= TRUNCATE_EXISTING
;
2155 creation
= OPEN_EXISTING
;
2160 case MSVCRT__SH_DENYRW
:
2163 case MSVCRT__SH_DENYWR
:
2164 sharing
= FILE_SHARE_READ
;
2166 case MSVCRT__SH_DENYRD
:
2167 sharing
= FILE_SHARE_WRITE
;
2169 case MSVCRT__SH_DENYNO
:
2170 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
2173 ERR( "Unhandled shflags 0x%x\n", shflags
);
2174 return MSVCRT_EINVAL
;
2177 if (!(pmode
& ~MSVCRT_umask
& MSVCRT__S_IWRITE
))
2178 attrib
= FILE_ATTRIBUTE_READONLY
;
2180 attrib
= FILE_ATTRIBUTE_NORMAL
;
2182 if (oflags
& MSVCRT__O_TEMPORARY
)
2184 attrib
|= FILE_FLAG_DELETE_ON_CLOSE
;
2186 sharing
|= FILE_SHARE_DELETE
;
2189 sa
.nLength
= sizeof( SECURITY_ATTRIBUTES
);
2190 sa
.lpSecurityDescriptor
= NULL
;
2191 sa
.bInheritHandle
= !(oflags
& MSVCRT__O_NOINHERIT
);
2193 if ((oflags
&(MSVCRT__O_WTEXT
|MSVCRT__O_U16TEXT
|MSVCRT__O_U8TEXT
))
2194 && (creation
==OPEN_ALWAYS
|| creation
==OPEN_EXISTING
)
2195 && !(access
&GENERIC_READ
))
2197 hand
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
2198 &sa
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0);
2199 if (hand
!= INVALID_HANDLE_VALUE
)
2201 oflags
= check_bom(hand
, oflags
, FALSE
);
2205 oflags
&= ~(MSVCRT__O_WTEXT
|MSVCRT__O_U16TEXT
|MSVCRT__O_U8TEXT
);
2208 hand
= CreateFileW(path
, access
, sharing
, &sa
, creation
, attrib
, 0);
2209 if (hand
== INVALID_HANDLE_VALUE
) {
2210 WARN(":failed-last error (%d)\n",GetLastError());
2211 msvcrt_set_errno(GetLastError());
2212 return *MSVCRT__errno();
2215 if (oflags
& (MSVCRT__O_WTEXT
|MSVCRT__O_U16TEXT
|MSVCRT__O_U8TEXT
))
2217 if ((access
& GENERIC_WRITE
) && (creation
==CREATE_NEW
2218 || creation
==CREATE_ALWAYS
|| creation
==TRUNCATE_EXISTING
2219 || (creation
==OPEN_ALWAYS
&& GetLastError()==ERROR_ALREADY_EXISTS
)))
2221 if (oflags
& MSVCRT__O_U8TEXT
)
2223 DWORD written
= 0, tmp
;
2225 while(written
!=sizeof(utf8_bom
) && WriteFile(hand
, (char*)utf8_bom
+written
,
2226 sizeof(utf8_bom
)-written
, &tmp
, NULL
))
2228 if (written
!= sizeof(utf8_bom
)) {
2229 WARN("error writing BOM\n");
2231 msvcrt_set_errno(GetLastError());
2232 return *MSVCRT__errno();
2237 DWORD written
= 0, tmp
;
2239 while(written
!=sizeof(utf16_bom
) && WriteFile(hand
, (char*)utf16_bom
+written
,
2240 sizeof(utf16_bom
)-written
, &tmp
, NULL
))
2242 if (written
!= sizeof(utf16_bom
))
2244 WARN("error writing BOM\n");
2246 msvcrt_set_errno(GetLastError());
2247 return *MSVCRT__errno();
2251 else if (access
& GENERIC_READ
)
2252 oflags
= check_bom(hand
, oflags
, TRUE
);
2255 type
= GetFileType(hand
);
2256 if (type
== FILE_TYPE_CHAR
)
2258 else if (type
== FILE_TYPE_PIPE
)
2261 *fd
= msvcrt_alloc_fd(hand
, wxflag
);
2263 return *MSVCRT__errno();
2265 if (oflags
& MSVCRT__O_WTEXT
)
2266 get_ioinfo_nolock(*fd
)->exflag
|= EF_UTF16
|EF_UNK_UNICODE
;
2267 else if (oflags
& MSVCRT__O_U16TEXT
)
2268 get_ioinfo_nolock(*fd
)->exflag
|= EF_UTF16
;
2269 else if (oflags
& MSVCRT__O_U8TEXT
)
2270 get_ioinfo_nolock(*fd
)->exflag
|= EF_UTF8
;
2272 TRACE(":fd (%d) handle (%p)\n", *fd
, hand
);
2276 /*********************************************************************
2277 * _wsopen (MSVCRT.@)
2279 int CDECL
MSVCRT__wsopen( const MSVCRT_wchar_t
*path
, int oflags
, int shflags
, ... )
2284 if (oflags
& MSVCRT__O_CREAT
)
2288 __ms_va_start(ap
, shflags
);
2289 pmode
= va_arg(ap
, int);
2295 MSVCRT__wsopen_s(&fd
, path
, oflags
, shflags
, pmode
);
2299 /*********************************************************************
2300 * _sopen_s (MSVCRT.@)
2302 int CDECL
MSVCRT__sopen_s( int *fd
, const char *path
, int oflags
, int shflags
, int pmode
)
2304 MSVCRT_wchar_t
*pathW
;
2307 if (!MSVCRT_CHECK_PMT(fd
!= NULL
))
2308 return MSVCRT_EINVAL
;
2310 if(!MSVCRT_CHECK_PMT(path
&& (pathW
= msvcrt_wstrdupa(path
))))
2311 return MSVCRT_EINVAL
;
2313 ret
= MSVCRT__wsopen_s(fd
, pathW
, oflags
, shflags
, pmode
);
2318 /*********************************************************************
2321 int CDECL
MSVCRT__sopen( const char *path
, int oflags
, int shflags
, ... )
2326 if (oflags
& MSVCRT__O_CREAT
)
2330 __ms_va_start(ap
, shflags
);
2331 pmode
= va_arg(ap
, int);
2337 MSVCRT__sopen_s(&fd
, path
, oflags
, shflags
, pmode
);
2341 /*********************************************************************
2344 int CDECL
MSVCRT__open( const char *path
, int flags
, ... )
2348 if (flags
& MSVCRT__O_CREAT
)
2351 __ms_va_start(ap
, flags
);
2352 pmode
= va_arg(ap
, int);
2354 return MSVCRT__sopen( path
, flags
, MSVCRT__SH_DENYNO
, pmode
);
2357 return MSVCRT__sopen( path
, flags
, MSVCRT__SH_DENYNO
);
2360 /*********************************************************************
2363 int CDECL
MSVCRT__wopen(const MSVCRT_wchar_t
*path
,int flags
,...)
2367 if (flags
& MSVCRT__O_CREAT
)
2370 __ms_va_start(ap
, flags
);
2371 pmode
= va_arg(ap
, int);
2373 return MSVCRT__wsopen( path
, flags
, MSVCRT__SH_DENYNO
, pmode
);
2376 return MSVCRT__wsopen( path
, flags
, MSVCRT__SH_DENYNO
);
2379 /*********************************************************************
2382 int CDECL
MSVCRT__creat(const char *path
, int flags
)
2384 int usedFlags
= (flags
& MSVCRT__O_TEXT
)| MSVCRT__O_CREAT
| MSVCRT__O_WRONLY
| MSVCRT__O_TRUNC
;
2385 return MSVCRT__open(path
, usedFlags
);
2388 /*********************************************************************
2389 * _wcreat (MSVCRT.@)
2391 int CDECL
MSVCRT__wcreat(const MSVCRT_wchar_t
*path
, int flags
)
2393 int usedFlags
= (flags
& MSVCRT__O_TEXT
)| MSVCRT__O_CREAT
| MSVCRT__O_WRONLY
| MSVCRT__O_TRUNC
;
2394 return MSVCRT__wopen(path
, usedFlags
);
2397 /*********************************************************************
2398 * _open_osfhandle (MSVCRT.@)
2400 int CDECL
MSVCRT__open_osfhandle(MSVCRT_intptr_t handle
, int oflags
)
2405 /* MSVCRT__O_RDONLY (0) always matches, so set the read flag
2406 * MFC's CStdioFile clears O_RDONLY (0)! if it wants to write to the
2407 * file, so set the write flag. It also only sets MSVCRT__O_TEXT if it wants
2408 * text - it never sets MSVCRT__O_BINARY.
2410 /* don't let split_oflags() decide the mode if no mode is passed */
2411 if (!(oflags
& (MSVCRT__O_BINARY
| MSVCRT__O_TEXT
)))
2412 oflags
|= MSVCRT__O_BINARY
;
2414 flags
= GetFileType((HANDLE
)handle
);
2415 if (flags
==FILE_TYPE_UNKNOWN
&& GetLastError()!=NO_ERROR
)
2417 msvcrt_set_errno(GetLastError());
2421 if (flags
== FILE_TYPE_CHAR
)
2423 else if (flags
== FILE_TYPE_PIPE
)
2427 flags
|= split_oflags(oflags
);
2429 fd
= msvcrt_alloc_fd((HANDLE
)handle
, flags
);
2430 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n", handle
, fd
, flags
);
2434 /*********************************************************************
2437 int CDECL
MSVCRT__rmtmp(void)
2439 int num_removed
= 0, i
;
2443 for (i
= 3; i
< MSVCRT_stream_idx
; i
++) {
2444 file
= msvcrt_get_file(i
);
2446 if (file
->_tmpfname
)
2448 MSVCRT_fclose(file
);
2455 TRACE(":removed (%d) temp files\n",num_removed
);
2459 static inline int get_utf8_char_len(char ch
)
2461 if((ch
&0xf8) == 0xf0)
2463 else if((ch
&0xf0) == 0xe0)
2465 else if((ch
&0xe0) == 0xc0)
2470 /*********************************************************************
2471 * (internal) read_utf8
2473 static int read_utf8(ioinfo
*fdinfo
, MSVCRT_wchar_t
*buf
, unsigned int count
)
2475 HANDLE hand
= fdinfo
->handle
;
2476 char min_buf
[4], *readbuf
, lookahead
;
2477 DWORD readbuf_size
, pos
=0, num_read
=1, char_len
, i
, j
;
2479 /* make the buffer big enough to hold at least one character */
2480 /* read bytes have to fit to output and lookahead buffers */
2482 readbuf_size
= count
< 4 ? 4 : count
;
2483 if(readbuf_size
<=4 || !(readbuf
= MSVCRT_malloc(readbuf_size
))) {
2488 if(fdinfo
->lookahead
[0] != '\n') {
2489 readbuf
[pos
++] = fdinfo
->lookahead
[0];
2490 fdinfo
->lookahead
[0] = '\n';
2492 if(fdinfo
->lookahead
[1] != '\n') {
2493 readbuf
[pos
++] = fdinfo
->lookahead
[1];
2494 fdinfo
->lookahead
[1] = '\n';
2496 if(fdinfo
->lookahead
[2] != '\n') {
2497 readbuf
[pos
++] = fdinfo
->lookahead
[2];
2498 fdinfo
->lookahead
[2] = '\n';
2503 /* NOTE: this case is broken in native dll, reading
2504 * sometimes fails when small buffer is passed
2507 if(!pos
&& !ReadFile(hand
, readbuf
, 1, &num_read
, NULL
)) {
2508 if (GetLastError() == ERROR_BROKEN_PIPE
) {
2509 fdinfo
->wxflag
|= WX_ATEOF
;
2512 msvcrt_set_errno(GetLastError());
2515 }else if(!num_read
) {
2516 fdinfo
->wxflag
|= WX_ATEOF
;
2522 char_len
= get_utf8_char_len(readbuf
[0]);
2524 if(ReadFile(hand
, readbuf
+pos
, char_len
-pos
, &num_read
, NULL
))
2528 if(readbuf
[0] == '\n')
2529 fdinfo
->wxflag
|= WX_READNL
;
2531 fdinfo
->wxflag
&= ~WX_READNL
;
2533 if(readbuf
[0] == 0x1a) {
2534 fdinfo
->wxflag
|= WX_ATEOF
;
2538 if(readbuf
[0] == '\r') {
2539 if(!ReadFile(hand
, &lookahead
, 1, &num_read
, NULL
) || num_read
!=1)
2541 else if(lookahead
== '\n')
2545 if(fdinfo
->wxflag
& (WX_PIPE
| WX_TTY
))
2546 fdinfo
->lookahead
[0] = lookahead
;
2548 SetFilePointer(fdinfo
->handle
, -1, NULL
, FILE_CURRENT
);
2553 if(!(num_read
= MultiByteToWideChar(CP_UTF8
, 0, readbuf
, pos
, buf
, count
))) {
2554 msvcrt_set_errno(GetLastError());
2561 if(!ReadFile(hand
, readbuf
+pos
, readbuf_size
-pos
, &num_read
, NULL
)) {
2564 }else if(GetLastError() == ERROR_BROKEN_PIPE
) {
2565 fdinfo
->wxflag
|= WX_ATEOF
;
2566 if (readbuf
!= min_buf
) MSVCRT_free(readbuf
);
2569 msvcrt_set_errno(GetLastError());
2570 if (readbuf
!= min_buf
) MSVCRT_free(readbuf
);
2573 }else if(!pos
&& !num_read
) {
2574 fdinfo
->wxflag
|= WX_ATEOF
;
2575 if (readbuf
!= min_buf
) MSVCRT_free(readbuf
);
2580 if(readbuf
[0] == '\n')
2581 fdinfo
->wxflag
|= WX_READNL
;
2583 fdinfo
->wxflag
&= ~WX_READNL
;
2585 /* Find first byte of last character (may be incomplete) */
2586 for(i
=pos
-1; i
>0 && i
>pos
-4; i
--)
2587 if((readbuf
[i
]&0xc0) != 0x80)
2589 char_len
= get_utf8_char_len(readbuf
[i
]);
2590 if(char_len
+i
<= pos
)
2593 if(fdinfo
->wxflag
& (WX_PIPE
| WX_TTY
)) {
2595 fdinfo
->lookahead
[0] = readbuf
[i
];
2597 fdinfo
->lookahead
[1] = readbuf
[i
+1];
2599 fdinfo
->lookahead
[2] = readbuf
[i
+2];
2601 SetFilePointer(fdinfo
->handle
, i
-pos
, NULL
, FILE_CURRENT
);
2605 for(i
=0, j
=0; i
<pos
; i
++) {
2606 if(readbuf
[i
] == 0x1a) {
2607 fdinfo
->wxflag
|= WX_ATEOF
;
2611 /* strip '\r' if followed by '\n' */
2612 if(readbuf
[i
] == '\r' && i
+1==pos
) {
2613 if(fdinfo
->lookahead
[0] != '\n' || !ReadFile(hand
, &lookahead
, 1, &num_read
, NULL
) || !num_read
) {
2614 readbuf
[j
++] = '\r';
2615 }else if(lookahead
== '\n' && j
==0) {
2616 readbuf
[j
++] = '\n';
2618 if(lookahead
!= '\n')
2619 readbuf
[j
++] = '\r';
2621 if(fdinfo
->wxflag
& (WX_PIPE
| WX_TTY
))
2622 fdinfo
->lookahead
[0] = lookahead
;
2624 SetFilePointer(fdinfo
->handle
, -1, NULL
, FILE_CURRENT
);
2626 }else if(readbuf
[i
]!='\r' || readbuf
[i
+1]!='\n') {
2627 readbuf
[j
++] = readbuf
[i
];
2632 if(!(num_read
= MultiByteToWideChar(CP_UTF8
, 0, readbuf
, pos
, buf
, count
))) {
2633 msvcrt_set_errno(GetLastError());
2634 if (readbuf
!= min_buf
) MSVCRT_free(readbuf
);
2638 if (readbuf
!= min_buf
) MSVCRT_free(readbuf
);
2642 /*********************************************************************
2645 * When reading \r as last character in text mode, read() positions
2646 * the file pointer on the \r character while getc() goes on to
2649 static int read_i(int fd
, ioinfo
*fdinfo
, void *buf
, unsigned int count
)
2651 DWORD num_read
, utf16
;
2652 char *bufstart
= buf
;
2657 if (fdinfo
->wxflag
& WX_ATEOF
) {
2658 TRACE("already at EOF, returning 0\n");
2661 /* Don't trace small reads, it gets *very* annoying */
2663 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n", fd
, fdinfo
->handle
, buf
, count
);
2664 if (fdinfo
->handle
== INVALID_HANDLE_VALUE
)
2666 *MSVCRT__errno() = MSVCRT_EBADF
;
2670 utf16
= (fdinfo
->exflag
& EF_UTF16
) != 0;
2671 if (((fdinfo
->exflag
&EF_UTF8
) || utf16
) && count
&1)
2673 *MSVCRT__errno() = MSVCRT_EINVAL
;
2677 if((fdinfo
->wxflag
&WX_TEXT
) && (fdinfo
->exflag
&EF_UTF8
))
2678 return read_utf8(fdinfo
, buf
, count
);
2680 if (fdinfo
->lookahead
[0]!='\n' || ReadFile(fdinfo
->handle
, bufstart
, count
, &num_read
, NULL
))
2682 if (fdinfo
->lookahead
[0] != '\n')
2684 bufstart
[0] = fdinfo
->lookahead
[0];
2685 fdinfo
->lookahead
[0] = '\n';
2689 bufstart
[1] = fdinfo
->lookahead
[1];
2690 fdinfo
->lookahead
[1] = '\n';
2693 if(count
>1+utf16
&& ReadFile(fdinfo
->handle
, bufstart
+1+utf16
, count
-1-utf16
, &num_read
, NULL
))
2694 num_read
+= 1+utf16
;
2699 if(utf16
&& (num_read
&1))
2701 /* msvcr90 uses uninitialized value from the buffer in this case */
2702 /* msvcrt ignores additional data */
2703 ERR("got odd number of bytes in UTF16 mode\n");
2707 if (count
!= 0 && num_read
== 0)
2709 fdinfo
->wxflag
|= WX_ATEOF
;
2710 TRACE(":EOF %s\n",debugstr_an(buf
,num_read
));
2712 else if (fdinfo
->wxflag
& WX_TEXT
)
2716 if (bufstart
[0]=='\n' && (!utf16
|| bufstart
[1]==0))
2717 fdinfo
->wxflag
|= WX_READNL
;
2719 fdinfo
->wxflag
&= ~WX_READNL
;
2721 for (i
=0, j
=0; i
<num_read
; i
+=1+utf16
)
2723 /* in text mode, a ctrl-z signals EOF */
2724 if (bufstart
[i
]==0x1a && (!utf16
|| bufstart
[i
+1]==0))
2726 fdinfo
->wxflag
|= WX_ATEOF
;
2727 TRACE(":^Z EOF %s\n",debugstr_an(buf
,num_read
));
2731 /* in text mode, strip \r if followed by \n */
2732 if (bufstart
[i
]=='\r' && (!utf16
|| bufstart
[i
+1]==0) && i
+1+utf16
==num_read
)
2737 lookahead
[1] = '\n';
2738 if (ReadFile(fdinfo
->handle
, lookahead
, 1+utf16
, &len
, NULL
) && len
)
2740 if(lookahead
[0]=='\n' && (!utf16
|| lookahead
[1]==0) && j
==0)
2742 bufstart
[j
++] = '\n';
2743 if(utf16
) bufstart
[j
++] = 0;
2747 if(lookahead
[0]!='\n' || (utf16
&& lookahead
[1]!=0))
2749 bufstart
[j
++] = '\r';
2750 if(utf16
) bufstart
[j
++] = 0;
2753 if (fdinfo
->wxflag
& (WX_PIPE
| WX_TTY
))
2755 if (lookahead
[0]=='\n' && (!utf16
|| !lookahead
[1]))
2757 bufstart
[j
++] = '\n';
2758 if (utf16
) bufstart
[j
++] = 0;
2762 fdinfo
->lookahead
[0] = lookahead
[0];
2763 fdinfo
->lookahead
[1] = lookahead
[1];
2767 SetFilePointer(fdinfo
->handle
, -1-utf16
, NULL
, FILE_CURRENT
);
2772 bufstart
[j
++] = '\r';
2773 if(utf16
) bufstart
[j
++] = 0;
2776 else if((bufstart
[i
]!='\r' || (utf16
&& bufstart
[i
+1]!=0))
2777 || (bufstart
[i
+1+utf16
]!='\n' || (utf16
&& bufstart
[i
+3]!=0)))
2779 bufstart
[j
++] = bufstart
[i
];
2780 if(utf16
) bufstart
[j
++] = bufstart
[i
+1];
2788 if (GetLastError() == ERROR_BROKEN_PIPE
)
2790 TRACE(":end-of-pipe\n");
2791 fdinfo
->wxflag
|= WX_ATEOF
;
2796 TRACE(":failed-last error (%d)\n",GetLastError());
2802 TRACE("(%u), %s\n",num_read
,debugstr_an(buf
, num_read
));
2806 /*********************************************************************
2809 int CDECL
MSVCRT__read(int fd
, void *buf
, unsigned int count
)
2811 ioinfo
*info
= get_ioinfo(fd
);
2812 int num_read
= read_i(fd
, info
, buf
, count
);
2813 release_ioinfo(info
);
2817 /*********************************************************************
2818 * _setmode (MSVCRT.@)
2820 int CDECL
MSVCRT__setmode(int fd
,int mode
)
2822 int ret
= get_ioinfo_nolock(fd
)->wxflag
& WX_TEXT
? MSVCRT__O_TEXT
: MSVCRT__O_BINARY
;
2823 if(ret
==MSVCRT__O_TEXT
&& (get_ioinfo_nolock(fd
)->exflag
& (EF_UTF8
|EF_UTF16
)))
2824 ret
= MSVCRT__O_WTEXT
;
2826 if(mode
!=MSVCRT__O_TEXT
&& mode
!=MSVCRT__O_BINARY
&& mode
!=MSVCRT__O_WTEXT
2827 && mode
!=MSVCRT__O_U16TEXT
&& mode
!=MSVCRT__O_U8TEXT
) {
2828 *MSVCRT__errno() = MSVCRT_EINVAL
;
2832 if(mode
== MSVCRT__O_BINARY
) {
2833 get_ioinfo_nolock(fd
)->wxflag
&= ~WX_TEXT
;
2834 get_ioinfo_nolock(fd
)->exflag
&= ~(EF_UTF8
|EF_UTF16
);
2838 get_ioinfo_nolock(fd
)->wxflag
|= WX_TEXT
;
2839 if(mode
== MSVCRT__O_TEXT
)
2840 get_ioinfo_nolock(fd
)->exflag
&= ~(EF_UTF8
|EF_UTF16
);
2841 else if(mode
== MSVCRT__O_U8TEXT
)
2842 get_ioinfo_nolock(fd
)->exflag
= (get_ioinfo_nolock(fd
)->exflag
& ~EF_UTF16
) | EF_UTF8
;
2844 get_ioinfo_nolock(fd
)->exflag
= (get_ioinfo_nolock(fd
)->exflag
& ~EF_UTF8
) | EF_UTF16
;
2849 /*********************************************************************
2850 * _stat64 (MSVCRT.@)
2852 int CDECL
MSVCRT_stat64(const char* path
, struct MSVCRT__stat64
* buf
)
2855 WIN32_FILE_ATTRIBUTE_DATA hfi
;
2856 unsigned short mode
= ALL_S_IREAD
;
2859 TRACE(":file (%s) buf(%p)\n",path
,buf
);
2861 plen
= strlen(path
);
2862 while (plen
&& path
[plen
-1]==' ')
2865 if (plen
&& (plen
<2 || path
[plen
-2]!=':') &&
2866 (path
[plen
-1]==':' || path
[plen
-1]=='\\' || path
[plen
-1]=='/'))
2868 *MSVCRT__errno() = MSVCRT_ENOENT
;
2872 if (!GetFileAttributesExA(path
, GetFileExInfoStandard
, &hfi
))
2874 TRACE("failed (%d)\n",GetLastError());
2875 *MSVCRT__errno() = MSVCRT_ENOENT
;
2879 memset(buf
,0,sizeof(struct MSVCRT__stat64
));
2881 /* FIXME: rdev isn't drive num, despite what the docs say-what is it?
2882 Bon 011120: This FIXME seems incorrect
2883 Also a letter as first char isn't enough to be classified
2886 if (isalpha(*path
)&& (*(path
+1)==':'))
2887 buf
->st_dev
= buf
->st_rdev
= toupper(*path
) - 'A'; /* drive num */
2889 buf
->st_dev
= buf
->st_rdev
= MSVCRT__getdrive() - 1;
2891 /* Dir, or regular file? */
2892 if (hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2893 mode
|= (MSVCRT__S_IFDIR
| ALL_S_IEXEC
);
2896 mode
|= MSVCRT__S_IFREG
;
2898 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
2900 unsigned int ext
= tolower(path
[plen
-1]) | (tolower(path
[plen
-2]) << 8) |
2901 (tolower(path
[plen
-3]) << 16);
2902 if (ext
== EXE
|| ext
== BAT
|| ext
== CMD
|| ext
== COM
)
2903 mode
|= ALL_S_IEXEC
;
2907 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
2908 mode
|= ALL_S_IWRITE
;
2910 buf
->st_mode
= mode
;
2912 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
2913 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
2915 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
2916 buf
->st_mtime
= buf
->st_ctime
= dw
;
2917 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf
->st_mode
,buf
->st_nlink
,
2918 (int)(buf
->st_size
>> 32),(int)buf
->st_size
,
2919 (int)buf
->st_atime
,(int)buf
->st_mtime
,(int)buf
->st_ctime
);
2923 /*********************************************************************
2924 * _stati64 (MSVCRT.@)
2926 int CDECL
MSVCRT_stati64(const char* path
, struct MSVCRT__stati64
* buf
)
2929 struct MSVCRT__stat64 buf64
;
2931 ret
= MSVCRT_stat64(path
, &buf64
);
2933 msvcrt_stat64_to_stati64(&buf64
, buf
);
2937 /*********************************************************************
2940 int CDECL
MSVCRT_stat(const char* path
, struct MSVCRT__stat
* buf
)
2943 struct MSVCRT__stat64 buf64
;
2945 ret
= MSVCRT_stat64( path
, &buf64
);
2947 msvcrt_stat64_to_stat(&buf64
, buf
);
2951 /*********************************************************************
2952 * _stat32 (MSVCR100.@)
2954 int CDECL
MSVCRT__stat32(const char *path
, struct MSVCRT__stat32
*buf
)
2957 struct MSVCRT__stat64 buf64
;
2959 ret
= MSVCRT_stat64(path
, &buf64
);
2961 msvcrt_stat64_to_stat32(&buf64
, buf
);
2965 /*********************************************************************
2966 * _stat32i64 (MSVCR100.@)
2968 int CDECL
MSVCRT__stat32i64(const char *path
, struct MSVCRT__stat32i64
*buf
)
2971 struct MSVCRT__stat64 buf64
;
2973 ret
= MSVCRT_stat64(path
, &buf64
);
2975 msvcrt_stat64_to_stat32i64(&buf64
, buf
);
2979 /*********************************************************************
2980 * _stat64i32 (MSVCR100.@)
2982 int CDECL
MSVCRT__stat64i32(const char* path
, struct MSVCRT__stat64i32
*buf
)
2985 struct MSVCRT__stat64 buf64
;
2987 ret
= MSVCRT_stat64(path
, &buf64
);
2989 msvcrt_stat64_to_stat64i32(&buf64
, buf
);
2993 /*********************************************************************
2994 * _wstat64 (MSVCRT.@)
2996 int CDECL
MSVCRT__wstat64(const MSVCRT_wchar_t
* path
, struct MSVCRT__stat64
* buf
)
2999 WIN32_FILE_ATTRIBUTE_DATA hfi
;
3000 unsigned short mode
= ALL_S_IREAD
;
3003 TRACE(":file (%s) buf(%p)\n",debugstr_w(path
),buf
);
3005 plen
= strlenW(path
);
3006 while (plen
&& path
[plen
-1]==' ')
3009 if(plen
&& (plen
<2 || path
[plen
-2]!=':') &&
3010 (path
[plen
-1]==':' || path
[plen
-1]=='\\' || path
[plen
-1]=='/'))
3012 *MSVCRT__errno() = MSVCRT_ENOENT
;
3016 if (!GetFileAttributesExW(path
, GetFileExInfoStandard
, &hfi
))
3018 TRACE("failed (%d)\n",GetLastError());
3019 *MSVCRT__errno() = MSVCRT_ENOENT
;
3023 memset(buf
,0,sizeof(struct MSVCRT__stat64
));
3025 /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
3026 if (MSVCRT_iswalpha(*path
))
3027 buf
->st_dev
= buf
->st_rdev
= toupperW(*path
- 'A'); /* drive num */
3029 buf
->st_dev
= buf
->st_rdev
= MSVCRT__getdrive() - 1;
3031 /* Dir, or regular file? */
3032 if (hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
3033 mode
|= (MSVCRT__S_IFDIR
| ALL_S_IEXEC
);
3036 mode
|= MSVCRT__S_IFREG
;
3038 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
3040 ULONGLONG ext
= tolowerW(path
[plen
-1]) | (tolowerW(path
[plen
-2]) << 16) |
3041 ((ULONGLONG
)tolowerW(path
[plen
-3]) << 32);
3042 if (ext
== WCEXE
|| ext
== WCBAT
|| ext
== WCCMD
|| ext
== WCCOM
)
3043 mode
|= ALL_S_IEXEC
;
3047 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
3048 mode
|= ALL_S_IWRITE
;
3050 buf
->st_mode
= mode
;
3052 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
3053 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
3055 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
3056 buf
->st_mtime
= buf
->st_ctime
= dw
;
3057 TRACE("%d %d 0x%08x%08x %d %d %d\n", buf
->st_mode
,buf
->st_nlink
,
3058 (int)(buf
->st_size
>> 32),(int)buf
->st_size
,
3059 (int)buf
->st_atime
,(int)buf
->st_mtime
,(int)buf
->st_ctime
);
3063 /*********************************************************************
3064 * _wstati64 (MSVCRT.@)
3066 int CDECL
MSVCRT__wstati64(const MSVCRT_wchar_t
* path
, struct MSVCRT__stati64
* buf
)
3069 struct MSVCRT__stat64 buf64
;
3071 ret
= MSVCRT__wstat64(path
, &buf64
);
3073 msvcrt_stat64_to_stati64(&buf64
, buf
);
3077 /*********************************************************************
3080 int CDECL
MSVCRT__wstat(const MSVCRT_wchar_t
* path
, struct MSVCRT__stat
* buf
)
3083 struct MSVCRT__stat64 buf64
;
3085 ret
= MSVCRT__wstat64( path
, &buf64
);
3086 if (!ret
) msvcrt_stat64_to_stat(&buf64
, buf
);
3090 /*********************************************************************
3091 * _wstat32 (MSVCR100.@)
3093 int CDECL
MSVCRT__wstat32(const MSVCRT_wchar_t
*path
, struct MSVCRT__stat32
*buf
)
3096 struct MSVCRT__stat64 buf64
;
3098 ret
= MSVCRT__wstat64(path
, &buf64
);
3100 msvcrt_stat64_to_stat32(&buf64
, buf
);
3104 /*********************************************************************
3105 * _wstat32i64 (MSVCR100.@)
3107 int CDECL
MSVCRT__wstat32i64(const MSVCRT_wchar_t
*path
, struct MSVCRT__stat32i64
*buf
)
3110 struct MSVCRT__stat64 buf64
;
3112 ret
= MSVCRT__wstat64(path
, &buf64
);
3114 msvcrt_stat64_to_stat32i64(&buf64
, buf
);
3118 /*********************************************************************
3119 * _wstat64i32 (MSVCR100.@)
3121 int CDECL
MSVCRT__wstat64i32(const MSVCRT_wchar_t
*path
, struct MSVCRT__stat64i32
*buf
)
3124 struct MSVCRT__stat64 buf64
;
3126 ret
= MSVCRT__wstat64(path
, &buf64
);
3128 msvcrt_stat64_to_stat64i32(&buf64
, buf
);
3132 /*********************************************************************
3135 MSVCRT_long CDECL
MSVCRT__tell(int fd
)
3137 return MSVCRT__lseek(fd
, 0, SEEK_CUR
);
3140 /*********************************************************************
3141 * _telli64 (MSVCRT.@)
3143 __int64 CDECL
_telli64(int fd
)
3145 return MSVCRT__lseeki64(fd
, 0, SEEK_CUR
);
3148 /*********************************************************************
3149 * _tempnam (MSVCRT.@)
3151 char * CDECL
MSVCRT__tempnam(const char *dir
, const char *prefix
)
3153 char tmpbuf
[MAX_PATH
];
3154 const char *tmp_dir
= MSVCRT_getenv("TMP");
3156 if (tmp_dir
) dir
= tmp_dir
;
3158 TRACE("dir (%s) prefix (%s)\n",dir
,prefix
);
3159 if (GetTempFileNameA(dir
,prefix
,0,tmpbuf
))
3161 TRACE("got name (%s)\n",tmpbuf
);
3162 DeleteFileA(tmpbuf
);
3163 return MSVCRT__strdup(tmpbuf
);
3165 TRACE("failed (%d)\n",GetLastError());
3169 /*********************************************************************
3170 * _wtempnam (MSVCRT.@)
3172 MSVCRT_wchar_t
* CDECL
MSVCRT__wtempnam(const MSVCRT_wchar_t
*dir
, const MSVCRT_wchar_t
*prefix
)
3174 static const MSVCRT_wchar_t tmpW
[] = {'T','M','P',0};
3175 MSVCRT_wchar_t tmpbuf
[MAX_PATH
];
3176 const MSVCRT_wchar_t
*tmp_dir
= MSVCRT__wgetenv(tmpW
);
3178 if (tmp_dir
) dir
= tmp_dir
;
3180 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir
),debugstr_w(prefix
));
3181 if (GetTempFileNameW(dir
,prefix
,0,tmpbuf
))
3183 TRACE("got name (%s)\n",debugstr_w(tmpbuf
));
3184 DeleteFileW(tmpbuf
);
3185 return MSVCRT__wcsdup(tmpbuf
);
3187 TRACE("failed (%d)\n",GetLastError());
3191 /*********************************************************************
3194 int CDECL
MSVCRT__umask(int umask
)
3196 int old_umask
= MSVCRT_umask
;
3197 TRACE("(%d)\n",umask
);
3198 MSVCRT_umask
= umask
;
3202 /*********************************************************************
3203 * _utime64 (MSVCRT.@)
3205 int CDECL
_utime64(const char* path
, struct MSVCRT___utimbuf64
*t
)
3207 int fd
= MSVCRT__open(path
, MSVCRT__O_WRONLY
| MSVCRT__O_BINARY
);
3211 int retVal
= _futime64(fd
, t
);
3218 /*********************************************************************
3219 * _utime32 (MSVCRT.@)
3221 int CDECL
_utime32(const char* path
, struct MSVCRT___utimbuf32
*t
)
3225 struct MSVCRT___utimbuf64 t64
;
3226 t64
.actime
= t
->actime
;
3227 t64
.modtime
= t
->modtime
;
3228 return _utime64( path
, &t64
);
3231 return _utime64( path
, NULL
);
3234 /*********************************************************************
3238 int CDECL
_utime(const char* path
, struct MSVCRT___utimbuf64
*t
)
3240 return _utime64( path
, t
);
3243 int CDECL
_utime(const char* path
, struct MSVCRT___utimbuf32
*t
)
3245 return _utime32( path
, t
);
3249 /*********************************************************************
3250 * _wutime64 (MSVCRT.@)
3252 int CDECL
_wutime64(const MSVCRT_wchar_t
* path
, struct MSVCRT___utimbuf64
*t
)
3254 int fd
= MSVCRT__wopen(path
, MSVCRT__O_WRONLY
| MSVCRT__O_BINARY
);
3258 int retVal
= _futime64(fd
, t
);
3265 /*********************************************************************
3266 * _wutime32 (MSVCRT.@)
3268 int CDECL
_wutime32(const MSVCRT_wchar_t
* path
, struct MSVCRT___utimbuf32
*t
)
3272 struct MSVCRT___utimbuf64 t64
;
3273 t64
.actime
= t
->actime
;
3274 t64
.modtime
= t
->modtime
;
3275 return _wutime64( path
, &t64
);
3278 return _wutime64( path
, NULL
);
3281 /*********************************************************************
3282 * _wutime (MSVCRT.@)
3285 int CDECL
_wutime(const MSVCRT_wchar_t
* path
, struct MSVCRT___utimbuf64
*t
)
3287 return _wutime64( path
, t
);
3290 int CDECL
_wutime(const MSVCRT_wchar_t
* path
, struct MSVCRT___utimbuf32
*t
)
3292 return _wutime32( path
, t
);
3296 /*********************************************************************
3299 int CDECL
MSVCRT__write(int fd
, const void* buf
, unsigned int count
)
3302 ioinfo
*info
= get_ioinfo_nolock(fd
);
3303 HANDLE hand
= info
->handle
;
3305 /* Don't trace small writes, it gets *very* annoying */
3308 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd
,hand
,buf
,count
);
3310 if (hand
== INVALID_HANDLE_VALUE
)
3312 *MSVCRT__errno() = MSVCRT_EBADF
;
3316 if (((info
->exflag
&EF_UTF8
) || (info
->exflag
&EF_UTF16
)) && count
&1)
3318 *MSVCRT__errno() = MSVCRT_EINVAL
;
3322 /* If appending, go to EOF */
3323 if (info
->wxflag
& WX_APPEND
)
3324 MSVCRT__lseek(fd
, 0, FILE_END
);
3326 if (!(info
->wxflag
& WX_TEXT
))
3328 if (WriteFile(hand
, buf
, count
, &num_written
, NULL
)
3329 && (num_written
== count
))
3331 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd
,
3332 hand
, GetLastError());
3333 *MSVCRT__errno() = MSVCRT_ENOSPC
;
3337 unsigned int i
, j
, nr_lf
, size
;
3340 const char *s
= buf
, *buf_start
= buf
;
3342 if (!(info
->exflag
& (EF_UTF8
|EF_UTF16
)))
3344 /* find number of \n */
3345 for (nr_lf
=0, i
=0; i
<count
; i
++)
3351 if ((q
= p
= MSVCRT_malloc(size
)))
3353 for (s
= buf
, i
= 0, j
= 0; i
< count
; i
++)
3362 FIXME("Malloc failed\n");
3374 else if (info
->exflag
& EF_UTF16
)
3376 for (nr_lf
=0, i
=0; i
<count
; i
+=2)
3377 if (s
[i
]=='\n' && s
[i
+1]==0)
3382 if ((q
= p
= MSVCRT_malloc(size
)))
3384 for (s
=buf
, i
=0, j
=0; i
<count
; i
++)
3386 if (s
[i
]=='\n' && s
[i
+1]==0)
3397 FIXME("Malloc failed\n");
3413 for(nr_lf
=0, i
=0; i
<count
; i
+=2)
3414 if (s
[i
]=='\n' && s
[i
+1]==0)
3417 conv_len
= WideCharToMultiByte(CP_UTF8
, 0, (WCHAR
*)buf
, count
/2, NULL
, 0, NULL
, NULL
);
3419 msvcrt_set_errno(GetLastError());
3424 size
= conv_len
+nr_lf
;
3425 if((p
= MSVCRT_malloc(count
+nr_lf
*2+size
)))
3427 for (s
=buf
, i
=0, j
=0; i
<count
; i
++)
3429 if (s
[i
]=='\n' && s
[i
+1]==0)
3437 q
= p
+count
+nr_lf
*2;
3438 WideCharToMultiByte(CP_UTF8
, 0, (WCHAR
*)p
, count
/2+nr_lf
,
3439 p
+count
+nr_lf
*2, conv_len
+nr_lf
, NULL
, NULL
);
3443 FIXME("Malloc failed\n");
3450 if (!WriteFile(hand
, q
, size
, &num_written
, NULL
))
3454 if (num_written
!= size
)
3456 TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n",
3457 fd
, hand
, GetLastError(), num_written
);
3458 *MSVCRT__errno() = MSVCRT_ENOSPC
;
3459 return s
- buf_start
;
3467 /*********************************************************************
3470 int CDECL
MSVCRT__putw(int val
, MSVCRT_FILE
* file
)
3474 MSVCRT__lock_file(file
);
3475 len
= MSVCRT__write(file
->_file
, &val
, sizeof(val
));
3476 if (len
== sizeof(val
)) {
3477 MSVCRT__unlock_file(file
);
3481 file
->_flag
|= MSVCRT__IOERR
;
3482 MSVCRT__unlock_file(file
);
3486 /*********************************************************************
3489 int CDECL
MSVCRT_fclose(MSVCRT_FILE
* file
)
3493 MSVCRT__lock_file(file
);
3494 ret
= MSVCRT__fclose_nolock(file
);
3495 MSVCRT__unlock_file(file
);
3500 /*********************************************************************
3501 * _fclose_nolock (MSVCRT.@)
3503 int CDECL
MSVCRT__fclose_nolock(MSVCRT_FILE
* file
)
3508 MSVCRT_free(file
->_tmpfname
);
3509 file
->_tmpfname
= NULL
;
3510 /* flush stdio buffers */
3511 if(file
->_flag
& MSVCRT__IOWRT
)
3512 MSVCRT__fflush_nolock(file
);
3513 if(file
->_flag
& MSVCRT__IOMYBUF
)
3514 MSVCRT_free(file
->_base
);
3516 r
=MSVCRT__close(file
->_file
);
3519 return ((r
== -1) || (flag
& MSVCRT__IOERR
) ? MSVCRT_EOF
: 0);
3522 /*********************************************************************
3525 int CDECL
MSVCRT_feof(MSVCRT_FILE
* file
)
3527 return file
->_flag
& MSVCRT__IOEOF
;
3530 /*********************************************************************
3533 int CDECL
MSVCRT_ferror(MSVCRT_FILE
* file
)
3535 return file
->_flag
& MSVCRT__IOERR
;
3538 /*********************************************************************
3539 * _filbuf (MSVCRT.@)
3541 int CDECL
MSVCRT__filbuf(MSVCRT_FILE
* file
)
3545 if(file
->_flag
& MSVCRT__IOSTRG
)
3548 /* Allocate buffer if needed */
3549 if(!(file
->_flag
& (MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)))
3550 msvcrt_alloc_buffer(file
);
3552 if(!(file
->_flag
& MSVCRT__IOREAD
)) {
3553 if(file
->_flag
& MSVCRT__IORW
)
3554 file
->_flag
|= MSVCRT__IOREAD
;
3559 if(!(file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
))) {
3561 if ((r
= MSVCRT__read(file
->_file
,&c
,1)) != 1) {
3562 file
->_flag
|= (r
== 0) ? MSVCRT__IOEOF
: MSVCRT__IOERR
;
3568 file
->_cnt
= MSVCRT__read(file
->_file
, file
->_base
, file
->_bufsiz
);
3570 file
->_flag
|= (file
->_cnt
== 0) ? MSVCRT__IOEOF
: MSVCRT__IOERR
;
3576 file
->_ptr
= file
->_base
+1;
3577 c
= *(unsigned char *)file
->_base
;
3582 /*********************************************************************
3585 int CDECL
MSVCRT_fgetc(MSVCRT_FILE
* file
)
3589 MSVCRT__lock_file(file
);
3590 ret
= MSVCRT__fgetc_nolock(file
);
3591 MSVCRT__unlock_file(file
);
3596 /*********************************************************************
3597 * _fgetc_nolock (MSVCRT.@)
3599 int CDECL
MSVCRT__fgetc_nolock(MSVCRT_FILE
* file
)
3606 i
= (unsigned char *)file
->_ptr
++;
3609 j
= MSVCRT__filbuf(file
);
3614 /*********************************************************************
3615 * _fgetchar (MSVCRT.@)
3617 int CDECL
MSVCRT__fgetchar(void)
3619 return MSVCRT_fgetc(MSVCRT_stdin
);
3622 /*********************************************************************
3625 char * CDECL
MSVCRT_fgets(char *s
, int size
, MSVCRT_FILE
* file
)
3627 int cc
= MSVCRT_EOF
;
3628 char * buf_start
= s
;
3630 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3631 file
,file
->_file
,s
,size
);
3633 MSVCRT__lock_file(file
);
3635 while ((size
>1) && (cc
= MSVCRT__fgetc_nolock(file
)) != MSVCRT_EOF
&& cc
!= '\n')
3640 if ((cc
== MSVCRT_EOF
) && (s
== buf_start
)) /* If nothing read, return 0*/
3642 TRACE(":nothing read\n");
3643 MSVCRT__unlock_file(file
);
3646 if ((cc
!= MSVCRT_EOF
) && (size
> 1))
3649 TRACE(":got %s\n", debugstr_a(buf_start
));
3650 MSVCRT__unlock_file(file
);
3654 /*********************************************************************
3657 MSVCRT_wint_t CDECL
MSVCRT_fgetwc(MSVCRT_FILE
* file
)
3661 MSVCRT__lock_file(file
);
3662 ret
= MSVCRT__fgetwc_nolock(file
);
3663 MSVCRT__unlock_file(file
);
3668 /*********************************************************************
3669 * _fgetwc_nolock (MSVCRT.@)
3671 MSVCRT_wint_t CDECL
MSVCRT__fgetwc_nolock(MSVCRT_FILE
* file
)
3676 if((get_ioinfo_nolock(file
->_file
)->exflag
& (EF_UTF8
| EF_UTF16
))
3677 || !(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
)) {
3680 for(p
=(char*)&ret
; (MSVCRT_wint_t
*)p
<&ret
+1; p
++) {
3681 ch
= MSVCRT__fgetc_nolock(file
);
3682 if(ch
== MSVCRT_EOF
) {
3689 char mbs
[MSVCRT_MB_LEN_MAX
];
3692 ch
= MSVCRT__fgetc_nolock(file
);
3693 if(ch
!= MSVCRT_EOF
) {
3695 if(MSVCRT_isleadbyte((unsigned char)mbs
[0])) {
3696 ch
= MSVCRT__fgetc_nolock(file
);
3697 if(ch
!= MSVCRT_EOF
) {
3706 if(!len
|| MSVCRT_mbtowc(&ret
, mbs
, len
)==-1)
3713 /*********************************************************************
3716 int CDECL
MSVCRT__getw(MSVCRT_FILE
* file
)
3723 MSVCRT__lock_file(file
);
3724 for (j
=0; j
<sizeof(int); j
++) {
3725 k
= MSVCRT__fgetc_nolock(file
);
3726 if (k
== MSVCRT_EOF
) {
3727 file
->_flag
|= MSVCRT__IOEOF
;
3728 MSVCRT__unlock_file(file
);
3734 MSVCRT__unlock_file(file
);
3738 /*********************************************************************
3741 MSVCRT_wint_t CDECL
MSVCRT_getwc(MSVCRT_FILE
* file
)
3743 return MSVCRT_fgetwc(file
);
3746 /*********************************************************************
3747 * _fgetwchar (MSVCRT.@)
3749 MSVCRT_wint_t CDECL
MSVCRT__fgetwchar(void)
3751 return MSVCRT_fgetwc(MSVCRT_stdin
);
3754 /*********************************************************************
3755 * getwchar (MSVCRT.@)
3757 MSVCRT_wint_t CDECL
MSVCRT_getwchar(void)
3759 return MSVCRT__fgetwchar();
3762 /*********************************************************************
3765 MSVCRT_wchar_t
* CDECL
MSVCRT_fgetws(MSVCRT_wchar_t
*s
, int size
, MSVCRT_FILE
* file
)
3767 MSVCRT_wint_t cc
= MSVCRT_WEOF
;
3768 MSVCRT_wchar_t
* buf_start
= s
;
3770 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
3771 file
,file
->_file
,s
,size
);
3773 MSVCRT__lock_file(file
);
3775 while ((size
>1) && (cc
= MSVCRT__fgetwc_nolock(file
)) != MSVCRT_WEOF
&& cc
!= '\n')
3780 if ((cc
== MSVCRT_WEOF
) && (s
== buf_start
)) /* If nothing read, return 0*/
3782 TRACE(":nothing read\n");
3783 MSVCRT__unlock_file(file
);
3786 if ((cc
!= MSVCRT_WEOF
) && (size
> 1))
3789 TRACE(":got %s\n", debugstr_w(buf_start
));
3790 MSVCRT__unlock_file(file
);
3794 /*********************************************************************
3795 * _flsbuf (MSVCRT.@)
3797 int CDECL
MSVCRT__flsbuf(int c
, MSVCRT_FILE
* file
)
3799 /* Flush output buffer */
3800 if(!(file
->_flag
& (MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
))) {
3801 msvcrt_alloc_buffer(file
);
3804 if(!(file
->_flag
& MSVCRT__IOWRT
)) {
3805 if(!(file
->_flag
& MSVCRT__IORW
)) {
3806 file
->_flag
|= MSVCRT__IOERR
;
3809 file
->_flag
|= MSVCRT__IOWRT
;
3811 if(file
->_flag
& MSVCRT__IOREAD
) {
3812 if(!(file
->_flag
& MSVCRT__IOEOF
)) {
3813 file
->_flag
|= MSVCRT__IOERR
;
3817 file
->_ptr
= file
->_base
;
3818 file
->_flag
&= ~(MSVCRT__IOREAD
| MSVCRT__IOEOF
);
3821 if(file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)) {
3824 if(file
->_cnt
<= 0) {
3825 res
= msvcrt_flush_buffer(file
);
3828 file
->_flag
|= MSVCRT__IOWRT
;
3829 file
->_cnt
=file
->_bufsiz
;
3837 /* set _cnt to 0 for unbuffered FILEs */
3839 len
= MSVCRT__write(file
->_file
, &cc
, 1);
3842 file
->_flag
|= MSVCRT__IOERR
;
3847 /*********************************************************************
3850 MSVCRT_size_t CDECL
MSVCRT_fwrite(const void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
3854 MSVCRT__lock_file(file
);
3855 ret
= MSVCRT__fwrite_nolock(ptr
, size
, nmemb
, file
);
3856 MSVCRT__unlock_file(file
);
3861 /*********************************************************************
3862 * _fwrite_nolock (MSVCRT.@)
3864 MSVCRT_size_t CDECL
MSVCRT__fwrite_nolock(const void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
3866 MSVCRT_size_t wrcnt
=size
* nmemb
;
3872 if(file
->_cnt
< 0) {
3873 WARN("negative file->_cnt value in %p\n", file
);
3874 file
->_flag
|= MSVCRT__IOERR
;
3876 } else if(file
->_cnt
) {
3877 int pcnt
=(file
->_cnt
>wrcnt
)? wrcnt
: file
->_cnt
;
3878 memcpy(file
->_ptr
, ptr
, pcnt
);
3883 ptr
= (const char*)ptr
+ pcnt
;
3884 } else if((file
->_flag
& MSVCRT__IONBF
)
3885 || ((file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)) && wrcnt
>= file
->_bufsiz
)
3886 || (!(file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)) && wrcnt
>= MSVCRT_INTERNAL_BUFSIZ
)) {
3890 if(file
->_flag
& MSVCRT__IONBF
)
3892 else if(!(file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)))
3893 bufsiz
= MSVCRT_INTERNAL_BUFSIZ
;
3895 bufsiz
= file
->_bufsiz
;
3897 pcnt
= (wrcnt
/ bufsiz
) * bufsiz
;
3899 if(msvcrt_flush_buffer(file
) == MSVCRT_EOF
)
3902 if(MSVCRT__write(file
->_file
, ptr
, pcnt
) <= 0) {
3903 file
->_flag
|= MSVCRT__IOERR
;
3908 ptr
= (const char*)ptr
+ pcnt
;
3910 if(MSVCRT__flsbuf(*(const char*)ptr
, file
) == MSVCRT_EOF
)
3914 ptr
= (const char*)ptr
+ 1;
3918 return written
/ size
;
3921 /*********************************************************************
3924 MSVCRT_wint_t CDECL
MSVCRT_fputwc(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
3928 MSVCRT__lock_file(file
);
3929 ret
= MSVCRT__fputwc_nolock(wc
, file
);
3930 MSVCRT__unlock_file(file
);
3935 /*********************************************************************
3936 * _fputwc_nolock (MSVCRT.@)
3938 MSVCRT_wint_t CDECL
MSVCRT__fputwc_nolock(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
3940 MSVCRT_wchar_t mwc
=wc
;
3944 fdinfo
= get_ioinfo_nolock(file
->_file
);
3946 if((fdinfo
->wxflag
&WX_TEXT
) && !(fdinfo
->exflag
&(EF_UTF8
|EF_UTF16
))) {
3947 char buf
[MSVCRT_MB_LEN_MAX
];
3950 char_len
= MSVCRT_wctomb(buf
, mwc
);
3951 if(char_len
!=-1 && MSVCRT__fwrite_nolock(buf
, char_len
, 1, file
)==1)
3955 }else if(MSVCRT__fwrite_nolock(&mwc
, sizeof(mwc
), 1, file
) == 1) {
3964 /*********************************************************************
3965 * _fputwchar (MSVCRT.@)
3967 MSVCRT_wint_t CDECL
MSVCRT__fputwchar(MSVCRT_wint_t wc
)
3969 return MSVCRT_fputwc(wc
, MSVCRT_stdout
);
3972 /*********************************************************************
3973 * _wfsopen (MSVCRT.@)
3975 MSVCRT_FILE
* CDECL
MSVCRT__wfsopen(const MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*mode
, int share
)
3978 int open_flags
, stream_flags
, fd
;
3980 TRACE("(%s,%s)\n", debugstr_w(path
), debugstr_w(mode
));
3982 /* map mode string to open() flags. "man fopen" for possibilities. */
3983 if (msvcrt_get_flags(mode
, &open_flags
, &stream_flags
) == -1)
3987 fd
= MSVCRT__wsopen(path
, open_flags
, share
, MSVCRT__S_IREAD
| MSVCRT__S_IWRITE
);
3990 else if ((file
= msvcrt_alloc_fp()) && msvcrt_init_fp(file
, fd
, stream_flags
)
3992 TRACE(":fd (%d) mode (%s) FILE* (%p)\n", fd
, debugstr_w(mode
), file
);
3999 TRACE(":got (%p)\n",file
);
4000 if (fd
>= 0 && !file
)
4006 /*********************************************************************
4007 * _fsopen (MSVCRT.@)
4009 MSVCRT_FILE
* CDECL
MSVCRT__fsopen(const char *path
, const char *mode
, int share
)
4012 MSVCRT_wchar_t
*pathW
= NULL
, *modeW
= NULL
;
4014 if (path
&& !(pathW
= msvcrt_wstrdupa(path
))) {
4015 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
4016 *MSVCRT__errno() = MSVCRT_EINVAL
;
4019 if (mode
&& !(modeW
= msvcrt_wstrdupa(mode
)))
4022 MSVCRT__invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
4023 *MSVCRT__errno() = MSVCRT_EINVAL
;
4027 ret
= MSVCRT__wfsopen(pathW
, modeW
, share
);
4034 /*********************************************************************
4037 MSVCRT_FILE
* CDECL
MSVCRT_fopen(const char *path
, const char *mode
)
4039 return MSVCRT__fsopen( path
, mode
, MSVCRT__SH_DENYNO
);
4042 /*********************************************************************
4043 * fopen_s (MSVCRT.@)
4045 int CDECL
MSVCRT_fopen_s(MSVCRT_FILE
** pFile
,
4046 const char *filename
, const char *mode
)
4048 if (!MSVCRT_CHECK_PMT(pFile
!= NULL
)) return MSVCRT_EINVAL
;
4049 if (!MSVCRT_CHECK_PMT(filename
!= NULL
)) return MSVCRT_EINVAL
;
4050 if (!MSVCRT_CHECK_PMT(mode
!= NULL
)) return MSVCRT_EINVAL
;
4052 *pFile
= MSVCRT_fopen(filename
, mode
);
4055 return *MSVCRT__errno();
4059 /*********************************************************************
4060 * _wfopen (MSVCRT.@)
4062 MSVCRT_FILE
* CDECL
MSVCRT__wfopen(const MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*mode
)
4064 return MSVCRT__wfsopen( path
, mode
, MSVCRT__SH_DENYNO
);
4067 /*********************************************************************
4068 * _wfopen_s (MSVCRT.@)
4070 int CDECL
MSVCRT__wfopen_s(MSVCRT_FILE
** pFile
, const MSVCRT_wchar_t
*filename
,
4071 const MSVCRT_wchar_t
*mode
)
4073 if (!MSVCRT_CHECK_PMT(pFile
!= NULL
)) return MSVCRT_EINVAL
;
4074 if (!MSVCRT_CHECK_PMT(filename
!= NULL
)) return MSVCRT_EINVAL
;
4075 if (!MSVCRT_CHECK_PMT(mode
!= NULL
)) return MSVCRT_EINVAL
;
4077 *pFile
= MSVCRT__wfopen(filename
, mode
);
4080 return *MSVCRT__errno();
4084 /*********************************************************************
4087 int CDECL
MSVCRT_fputc(int c
, MSVCRT_FILE
* file
)
4091 MSVCRT__lock_file(file
);
4092 ret
= MSVCRT__fputc_nolock(c
, file
);
4093 MSVCRT__unlock_file(file
);
4098 /*********************************************************************
4099 * _fputc_nolock (MSVCRT.@)
4101 int CDECL
MSVCRT__fputc_nolock(int c
, MSVCRT_FILE
* file
)
4110 res
= msvcrt_flush_buffer(file
);
4111 return res
? res
: c
;
4117 res
= MSVCRT__flsbuf(c
, file
);
4122 /*********************************************************************
4123 * _fputchar (MSVCRT.@)
4125 int CDECL
MSVCRT__fputchar(int c
)
4127 return MSVCRT_fputc(c
, MSVCRT_stdout
);
4130 /*********************************************************************
4133 MSVCRT_size_t CDECL
MSVCRT_fread(void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
4137 MSVCRT__lock_file(file
);
4138 ret
= MSVCRT__fread_nolock(ptr
, size
, nmemb
, file
);
4139 MSVCRT__unlock_file(file
);
4144 /*********************************************************************
4145 * _fread_nolock (MSVCRT.@)
4147 MSVCRT_size_t CDECL
MSVCRT__fread_nolock(void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
4149 MSVCRT_size_t rcnt
=size
* nmemb
;
4150 MSVCRT_size_t read
=0;
4151 MSVCRT_size_t pread
=0;
4156 /* first buffered data */
4158 int pcnt
= (rcnt
>file
->_cnt
)? file
->_cnt
:rcnt
;
4159 memcpy(ptr
, file
->_ptr
, pcnt
);
4164 ptr
= (char*)ptr
+ pcnt
;
4165 } else if(!(file
->_flag
& MSVCRT__IOREAD
)) {
4166 if(file
->_flag
& MSVCRT__IORW
) {
4167 file
->_flag
|= MSVCRT__IOREAD
;
4173 if(rcnt
>0 && !(file
->_flag
& (MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)))
4174 msvcrt_alloc_buffer(file
);
4179 if (!file
->_cnt
&& rcnt
<MSVCRT_BUFSIZ
&& (file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
))) {
4180 file
->_cnt
= MSVCRT__read(file
->_file
, file
->_base
, file
->_bufsiz
);
4181 file
->_ptr
= file
->_base
;
4182 i
= (file
->_cnt
<rcnt
) ? file
->_cnt
: rcnt
;
4183 /* If the buffer fill reaches eof but fread wouldn't, clear eof. */
4184 if (i
> 0 && i
< file
->_cnt
) {
4185 get_ioinfo_nolock(file
->_file
)->wxflag
&= ~WX_ATEOF
;
4186 file
->_flag
&= ~MSVCRT__IOEOF
;
4189 memcpy(ptr
, file
->_ptr
, i
);
4193 } else if (rcnt
> INT_MAX
) {
4194 i
= MSVCRT__read(file
->_file
, ptr
, INT_MAX
);
4195 } else if (rcnt
< MSVCRT_BUFSIZ
) {
4196 i
= MSVCRT__read(file
->_file
, ptr
, rcnt
);
4198 i
= MSVCRT__read(file
->_file
, ptr
, rcnt
- MSVCRT_BUFSIZ
/2);
4202 ptr
= (char *)ptr
+i
;
4203 /* expose feof condition in the flags
4204 * MFC tests file->_flag for feof, and doesn't call feof())
4206 if (get_ioinfo_nolock(file
->_file
)->wxflag
& WX_ATEOF
)
4207 file
->_flag
|= MSVCRT__IOEOF
;
4210 file
->_flag
|= MSVCRT__IOERR
;
4221 /*********************************************************************
4222 * fread_s (MSVCR80.@)
4224 MSVCRT_size_t CDECL
MSVCRT_fread_s(void *buf
, MSVCRT_size_t buf_size
, MSVCRT_size_t elem_size
,
4225 MSVCRT_size_t count
, MSVCRT_FILE
*stream
)
4229 if(!MSVCRT_CHECK_PMT(stream
!= NULL
)) {
4231 memset(buf
, 0, buf_size
);
4234 if(!elem_size
|| !count
) return 0;
4236 MSVCRT__lock_file(stream
);
4237 ret
= MSVCRT__fread_nolock_s(buf
, buf_size
, elem_size
, count
, stream
);
4238 MSVCRT__unlock_file(stream
);
4243 /*********************************************************************
4244 * _fread_nolock_s (MSVCR80.@)
4246 MSVCRT_size_t CDECL
MSVCRT__fread_nolock_s(void *buf
, MSVCRT_size_t buf_size
, MSVCRT_size_t elem_size
,
4247 MSVCRT_size_t count
, MSVCRT_FILE
*stream
)
4249 size_t bytes_left
, buf_pos
;
4251 TRACE("(%p %lu %lu %lu %p)\n", buf
, buf_size
, elem_size
, count
, stream
);
4253 if(!MSVCRT_CHECK_PMT(stream
!= NULL
)) {
4255 memset(buf
, 0, buf_size
);
4258 if(!elem_size
|| !count
) return 0;
4259 if(!MSVCRT_CHECK_PMT(buf
!= NULL
)) return 0;
4260 if(!MSVCRT_CHECK_PMT(MSVCRT_SIZE_MAX
/count
>= elem_size
)) return 0;
4262 bytes_left
= elem_size
*count
;
4265 if(stream
->_cnt
> 0) {
4266 size_t size
= bytes_left
<stream
->_cnt
? bytes_left
: stream
->_cnt
;
4268 if(!MSVCRT_CHECK_PMT_ERR(size
<= buf_size
-buf_pos
, MSVCRT_ERANGE
)) {
4269 memset(buf
, 0, buf_size
);
4273 MSVCRT__fread_nolock((char*)buf
+buf_pos
, 1, size
, stream
);
4277 int c
= MSVCRT__filbuf(stream
);
4282 if(!MSVCRT_CHECK_PMT_ERR(buf_size
!= buf_pos
, MSVCRT_ERANGE
)) {
4283 memset(buf
, 0, buf_size
);
4287 ((char*)buf
)[buf_pos
++] = c
;
4292 return buf_pos
/elem_size
;
4295 /*********************************************************************
4296 * _wfreopen (MSVCRT.@)
4299 MSVCRT_FILE
* CDECL
MSVCRT__wfreopen(const MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*mode
, MSVCRT_FILE
* file
)
4301 int open_flags
, stream_flags
, fd
;
4303 TRACE(":path (%s) mode (%s) file (%p) fd (%d)\n", debugstr_w(path
), debugstr_w(mode
), file
, file
? file
->_file
: -1);
4306 if (!file
|| ((fd
= file
->_file
) < 0) || fd
> MSVCRT_fdend
)
4310 MSVCRT_fclose(file
);
4311 if (msvcrt_get_flags(mode
, &open_flags
, &stream_flags
) == -1)
4313 else if((fd
= MSVCRT__wopen(path
, open_flags
, MSVCRT__S_IREAD
| MSVCRT__S_IWRITE
)) < 0)
4315 else if(msvcrt_init_fp(file
, fd
, stream_flags
) == -1)
4325 /*********************************************************************
4326 * _wfreopen_s (MSVCRT.@)
4328 int CDECL
MSVCRT__wfreopen_s(MSVCRT_FILE
** pFile
,
4329 const MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*mode
, MSVCRT_FILE
* file
)
4331 if (!MSVCRT_CHECK_PMT(pFile
!= NULL
)) return MSVCRT_EINVAL
;
4332 if (!MSVCRT_CHECK_PMT(path
!= NULL
)) return MSVCRT_EINVAL
;
4333 if (!MSVCRT_CHECK_PMT(mode
!= NULL
)) return MSVCRT_EINVAL
;
4334 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
4336 *pFile
= MSVCRT__wfreopen(path
, mode
, file
);
4339 return *MSVCRT__errno();
4343 /*********************************************************************
4344 * freopen (MSVCRT.@)
4347 MSVCRT_FILE
* CDECL
MSVCRT_freopen(const char *path
, const char *mode
, MSVCRT_FILE
* file
)
4350 MSVCRT_wchar_t
*pathW
= NULL
, *modeW
= NULL
;
4352 if (path
&& !(pathW
= msvcrt_wstrdupa(path
))) return NULL
;
4353 if (mode
&& !(modeW
= msvcrt_wstrdupa(mode
)))
4359 ret
= MSVCRT__wfreopen(pathW
, modeW
, file
);
4366 /*********************************************************************
4367 * freopen_s (MSVCRT.@)
4369 int CDECL
MSVCRT_freopen_s(MSVCRT_FILE
** pFile
,
4370 const char *path
, const char *mode
, MSVCRT_FILE
* file
)
4372 if (!MSVCRT_CHECK_PMT(pFile
!= NULL
)) return MSVCRT_EINVAL
;
4373 if (!MSVCRT_CHECK_PMT(path
!= NULL
)) return MSVCRT_EINVAL
;
4374 if (!MSVCRT_CHECK_PMT(mode
!= NULL
)) return MSVCRT_EINVAL
;
4375 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
4377 *pFile
= MSVCRT_freopen(path
, mode
, file
);
4380 return *MSVCRT__errno();
4384 /*********************************************************************
4385 * fsetpos (MSVCRT.@)
4387 int CDECL
MSVCRT_fsetpos(MSVCRT_FILE
* file
, MSVCRT_fpos_t
*pos
)
4391 MSVCRT__lock_file(file
);
4392 msvcrt_flush_buffer(file
);
4394 /* Reset direction of i/o */
4395 if(file
->_flag
& MSVCRT__IORW
) {
4396 file
->_flag
&= ~(MSVCRT__IOREAD
|MSVCRT__IOWRT
);
4399 ret
= (MSVCRT__lseeki64(file
->_file
,*pos
,SEEK_SET
) == -1) ? -1 : 0;
4400 MSVCRT__unlock_file(file
);
4404 /*********************************************************************
4405 * _ftelli64 (MSVCRT.@)
4407 __int64 CDECL
MSVCRT__ftelli64(MSVCRT_FILE
* file
)
4411 MSVCRT__lock_file(file
);
4412 ret
= MSVCRT__ftelli64_nolock(file
);
4413 MSVCRT__unlock_file(file
);
4418 /*********************************************************************
4419 * _ftelli64_nolock (MSVCRT.@)
4421 __int64 CDECL
MSVCRT__ftelli64_nolock(MSVCRT_FILE
* file
)
4425 pos
= _telli64(file
->_file
);
4428 if(file
->_flag
& (MSVCRT__IOMYBUF
| MSVCRT__USERBUF
)) {
4429 if(file
->_flag
& MSVCRT__IOWRT
) {
4430 pos
+= file
->_ptr
- file
->_base
;
4432 if(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
) {
4435 for(p
=file
->_base
; p
<file
->_ptr
; p
++)
4439 } else if(!file
->_cnt
) { /* nothing to do */
4440 } else if(MSVCRT__lseeki64(file
->_file
, 0, SEEK_END
)==pos
) {
4444 if(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
) {
4445 for(i
=0; i
<file
->_cnt
; i
++)
4446 if(file
->_ptr
[i
] == '\n')
4452 if(MSVCRT__lseeki64(file
->_file
, pos
, SEEK_SET
) != pos
)
4455 pos
-= file
->_bufsiz
;
4456 pos
+= file
->_ptr
- file
->_base
;
4458 if(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
) {
4459 if(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_READNL
)
4462 for(p
=file
->_base
; p
<file
->_ptr
; p
++)
4472 /*********************************************************************
4475 LONG CDECL
MSVCRT_ftell(MSVCRT_FILE
* file
)
4477 return MSVCRT__ftelli64(file
);
4480 /*********************************************************************
4481 * _ftell_nolock (MSVCRT.@)
4483 LONG CDECL
MSVCRT__ftell_nolock(MSVCRT_FILE
* file
)
4485 return MSVCRT__ftelli64_nolock(file
);
4488 /*********************************************************************
4489 * fgetpos (MSVCRT.@)
4491 int CDECL
MSVCRT_fgetpos(MSVCRT_FILE
* file
, MSVCRT_fpos_t
*pos
)
4493 *pos
= MSVCRT__ftelli64(file
);
4499 /*********************************************************************
4502 int CDECL
MSVCRT_fputs(const char *s
, MSVCRT_FILE
* file
)
4504 MSVCRT_size_t len
= strlen(s
);
4507 MSVCRT__lock_file(file
);
4508 ret
= MSVCRT__fwrite_nolock(s
, sizeof(*s
), len
, file
) == len
? 0 : MSVCRT_EOF
;
4509 MSVCRT__unlock_file(file
);
4513 /*********************************************************************
4516 int CDECL
MSVCRT_fputws(const MSVCRT_wchar_t
*s
, MSVCRT_FILE
* file
)
4518 MSVCRT_size_t i
, len
= strlenW(s
);
4522 MSVCRT__lock_file(file
);
4523 if (!(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
)) {
4524 ret
= MSVCRT__fwrite_nolock(s
,sizeof(*s
),len
,file
) == len
? 0 : MSVCRT_EOF
;
4525 MSVCRT__unlock_file(file
);
4529 tmp_buf
= add_std_buffer(file
);
4530 for (i
=0; i
<len
; i
++) {
4531 if(MSVCRT__fputwc_nolock(s
[i
], file
) == MSVCRT_WEOF
) {
4532 if(tmp_buf
) remove_std_buffer(file
);
4533 MSVCRT__unlock_file(file
);
4538 if(tmp_buf
) remove_std_buffer(file
);
4539 MSVCRT__unlock_file(file
);
4543 /*********************************************************************
4544 * getchar (MSVCRT.@)
4546 int CDECL
MSVCRT_getchar(void)
4548 return MSVCRT_fgetc(MSVCRT_stdin
);
4551 /*********************************************************************
4554 int CDECL
MSVCRT_getc(MSVCRT_FILE
* file
)
4556 return MSVCRT_fgetc(file
);
4559 /*********************************************************************
4562 char * CDECL
MSVCRT_gets(char *buf
)
4565 char * buf_start
= buf
;
4567 MSVCRT__lock_file(MSVCRT_stdin
);
4568 for(cc
= MSVCRT__fgetc_nolock(MSVCRT_stdin
); cc
!= MSVCRT_EOF
&& cc
!= '\n';
4569 cc
= MSVCRT__fgetc_nolock(MSVCRT_stdin
))
4570 if(cc
!= '\r') *buf
++ = (char)cc
;
4574 TRACE("got '%s'\n", buf_start
);
4575 MSVCRT__unlock_file(MSVCRT_stdin
);
4579 /*********************************************************************
4582 MSVCRT_wchar_t
* CDECL
MSVCRT__getws(MSVCRT_wchar_t
* buf
)
4585 MSVCRT_wchar_t
* ws
= buf
;
4587 MSVCRT__lock_file(MSVCRT_stdin
);
4588 for (cc
= MSVCRT__fgetwc_nolock(MSVCRT_stdin
); cc
!= MSVCRT_WEOF
&& cc
!= '\n';
4589 cc
= MSVCRT__fgetwc_nolock(MSVCRT_stdin
))
4592 *buf
++ = (MSVCRT_wchar_t
)cc
;
4596 TRACE("got %s\n", debugstr_w(ws
));
4597 MSVCRT__unlock_file(MSVCRT_stdin
);
4601 /*********************************************************************
4604 int CDECL
MSVCRT_putc(int c
, MSVCRT_FILE
* file
)
4606 return MSVCRT_fputc(c
, file
);
4609 /*********************************************************************
4610 * putchar (MSVCRT.@)
4612 int CDECL
MSVCRT_putchar(int c
)
4614 return MSVCRT_fputc(c
, MSVCRT_stdout
);
4617 /*********************************************************************
4618 * _putwch (MSVCRT.@)
4620 int CDECL
MSVCRT__putwch(int c
)
4622 return MSVCRT_fputwc(c
, MSVCRT_stdout
);
4625 /*********************************************************************
4628 int CDECL
MSVCRT_puts(const char *s
)
4630 MSVCRT_size_t len
= strlen(s
);
4633 MSVCRT__lock_file(MSVCRT_stdout
);
4634 if(MSVCRT__fwrite_nolock(s
, sizeof(*s
), len
, MSVCRT_stdout
) != len
) {
4635 MSVCRT__unlock_file(MSVCRT_stdout
);
4639 ret
= MSVCRT__fwrite_nolock("\n",1,1,MSVCRT_stdout
) == 1 ? 0 : MSVCRT_EOF
;
4640 MSVCRT__unlock_file(MSVCRT_stdout
);
4644 /*********************************************************************
4647 int CDECL
MSVCRT__putws(const MSVCRT_wchar_t
*s
)
4649 static const MSVCRT_wchar_t nl
= '\n';
4650 MSVCRT_size_t len
= strlenW(s
);
4653 MSVCRT__lock_file(MSVCRT_stdout
);
4654 if(MSVCRT__fwrite_nolock(s
, sizeof(*s
), len
, MSVCRT_stdout
) != len
) {
4655 MSVCRT__unlock_file(MSVCRT_stdout
);
4659 ret
= MSVCRT__fwrite_nolock(&nl
,sizeof(nl
),1,MSVCRT_stdout
) == 1 ? 0 : MSVCRT_EOF
;
4660 MSVCRT__unlock_file(MSVCRT_stdout
);
4664 /*********************************************************************
4667 int CDECL
MSVCRT_remove(const char *path
)
4669 TRACE("(%s)\n",path
);
4670 if (DeleteFileA(path
))
4672 TRACE(":failed (%d)\n",GetLastError());
4673 msvcrt_set_errno(GetLastError());
4677 /*********************************************************************
4678 * _wremove (MSVCRT.@)
4680 int CDECL
MSVCRT__wremove(const MSVCRT_wchar_t
*path
)
4682 TRACE("(%s)\n",debugstr_w(path
));
4683 if (DeleteFileW(path
))
4685 TRACE(":failed (%d)\n",GetLastError());
4686 msvcrt_set_errno(GetLastError());
4690 /*********************************************************************
4693 int CDECL
MSVCRT_rename(const char *oldpath
,const char *newpath
)
4695 TRACE(":from %s to %s\n",oldpath
,newpath
);
4696 if (MoveFileExA(oldpath
, newpath
, MOVEFILE_COPY_ALLOWED
))
4698 TRACE(":failed (%d)\n",GetLastError());
4699 msvcrt_set_errno(GetLastError());
4703 /*********************************************************************
4704 * _wrename (MSVCRT.@)
4706 int CDECL
MSVCRT__wrename(const MSVCRT_wchar_t
*oldpath
,const MSVCRT_wchar_t
*newpath
)
4708 TRACE(":from %s to %s\n",debugstr_w(oldpath
),debugstr_w(newpath
));
4709 if (MoveFileExW(oldpath
, newpath
, MOVEFILE_COPY_ALLOWED
))
4711 TRACE(":failed (%d)\n",GetLastError());
4712 msvcrt_set_errno(GetLastError());
4716 /*********************************************************************
4717 * setvbuf (MSVCRT.@)
4719 int CDECL
MSVCRT_setvbuf(MSVCRT_FILE
* file
, char *buf
, int mode
, MSVCRT_size_t size
)
4721 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return -1;
4722 if(!MSVCRT_CHECK_PMT(mode
==MSVCRT__IONBF
|| mode
==MSVCRT__IOFBF
|| mode
==MSVCRT__IOLBF
)) return -1;
4723 if(!MSVCRT_CHECK_PMT(mode
==MSVCRT__IONBF
|| (size
>=2 && size
<=INT_MAX
))) return -1;
4725 MSVCRT__lock_file(file
);
4727 MSVCRT__fflush_nolock(file
);
4728 if(file
->_flag
& MSVCRT__IOMYBUF
)
4729 MSVCRT_free(file
->_base
);
4730 file
->_flag
&= ~(MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
);
4733 if(mode
== MSVCRT__IONBF
) {
4734 file
->_flag
|= MSVCRT__IONBF
;
4735 file
->_base
= file
->_ptr
= (char*)&file
->_charbuf
;
4738 file
->_base
= file
->_ptr
= buf
;
4739 file
->_flag
|= MSVCRT__USERBUF
;
4740 file
->_bufsiz
= size
;
4742 file
->_base
= file
->_ptr
= MSVCRT_malloc(size
);
4745 MSVCRT__unlock_file(file
);
4749 file
->_flag
|= MSVCRT__IOMYBUF
;
4750 file
->_bufsiz
= size
;
4752 MSVCRT__unlock_file(file
);
4756 /*********************************************************************
4759 void CDECL
MSVCRT_setbuf(MSVCRT_FILE
* file
, char *buf
)
4761 MSVCRT_setvbuf(file
, buf
, buf
? MSVCRT__IOFBF
: MSVCRT__IONBF
, MSVCRT_BUFSIZ
);
4764 /*********************************************************************
4767 char * CDECL
MSVCRT_tmpnam(char *s
)
4774 thread_data_t
*data
= msvcrt_get_thread_data();
4776 if(!data
->tmpnam_buffer
)
4777 data
->tmpnam_buffer
= MSVCRT_malloc(MAX_PATH
);
4779 s
= data
->tmpnam_buffer
;
4782 msvcrt_int_to_base32(GetCurrentProcessId(), tmpstr
);
4783 p
= s
+ sprintf(s
, "\\s%s.", tmpstr
);
4784 for (count
= 0; count
< MSVCRT_TMP_MAX
; count
++)
4786 size
= msvcrt_int_to_base32(tmpnam_unique
++, tmpstr
);
4787 memcpy(p
, tmpstr
, size
);
4789 if (GetFileAttributesA(s
) == INVALID_FILE_ATTRIBUTES
&&
4790 GetLastError() == ERROR_FILE_NOT_FOUND
)
4796 /*********************************************************************
4797 * _wtmpnam (MSVCRT.@)
4799 MSVCRT_wchar_t
* CDECL
MSVCRT_wtmpnam(MSVCRT_wchar_t
*s
)
4801 static const MSVCRT_wchar_t format
[] = {'\\','s','%','s','.',0};
4802 MSVCRT_wchar_t tmpstr
[16];
4806 thread_data_t
*data
= msvcrt_get_thread_data();
4808 if(!data
->wtmpnam_buffer
)
4809 data
->wtmpnam_buffer
= MSVCRT_malloc(sizeof(MSVCRT_wchar_t
[MAX_PATH
]));
4811 s
= data
->wtmpnam_buffer
;
4814 msvcrt_int_to_base32_w(GetCurrentProcessId(), tmpstr
);
4815 p
= s
+ MSVCRT__snwprintf(s
, MAX_PATH
, format
, tmpstr
);
4816 for (count
= 0; count
< MSVCRT_TMP_MAX
; count
++)
4818 size
= msvcrt_int_to_base32_w(tmpnam_unique
++, tmpstr
);
4819 memcpy(p
, tmpstr
, size
*sizeof(MSVCRT_wchar_t
));
4821 if (GetFileAttributesW(s
) == INVALID_FILE_ATTRIBUTES
&&
4822 GetLastError() == ERROR_FILE_NOT_FOUND
)
4828 /*********************************************************************
4829 * tmpfile (MSVCRT.@)
4831 MSVCRT_FILE
* CDECL
MSVCRT_tmpfile(void)
4833 char *filename
= MSVCRT_tmpnam(NULL
);
4835 MSVCRT_FILE
* file
= NULL
;
4838 fd
= MSVCRT__open(filename
, MSVCRT__O_CREAT
| MSVCRT__O_BINARY
| MSVCRT__O_RDWR
| MSVCRT__O_TEMPORARY
,
4839 MSVCRT__S_IREAD
| MSVCRT__S_IWRITE
);
4840 if (fd
!= -1 && (file
= msvcrt_alloc_fp()))
4842 if (msvcrt_init_fp(file
, fd
, MSVCRT__IORW
) == -1)
4847 else file
->_tmpfname
= MSVCRT__strdup(filename
);
4850 if(fd
!= -1 && !file
)
4856 /*********************************************************************
4857 * tmpfile_s (MSVCRT.@)
4859 int CDECL
MSVCRT_tmpfile_s(MSVCRT_FILE
** file
)
4861 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
4863 *file
= MSVCRT_tmpfile();
4867 static int puts_clbk_file_a(void *file
, int len
, const char *str
)
4869 return MSVCRT_fwrite(str
, sizeof(char), len
, file
);
4872 static int puts_clbk_file_w(void *file
, int len
, const MSVCRT_wchar_t
*str
)
4876 MSVCRT__lock_file(file
);
4878 if(!(get_ioinfo_nolock(((MSVCRT_FILE
*)file
)->_file
)->wxflag
& WX_TEXT
)) {
4879 ret
= MSVCRT__fwrite_nolock(str
, sizeof(MSVCRT_wchar_t
), len
, file
);
4880 MSVCRT__unlock_file(file
);
4884 for(i
=0; i
<len
; i
++) {
4885 if(MSVCRT__fputwc_nolock(str
[i
], file
) == MSVCRT_WEOF
) {
4886 MSVCRT__unlock_file(file
);
4891 MSVCRT__unlock_file(file
);
4895 /*********************************************************************
4896 * vfprintf (MSVCRT.@)
4898 int CDECL
MSVCRT_vfprintf(MSVCRT_FILE
* file
, const char *format
, __ms_va_list valist
)
4903 MSVCRT__lock_file(file
);
4904 tmp_buf
= add_std_buffer(file
);
4905 ret
= pf_printf_a(puts_clbk_file_a
, file
, format
, NULL
, FALSE
, FALSE
, arg_clbk_valist
, NULL
, &valist
);
4906 if(tmp_buf
) remove_std_buffer(file
);
4907 MSVCRT__unlock_file(file
);
4912 /*********************************************************************
4913 * vfprintf_s (MSVCRT.@)
4915 int CDECL
MSVCRT_vfprintf_s(MSVCRT_FILE
* file
, const char *format
, __ms_va_list valist
)
4920 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return -1;
4922 MSVCRT__lock_file(file
);
4923 tmp_buf
= add_std_buffer(file
);
4924 ret
= pf_printf_a(puts_clbk_file_a
, file
, format
, NULL
, FALSE
, TRUE
, arg_clbk_valist
, NULL
, &valist
);
4925 if(tmp_buf
) remove_std_buffer(file
);
4926 MSVCRT__unlock_file(file
);
4931 /*********************************************************************
4932 * vfwprintf (MSVCRT.@)
4934 int CDECL
MSVCRT_vfwprintf(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
, __ms_va_list valist
)
4939 MSVCRT__lock_file(file
);
4940 tmp_buf
= add_std_buffer(file
);
4941 ret
= pf_printf_w(puts_clbk_file_w
, file
, format
, NULL
, FALSE
, FALSE
, arg_clbk_valist
, NULL
, &valist
);
4942 if(tmp_buf
) remove_std_buffer(file
);
4943 MSVCRT__unlock_file(file
);
4948 /*********************************************************************
4949 * vfwprintf_s (MSVCRT.@)
4951 int CDECL
MSVCRT_vfwprintf_s(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
, __ms_va_list valist
)
4956 if (!MSVCRT_CHECK_PMT( file
!= NULL
)) return -1;
4958 MSVCRT__lock_file(file
);
4959 tmp_buf
= add_std_buffer(file
);
4960 ret
= pf_printf_w(puts_clbk_file_w
, file
, format
, NULL
, FALSE
, TRUE
, arg_clbk_valist
, NULL
, &valist
);
4961 if(tmp_buf
) remove_std_buffer(file
);
4962 MSVCRT__unlock_file(file
);
4967 /*********************************************************************
4968 * _vfwprintf_l (MSVCRT.@)
4970 int CDECL
MSVCRT__vfwprintf_l(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
,
4971 MSVCRT__locale_t locale
, __ms_va_list valist
)
4976 if (!MSVCRT_CHECK_PMT( file
!= NULL
)) return -1;
4978 MSVCRT__lock_file(file
);
4979 tmp_buf
= add_std_buffer(file
);
4980 ret
= pf_printf_w(puts_clbk_file_w
, file
, format
, locale
, FALSE
, FALSE
, arg_clbk_valist
, NULL
, &valist
);
4981 if(tmp_buf
) remove_std_buffer(file
);
4982 MSVCRT__unlock_file(file
);
4987 /*********************************************************************
4988 * vprintf (MSVCRT.@)
4990 int CDECL
MSVCRT_vprintf(const char *format
, __ms_va_list valist
)
4992 return MSVCRT_vfprintf(MSVCRT_stdout
,format
,valist
);
4995 /*********************************************************************
4996 * vprintf_s (MSVCRT.@)
4998 int CDECL
MSVCRT_vprintf_s(const char *format
, __ms_va_list valist
)
5000 return MSVCRT_vfprintf_s(MSVCRT_stdout
,format
,valist
);
5003 /*********************************************************************
5004 * vwprintf (MSVCRT.@)
5006 int CDECL
MSVCRT_vwprintf(const MSVCRT_wchar_t
*format
, __ms_va_list valist
)
5008 return MSVCRT_vfwprintf(MSVCRT_stdout
,format
,valist
);
5011 /*********************************************************************
5012 * vwprintf_s (MSVCRT.@)
5014 int CDECL
MSVCRT_vwprintf_s(const MSVCRT_wchar_t
*format
, __ms_va_list valist
)
5016 return MSVCRT_vfwprintf_s(MSVCRT_stdout
,format
,valist
);
5019 /*********************************************************************
5020 * fprintf (MSVCRT.@)
5022 int CDECL
MSVCRT_fprintf(MSVCRT_FILE
* file
, const char *format
, ...)
5024 __ms_va_list valist
;
5026 __ms_va_start(valist
, format
);
5027 res
= MSVCRT_vfprintf(file
, format
, valist
);
5028 __ms_va_end(valist
);
5032 /*********************************************************************
5033 * fprintf_s (MSVCRT.@)
5035 int CDECL
MSVCRT_fprintf_s(MSVCRT_FILE
* file
, const char *format
, ...)
5037 __ms_va_list valist
;
5039 __ms_va_start(valist
, format
);
5040 res
= MSVCRT_vfprintf_s(file
, format
, valist
);
5041 __ms_va_end(valist
);
5045 /*********************************************************************
5046 * fwprintf (MSVCRT.@)
5048 int CDECL
MSVCRT_fwprintf(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
, ...)
5050 __ms_va_list valist
;
5052 __ms_va_start(valist
, format
);
5053 res
= MSVCRT_vfwprintf(file
, format
, valist
);
5054 __ms_va_end(valist
);
5058 /*********************************************************************
5059 * fwprintf_s (MSVCRT.@)
5061 int CDECL
MSVCRT_fwprintf_s(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
, ...)
5063 __ms_va_list valist
;
5065 __ms_va_start(valist
, format
);
5066 res
= MSVCRT_vfwprintf_s(file
, format
, valist
);
5067 __ms_va_end(valist
);
5071 /*********************************************************************
5072 * _fwprintf_l (MSVCRT.@)
5074 int CDECL
MSVCRT__fwprintf_l(MSVCRT_FILE
* file
, const MSVCRT_wchar_t
*format
, MSVCRT__locale_t locale
, ...)
5076 __ms_va_list valist
;
5078 __ms_va_start(valist
, locale
);
5079 res
= MSVCRT__vfwprintf_l(file
, format
, locale
, valist
);
5080 __ms_va_end(valist
);
5084 /*********************************************************************
5087 int CDECL
MSVCRT_printf(const char *format
, ...)
5089 __ms_va_list valist
;
5091 __ms_va_start(valist
, format
);
5092 res
= MSVCRT_vfprintf(MSVCRT_stdout
, format
, valist
);
5093 __ms_va_end(valist
);
5097 /*********************************************************************
5098 * printf_s (MSVCRT.@)
5100 int CDECL
MSVCRT_printf_s(const char *format
, ...)
5102 __ms_va_list valist
;
5104 __ms_va_start(valist
, format
);
5105 res
= MSVCRT_vprintf_s(format
, valist
);
5106 __ms_va_end(valist
);
5110 /*********************************************************************
5113 int CDECL
MSVCRT_ungetc(int c
, MSVCRT_FILE
* file
)
5117 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EOF
;
5119 MSVCRT__lock_file(file
);
5120 ret
= MSVCRT__ungetc_nolock(c
, file
);
5121 MSVCRT__unlock_file(file
);
5126 /*********************************************************************
5127 * _ungetc_nolock (MSVCRT.@)
5129 int CDECL
MSVCRT__ungetc_nolock(int c
, MSVCRT_FILE
* file
)
5131 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EOF
;
5133 if (c
== MSVCRT_EOF
|| !(file
->_flag
&MSVCRT__IOREAD
||
5134 (file
->_flag
&MSVCRT__IORW
&& !(file
->_flag
&MSVCRT__IOWRT
))))
5137 if((!(file
->_flag
& (MSVCRT__IONBF
| MSVCRT__IOMYBUF
| MSVCRT__USERBUF
))
5138 && msvcrt_alloc_buffer(file
))
5139 || (!file
->_cnt
&& file
->_ptr
==file
->_base
))
5142 if(file
->_ptr
>file
->_base
) {
5144 if(file
->_flag
& MSVCRT__IOSTRG
) {
5145 if(*file
->_ptr
!= c
) {
5153 file
->_flag
&= ~(MSVCRT__IOERR
| MSVCRT__IOEOF
);
5154 file
->_flag
|= MSVCRT__IOREAD
;
5161 /*********************************************************************
5162 * ungetwc (MSVCRT.@)
5164 MSVCRT_wint_t CDECL
MSVCRT_ungetwc(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
5168 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_WEOF
;
5170 MSVCRT__lock_file(file
);
5171 ret
= MSVCRT__ungetwc_nolock(wc
, file
);
5172 MSVCRT__unlock_file(file
);
5177 /*********************************************************************
5178 * _ungetwc_nolock (MSVCRT.@)
5180 MSVCRT_wint_t CDECL
MSVCRT__ungetwc_nolock(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
5182 MSVCRT_wchar_t mwc
= wc
;
5184 if(!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_WEOF
;
5185 if (wc
== MSVCRT_WEOF
)
5188 if((get_ioinfo_nolock(file
->_file
)->exflag
& (EF_UTF8
| EF_UTF16
))
5189 || !(get_ioinfo_nolock(file
->_file
)->wxflag
& WX_TEXT
)) {
5190 unsigned char * pp
= (unsigned char *)&mwc
;
5193 for(i
=sizeof(MSVCRT_wchar_t
)-1;i
>=0;i
--) {
5194 if(pp
[i
] != MSVCRT__ungetc_nolock(pp
[i
],file
))
5198 char mbs
[MSVCRT_MB_LEN_MAX
];
5201 len
= MSVCRT_wctomb(mbs
, mwc
);
5205 for(len
--; len
>=0; len
--) {
5206 if(mbs
[len
] != MSVCRT__ungetc_nolock(mbs
[len
], file
))
5214 /*********************************************************************
5215 * wprintf (MSVCRT.@)
5217 int CDECL
MSVCRT_wprintf(const MSVCRT_wchar_t
*format
, ...)
5219 __ms_va_list valist
;
5221 __ms_va_start(valist
, format
);
5222 res
= MSVCRT_vwprintf(format
, valist
);
5223 __ms_va_end(valist
);
5227 /*********************************************************************
5228 * wprintf_s (MSVCRT.@)
5230 int CDECL
MSVCRT_wprintf_s(const MSVCRT_wchar_t
*format
, ...)
5232 __ms_va_list valist
;
5234 __ms_va_start(valist
, format
);
5235 res
= MSVCRT_vwprintf_s(format
, valist
);
5236 __ms_va_end(valist
);
5240 /*********************************************************************
5241 * _getmaxstdio (MSVCRT.@)
5243 int CDECL
MSVCRT__getmaxstdio(void)
5245 return MSVCRT_max_streams
;
5248 /*********************************************************************
5249 * _setmaxstdio (MSVCRT.@)
5251 int CDECL
MSVCRT__setmaxstdio(int newmax
)
5253 TRACE("%d\n", newmax
);
5255 if(newmax
<_IOB_ENTRIES
|| newmax
>MSVCRT_MAX_FILES
|| newmax
<MSVCRT_stream_idx
)
5258 MSVCRT_max_streams
= newmax
;
5259 return MSVCRT_max_streams
;