xref: /reactos/sdk/lib/ucrt/conio/initconin.cpp (revision 04e0dc4a)
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