Reload environment variables by default; add setting to disable (#14999)
Adds a global setting `compatibility.reloadEnvironmentVariables` with a default value of `true`. When set, during connection creation a new environment block will be generated to ensure it has the latest environment variables. Closes #1125 Co-authored-by: Leonard Hecker <lhecker@microsoft.com>
This commit is contained in:
parent
65640f6fe3
commit
51661487c2
|
@ -34,7 +34,6 @@ DNE
|
|||
DONTADDTORECENT
|
||||
DWMSBT
|
||||
DWMWA
|
||||
DWMWA
|
||||
DWORDLONG
|
||||
endfor
|
||||
ENDSESSION
|
||||
|
@ -251,3 +250,4 @@ xtree
|
|||
xutility
|
||||
YIcon
|
||||
YMax
|
||||
zwstring
|
||||
|
|
|
@ -2164,6 +2164,11 @@
|
|||
"description": "When set to true, the background image for the currently focused profile is expanded to encompass the entire window, beneath other panes.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"compatibility.reloadEnvironmentVariables": {
|
||||
"default": true,
|
||||
"description": "When set to true, when opening a new tab or pane it will get reloaded environment variables.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"initialCols": {
|
||||
"default": 120,
|
||||
"description": "The number of columns displayed in the window upon first load. If \"launchMode\" is set to \"maximized\" (or \"maximizedFocus\"), this property is ignored.",
|
||||
|
|
|
@ -1274,6 +1274,8 @@ namespace winrt::TerminalApp::implementation
|
|||
winrt::guid());
|
||||
|
||||
valueSet.Insert(L"passthroughMode", Windows::Foundation::PropertyValue::CreateBoolean(settings.VtPassthrough()));
|
||||
valueSet.Insert(L"reloadEnvironmentVariables",
|
||||
Windows::Foundation::PropertyValue::CreateBoolean(_settings.GlobalSettings().ReloadEnvironmentVariables()));
|
||||
|
||||
conhostConn.Initialize(valueSet);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "ConptyConnection.h"
|
||||
|
||||
#include <conpty-static.h>
|
||||
#include <til/env.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#include "CTerminalHandoff.h"
|
||||
|
@ -95,7 +96,20 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
});
|
||||
|
||||
// Populate the environment map with the current environment.
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
|
||||
if (_reloadEnvironmentVariables)
|
||||
{
|
||||
til::env refreshedEnvironment;
|
||||
refreshedEnvironment.regenerate();
|
||||
|
||||
for (auto& [key, value] : refreshedEnvironment.as_map())
|
||||
{
|
||||
environment.try_emplace(key, std::move(value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
|
||||
}
|
||||
|
||||
{
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
|
@ -272,6 +286,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
{
|
||||
_passthroughMode = winrt::unbox_value_or<bool>(settings.TryLookup(L"passthroughMode").try_as<Windows::Foundation::IPropertyValue>(), _passthroughMode);
|
||||
}
|
||||
_reloadEnvironmentVariables = winrt::unbox_value_or<bool>(settings.TryLookup(L"reloadEnvironmentVariables").try_as<Windows::Foundation::IPropertyValue>(),
|
||||
_reloadEnvironmentVariables);
|
||||
}
|
||||
|
||||
if (_guid == guid{})
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
std::wstring _u16Str{};
|
||||
std::array<char, 4096> _buffer{};
|
||||
bool _passthroughMode{};
|
||||
bool _reloadEnvironmentVariables{};
|
||||
|
||||
struct StartupInfoFromDefTerm
|
||||
{
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_SETTING(Boolean, ForceFullRepaintRendering);
|
||||
INHERITABLE_SETTING(Boolean, SoftwareRendering);
|
||||
INHERITABLE_SETTING(Boolean, UseBackgroundImageForWindow);
|
||||
INHERITABLE_SETTING(Boolean, ReloadEnvironmentVariables);
|
||||
INHERITABLE_SETTING(Boolean, ForceVTInput);
|
||||
INHERITABLE_SETTING(Boolean, DebugFeaturesEnabled);
|
||||
INHERITABLE_SETTING(Boolean, StartOnUserLogin);
|
||||
|
|
|
@ -27,6 +27,7 @@ Author(s):
|
|||
X(bool, ForceFullRepaintRendering, "experimental.rendering.forceFullRepaint", false) \
|
||||
X(bool, SoftwareRendering, "experimental.rendering.software", false) \
|
||||
X(bool, UseBackgroundImageForWindow, "experimental.useBackgroundImageForWindow", false) \
|
||||
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \
|
||||
X(bool, ForceVTInput, "experimental.input.forceVT", false) \
|
||||
X(bool, TrimBlockSelection, "trimBlockSelection", true) \
|
||||
X(bool, DetectURLs, "experimental.detectURLs", true) \
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
#include <wil/token_helpers.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 26429) // Symbol '...' is never tested for nullness, it can be marked as not_null (f.23).
|
||||
#pragma warning(disable : 26472) // Don't use a static_cast for arithmetic conversions. Use brace initialization, gsl::narrow_cast or gsl::narrow (type.1).
|
||||
#pragma warning(disable : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
|
||||
#pragma warning(disable : 26490) // Don't use reinterpret_cast (type.1).
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
class EnvTests;
|
||||
#endif
|
||||
|
@ -26,13 +32,14 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// https://docs.microsoft.com/en-us/windows/desktop/ProcThread/changing-environment-variables
|
||||
//
|
||||
// - Returns CSTR_LESS_THAN, CSTR_EQUAL or CSTR_GREATER_THAN
|
||||
[[nodiscard]] int compare_string_ordinal(const std::wstring_view& lhs, const std::wstring_view& rhs) noexcept
|
||||
[[nodiscard]] inline int compare_string_ordinal(const std::wstring_view& lhs, const std::wstring_view& rhs) noexcept
|
||||
{
|
||||
int result = CompareStringOrdinal(lhs.data(),
|
||||
::base::saturated_cast<int>(lhs.size()),
|
||||
rhs.data(),
|
||||
::base::saturated_cast<int>(rhs.size()),
|
||||
TRUE);
|
||||
const auto result = CompareStringOrdinal(
|
||||
lhs.data(),
|
||||
::base::saturated_cast<int>(lhs.size()),
|
||||
rhs.data(),
|
||||
::base::saturated_cast<int>(rhs.size()),
|
||||
TRUE);
|
||||
FAIL_FAST_LAST_ERROR_IF(!result);
|
||||
return result;
|
||||
}
|
||||
|
@ -47,30 +54,30 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
|
||||
namespace vars
|
||||
{
|
||||
inline constexpr std::wstring_view system_root{ L"SystemRoot" };
|
||||
inline constexpr std::wstring_view system_drive{ L"SystemDrive" };
|
||||
inline constexpr std::wstring_view all_users_profile{ L"ALLUSERSPROFILE" };
|
||||
inline constexpr std::wstring_view public_var{ L"PUBLIC" };
|
||||
inline constexpr std::wstring_view program_data{ L"ProgramData" };
|
||||
inline constexpr std::wstring_view computer_name{ L"COMPUTERNAME" };
|
||||
inline constexpr std::wstring_view user_name{ L"USERNAME" };
|
||||
inline constexpr std::wstring_view user_domain{ L"USERDOMAIN" };
|
||||
inline constexpr std::wstring_view user_dns_domain{ L"USERDNSDOMAIN" };
|
||||
inline constexpr std::wstring_view home_drive{ L"HOMEDRIVE" };
|
||||
inline constexpr std::wstring_view home_share{ L"HOMESHARE" };
|
||||
inline constexpr std::wstring_view home_path{ L"HOMEPATH" };
|
||||
inline constexpr std::wstring_view user_profile{ L"USERPROFILE" };
|
||||
inline constexpr std::wstring_view app_data{ L"APPDATA" };
|
||||
inline constexpr std::wstring_view local_app_data{ L"LOCALAPPDATA" };
|
||||
inline constexpr wil::zwstring_view system_root{ L"SystemRoot" };
|
||||
inline constexpr wil::zwstring_view system_drive{ L"SystemDrive" };
|
||||
inline constexpr wil::zwstring_view all_users_profile{ L"ALLUSERSPROFILE" };
|
||||
inline constexpr wil::zwstring_view public_var{ L"PUBLIC" };
|
||||
inline constexpr wil::zwstring_view program_data{ L"ProgramData" };
|
||||
inline constexpr wil::zwstring_view computer_name{ L"COMPUTERNAME" };
|
||||
inline constexpr wil::zwstring_view user_name{ L"USERNAME" };
|
||||
inline constexpr wil::zwstring_view user_domain{ L"USERDOMAIN" };
|
||||
inline constexpr wil::zwstring_view user_dns_domain{ L"USERDNSDOMAIN" };
|
||||
inline constexpr wil::zwstring_view home_drive{ L"HOMEDRIVE" };
|
||||
inline constexpr wil::zwstring_view home_share{ L"HOMESHARE" };
|
||||
inline constexpr wil::zwstring_view home_path{ L"HOMEPATH" };
|
||||
inline constexpr wil::zwstring_view user_profile{ L"USERPROFILE" };
|
||||
inline constexpr wil::zwstring_view app_data{ L"APPDATA" };
|
||||
inline constexpr wil::zwstring_view local_app_data{ L"LOCALAPPDATA" };
|
||||
|
||||
inline constexpr std::wstring_view program_files{ L"ProgramFiles" };
|
||||
inline constexpr std::wstring_view program_files_x86{ L"ProgramFiles(x86)" };
|
||||
inline constexpr std::wstring_view program_files_arm64{ L"ProgramFiles(Arm)" };
|
||||
inline constexpr std::wstring_view program_w6432{ L"ProgramW6432" };
|
||||
inline constexpr std::wstring_view common_program_files{ L"CommonProgramFiles" };
|
||||
inline constexpr std::wstring_view common_program_files_x86{ L"CommonProgramFiles(x86)" };
|
||||
inline constexpr std::wstring_view common_program_files_arm64{ L"CommonProgramFiles(Arm)" };
|
||||
inline constexpr std::wstring_view common_program_w6432{ L"CommonProgramW6432" };
|
||||
inline constexpr wil::zwstring_view program_files{ L"ProgramFiles" };
|
||||
inline constexpr wil::zwstring_view program_files_x86{ L"ProgramFiles(x86)" };
|
||||
inline constexpr wil::zwstring_view program_files_arm64{ L"ProgramFiles(Arm)" };
|
||||
inline constexpr wil::zwstring_view program_w6432{ L"ProgramW6432" };
|
||||
inline constexpr wil::zwstring_view common_program_files{ L"CommonProgramFiles" };
|
||||
inline constexpr wil::zwstring_view common_program_files_x86{ L"CommonProgramFiles(x86)" };
|
||||
inline constexpr wil::zwstring_view common_program_files_arm64{ L"CommonProgramFiles(Arm)" };
|
||||
inline constexpr wil::zwstring_view common_program_w6432{ L"CommonProgramW6432" };
|
||||
|
||||
const std::array program_files_map{
|
||||
std::pair{ L"ProgramFilesDir", program_files },
|
||||
|
@ -89,11 +96,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
|
||||
namespace reg
|
||||
{
|
||||
inline constexpr std::wstring_view program_files_root{ LR"(Software\Microsoft\Windows\CurrentVersion)" };
|
||||
inline constexpr std::wstring_view system_env_var_root{ LR"(SYSTEM\CurrentControlSet\Control\Session Manager\Environment)" };
|
||||
inline constexpr std::wstring_view user_env_var_root{ LR"(Environment)" };
|
||||
inline constexpr std::wstring_view user_volatile_env_var_root{ LR"(Volatile Environment)" };
|
||||
inline constexpr std::wstring_view user_volatile_session_env_var_root_pattern{ LR"(Volatile Environment\{0:d})" };
|
||||
inline constexpr wil::zwstring_view program_files_root{ LR"(Software\Microsoft\Windows\CurrentVersion)" };
|
||||
inline constexpr wil::zwstring_view system_env_var_root{ LR"(SYSTEM\CurrentControlSet\Control\Session Manager\Environment)" };
|
||||
inline constexpr wil::zwstring_view user_env_var_root{ LR"(Environment)" };
|
||||
inline constexpr wil::zwstring_view user_volatile_env_var_root{ LR"(Volatile Environment)" };
|
||||
inline constexpr wil::zwstring_view user_volatile_session_env_var_root_pattern{ LR"(Volatile Environment\{0:d})" };
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -101,33 +108,32 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
{
|
||||
/** Looks up the computer name and fails if it is not found. */
|
||||
template<typename string_type, size_t initialBufferLength = MAX_COMPUTERNAME_LENGTH + 1>
|
||||
inline HRESULT GetComputerNameW(string_type& result) WI_NOEXCEPT
|
||||
HRESULT GetComputerNameW(string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, initialBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT {
|
||||
// If the function succeeds, the return value is the number of characters stored in the buffer
|
||||
// pointed to by lpBuffer, not including the terminating null character.
|
||||
//
|
||||
// If lpBuffer is not large enough to hold the data, the return value is the buffer size, in
|
||||
// characters, required to hold the string and its terminating null character and the contents of
|
||||
// lpBuffer are undefined.
|
||||
//
|
||||
// If the function fails, the return value is zero. If the specified environment variable was not
|
||||
// found in the environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, initialBufferLength>(result, [&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT {
|
||||
// If the function succeeds, the return value is the number of characters stored in the buffer
|
||||
// pointed to by lpBuffer, not including the terminating null character.
|
||||
//
|
||||
// If lpBuffer is not large enough to hold the data, the return value is the buffer size, in
|
||||
// characters, required to hold the string and its terminating null character and the contents of
|
||||
// lpBuffer are undefined.
|
||||
//
|
||||
// If the function fails, the return value is zero. If the specified environment variable was not
|
||||
// found in the environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND.
|
||||
|
||||
::SetLastError(ERROR_SUCCESS);
|
||||
::SetLastError(ERROR_SUCCESS);
|
||||
|
||||
DWORD length = static_cast<DWORD>(valueLength);
|
||||
DWORD length = static_cast<DWORD>(valueLength);
|
||||
|
||||
auto result = ::GetComputerNameW(value, &length);
|
||||
*valueLengthNeededWithNul = length;
|
||||
RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(result);
|
||||
if (*valueLengthNeededWithNul < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNul)++; // It fit, account for the null.
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
const auto result = ::GetComputerNameW(value, &length);
|
||||
*valueLengthNeededWithNul = length;
|
||||
RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(result);
|
||||
if (*valueLengthNeededWithNul < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNul)++; // It fit, account for the null.
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
}
|
||||
|
||||
/** Looks up the computer name and returns null if it is not found. */
|
||||
|
@ -161,18 +167,17 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
|
||||
/** Looks up a registry value from 'key' and fails if it is not found. */
|
||||
template<typename string_type, size_t initialBufferLength = 256>
|
||||
inline HRESULT RegQueryValueExW(HKEY key, PCWSTR valueName, string_type& result) WI_NOEXCEPT
|
||||
HRESULT RegQueryValueExW(HKEY key, PCWSTR valueName, string_type& result) WI_NOEXCEPT
|
||||
{
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, initialBufferLength>(result,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT {
|
||||
auto length = gsl::narrow<DWORD>(valueLength * sizeof(wchar_t));
|
||||
const auto status = ::RegQueryValueExW(key, valueName, 0, nullptr, reinterpret_cast<BYTE*>(value), &length);
|
||||
// length will receive the number of bytes including trailing null byte. Convert to a number of wchar_t's.
|
||||
// AdaptFixedSizeToAllocatedResult will then resize buffer to valueLengthNeededWithNull.
|
||||
// We're rounding up to prevent infinite loops if the data isn't a REG_SZ and length isn't divisible by 2.
|
||||
*valueLengthNeededWithNul = (length + sizeof(wchar_t) - 1) / sizeof(wchar_t);
|
||||
return status == ERROR_MORE_DATA ? S_OK : HRESULT_FROM_WIN32(status);
|
||||
});
|
||||
return wil::AdaptFixedSizeToAllocatedResult<string_type, initialBufferLength>(result, [&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT {
|
||||
auto length = gsl::narrow<DWORD>(valueLength * sizeof(wchar_t));
|
||||
const auto status = ::RegQueryValueExW(key, valueName, nullptr, nullptr, reinterpret_cast<BYTE*>(value), &length);
|
||||
// length will receive the number of bytes including trailing null byte. Convert to a number of wchar_t's.
|
||||
// AdaptFixedSizeToAllocatedResult will then resize buffer to valueLengthNeededWithNull.
|
||||
// We're rounding up to prevent infinite loops if the data isn't a REG_SZ and length isn't divisible by 2.
|
||||
*valueLengthNeededWithNul = (length + sizeof(wchar_t) - 1) / sizeof(wchar_t);
|
||||
return status == ERROR_MORE_DATA ? S_OK : HRESULT_FROM_WIN32(status);
|
||||
});
|
||||
}
|
||||
|
||||
/** Looks up a registry value from 'key' and returns null if it is not found. */
|
||||
|
@ -209,19 +214,18 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
template<typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT GetShortPathNameW(PCWSTR file, string_type& path)
|
||||
{
|
||||
const auto hr = wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path,
|
||||
[&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT {
|
||||
// Note that GetShortPathNameW() is not limited to MAX_PATH
|
||||
// but it does take a fixed size buffer.
|
||||
*valueLengthNeededWithNull = ::GetShortPathNameW(file, value, static_cast<DWORD>(valueLength));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
const auto hr = wil::AdaptFixedSizeToAllocatedResult<string_type, stackBufferLength>(path, [&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNull) -> HRESULT {
|
||||
// Note that GetShortPathNameW() is not limited to MAX_PATH
|
||||
// but it does take a fixed size buffer.
|
||||
*valueLengthNeededWithNull = ::GetShortPathNameW(file, value, static_cast<DWORD>(valueLength));
|
||||
RETURN_LAST_ERROR_IF(*valueLengthNeededWithNull == 0);
|
||||
WI_ASSERT((*value != L'\0') == (*valueLengthNeededWithNull < valueLength));
|
||||
if (*valueLengthNeededWithNull < valueLength)
|
||||
{
|
||||
(*valueLengthNeededWithNull)++; // it fit, account for the null
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -249,27 +253,27 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
std::map<std::wstring, std::wstring, til::details::wstring_case_insensitive_compare> _envMap{};
|
||||
|
||||
// We make copies of the environment variable names to ensure they are null terminated.
|
||||
void get(std::wstring variable)
|
||||
void get(wil::zwstring_view variable)
|
||||
{
|
||||
if (auto value = wil::TryGetEnvironmentVariableW(variable.c_str()))
|
||||
if (auto value = wil::TryGetEnvironmentVariableW<std::wstring>(variable.c_str()); !value.empty())
|
||||
{
|
||||
save_to_map(std::move(variable), std::move(value.get()));
|
||||
save_to_map(std::wstring{ variable }, std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
void get_computer_name()
|
||||
{
|
||||
if (auto value = til::details::wil_env::TryGetComputerNameW())
|
||||
if (auto value = til::details::wil_env::TryGetComputerNameW<std::wstring>(); !value.empty())
|
||||
{
|
||||
save_to_map(std::wstring{ til::details::vars::computer_name }, std::move(value.get()));
|
||||
save_to_map(std::wstring{ til::details::vars::computer_name }, std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
void get_user_name_and_domain()
|
||||
try
|
||||
{
|
||||
auto token = wil::open_current_access_token();
|
||||
auto user = wil::get_token_information<TOKEN_USER>(token.get());
|
||||
const auto token = wil::open_current_access_token();
|
||||
const auto user = wil::get_token_information<TOKEN_USER>(token.get());
|
||||
|
||||
DWORD accountNameSize = 0, userDomainSize = 0;
|
||||
SID_NAME_USE sidNameUse;
|
||||
|
@ -305,10 +309,10 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
}
|
||||
|
||||
void get_vars_from_registry(HKEY rootKey, std::wstring_view subkey)
|
||||
void get_vars_from_registry(HKEY rootKey, wil::zwstring_view subkey)
|
||||
{
|
||||
wil::unique_hkey key;
|
||||
if (RegOpenKeyExW(rootKey, subkey.data(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
if (RegOpenKeyExW(rootKey, subkey.c_str(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD maxValueNameSize = 0, maxValueDataSize = 0;
|
||||
if (RegQueryInfoKeyW(key.get(), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &maxValueNameSize, &maxValueDataSize, nullptr, nullptr) == ERROR_SUCCESS)
|
||||
|
@ -329,7 +333,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
|
||||
while (true)
|
||||
{
|
||||
DWORD result = RegEnumValueW(key.get(), index, valueName.data(), &valueNameSize, nullptr, &type, valueData.data(), &valueDataSize);
|
||||
const DWORD result = RegEnumValueW(key.get(), index, valueName.data(), &valueNameSize, nullptr, &type, valueData.data(), &valueDataSize);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
|
@ -363,11 +367,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
{
|
||||
if (is_path_var(valueName))
|
||||
{
|
||||
concat_var(valueName, std::wstring{ data });
|
||||
concat_var(valueName, std::move(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
set_user_environment_var(valueName, std::wstring{ data });
|
||||
set_user_environment_var(valueName, std::move(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,10 +453,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
// Otherwise, just take advantage of the one it has.
|
||||
if (existing->second.back() != L';')
|
||||
{
|
||||
existing->second.append(L";");
|
||||
existing->second.push_back(L';');
|
||||
}
|
||||
existing->second.append(value);
|
||||
save_to_map(std::move(var), std::move(existing->second));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -468,12 +471,12 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
}
|
||||
|
||||
static constexpr std::wstring_view temp{ L"temp" };
|
||||
static constexpr std::wstring_view tmp{ L"tmp" };
|
||||
std::wstring check_for_temp(std::wstring_view var, std::wstring_view value)
|
||||
{
|
||||
if (til::details::compare_string_ordinal(var.data(), temp.data()) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(var.data(), tmp.data()) == CSTR_EQUAL)
|
||||
static constexpr std::wstring_view temp{ L"temp" };
|
||||
static constexpr std::wstring_view tmp{ L"tmp" };
|
||||
if (til::details::compare_string_ordinal(var, temp) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(var, tmp) == CSTR_EQUAL)
|
||||
{
|
||||
return til::details::wil_env::GetShortPathNameW<std::wstring, 256>(value.data());
|
||||
}
|
||||
|
@ -483,17 +486,17 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
}
|
||||
|
||||
static constexpr std::wstring_view path{ L"Path" };
|
||||
static constexpr std::wstring_view libPath{ L"LibPath" };
|
||||
static constexpr std::wstring_view os2LibPath{ L"Os2LibPath" };
|
||||
bool is_path_var(std::wstring_view input)
|
||||
static bool is_path_var(std::wstring_view input) noexcept
|
||||
{
|
||||
return til::details::compare_string_ordinal(input.data(), path.data()) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(input.data(), libPath.data()) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(input.data(), os2LibPath.data()) == CSTR_EQUAL;
|
||||
static constexpr std::wstring_view path{ L"Path" };
|
||||
static constexpr std::wstring_view libPath{ L"LibPath" };
|
||||
static constexpr std::wstring_view os2LibPath{ L"Os2LibPath" };
|
||||
return til::details::compare_string_ordinal(input, path) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(input, libPath) == CSTR_EQUAL ||
|
||||
til::details::compare_string_ordinal(input, os2LibPath) == CSTR_EQUAL;
|
||||
}
|
||||
|
||||
void strip_trailing_null(std::wstring& str)
|
||||
static void strip_trailing_null(std::wstring& str) noexcept
|
||||
{
|
||||
if (!str.empty() && str.back() == L'\0')
|
||||
{
|
||||
|
@ -501,9 +504,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
}
|
||||
|
||||
void parse(wchar_t* block)
|
||||
void parse(const wchar_t* lastCh)
|
||||
{
|
||||
for (wchar_t const* lastCh{ block }; *lastCh != '\0'; ++lastCh)
|
||||
for (; *lastCh != '\0'; ++lastCh)
|
||||
{
|
||||
// Copy current entry into temporary map.
|
||||
const size_t cchEntry{ ::wcslen(lastCh) };
|
||||
|
@ -523,11 +526,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
}
|
||||
|
||||
public:
|
||||
env()
|
||||
{
|
||||
}
|
||||
env() = default;
|
||||
|
||||
env(wchar_t* block)
|
||||
env(const wchar_t* block)
|
||||
{
|
||||
parse(block);
|
||||
}
|
||||
|
@ -535,20 +536,20 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
void regenerate()
|
||||
{
|
||||
// Generally replicates the behavior of shell32!RegenerateUserEnvironment
|
||||
get(std::wstring{ til::details::vars::system_root });
|
||||
get(std::wstring{ til::details::vars::system_drive });
|
||||
get(std::wstring{ til::details::vars::all_users_profile });
|
||||
get(std::wstring{ til::details::vars::public_var });
|
||||
get(std::wstring{ til::details::vars::program_data });
|
||||
get(til::details::vars::system_root);
|
||||
get(til::details::vars::system_drive);
|
||||
get(til::details::vars::all_users_profile);
|
||||
get(til::details::vars::public_var);
|
||||
get(til::details::vars::program_data);
|
||||
get_computer_name();
|
||||
get_user_name_and_domain();
|
||||
get(std::wstring{ til::details::vars::user_dns_domain });
|
||||
get(std::wstring{ til::details::vars::home_drive });
|
||||
get(std::wstring{ til::details::vars::home_share });
|
||||
get(std::wstring{ til::details::vars::home_path });
|
||||
get(std::wstring{ til::details::vars::user_profile });
|
||||
get(std::wstring{ til::details::vars::app_data });
|
||||
get(std::wstring{ til::details::vars::local_app_data });
|
||||
get(til::details::vars::user_dns_domain);
|
||||
get(til::details::vars::home_drive);
|
||||
get(til::details::vars::home_share);
|
||||
get(til::details::vars::home_path);
|
||||
get(til::details::vars::user_profile);
|
||||
get(til::details::vars::app_data);
|
||||
get(til::details::vars::local_app_data);
|
||||
get_program_files();
|
||||
get_vars_from_registry(HKEY_LOCAL_MACHINE, til::details::vars::reg::system_env_var_root);
|
||||
// not processing autoexec.bat
|
||||
|
@ -571,9 +572,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||
return result;
|
||||
}
|
||||
|
||||
std::map<std::wstring, std::wstring, til::details::wstring_case_insensitive_compare>& as_map()
|
||||
auto& as_map() noexcept
|
||||
{
|
||||
return _envMap;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
|
|
Loading…
Reference in New Issue