@samitouri / QOSAMI-WSL / commits / e663585e

cleanup: refactor console helper class (#14091)

* cleanup: refactor console helper class * make opening CONIN and CONOUT non-fatal --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>

Ben Hillis committed Jan 22, 2026 at 11:18 UTC e663585eeb8fa332f229a7d908bbbaa7af1adafa
12 files changed +251 -269
src/windows/common/CMakeLists.txt
+2 -2
@@ -32,7 +32,7 @@ set(SOURCES
32 string.cpp
33 SubProcess.cpp
34 svccomm.cpp
35 - svccommio.cpp
35 + ConsoleState.cpp
36 WslClient.cpp
37 WslCoreConfig.cpp
38 WslCoreFilesystem.cpp
@@ -107,7 +107,7 @@ set(HEADERS
107 Stringify.h
108 SubProcess.h
109 svccomm.hpp
110 - svccommio.hpp
110 + ConsoleState.h
111 WslClient.h
112 WslCoreConfig.h
113 WslCoreFilesystem.h
src/windows/common/ConsoleState.cpp new
+167
@@ -0,0 +1,167 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + ConsoleState.cpp
8 +
9 +Abstract:
10 +
11 + This file contains function definitions for the ConsoleState helper class.
12 +--*/
13 +
14 +#include "precomp.h"
15 +#include "svccomm.hpp"
16 +#include "ConsoleState.h"
17 +#pragma hdrstop
18 +
19 +namespace {
20 +
21 +void ChangeConsoleMode(_In_ HANDLE Handle, _In_ DWORD Mode)
22 +{
23 + // Use the invalid parameter error code to detect the v1 console that does not support the provided mode.
24 + // This can be improved in the future when a more elegant solution exists.
25 + //
26 + // N.B. Ignore failures setting the mode if the console has already disconnected.
27 + if (!SetConsoleMode(Handle, Mode))
28 + {
29 + // DISABLE_NEWLINE_AUTO_RETURN is not supported everywhere, if the flag was present fall back and try again.
30 + if (WI_IsFlagSet(Mode, DISABLE_NEWLINE_AUTO_RETURN))
31 + {
32 + Mode = WI_ClearFlag(Mode, DISABLE_NEWLINE_AUTO_RETURN);
33 + if (SetConsoleMode(Handle, Mode))
34 + {
35 + return;
36 + }
37 + }
38 +
39 + switch (GetLastError())
40 + {
41 + case ERROR_PIPE_NOT_CONNECTED:
42 + break;
43 +
44 + case ERROR_INVALID_PARAMETER:
45 + THROW_HR_MSG(WSL_E_CONSOLE, "SetConsoleMode(0x%x) failed", Mode);
46 +
47 + default:
48 + THROW_LAST_ERROR_MSG("SetConsoleMode(0x%x) failed", Mode);
49 + }
50 + }
51 +}
52 +
53 +void TrySetConsoleMode(_In_ HANDLE Handle, _In_ DWORD Mode)
54 +try
55 +{
56 + ChangeConsoleMode(Handle, Mode);
57 +}
58 +CATCH_LOG()
59 +
60 +} // namespace
61 +
62 +namespace wsl::windows::common {
63 +
64 +ConsoleState::ConsoleState()
65 +{
66 + // Ensure console state is restored if the constructor throws.
67 + auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { RestoreConsoleState(); });
68 +
69 + m_InputHandle.reset(
70 + CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr));
71 +
72 + if (m_InputHandle)
73 + {
74 + m_SavedInputCodePage = GetConsoleCP();
75 + LOG_IF_WIN32_BOOL_FALSE(SetConsoleCP(CP_UTF8));
76 +
77 + // Configure for raw input with VT support.
78 + DWORD mode;
79 + THROW_LAST_ERROR_IF(!GetConsoleMode(m_InputHandle.get(), &mode));
80 +
81 + DWORD NewMode = mode;
82 + WI_SetAllFlags(NewMode, ENABLE_WINDOW_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT);
83 + WI_ClearAllFlags(NewMode, ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
84 + ChangeConsoleMode(m_InputHandle.get(), NewMode);
85 + m_SavedInputMode = mode;
86 + }
87 + else
88 + {
89 + LOG_LAST_ERROR_MSG("CreateFileW(CONIN$) failed");
90 + }
91 +
92 + m_OutputHandle.reset(
93 + CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr));
94 +
95 + if (m_OutputHandle)
96 + {
97 + m_SavedOutputCodePage = GetConsoleOutputCP();
98 + LOG_IF_WIN32_BOOL_FALSE(SetConsoleOutputCP(CP_UTF8));
99 +
100 + // Configure for VT output.
101 + DWORD mode;
102 + THROW_LAST_ERROR_IF(!GetConsoleMode(m_OutputHandle.get(), &mode));
103 +
104 + DWORD NewMode = mode;
105 + WI_SetAllFlags(NewMode, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN);
106 + ChangeConsoleMode(m_OutputHandle.get(), NewMode);
107 + m_SavedOutputMode = mode;
108 + }
109 + else
110 + {
111 + LOG_LAST_ERROR_MSG("CreateFileW(CONOUT$) failed");
112 + }
113 +
114 + cleanup.release();
115 +}
116 +
117 +ConsoleState::~ConsoleState()
118 +{
119 + RestoreConsoleState();
120 +}
121 +
122 +void ConsoleState::RestoreConsoleState()
123 +{
124 + if (m_InputHandle)
125 + {
126 + if (m_SavedInputCodePage.has_value())
127 + {
128 + LOG_IF_WIN32_BOOL_FALSE(SetConsoleCP(m_SavedInputCodePage.value()));
129 + }
130 +
131 + if (m_SavedInputMode.has_value())
132 + {
133 + TrySetConsoleMode(m_InputHandle.get(), m_SavedInputMode.value());
134 + }
135 + }
136 +
137 + if (m_OutputHandle)
138 + {
139 + if (m_SavedOutputCodePage.has_value())
140 + {
141 + LOG_IF_WIN32_BOOL_FALSE(SetConsoleOutputCP(m_SavedOutputCodePage.value()));
142 + }
143 +
144 + if (m_SavedOutputMode.has_value())
145 + {
146 + TrySetConsoleMode(m_OutputHandle.get(), m_SavedOutputMode.value());
147 + }
148 + }
149 +}
150 +
151 +COORD ConsoleState::GetWindowSize() const
152 +{
153 + if (m_OutputHandle)
154 + {
155 + CONSOLE_SCREEN_BUFFER_INFOEX Info{};
156 + Info.cbSize = sizeof(Info);
157 + THROW_IF_WIN32_BOOL_FALSE(GetConsoleScreenBufferInfoEx(m_OutputHandle.get(), &Info));
158 + return {
159 + static_cast<short>(Info.srWindow.Right - Info.srWindow.Left + 1),
160 + static_cast<short>(Info.srWindow.Bottom - Info.srWindow.Top + 1)};
161 + }
162 +
163 + LOG_HR_MSG(E_UNEXPECTED, "No console handle available for GetWindowSize");
164 + return {80, 24};
165 +}
166 +
167 +} // namespace wsl::windows::common
src/windows/common/ConsoleState.h new
+46
@@ -0,0 +1,46 @@
1 +/*++
2 +
3 +Copyright (c) Microsoft. All rights reserved.
4 +
5 +Module Name:
6 +
7 + ConsoleState.h
8 +
9 +Abstract:
10 +
11 + This file contains function declarations for the ConsoleState helper class.
12 +
13 +--*/
14 +
15 +#pragma once
16 +
17 +#include <wil/filesystem.h>
18 +#include <wil/result.h>
19 +#include "wslservice.h"
20 +
21 +namespace wsl::windows::common {
22 +
23 +// RAII wrapper for console state configuration and restoration
24 +class ConsoleState
25 +{
26 +public:
27 + ConsoleState();
28 + ~ConsoleState();
29 + ConsoleState(const ConsoleState&) = delete;
30 + ConsoleState& operator=(const ConsoleState&) = delete;
31 + ConsoleState(ConsoleState&&) = delete;
32 + ConsoleState& operator=(ConsoleState&&) = delete;
33 +
34 + COORD GetWindowSize() const;
35 +
36 +private:
37 + void RestoreConsoleState();
38 +
39 + wil::unique_hfile m_InputHandle;
40 + wil::unique_hfile m_OutputHandle;
41 + std::optional<DWORD> m_SavedInputMode{};
42 + std::optional<UINT> m_SavedInputCodePage{};
43 + std::optional<DWORD> m_SavedOutputMode{};
44 + std::optional<UINT> m_SavedOutputCodePage{};
45 +};
46 +} // namespace wsl::windows::common
src/windows/common/WslClient.cpp
+1 -1
@@ -1501,7 +1501,7 @@ int RunDebugShell()
1501 THROW_IF_WIN32_BOOL_FALSE(WriteFile(pipe.get(), "\n", 1, nullptr, nullptr));
1502
1503 // Create a thread to relay stdin to the pipe.
1504 - wsl::windows::common::SvcCommIo Io;
1504 + wsl::windows::common::ConsoleState Io;
1505 auto exitEvent = wil::unique_event(wil::EventOptions::ManualReset);
1506 std::thread inputThread(
1507 [&]() { wsl::windows::common::RelayStandardInput(GetStdHandle(STD_INPUT_HANDLE), pipe.get(), {}, exitEvent.get(), &Io); });
src/windows/common/precomp.h
+1 -1
@@ -160,7 +160,7 @@ Abstract:
160 #include "LxssDynamicFunction.h"
161 #include "relay.hpp"
162 #include "svccomm.hpp"
163 -#include "svccommio.hpp"
163 +#include "ConsoleState.h"
164 #include "disk.hpp"
165 #include "WslSecurity.h"
166 #include "ExecutionContext.h"
src/windows/common/relay.hpp
+1 -1
@@ -15,7 +15,7 @@ Abstract:
15 #pragma once
16
17 #include <winsock2.h>
18 -#include "svccommio.hpp"
18 +#include "ConsoleState.h"
19
20 #define LX_RELAY_BUFFER_SIZE 0x1000
21
src/windows/common/svccomm.cpp
+17 -4
@@ -216,7 +216,7 @@ void wsl::windows::common::RelayStandardInput(
216 HANDLE OutputHandle,
217 const std::shared_ptr<wsl::shared::SocketChannel>& ControlChannel,
218 HANDLE ExitEvent,
219 - wsl::windows::common::SvcCommIo* Io)
219 + wsl::windows::common::ConsoleState* Io)
220 try
221 {
222 if (GetFileType(ConsoleHandle) != FILE_TYPE_CHAR)
@@ -666,8 +666,7 @@ wsl::windows::common::SvcComm::LaunchProcess(
666 // Create the process.
667 //
668
669 - SvcCommIo Io;
670 - PLXSS_STD_HANDLES StdHandles = Io.GetStdHandles();
669 + ConsoleState Io;
670 COORD WindowSize = Io.GetWindowSize();
671 ULONG Flags = LXSS_CREATE_INSTANCE_FLAGS_ALLOW_FS_UPGRADE;
672 if (WI_IsFlagSet(LaunchFlags, LXSS_LAUNCH_FLAG_USE_SYSTEM_DISTRO))
@@ -684,6 +683,20 @@ wsl::windows::common::SvcComm::LaunchProcess(
683 // See: https://github.com/microsoft/terminal/blob/ec434e3fba2a6ef254123e31f5257c25b04f2547/src/tools/ConsoleBench/conhost.cpp#L159-L164
684 HANDLE console = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Reserved2[0];
685
686 + LXSS_STD_HANDLES StdHandles{};
687 + const HANDLE InputHandle = GetStdHandle(STD_INPUT_HANDLE);
688 + const bool IsConsoleInput = wsl::windows::common::wslutil::IsConsoleHandle(InputHandle);
689 + StdHandles.StdIn.HandleType = IsConsoleInput ? LxssHandleConsole : LxssHandleInput;
690 + StdHandles.StdIn.Handle = IsConsoleInput ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(InputHandle);
691 + const HANDLE OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
692 + const bool IsConsoleOutput = wsl::windows::common::wslutil::IsConsoleHandle(OutputHandle);
693 + StdHandles.StdOut.HandleType = IsConsoleOutput ? LxssHandleConsole : LxssHandleOutput;
694 + StdHandles.StdOut.Handle = IsConsoleOutput ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(OutputHandle);
695 + const HANDLE ErrorHandle = GetStdHandle(STD_ERROR_HANDLE);
696 + const bool IsConsoleError = wsl::windows::common::wslutil::IsConsoleHandle(ErrorHandle);
697 + StdHandles.StdErr.HandleType = IsConsoleError ? LxssHandleConsole : LxssHandleOutput;
698 + StdHandles.StdErr.Handle = IsConsoleError ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(ErrorHandle);
699 +
700 GUID DistributionId;
701 GUID InstanceId;
702 wil::unique_handle ProcessHandle;
@@ -712,7 +725,7 @@ wsl::windows::common::SvcComm::LaunchProcess(
725 WindowSize.X,
726 WindowSize.Y,
727 HandleToUlong(console),
715 - StdHandles,
728 + &StdHandles,
729 Flags,
730 &DistributionId,
731 &InstanceId,
src/windows/common/svccomm.hpp
+1 -1
@@ -21,7 +21,7 @@ Abstract:
21
22 namespace wsl::windows::common {
23
24 -void RelayStandardInput(HANDLE ConsoleHandle, HANDLE OutputHandle, const std::shared_ptr<wsl::shared::SocketChannel>& ControlChannel, HANDLE ExitEvent, SvcCommIo* Io);
24 +void RelayStandardInput(HANDLE ConsoleHandle, HANDLE OutputHandle, const std::shared_ptr<wsl::shared::SocketChannel>& ControlChannel, HANDLE ExitEvent, ConsoleState* Io);
25
26 class SvcComm
27 {
src/windows/common/svccommio.cpp deleted
-178
@@ -1,178 +0,0 @@
1 -/*++
2 -
3 -Copyright (c) Microsoft. All rights reserved.
4 -
5 -Module Name:
6 -
7 - svccommio.cpp
8 -
9 -Abstract:
10 -
11 - This file contains function definitions for the SvcCommIo helper class.
12 -
13 ---*/
14 -
15 -#include "precomp.h"
16 -#include "svccomm.hpp"
17 -#include "svccommio.hpp"
18 -#pragma hdrstop
19 -
20 -namespace {
21 -
22 -bool IsConsoleHandle(_In_ HANDLE Handle)
23 -{
24 - DWORD Mode;
25 - return GetFileType(Handle) == FILE_TYPE_CHAR && GetConsoleMode(Handle, &Mode);
26 -}
27 -
28 -void ChangeConsoleMode(_In_ HANDLE Handle, _In_ DWORD Mode)
29 -{
30 - //
31 - // Use the invalid parameter error code to detect the v1 console that does
32 - // not support the provided mode. This can be improved in the future when
33 - // a more elegant solution exists.
34 - //
35 - // N.B. Ignore failures setting the mode if the console has already
36 - // disconnected.
37 - //
38 -
39 - if (!SetConsoleMode(Handle, Mode))
40 - {
41 - // DISABLE_NEWLINE_AUTO_RETURN is not supported everywhere, if the flag was present fall back and try again.
42 - if (WI_IsFlagSet(Mode, DISABLE_NEWLINE_AUTO_RETURN))
43 - {
44 - if (SetConsoleMode(Handle, WI_ClearFlag(Mode, DISABLE_NEWLINE_AUTO_RETURN)))
45 - {
46 - return;
47 - }
48 - }
49 -
50 - switch (GetLastError())
51 - {
52 - case ERROR_INVALID_PARAMETER:
53 - THROW_HR(WSL_E_CONSOLE);
54 -
55 - case ERROR_PIPE_NOT_CONNECTED:
56 - break;
57 -
58 - default:
59 - THROW_LAST_ERROR();
60 - }
61 - }
62 -}
63 -
64 -void TrySetConsoleMode(_In_ HANDLE Handle, _In_ DWORD Mode)
65 -try
66 -{
67 - ChangeConsoleMode(Handle, Mode);
68 -}
69 -CATCH_LOG()
70 -
71 -} // namespace
72 -
73 -namespace wsl::windows::common {
74 -
75 -ConsoleInput::ConsoleInput(HANDLE Handle, DWORD SavedMode) :
76 - m_Handle(Handle), m_SavedMode(SavedMode), m_SavedCodePage(GetConsoleCP())
77 -{
78 - // Configure for raw input with VT support.
79 - DWORD NewMode = m_SavedMode;
80 - WI_SetAllFlags(NewMode, ENABLE_WINDOW_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT);
81 - WI_ClearAllFlags(NewMode, ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
82 - ChangeConsoleMode(Handle, NewMode);
83 -
84 - // Set UTF-8 code page.
85 - LOG_IF_WIN32_BOOL_FALSE(SetConsoleCP(CP_UTF8));
86 -}
87 -
88 -ConsoleInput::~ConsoleInput()
89 -{
90 - TrySetConsoleMode(m_Handle, m_SavedMode);
91 - LOG_IF_WIN32_BOOL_FALSE(SetConsoleCP(m_SavedCodePage));
92 -}
93 -
94 -ConsoleOutput::ConsoleOutput(wil::unique_hfile&& ConsoleHandle, DWORD SavedMode) :
95 - m_ConsoleHandle(std::move(ConsoleHandle)), m_SavedMode(SavedMode), m_SavedCodePage(GetConsoleOutputCP())
96 -{
97 - // Configure for VT output.
98 - DWORD NewMode = m_SavedMode;
99 - WI_SetAllFlags(NewMode, ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN);
100 - ChangeConsoleMode(m_ConsoleHandle.get(), NewMode);
101 -
102 - // Set UTF-8 code page.
103 - LOG_IF_WIN32_BOOL_FALSE(SetConsoleOutputCP(CP_UTF8));
104 -}
105 -
106 -ConsoleOutput::~ConsoleOutput()
107 -{
108 - TrySetConsoleMode(m_ConsoleHandle.get(), m_SavedMode);
109 - LOG_IF_WIN32_BOOL_FALSE(SetConsoleOutputCP(m_SavedCodePage));
110 -}
111 -
112 -SvcCommIo::SvcCommIo()
113 -{
114 - const HANDLE InputHandle = GetStdHandle(STD_INPUT_HANDLE);
115 - const HANDLE OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
116 - const HANDLE ErrorHandle = GetStdHandle(STD_ERROR_HANDLE);
117 -
118 - // Configure input console
119 - DWORD InputMode;
120 - if (GetFileType(InputHandle) == FILE_TYPE_CHAR && GetConsoleMode(InputHandle, &InputMode))
121 - {
122 - m_ConsoleInput.emplace(InputHandle, InputMode);
123 - }
124 -
125 - // Configure output console
126 - wil::unique_hfile ConsoleHandle(
127 - CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr));
128 -
129 - if (ConsoleHandle)
130 - {
131 - DWORD OutputMode;
132 - if (GetConsoleMode(ConsoleHandle.get(), &OutputMode))
133 - {
134 - m_ConsoleOutput.emplace(std::move(ConsoleHandle), OutputMode);
135 - }
136 - }
137 -
138 - // Initialize the standard handles structure
139 - const bool IsConsoleInput = m_ConsoleInput.has_value();
140 - m_StdHandles.StdIn.HandleType = IsConsoleInput ? LxssHandleConsole : LxssHandleInput;
141 - m_StdHandles.StdIn.Handle = IsConsoleInput ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(InputHandle);
142 -
143 - const bool IsConsoleOutput = IsConsoleHandle(OutputHandle);
144 - m_StdHandles.StdOut.HandleType = IsConsoleOutput ? LxssHandleConsole : LxssHandleOutput;
145 - m_StdHandles.StdOut.Handle = IsConsoleOutput ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(OutputHandle);
146 -
147 - const bool IsConsoleError = IsConsoleHandle(ErrorHandle);
148 - m_StdHandles.StdErr.HandleType = IsConsoleError ? LxssHandleConsole : LxssHandleOutput;
149 - m_StdHandles.StdErr.Handle = IsConsoleError ? LXSS_HANDLE_USE_CONSOLE : HandleToUlong(ErrorHandle);
150 -
151 - // Cache a console handle for GetWindowSize
152 - m_WindowSizeHandle = IsConsoleOutput ? OutputHandle : (IsConsoleError ? ErrorHandle : nullptr);
153 -}
154 -
155 -PLXSS_STD_HANDLES
156 -SvcCommIo::GetStdHandles()
157 -{
158 - return &m_StdHandles;
159 -}
160 -
161 -COORD
162 -SvcCommIo::GetWindowSize() const
163 -{
164 - if (m_WindowSizeHandle)
165 - {
166 - CONSOLE_SCREEN_BUFFER_INFOEX Info{};
167 - Info.cbSize = sizeof(Info);
168 - THROW_IF_WIN32_BOOL_FALSE(GetConsoleScreenBufferInfoEx(m_WindowSizeHandle, &Info));
169 - return {
170 - static_cast<short>(Info.srWindow.Right - Info.srWindow.Left + 1),
171 - static_cast<short>(Info.srWindow.Bottom - Info.srWindow.Top + 1)};
172 - }
173 -
174 - LOG_HR_MSG(E_UNEXPECTED, "No console handle available for GetWindowSize");
175 - return {80, 24};
176 -}
177 -
178 -} // namespace wsl::windows::common
src/windows/common/svccommio.hpp deleted
-74
@@ -1,74 +0,0 @@
1 -/*++
2 -
3 -Copyright (c) Microsoft. All rights reserved.
4 -
5 -Module Name:
6 -
7 - svccommio.hpp
8 -
9 -Abstract:
10 -
11 - This file contains function declarations for the SvcCommIo helper class.
12 -
13 ---*/
14 -
15 -#pragma once
16 -
17 -#include <optional>
18 -#include <wil/filesystem.h>
19 -#include <wil/result.h>
20 -#include "wslservice.h"
21 -
22 -namespace wsl::windows::common {
23 -
24 -// RAII wrapper for console input configuration and restoration
25 -class ConsoleInput
26 -{
27 -public:
28 - ConsoleInput(HANDLE Handle, DWORD SavedMode);
29 - ~ConsoleInput();
30 - ConsoleInput(const ConsoleInput&) = delete;
31 - ConsoleInput& operator=(const ConsoleInput&) = delete;
32 - ConsoleInput(ConsoleInput&&) = delete;
33 - ConsoleInput& operator=(ConsoleInput&&) = delete;
34 -
35 -private:
36 - HANDLE m_Handle{};
37 - DWORD m_SavedMode{};
38 - UINT m_SavedCodePage{};
39 -};
40 -
41 -// RAII wrapper for console output configuration and restoration
42 -class ConsoleOutput
43 -{
44 -public:
45 - ConsoleOutput(wil::unique_hfile&& ConsoleHandle, DWORD SavedMode);
46 - ~ConsoleOutput();
47 - ConsoleOutput(const ConsoleOutput&) = delete;
48 - ConsoleOutput& operator=(const ConsoleOutput&) = delete;
49 - ConsoleOutput(ConsoleOutput&&) = delete;
50 - ConsoleOutput& operator=(ConsoleOutput&&) = delete;
51 -
52 -private:
53 - wil::unique_hfile m_ConsoleHandle;
54 - DWORD m_SavedMode{};
55 - UINT m_SavedCodePage{};
56 -};
57 -
58 -class SvcCommIo
59 -{
60 -public:
61 - SvcCommIo();
62 -
63 - PLXSS_STD_HANDLES GetStdHandles();
64 - COORD GetWindowSize() const;
65 -
66 -private:
67 - LXSS_STD_HANDLES m_StdHandles{};
68 - HANDLE m_WindowSizeHandle = nullptr; // Cached console handle for GetWindowSize
69 -
70 - // RAII members for automatic restoration
71 - std::optional<ConsoleInput> m_ConsoleInput;
72 - std::optional<ConsoleOutput> m_ConsoleOutput;
73 -};
74 -} // namespace wsl::windows::common
src/windows/common/wslutil.cpp
+11 -7
@@ -209,13 +209,6 @@ wil::unique_hlocal_string GetWinInetErrorString(HRESULT error)
209 return message;
210 }
211
212 -bool IsInteractiveConsole()
213 -{
214 - const HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
215 - DWORD mode{};
216 - return GetFileType(stdinHandle) == FILE_TYPE_CHAR && GetConsoleMode(stdinHandle, &mode);
217 -}
218 -
212 bool IsWinInetError(HRESULT error)
213 {
214 const DWORD code = error - 0x80070000;
@@ -1144,6 +1137,17 @@ void wsl::windows::common::wslutil::InitializeWil()
1137 }
1138 }
1139
1140 +bool wsl::windows::common::wslutil::IsConsoleHandle(HANDLE Handle)
1141 +{
1142 + DWORD Mode;
1143 + return GetFileType(Handle) == FILE_TYPE_CHAR && GetConsoleMode(Handle, &Mode);
1144 +}
1145 +
1146 +bool wsl::windows::common::wslutil::IsInteractiveConsole()
1147 +{
1148 + return IsConsoleHandle(GetStdHandle(STD_INPUT_HANDLE));
1149 +}
1150 +
1151 bool wsl::windows::common::wslutil::IsRunningInMsix()
1152 {
1153 UINT32 dummy{};
src/windows/common/wslutil.h
+4
@@ -137,6 +137,10 @@ std::vector<BYTE> HashFile(HANDLE File, DWORD Algorithm);
137
138 void InitializeWil();
139
140 +bool IsConsoleHandle(HANDLE Handle);
141 +
142 +bool IsInteractiveConsole();
143 +
144 bool IsRunningInMsix();
145
146 bool IsVhdFile(_In_ const std::filesystem::path& path);