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 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 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 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> 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 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