You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Use NtQueryVolumeInformationFile instead of GetConsoleMode to check whether a handle is a console - #6483
Earlier this year I looked into the Windows console in depth, and since it's open source, I had the opportunity to analyze how it's implemented.
Put simply, when program call GetConsoleMode (as well as any other console API, and when reading from or writing to the console handle), the following happens:
conhost.exe processes these messages and write back
NtQueryVolumeInformationFile is not a console API; it merely queries the device (condrv.sys) info provided when the fs driver is registered, so it is much faster than GetConsoleMode.
This usage of NtQueryVolumeInformationFile has been supported since Windows 8, see rust-lang/rust#164170.
[print.fun] 10.2 says that on Windows, GetConsoleMode is used to determine whether a handle refers to a console, so an LWG issue may be needed. However, since there is no observable difference, this patch does not need to wait for standards.
I just ran a simple test, and NtQueryVolumeInformationFile is 100 times faster than GetConsoleMode.
test program:
#include<iostream>
#include<chrono>
#include<windows.h>
#include<winternl.h>
#include<winioctl.h>
#pragma comment(lib, "ntdll.lib")
extern"C" {
// Exported by ntdll.lib and can most efficiently query whether a HANDLE references a console.// Since the user mode header isn't provided, all needed declarations are declared manually.NTSYSAPINTSTATUSNTAPINtQueryVolumeInformationFile(
HANDLE handle, PIO_STATUS_BLOCK ioStatus, PVOID information, ULONG length, ULONG informationClass);
} // extern "C"// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_file_fs_device_informationtypedefstruct_FILE_FS_DEVICE_INFORMATION {
DEVICE_TYPE DeviceType;
ULONG Characteristics;
} FILE_FS_DEVICE_INFORMATION, * PFILE_FS_DEVICE_INFORMATION;
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_fsinfoclass
#defineFileFsDeviceInformation4bool_Is_console_handle(HANDLE handle) {
IO_STATUS_BLOCK iosb;
FILE_FS_DEVICE_INFORMATION info;
constauto status = NtQueryVolumeInformationFile(handle, &iosb, &info, sizeof(info), FileFsDeviceInformation);
return (status >= 0) & (info.DeviceType == FILE_DEVICE_CONSOLE);
}
intmain() {
constexprint N = 1000000;
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
auto t0 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; ++i)
(void)_Is_console_handle(h);
auto t1 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; ++i)
(void)GetConsoleMode(h, &mode);
auto t2 = std::chrono::high_resolution_clock::now();
auto ftNs = std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count() / N;
auto cmNs = std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() / N;
std::cout << ftNs << " ns and " << cmNs << " ns\n";
}
I wrote a benchmark for std::print, but the results fluctuate a lot.
Yexuan Xiao (YexuanXiao)
changed the title
Use GetFileType instead of GetConsoleMode to check whether a handle is a console
Use NtQueryVolumeInformationFile instead of GetConsoleMode to check whether a handle is a console
Oct 9, 2026
Avoid treating STATUS_PENDING as successful handle query
stl/src/print.cpp:43
NT_SUCCESS-style checking also accepts STATUS_PENDING (a positive status). For an asynchronously opened handle, the information buffer is not valid until the I/O completes, so this can read uninitialized info and potentially classify the handle from garbage. Since console handles complete this query synchronously, require immediate success here (or explicitly wait and inspect iosb.Status).
Document redirecting benchmark payload away from report output
benchmarks/src/print.cpp:14
This benchmark emits its payload to stdout, so a normal invocation mixes a very large amount of Lorem Ipsum with the benchmark report and makes the results difficult to retrieve. The existing stdout benchmark documents the required output redirection at benchmarks/src/efficient_nonlocking_print.cpp:4-5; add equivalent invocation guidance here or separate the reporter output programmatically.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Earlier this year I looked into the Windows console in depth, and since it's open source, I had the opportunity to analyze how it's implemented.
Put simply, when program call
GetConsoleMode(as well as any other console API, and when reading from or writing to the console handle), the following happens:https://github.com/microsoft/terminal/blob/6676c6f938f7e98ad680f0cecedd3bafb6529734/dep/Console/condrv.h#L33-L40
NtQueryVolumeInformationFileis not a console API; it merely queries the device (condrv.sys) info provided when the fs driver is registered, so it is much faster thanGetConsoleMode.This usage of NtQueryVolumeInformationFile has been supported since Windows 8, see rust-lang/rust#164170.
[print.fun] 10.2 says that on Windows,
GetConsoleModeis used to determine whether a handle refers to a console, so an LWG issue may be needed. However, since there is no observable difference, this patch does not need to wait for standards.I just ran a simple test, and
NtQueryVolumeInformationFileis 100 times faster thanGetConsoleMode.test program:
I wrote a benchmark for
std::print, but the results fluctuate a lot.