Skip to content

Commit

Permalink
Remove the fallback to wsl.exe when HKCU\...\Lxss doesn't exist (#13436)
Browse files Browse the repository at this point in the history
The main result of this fallback is that we attempt to launch wsl.exe
when the user hasn't installed or interacted with WSL. On our test
machines, that results in the creation of a wsl.exe process that tells
us precisely nothing; on WDAC managed machines it results in an Event
Log entry about spawning another (possibly blocked) process.

The registry is more reliable, and if the "API" it provides changes we
can just rev terminal.

Closes #11716

(cherry picked from commit f025c53)
Service-Card-Id: 83892843
Service-Version: 1.14
  • Loading branch information
DHowett committed Jul 5, 2022
1 parent d7d15db commit a47bb0d
Showing 1 changed file with 3 additions and 106 deletions.
109 changes: 3 additions & 106 deletions src/cascadia/TerminalSettingsModel/WslDistroGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include "LegacyProfileGeneratorNamespaces.h"
#include "../../inc/DefaultSettings.h"

#include <io.h>
#include <fcntl.h>
#include "DynamicProfileUtils.h"

static constexpr std::wstring_view WslHomeDirectory{ L"~" };
Expand Down Expand Up @@ -68,105 +66,6 @@ static winrt::com_ptr<implementation::Profile> makeProfile(const std::wstring& d
return WSLDistro;
}

// Method Description:
// - Enumerates all the installed WSL distros to create profiles for them.
// Arguments:
// - <none>
// Return Value:
// - a vector with all distros for all the installed WSL distros
static void legacyGenerate(std::vector<winrt::com_ptr<implementation::Profile>>& profiles)
{
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{ 0 };
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, 2000))
{
case WAIT_OBJECT_0:
break;
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
return;
case WAIT_FAILED:
THROW_LAST_ERROR();
default:
THROW_HR(ERROR_UNHANDLED_EXCEPTION);
}
DWORD exitCode;
if (!GetExitCodeProcess(pi.hProcess, &exitCode))
{
THROW_HR(E_INVALIDARG);
}
else if (exitCode != 0)
{
return;
}
DWORD bytesAvailable;
THROW_IF_WIN32_BOOL_FALSE(PeekNamedPipe(readPipe.get(), nullptr, NULL, nullptr, &bytesAvailable, nullptr));
// "The _open_osfhandle call transfers ownership of the Win32 file handle to the file descriptor."
// (https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/open-osfhandle?view=vs-2019)
// so, we detach_from_smart_pointer it -- but...
// "File descriptors passed into _fdopen are owned by the returned FILE * stream.
// If _fdopen is successful, do not call _close on the file descriptor.
// Calling fclose on the returned FILE * also closes the file descriptor."
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fdopen-wfdopen?view=vs-2019
auto stdioPipeHandle = _wfdopen(_open_osfhandle((intptr_t)wil::detach_from_smart_pointer(readPipe), _O_WTEXT | _O_RDONLY), L"r");
auto closeFile = wil::scope_exit([&]() { fclose(stdioPipeHandle); });

std::wfstream pipe{ stdioPipeHandle };

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'\r');

if (til::starts_with(distName, DockerDistributionPrefix))
{
// Docker for Windows creates some utility distributions to handle Docker commands.
// Pursuant to GH#3556, because they are _not_ user-facing we want to hide them.
continue;
}

const auto firstChar = distName.find_first_of(L"( ");
// Some localizations don't have a space between the name and "(Default)"
// https://github.com/microsoft/terminal/issues/1168#issuecomment-500187109
if (firstChar < distName.size())
{
distName.resize(firstChar);
}

profiles.emplace_back(makeProfile(distName));
}
}
}

// Function Description:
// - Create a list of Profiles for each distro listed in names.
// - Skips distros that are utility distros for docker (see GH#3556)
Expand Down Expand Up @@ -310,9 +209,9 @@ static bool getWslNames(const wil::unique_hkey& wslRootKey,
// Method Description:
// - Generate a list of profiles for each on the installed WSL distros. This
// will first try to read the installed distros from the registry. If that
// fails, we'll fall back to the legacy way of launching WSL.exe to read the
// distros from the commandline. Reading the registry is slightly more stable
// (see GH#7199, GH#9905), but it is certainly BODGY
// fails, we'll assume there are no WSL distributions installed.
// Reading the registry is slightly more stable (see GH#7199, GH#9905),
// but it is certainly BODGY
// Arguments:
// - <none>
// Return Value:
Expand All @@ -333,6 +232,4 @@ void WslDistroGenerator::GenerateProfiles(std::vector<winrt::com_ptr<implementat
}
}
}

legacyGenerate(profiles);
}

0 comments on commit a47bb0d

Please sign in to comment.