Reactos
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}