1 //
2 // corecrt_internal_lowio.h
3 //
4 //      Copyright (c) Microsoft Corporation.  All rights reserved.
5 //
6 // This internal header defines internal utilities for working with the lowio
7 // library.  This header may only be included in C++ translation units.
8 //
9 #pragma once
10 
11 #include <fcntl.h>
12 #include <io.h>
13 #include <corecrt_internal_traits.h>
14 #include <share.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 
18 _CRT_BEGIN_C_HEADER
19 
20 
21 
22 #define LF 10           /* line feed */
23 #define CR 13           /* carriage return */
24 #define CTRLZ 26        /* ctrl-z means eof for text */
25 
26 // Real default size for stdio buffers
27 #define _INTERNAL_BUFSIZ    4096
28 #define _SMALL_BUFSIZ       512
29 
30 /* Most significant Bit */
31 #define _msbit(c) ((c) & 0x80)
32 
33 /* Independent byte has most significant bit set to 0 */
34 #define  _utf8_is_independent(c)    (_msbit(c) == 0)
35 
36 /* Get no of trailing bytes from the lookup table */
37 //    1 for pattern 110xxxxx - 1 trailbyte
38 //    2 for pattern 1110xxxx - 2 trailbytes
39 //    3 for pattern 11110xxx - 3 trailbytes
40 //    0 for everything else, including invalid patterns.
41 // We return 0 for invalid patterns because we rely on MultiByteToWideChar to
42 // do the validations.
43 
44 extern char _lookuptrailbytes[256];
_utf8_no_of_trailbytes(const unsigned char c)45 __inline char _utf8_no_of_trailbytes(const unsigned char c)
46 {
47     return _lookuptrailbytes[c];
48 }
49 // It may be faster to just look up the bytes than to use the lookup table.
50 //__inline char _utf8_no_of_trailbytes(const unsigned char c)
51 //{
52 //    // ASCII range is a single character
53 //    if ((c & 0x80) == 0) return 0;
54 //    // Trail bytes 10xxxxxx aren't lead bytes
55 //    if ((c & 0x40) == 0) return 0;
56 //    // 110xxxxx is a 2 byte sequence (1 trail byte)
57 //    if ((c & 0x20) == 0) return 1;
58 //    // 1110xxxx is a 3 byte sequence (2 trail bytes)
59 //    if ((c & 0x10) == 0) return 2;
60 //    // 11110xxx is a 4 byte sequence (3 trail bytes)
61 //    if ((c & 0x08) == 0) return 3;
62 //    // Anything with 5 or more lead bits is illegal
63 //    return 0;
64 //}
65 
66 /* Any leadbyte will have the patterns 11000xxx 11100xxx or 11110xxx */
67 #define  _utf8_is_leadbyte(c)       (_utf8_no_of_trailbytes(static_cast<const unsigned char>(c)) != 0)
68 
69 enum class __crt_lowio_text_mode : char
70 {
71     ansi    = 0, // Regular text
72     utf8    = 1, // UTF-8 encoded
73     utf16le = 2, // UTF-16LE encoded
74 };
75 
76 // osfile flag values
77 enum : unsigned char
78 {
79     FOPEN      = 0x01, // file handle open
80     FEOFLAG    = 0x02, // end of file has been encountered
81     FCRLF      = 0x04, // CR-LF across read buffer (in text mode)
82     FPIPE      = 0x08, // file handle refers to a pipe
83     FNOINHERIT = 0x10, // file handle opened _O_NOINHERIT
84     FAPPEND    = 0x20, // file handle opened O_APPEND
85     FDEV       = 0x40, // file handle refers to device
86     FTEXT      = 0x80, // file handle is in text mode
87 };
88 
89 typedef char __crt_lowio_pipe_lookahead[3];
90 
91 /*
92  * Control structure for lowio file handles
93  */
94 struct __crt_lowio_handle_data
95 {
96     CRITICAL_SECTION           lock;
97     intptr_t                   osfhnd;          // underlying OS file HANDLE
98     __int64                    startpos;        // File position that matches buffer start
99     unsigned char              osfile;          // Attributes of file (e.g., open in text mode?)
100     __crt_lowio_text_mode      textmode;
101     __crt_lowio_pipe_lookahead _pipe_lookahead;
102 
103     uint8_t unicode          : 1; // Was the file opened as unicode?
104     uint8_t utf8translations : 1; // Buffer contains translations other than CRLF
105     uint8_t dbcsBufferUsed   : 1; // Is the dbcsBuffer in use?
106     char    mbBuffer[MB_LEN_MAX]; // Buffer for the lead byte of DBCS when converting from DBCS to Unicode
107                                   // Or for the first up to 3 bytes of a UTF-8 character
108 };
109 
110 // The log-base-2 of the number of elements in each array of lowio file objects
111 #define IOINFO_L2E          6
112 
113 // The number of elements in each array of lowio file objects
114 #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
115 
116 // The hard maximum number of arrays of lowio file objects that may be allocated
117 #define IOINFO_ARRAYS       128
118 
119 // The maximum number of lowio file objects that may be allocated at any one time
120 #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
121 
122 
123 
124 #define STDIO_HANDLES_COUNT       3
125 /*
126  * Access macros for getting at an __crt_lowio_handle_data struct and its fields from a
127  * file handle
128  */
129 #define _pioinfo(i)          (__pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - 1)))
130 #define _osfhnd(i)           (_pioinfo(i)->osfhnd)
131 #define _osfile(i)           (_pioinfo(i)->osfile)
132 #define _pipe_lookahead(i)   (_pioinfo(i)->_pipe_lookahead)
133 #define _textmode(i)         (_pioinfo(i)->textmode)
134 #define _tm_unicode(i)       (_pioinfo(i)->unicode)
135 #define _startpos(i)         (_pioinfo(i)->startpos)
136 #define _utf8translations(i) (_pioinfo(i)->utf8translations)
137 #define _mbBuffer(i)         (_pioinfo(i)->mbBuffer)
138 #define _dbcsBuffer(i)       (_pioinfo(i)->mbBuffer[0])
139 #define _dbcsBufferUsed(i)   (_pioinfo(i)->dbcsBufferUsed)
140 
141 /*
142  * Safer versions of the above macros. Currently, only _osfile_safe is
143  * used.
144  */
145 #define _pioinfo_safe(i)    ((((i) != -1) && ((i) != -2)) ? _pioinfo(i) : &__badioinfo)
146 #define _osfile_safe(i)     (_pioinfo_safe(i)->osfile)
147 #define _textmode_safe(i)   (_pioinfo_safe(i)->textmode)
148 #define _tm_unicode_safe(i) (_pioinfo_safe(i)->unicode)
149 
150 typedef __crt_lowio_handle_data* __crt_lowio_handle_data_array[IOINFO_ARRAYS];
151 
152 // Special, static lowio file object used only for more graceful handling
153 // of a C file handle value of -1 (results from common errors at the stdio
154 // level).
155 extern __crt_lowio_handle_data __badioinfo;
156 
157 // The umask value
158 extern int _umaskval;
159 
160 // Global array of pointers to the arrays of lowio file objects.
161 extern __crt_lowio_handle_data_array __pioinfo;
162 
163 // The number of handles for which file objects have been allocated.  This
164 // number is such that for any fh in [0, _nhandle), _pioinfo(fh) is well-
165 // formed.
166 extern int _nhandle;
167 
168 
169 
170 int __cdecl _alloc_osfhnd(void);
171 int __cdecl _free_osfhnd(int);
172 int __cdecl __acrt_lowio_set_os_handle(int, intptr_t);
173 
174 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 //
176 // Internal lowio functions
177 //
178 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 
180 _Success_(return == 0)
181 errno_t __cdecl _sopen_nolock(
182     _Out_  int*        _UnlockFlag,
183     _Out_  int*        _FileHandle,
184     _In_z_ char const* _FileName,
185     _In_   int         _OpenFlag,
186     _In_   int         _ShareFlag,
187     _In_   int         _PermissionFlag,
188     _In_   int         _SecureFlag
189     );
190 
191 _Success_(return == 0)
192 errno_t __cdecl _wsopen_nolock(
193     _Out_  int*           _UnlockFlag,
194     _Out_  int*           _FileHandle,
195     _In_z_ wchar_t const* _FileName,
196     _In_   int            _OpenFlag,
197     _In_   int            _ShareFlag,
198     _In_   int            _PermissionFlag,
199     _In_   int            _SecureFlag
200     );
201 
202 
203 _Check_return_
204 __crt_lowio_handle_data* __cdecl __acrt_lowio_create_handle_array();
205 
206 void __cdecl __acrt_lowio_destroy_handle_array(
207     _Pre_maybenull_ _Post_invalid_ _In_reads_opt_(IOINFO_ARRAY_ELTS) __crt_lowio_handle_data* _Array
208     );
209 
210 _Check_return_opt_
211 errno_t __cdecl __acrt_lowio_ensure_fh_exists(
212     _In_ int _FileHandle
213     );
214 
215 void __cdecl __acrt_lowio_lock_fh  (_In_ int _FileHandle);
216 void __cdecl __acrt_lowio_unlock_fh(_In_ int _FileHandle);
217 
218 extern "C++"
219 {
220     template <typename Action>
221     auto __acrt_lowio_lock_fh_and_call(int const fh, Action&& action) throw()
222         -> decltype(action())
223     {
224         return __crt_seh_guarded_call<decltype(action())>()(
225             [fh]() { __acrt_lowio_lock_fh(fh); },
226             action,
227             [fh]() { __acrt_lowio_unlock_fh(fh); });
228     }
229 }
230 
231 // console_invalid_handle indicates that CONOUT$ or CONIN$ could not be created
232 // console_uninitialized_handle indicates that the handle has not yet been initialized
233 const HANDLE _console_invalid_handle = reinterpret_cast<HANDLE>(-1);
234 const HANDLE _console_uninitialized_handle = reinterpret_cast<HANDLE>(-2);
235 
236 BOOL __cdecl __dcrt_lowio_ensure_console_input_initialized(void);
237 
238 BOOL __cdecl __dcrt_read_console_input(
239     _Out_ PINPUT_RECORD lpBuffer,
240     _In_  DWORD         nLength,
241     _Out_ LPDWORD       lpNumberOfEventsRead
242     );
243 
244 BOOL __cdecl __dcrt_read_console(
245     _Out_ LPVOID  lpBuffer,
246     _In_  DWORD   nNumberOfCharsToRead,
247     _Out_ LPDWORD lpNumberOfCharsRead
248     );
249 
250 BOOL __cdecl __dcrt_get_number_of_console_input_events(
251     _Out_ LPDWORD lpcNumberOfEvents
252     );
253 
254 BOOL __cdecl __dcrt_peek_console_input_a(
255     _Out_ PINPUT_RECORD lpBuffer,
256     _In_  DWORD         nLength,
257     _Out_ LPDWORD       lpNumberOfEventsRead
258     );
259 
260 BOOL __cdecl __dcrt_get_input_console_mode(
261     _Out_ LPDWORD lpMode
262     );
263 
264 BOOL __cdecl __dcrt_set_input_console_mode(
265     _In_ DWORD dwMode
266     );
267 
268 BOOL __cdecl __dcrt_lowio_ensure_console_output_initialized(void);
269 
270 BOOL __cdecl __dcrt_write_console(
271     _In_  void const * lpBuffer,
272     _In_  DWORD        nNumberOfCharsToWrite,
273     _Out_ LPDWORD      lpNumberOfCharsWritten
274     );
275 
276 _Check_return_ int __cdecl _chsize_nolock(_In_ int _FileHandle,_In_ __int64 _Size);
277 _Check_return_opt_ int __cdecl _close_nolock(_In_ int _FileHandle);
278 _Check_return_opt_ long __cdecl _lseek_nolock(_In_ int _FileHandle, _In_ long _Offset, _In_ int _Origin);
279 _Check_return_ int __cdecl _setmode_nolock(_In_ int _FileHandle, _In_ int _Mode);
280 _Check_return_ _Success_(return >= 0 && return <= _MaxCharCount) int __cdecl _read_nolock(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void * _DstBuf, _In_ unsigned int _MaxCharCount);
281 _Check_return_ int __cdecl _write_nolock(_In_ int _FileHandle, _In_reads_bytes_(_MaxCharCount) const void * _Buf, _In_ unsigned int _MaxCharCount, __crt_cached_ptd_host& _Ptd);
282 _Check_return_opt_ __int64 __cdecl _lseeki64_nolock(_In_ int _FileHandle, _In_ __int64 _Offset, _In_ int _Origin);
283 
284 // Temporary until non-PTD propagating versions can be replaced:
285 _Check_return_ int __cdecl _chsize_nolock_internal(_In_ int _FileHandle, _In_ __int64 _Size, _Inout_ __crt_cached_ptd_host& _Ptd);
286 _Check_return_opt_ __int64 __cdecl _lseeki64_nolock_internal(_In_ int _FileHandle, _In_ __int64 _Offset, _In_ int _Origin, _Inout_ __crt_cached_ptd_host& _Ptd);
287 _Check_return_opt_ int __cdecl _close_nolock_internal(_In_ int _FileHandle, _Inout_ __crt_cached_ptd_host& _Ptd);
288 
289 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
290 //
291 // Internal stdio functions with PTD propagation
292 //
293 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
294 
295 _Check_return_opt_
296 int __cdecl _close_internal(
297     _In_    int                    _FileHandle,
298     _Inout_ __crt_cached_ptd_host& _Ptd
299     );
300 
301 _Check_return_opt_
302 long __cdecl _lseek_internal(
303     _In_    int                    _FileHandle,
304     _In_    long                   _Offset,
305     _In_    int                    _Origin,
306     _Inout_ __crt_cached_ptd_host& _Ptd
307     );
308 
309 _Check_return_opt_
310 __int64 __cdecl _lseeki64_internal(
311     _In_    int                    _FileHandle,
312     _In_    __int64                _Offset,
313     _In_    int                    _Origin,
314     _Inout_ __crt_cached_ptd_host& _Ptd
315     );
316 
317 int __cdecl _write_internal(
318     _In_                            int                    _FileHandle,
319     _In_reads_bytes_(_MaxCharCount) void const*            _Buf,
320     _In_                            unsigned int           _MaxCharCount,
321     _Inout_                         __crt_cached_ptd_host& _Ptd
322     );
323 
324 // fileno for stdout, stdin & stderr when there is no console
325 #define _NO_CONSOLE_FILENO ((intptr_t)-2)
326 
327 
328 _CRT_END_C_HEADER
329