xref: /reactos/sdk/lib/ucrt/conio/initcon.cpp (revision 04e0dc4a)
1 //
2 // initcon.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Defines the global console output handle and the __dcrt_lowio_initialize_console_output() and
7 // __dcrt_terminate_console_output() 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_output_terminator);
14 
15 // The global console output handle.
16 static HANDLE __dcrt_lowio_console_output_handle = _console_uninitialized_handle;
17 
18 // Initializes the global console output handle
__dcrt_lowio_initialize_console_output()19 static void __dcrt_lowio_initialize_console_output()
20 {
21     __dcrt_lowio_console_output_handle = CreateFileW(
22         L"CONOUT$",
23         GENERIC_WRITE,
24         FILE_SHARE_READ | FILE_SHARE_WRITE,
25         nullptr,
26         OPEN_EXISTING,
27         0,
28         nullptr);
29 }
30 
__dcrt_lowio_ensure_console_output_initialized()31 extern "C" BOOL __cdecl __dcrt_lowio_ensure_console_output_initialized()
32 {
33     if (__dcrt_lowio_console_output_handle == _console_uninitialized_handle)
34     {
35         __dcrt_lowio_initialize_console_output();
36     }
37 
38     if (__dcrt_lowio_console_output_handle == _console_invalid_handle)
39     {
40         return FALSE;
41     }
42     return TRUE;
43 }
44 
45 // Closes the global console output handle
__dcrt_terminate_console_output()46 extern "C" void __cdecl __dcrt_terminate_console_output()
47 {
48     if (   __dcrt_lowio_console_output_handle != _console_invalid_handle
49         && __dcrt_lowio_console_output_handle != _console_uninitialized_handle)
50     {
51         CloseHandle(__dcrt_lowio_console_output_handle);
52     }
53 }
54 
55 template <typename Func>
console_output_reopen_and_retry(Func const & fp)56 static BOOL console_output_reopen_and_retry(Func const& fp) throw()
57 {
58     BOOL result = fp();
59     if (!result && GetLastError() == ERROR_INVALID_HANDLE) {
60         __dcrt_terminate_console_output();
61         __dcrt_lowio_initialize_console_output();
62         result = fp();
63     }
64     return result;
65 }
66 
__dcrt_write_console(_In_ void const * lpBuffer,_In_ DWORD nNumberOfCharsToWrite,_Out_ LPDWORD lpNumberOfCharsWritten)67 extern "C" BOOL __cdecl __dcrt_write_console(
68     _In_  void const * lpBuffer,
69     _In_  DWORD        nNumberOfCharsToWrite,
70     _Out_ LPDWORD      lpNumberOfCharsWritten
71     )
72 {
73     return console_output_reopen_and_retry(
74         [lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten]()
75         {
76             return ::WriteConsoleW(
77                 __dcrt_lowio_console_output_handle,
78                 lpBuffer,
79                 nNumberOfCharsToWrite,
80                 lpNumberOfCharsWritten,
81                 nullptr);
82         });
83 }
84