Reactos
at listview 129 lines 4.2 kB view raw
1// 2// freopen.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Defines the freopen() family of functions, which is used to close a stream 7// and associate it with a new file (typically used for redirecting the 8// standard streams). 9// 10#include <corecrt_internal_stdio.h> 11 12 13 14// Reopens a stream to a new file. If the 'stream' is open, it is closed. The 15// new file, named by 'file_name', is then opened, and 'stream' is associated 16// with that file. The provided 'mode' and 'share_flag' are used when opening 17// the new file. The resulting FILE* is returned via 'result'. 18// 19// Returns 0 on success; returns an error code on failure. 20template <typename Character> 21static errno_t __cdecl common_freopen( 22 FILE** const result, 23 Character const* const file_name, 24 Character const* const mode, 25 __crt_stdio_stream const stream, 26 int const share_flag 27 ) throw() 28{ 29 typedef __acrt_stdio_char_traits<Character> stdio_traits; 30 31 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 32 *result = nullptr; 33 34 // C11 7.21.5.4/3: "If filename is a null pointer, the freopen function 35 // attempts to change the mode of the stream to that specified by mode, as 36 // if the name of the file currently associated with the stream had been 37 // used. It is implementation-defined which changes of mode are permitted 38 // (if any), and under what circumstances." 39 // 40 // In our implementation, we do not currently support changing the mode 41 // in this way. In the future, we might consider use of ReOpenFile to 42 // implement support for changing the mode. 43 _VALIDATE_RETURN_ERRCODE_NOEXC(file_name != nullptr, EBADF); 44 45 _VALIDATE_RETURN_ERRCODE(mode != nullptr, EINVAL); 46 _VALIDATE_RETURN_ERRCODE(stream.valid() , EINVAL); 47 48 // Just as in the common_fsopen function, we do not hard-validate empty 49 // 'file_name' strings in this function: 50 _VALIDATE_RETURN_ERRCODE_NOEXC(*file_name != 0, EINVAL); 51 52 errno_t return_value = 0; 53 54 _lock_file(stream.public_stream()); 55 __try 56 { 57 // If the stream is in use, try to close it, ignoring possible errors: 58 if (stream.is_in_use()) 59 _fclose_nolock(stream.public_stream()); 60 61 stream->_ptr = nullptr; 62 stream->_base = nullptr; 63 stream->_cnt = 0; 64 stream.unset_flags(-1); 65 66 // We may have called fclose above, which will deallocate the stream. 67 // We still hold the lock on the stream, though, so we can just reset 68 // the allocated flag to retain ownership. 69 stream.set_flags(_IOALLOCATED); 70 71 *result = stdio_traits::open_file(file_name, mode, share_flag, stream.public_stream()); 72 if (*result == nullptr) 73 { 74 stream.unset_flags(_IOALLOCATED); 75 return_value = errno; 76 } 77 } 78 __finally 79 { 80 _unlock_file(stream.public_stream()); 81 } 82 __endtry 83 84 return return_value; 85} 86 87 88 89extern "C" FILE* __cdecl freopen( 90 char const* const file_name, 91 char const* const mode, 92 FILE* const public_stream 93 ) 94{ 95 FILE* result_stream = nullptr; 96 common_freopen(&result_stream, file_name, mode, __crt_stdio_stream(public_stream), _SH_DENYNO); 97 return result_stream; 98} 99 100extern "C" errno_t __cdecl freopen_s( 101 FILE** const result, 102 char const* const file_name, 103 char const* const mode, 104 FILE* const public_stream 105 ) 106{ 107 return common_freopen(result, file_name, mode, __crt_stdio_stream(public_stream), _SH_SECURE); 108} 109 110extern "C" FILE* __cdecl _wfreopen( 111 wchar_t const* const file_name, 112 wchar_t const* const mode, 113 FILE* const public_stream 114 ) 115{ 116 FILE* result_stream = nullptr; 117 common_freopen(&result_stream, file_name, mode, __crt_stdio_stream(public_stream), _SH_DENYNO); 118 return result_stream; 119} 120 121extern "C" errno_t __cdecl _wfreopen_s( 122 FILE** const result, 123 wchar_t const* const file_name, 124 wchar_t const* const mode, 125 FILE* const public_stream 126 ) 127{ 128 return common_freopen(result, file_name, mode, __crt_stdio_stream(public_stream), _SH_SECURE); 129}