Repository: microsoft/terminal (language: cpp)

Issue:
Terminal Preview 1.3 breaks Windows PowerShell 5 (32-bit x86)'s history save and view and its command line colors
### Environment

**Windows build number:** Microsoft Windows [Version 10.0.19042.422] for x64
**Windows Terminal version (if applicable):** 1.3.2382.0

Using the default Terminal settings.json file and without any PowerShell profile files.

### Steps to reproduce

1. Make sure that Windows Terminal Preview is registered to be run as `wt.exe` in Settings -> Apps -> Apps and features -> App execution aliases, and log out and log in if needed to make the setting fully take effect.
1. Run this command from Start -> Run: `wt.exe "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe"`
1. Type `get-help gv -ful` with one L, press Tab.
1. Observe `get-help gv -Full` with 2 letters L, and the colors of that string.
1. Press Enter to run the command.
1. Exit Terminal and restart it using the same command you previously used in Start -> Run.
1. Press the up arrow key repeatedly.

### Expected behavior

* In the `get-help` command you ran, `get-help` was in yellow and `-Full` was in a darker shade of gray than the other text.
* After relaunching Terminal, you could use the up arrow key to see your command history, including the `get-help` command you just ran.

### Actual behavior

* In the `get-help` command, all the text was the same color.
* The command history was not accessible.
* If you now run PowerShell (x86) using the old console window, you see that the `get-help` command and other commands you ran in PowerShell within Terminal were not recorded in the history.


Discussion / hints:
This is absolutely wild. `PSModulePath` contains the unexpanded token, `%ProgramFiles%`, which gets either inherited fully-expanded (from Explorer or pre-1.3 WT) or inherited unexpanded (post-1.3 WT) and expanded at `CreateProcess`-time.

It looks like PowerShell (x86) has been working thanks to a fluke this whole time. Neat!
The `PSReadline` module can't be found on 32-bit Windows PowerShell on Windows Terminal 1.3.

`get-module -l | measure` gives me a count of 143 on Windows Terminal 1.3 and 497 on Winodes Terminal 1.2 for PowerShell 32-bit.

On Windows Terminal 1.2 `get-module -l` shows modules from ´C:\Program Files\WindowsPowerShell\Modules\` and `C:\Program Files (x86)\WindowsPowerShell\Modules\` and on Windows Terminal 1.3 it only shows modules from `C:\Program Files (x86)\WindowsPowerShell\Modules\`.
If I explicitly import `C:\Program Files\WindowsPowerShell\Modules\PSReadline\2.0.0\PSReadLine.psm1`, it imports without any problems.
It's very curious that PowerShell ships every module in both places _except PSReadline_. It is additionally concerning that this has simply _worked_ forever (except perhaps there have been maybe ten users using weird configurations who have gotten the 32-bit module path and written it off as a fluke.)

We can fix this by expanding the environment variables in our newly-minted block before passing them off, but ... I'd like to understand how PowerShell expected this to work :smile:
Summoning @stevel-msft - Do you have any idea why PSReadline is the special case here?

Fix patch:
diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp
index acde96d3de5..b4e5978440b 100644
--- a/src/cascadia/TerminalConnection/ConptyConnection.cpp
+++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp
@@ -5,7 +5,6 @@
 
 #include "ConptyConnection.h"
 
-#include <UserEnv.h>
 #include <winternl.h>
 
 #include "ConptyConnection.g.cpp"
@@ -99,11 +98,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
             environment.clear();
         });
 
-        {
-            const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
-            // Populate the environment map with the current environment.
-            RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
-        }
+        // Populate the environment map with the current environment.
+        RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
 
         {
             // Convert connection Guid to string and ignore the enclosing '{}'.
diff --git a/src/types/Environment.cpp b/src/types/Environment.cpp
index 962297ace2c..106503d8404 100644
--- a/src/types/Environment.cpp
+++ b/src/types/Environment.cpp
@@ -3,50 +3,36 @@
 
 #include "precomp.h"
 #include "inc/Environment.hpp"
-#include "wil/token_helpers.h"
 
 using namespace ::Microsoft::Console::Utils;
 
 // We cannot use spand or not_null because we're dealing with \0\0-terminated buffers of unknown length
 #pragma warning(disable : 26481 26429)
 
-// Function Description:
-// - Wraps win32's CreateEnvironmentBlock to return a smart pointer.
-EnvironmentBlockPtr Microsoft::Console::Utils::CreateEnvironmentBlock()
-{
-    void* newEnvironmentBlock{ nullptr };
-    auto processToken{ wil::open_current_access_token(TOKEN_QUERY | TOKEN_DUPLICATE) };
-    if (!::CreateEnvironmentBlock(&newEnvironmentBlock, processToken.get(), FALSE))
-    {
-        return nullptr;
-    }
-    return EnvironmentBlockPtr{ newEnvironmentBlock };
-}
-
 // Function Description:
 // - Updates an EnvironmentVariableMapW with the current process's unicode
 //   environment variables ignoring ones already set in the provided map.
 // Arguments:
 // - map: The map to populate with the current processes's environment variables.
-// - environmentBlock: Optional environment block to use when filling map. If omitted,
-//   defaults to the current environment.
 // Return Value:
 // - S_OK if we succeeded, or an appropriate HRESULT for failing
-HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock) noexcept
+HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept
 try
 {
-    wchar_t const* activeEnvironmentBlock{ static_cast<wchar_t const*>(environmentBlock) };
+    LPWCH currentEnvVars{};
+    auto freeCurrentEnv = wil::scope_exit([&] {
+        if (currentEnvVars)
+        {
+            FreeEnvironmentStringsW(currentEnvVars);
+            currentEnvVars = nullptr;
+        }
+    });
 
-    wil::unique_environstrings_ptr currentEnvVars;
-    if (!activeEnvironmentBlock)
-    {
-        currentEnvVars.reset(::GetEnvironmentStringsW());
-        RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
-        activeEnvironmentBlock = currentEnvVars.get();
-    }
+    currentEnvVars = ::GetEnvironmentStringsW();
+    RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
 
     // Each entry is NULL-terminated; block is guaranteed to be double-NULL terminated at a minimum.
-    for (wchar_t const* lastCh{ activeEnvironmentBlock }; *lastCh != '\0'; ++lastCh)
+    for (wchar_t const* lastCh{ currentEnvVars }; *lastCh != '\0'; ++lastCh)
     {
         // Copy current entry into temporary map.
         const size_t cchEntry{ ::wcslen(lastCh) };
diff --git a/src/types/inc/Environment.hpp b/src/types/inc/Environment.hpp
index a982db60432..0994a177762 100644
--- a/src/types/inc/Environment.hpp
+++ b/src/types/inc/Environment.hpp
@@ -21,12 +21,9 @@ namespace Microsoft::Console::Utils
         }
     };
 
-    using EnvironmentBlockPtr = wil::unique_any<void*, decltype(::DestroyEnvironmentBlock), ::DestroyEnvironmentBlock>;
-    [[nodiscard]] EnvironmentBlockPtr CreateEnvironmentBlock();
-
     using EnvironmentVariableMapW = std::map<std::wstring, std::wstring, WStringCaseInsensitiveCompare>;
 
-    [[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock = nullptr) noexcept;
+    [[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept;
 
     [[nodiscard]] HRESULT EnvironmentMapToEnvironmentStringsW(EnvironmentVariableMapW& map,
                                                               std::vector<wchar_t>& newEnvVars) noexcept;
diff --git a/src/types/precomp.h b/src/types/precomp.h
index d14fc703a8d..0b4a1124db6 100644
--- a/src/types/precomp.h
+++ b/src/types/precomp.h
@@ -29,7 +29,6 @@ Module Name:
 
 // Windows Header Files:
 #include <windows.h>
-#include <userenv.h>
 #include <combaseapi.h>
 #include <UIAutomation.h>
 #include <objbase.h>


Test patch: