https://github.com/charles-zablit updated 
https://github.com/llvm/llvm-project/pull/168729

>From 3ac4774c5d45ef4830b6605d7de9e133a19a1c60 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Wed, 26 Nov 2025 18:25:23 +0000
Subject: [PATCH] [lldb][windows] add Windows Virtual Console support

---
 lldb/include/lldb/Host/ProcessLaunchInfo.h    |   4 +-
 lldb/include/lldb/Host/PseudoTerminal.h       |  40 ++++-
 .../Host/windows/ProcessLauncherWindows.h     |  29 ++++
 .../lldb/Host/windows/PseudoTerminalWindows.h |  37 ++++
 lldb/include/lldb/Host/windows/windows.h      |   4 +-
 lldb/include/lldb/Target/Process.h            |  28 +++
 lldb/source/Host/CMakeLists.txt               |   1 +
 lldb/source/Host/common/ProcessLaunchInfo.cpp |  19 +-
 lldb/source/Host/common/PseudoTerminal.cpp    |  12 +-
 .../Host/windows/ProcessLauncherWindows.cpp   | 164 ++++++++++--------
 .../Host/windows/PseudoTerminalWindows.cpp    |  68 ++++++++
 lldb/source/Interpreter/ScriptInterpreter.cpp |   2 +-
 .../Platform/Windows/PlatformWindows.cpp      |  11 +-
 .../Process/Windows/Common/ProcessWindows.cpp |  32 ++--
 .../Process/Windows/Common/ProcessWindows.h   |   8 +-
 lldb/source/Target/Process.cpp                |  17 +-
 .../tools/lldb-dap/launch/TestDAP_launch.py   |   1 -
 .../GDBRemoteCommunicationClientTest.cpp      |  34 ++--
 .../gn/secondary/lldb/source/Host/BUILD.gn    |   1 +
 19 files changed, 369 insertions(+), 143 deletions(-)
 create mode 100644 lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
 create mode 100644 lldb/source/Host/windows/PseudoTerminalWindows.cpp

diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h 
b/lldb/include/lldb/Host/ProcessLaunchInfo.h
index 25762bc65295d..e0528c5b80539 100644
--- a/lldb/include/lldb/Host/ProcessLaunchInfo.h
+++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h
@@ -118,7 +118,9 @@ class ProcessLaunchInfo : public ProcessInfo {
 
   bool MonitorProcess() const;
 
-  PseudoTerminal &GetPTY() { return *m_pty; }
+  PseudoTerminal &GetPTY() const { return *m_pty; }
+
+  std::shared_ptr<PseudoTerminal> GetPTYSP() const { return m_pty; }
 
   void SetLaunchEventData(const char *data) { m_event_data.assign(data); }
 
diff --git a/lldb/include/lldb/Host/PseudoTerminal.h 
b/lldb/include/lldb/Host/PseudoTerminal.h
index bd1e2f56241b2..b61c213e138cb 100644
--- a/lldb/include/lldb/Host/PseudoTerminal.h
+++ b/lldb/include/lldb/Host/PseudoTerminal.h
@@ -35,11 +35,14 @@ class PseudoTerminal {
 
   /// Destructor
   ///
-  /// The destructor will close the primary and secondary file descriptors if
-  /// they are valid and ownership has not been released using one of: @li
-  /// PseudoTerminal::ReleasePrimaryFileDescriptor() @li
-  /// PseudoTerminal::ReleaseSaveFileDescriptor()
-  ~PseudoTerminal();
+  /// The destructor will close the primary and secondary file
+  /// descriptor/HANDLEs if they are valid and ownership has not been released
+  /// using PseudoTerminal::Close().
+  virtual ~PseudoTerminal();
+
+  /// Close all the file descriptors or Handles of the PseudoTerminal if they
+  /// are valid.
+  virtual void Close();
 
   /// Close the primary file descriptor if it is valid.
   void ClosePrimaryFileDescriptor();
@@ -59,8 +62,7 @@ class PseudoTerminal {
   ///
   /// This class will close the file descriptors for the primary/secondary when
   /// the destructor is called. The file handles can be released using either:
-  /// @li PseudoTerminal::ReleasePrimaryFileDescriptor() @li
-  /// PseudoTerminal::ReleaseSaveFileDescriptor()
+  /// @li PseudoTerminal::ReleasePrimaryFileDescriptor()
   ///
   /// \return
   ///     \b Parent process: a child process ID that is greater
@@ -82,6 +84,16 @@ class PseudoTerminal {
   /// \see PseudoTerminal::ReleasePrimaryFileDescriptor()
   int GetPrimaryFileDescriptor() const;
 
+  /// The primary HANDLE accessor.
+  ///
+  /// This object retains ownership of the primary HANDLE when this
+  /// accessor is used.
+  ///
+  /// \return
+  ///     The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+  ///     not currently valid.
+  virtual void *GetPrimaryHandle() const { return ((void *)(long long)-1); };
+
   /// The secondary file descriptor accessor.
   ///
   /// This object retains ownership of the secondary file descriptor when this
@@ -105,7 +117,17 @@ class PseudoTerminal {
   ///     The name of the secondary pseudo terminal.
   ///
   /// \see PseudoTerminal::OpenFirstAvailablePrimary()
-  std::string GetSecondaryName() const;
+  virtual std::string GetSecondaryName() const;
+
+  /// The underlying Windows Pseudo Terminal HANDLE's accessor.
+  ///
+  /// This object retains ownership of the ConPTY's HANDLE when this
+  /// accessor is used.
+  ///
+  /// \return
+  ///     The primary HANDLE, or INVALID_HANDLE_VALUE if the primary HANDLE is
+  ///     not currently valid.
+  virtual void *GetPseudoTerminalHandle() { return ((void *)(long long)-1); };
 
   /// Open the first available pseudo terminal.
   ///
@@ -126,7 +148,7 @@ class PseudoTerminal {
   ///
   /// \see PseudoTerminal::GetPrimaryFileDescriptor() @see
   /// PseudoTerminal::ReleasePrimaryFileDescriptor()
-  llvm::Error OpenFirstAvailablePrimary(int oflag);
+  virtual llvm::Error OpenFirstAvailablePrimary(int oflag);
 
   /// Open the secondary for the current primary pseudo terminal.
   ///
diff --git a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h 
b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
index 81aea5b2022a5..a04077a5e1d03 100644
--- a/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
+++ b/lldb/include/lldb/Host/windows/ProcessLauncherWindows.h
@@ -11,6 +11,9 @@
 
 #include "lldb/Host/ProcessLauncher.h"
 #include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Environment.h"
+#include "llvm/Support/ErrorOr.h"
 
 namespace lldb_private {
 
@@ -23,6 +26,32 @@ class ProcessLauncherWindows : public ProcessLauncher {
 
 protected:
   HANDLE GetStdioHandle(const ProcessLaunchInfo &launch_info, int fd);
+
+  /// Create a UTF-16 environment block to use with CreateProcessW.
+  ///
+  /// The buffer is a sequence of null-terminated UTF-16 strings, followed by 
an
+  /// extra L'\0' (two bytes of 0). An empty environment must have one
+  /// empty string, followed by an extra L'\0'.
+  ///
+  /// The keys are sorted to comply with the CreateProcess' calling convention.
+  ///
+  /// Ensure that the resulting buffer is used in conjunction with
+  /// CreateProcessW and be sure that dwCreationFlags includes
+  /// CREATE_UNICODE_ENVIRONMENT.
+  ///
+  /// \param env The Environment object to convert.
+  /// \returns The sorted sequence of environment variables and their values,
+  /// separated by null terminators.
+  static std::vector<wchar_t> CreateEnvironmentBufferW(const Environment &env);
+
+  /// Flattens an Args object into a Windows command-line wide string.
+  ///
+  /// Returns an empty string if args is empty.
+  ///
+  /// \param args The Args object to flatten.
+  /// \returns A wide string containing the flattened command line.
+  static llvm::ErrorOr<std::wstring>
+  GetFlattenedWindowsCommandStringW(Args args);
 };
 }
 
diff --git a/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h 
b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
new file mode 100644
index 0000000000000..9e71520420b01
--- /dev/null
+++ b/lldb/include/lldb/Host/windows/PseudoTerminalWindows.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Host_Windows_PseudoTerminalWindows_H_
+#define liblldb_Host_Windows_PseudoTerminalWindows_H_
+
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private {
+
+class PseudoTerminalWindows : public PseudoTerminal {
+
+public:
+  void Close() override;
+
+  HPCON GetPseudoTerminalHandle() override { return m_conpty_handle; };
+
+  HANDLE GetPrimaryHandle() const override { return m_conpty_output; };
+
+  std::string GetSecondaryName() const override { return ""; };
+
+  llvm::Error OpenFirstAvailablePrimary(int oflag) override;
+
+protected:
+  HANDLE m_conpty_handle = INVALID_HANDLE_VALUE;
+  HANDLE m_conpty_output = INVALID_HANDLE_VALUE;
+  HANDLE m_conpty_input = INVALID_HANDLE_VALUE;
+};
+}; // namespace lldb_private
+
+#endif // liblldb_Host_Windows_PseudoTerminalWindows_H_
\ No newline at end of file
diff --git a/lldb/include/lldb/Host/windows/windows.h 
b/lldb/include/lldb/Host/windows/windows.h
index d53d4b9967268..4abee744d2386 100644
--- a/lldb/include/lldb/Host/windows/windows.h
+++ b/lldb/include/lldb/Host/windows/windows.h
@@ -9,9 +9,9 @@
 #ifndef LLDB_lldb_windows_h_
 #define LLDB_lldb_windows_h_
 
-#define NTDDI_VERSION NTDDI_VISTA
+// #define NTDDI_VERSION NTDDI_VISTA
 #undef _WIN32_WINNT // undef a previous definition to avoid warning
-#define _WIN32_WINNT _WIN32_WINNT_VISTA
+// #define _WIN32_WINNT _WIN32_WINNT_VISTA
 #define WIN32_LEAN_AND_MEAN
 #define NOGDI
 #undef NOMINMAX // undef a previous definition to avoid warning
diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index c1f9785e76f90..71fa468be5b2c 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2534,8 +2534,36 @@ void PruneThreadPlans();
 
   void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
 
+  /// Associates a file descriptor with the process's STDIO handling
+  /// and configures an asynchronous reading of that descriptor.
+  ///
+  /// This method installs a ConnectionFileDescriptor for the passed file
+  /// descriptor and starts a dedicated read thread. If the read thread starts
+  /// successfully, the method also ensures that an IOHandlerProcessSTDIO is
+  /// created to manage user input to the process.
+  ///
+  /// The descriptor's ownership is transferred to the underlying
+  /// ConnectionFileDescriptor.
+  ///
+  /// \param[in] fd
+  ///     The file descriptor to use for process STDIO communication. It's
+  ///     assumed to be valid and will be managed by the newly created
+  ///     connection.
+  ///
+  /// \see lldb_private::Process::STDIOReadThreadBytesReceived()
+  /// \see lldb_private::IOHandlerProcessSTDIO
+  /// \see lldb_private::ConnectionFileDescriptor
   void SetSTDIOFileDescriptor(int file_descriptor);
 
+  /// Windows equivalent of Process::SetSTDIOFileDescriptor, with a
+  /// PseudoTerminalWindows instead of a file descriptor.
+  ///
+  /// \param pty
+  ///     The PseudoTerminal to use for process STDIO communication. It is not
+  ///     managed by the created read thread.
+  virtual void
+  SetPseudoTerminalHandle(const std::shared_ptr<PseudoTerminal> &pty) {};
+
   // Add a permanent region of memory that should never be read or written to.
   // This can be used to ensure that memory reads or writes to certain areas of
   // memory never end up being sent to the DoReadMemory or DoWriteMemory
diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index c9e8afe48fcde..17bfacc07b082 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -75,6 +75,7 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
     windows/MainLoopWindows.cpp
     windows/PipeWindows.cpp
     windows/ProcessLauncherWindows.cpp
+    windows/PseudoTerminalWindows.cpp
     windows/ProcessRunLock.cpp
     )
 else()
diff --git a/lldb/source/Host/common/ProcessLaunchInfo.cpp 
b/lldb/source/Host/common/ProcessLaunchInfo.cpp
index 49159cca9c57c..c3beef7031f18 100644
--- a/lldb/source/Host/common/ProcessLaunchInfo.cpp
+++ b/lldb/source/Host/common/ProcessLaunchInfo.cpp
@@ -20,7 +20,9 @@
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 
-#if !defined(_WIN32)
+#ifdef _WIN32
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+#else
 #include <climits>
 #endif
 
@@ -31,7 +33,12 @@ using namespace lldb_private;
 
 ProcessLaunchInfo::ProcessLaunchInfo()
     : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(0),
-      m_file_actions(), m_pty(new PseudoTerminal), m_monitor_callback(nullptr) 
{
+      m_file_actions(), m_monitor_callback(nullptr) {
+#ifdef _WIN32
+  m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+  m_pty = std::make_shared<PseudoTerminal>();
+#endif
 }
 
 ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec &stdin_file_spec,
@@ -40,7 +47,13 @@ ProcessLaunchInfo::ProcessLaunchInfo(const FileSpec 
&stdin_file_spec,
                                      const FileSpec &working_directory,
                                      uint32_t launch_flags)
     : ProcessInfo(), m_working_dir(), m_plugin_name(), m_flags(launch_flags),
-      m_file_actions(), m_pty(new PseudoTerminal) {
+      m_file_actions() {
+#ifdef _WIN32
+  m_pty = std::make_shared<PseudoTerminalWindows>();
+#else
+  m_pty = std::make_shared<PseudoTerminal>();
+#endif
+
   if (stdin_file_spec) {
     FileAction file_action;
     const bool read = true;
diff --git a/lldb/source/Host/common/PseudoTerminal.cpp 
b/lldb/source/Host/common/PseudoTerminal.cpp
index 53e91aff212a4..4d062c3618523 100644
--- a/lldb/source/Host/common/PseudoTerminal.cpp
+++ b/lldb/source/Host/common/PseudoTerminal.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Host/windows/windows.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Errno.h"
 #include <cassert>
@@ -29,16 +30,11 @@
 
 using namespace lldb_private;
 
-// PseudoTerminal constructor
 PseudoTerminal::PseudoTerminal() = default;
 
-// Destructor
-//
-// The destructor will close the primary and secondary file descriptors if they
-// are valid and ownership has not been released using the
-// ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
-// functions.
-PseudoTerminal::~PseudoTerminal() {
+PseudoTerminal::~PseudoTerminal() { Close(); }
+
+void PseudoTerminal::Close() {
   ClosePrimaryFileDescriptor();
   CloseSecondaryFileDescriptor();
 }
diff --git a/lldb/source/Host/windows/ProcessLauncherWindows.cpp 
b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
index f5adadaf061bf..64336492157a8 100644
--- a/lldb/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/lldb/source/Host/windows/ProcessLauncherWindows.cpp
@@ -21,42 +21,41 @@
 using namespace lldb;
 using namespace lldb_private;
 
-static void CreateEnvironmentBuffer(const Environment &env,
-                                    std::vector<char> &buffer) {
-  // The buffer is a list of null-terminated UTF-16 strings, followed by an
-  // extra L'\0' (two bytes of 0).  An empty environment must have one
-  // empty string, followed by an extra L'\0'.
+std::vector<wchar_t>
+ProcessLauncherWindows::CreateEnvironmentBufferW(const Environment &env) {
+  std::vector<std::wstring> env_entries;
   for (const auto &KV : env) {
-    std::wstring warg;
-    if (llvm::ConvertUTF8toWide(Environment::compose(KV), warg)) {
-      buffer.insert(
-          buffer.end(), reinterpret_cast<const char *>(warg.c_str()),
-          reinterpret_cast<const char *>(warg.c_str() + warg.size() + 1));
+    std::wstring wentry;
+    if (llvm::ConvertUTF8toWide(Environment::compose(KV), wentry)) {
+      env_entries.push_back(std::move(wentry));
     }
   }
-  // One null wchar_t (to end the block) is two null bytes
-  buffer.push_back(0);
-  buffer.push_back(0);
-  // Insert extra two bytes, just in case the environment was empty.
-  buffer.push_back(0);
-  buffer.push_back(0);
+  std::sort(env_entries.begin(), env_entries.end(),
+            [](const std::wstring &a, const std::wstring &b) {
+              return _wcsicmp(a.c_str(), b.c_str()) < 0;
+            });
+
+  std::vector<wchar_t> buffer;
+  buffer.clear();
+  for (const auto &env_entry : env_entries) {
+    buffer.insert(buffer.end(), env_entry.begin(), env_entry.end());
+    buffer.push_back(L'\0');
+  }
+  buffer.push_back(L'\0');
+
+  return buffer;
 }
 
-static bool GetFlattenedWindowsCommandString(Args args, std::wstring &command) 
{
+llvm::ErrorOr<std::wstring>
+ProcessLauncherWindows::GetFlattenedWindowsCommandStringW(Args args) {
   if (args.empty())
-    return false;
+    return L"";
 
   std::vector<llvm::StringRef> args_ref;
   for (auto &entry : args.entries())
     args_ref.push_back(entry.ref());
 
-  llvm::ErrorOr<std::wstring> result =
-      llvm::sys::flattenWindowsCommandLine(args_ref);
-  if (result.getError())
-    return false;
-
-  command = *result;
-  return true;
+  return llvm::sys::flattenWindowsCommandLine(args_ref);
 }
 
 HostProcess
@@ -64,12 +63,13 @@ ProcessLauncherWindows::LaunchProcess(const 
ProcessLaunchInfo &launch_info,
                                       Status &error) {
   error.Clear();
 
-  std::string executable;
-  std::vector<char> environment;
-  STARTUPINFOEX startupinfoex = {};
-  STARTUPINFO &startupinfo = startupinfoex.StartupInfo;
+  std::vector<HANDLE> inherited_handles;
+  STARTUPINFOEXW startupinfoex = {};
+  STARTUPINFOW &startupinfo = startupinfoex.StartupInfo;
   PROCESS_INFORMATION pi = {};
 
+  HPCON hPC = launch_info.GetPTY().GetPseudoTerminalHandle();
+
   HANDLE stdin_handle = GetStdioHandle(launch_info, STDIN_FILENO);
   HANDLE stdout_handle = GetStdioHandle(launch_info, STDOUT_FILENO);
   HANDLE stderr_handle = GetStdioHandle(launch_info, STDERR_FILENO);
@@ -82,32 +82,34 @@ ProcessLauncherWindows::LaunchProcess(const 
ProcessLaunchInfo &launch_info,
       ::CloseHandle(stderr_handle);
   });
 
-  startupinfo.cb = sizeof(startupinfoex);
+  startupinfo.cb = sizeof(STARTUPINFOEXW);
   startupinfo.dwFlags |= STARTF_USESTDHANDLES;
-  startupinfo.hStdError =
-      stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
-  startupinfo.hStdInput =
-      stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
-  startupinfo.hStdOutput =
-      stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
 
-  std::vector<HANDLE> inherited_handles;
-  if (startupinfo.hStdError)
-    inherited_handles.push_back(startupinfo.hStdError);
-  if (startupinfo.hStdInput)
-    inherited_handles.push_back(startupinfo.hStdInput);
-  if (startupinfo.hStdOutput)
-    inherited_handles.push_back(startupinfo.hStdOutput);
+  if (hPC == INVALID_HANDLE_VALUE) {
+    startupinfo.hStdError =
+        stderr_handle ? stderr_handle : ::GetStdHandle(STD_ERROR_HANDLE);
+    startupinfo.hStdInput =
+        stdin_handle ? stdin_handle : ::GetStdHandle(STD_INPUT_HANDLE);
+    startupinfo.hStdOutput =
+        stdout_handle ? stdout_handle : ::GetStdHandle(STD_OUTPUT_HANDLE);
+
+    if (startupinfo.hStdError)
+      inherited_handles.push_back(startupinfo.hStdError);
+    if (startupinfo.hStdInput)
+      inherited_handles.push_back(startupinfo.hStdInput);
+    if (startupinfo.hStdOutput)
+      inherited_handles.push_back(startupinfo.hStdOutput);
+  }
 
   SIZE_T attributelist_size = 0;
   InitializeProcThreadAttributeList(/*lpAttributeList=*/nullptr,
                                     /*dwAttributeCount=*/1, /*dwFlags=*/0,
                                     &attributelist_size);
 
-  startupinfoex.lpAttributeList =
-      static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attributelist_size));
-  auto free_attributelist =
-      llvm::make_scope_exit([&] { free(startupinfoex.lpAttributeList); });
+  startupinfoex.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
+      GetProcessHeap(), 0, attributelist_size);
+  auto free_attributelist = llvm::make_scope_exit(
+      [&] { HeapFree(GetProcessHeap(), 0, startupinfoex.lpAttributeList); });
   if (!InitializeProcThreadAttributeList(startupinfoex.lpAttributeList,
                                          /*dwAttributeCount=*/1, /*dwFlags=*/0,
                                          &attributelist_size)) {
@@ -116,21 +118,31 @@ ProcessLauncherWindows::LaunchProcess(const 
ProcessLaunchInfo &launch_info,
   }
   auto delete_attributelist = llvm::make_scope_exit(
       [&] { DeleteProcThreadAttributeList(startupinfoex.lpAttributeList); });
-  for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
-    const FileAction *act = launch_info.GetFileActionAtIndex(i);
-    if (act->GetAction() == FileAction::eFileActionDuplicate &&
-        act->GetFD() == act->GetActionArgument())
-      inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
-  }
-  if (!inherited_handles.empty()) {
-    if (!UpdateProcThreadAttribute(
-            startupinfoex.lpAttributeList, /*dwFlags=*/0,
-            PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
-            inherited_handles.size() * sizeof(HANDLE),
-            /*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
+
+  if (hPC != INVALID_HANDLE_VALUE) {
+    if (!UpdateProcThreadAttribute(startupinfoex.lpAttributeList, 0,
+                                   PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC,
+                                   sizeof(hPC), NULL, NULL)) {
       error = Status(::GetLastError(), eErrorTypeWin32);
       return HostProcess();
     }
+  } else {
+    for (size_t i = 0; i < launch_info.GetNumFileActions(); ++i) {
+      const FileAction *act = launch_info.GetFileActionAtIndex(i);
+      if (act->GetAction() == FileAction::eFileActionDuplicate &&
+          act->GetFD() == act->GetActionArgument())
+        inherited_handles.push_back(reinterpret_cast<HANDLE>(act->GetFD()));
+    }
+    if (!inherited_handles.empty()) {
+      if (!UpdateProcThreadAttribute(
+              startupinfoex.lpAttributeList, /*dwFlags=*/0,
+              PROC_THREAD_ATTRIBUTE_HANDLE_LIST, inherited_handles.data(),
+              inherited_handles.size() * sizeof(HANDLE),
+              /*lpPreviousValue=*/nullptr, /*lpReturnSize=*/nullptr)) {
+        error = Status(::GetLastError(), eErrorTypeWin32);
+        return HostProcess();
+      }
+    }
   }
 
   const char *hide_console_var =
@@ -146,31 +158,37 @@ ProcessLauncherWindows::LaunchProcess(const 
ProcessLaunchInfo &launch_info,
   if (launch_info.GetFlags().Test(eLaunchFlagDebug))
     flags |= DEBUG_ONLY_THIS_PROCESS;
 
-  if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO))
+  if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO) ||
+      hPC != INVALID_HANDLE_VALUE)
     flags &= ~CREATE_NEW_CONSOLE;
 
-  LPVOID env_block = nullptr;
-  ::CreateEnvironmentBuffer(launch_info.GetEnvironment(), environment);
-  env_block = environment.data();
+  std::vector<wchar_t> environment =
+      CreateEnvironmentBufferW(launch_info.GetEnvironment());
+  LPVOID env_block = environment.empty() ? nullptr : environment.data();
 
-  executable = launch_info.GetExecutableFile().GetPath();
-  std::wstring wcommandLine;
-  GetFlattenedWindowsCommandString(launch_info.GetArguments(), wcommandLine);
-
-  std::wstring wexecutable, wworkingDirectory;
-  llvm::ConvertUTF8toWide(executable, wexecutable);
-  llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetPath(),
-                          wworkingDirectory);
+  auto wcommandLineOrErr =
+      GetFlattenedWindowsCommandStringW(launch_info.GetArguments());
+  if (!wcommandLineOrErr) {
+    error = Status(wcommandLineOrErr.getError());
+    return HostProcess();
+  }
+  std::wstring wcommandLine = *wcommandLineOrErr;
   // If the command line is empty, it's best to pass a null pointer to tell
   // CreateProcessW to use the executable name as the command line.  If the
   // command line is not empty, its contents may be modified by CreateProcessW.
   WCHAR *pwcommandLine = wcommandLine.empty() ? nullptr : &wcommandLine[0];
 
+  std::wstring wexecutable, wworkingDirectory;
+  llvm::ConvertUTF8toWide(launch_info.GetExecutableFile().GetPath(),
+                          wexecutable);
+  llvm::ConvertUTF8toWide(launch_info.GetWorkingDirectory().GetPath(),
+                          wworkingDirectory);
+
   BOOL result = ::CreateProcessW(
       wexecutable.c_str(), pwcommandLine, NULL, NULL,
       /*bInheritHandles=*/!inherited_handles.empty(), flags, env_block,
       wworkingDirectory.size() == 0 ? NULL : wworkingDirectory.c_str(),
-      reinterpret_cast<STARTUPINFO *>(&startupinfoex), &pi);
+      reinterpret_cast<STARTUPINFOW *>(&startupinfoex), &pi);
 
   if (!result) {
     // Call GetLastError before we make any other system calls.
@@ -223,4 +241,4 @@ ProcessLauncherWindows::GetStdioHandle(const 
ProcessLaunchInfo &launch_info,
   HANDLE result = ::CreateFileW(wpath.c_str(), access, share, &secattr, create,
                                 flags, NULL);
   return (result == INVALID_HANDLE_VALUE) ? NULL : result;
-}
+}
\ No newline at end of file
diff --git a/lldb/source/Host/windows/PseudoTerminalWindows.cpp 
b/lldb/source/Host/windows/PseudoTerminalWindows.cpp
new file mode 100644
index 0000000000000..38ebbbce84cfe
--- /dev/null
+++ b/lldb/source/Host/windows/PseudoTerminalWindows.cpp
@@ -0,0 +1,68 @@
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
+
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Errno.h"
+
+using namespace lldb_private;
+
+void PseudoTerminalWindows::Close() {
+  if (m_conpty_handle != INVALID_HANDLE_VALUE)
+    ClosePseudoConsole(m_conpty_handle);
+  CloseHandle(m_conpty_input);
+  CloseHandle(m_conpty_output);
+  m_conpty_handle = INVALID_HANDLE_VALUE;
+  m_conpty_input = INVALID_HANDLE_VALUE;
+  m_conpty_output = INVALID_HANDLE_VALUE;
+}
+
+llvm::Error PseudoTerminalWindows::OpenFirstAvailablePrimary(int oflag) {
+  HRESULT hr;
+  HANDLE hInputRead = INVALID_HANDLE_VALUE;
+  HANDLE hInputWrite = INVALID_HANDLE_VALUE;
+  HANDLE hOutputRead = INVALID_HANDLE_VALUE;
+  HANDLE hOutputWrite = INVALID_HANDLE_VALUE;
+
+  wchar_t pipe_name[MAX_PATH];
+  swprintf(pipe_name, MAX_PATH, L"\\\\.\\pipe\\conpty-%d-%p",
+           GetCurrentProcessId(), this);
+
+  hOutputRead =
+      CreateNamedPipeW(pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+                       PIPE_TYPE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, NULL);
+  hOutputWrite = CreateFileW(pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL, NULL);
+
+  if (!CreatePipe(&hInputRead, &hInputWrite, NULL, 0))
+    return llvm::errorCodeToError(
+        std::error_code(GetLastError(), std::system_category()));
+
+  // if (!CreatePipe(&hOutputRead, &hOutputWrite, NULL, 0)) {
+  //   CloseHandle(hInputRead);
+  //   CloseHandle(hInputWrite);
+  //   return llvm::errorCodeToError(
+  //       std::error_code(GetLastError(), std::system_category()));
+  // }
+
+  COORD consoleSize{80, 25};
+  HPCON hPC = INVALID_HANDLE_VALUE;
+  hr = CreatePseudoConsole(consoleSize, hInputRead, hOutputWrite, 0, &hPC);
+  CloseHandle(hInputRead);
+  CloseHandle(hOutputWrite);
+
+  if (FAILED(hr)) {
+    CloseHandle(hInputWrite);
+    CloseHandle(hOutputRead);
+    return llvm::make_error<llvm::StringError>(
+        "Failed to create Windows ConPTY pseudo terminal",
+        llvm::errc::io_error);
+  }
+
+  DWORD mode = PIPE_NOWAIT;
+  SetNamedPipeHandleState(hOutputRead, &mode, NULL, NULL);
+
+  m_conpty_handle = hPC;
+  m_conpty_output = hOutputRead;
+  m_conpty_input = hInputWrite;
+
+  return llvm::Error::success();
+}
\ No newline at end of file
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp 
b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 211868b51facb..d2fd372bfe9e3 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -136,7 +136,7 @@ SymbolContext 
ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(
   return {};
 }
 
-std::optional<MemoryRegionInfo>
+std::optional<lldb_private::MemoryRegionInfo>
 ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
     const lldb::SBMemoryRegionInfo &mem_region) const {
   if (!mem_region.m_opaque_up)
diff --git a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp 
b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
index c0c26cc5f1954..da52bd59bdc4c 100644
--- a/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -496,6 +496,7 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo 
&launch_info,
   // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
   // the process plugin.
 
+  Log *log = GetLog(LLDBLog::Platform);
   if (IsRemote()) {
     if (m_remote_platform_sp)
       return m_remote_platform_sp->DebugProcess(launch_info, debugger, target,
@@ -519,8 +520,14 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo 
&launch_info,
 
   // We need to launch and attach to the process.
   launch_info.GetFlags().Set(eLaunchFlagDebug);
-  if (process_sp)
-    error = process_sp->Launch(launch_info);
+  if (!process_sp)
+    return process_sp;
+  error = process_sp->Launch(launch_info);
+  if (error.Success())
+    process_sp->SetPseudoTerminalHandle(launch_info.GetPTYSP());
+  else
+    LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,
+              error.AsCString());
 
   return process_sp;
 }
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp 
b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 0fecefe23b88e..98bf477bb462a 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -21,6 +21,8 @@
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Host/HostNativeProcessBase.h"
 #include "lldb/Host/HostProcess.h"
+#include "lldb/Host/PseudoTerminal.h"
+#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
 #include "lldb/Host/windows/HostThreadWindows.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
@@ -121,22 +123,6 @@ ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
 
 ProcessWindows::~ProcessWindows() {}
 
-size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) {
-  error = Status::FromErrorString("GetSTDOUT unsupported on Windows");
-  return 0;
-}
-
-size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) {
-  error = Status::FromErrorString("GetSTDERR unsupported on Windows");
-  return 0;
-}
-
-size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
-                                Status &error) {
-  error = Status::FromErrorString("PutSTDIN unsupported on Windows");
-  return 0;
-}
-
 Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
   if (bp_site->HardwareRequired())
     return Status::FromErrorString("Hardware breakpoints are not supported.");
@@ -659,6 +645,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) {
   LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
 
   TargetSP target = CalculateTarget();
+  target->GetProcessLaunchInfo().GetPTY().Close();
   if (target) {
     ModuleSP executable_module = target->GetExecutableModule();
     ModuleList unloaded_modules;
@@ -954,4 +941,17 @@ Status ProcessWindows::DisableWatchpoint(WatchpointSP 
wp_sp, bool notify) {
 
   return error;
 }
+
+void ProcessWindows::SetPseudoTerminalHandle(
+    const std::shared_ptr<PseudoTerminal> &pty) {
+  m_stdio_communication.SetConnection(
+      std::make_unique<ConnectionGenericFile>(pty->GetPrimaryHandle(), false));
+  if (m_stdio_communication.IsConnected()) {
+    m_stdio_communication.SetReadThreadBytesReceivedCallback(
+        STDIOReadThreadBytesReceived, this);
+    m_stdio_communication.StartReadThread();
+
+    // TODO: Now read thread is set up, set up input reader.
+  }
+}
 } // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h 
b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
index 97284b7cd1436..49596e49a9f82 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -9,6 +9,7 @@
 #ifndef liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
 #define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
 
+#include "lldb/Host/windows/PseudoTerminalWindows.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/Status.h"
 #include "lldb/lldb-forward.h"
@@ -38,10 +39,6 @@ class ProcessWindows : public Process, public 
ProcessDebugger {
 
   ~ProcessWindows();
 
-  size_t GetSTDOUT(char *buf, size_t buf_size, Status &error) override;
-  size_t GetSTDERR(char *buf, size_t buf_size, Status &error) override;
-  size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override;
-
   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
 
   Status EnableBreakpointSite(BreakpointSite *bp_site) override;
@@ -101,6 +98,9 @@ class ProcessWindows : public Process, public 
ProcessDebugger {
   Status DisableWatchpoint(lldb::WatchpointSP wp_sp,
                            bool notify = true) override;
 
+  void
+  SetPseudoTerminalHandle(const std::shared_ptr<PseudoTerminal> &pty) override;
+
 protected:
   ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
 
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 69edea503002e..7059726671e05 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -6545,7 +6545,7 @@ Status Process::WriteMemoryTags(lldb::addr_t addr, size_t 
len,
 
 // Create a CoreFileMemoryRange from a MemoryRegionInfo
 static CoreFileMemoryRange
-CreateCoreFileMemoryRange(const MemoryRegionInfo &region) {
+CreateCoreFileMemoryRange(const lldb_private::MemoryRegionInfo &region) {
   const addr_t addr = region.GetRange().GetRangeBase();
   llvm::AddressRange range(addr, addr + region.GetRange().GetByteSize());
   return {range, region.GetLLDBPermissions()};
@@ -6554,7 +6554,7 @@ CreateCoreFileMemoryRange(const MemoryRegionInfo &region) 
{
 // Add dirty pages to the core file ranges and return true if dirty pages
 // were added. Return false if the dirty page information is not valid or in
 // the region.
-static bool AddDirtyPages(const MemoryRegionInfo &region,
+static bool AddDirtyPages(const lldb_private::MemoryRegionInfo &region,
                           CoreFileMemoryRanges &ranges) {
   const auto &dirty_page_list = region.GetDirtyPageList();
   if (!dirty_page_list)
@@ -6593,8 +6593,8 @@ static bool AddDirtyPages(const MemoryRegionInfo &region,
 // given region. If the region has dirty page information, only dirty pages
 // will be added to \a ranges, else the entire range will be added to \a
 // ranges.
-static void AddRegion(const MemoryRegionInfo &region, bool try_dirty_pages,
-                      CoreFileMemoryRanges &ranges) {
+static void AddRegion(const lldb_private::MemoryRegionInfo &region,
+                      bool try_dirty_pages, CoreFileMemoryRanges &ranges) {
   // Don't add empty ranges.
   if (region.GetRange().GetByteSize() == 0)
     return;
@@ -6617,7 +6617,7 @@ static void SaveDynamicLoaderSections(Process &process,
   if (!dyld)
     return;
 
-  std::vector<MemoryRegionInfo> dynamic_loader_mem_regions;
+  std::vector<lldb_private::MemoryRegionInfo> dynamic_loader_mem_regions;
   std::function<bool(const lldb_private::Thread &)> save_thread_predicate =
       [&](const lldb_private::Thread &t) -> bool {
     return options.ShouldThreadBeSaved(t.GetID());
@@ -6742,10 +6742,11 @@ static void GetCoreFileSaveRangesStackOnly(Process 
&process,
 
 // TODO: We should refactor CoreFileMemoryRanges to use the lldb range type, 
and
 // then add an intersect method on it, or MemoryRegionInfo.
-static MemoryRegionInfo Intersect(const MemoryRegionInfo &lhs,
-                                  const MemoryRegionInfo::RangeType &rhs) {
+static lldb_private::MemoryRegionInfo
+Intersect(const lldb_private::MemoryRegionInfo &lhs,
+          const MemoryRegionInfo::RangeType &rhs) {
 
-  MemoryRegionInfo region_info;
+  lldb_private::MemoryRegionInfo region_info;
   region_info.SetLLDBPermissions(lhs.GetLLDBPermissions());
   region_info.GetRange() = lhs.GetRange().Intersect(rhs);
 
diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py 
b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
index ca881f1d817c5..4196c8be24fc8 100644
--- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
+++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py
@@ -16,7 +16,6 @@
 
 
 class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase):
-    @skipIfWindows
     def test_default(self):
         """
         Tests the default launch of a simple program. No arguments,
diff --git 
a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp 
b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index 012eae02d5857..966b37e09ee55 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -326,7 +326,7 @@ TEST_F(GDBRemoteCommunicationClientTest, 
SendSignalsToIgnore) {
 
 TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) {
   const lldb::addr_t addr = 0xa000;
-  MemoryRegionInfo region_info;
+  lldb_private::MemoryRegionInfo region_info;
   std::future<Status> result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
   });
@@ -343,13 +343,16 @@ TEST_F(GDBRemoteCommunicationClientTest, 
GetMemoryRegionInfo) {
   EXPECT_TRUE(result.get().Success());
   EXPECT_EQ(addr, region_info.GetRange().GetRangeBase());
   EXPECT_EQ(0x2000u, region_info.GetRange().GetByteSize());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetReadable());
-  EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetWritable());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetExecutable());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.GetReadable());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.GetWritable());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.GetExecutable());
   EXPECT_EQ("/foo/bar.so", region_info.GetName().GetStringRef());
-  EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.GetMemoryTagged());
-  EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsStackMemory());
-  EXPECT_EQ(MemoryRegionInfo::eDontKnow, region_info.IsShadowStack());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+            region_info.GetMemoryTagged());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+            region_info.IsStackMemory());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eDontKnow,
+            region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
@@ -358,9 +361,9 @@ TEST_F(GDBRemoteCommunicationClientTest, 
GetMemoryRegionInfo) {
   HandlePacket(server, "qMemoryRegionInfo:a000",
                "start:a000;size:2000;flags:;type:stack;");
   EXPECT_TRUE(result.get().Success());
-  EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetMemoryTagged());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
-  EXPECT_EQ(MemoryRegionInfo::eNo, region_info.IsShadowStack());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, 
region_info.GetMemoryTagged());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsStackMemory());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
@@ -369,9 +372,10 @@ TEST_F(GDBRemoteCommunicationClientTest, 
GetMemoryRegionInfo) {
   HandlePacket(server, "qMemoryRegionInfo:a000",
                "start:a000;size:2000;flags: mt  zz mt ss  ;type:ha,ha,stack;");
   EXPECT_TRUE(result.get().Success());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetMemoryTagged());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsStackMemory());
-  EXPECT_EQ(MemoryRegionInfo::eYes, region_info.IsShadowStack());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes,
+            region_info.GetMemoryTagged());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsStackMemory());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eYes, region_info.IsShadowStack());
 
   result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
@@ -380,12 +384,12 @@ TEST_F(GDBRemoteCommunicationClientTest, 
GetMemoryRegionInfo) {
   HandlePacket(server, "qMemoryRegionInfo:a000",
                "start:a000;size:2000;type:heap;");
   EXPECT_TRUE(result.get().Success());
-  EXPECT_EQ(MemoryRegionInfo::eNo, region_info.IsStackMemory());
+  EXPECT_EQ(lldb_private::MemoryRegionInfo::eNo, region_info.IsStackMemory());
 }
 
 TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) {
   const lldb::addr_t addr = 0x4000;
-  MemoryRegionInfo region_info;
+  lldb_private::MemoryRegionInfo region_info;
   std::future<Status> result = std::async(std::launch::async, [&] {
     return client.GetMemoryRegionInfo(addr, region_info);
   });
diff --git a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn 
b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
index 10c5f95edf5fd..0c3e42304933b 100644
--- a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn
@@ -74,6 +74,7 @@ static_library("Host") {
       "windows/MainLoopWindows.cpp",
       "windows/PipeWindows.cpp",
       "windows/ProcessLauncherWindows.cpp",
+      "windows/PseudoTerminalWindows.cpp",
       "windows/ProcessRunLock.cpp",
     ]
   } else {

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to