Code to add WSLProfiles. (#1050)

* Code to add WSLProfiles.

* Updates recomended by miniksa

* Corrections from Mauve

* More updates from miniska (clarified WaitForSingleObject errors, and moved the try block to the calling function)

* Added THROW_LAST_ERROR for WAIT_FAILED instead of passing an unhandled exception.

* Migrate STL dependancies to LibraryIncludes.h

* Renamed function to provide more clarity

* Set WSL starting directory.

* Default Linux icon and brackets on new lines.

* Added system path so we don't rely on execution from the PATH environment variable.  Removed incorrect error useage.  Removed variable that was not required.

* Remove default directory setting.
This commit is contained in:
Jeremy Banks 2019-06-07 17:12:32 -04:00 committed by Mike Griese
parent 6b51d783c2
commit 31b614d5b2
3 changed files with 82 additions and 0 deletions

View file

@ -4,6 +4,8 @@
#include "pch.h"
#include <argb.h>
#include <conattrs.hpp>
#include <io.h>
#include <fcntl.h>
#include "CascadiaSettings.h"
#include "../../types/inc/utils.hpp"
#include "../../inc/DefaultSettings.h"
@ -21,6 +23,7 @@ static constexpr GUID TERMINAL_PROFILE_NAMESPACE_GUID =
static constexpr std::wstring_view PACKAGED_PROFILE_ICON_PATH{ L"ms-appx:///ProfileIcons/" };
static constexpr std::wstring_view PACKAGED_PROFILE_ICON_EXTENSION{ L".png" };
static constexpr std::wstring_view DEFAULT_LINUX_ICON_GUID{ L"{9acb9455-ca41-5af7-950f-6bca1bc9722f}" };
CascadiaSettings::CascadiaSettings() :
_globals{},
@ -227,6 +230,11 @@ void CascadiaSettings::_CreateDefaultProfiles()
_profiles.emplace_back(powershellProfile);
_profiles.emplace_back(cmdProfile);
try
{
_AppendWslProfiles(_profiles);
}
CATCH_LOG()
}
// Method Description:
@ -467,6 +475,78 @@ bool CascadiaSettings::_isPowerShellCoreInstalledInPath(const std::wstring_view
return false;
}
// Function Description:
// - Adds all of the WSL profiles to the provided container.
// Arguments:
// - A ref to the profiles container where the WSL profiles are to be added
// Return Value:
// - <none>
void CascadiaSettings::_AppendWslProfiles(std::vector<TerminalApp::Profile>& profileStorage)
{
wil::unique_handle readPipe;
wil::unique_handle writePipe;
SECURITY_ATTRIBUTES sa{ sizeof(sa), nullptr, true };
THROW_IF_WIN32_BOOL_FALSE(CreatePipe(&readPipe, &writePipe, &sa, 0));
STARTUPINFO si{};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = writePipe.get();
si.hStdError = writePipe.get();
wil::unique_process_information pi{};
wil::unique_cotaskmem_string systemPath;
THROW_IF_FAILED(wil::GetSystemDirectoryW(systemPath));
std::wstring command(systemPath.get());
command += L"\\wsl.exe --list";
THROW_IF_WIN32_BOOL_FALSE(CreateProcessW(nullptr, const_cast<LPWSTR>(command.c_str()), nullptr, nullptr,
TRUE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi));
switch (WaitForSingleObject(pi.hProcess, INFINITE))
{
case WAIT_OBJECT_0:
break;
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
THROW_HR(ERROR_CHILD_NOT_COMPLETE);
case WAIT_FAILED:
THROW_LAST_ERROR();
default:
THROW_HR(ERROR_UNHANDLED_EXCEPTION);
}
DWORD exitCode;
if (GetExitCodeProcess(pi.hProcess, &exitCode) == false)
{
THROW_HR(E_INVALIDARG);
}
else if (exitCode != 0)
{
return;
}
DWORD bytesAvailable;
THROW_IF_WIN32_BOOL_FALSE(PeekNamedPipe(readPipe.get(), nullptr, NULL, nullptr, &bytesAvailable, nullptr));
std::wfstream pipe{ _wfdopen(_open_osfhandle((intptr_t)readPipe.get(), _O_WTEXT | _O_RDONLY), L"r") };
//don't worry about the handle returned from wfdOpen, readPipe handle is already managed by wil and closing the file handle will cause an error.
std::wstring wline;
std::getline(pipe, wline); //remove the header from the output.
while (pipe.tellp() < bytesAvailable)
{
std::getline(pipe, wline);
std::wstringstream wlinestream(wline);
if (wlinestream)
{
std::wstring distName;
std::getline(wlinestream, distName, L' ');
auto WSLDistro{ _CreateDefaultProfile(distName) };
WSLDistro.SetCommandline(L"wsl.exe -d " + distName);
WSLDistro.SetColorScheme({ L"Campbell" });
std::wstring iconPath{ PACKAGED_PROFILE_ICON_PATH };
iconPath.append(DEFAULT_LINUX_ICON_GUID);
iconPath.append(PACKAGED_PROFILE_ICON_EXTENSION);
WSLDistro.SetIconPath(iconPath);
profileStorage.emplace_back(WSLDistro);
}
}
}
// Function Description:
// - Get a environment variable string.
// Arguments:

View file

@ -70,6 +70,7 @@ private:
static std::optional<std::string> _LoadAsUnpackagedApp();
static bool _isPowerShellCoreInstalledInPath(const std::wstring_view programFileEnv, std::filesystem::path& cmdline);
static bool _isPowerShellCoreInstalled(std::filesystem::path& cmdline);
static void _AppendWslProfiles(std::vector<TerminalApp::Profile>& profileStorage);
static std::wstring ExpandEnvironmentVariableString(std::wstring_view source);
static Profile _CreateDefaultProfile(const std::wstring_view name);
};

View file

@ -37,6 +37,7 @@
#include <iterator>
#include <math.h>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <filesystem>
#include <functional>