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