ReactOS 0.4.16-dev-889-g9563c07
cgets.cpp
Go to the documentation of this file.
1//
2// cgets.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines _cgets() and _cgets_s(), which read a string from the console.
7//
8#include <conio.h>
10#include <stdlib.h>
11
12
13
15
16
17
18// Use of the following buffer variables is primarily for syncronizing with
19// _cgets_s. _cget_s fills the MBCS buffer and if the user passes in single
20// character buffer and the unicode character is not converted to single byte
21// MBC, then _cget_s should buffer that character so that next call to
22// _cgetws_s can return the same character.
23extern "C" { extern wchar_t __console_wchar_buffer; }
24extern "C" { extern int __console_wchar_buffer_used; }
25
26
27
28// Reads a string from the console; always null-terminates the buffer. Returns
29// 0 on success; returns an errno error code on failure.
30extern "C" errno_t __cdecl _cgets_s(char* const source_string, size_t const size_in_bytes, size_t* const size_read)
31{
32 _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE(source_string != nullptr, EINVAL);
34 _RESET_STRING(source_string, size_in_bytes);
35
36 _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE(size_read != nullptr, EINVAL);
37
38 errno_t error = 0;
39 char* string = source_string;
40
42 __try
43 {
44 // The implementation of cgets is slightly tricky. The reason being,
45 // the code page for console is different from the CRT code page.
46 // What this means is the program may interpret character
47 // differently from it's acctual value. To fix this, what we really
48 // want to do is read the input as unicode string and then convert
49 // it to proper MBCS representation.
50 //
51 // This fix this we are really converting from Unicode to MBCS.
52 // This adds performance problem as we may endup doing this
53 // character by character. The basic problem here is that we have
54 // no way to know how many UNICODE characters will be needed to fit
55 // them in given size of MBCS buffer. To fix this issue we will be
56 // converting one Unicode character at a time to MBCS. This makes
57 // this slow, but then this is already console input,
58 *size_read = 0;
59
60 size_t available = size_in_bytes - 1;
61 do
62 {
63 wchar_t wchar_buff[2];
64 size_t sizeRead = 0;
65
66 error = _cgetws_s(wchar_buff, _countof(wchar_buff), &sizeRead);
67 if (error != 0)
68 break;
69
70 if (wchar_buff[0] == '\0')
71 break;
72
73 int size_converted = 0;
74 errno_t const wctomb_result = wctomb_s(&size_converted, string, available, wchar_buff[0]);
75 if (wctomb_result != 0)
76 {
77 // Put the wide character back in the buffer so that the
78 // unutilized wide character is still in the stream:
79 __console_wchar_buffer = wchar_buff[0];
81 break;
82 }
83
84 string += size_converted;
85 *size_read += size_converted;
86 available -= size_converted;
87 }
88 while (available > 0);
89 }
91 {
93 }
95
96 *string++ = '\0';
97
98 if (error != 0)
99 errno = error;
100
101 return error;
102}
103
104
105
106// Reads a string from the console via ReadConsole on a cooked console handle.
107// string[0] must contain the maximum length of the string. The number of
108// characters written is stored in string[1]. The return value is a pointer to
109// string[2] on success; nullptr on failure.
110extern "C" char* __cdecl _cgets(_Inout_z_ char* const string)
111{
112 _VALIDATE_CLEAR_OSSERR_RETURN(string != nullptr, EINVAL, nullptr);
113 _VALIDATE_CLEAR_OSSERR_RETURN(string[0] > 0, EINVAL, nullptr);
114
115 size_t const size_in_bytes = static_cast<size_t>(string[0]);
116
117 size_t size_read = 0;
118 // warning 26018: Potential overflow of null terminated buffer using expression string+2
119 // Suppressing warning since _cgets is purposefully unsafe.
120#pragma warning(suppress:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED)
121 errno_t const result = _cgets_s(string + 2, size_in_bytes, &size_read);
122
123 // warning 26018: Potential overflow of null terminated buffer using expression string[1]
124 // Suppressing warning since _cgets is purposefully unsafe.
125#pragma warning(suppress:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED)
126 string[1] = static_cast<char>(size_read);
127
128 return result == 0 ? string + 2 : nullptr;
129}
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
int __console_wchar_buffer_used
Definition: cgetws.cpp:19
intptr_t __dcrt_lowio_console_input_handle
Definition: getch.cpp:232
wchar_t __console_wchar_buffer
Definition: cgetws.cpp:18
errno_t __cdecl _cgets_s(char *const source_string, size_t const size_in_bytes, size_t *const size_read)
Definition: cgets.cpp:30
errno_t __cdecl _cgetws_s(wchar_t *const string_buffer, size_t const size_in_words, size_t *const size_read)
Definition: cgetws.cpp:25
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_conio_lock
#define _RESET_STRING(_String, _Size)
__acrt_lock(__acrt_heap_lock)
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2336
GLuint64EXT * result
Definition: glext.h:11304
#define _VALIDATE_CLEAR_OSSERR_RETURN(expr, errorcode, retexpr)
#define _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE(expr, errorcode)
#define error(str)
Definition: mkdosfs.c:1605
#define _Inout_z_
Definition: no_sal2.h:166
#define __try
Definition: pseh2_64.h:188
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
#define errno
Definition: errno.h:18
#define _countof(array)
Definition: sndvol32.h:70
int errno_t
Definition: corecrt.h:615
int intptr_t
Definition: vcruntime.h:134
errno_t __cdecl wctomb_s(int *const return_value, char *const destination, size_t const destination_count, wchar_t const wchar)
Definition: wctomb.cpp:160