From 51661487c242ab4384d3d39361437cecadb66706 Mon Sep 17 00:00:00 2001 From: Ian O'Neill Date: Fri, 17 Mar 2023 18:50:18 +0000 Subject: [PATCH] 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 --- .github/actions/spelling/allow/apis.txt | 2 +- doc/cascadia/profiles.schema.json | 5 + src/cascadia/TerminalApp/TerminalPage.cpp | 2 + .../TerminalConnection/ConptyConnection.cpp | 18 +- .../TerminalConnection/ConptyConnection.h | 1 + .../GlobalAppSettings.idl | 1 + .../TerminalSettingsModel/MTSMSettings.h | 1 + src/inc/til/env.h | 255 +++++++++--------- 8 files changed, 157 insertions(+), 128 deletions(-) diff --git a/.github/actions/spelling/allow/apis.txt b/.github/actions/spelling/allow/apis.txt index ce36d8d2a2..0843ec910e 100644 --- a/.github/actions/spelling/allow/apis.txt +++ b/.github/actions/spelling/allow/apis.txt @@ -34,7 +34,6 @@ DNE DONTADDTORECENT DWMSBT DWMWA -DWMWA DWORDLONG endfor ENDSESSION @@ -251,3 +250,4 @@ xtree xutility YIcon YMax +zwstring diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index bac66b8066..64b5903dc3 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -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.", diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e4e5c8a0a1..16edcfcf9f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -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); diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 9ddc90cdf2..fef88c3362 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -5,6 +5,7 @@ #include "ConptyConnection.h" #include +#include #include #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(settings.TryLookup(L"passthroughMode").try_as(), _passthroughMode); } + _reloadEnvironmentVariables = winrt::unbox_value_or(settings.TryLookup(L"reloadEnvironmentVariables").try_as(), + _reloadEnvironmentVariables); } if (_guid == guid{}) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 3709ccef33..60528dc046 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -89,6 +89,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation std::wstring _u16Str{}; std::array _buffer{}; bool _passthroughMode{}; + bool _reloadEnvironmentVariables{}; struct StartupInfoFromDefTerm { diff --git a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl index 738159b5eb..e986339665 100644 --- a/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl +++ b/src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl @@ -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); diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h index 73d7cd8000..af4798a75b 100644 --- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h +++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h @@ -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) \ diff --git a/src/inc/til/env.h b/src/inc/til/env.h index 031ea4388e..72e626a8da 100644 --- a/src/inc/til/env.h +++ b/src/inc/til/env.h @@ -6,6 +6,12 @@ #include #include +#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(lhs.size()), - rhs.data(), - ::base::saturated_cast(rhs.size()), - TRUE); + const auto result = CompareStringOrdinal( + lhs.data(), + ::base::saturated_cast(lhs.size()), + rhs.data(), + ::base::saturated_cast(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 - inline HRESULT GetComputerNameW(string_type& result) WI_NOEXCEPT + HRESULT GetComputerNameW(string_type& result) WI_NOEXCEPT { - return wil::AdaptFixedSizeToAllocatedResult(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(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(valueLength); + DWORD length = static_cast(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 - 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(result, - [&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT { - auto length = gsl::narrow(valueLength * sizeof(wchar_t)); - const auto status = ::RegQueryValueExW(key, valueName, 0, nullptr, reinterpret_cast(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(result, [&](_Out_writes_(valueLength) PWSTR value, size_t valueLength, _Out_ size_t* valueLengthNeededWithNul) -> HRESULT { + auto length = gsl::narrow(valueLength * sizeof(wchar_t)); + const auto status = ::RegQueryValueExW(key, valueName, nullptr, nullptr, reinterpret_cast(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 HRESULT GetShortPathNameW(PCWSTR file, string_type& path) { - const auto hr = wil::AdaptFixedSizeToAllocatedResult(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(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(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(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 _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(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(); !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.get()); + const auto token = wil::open_current_access_token(); + const auto user = wil::get_token_information(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(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& as_map() + auto& as_map() noexcept { return _envMap; } }; }; + +#pragma warning(pop)