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