Reactos
at listview 140 lines 3.8 kB view raw
1// 2// fopen.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// Functions that open a file as a stdio stream. 7// 8#include <corecrt_internal_stdio.h> 9 10 11 12// Opens the file named by 'file_name' as a stdio stream. The 'mode' determines 13// the mode in which the file is opened and the 'share_flag' determines the 14// sharing mode. Supported modes are "r" (read), "w" (write), "a" (append), 15// "r+" (read and write), "w+" (open empty for read and write), and "a+" (read 16// and append). A "t" or "b" may be appended to the mode string to request text 17// or binary mode, respectively. 18// 19// Returns the FILE* for the newly opened stream on success; returns nullptr on 20// failure. 21template <typename Character> 22static FILE* __cdecl common_fsopen( 23 Character const* const file_name, 24 Character const* const mode, 25 int const share_flag 26 ) throw() 27{ 28 typedef __acrt_stdio_char_traits<Character> stdio_traits; 29 30 _VALIDATE_RETURN(file_name != nullptr, EINVAL, nullptr); 31 _VALIDATE_RETURN(mode != nullptr, EINVAL, nullptr); 32 _VALIDATE_RETURN(*mode != 0, EINVAL, nullptr); 33 34 // We deliberately don't hard-validate for empty strings here. All other 35 // invalid path strings are treated as runtime errors by the inner code 36 // in _open and openfile. This is also the appropriate treatment here. 37 // Since fopen is the primary access point for file strings it might be 38 // subjected to direct user input and thus must be robust to that rather 39 // than aborting. The CRT and OS do not provide any other path validator 40 // (because Win32 doesn't allow such things to exist in full generality). 41 _VALIDATE_RETURN_NOEXC(*file_name != 0, EINVAL, nullptr); 42 43 // Obtain a free stream. Note that the stream is returned locked: 44 __crt_stdio_stream stream = __acrt_stdio_allocate_stream(); 45 if (!stream.valid()) 46 { 47 errno = EMFILE; 48 return nullptr; 49 } 50 51 FILE* return_value = nullptr; 52 __try 53 { 54 return_value = stdio_traits::open_file(file_name, mode, share_flag, stream.public_stream()); 55 } 56 __finally 57 { 58 if (return_value == nullptr) 59 __acrt_stdio_free_stream(stream); 60 61 stream.unlock(); 62 } 63 __endtry 64 65 return return_value; 66} 67 68 69 70// A "secure" version of fsopen, which sets the result and returns zero on 71// success and an error code on failure. 72template <typename Character> 73static errno_t __cdecl common_fopen_s( 74 FILE** const result, 75 Character const* const file_name, 76 Character const* const mode 77 ) throw() 78{ 79 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 80 81 *result = common_fsopen(file_name, mode, _SH_SECURE); 82 if (*result == nullptr) 83 return errno; 84 85 return 0; 86} 87 88 89 90extern "C" FILE* __cdecl _fsopen( 91 char const* const file, 92 char const* const mode, 93 int const share_flag 94 ) 95{ 96 return common_fsopen(file, mode, share_flag); 97} 98 99extern "C" FILE* __cdecl fopen( 100 char const* const file, 101 char const* const mode 102 ) 103{ 104 return common_fsopen(file, mode, _SH_DENYNO); 105} 106 107extern "C" errno_t __cdecl fopen_s( 108 FILE** const result, 109 char const* const file, 110 char const* const mode 111 ) 112{ 113 return common_fopen_s(result, file, mode); 114} 115 116extern "C" FILE* __cdecl _wfsopen( 117 wchar_t const* const file, 118 wchar_t const* const mode, 119 int const share_flag 120 ) 121{ 122 return common_fsopen(file, mode, share_flag); 123} 124 125extern "C" FILE* __cdecl _wfopen( 126 wchar_t const* const file, 127 wchar_t const* const mode 128 ) 129{ 130 return common_fsopen(file, mode, _SH_DENYNO); 131} 132 133extern "C" errno_t __cdecl _wfopen_s( 134 FILE** const result, 135 wchar_t const* const file, 136 wchar_t const* const mode 137 ) 138{ 139 return common_fopen_s(result, file, mode); 140}