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
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/port.h"
35 #include "msvcrt/errno.h"
37 #include "wine/unicode.h"
38 #include "msvcrt/direct.h"
39 #include "msvcrt/fcntl.h"
40 #include "msvcrt/io.h"
41 #include "msvcrt/sys/locking.h"
42 #include "msvcrt/stdio.h"
43 #include "msvcrt/stdlib.h"
44 #include "msvcrt/string.h"
45 #include "msvcrt/sys/stat.h"
46 #include "msvcrt/sys/utime.h"
47 #include "msvcrt/time.h"
48 #include "msvcrt/share.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
54 /* for stat mode, permissions apply to all,owner and group */
55 #define MSVCRT_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6))
56 #define MSVCRT_S_IWRITE (_S_IWRITE | (_S_IWRITE >> 3) | (_S_IWRITE >> 6))
57 #define MSVCRT_S_IEXEC (_S_IEXEC | (_S_IEXEC >> 3) | (_S_IEXEC >> 6))
59 /* _access() bit flags FIXME: incomplete */
60 #define MSVCRT_W_OK 0x02
63 /* FIXME: Make this dynamic */
64 #define MSVCRT_MAX_FILES 257
66 HANDLE MSVCRT_handles
[MSVCRT_MAX_FILES
];
67 MSVCRT_FILE
* MSVCRT_files
[MSVCRT_MAX_FILES
];
68 int MSVCRT_flags
[MSVCRT_MAX_FILES
];
69 char *MSVCRT_tempfiles
[MSVCRT_MAX_FILES
];
70 MSVCRT_FILE MSVCRT__iob
[3];
71 #define MSVCRT_stdin (MSVCRT__iob+STDIN_FILENO)
72 #define MSVCRT_stdout (MSVCRT__iob+STDOUT_FILENO)
73 #define MSVCRT_stderr (MSVCRT__iob+STDERR_FILENO)
75 static int MSVCRT_fdstart
= 3; /* first unallocated fd */
76 static int MSVCRT_fdend
= 3; /* highest allocated fd */
78 /* INTERNAL: process umask */
79 static int MSVCRT_umask
= 0;
81 /* INTERNAL: Static buffer for temp file name */
82 static char MSVCRT_tmpname
[MAX_PATH
];
84 static const unsigned int EXE
= 'e' << 16 | 'x' << 8 | 'e';
85 static const unsigned int BAT
= 'b' << 16 | 'a' << 8 | 't';
86 static const unsigned int CMD
= 'c' << 16 | 'm' << 8 | 'd';
87 static const unsigned int COM
= 'c' << 16 | 'o' << 8 | 'm';
89 #define TOUL(x) (ULONGLONG)((WCHAR)L##x)
90 static const ULONGLONG WCEXE
= TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e');
91 static const ULONGLONG WCBAT
= TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t');
92 static const ULONGLONG WCCMD
= TOUL('c') << 32 | TOUL('m') << 16 | TOUL('d');
93 static const ULONGLONG WCCOM
= TOUL('c') << 32 | TOUL('o') << 16 | TOUL('m');
95 extern CRITICAL_SECTION MSVCRT_file_cs
;
96 #define LOCK_FILES EnterCriticalSection(&MSVCRT_file_cs)
97 #define UNLOCK_FILES LeaveCriticalSection(&MSVCRT_file_cs)
99 static void msvcrt_cp_from_stati64(const struct _stati64
*bufi64
, struct _stat
*buf
)
101 buf
->st_dev
= bufi64
->st_dev
;
102 buf
->st_ino
= bufi64
->st_ino
;
103 buf
->st_mode
= bufi64
->st_mode
;
104 buf
->st_nlink
= bufi64
->st_nlink
;
105 buf
->st_uid
= bufi64
->st_uid
;
106 buf
->st_gid
= bufi64
->st_gid
;
107 buf
->st_rdev
= bufi64
->st_rdev
;
108 buf
->st_size
= bufi64
->st_size
;
109 buf
->st_atime
= bufi64
->st_atime
;
110 buf
->st_mtime
= bufi64
->st_mtime
;
111 buf
->st_ctime
= bufi64
->st_ctime
;
114 /* INTERNAL: Get the HANDLE for a fd */
115 static HANDLE
msvcrt_fdtoh(int fd
)
117 if (fd
< 0 || fd
>= MSVCRT_fdend
||
118 MSVCRT_handles
[fd
] == INVALID_HANDLE_VALUE
)
120 WARN(":fd (%d) - no handle!\n",fd
);
122 *MSVCRT__errno() = MSVCRT_EBADF
;
123 return INVALID_HANDLE_VALUE
;
125 return MSVCRT_handles
[fd
];
128 /* INTERNAL: free a file entry fd */
129 static void msvcrt_free_fd(int fd
)
131 MSVCRT_handles
[fd
] = INVALID_HANDLE_VALUE
;
132 MSVCRT_files
[fd
] = 0;
133 MSVCRT_flags
[fd
] = 0;
134 TRACE(":fd (%d) freed\n",fd
);
136 return; /* dont use 0,1,2 for user files */
137 if (fd
== MSVCRT_fdend
- 1)
139 if (fd
< MSVCRT_fdstart
)
143 /* INTERNAL: Allocate an fd slot from a Win32 HANDLE */
144 static int msvcrt_alloc_fd(HANDLE hand
, int flag
)
146 int fd
= MSVCRT_fdstart
;
148 TRACE(":handle (%p) allocating fd (%d)\n",hand
,fd
);
149 if (fd
>= MSVCRT_MAX_FILES
)
151 WARN(":files exhausted!\n");
154 MSVCRT_handles
[fd
] = hand
;
155 MSVCRT_flags
[fd
] = flag
;
157 /* locate next free slot */
158 if (fd
== MSVCRT_fdend
)
159 MSVCRT_fdstart
= ++MSVCRT_fdend
;
161 while(MSVCRT_fdstart
< MSVCRT_fdend
&&
162 MSVCRT_handles
[MSVCRT_fdstart
] != INVALID_HANDLE_VALUE
)
168 /* INTERNAL: Allocate a FILE* for an fd slot
169 * This is done lazily to avoid memory wastage for low level open/write
170 * usage when a FILE* is not requested (but may be later).
172 static MSVCRT_FILE
* msvcrt_alloc_fp(int fd
)
174 TRACE(":fd (%d) allocating FILE*\n",fd
);
175 if (fd
< 0 || fd
>= MSVCRT_fdend
||
176 MSVCRT_handles
[fd
] == INVALID_HANDLE_VALUE
)
178 WARN(":invalid fd %d\n",fd
);
180 *MSVCRT__errno() = MSVCRT_EBADF
;
183 if (!MSVCRT_files
[fd
])
185 if ((MSVCRT_files
[fd
] = MSVCRT_calloc(sizeof(MSVCRT_FILE
),1)))
187 MSVCRT_files
[fd
]->_file
= fd
;
188 MSVCRT_files
[fd
]->_flag
= MSVCRT_flags
[fd
];
189 MSVCRT_files
[fd
]->_flag
&= ~MSVCRT__IOAPPEND
; /* mask out, see above */
192 TRACE(":got FILE* (%p)\n",MSVCRT_files
[fd
]);
193 return MSVCRT_files
[fd
];
197 /* INTERNAL: Set up stdin, stderr and stdout */
198 void msvcrt_init_io(void)
201 memset(MSVCRT__iob
,0,3*sizeof(MSVCRT_FILE
));
202 MSVCRT_handles
[0] = GetStdHandle(STD_INPUT_HANDLE
);
203 MSVCRT_flags
[0] = MSVCRT__iob
[0]._flag
= MSVCRT__IOREAD
;
204 MSVCRT_handles
[1] = GetStdHandle(STD_OUTPUT_HANDLE
);
205 MSVCRT_flags
[1] = MSVCRT__iob
[1]._flag
= MSVCRT__IOWRT
;
206 MSVCRT_handles
[2] = GetStdHandle(STD_ERROR_HANDLE
);
207 MSVCRT_flags
[2] = MSVCRT__iob
[2]._flag
= MSVCRT__IOWRT
;
209 TRACE(":handles (%p)(%p)(%p)\n",MSVCRT_handles
[0],
210 MSVCRT_handles
[1],MSVCRT_handles
[2]);
212 for (i
= 0; i
< 3; i
++)
214 /* FILE structs for stdin/out/err are static and never deleted */
215 MSVCRT_files
[i
] = &MSVCRT__iob
[i
];
216 MSVCRT__iob
[i
]._file
= i
;
217 MSVCRT_tempfiles
[i
] = NULL
;
221 /* free everything on process exit */
222 void msvcrt_free_io(void)
230 /* INTERNAL: Flush stdio file buffer */
231 static int msvcrt_flush_buffer(MSVCRT_FILE
* file
)
234 int cnt
=file
->_ptr
-file
->_base
;
235 if(cnt
>0 && _write(file
->_file
, file
->_base
, cnt
) != cnt
) {
238 file
->_ptr
=file
->_base
;
239 file
->_cnt
=file
->_bufsiz
;
244 /* INTERNAL: Allocate stdio file buffer */
245 static void msvcrt_alloc_buffer(MSVCRT_FILE
* file
)
247 file
->_base
= MSVCRT_calloc(MSVCRT_BUFSIZ
,1);
249 file
->_bufsiz
= MSVCRT_BUFSIZ
;
250 file
->_flag
|= MSVCRT__IOMYBUF
;
252 file
->_base
= (unsigned char *)(&file
->_charbuf
);
254 file
->_bufsiz
= sizeof(file
->_charbuf
);
256 file
->_ptr
= file
->_base
;
260 /*********************************************************************
263 MSVCRT_FILE
*__p__iob(void)
265 return &MSVCRT__iob
[0];
268 /*********************************************************************
271 int _access(const char *filename
, int mode
)
273 DWORD attr
= GetFileAttributesA(filename
);
275 TRACE("(%s,%d) %ld\n",filename
,mode
,attr
);
277 if (!filename
|| attr
== 0xffffffff)
279 MSVCRT__set_errno(GetLastError());
282 if ((attr
& FILE_ATTRIBUTE_READONLY
) && (mode
& MSVCRT_W_OK
))
284 MSVCRT__set_errno(ERROR_ACCESS_DENIED
);
290 /*********************************************************************
291 * _waccess (MSVCRT.@)
293 int _waccess(const WCHAR
*filename
, int mode
)
295 DWORD attr
= GetFileAttributesW(filename
);
297 TRACE("(%s,%d) %ld\n",debugstr_w(filename
),mode
,attr
);
299 if (!filename
|| attr
== 0xffffffff)
301 MSVCRT__set_errno(GetLastError());
304 if ((attr
& FILE_ATTRIBUTE_READONLY
) && (mode
& MSVCRT_W_OK
))
306 MSVCRT__set_errno(ERROR_ACCESS_DENIED
);
312 /*********************************************************************
315 int _chmod(const char *path
, int flags
)
317 DWORD oldFlags
= GetFileAttributesA(path
);
319 if (oldFlags
!= 0x0FFFFFFFF)
321 DWORD newFlags
= (flags
& _S_IWRITE
)? oldFlags
& ~FILE_ATTRIBUTE_READONLY
:
322 oldFlags
| FILE_ATTRIBUTE_READONLY
;
324 if (newFlags
== oldFlags
|| SetFileAttributesA(path
, newFlags
))
327 MSVCRT__set_errno(GetLastError());
331 /*********************************************************************
334 int _wchmod(const WCHAR
*path
, int flags
)
336 DWORD oldFlags
= GetFileAttributesW(path
);
338 if (oldFlags
!= 0x0FFFFFFFF)
340 DWORD newFlags
= (flags
& _S_IWRITE
)? oldFlags
& ~FILE_ATTRIBUTE_READONLY
:
341 oldFlags
| FILE_ATTRIBUTE_READONLY
;
343 if (newFlags
== oldFlags
|| SetFileAttributesW(path
, newFlags
))
346 MSVCRT__set_errno(GetLastError());
350 /*********************************************************************
353 int _unlink(const char *path
)
355 TRACE("(%s)\n",path
);
356 if(DeleteFileA(path
))
358 TRACE("failed (%ld)\n",GetLastError());
359 MSVCRT__set_errno(GetLastError());
363 /*********************************************************************
364 * _wunlink (MSVCRT.@)
366 int _wunlink(const WCHAR
*path
)
368 TRACE("(%s)\n",debugstr_w(path
));
369 if(DeleteFileW(path
))
371 TRACE("failed (%ld)\n",GetLastError());
372 MSVCRT__set_errno(GetLastError());
376 /*********************************************************************
381 HANDLE hand
= msvcrt_fdtoh(fd
);
383 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
384 if (hand
== INVALID_HANDLE_VALUE
)
386 /* flush stdio buffers */
387 if(MSVCRT_files
[fd
]) {
388 if(MSVCRT_files
[fd
]->_flag
& MSVCRT__IOWRT
)
389 MSVCRT_fflush(MSVCRT_files
[fd
]);
391 if(MSVCRT_files
[fd
]->_flag
& MSVCRT__IOMYBUF
)
392 MSVCRT_free(MSVCRT_files
[fd
]->_base
);
395 /* Dont free std FILE*'s, they are not dynamic */
396 if (fd
> 2 && MSVCRT_files
[fd
])
397 MSVCRT_free(MSVCRT_files
[fd
]);
401 if (!CloseHandle(hand
))
403 WARN(":failed-last error (%ld)\n",GetLastError());
404 MSVCRT__set_errno(GetLastError());
407 if (MSVCRT_tempfiles
[fd
])
409 TRACE("deleting temporary file '%s'\n",MSVCRT_tempfiles
[fd
]);
410 _unlink(MSVCRT_tempfiles
[fd
]);
411 MSVCRT_free(MSVCRT_tempfiles
[fd
]);
412 MSVCRT_tempfiles
[fd
] = NULL
;
419 /*********************************************************************
424 HANDLE hand
= msvcrt_fdtoh(fd
);
426 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
427 if (hand
== INVALID_HANDLE_VALUE
)
430 if (!FlushFileBuffers(hand
))
432 if (GetLastError() == ERROR_INVALID_HANDLE
)
434 /* FlushFileBuffers fails for console handles
435 * so we ignore this error.
439 TRACE(":failed-last error (%ld)\n",GetLastError());
440 MSVCRT__set_errno(GetLastError());
447 /*********************************************************************
453 HANDLE hand
= msvcrt_fdtoh(fd
);
455 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
457 if (hand
== INVALID_HANDLE_VALUE
)
460 /* If we have a FILE* for this file, the EOF flag
461 * will be set by the read()/write() functions.
463 if (MSVCRT_files
[fd
])
464 return MSVCRT_flags
[fd
] & MSVCRT__IOEOF
;
466 /* Otherwise we do it the hard way */
467 curpos
= SetFilePointer(hand
, 0, NULL
, SEEK_CUR
);
468 endpos
= SetFilePointer(hand
, 0, NULL
, FILE_END
);
470 if (curpos
== endpos
)
473 SetFilePointer(hand
, curpos
, 0, FILE_BEGIN
);
477 /*********************************************************************
478 * _fcloseall (MSVCRT.@)
482 int num_closed
= 0, i
;
484 for (i
= 3; i
< MSVCRT_fdend
; i
++)
485 if (MSVCRT_handles
[i
] != INVALID_HANDLE_VALUE
)
491 TRACE(":closed (%d) handles\n",num_closed
);
495 /*********************************************************************
498 __int64
_lseeki64(int fd
, __int64 offset
, int whence
)
500 DWORD ret
, hoffset
= (DWORD
) (offset
>> 32);
501 HANDLE hand
= msvcrt_fdtoh(fd
);
503 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
504 if (hand
== INVALID_HANDLE_VALUE
)
507 if (whence
< 0 || whence
> 2)
509 *MSVCRT__errno() = MSVCRT_EINVAL
;
513 TRACE(":fd (%d) to 0x%08lx%08lx pos %s\n",
514 fd
,hoffset
,(long)offset
,
515 (whence
==SEEK_SET
)?"SEEK_SET":
516 (whence
==SEEK_CUR
)?"SEEK_CUR":
517 (whence
==SEEK_END
)?"SEEK_END":"UNKNOWN");
519 if (((ret
= SetFilePointer(hand
, (long)offset
, &hoffset
,
520 whence
)) != INVALID_SET_FILE_POINTER
) || !GetLastError())
522 if (MSVCRT_files
[fd
])
523 MSVCRT_files
[fd
]->_flag
&= ~MSVCRT__IOEOF
;
524 /* FIXME: What if we seek _to_ EOF - is EOF set? */
526 return ((__int64
)hoffset
<< 32) | ret
;
528 TRACE(":error-last error (%ld)\n",GetLastError());
529 if (MSVCRT_files
[fd
])
530 switch(GetLastError())
532 case ERROR_NEGATIVE_SEEK
:
533 case ERROR_SEEK_ON_DEVICE
:
534 MSVCRT__set_errno(GetLastError());
535 MSVCRT_files
[fd
]->_flag
|= MSVCRT__IOERR
;
543 /*********************************************************************
546 LONG
_lseek(int fd
, LONG offset
, int whence
)
548 return _lseeki64(fd
, offset
, whence
);
551 /*********************************************************************
552 * _locking (MSVCRT.@)
554 * This is untested; the underlying LockFile doesn't work yet.
556 int _locking(int fd
, int mode
, LONG nbytes
)
560 HANDLE hand
= msvcrt_fdtoh(fd
);
562 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
563 if (hand
== INVALID_HANDLE_VALUE
)
566 if (mode
< 0 || mode
> 4)
568 *MSVCRT__errno() = MSVCRT_EINVAL
;
572 TRACE(":fd (%d) by 0x%08lx mode %s\n",
573 fd
,nbytes
,(mode
==_LK_UNLCK
)?"_LK_UNLCK":
574 (mode
==_LK_LOCK
)?"_LK_LOCK":
575 (mode
==_LK_NBLCK
)?"_LK_NBLCK":
576 (mode
==_LK_RLCK
)?"_LK_RLCK":
577 (mode
==_LK_NBRLCK
)?"_LK_NBRLCK":
580 if ((cur_locn
= SetFilePointer(hand
, 0L, NULL
, SEEK_CUR
)) == 0xffffffff)
582 FIXME ("Seek failed\n");
583 *MSVCRT__errno() = MSVCRT_EINVAL
; /* FIXME */
586 if (mode
== _LK_LOCK
|| mode
== _LK_RLCK
)
589 ret
= 1; /* just to satisfy gcc */
592 ret
= LockFile(hand
, cur_locn
, 0L, nbytes
, 0L);
597 else if (mode
== _LK_UNLCK
)
598 ret
= UnlockFile(hand
, cur_locn
, 0L, nbytes
, 0L);
600 ret
= LockFile(hand
, cur_locn
, 0L, nbytes
, 0L);
601 /* FIXME - what about error settings? */
605 /*********************************************************************
608 void MSVCRT_rewind(MSVCRT_FILE
* file
)
610 TRACE(":file (%p) fd (%d)\n",file
,file
->_file
);
611 MSVCRT_fseek(file
, 0L, SEEK_SET
);
612 MSVCRT_clearerr(file
);
615 /*********************************************************************
618 MSVCRT_FILE
* _fdopen(int fd
, const char *mode
)
620 MSVCRT_FILE
* file
= msvcrt_alloc_fp(fd
);
622 TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd
,mode
,file
);
629 /*********************************************************************
630 * _wfdopen (MSVCRT.@)
632 MSVCRT_FILE
* _wfdopen(int fd
, const WCHAR
*mode
)
634 MSVCRT_FILE
* file
= msvcrt_alloc_fp(fd
);
636 TRACE(":fd (%d) mode (%s) FILE* (%p)\n",fd
,debugstr_w(mode
),file
);
643 /*********************************************************************
644 * _filelength (MSVCRT.@)
646 LONG
_filelength(int fd
)
648 LONG curPos
= _lseek(fd
, 0, SEEK_CUR
);
651 LONG endPos
= _lseek(fd
, 0, SEEK_END
);
654 if (endPos
!= curPos
)
655 _lseek(fd
, curPos
, SEEK_SET
);
662 /*********************************************************************
665 int _fileno(MSVCRT_FILE
* file
)
667 TRACE(":FILE* (%p) fd (%d)\n",file
,file
->_file
);
671 /*********************************************************************
672 * _flushall (MSVCRT.@)
676 int num_flushed
= 0, i
= 3;
678 while(i
< MSVCRT_fdend
)
679 if (MSVCRT_handles
[i
] != INVALID_HANDLE_VALUE
)
682 /* FIXME: flush, do not commit */
683 if (_commit(i
) == -1)
685 MSVCRT_files
[i
]->_flag
|= MSVCRT__IOERR
;
687 if(MSVCRT_files
[i
] && MSVCRT_files
[i
]->_flag
& MSVCRT__IOWRT
) {
688 MSVCRT_fflush(MSVCRT_files
[i
]);
693 TRACE(":flushed (%d) handles\n",num_flushed
);
697 /*********************************************************************
698 * _fstati64 (MSVCRT.@)
700 int _fstati64(int fd
, struct _stati64
* buf
)
703 BY_HANDLE_FILE_INFORMATION hfi
;
704 HANDLE hand
= msvcrt_fdtoh(fd
);
706 TRACE(":fd (%d) stat (%p)\n",fd
,buf
);
707 if (hand
== INVALID_HANDLE_VALUE
)
712 WARN(":failed-NULL buf\n");
713 MSVCRT__set_errno(ERROR_INVALID_PARAMETER
);
717 memset(&hfi
, 0, sizeof(hfi
));
718 memset(buf
, 0, sizeof(struct _stati64
));
719 if (!GetFileInformationByHandle(hand
, &hfi
))
721 WARN(":failed-last error (%ld)\n",GetLastError());
722 MSVCRT__set_errno(ERROR_INVALID_PARAMETER
);
725 FIXME(":dwFileAttributes = %ld, mode set to 0\n",hfi
.dwFileAttributes
);
726 buf
->st_nlink
= hfi
.nNumberOfLinks
;
727 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
728 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
730 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
731 buf
->st_mtime
= buf
->st_ctime
= dw
;
735 /*********************************************************************
738 int MSVCRT__fstat(int fd
, struct _stat
* buf
)
740 struct _stati64 bufi64
;
742 ret
= _fstati64(fd
, &bufi64
);
744 msvcrt_cp_from_stati64(&bufi64
, buf
);
748 /*********************************************************************
751 int _futime(int fd
, struct _utimbuf
*t
)
753 HANDLE hand
= msvcrt_fdtoh(fd
);
758 MSVCRT_time_t currTime
;
759 MSVCRT_time(&currTime
);
760 RtlSecondsSince1970ToTime(currTime
, (LARGE_INTEGER
*)&at
);
761 memcpy(&wt
, &at
, sizeof(wt
));
765 RtlSecondsSince1970ToTime(t
->actime
, (LARGE_INTEGER
*)&at
);
766 if (t
->actime
== t
->modtime
)
767 memcpy(&wt
, &at
, sizeof(wt
));
769 RtlSecondsSince1970ToTime(t
->modtime
, (LARGE_INTEGER
*)&wt
);
772 if (!SetFileTime(hand
, NULL
, &at
, &wt
))
774 MSVCRT__set_errno(GetLastError());
780 /*********************************************************************
781 * _get_osfhandle (MSVCRT.@)
783 long _get_osfhandle(int fd
)
785 HANDLE hand
= msvcrt_fdtoh(fd
);
786 HANDLE newhand
= hand
;
787 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
789 if (hand
!= INVALID_HANDLE_VALUE
)
791 /* FIXME: I'm not convinced that I should be copying the
792 * handle here - it may be leaked if the app doesn't
793 * close it (and the API docs dont say that it should)
794 * Not duplicating it means that it can't be inherited
795 * and so lcc's wedit doesn't cope when it passes it to
796 * child processes. I've an idea that it should either
797 * be copied by CreateProcess, or marked as inheritable
798 * when initialised, or maybe both? JG 21-9-00.
800 DuplicateHandle(GetCurrentProcess(),hand
,GetCurrentProcess(),
801 &newhand
,0,TRUE
,DUPLICATE_SAME_ACCESS
);
803 return (long)newhand
;
806 /*********************************************************************
811 HANDLE hand
= msvcrt_fdtoh(fd
);
813 TRACE(":fd (%d) handle (%p)\n",fd
,hand
);
814 if (hand
== INVALID_HANDLE_VALUE
)
817 return GetFileType(hand
) == FILE_TYPE_CHAR
? 1 : 0;
820 /*********************************************************************
823 char *_mktemp(char *pattern
)
826 char *retVal
= pattern
;
831 numX
= (*pattern
++ == 'X')? numX
+ 1 : 0;
835 id
= GetCurrentProcessId();
839 int tempNum
= id
/ 10;
840 *pattern
-- = id
- (tempNum
* 10) + '0';
846 if (GetFileAttributesA(retVal
) == 0xFFFFFFFF &&
847 GetLastError() == ERROR_FILE_NOT_FOUND
)
850 } while(letter
!= '|');
854 /*********************************************************************
855 * _wmktemp (MSVCRT.@)
857 WCHAR
*_wmktemp(WCHAR
*pattern
)
860 WCHAR
*retVal
= pattern
;
862 WCHAR letter
= (WCHAR
)L
'a';
865 numX
= (*pattern
++ == (WCHAR
)L
'X')? numX
+ 1 : 0;
869 id
= GetCurrentProcessId();
873 int tempNum
= id
/ 10;
874 *pattern
-- = id
- (tempNum
* 10) + (WCHAR
)L
'0';
880 if (GetFileAttributesW(retVal
) == 0xFFFFFFFF &&
881 GetLastError() == ERROR_FILE_NOT_FOUND
)
884 } while(letter
!= (WCHAR
)L
'|');
888 /*********************************************************************
891 int MSVCRT__sopen( const char *path
, int oflags
, int shflags
, ... )
895 DWORD access
= 0, creation
= 0;
899 SECURITY_ATTRIBUTES sa
;
902 TRACE(":file (%s) oflags: 0x%04x shflags: 0x%04x\n",
903 path
, oflags
, shflags
);
905 switch(oflags
& (_O_RDONLY
| _O_WRONLY
| _O_RDWR
))
908 access
|= GENERIC_READ
;
909 ioflag
|= MSVCRT__IOREAD
;
912 access
|= GENERIC_WRITE
;
913 ioflag
|= MSVCRT__IOWRT
;
916 access
|= GENERIC_WRITE
| GENERIC_READ
;
917 ioflag
|= MSVCRT__IORW
;
921 if (oflags
& _O_CREAT
)
923 va_start(ap
, shflags
);
924 pmode
= va_arg(ap
, int);
927 FIXME(": pmode 0x%04x ignored\n", pmode
);
929 if (oflags
& _O_EXCL
)
930 creation
= CREATE_NEW
;
931 else if (oflags
& _O_TRUNC
)
932 creation
= CREATE_ALWAYS
;
934 creation
= OPEN_ALWAYS
;
936 else /* no _O_CREAT */
938 if (oflags
& _O_TRUNC
)
939 creation
= TRUNCATE_EXISTING
;
941 creation
= OPEN_EXISTING
;
943 if (oflags
& _O_APPEND
)
944 ioflag
|= MSVCRT__IOAPPEND
;
947 oflags
|= _O_BINARY
; /* FIXME: Default to text */
949 if (oflags
& _O_TEXT
)
951 /* Dont warn when writing */
952 if (ioflag
& GENERIC_READ
)
953 FIXME(":TEXT node not implemented\n");
963 sharing
= FILE_SHARE_READ
;
966 sharing
= FILE_SHARE_WRITE
;
969 sharing
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
972 ERR( "Unhandled shflags 0x%x\n", shflags
);
976 if (oflags
& ~(_O_BINARY
|_O_TEXT
|_O_APPEND
|_O_TRUNC
|_O_EXCL
977 |_O_CREAT
|_O_RDWR
|_O_TEMPORARY
|_O_NOINHERIT
))
978 TRACE(":unsupported oflags 0x%04x\n",oflags
);
980 sa
.nLength
= sizeof( SECURITY_ATTRIBUTES
);
981 sa
.lpSecurityDescriptor
= NULL
;
982 sa
.bInheritHandle
= (oflags
& _O_NOINHERIT
) ? FALSE
: TRUE
;
984 hand
= CreateFileA(path
, access
, sharing
,
985 &sa
, creation
, FILE_ATTRIBUTE_NORMAL
, 0);
987 if (hand
== INVALID_HANDLE_VALUE
) {
988 WARN(":failed-last error (%ld)\n",GetLastError());
989 MSVCRT__set_errno(GetLastError());
993 fd
= msvcrt_alloc_fd(hand
, ioflag
);
995 TRACE(":fd (%d) handle (%p)\n",fd
, hand
);
999 if (oflags
& _O_TEMPORARY
)
1000 MSVCRT_tempfiles
[fd
] = _strdup(path
);
1001 if (ioflag
& MSVCRT__IOAPPEND
)
1002 _lseek(fd
, 0, FILE_END
);
1008 /*********************************************************************
1009 * _wsopen (MSVCRT.@)
1011 int MSVCRT__wsopen( const WCHAR
* path
, int oflags
, int shflags
, ... )
1013 const unsigned int len
= strlenW(path
);
1014 char *patha
= MSVCRT_calloc(len
+ 1,1);
1018 va_start(ap
, shflags
);
1019 pmode
= va_arg(ap
, int);
1022 if (patha
&& WideCharToMultiByte(CP_ACP
,0,path
,len
,patha
,len
,NULL
,NULL
))
1024 int retval
= MSVCRT__sopen(patha
,oflags
,shflags
,pmode
);
1029 MSVCRT__set_errno(GetLastError());
1033 /*********************************************************************
1036 int _open( const char *path
, int flags
, ... )
1041 va_start(ap
, flags
);
1042 pmode
= va_arg(ap
, int);
1045 return MSVCRT__sopen( path
, flags
, _SH_DENYNO
, pmode
);
1048 /*********************************************************************
1051 int _wopen(const WCHAR
*path
,int flags
,...)
1053 const unsigned int len
= strlenW(path
);
1054 char *patha
= MSVCRT_calloc(len
+ 1,1);
1058 va_start(ap
, flags
);
1059 pmode
= va_arg(ap
, int);
1062 if (patha
&& WideCharToMultiByte(CP_ACP
,0,path
,len
,patha
,len
,NULL
,NULL
))
1064 int retval
= _open(patha
,flags
,pmode
);
1069 MSVCRT__set_errno(GetLastError());
1073 /*********************************************************************
1076 int _creat(const char *path
, int flags
)
1078 int usedFlags
= (flags
& _O_TEXT
)| _O_CREAT
| _O_WRONLY
| _O_TRUNC
;
1079 return _open(path
, usedFlags
);
1082 /*********************************************************************
1083 * _wcreat (MSVCRT.@)
1085 int _wcreat(const WCHAR
*path
, int flags
)
1087 int usedFlags
= (flags
& _O_TEXT
)| _O_CREAT
| _O_WRONLY
| _O_TRUNC
;
1088 return _wopen(path
, usedFlags
);
1091 /*********************************************************************
1092 * _open_osfhandle (MSVCRT.@)
1094 int _open_osfhandle(long hand
, int flags
)
1096 /* _O_RDONLY (0) always matches, so set the read flag*/
1097 /* FIXME: handle more flags */
1098 int fd
= msvcrt_alloc_fd((HANDLE
)hand
,flags
|MSVCRT__IOREAD
);
1099 TRACE(":handle (%ld) fd (%d) flags 0x%08x\n",hand
,fd
, flags
|MSVCRT__IOREAD
);
1103 /*********************************************************************
1108 int num_removed
= 0, i
;
1110 for (i
= 3; i
< MSVCRT_fdend
; i
++)
1111 if (MSVCRT_tempfiles
[i
])
1118 TRACE(":removed (%d) temp files\n",num_removed
);
1122 /*********************************************************************
1125 int _read(int fd
, void *buf
, unsigned int count
)
1128 HANDLE hand
= msvcrt_fdtoh(fd
);
1130 /* Dont trace small reads, it gets *very* annoying */
1132 TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd
,hand
,buf
,count
);
1133 if (hand
== INVALID_HANDLE_VALUE
)
1136 if (ReadFile(hand
, buf
, count
, &num_read
, NULL
))
1138 if (num_read
!= count
&& MSVCRT_files
[fd
])
1141 MSVCRT_flags
[fd
] |= MSVCRT__IOEOF
;
1143 MSVCRT_files[fd]->_flag |= MSVCRT__IOEOF;
1148 TRACE(":failed-last error (%ld)\n",GetLastError());
1149 if (MSVCRT_files
[fd
])
1150 MSVCRT_files
[fd
]->_flag
|= MSVCRT__IOERR
;
1154 /*********************************************************************
1157 int _getw(MSVCRT_FILE
* file
)
1160 if (_read(file
->_file
, &i
, sizeof(int)) != 1)
1165 /*********************************************************************
1166 * _setmode (MSVCRT.@)
1168 int _setmode(int fd
,int mode
)
1171 FIXME("fd (%d) mode (%d) TEXT not implemented\n",fd
,mode
);
1175 /*********************************************************************
1176 * _stati64 (MSVCRT.@)
1178 int _stati64(const char* path
, struct _stati64
* buf
)
1181 WIN32_FILE_ATTRIBUTE_DATA hfi
;
1182 unsigned short mode
= MSVCRT_S_IREAD
;
1185 TRACE(":file (%s) buf(%p)\n",path
,buf
);
1187 if (!GetFileAttributesExA(path
, GetFileExInfoStandard
, &hfi
))
1189 TRACE("failed (%ld)\n",GetLastError());
1190 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1194 memset(buf
,0,sizeof(struct _stati64
));
1196 /* FIXME: rdev isnt drive num,despite what the docs say-what is it?
1197 Bon 011120: This FIXME seems incorrect
1198 Also a letter as first char isn't enough to be classify
1201 if (isalpha(*path
)&& (*(path
+1)==':'))
1202 buf
->st_dev
= buf
->st_rdev
= toupper(*path
) - 'A'; /* drive num */
1204 buf
->st_dev
= buf
->st_rdev
= _getdrive() - 1;
1206 plen
= strlen(path
);
1208 /* Dir, or regular file? */
1209 if ((hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
1210 (path
[plen
-1] == '\\'))
1211 mode
|= (_S_IFDIR
| MSVCRT_S_IEXEC
);
1216 if (plen
> 6 && path
[plen
-4] == '.') /* shortest exe: "\x.exe" */
1218 unsigned int ext
= tolower(path
[plen
-1]) | (tolower(path
[plen
-2]) << 8) |
1219 (tolower(path
[plen
-3]) << 16);
1220 if (ext
== EXE
|| ext
== BAT
|| ext
== CMD
|| ext
== COM
)
1221 mode
|= MSVCRT_S_IEXEC
;
1225 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1226 mode
|= MSVCRT_S_IWRITE
;
1228 buf
->st_mode
= mode
;
1230 buf
->st_size
= ((__int64
)hfi
.nFileSizeHigh
<< 32) + hfi
.nFileSizeLow
;
1231 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
1233 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
1234 buf
->st_mtime
= buf
->st_ctime
= dw
;
1235 TRACE("%d %d 0x%08lx%08lx %ld %ld %ld\n", buf
->st_mode
,buf
->st_nlink
,
1236 (long)(buf
->st_size
>> 32),(long)buf
->st_size
,
1237 buf
->st_atime
,buf
->st_mtime
, buf
->st_ctime
);
1241 /*********************************************************************
1244 int MSVCRT__stat(const char* path
, struct _stat
* buf
)
1246 struct _stati64 bufi64
;
1248 ret
= _stati64( path
, &bufi64
);
1250 msvcrt_cp_from_stati64(&bufi64
, buf
);
1254 /*********************************************************************
1257 int _wstat(const WCHAR
* path
, struct _stat
* buf
)
1260 WIN32_FILE_ATTRIBUTE_DATA hfi
;
1261 unsigned short mode
= MSVCRT_S_IREAD
;
1264 TRACE(":file (%s) buf(%p)\n",debugstr_w(path
),buf
);
1266 if (!GetFileAttributesExW(path
, GetFileExInfoStandard
, &hfi
))
1268 TRACE("failed (%ld)\n",GetLastError());
1269 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1273 memset(buf
,0,sizeof(struct _stat
));
1275 /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */
1276 if (MSVCRT_iswalpha(*path
))
1277 buf
->st_dev
= buf
->st_rdev
= toupperW(*path
- (WCHAR
)L
'A'); /* drive num */
1279 buf
->st_dev
= buf
->st_rdev
= _getdrive() - 1;
1281 plen
= strlenW(path
);
1283 /* Dir, or regular file? */
1284 if ((hfi
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ||
1285 (path
[plen
-1] == (WCHAR
)L
'\\'))
1286 mode
|= (_S_IFDIR
| MSVCRT_S_IEXEC
);
1291 if (plen
> 6 && path
[plen
-4] == (WCHAR
)L
'.') /* shortest exe: "\x.exe" */
1293 ULONGLONG ext
= tolowerW(path
[plen
-1]) | (tolowerW(path
[plen
-2]) << 16) |
1294 ((ULONGLONG
)tolowerW(path
[plen
-3]) << 32);
1295 if (ext
== WCEXE
|| ext
== WCBAT
|| ext
== WCCMD
|| ext
== WCCOM
)
1296 mode
|= MSVCRT_S_IEXEC
;
1300 if (!(hfi
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1301 mode
|= MSVCRT_S_IWRITE
;
1303 buf
->st_mode
= mode
;
1305 buf
->st_size
= hfi
.nFileSizeLow
;
1306 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastAccessTime
, &dw
);
1308 RtlTimeToSecondsSince1970((LARGE_INTEGER
*)&hfi
.ftLastWriteTime
, &dw
);
1309 buf
->st_mtime
= buf
->st_ctime
= dw
;
1310 TRACE("\n%d %d %d %ld %ld %ld\n", buf
->st_mode
,buf
->st_nlink
,buf
->st_size
,
1311 buf
->st_atime
,buf
->st_mtime
, buf
->st_ctime
);
1315 /*********************************************************************
1320 return _lseek(fd
, 0, SEEK_CUR
);
1323 /*********************************************************************
1324 * _tempnam (MSVCRT.@)
1326 char *_tempnam(const char *dir
, const char *prefix
)
1328 char tmpbuf
[MAX_PATH
];
1330 TRACE("dir (%s) prefix (%s)\n",dir
,prefix
);
1331 if (GetTempFileNameA(dir
,prefix
,0,tmpbuf
))
1333 TRACE("got name (%s)\n",tmpbuf
);
1334 return _strdup(tmpbuf
);
1336 TRACE("failed (%ld)\n",GetLastError());
1340 /*********************************************************************
1341 * _wtempnam (MSVCRT.@)
1343 WCHAR
*_wtempnam(const WCHAR
*dir
, const WCHAR
*prefix
)
1345 WCHAR tmpbuf
[MAX_PATH
];
1347 TRACE("dir (%s) prefix (%s)\n",debugstr_w(dir
),debugstr_w(prefix
));
1348 if (GetTempFileNameW(dir
,prefix
,0,tmpbuf
))
1350 TRACE("got name (%s)\n",debugstr_w(tmpbuf
));
1351 return _wcsdup(tmpbuf
);
1353 TRACE("failed (%ld)\n",GetLastError());
1357 /*********************************************************************
1360 int _umask(int umask
)
1362 int old_umask
= MSVCRT_umask
;
1363 TRACE("(%d)\n",umask
);
1364 MSVCRT_umask
= umask
;
1368 /*********************************************************************
1371 int _utime(const char* path
, struct _utimbuf
*t
)
1373 int fd
= _open(path
, _O_WRONLY
| _O_BINARY
);
1377 int retVal
= _futime(fd
, t
);
1384 /*********************************************************************
1385 * _wutime (MSVCRT.@)
1387 int _wutime(const WCHAR
* path
, struct _utimbuf
*t
)
1389 int fd
= _wopen(path
, _O_WRONLY
| _O_BINARY
);
1393 int retVal
= _futime(fd
, t
);
1400 /*********************************************************************
1403 int _write(int fd
, const void* buf
, unsigned int count
)
1406 HANDLE hand
= msvcrt_fdtoh(fd
);
1408 /* Dont trace small writes, it gets *very* annoying */
1411 TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd
,hand
,buf
,count
);
1413 if (hand
== INVALID_HANDLE_VALUE
)
1416 /* If appending, go to EOF */
1417 if (MSVCRT_flags
[fd
] & MSVCRT__IOAPPEND
)
1418 _lseek(fd
, 0, FILE_END
);
1420 if (WriteFile(hand
, buf
, count
, &num_written
, NULL
)
1421 && (num_written
== count
))
1424 TRACE(":failed-last error (%ld)\n",GetLastError());
1425 if (MSVCRT_files
[fd
])
1426 MSVCRT_files
[fd
]->_flag
|= MSVCRT__IOERR
;
1431 /*********************************************************************
1434 int _putw(int val
, MSVCRT_FILE
* file
)
1436 return _write(file
->_file
, &val
, sizeof(val
)) == 1? val
: MSVCRT_EOF
;
1439 /*********************************************************************
1440 * clearerr (MSVCRT.@)
1442 void MSVCRT_clearerr(MSVCRT_FILE
* file
)
1444 TRACE(":file (%p) fd (%d)\n",file
,file
->_file
);
1445 file
->_flag
&= ~(MSVCRT__IOERR
| MSVCRT__IOEOF
);
1448 /*********************************************************************
1451 int MSVCRT_fclose(MSVCRT_FILE
* file
)
1454 r
=_close(file
->_file
);
1455 return ((r
==MSVCRT_EOF
) || (file
->_flag
& MSVCRT__IOERR
) ? MSVCRT_EOF
: 0);
1458 /*********************************************************************
1461 int MSVCRT_feof(MSVCRT_FILE
* file
)
1463 return file
->_flag
& MSVCRT__IOEOF
;
1466 /*********************************************************************
1469 int MSVCRT_ferror(MSVCRT_FILE
* file
)
1471 return file
->_flag
& MSVCRT__IOERR
;
1474 /*********************************************************************
1477 int MSVCRT_fflush(MSVCRT_FILE
* file
)
1483 int res
=msvcrt_flush_buffer(file
);
1488 /*********************************************************************
1491 int MSVCRT_fgetc(MSVCRT_FILE
* file
)
1495 return *(unsigned char *)file
->_ptr
++;
1497 return _filbuf(file
);
1501 /*********************************************************************
1502 * _fgetchar (MSVCRT.@)
1506 return MSVCRT_fgetc(MSVCRT_stdin
);
1509 /*********************************************************************
1510 * _filbuf (MSVCRT.@)
1512 int _filbuf(MSVCRT_FILE
* file
)
1515 /* Allocate buffer if needed */
1516 if(file
->_bufsiz
== 0 && !(file
->_flag
& MSVCRT__IONBF
) ) {
1517 msvcrt_alloc_buffer(file
);
1519 if(!(file
->_flag
& MSVCRT__IOREAD
)) {
1520 if(file
->_flag
& MSVCRT__IORW
) {
1521 file
->_flag
|= MSVCRT__IOREAD
;
1526 if(file
->_flag
& MSVCRT__IONBF
) {
1528 if (_read(file
->_file
,&c
,1) != 1) {
1529 file
->_flag
|= MSVCRT__IOEOF
;
1534 file
->_cnt
= _read(file
->_file
, file
->_base
, file
->_bufsiz
);
1535 if(file
->_cnt
<0) file
->_cnt
= 0;
1537 file
->_flag
|= MSVCRT__IOEOF
;
1541 file
->_ptr
= file
->_base
+1;
1542 return *(unsigned char *)file
->_base
;
1546 /*********************************************************************
1547 * fgetpos (MSVCRT.@)
1549 int MSVCRT_fgetpos(MSVCRT_FILE
* file
, MSVCRT_fpos_t
*pos
)
1551 *pos
= MSVCRT_ftell(file
);
1552 return (*pos
== -1? -1 : 0);
1555 /*********************************************************************
1558 char *MSVCRT_fgets(char *s
, int size
, MSVCRT_FILE
* file
)
1561 char * buf_start
= s
;
1563 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
1564 file
,file
->_file
,s
,size
);
1566 for(cc
= MSVCRT_fgetc(file
); cc
!= MSVCRT_EOF
&& cc
!= '\n';
1567 cc
= MSVCRT_fgetc(file
))
1570 if (--size
<= 0) break;
1573 if ((cc
== MSVCRT_EOF
) && (s
== buf_start
)) /* If nothing read, return 0*/
1575 TRACE(":nothing read\n");
1582 TRACE(":got '%s'\n", buf_start
);
1586 /*********************************************************************
1589 MSVCRT_wint_t
MSVCRT_fgetwc(MSVCRT_FILE
* file
)
1592 if (_read(file
->_file
, &wc
, sizeof(wc
)) != sizeof(wc
))
1597 /*********************************************************************
1600 MSVCRT_wint_t
MSVCRT_getwc(MSVCRT_FILE
* file
)
1602 return MSVCRT_fgetwc(file
);
1605 /*********************************************************************
1606 * _fgetwchar (MSVCRT.@)
1608 MSVCRT_wint_t
_fgetwchar(void)
1610 return MSVCRT_fgetwc(MSVCRT_stdin
);
1613 /*********************************************************************
1614 * getwchar (MSVCRT.@)
1616 MSVCRT_wint_t
MSVCRT_getwchar(void)
1618 return _fgetwchar();
1621 /*********************************************************************
1624 WCHAR
*MSVCRT_fgetws(WCHAR
*s
, int size
, MSVCRT_FILE
* file
)
1627 WCHAR
* buf_start
= s
;
1629 TRACE(":file(%p) fd (%d) str (%p) len (%d)\n",
1630 file
,file
->_file
,s
,size
);
1632 for(cc
= MSVCRT_fgetwc(file
); cc
!= MSVCRT_WEOF
&& cc
!= L
'\n';
1633 cc
= MSVCRT_fgetwc(file
))
1636 if (--size
<= 0) break;
1639 if ((cc
== MSVCRT_EOF
) && (s
== buf_start
)) /* If nothing read, return 0*/
1641 TRACE(":nothing read\n");
1648 /* TRACE(":got '%s'\n", buf_start); */
1653 /*********************************************************************
1656 MSVCRT_wint_t
MSVCRT_fputwc(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
1659 if (MSVCRT_fwrite( &mwc
, sizeof(mwc
), 1, file
) != 1)
1664 /*********************************************************************
1665 * _fputwchar (MSVCRT.@)
1667 MSVCRT_wint_t
_fputwchar(MSVCRT_wint_t wc
)
1669 return MSVCRT_fputwc(wc
, MSVCRT_stdout
);
1672 /*********************************************************************
1675 MSVCRT_FILE
* MSVCRT_fopen(const char *path
, const char *mode
)
1678 int flags
= 0, plus
= 0, fd
;
1679 const char* search
= mode
;
1681 TRACE("(%s,%s)\n",path
,mode
);
1684 if (*search
++ == '+')
1687 /* map mode string to open() flags. "man fopen" for possibilities. */
1691 flags
= (plus
? _O_RDWR
: _O_RDONLY
);
1694 flags
= _O_CREAT
| _O_TRUNC
| (plus
? _O_RDWR
: _O_WRONLY
);
1697 flags
= _O_CREAT
| _O_APPEND
| (plus
? _O_RDWR
: _O_WRONLY
);
1712 flags
&= ~_O_BINARY
;
1717 FIXME(":unknown flag %c not supported\n",mode
[-1]);
1720 fd
= _open(path
, flags
);
1725 file
= msvcrt_alloc_fp(fd
);
1726 TRACE(":got (%p)\n",file
);
1733 /*********************************************************************
1734 * _wfopen (MSVCRT.@)
1736 MSVCRT_FILE
*_wfopen(const WCHAR
*path
, const WCHAR
*mode
)
1738 const unsigned int plen
= strlenW(path
), mlen
= strlenW(mode
);
1739 char *patha
= MSVCRT_calloc(plen
+ 1, 1);
1740 char *modea
= MSVCRT_calloc(mlen
+ 1, 1);
1742 TRACE("(%s,%s)\n",debugstr_w(path
),debugstr_w(mode
));
1744 if (patha
&& modea
&&
1745 WideCharToMultiByte(CP_ACP
,0,path
,plen
,patha
,plen
,NULL
,NULL
) &&
1746 WideCharToMultiByte(CP_ACP
,0,mode
,mlen
,modea
,mlen
,NULL
,NULL
))
1748 MSVCRT_FILE
*retval
= MSVCRT_fopen(patha
,modea
);
1754 MSVCRT__set_errno(GetLastError());
1758 /*********************************************************************
1759 * _fsopen (MSVCRT.@)
1761 MSVCRT_FILE
* _fsopen(const char *path
, const char *mode
, int share
)
1763 FIXME(":(%s,%s,%d),ignoring share mode!\n",path
,mode
,share
);
1764 return MSVCRT_fopen(path
,mode
);
1767 /*********************************************************************
1768 * _wfsopen (MSVCRT.@)
1770 MSVCRT_FILE
* _wfsopen(const WCHAR
*path
, const WCHAR
*mode
, int share
)
1772 FIXME(":(%s,%s,%d),ignoring share mode!\n",
1773 debugstr_w(path
),debugstr_w(mode
),share
);
1774 return _wfopen(path
,mode
);
1777 /*********************************************************************
1780 int MSVCRT_fputc(int c
, MSVCRT_FILE
* file
)
1787 return _flsbuf(c
, file
);
1791 /*********************************************************************
1792 * _flsbuf (MSVCRT.@)
1794 int _flsbuf(int c
, MSVCRT_FILE
* file
)
1796 /* Flush output buffer */
1797 if(file
->_bufsiz
== 0 && !(file
->_flag
& MSVCRT__IONBF
)) {
1798 msvcrt_alloc_buffer(file
);
1800 if(!(file
->_flag
& MSVCRT__IOWRT
)) {
1801 if(file
->_flag
& MSVCRT__IORW
) {
1802 file
->_flag
|= MSVCRT__IOWRT
;
1808 int res
=msvcrt_flush_buffer(file
);
1809 return res
?res
: MSVCRT_fputc(c
, file
);
1812 return _write(file
->_file
, &cc
, 1) == 1? c
: MSVCRT_EOF
;
1816 /*********************************************************************
1817 * _fputchar (MSVCRT.@)
1819 int _fputchar(int c
)
1821 return MSVCRT_fputc(c
, MSVCRT_stdout
);
1824 /*********************************************************************
1827 MSVCRT_size_t
MSVCRT_fread(void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
1828 { MSVCRT_size_t rcnt
=size
* nmemb
;
1829 MSVCRT_size_t read
=0;
1831 /* first buffered data */
1833 int pcnt
= (rcnt
>file
->_cnt
)? file
->_cnt
:rcnt
;
1834 memcpy(ptr
, file
->_ptr
, pcnt
);
1839 ptr
= (char*)ptr
+ pcnt
;
1840 } else if(!(file
->_flag
& MSVCRT__IOREAD
)) {
1841 if(file
->_flag
& MSVCRT__IORW
) {
1842 file
->_flag
|= MSVCRT__IOREAD
;
1846 if(rcnt
) pread
= _read(file
->_file
,ptr
, rcnt
);
1847 if (MSVCRT_flags
[file
->_file
] & MSVCRT__IOEOF
)
1848 /* expose feof condition in the flags
1849 MFC tests file->_flag for feof, and doesn't not call feof())
1851 file
->_flag
|= MSVCRT__IOEOF
;
1858 /*********************************************************************
1859 * freopen (MSVCRT.@)
1862 MSVCRT_FILE
* MSVCRT_freopen(const char *path
, const char *mode
,MSVCRT_FILE
* file
)
1864 MSVCRT_FILE
* newfile
;
1867 TRACE(":path (%p) mode (%s) file (%p) fd (%d)\n",path
,mode
,file
,file
->_file
);
1868 if (!file
|| ((fd
= file
->_file
) < 0) || fd
> MSVCRT_fdend
)
1874 FIXME(":reopen on user file not implemented!\n");
1875 MSVCRT__set_errno(ERROR_CALL_NOT_IMPLEMENTED
);
1878 if(MSVCRT_fclose(file
))
1880 return MSVCRT_fopen(path
, mode
);
1883 /* first, create the new file */
1884 if ((newfile
= MSVCRT_fopen(path
,mode
)) == NULL
)
1887 if (fd
< 3 && SetStdHandle(fd
== 0 ? STD_INPUT_HANDLE
:
1888 (fd
== 1? STD_OUTPUT_HANDLE
: STD_ERROR_HANDLE
),
1889 MSVCRT_handles
[newfile
->_file
]))
1891 /* Redirecting std handle to file , copy over.. */
1892 MSVCRT_handles
[fd
] = MSVCRT_handles
[newfile
->_file
];
1893 MSVCRT_flags
[fd
] = MSVCRT_flags
[newfile
->_file
];
1894 memcpy(&MSVCRT__iob
[fd
], newfile
, sizeof (MSVCRT_FILE
));
1895 MSVCRT__iob
[fd
]._file
= fd
;
1896 /* And free up the resources allocated by fopen, but
1897 * not the HANDLE we copied. */
1898 MSVCRT_free(MSVCRT_files
[fd
]);
1899 msvcrt_free_fd(newfile
->_file
);
1900 return &MSVCRT__iob
[fd
];
1903 WARN(":failed-last error (%ld)\n",GetLastError());
1904 MSVCRT_fclose(newfile
);
1905 MSVCRT__set_errno(GetLastError());
1909 /*********************************************************************
1910 * fsetpos (MSVCRT.@)
1912 int MSVCRT_fsetpos(MSVCRT_FILE
* file
, MSVCRT_fpos_t
*pos
)
1914 return _lseek(file
->_file
,*pos
,SEEK_SET
);
1917 /*********************************************************************
1920 int MSVCRT_fseek(MSVCRT_FILE
* file
, long offset
, int whence
)
1922 /* Flush output if needed */
1923 if(file
->_flag
& MSVCRT__IOWRT
)
1924 msvcrt_flush_buffer(file
);
1926 if(whence
== SEEK_CUR
&& file
->_flag
& MSVCRT__IOREAD
) {
1927 offset
-= file
->_cnt
;
1929 /* Discard buffered input */
1931 file
->_ptr
= file
->_base
;
1932 /* Reset direction of i/o */
1933 if(file
->_flag
& MSVCRT__IORW
) {
1934 file
->_flag
&= ~(MSVCRT__IOREAD
|MSVCRT__IOWRT
);
1936 return (_lseek(file
->_file
,offset
,whence
) == -1)?-1:0;
1939 /*********************************************************************
1942 LONG
MSVCRT_ftell(MSVCRT_FILE
* file
)
1947 if( file
->_flag
& MSVCRT__IOWRT
) {
1948 off
= file
->_ptr
- file
->_base
;
1953 pos
= _tell(file
->_file
);
1954 if(pos
== -1) return pos
;
1958 /*********************************************************************
1961 MSVCRT_size_t
MSVCRT_fwrite(const void *ptr
, MSVCRT_size_t size
, MSVCRT_size_t nmemb
, MSVCRT_FILE
* file
)
1963 MSVCRT_size_t wrcnt
=size
* nmemb
;
1968 int pcnt
=(file
->_cnt
>wrcnt
)? wrcnt
: file
->_cnt
;
1969 memcpy(file
->_ptr
, ptr
, pcnt
);
1974 ptr
= (char*)ptr
+ pcnt
;
1975 } else if(!(file
->_flag
& MSVCRT__IOWRT
)) {
1976 if(file
->_flag
& MSVCRT__IORW
) {
1977 file
->_flag
|= MSVCRT__IOWRT
;
1983 int res
=msvcrt_flush_buffer(file
);
1985 int pwritten
= _write(file
->_file
, ptr
, wrcnt
);
1986 if (pwritten
<= 0) pwritten
=0;
1987 written
+= pwritten
;
1990 return written
/ size
;
1993 /*********************************************************************
1996 int MSVCRT_fputs(const char *s
, MSVCRT_FILE
* file
)
1998 size_t len
= strlen(s
);
1999 return MSVCRT_fwrite(s
,sizeof(*s
),len
,file
) == len
? 0 : MSVCRT_EOF
;
2002 /*********************************************************************
2005 int MSVCRT_fputws(const WCHAR
*s
, MSVCRT_FILE
* file
)
2007 size_t len
= strlenW(s
);
2008 return MSVCRT_fwrite(s
,sizeof(*s
),len
,file
) == len
? 0 : MSVCRT_EOF
;
2011 /*********************************************************************
2012 * getchar (MSVCRT.@)
2014 int MSVCRT_getchar(void)
2016 return MSVCRT_fgetc(MSVCRT_stdin
);
2019 /*********************************************************************
2022 int MSVCRT_getc(MSVCRT_FILE
* file
)
2024 return MSVCRT_fgetc(file
);
2027 /*********************************************************************
2030 char *MSVCRT_gets(char *buf
)
2033 char * buf_start
= buf
;
2035 for(cc
= MSVCRT_fgetc(MSVCRT_stdin
); cc
!= MSVCRT_EOF
&& cc
!= '\n';
2036 cc
= MSVCRT_fgetc(MSVCRT_stdin
))
2037 if(cc
!= '\r') *buf
++ = (char)cc
;
2041 TRACE("got '%s'\n", buf_start
);
2045 /*********************************************************************
2048 WCHAR
* MSVCRT__getws(WCHAR
* buf
)
2053 for (cc
= MSVCRT_fgetwc(MSVCRT_stdin
); cc
!= MSVCRT_WEOF
&& cc
!= '\n';
2054 cc
= MSVCRT_fgetwc(MSVCRT_stdin
))
2061 TRACE("got '%s'\n", debugstr_w(ws
));
2065 /*********************************************************************
2068 int MSVCRT_putc(int c
, MSVCRT_FILE
* file
)
2070 return MSVCRT_fputc(c
, file
);
2073 /*********************************************************************
2074 * putchar (MSVCRT.@)
2076 int MSVCRT_putchar(int c
)
2078 return MSVCRT_fputc(c
, MSVCRT_stdout
);
2081 /*********************************************************************
2084 int MSVCRT_puts(const char *s
)
2086 size_t len
= strlen(s
);
2087 if (MSVCRT_fwrite(s
,sizeof(*s
),len
,MSVCRT_stdout
) != len
) return MSVCRT_EOF
;
2088 return MSVCRT_fwrite("\n",1,1,MSVCRT_stdout
) == 1 ? 0 : MSVCRT_EOF
;
2091 /*********************************************************************
2094 int _putws(const WCHAR
*s
)
2096 static const WCHAR nl
= '\n';
2097 size_t len
= strlenW(s
);
2098 if (MSVCRT_fwrite(s
,sizeof(*s
),len
,MSVCRT_stdout
) != len
) return MSVCRT_EOF
;
2099 return MSVCRT_fwrite(&nl
,sizeof(nl
),1,MSVCRT_stdout
) == 1 ? 0 : MSVCRT_EOF
;
2102 /*********************************************************************
2105 int MSVCRT_remove(const char *path
)
2107 TRACE("(%s)\n",path
);
2108 if (DeleteFileA(path
))
2110 TRACE(":failed (%ld)\n",GetLastError());
2111 MSVCRT__set_errno(GetLastError());
2115 /*********************************************************************
2116 * _wremove (MSVCRT.@)
2118 int _wremove(const WCHAR
*path
)
2120 TRACE("(%s)\n",debugstr_w(path
));
2121 if (DeleteFileW(path
))
2123 TRACE(":failed (%ld)\n",GetLastError());
2124 MSVCRT__set_errno(GetLastError());
2128 /*********************************************************************
2131 int MSVCRT_scanf(const char *format
, ...)
2136 va_start(valist
, format
);
2137 res
= MSVCRT_fscanf(MSVCRT_stdin
, format
, valist
);
2142 /*********************************************************************
2145 int MSVCRT_wscanf(const WCHAR
*format
, ...)
2150 va_start(valist
, format
);
2151 res
= MSVCRT_fwscanf(MSVCRT_stdin
, format
, valist
);
2156 /*********************************************************************
2159 int MSVCRT_rename(const char *oldpath
,const char *newpath
)
2161 TRACE(":from %s to %s\n",oldpath
,newpath
);
2162 if (MoveFileExA(oldpath
, newpath
, MOVEFILE_COPY_ALLOWED
))
2164 TRACE(":failed (%ld)\n",GetLastError());
2165 MSVCRT__set_errno(GetLastError());
2169 /*********************************************************************
2170 * _wrename (MSVCRT.@)
2172 int _wrename(const WCHAR
*oldpath
,const WCHAR
*newpath
)
2174 TRACE(":from %s to %s\n",debugstr_w(oldpath
),debugstr_w(newpath
));
2175 if (MoveFileExW(oldpath
, newpath
, MOVEFILE_COPY_ALLOWED
))
2177 TRACE(":failed (%ld)\n",GetLastError());
2178 MSVCRT__set_errno(GetLastError());
2182 /*********************************************************************
2183 * setvbuf (MSVCRT.@)
2185 int MSVCRT_setvbuf(MSVCRT_FILE
* file
, char *buf
, int mode
, MSVCRT_size_t size
)
2187 /* TODO: Check if file busy */
2189 MSVCRT_free(file
->_base
);
2193 if(mode
== MSVCRT__IOFBF
) {
2194 file
->_flag
&= ~MSVCRT__IONBF
;
2195 file
->_base
= file
->_ptr
= buf
;
2197 file
->_bufsiz
= size
;
2200 file
->_flag
|= MSVCRT__IONBF
;
2205 /*********************************************************************
2208 void MSVCRT_setbuf(MSVCRT_FILE
* file
, char *buf
)
2210 MSVCRT_setvbuf(file
, buf
, buf
? MSVCRT__IOFBF
: MSVCRT__IONBF
, MSVCRT_BUFSIZ
);
2213 /*********************************************************************
2216 char *MSVCRT_tmpnam(char *s
)
2218 char tmpbuf
[MAX_PATH
];
2219 char* prefix
= "TMP";
2220 if (!GetTempPathA(MAX_PATH
,tmpbuf
) ||
2221 !GetTempFileNameA(tmpbuf
,prefix
,0,MSVCRT_tmpname
))
2223 TRACE(":failed-last error (%ld)\n",GetLastError());
2226 TRACE(":got tmpnam %s\n",MSVCRT_tmpname
);
2231 /*********************************************************************
2232 * tmpfile (MSVCRT.@)
2234 MSVCRT_FILE
* MSVCRT_tmpfile(void)
2236 char *filename
= MSVCRT_tmpnam(NULL
);
2238 fd
= _open(filename
, _O_CREAT
| _O_BINARY
| _O_RDWR
| _O_TEMPORARY
);
2240 return msvcrt_alloc_fp(fd
);
2244 /*********************************************************************
2245 * vfprintf (MSVCRT.@)
2247 int MSVCRT_vfprintf(MSVCRT_FILE
* file
, const char *format
, va_list valist
)
2249 char buf
[2048], *mem
= buf
;
2250 int written
, resize
= sizeof(buf
), retval
;
2251 /* There are two conventions for vsnprintf failing:
2252 * Return -1 if we truncated, or
2253 * Return the number of bytes that would have been written
2254 * The code below handles both cases
2256 while ((written
= vsnprintf(mem
, resize
, format
, valist
)) == -1 ||
2259 resize
= (written
== -1 ? resize
* 2 : written
+ 1);
2262 if (!(mem
= (char *)MSVCRT_malloc(resize
)))
2265 retval
= MSVCRT_fwrite(mem
, sizeof(*mem
), written
, file
);
2271 /*********************************************************************
2272 * vfwprintf (MSVCRT.@)
2274 * Is final char included in written (then resize is too big) or not
2275 * (then we must test for equality too)?
2277 int MSVCRT_vfwprintf(MSVCRT_FILE
* file
, const WCHAR
*format
, va_list valist
)
2279 WCHAR buf
[2048], *mem
= buf
;
2280 int written
, resize
= sizeof(buf
) / sizeof(WCHAR
), retval
;
2281 /* See vfprintf comments */
2282 while ((written
= _vsnwprintf(mem
, resize
, format
, valist
)) == -1 ||
2285 resize
= (written
== -1 ? resize
* 2 : written
+ sizeof(WCHAR
));
2288 if (!(mem
= (WCHAR
*)MSVCRT_malloc(resize
*sizeof(*mem
))))
2291 retval
= MSVCRT_fwrite(mem
, sizeof(*mem
), written
, file
);
2297 /*********************************************************************
2298 * vprintf (MSVCRT.@)
2300 int MSVCRT_vprintf(const char *format
, va_list valist
)
2302 return MSVCRT_vfprintf(MSVCRT_stdout
,format
,valist
);
2305 /*********************************************************************
2306 * vwprintf (MSVCRT.@)
2308 int MSVCRT_vwprintf(const WCHAR
*format
, va_list valist
)
2310 return MSVCRT_vfwprintf(MSVCRT_stdout
,format
,valist
);
2313 /*********************************************************************
2314 * fprintf (MSVCRT.@)
2316 int MSVCRT_fprintf(MSVCRT_FILE
* file
, const char *format
, ...)
2320 va_start(valist
, format
);
2321 res
= MSVCRT_vfprintf(file
, format
, valist
);
2326 /*********************************************************************
2327 * fwprintf (MSVCRT.@)
2329 int MSVCRT_fwprintf(MSVCRT_FILE
* file
, const WCHAR
*format
, ...)
2333 va_start(valist
, format
);
2334 res
= MSVCRT_vfwprintf(file
, format
, valist
);
2339 /*********************************************************************
2342 int MSVCRT_printf(const char *format
, ...)
2346 va_start(valist
, format
);
2347 res
= MSVCRT_vfprintf(MSVCRT_stdout
, format
, valist
);
2352 /*********************************************************************
2355 int MSVCRT_ungetc(int c
, MSVCRT_FILE
* file
)
2357 if(file
->_bufsiz
== 0 && !(file
->_flag
& MSVCRT__IONBF
)) {
2358 msvcrt_alloc_buffer(file
);
2361 if(file
->_ptr
>file
->_base
) {
2370 /*********************************************************************
2371 * ungetwc (MSVCRT.@)
2373 MSVCRT_wint_t
MSVCRT_ungetwc(MSVCRT_wint_t wc
, MSVCRT_FILE
* file
)
2376 char * pp
= (char *)&mwc
;
2378 for(i
=sizeof(WCHAR
)-1;i
>=0;i
--) {
2379 if(pp
[i
] != MSVCRT_ungetc(pp
[i
],file
))
2385 /*********************************************************************
2386 * wprintf (MSVCRT.@)
2388 int MSVCRT_wprintf(const WCHAR
*format
, ...)
2392 va_start(valist
, format
);
2393 res
= MSVCRT_vwprintf(format
, valist
);