terminal/src/types/inc/Environment.hpp
Dustin L. Howett 849243af99
Always create a new environment block before we spawn a process (#7243)
This commit ensures that we always furnish a new process with the
cleanest, most up-to-date environment variables we can. There is a minor
cost here in that WT will no longer pass environment variables that it
itself inherited to its child processes.

This could be considered a reasonable sacrifice. It will also remove
somebody else's TERM, TERM_PROGRAM and TERM_PROGRAM_VERSION from the
environment, which could be considered a win.

I validated  that GetCurrentProcessToken returns a token we're
_technically able_ to use with this API; it is roughly equivalent to
OpenProcessToken(GetCurrentProcess) in that it returns the current
active _access token_ (which is what CreateEnvironmentBlock wants.)

There's been discussion about doing a 3-way merge between WT's
environment and the new one. This will be complicated and I'd like to
scream test the 0-way merge first ;P

Related to #1125 (but it does not close it or resolve any of the other
issues it calls out.)

Fixes #7239
Fixes #7204 ("App Paths" value creeping into wt's environment)
2020-08-11 23:58:45 +00:00

35 lines
1.5 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft::Console::Utils
{
//
// A case-insensitive wide-character map is used to store environment variables
// due to documented requirements:
//
// "All strings in the environment block must be sorted alphabetically by name.
// The sort is case-insensitive, Unicode order, without regard to locale.
// Because the equal sign is a separator, it must not be used in the name of
// an environment variable."
// https://docs.microsoft.com/en-us/windows/desktop/ProcThread/changing-environment-variables
//
struct WStringCaseInsensitiveCompare
{
[[nodiscard]] bool operator()(const std::wstring& lhs, const std::wstring& rhs) const noexcept
{
return (::_wcsicmp(lhs.c_str(), rhs.c_str()) < 0);
}
};
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 EnvironmentMapToEnvironmentStringsW(EnvironmentVariableMapW& map,
std::vector<wchar_t>& newEnvVars) noexcept;
};