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