1 //
2 // initconin.cpp
3 //
4 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Defines the global console input handle and the __dcrt_lowio_initialize_console_input() and
7 // __dcrt_terminate_console_input() functions, which initialize and close that handle.
8 // Also defines functions that can be used instead of the Console API to enable retry behavior
9 // in case the cached console handle is freed.
10
11 #include <corecrt_internal_lowio.h>
12
13 _CRT_LINKER_FORCE_INCLUDE(__dcrt_console_input_terminator);
14
15 // The global console input handle.
16 static HANDLE __dcrt_lowio_console_input_handle = _console_uninitialized_handle;
17
18 // Initializes the global console input handle
__dcrt_lowio_initialize_console_input()19 static void __dcrt_lowio_initialize_console_input()
20 {
21 __dcrt_lowio_console_input_handle = CreateFileW(
22 L"CONIN$",
23 GENERIC_READ | GENERIC_WRITE,
24 FILE_SHARE_READ | FILE_SHARE_WRITE,
25 nullptr,
26 OPEN_EXISTING,
27 0,
28 nullptr);
29 }
30
__dcrt_lowio_ensure_console_input_initialized()31 extern "C" BOOL __cdecl __dcrt_lowio_ensure_console_input_initialized()
32 {
33 if (__dcrt_lowio_console_input_handle == _console_uninitialized_handle)
34 {
35 __dcrt_lowio_initialize_console_input();
36 }
37
38 if (__dcrt_lowio_console_input_handle == _console_invalid_handle)
39 {
40 return FALSE;
41 }
42 return TRUE;
43 }
44
45 // Closes the global console input handle
__dcrt_terminate_console_input()46 extern "C" void __cdecl __dcrt_terminate_console_input()
47 {
48 if ( __dcrt_lowio_console_input_handle != _console_invalid_handle
49 && __dcrt_lowio_console_input_handle != _console_uninitialized_handle)
50 {
51 CloseHandle(__dcrt_lowio_console_input_handle);
52 }
53 }
54
55 template <typename Func>
console_input_reopen_and_retry(Func const & fp)56 static BOOL console_input_reopen_and_retry(Func const& fp) throw()
57 {
58 BOOL result = fp();
59 if (!result && GetLastError() == ERROR_INVALID_HANDLE) {
60 __dcrt_terminate_console_input();
61 __dcrt_lowio_initialize_console_input();
62 result = fp();
63 }
64 return result;
65 }
66
__dcrt_read_console_input(_Out_ PINPUT_RECORD lpBuffer,_In_ DWORD nLength,_Out_ LPDWORD lpNumberOfEventsRead)67 extern "C" BOOL __cdecl __dcrt_read_console_input(
68 _Out_ PINPUT_RECORD lpBuffer,
69 _In_ DWORD nLength,
70 _Out_ LPDWORD lpNumberOfEventsRead
71 )
72 {
73 return console_input_reopen_and_retry(
74 [lpBuffer, nLength, lpNumberOfEventsRead]()
75 {
76 return ::ReadConsoleInputW(
77 __dcrt_lowio_console_input_handle,
78 lpBuffer,
79 nLength,
80 lpNumberOfEventsRead
81 );
82 });
83 }
84
__dcrt_read_console(_Out_ LPVOID lpBuffer,_In_ DWORD nNumberOfCharsToRead,_Out_ LPDWORD lpNumberOfCharsRead)85 extern "C" BOOL __cdecl __dcrt_read_console(
86 _Out_ LPVOID lpBuffer,
87 _In_ DWORD nNumberOfCharsToRead,
88 _Out_ LPDWORD lpNumberOfCharsRead
89 )
90 {
91 return console_input_reopen_and_retry(
92 [lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead]()
93 {
94 return ::ReadConsoleW(
95 __dcrt_lowio_console_input_handle,
96 lpBuffer,
97 nNumberOfCharsToRead,
98 lpNumberOfCharsRead,
99 nullptr
100 );
101 });
102 }
103
__dcrt_get_number_of_console_input_events(_Out_ LPDWORD lpcNumberOfEvents)104 extern "C" BOOL __cdecl __dcrt_get_number_of_console_input_events(
105 _Out_ LPDWORD lpcNumberOfEvents
106 )
107 {
108 return console_input_reopen_and_retry(
109 [lpcNumberOfEvents]()
110 {
111 return ::GetNumberOfConsoleInputEvents(
112 __dcrt_lowio_console_input_handle,
113 lpcNumberOfEvents
114 );
115 });
116 }
117
__dcrt_peek_console_input_a(_Out_ PINPUT_RECORD lpBuffer,_In_ DWORD nLength,_Out_ LPDWORD lpNumberOfEventsRead)118 extern "C" BOOL __cdecl __dcrt_peek_console_input_a(
119 _Out_ PINPUT_RECORD lpBuffer,
120 _In_ DWORD nLength,
121 _Out_ LPDWORD lpNumberOfEventsRead
122 )
123 {
124 return console_input_reopen_and_retry(
125 [lpBuffer, nLength, lpNumberOfEventsRead]()
126 {
127 return ::PeekConsoleInputA(
128 __dcrt_lowio_console_input_handle,
129 lpBuffer,
130 nLength,
131 lpNumberOfEventsRead
132 );
133 });
134 }
135
__dcrt_get_input_console_mode(_Out_ LPDWORD lpMode)136 extern "C" BOOL __cdecl __dcrt_get_input_console_mode(
137 _Out_ LPDWORD lpMode
138 )
139 {
140 return console_input_reopen_and_retry(
141 [lpMode]()
142 {
143 return ::GetConsoleMode(
144 __dcrt_lowio_console_input_handle,
145 lpMode
146 );
147 });
148 }
149
__dcrt_set_input_console_mode(_In_ DWORD dwMode)150 extern "C" BOOL __cdecl __dcrt_set_input_console_mode(
151 _In_ DWORD dwMode
152 )
153 {
154 return console_input_reopen_and_retry(
155 [dwMode]()
156 {
157 return ::SetConsoleMode(
158 __dcrt_lowio_console_input_handle,
159 dwMode
160 );
161 });
162 }
163