ReactOS 0.4.16-dev-737-g3368adc
osfinfo.cpp
Go to the documentation of this file.
1//
2// osfinfo.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines the functions used to control allocation, locking, and freeing of CRT
7// file handles.
8//
10
11
12
14{
15 __crt_unique_heap_ptr<__crt_lowio_handle_data> array(_calloc_crt_t(
18
19 if (!array)
20 return nullptr;
21
22 __crt_lowio_handle_data* const first = array.get();
24 for (auto it = first; it != last; ++it)
25 {
27 it->osfhnd = reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE);
28 it->startpos = 0;
29 it->osfile = 0;
30 it->textmode = __crt_lowio_text_mode::ansi;
31 it->_pipe_lookahead[0] = LF;
32 it->_pipe_lookahead[1] = LF;
33 it->_pipe_lookahead[2] = LF;
34 it->unicode = false;
35 it->utf8translations = false;
36 it->dbcsBufferUsed = false;
37 for (int i = 0; i < sizeof(it->mbBuffer); ++i)
38 {
39 it->mbBuffer[i] = '\0';
40 }
41 }
42
43 return array.detach();
44}
45
47{
48 if (!array)
49 return;
50
53 for (auto it = first; it != last; ++it)
54 {
55 DeleteCriticalSection(&it->lock);
56 }
57
59}
60
61// Ensures that a lowio handle data object has been created for file handle 'fh'.
62// The 'fh' must be less than the hard maximum, _NHANDLE_. If 'fh' is already
63// backed by a handle data object, this function has no effect. Otherwise, this
64// function extends the global arrays of handle data objects until 'fh' is backed
65// by a handle data object.
67{
68 _VALIDATE_RETURN_ERRCODE(static_cast<unsigned>(fh) < _NHANDLE_, EBADF);
69
70 errno_t status = 0;
71
73 __try
74 {
75 for (size_t i = 0; fh >= _nhandle; ++i)
76 {
77 if (__pioinfo[i])
78 {
79 continue;
80 }
81
83 if (!__pioinfo[i])
84 {
85 status = ENOMEM;
86 __leave;
87 }
88
90 }
91 }
93 {
95 }
97
98 return status;
99}
100
101
102
103// Allocates a CRT file handle. This function finds the first free entry in
104// the arrays of file objects and returns the index of that entry (that index
105// is the CRT file handle) to the caller. The FOPEN flag is set in the new
106// entry, to pevent multithreaded race conditions and deadlocks.
107//
108// Returns the CRT file handle on success; returns -1 on failure (e.g. if no
109// more file handles are available or if memory allocation is required but
110// fails).
111//
112// MULTITHREADING NOTE: If this function is successful and returns a CRT file
113// handle, the handle is locked when it is returned and the FOPEN flag has been
114// set. The caller must be sure to release the lock, and if the caller abandons
115// the file handle, it must clear the FOPEN flag to free the handle.
116extern "C" int __cdecl _alloc_osfhnd()
117{
119 int result = -1;
120 __try
121 {
122 // Search the arrays of file objects, in order, looking for the first
123 // free entry. The compound index of this free entry is the return
124 // value.
125 //
126 // The compound index of the file object entry *(__pioinfo[i] + j) is
127 // k = i * IOINFO_ARRAY_ELTS + j.
128 for (int i = 0; i < IOINFO_ARRAYS; ++i)
129 {
130 // If this __crt_lowio_handle_data array does not yet exist, create a new one:
131 if (!__pioinfo[i])
132 {
134 if (!__pioinfo[i])
135 __leave;
136
138
139 // The first element of the newly allocated array of handle data
140 // objects is our first free entry. Note that since we hold the
141 // index lock, no one else can allocate this handle.
142 int const fh = i * IOINFO_ARRAY_ELTS;
143
145 _osfile(fh) = FOPEN;
146 result = fh;
147 __leave;
148 }
149
150 // Otherwise, this file object array already exists. Search it looking
151 // for the first free entry:
154 for (__crt_lowio_handle_data* pio = first; pio != last; ++pio)
155 {
156 if (pio->osfile & FOPEN)
157 continue;
158
159 // Another thread may have grabbed this file handle out from
160 // under us while we waited for the lock. If so, continue on
161 // searching through the array.
162 //
163 // CRT_REFACTOR TODO: Resolve lowio synchronization issues.
164 EnterCriticalSection(&pio->lock);
165 if ((pio->osfile & FOPEN) != 0)
166 {
167 LeaveCriticalSection(&pio->lock);
168 continue;
169 }
170
171 // Otherwise, this entry is ours: we hold the lock, so we can
172 // initialize it and return its handle:
173 int const fh = i * IOINFO_ARRAY_ELTS + static_cast<int>(pio - first);
174 _osfile(fh) = FOPEN;
175 _osfhnd(fh) = reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE);
176 result = fh;
177 __leave;
178 }
179 }
180
181 // All entries are in use if we fall out of the loop. return -1 in this case (which result is already set to)
182 }
184 {
186 }
188 return result;
189}
190
191
192
193// Sets the Win32 HANDLE associated with the specified CRT file. Returns 0
194// on success; returns -1 and sets errno on failure.
195extern "C" int __cdecl __acrt_lowio_set_os_handle(int const fh, intptr_t const value)
196{
197 if (fh >= 0 &&
198 static_cast<unsigned>(fh) < static_cast<unsigned>(_nhandle) &&
199 _osfhnd(fh) == reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE))
200 {
202 {
203 HANDLE const handle_value = reinterpret_cast<HANDLE>(value);
204 switch (fh)
205 {
206 case 0: SetStdHandle(STD_INPUT_HANDLE, handle_value); break;
207 case 1: SetStdHandle(STD_OUTPUT_HANDLE, handle_value); break;
208 case 2: SetStdHandle(STD_ERROR_HANDLE, handle_value); break;
209 }
210 }
211
212 _osfhnd(fh) = value;
213 return 0 ;
214 }
215 else
216 {
217 errno = EBADF; // Bad handle
218 _doserrno = 0; // This is not an OS error
219 return -1;
220 }
221}
222
223
224
225// Marks the specified CRT file handle as free and available for allocation.
226// Returns 0 on success; returns -1 and sets errno on failure.
227extern "C" int __cdecl _free_osfhnd(int const fh)
228{
229 if (fh >= 0 &&
230 static_cast<unsigned>(fh) < static_cast<unsigned>(_nhandle) &&
231 (_osfile(fh) & FOPEN) &&
232 _osfhnd(fh) != reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE))
233 {
235 {
236 switch (fh)
237 {
238 case 0: SetStdHandle(STD_INPUT_HANDLE, nullptr); break;
239 case 1: SetStdHandle(STD_OUTPUT_HANDLE, nullptr); break;
240 case 2: SetStdHandle(STD_ERROR_HANDLE, nullptr); break;
241 }
242 }
243
244 _osfhnd(fh) = reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE);
245 return 0;
246 }
247 else
248 {
249 errno = EBADF; // Bad handle
250 _doserrno = 0; // This is not an OS error
251 return -1;
252 }
253}
254
255
256
257// Gets the Win32 HANDLE with which the given CRT file handle is associated.
258// On success, returns the Win32 HANDLE; on failure, returns -1 and sets errno.
259extern "C" intptr_t __cdecl _get_osfhandle(int const fh)
260{
262 _VALIDATE_CLEAR_OSSERR_RETURN(fh >= 0 && (unsigned)fh < (unsigned)_nhandle, EBADF, -1);
264
265 return _osfhnd(fh);
266}
267
268
269
270// Allocates a free CRT file handle and associates it with the provided Win32
271// HANDLE and sets its flags to the given flags. Returns the CRT file handle
272// on success; returns -1 on failure.
273extern "C" int __cdecl _open_osfhandle(intptr_t const osfhandle, int const source_flags)
274{
275 // Copy relevant source_flags from second parameter
276 unsigned char file_flags = 0;
277
278 if (source_flags & _O_APPEND)
279 file_flags |= FAPPEND;
280
281 if (source_flags & _O_TEXT)
282 file_flags |= FTEXT;
283
284 if (source_flags & _O_NOINHERIT)
285 file_flags |= FNOINHERIT;
286
287 // Find out what type of file (file/device/pipe):
288 DWORD const file_type = GetFileType(reinterpret_cast<HANDLE>(osfhandle));
290 {
292 return -1;
293 }
294
296 file_flags |= FDEV;
297
298 else if (file_type == FILE_TYPE_PIPE)
299 file_flags |= FPIPE;
300
301 // Attempt to allocate a CRT file handle:
302 int const fh = _alloc_osfhnd();
303 if (fh == -1)
304 {
305 errno = EMFILE; // Too many open files
306 _doserrno = 0L; // This is not an OS error
307 return -1;
308 }
309
310 bool success = false;
311 __try
312 {
313 // The file is open. now set the info in _osfhnd array:
314 __acrt_lowio_set_os_handle(fh, osfhandle);
315
316 file_flags |= FOPEN;
317
318 _osfile(fh) = file_flags;
320 _tm_unicode(fh) = false;
321
322 success = true;
323 }
325 {
326 if (!success)
327 {
328 _osfile(fh) &= ~FOPEN;
329 }
330
332 }
334 return fh;
335}
336
337
338
339// Acquires the lock associated with the given file handle.
340extern "C" void __cdecl __acrt_lowio_lock_fh(int const fh)
341{
343}
344
345
346
347// Releases the lock associated with the given file handle.
348extern "C" void __cdecl __acrt_lowio_unlock_fh(int const fh)
349{
351}
#define ENOMEM
Definition: acclib.h:84
#define EBADF
Definition: acclib.h:82
#define __cdecl
Definition: accygwin.h:79
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
#define _CHECK_FH_CLEAR_OSSERR_RETURN(handle, errorcode, retexpr)
@ __acrt_lowio_index_lock
#define _CORECRT_SPINCOUNT
void __cdecl __acrt_errno_map_os_error(unsigned long)
Definition: errno.cpp:91
BOOL WINAPI __acrt_InitializeCriticalSectionEx(_Out_ LPCRITICAL_SECTION critical_section, _In_ DWORD spin_count, _In_ DWORD flags)
#define _osfhnd(i)
int _nhandle
Definition: ioinit.cpp:34
#define IOINFO_ARRAYS
#define _NHANDLE_
@ _crt_console_app
_ACRTIMP _crt_app_type __cdecl _query_app_type(void)
__acrt_lock(__acrt_heap_lock)
#define _O_NOINHERIT
Definition: cabinet.h:45
#define _O_APPEND
Definition: cabinet.h:41
#define _O_TEXT
Definition: cabinet.h:50
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI DECLSPEC_HOTPATCH SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Definition: console.c:1213
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:269
#define EMFILE
Definition: errno.h:30
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FOPEN
const GLint * first
Definition: glext.h:5794
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
#define _doserrno
Definition: stdlib.h:131
#define _free_crt
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
#define _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, retexpr)
static UINT UINT last
Definition: font.c:45
static ioinfo ** __pioinfo
Definition: file.c:47
#define L(x)
Definition: ntvdm.h:50
int __cdecl _alloc_osfhnd()
Definition: osfinfo.cpp:116
void __cdecl __acrt_lowio_lock_fh(int const fh)
Definition: osfinfo.cpp:340
errno_t __cdecl __acrt_lowio_ensure_fh_exists(int const fh)
Definition: osfinfo.cpp:66
intptr_t __cdecl _get_osfhandle(int const fh)
Definition: osfinfo.cpp:259
void __cdecl __acrt_lowio_destroy_handle_array(__crt_lowio_handle_data *const array)
Definition: osfinfo.cpp:46
__crt_lowio_handle_data *__cdecl __acrt_lowio_create_handle_array()
Definition: osfinfo.cpp:13
int __cdecl __acrt_lowio_set_os_handle(int const fh, intptr_t const value)
Definition: osfinfo.cpp:195
int __cdecl _free_osfhnd(int const fh)
Definition: osfinfo.cpp:227
void __cdecl __acrt_lowio_unlock_fh(int const fh)
Definition: osfinfo.cpp:348
int __cdecl _open_osfhandle(intptr_t const osfhandle, int const source_flags)
Definition: osfinfo.cpp:273
#define __try
Definition: pseh2_64.h:172
#define __leave
Definition: pseh2_64.h:176
#define __endtry
Definition: pseh2_64.h:175
#define __finally
Definition: pseh2_64.h:174
#define errno
Definition: errno.h:18
#define _pioinfo(i)
Definition: internal.h:71
#define _osfile(i)
Definition: internal.h:72
#define IOINFO_ARRAY_ELTS
Definition: internal.h:69
#define _tm_unicode(i)
Definition: internal.h:75
#define _textmode(i)
Definition: internal.h:74
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
Definition: ps.c:97
rwlock_t lock
Definition: tcpcore.h:0
#define LF
Definition: telnetd.h:24
int errno_t
Definition: corecrt.h:615
Definition: pdh_main.c:94
int intptr_t
Definition: vcruntime.h:134
#define success(from, fromstr, to, tostr)
#define STD_OUTPUT_HANDLE
Definition: winbase.h:294
#define STD_INPUT_HANDLE
Definition: winbase.h:293
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#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
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)