Дескрипторы консоли

Процесс консоли получает доступ к входным буферам и буферам экрана консоли с помощью дескрипторов. Процесс может открыть один из этих дескрипторов с помощью функций GetStdHandle, CreateFile или CreateConsoleScreenBuffer.

Функция GetStdHandle предоставляет механизм получения связанных с процессом дескрипторов стандартного ввода (STDIN), стандартного вывода (STDOUT) и стандартных ошибок (STDERR). Во время создания консоли эти дескрипторы создаются системой. Изначально STDIN является дескриптором входного буфера консоли, а STDOUT и STDERR являются дескрипторами активного буфера экрана консоли. Но функция SetStdHandle может перенаправить стандартные дескрипторы путем изменения дескриптора, связанного с STDIN, STDOUT или STDERR. Так как стандартные дескрипторы родительского процесса наследуются любым дочерним процессом, последующие вызовы метода GetStdHandle возвращают перенаправленный дескриптор. Дескриптор, возвращенный с помощью GetStdHandle, может ссылаться на элемент, отличный от ввода-вывода в консоли. Например, перед созданием дочернего процесса родительский процесс может использовать SetStdHandle, чтобы задать канал STDIN, наследуемый дочерним процессом, в качестве канала дескриптора. Когда дочерний процесс вызывает GetStdHandle, он получает дескриптор канала. Это означает, что родительский процесс может управлять стандартными дескрипторами дочернего процесса. Дескрипторы, возвращаемые с помощью GetStdHandle, имеют права доступа GENERIC_READ | GENERIC_WRITE, если только с помощью метода SetStdHandle не был задан стандартный дескриптор с более ограниченным доступом.

Значение дескрипторов, возвращаемых с помощью GetStdHandle, не равно 0, 1 или 2, поэтому стандартные предопределенные константы потока в Stdio.h (STDIN, STDOUT и STDERR) нельзя использовать в функциях, для которых требуется дескриптор консоли.

Функция CreateFile позволяет процессу получить дескриптор для входного буфера консоли и активного буфера экрана, даже если STDIN и STDOUT были перенаправлены. Чтобы открыть дескриптор для входного буфера консоли, укажите значение CONIN$ при вызове CreateFile. Укажите значение CONOUT$ при вызове CreateFile, чтобы открыть дескриптор для активного буфера экрана консоли. CreateFile позволяет указать доступ только для чтения и записи в возвращаемом дескрипторе.

Функция CreateConsoleScreenBuffer создает буфер экрана и возвращает дескриптор. Этот дескриптор можно использовать в любой функции, которая принимает дескриптор для вывода в консоли. Новый буфер экрана не активен (не отображается), пока его дескриптор не будет указан в вызове функции SetConsoleActiveScreenBuffer. Обратите внимание, что изменение активного буфера экрана не влияет на дескриптор, возвращаемый методом GetStdHandle. Аналогичным образом использование SetStdHandle для изменения дескриптора STDOUT не влияет на активный буфер экрана.

Дескрипторы консоли, возвращенные методом CreateFile и CreateConsoleScreenBuffer, можно использовать в любой из консольных функций, которым необходим дескриптор для входного буфера консоли или буфера экрана консоли. Дескрипторы, возвращенные методом GetStdHandle, могут использоваться функциями консоли, если они не были перенаправлены для ссылки на элементы, отличные от ввода-вывода в консоли. Но если стандартный дескриптор был перенаправлен для ссылки на файл или канал, этот дескриптор может использоваться только функциями ReadFile и WriteFile. С помощью метода GetFileType можно определить тип устройства, на который ссылается этот дескриптор. Дескриптор консоли представлен как FILE_TYPE_CHAR.

Процесс может использовать функцию DuplicateHandle для дублирования дескриптора консоли, который имеет не такой уровень доступа или режим наследования, как у исходного дескриптора. Но обратите внимание, что процесс может дублировать дескриптор консоли только для собственного использования. Он отличается от других типов дескрипторов (таких как файл, канал или объекты мьютекса), для которых DuplicateHandle может создать дубликат, допустимый для другого процесса. Доступ к консоли должен быть общим во время создания другого процесса или запрашиваться другим процессом с помощью механизма AttachConsole.

Процесс может закрыть дескриптор консоли с помощью функции CloseHandle.