ReactOS 0.4.16-dev-979-g79f281e
ioinit.cpp
Go to the documentation of this file.
1//
2// ioinit.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines initialization and termination routines for the lowio library, along
7// with global data shared by most of the lowio library.
8//
11
12
13
14// This is a special static lowio file object referenced only by the safe access
15// functionality in the internal headers. It is used in certain stdio-level
16// functions to more gracefully handle a FILE with -1 as its lowio file id.
18{
19 { }, // lock
20 static_cast<intptr_t>(-1), // osfhnd
21 0, // startpos
22 FTEXT, // osfile
24 { LF, LF, LF }, // _pipe_lookahead
25}; }
26
27
28
29// This is the number of lowio file objects that have been allocated. This
30// includes both in-use and unused elements, since not all allocated files
31// are necessarily in use at any given time.
32//
33// This number is in the range of [IOINFO_ARRAY_ELTS, _NHANDLE_]
34extern "C" { int _nhandle = 0; }
35
36
37
38// This is the global array of file object arrays:
40
41
42
43static DWORD __cdecl get_std_handle_id(int const fh) throw()
44{
45 // Convert the CRT file handle to the OS file handle for the three
46 // standard streams:
47 switch (fh)
48 {
49 case 0: return STD_INPUT_HANDLE;
50 case 1: return STD_OUTPUT_HANDLE;
51 case 2: return STD_ERROR_HANDLE;
52 }
53
54 return STD_ERROR_HANDLE; // Unreachable, but the compiler can't know.
55}
56
57
58
60{
61 STARTUPINFOW startup_info;
62 GetStartupInfoW(&startup_info);
63
64 // First check and see if we inherited any file handles. If we didn't, then
65 // we don't have anything to initialize:
66 if (startup_info.cbReserved2 == 0 || startup_info.lpReserved2 == nullptr)
67 return;
68
69 // Get the number of inherited handles:
70 int const handle_count = *reinterpret_cast<UNALIGNED int*>(startup_info.lpReserved2);
71
72 // Compute the start of the passed file info and OS HANDLEs:
73 unsigned char* const first_file =
74 reinterpret_cast<unsigned char*>(startup_info.lpReserved2) + sizeof(int);
75
76 UNALIGNED intptr_t* const first_handle =
77 reinterpret_cast<UNALIGNED intptr_t*>(first_file + handle_count);
78
79 // Do not attempt to inherit more than the maximum number of supported handles:
80 int handles_to_inherit = handle_count < _NHANDLE_
81 ? handle_count
82 : _NHANDLE_;
83
84 // Attempt to allocate the required number of handles. If we fail for any
85 // reason, we'll inherit as many handles as we can:
86 __acrt_lowio_ensure_fh_exists(handles_to_inherit);
87 if (handles_to_inherit > _nhandle)
88 handles_to_inherit = _nhandle;
89
90 // Validate and copy the provided file information:
91 unsigned char* it_file = first_file;
92 UNALIGNED intptr_t* it_handle = first_handle;
93
94 for (int fh = 0; fh != handles_to_inherit; ++fh, ++it_file, ++it_handle)
95 {
96 HANDLE const real_handle = reinterpret_cast<HANDLE>(*it_handle);
97
98 // If the provided information does not appear to describe an open,
99 // valid file or device, skip it:
100 if (real_handle == INVALID_HANDLE_VALUE)
101 continue;
102
103 if (*it_handle == _NO_CONSOLE_FILENO)
104 continue;
105
106 if ((*it_file & FOPEN) == 0)
107 continue;
108
109 // GetFileType cannot be called for pipe handles since it may "hang" if
110 // there is a blocked read pending on the pipe in the parent.
111 if ((*it_file & FPIPE) == 0 && GetFileType(real_handle) == FILE_TYPE_UNKNOWN)
112 continue;
113
114 // Okay, the file looks valid:
115 __crt_lowio_handle_data* const pio = _pioinfo(fh);
116 pio->osfhnd = *it_handle;
117 pio->osfile = *it_file;
118 }
119}
120
121
122
124{
125 for (int fh = 0; fh != STDIO_HANDLES_COUNT; ++fh)
126 {
127 __crt_lowio_handle_data* const pio = _pioinfo(fh);
128
129 // If this handle was inherited from the parent process and initialized
130 // already, make sure it has the FTEXT flag and continue:
131 if (pio->osfhnd != reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE) &&
133 {
134 pio->osfile |= FTEXT;
135 continue;
136 }
137
138 // Regardless what happens next, the file will be treated as if it is
139 // open in text mode:
140 pio->osfile = FOPEN | FTEXT;
141
142 // This handle has not yet been initialized, so let's see if we can get
143 // the handle from the OS:
144 intptr_t const os_handle = reinterpret_cast<intptr_t>(GetStdHandle(get_std_handle_id(fh)));
145
146 bool const is_valid_handle =
147 os_handle != reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE) &&
148 os_handle != reinterpret_cast<intptr_t>(nullptr);
149
150 DWORD const handle_type = is_valid_handle
151 ? GetFileType(reinterpret_cast<HANDLE>(os_handle))
153
154
155 if (handle_type != FILE_TYPE_UNKNOWN)
156 {
157 // The file type is known, so we obtained a valid handle from the
158 // OS. Finish initializing the lowio file object for this handle,
159 // including the flag specifying whether this is a character device
160 // or a pipe:
161 pio->osfhnd = os_handle;
162
163 if ((handle_type & 0xff) == FILE_TYPE_CHAR)
164 pio->osfile |= FDEV;
165
166 else if ((handle_type & 0xff) == FILE_TYPE_PIPE)
167 pio->osfile |= FPIPE;
168 }
169 else
170 {
171 // We were unable to get the handles from the OS. For stdin, stdout,
172 // and stderr, if there is no valid OS handle, treat the CRT handle
173 // as being open in text mode on a device with _NO_CONSOLE_FILENO
174 // underlying it. We use this value instead of INVALID_HANDLE_VALUE
175 // to distinguish between a failure in opening a file and a program
176 // run without a console:
177 pio->osfile |= FDEV;
179
180 // Also update the corresponding stdio stream, unless stdio was
181 // already terminated:
182 if (__piob)
184 }
185 }
186}
187
188
189
190// Initializes the lowio library. This initialization comprises several steps:
191//
192// [1] An initial array of __crt_lowio_handle_data structures is allocated.
193//
194// [2] Inherited file handles are initialized. To do this, sthe startup info
195// is obtained from the OS, via the lpReserved2 member. The format of the
196// information is as follows:
197//
198// [Bytes 0 - 3] Integer value N, which is the number of handles that
199// are provided by the parent process.
200//
201// [Bytes 4 - N+3] The N osfile values.
202//
203// [Bytes N+4 - 5*N+3] The N OS HANDLE values, as DWORDs
204//
205// [3] Next, the first three lowio files (corresponding to stdin, stdout, and
206// stderr) are initialized as follows: If the value in osfhnd is
207// INVALID_HANDLE_VALUE, then we try to obtain a HANDLE from the OS. These
208// handles are forced to text mode, as standard input, output, and error
209// always start out in text mode.
210//
211// Notes:
212//
213// [1] In general, not all of the pased info from the parent process will
214// describe open handles. If, for example, only C handle 1 (stdout) and
215// C handle 6 are open in the parent, info for C handles 0 through 6 are
216// passed to the child. 0, 2, 3, 4, and 5 will not describe open handles.
217//
218// [2] Care is taken not to "overflow" the arrays of lowio file objects.
219//
220// [3] See the dospawn logic for the encoding of the file handle info to be
221// passed to a child process.
222//
223// This funtion returns 0 on success; -1 on failure.
225{
227 bool result = false;
228 __try
229 {
230 // First, allocate and initialize the initial array of lowio files:
232 __leave;
233
234 // Next, process and initialize all inherited file handles:
236
237 // Finally, initialize the stdio handles, if they were not inherited:
239 result = true;
240 }
242 {
244 }
246
247 return result;
248}
249
250
251
252// Shuts down the lowio library, freeing all allocated memory and destroying all
253// created synchronization objects.
254extern "C" bool __cdecl __acrt_uninitialize_lowio(bool const /* terminating */)
255{
256 for (size_t i = 0; i < IOINFO_ARRAYS; ++i)
257 {
258 if (!__pioinfo[i])
259 continue;
260
262 __pioinfo[i] = nullptr;
263 }
264
265 return true;
266}
#define __cdecl
Definition: accygwin.h:79
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_lowio_index_lock
void __cdecl __acrt_lowio_destroy_handle_array(_Pre_maybenull_ _Post_invalid_ _In_reads_opt_(IOINFO_ARRAY_ELTS) __crt_lowio_handle_data *_Array)
#define STDIO_HANDLES_COUNT
#define IOINFO_ARRAYS
_Check_return_opt_ errno_t __cdecl __acrt_lowio_ensure_fh_exists(_In_ int _FileHandle)
#define _NHANDLE_
__crt_stdio_stream_data ** __piob
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
__acrt_lock(__acrt_heap_lock)
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:269
VOID WINAPI GetStartupInfoW(IN LPSTARTUPINFOW lpStartupInfo)
Definition: proc.c:1279
BOOL is_valid_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType)
Definition: handle.c:96
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FOPEN
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
__crt_lowio_handle_data * __pioinfo[IOINFO_ARRAYS]
Definition: ioinit.cpp:39
int _nhandle
Definition: ioinit.cpp:34
bool __cdecl __acrt_initialize_lowio()
Definition: ioinit.cpp:224
static void initialize_stdio_handles_nolock()
Definition: ioinit.cpp:123
__crt_lowio_handle_data __badioinfo
Definition: ioinit.cpp:17
static void __cdecl initialize_inherited_file_handles_nolock()
Definition: ioinit.cpp:59
static DWORD __cdecl get_std_handle_id(int const fh)
Definition: ioinit.cpp:43
bool __cdecl __acrt_uninitialize_lowio(bool const)
Definition: ioinit.cpp:254
static struct file_entry * first_file
Definition: makefsdata.c:165
#define UNALIGNED
Definition: pecoff.h:227
#define __try
Definition: pseh2_64.h:188
#define __leave
Definition: pseh2_64.h:192
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
#define _NO_CONSOLE_FILENO
Definition: internal.h:92
#define _pioinfo(i)
Definition: internal.h:71
PBYTE lpReserved2
Definition: winbase.h:891
WORD cbReserved2
Definition: winbase.h:890
#define LF
Definition: telnetd.h:24
int intptr_t
Definition: vcruntime.h:134
#define STD_OUTPUT_HANDLE
Definition: winbase.h:294
#define STD_INPUT_HANDLE
Definition: winbase.h:293
#define FILE_TYPE_UNKNOWN
Definition: winbase.h:284
#define STD_ERROR_HANDLE
Definition: winbase.h:295
#define FILE_TYPE_CHAR
Definition: winbase.h:286
#define FILE_TYPE_PIPE
Definition: winbase.h:287