mirror of
https://github.com/microsoft/WSL.git
synced 2025-12-11 22:24:19 -06:00
* link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Advanced Authoring Tests in C++ Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: CMake Documentation and Community Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs for networking issues Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: ; otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: a Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: access Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: accessible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: across Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: actively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: adapters Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: address Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: addresses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: and Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: appropriate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: argument Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: associated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: attach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: available Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: beginning Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: between Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: binaries Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: bound Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: cannot Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: canonical Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: capabilities Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-insensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-sensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: certified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: command Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: committer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: communication Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: complains Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: configuration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: consumed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: continue Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: converted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: currently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: customers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: daemon Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: deferred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: definitions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delimiter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delivered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: dellink Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: derived Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: descriptor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destined Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destruct Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: detach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: differentiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: directories Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disassociate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disposition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distribution Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distro Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: duping Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: emitted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: empty Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: environment Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: every time Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: exclusive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expire Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: explicitly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fall back Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: false Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fastfail Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: filesystem Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: first Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: followed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: for Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionality Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: greater Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guarantee Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guaranteed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: handles Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hangup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hierarchy Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hogwarts Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hydrated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: icrnl Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: initialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instance Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: intentionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpret Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpreter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: irreversibly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iteration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iterator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: its Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kernel Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kmsg Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: knowledge Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: maximum Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mirrored Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: msftconnecttest Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multi Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multiple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mutable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: namespace Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: nonexistent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: notifications Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: outstanding Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: overridden Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: partition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: pass through Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: passthrough Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: performs Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: periodically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: positional Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: precedence Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preexisting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preferring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: prepopulate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: previous Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: privileges Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: process Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: processes Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: programmatically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: protection Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: provided Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reasonable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: receive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: received Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: red hat Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reentrant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: registered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: regularly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: relay Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: release Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: representing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: requests Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: response Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: resurrect Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: retention Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: returned Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: security Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: semaphore Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: service Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: set up Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: setup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: severely Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: should Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: signal Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: similarly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simplified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: single Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: specified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: splitting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: standard Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: stress Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: succeed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: success Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: successfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: supplementary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: synced Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: system Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: take Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: than Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: that opening Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: threadpool Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: to Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: true Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: truncate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: tunneling Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unexpected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: uninitialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unique Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unprivileged Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unregistered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: untrusted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: upgrade Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: utility Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: validating Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: verify Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: visible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: whether Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: winget Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: worker Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: written Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: wslservice Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * format source --------- Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> Co-authored-by: Ben Hillis <benhillis@gmail.com> Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
386 lines
14 KiB
C++
386 lines
14 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Plugin.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains a test plugin.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "WslPluginApi.h"
|
|
|
|
#include "PluginTests.h"
|
|
|
|
using namespace wsl::windows::common::registry;
|
|
|
|
std::ofstream g_logfile;
|
|
std::optional<GUID> g_distroGuid;
|
|
|
|
const WSLPluginAPIV1* g_api = nullptr;
|
|
PluginTestType g_testType = PluginTestType::Invalid;
|
|
|
|
std::optional<uint32_t> g_previousInitPid;
|
|
|
|
std::vector<char> ReadFromSocket(SOCKET socket)
|
|
{
|
|
// Simplified error handling for the sake of the demo.
|
|
int result = 0;
|
|
int offset = 0;
|
|
|
|
std::vector<char> content(1024);
|
|
while ((result = recv(socket, content.data() + offset, 1024, 0)) > 0)
|
|
{
|
|
offset += result;
|
|
content.resize(offset + 1024);
|
|
}
|
|
|
|
content.resize(offset);
|
|
return content;
|
|
}
|
|
|
|
HRESULT OnVmStarted(const WSLSessionInformation* Session, const WSLVmCreationSettings* Settings)
|
|
{
|
|
g_logfile << "VM created (settings->CustomConfigurationFlags=" << Settings->CustomConfigurationFlags << ")" << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToStartVm)
|
|
{
|
|
g_logfile << "OnVmStarted: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
else if (g_testType == PluginTestType::FailToStartVmWithPluginErrorMessage)
|
|
{
|
|
g_logfile << "OnVmStarted: E_UNEXPECTED" << std::endl;
|
|
g_api->PluginError(L"Plugin error message");
|
|
return E_UNEXPECTED;
|
|
}
|
|
else if (WI_IsFlagSet(Settings->CustomConfigurationFlags, WSLUserConfigurationCustomKernel))
|
|
{
|
|
g_logfile << "OnVmStarted: E_ACCESSDENIED" << std::endl;
|
|
return E_ACCESSDENIED;
|
|
}
|
|
else if (g_testType == PluginTestType::Success)
|
|
{
|
|
// Get the current module's directory
|
|
std::filesystem::path modulePath = wil::GetModuleFileNameW(wil::GetModuleInstanceHandle()).get();
|
|
auto mountSource = modulePath.parent_path().wstring();
|
|
|
|
// Mount the folder with the linux binary in the vm
|
|
RETURN_IF_FAILED(
|
|
g_api->MountFolder(Session->SessionId, mountSource.c_str(), L"/test-plugin/deep/folder", true, L"test-plugin-mount"));
|
|
|
|
g_logfile << "Folder mounted (" << wsl::shared::string::WideToMultiByte(mountSource) << " -> /test-plugin)" << std::endl;
|
|
|
|
// Create a file with dummy content
|
|
std::ofstream file(mountSource + L"\\test-file.txt");
|
|
if (!file || !(file << "OK"))
|
|
{
|
|
g_logfile << "Failed to open test-file.txt in: " << wsl::shared::string::WideToMultiByte(mountSource) << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
|
|
file.close();
|
|
|
|
// Launch the process
|
|
std::vector<const char*> arguments = {"/bin/cat", "/test-plugin/deep/folder/test-file.txt", nullptr};
|
|
wil::unique_socket socket;
|
|
RETURN_IF_FAILED(g_api->ExecuteBinary(Session->SessionId, arguments[0], arguments.data(), &socket));
|
|
g_logfile << "Process created" << std::endl;
|
|
|
|
// Read the socket output
|
|
auto output = ReadFromSocket(socket.get());
|
|
if (output != std::vector<char>{'O', 'K'})
|
|
{
|
|
g_logfile << "Got unexpected output from bash" << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
}
|
|
else if (g_testType == PluginTestType::ApiErrors)
|
|
{
|
|
auto result = g_api->MountFolder(Session->SessionId, L"C:\\DoesNotExit", L"/dummy", true, L"test-plugin-mount");
|
|
if (result != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
|
{
|
|
g_logfile << "Unexpected error for MountFolder(): " << result << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
|
|
wil::unique_socket socket;
|
|
std::vector<const char*> arguments = {"/bin/does-no-exist", nullptr};
|
|
result = g_api->ExecuteBinary(Session->SessionId, arguments[0], arguments.data(), &socket);
|
|
if (result != E_FAIL)
|
|
{
|
|
g_logfile << "Unexpected error for ExecuteBinary(): " << result << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
|
|
result = g_api->ExecuteBinary(0xcafe, arguments[0], arguments.data(), &socket);
|
|
if (result != RPC_E_DISCONNECTED)
|
|
{
|
|
g_logfile << "Unexpected error for ExecuteBinary(): " << result << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
|
|
// Call PluginError asynchronously to verify that we handle this properly.
|
|
|
|
std::thread thread{[Session]() {
|
|
const auto result = g_api->PluginError(L"Dummy");
|
|
|
|
if (result != E_ILLEGAL_METHOD_CALL)
|
|
{
|
|
g_logfile << "Unexpected error for async PluginError(): " << result << std::endl;
|
|
}
|
|
}};
|
|
|
|
thread.join();
|
|
|
|
g_logfile << "API error tests passed" << std::endl;
|
|
}
|
|
else if (g_testType == PluginTestType::ErrorMessageStartVm)
|
|
{
|
|
auto result = g_api->PluginError(L"StartVm plugin error message");
|
|
if (FAILED(result))
|
|
{
|
|
g_logfile << "Unexpected error from PluginError(): " << result << std::endl;
|
|
}
|
|
g_logfile << "OnVmStarted: E_FAIL" << std::endl;
|
|
return E_FAIL;
|
|
}
|
|
else if (g_testType == PluginTestType::GetUsername)
|
|
{
|
|
try
|
|
{
|
|
auto info = wil::get_token_information<TOKEN_USER>(Session->UserToken);
|
|
|
|
DWORD size{};
|
|
DWORD domainSize{};
|
|
SID_NAME_USE use{};
|
|
LookupAccountSid(nullptr, info->User.Sid, nullptr, &size, nullptr, &domainSize, &use);
|
|
|
|
THROW_HR_IF(E_UNEXPECTED, size < 1);
|
|
std::wstring user(size - 1, '\0');
|
|
std::wstring domain(domainSize - 1, '\0');
|
|
|
|
THROW_IF_WIN32_BOOL_FALSE(LookupAccountSid(nullptr, info->User.Sid, user.data(), &size, domain.data(), &domainSize, &use));
|
|
|
|
g_logfile << "Username: " << wsl::shared::string::WideToMultiByte(domain) << "\\"
|
|
<< wsl::shared::string::WideToMultiByte(user) << std::endl;
|
|
}
|
|
catch (...)
|
|
{
|
|
g_logfile << "OnVmStarted: get_token_information failed: " << wil::ResultFromCaughtException() << std::endl;
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OnVmStopping(const WSLSessionInformation* Session)
|
|
{
|
|
g_logfile << "VM Stopping" << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToStopVm)
|
|
{
|
|
g_logfile << "OnVmStopping: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OnDistroStarted(const WSLSessionInformation* Session, const WSLDistributionInformation* Distribution)
|
|
{
|
|
g_logfile << "Distribution started, name=" << wsl::shared::string::WideToMultiByte(Distribution->Name)
|
|
<< ", package=" << wsl::shared::string::WideToMultiByte(Distribution->PackageFamilyName)
|
|
<< ", PidNs=" << Distribution->PidNamespace << ", InitPid=" << Distribution->InitPid
|
|
<< ", Flavor=" << wsl::shared::string::WideToMultiByte(Distribution->Flavor)
|
|
<< ", Version=" << wsl::shared::string::WideToMultiByte(Distribution->Version) << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToStartDistro)
|
|
{
|
|
g_logfile << "OnDistroStarted: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
else if (g_testType == PluginTestType::SameDistroId)
|
|
{
|
|
if (g_distroGuid.has_value())
|
|
{
|
|
if (IsEqualGUID(g_distroGuid.value(), Distribution->Id))
|
|
{
|
|
g_logfile << "OnDistroStarted: received same GUID" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
g_logfile << "OnDistroStarted: received different GUID" << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_distroGuid = Distribution->Id;
|
|
}
|
|
}
|
|
else if (g_testType == PluginTestType::ErrorMessageStartDistro)
|
|
{
|
|
g_logfile << "OnDistroStarted: E_FAIL" << std::endl;
|
|
g_api->PluginError(L"StartDistro plugin error message");
|
|
return E_FAIL;
|
|
}
|
|
else if (g_testType == PluginTestType::InitPidIsDifferent)
|
|
{
|
|
if (g_previousInitPid.has_value())
|
|
{
|
|
if (g_previousInitPid.value() != Distribution->InitPid)
|
|
{
|
|
g_logfile << "Init's pid is different (" << Distribution->InitPid << " ! = " << g_previousInitPid.value() << ")" << std::endl;
|
|
}
|
|
else
|
|
{
|
|
g_logfile << "Init's pid did not change (" << g_previousInitPid.value() << ")" << std::endl;
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_previousInitPid = Distribution->InitPid;
|
|
}
|
|
}
|
|
else if (g_testType == PluginTestType::RunDistroCommand)
|
|
{
|
|
// Launch a process
|
|
std::vector<const char*> arguments = {"/bin/sh", "-c", "cat /etc/issue.net", nullptr};
|
|
wil::unique_socket socket;
|
|
RETURN_IF_FAILED(g_api->ExecuteBinaryInDistribution(Session->SessionId, &Distribution->Id, arguments[0], arguments.data(), &socket));
|
|
g_logfile << "Process created" << std::endl;
|
|
|
|
// Validate that the process actually ran inside the distro.
|
|
auto output = ReadFromSocket(socket.get());
|
|
const auto expected = "Debian GNU/Linux 12\n";
|
|
if (std::string(output.begin(), output.end()) != expected)
|
|
{
|
|
g_logfile << "Got unexpected output from bash: " << std::string(output.begin(), output.end())
|
|
<< ", expected: " << expected << std::endl;
|
|
return E_ABORT;
|
|
}
|
|
|
|
// Verify that failure to launch a process behaves properly.
|
|
arguments = {"/does-not-exist"};
|
|
g_logfile << "Failed process launch returned: "
|
|
<< g_api->ExecuteBinaryInDistribution(Session->SessionId, &Distribution->Id, arguments[0], arguments.data(), &socket)
|
|
<< std::endl;
|
|
|
|
const GUID guid{};
|
|
g_logfile << "Invalid distro launch returned: "
|
|
<< g_api->ExecuteBinaryInDistribution(Session->SessionId, &guid, arguments[0], arguments.data(), &socket) << std::endl;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OnDistroStopping(const WSLSessionInformation* Session, const WSLDistributionInformation* Distribution)
|
|
{
|
|
g_logfile << "Distribution Stopping, name=" << wsl::shared::string::WideToMultiByte(Distribution->Name)
|
|
<< ", package=" << wsl::shared::string::WideToMultiByte(Distribution->PackageFamilyName)
|
|
<< ", PidNs=" << Distribution->PidNamespace << ", Flavor=" << wsl::shared::string::WideToMultiByte(Distribution->Flavor)
|
|
<< ", Version=" << wsl::shared::string::WideToMultiByte(Distribution->Version) << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToStopDistro)
|
|
{
|
|
g_logfile << "OnDistroStopping: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
else if (g_testType == PluginTestType::SameDistroId && g_distroGuid.has_value())
|
|
{
|
|
if (!IsEqualGUID(g_distroGuid.value(), Distribution->Id))
|
|
{
|
|
g_logfile << "OnDistroStarted: received different GUID" << std::endl;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OnDistributionRegistered(const WSLSessionInformation* Session, const WslOfflineDistributionInformation* Distribution)
|
|
{
|
|
g_logfile << "Distribution registered, name=" << wsl::shared::string::WideToMultiByte(Distribution->Name)
|
|
<< ", package=" << wsl::shared::string::WideToMultiByte(Distribution->PackageFamilyName)
|
|
<< ", Flavor=" << wsl::shared::string::WideToMultiByte(Distribution->Flavor)
|
|
<< ", Version=" << wsl::shared::string::WideToMultiByte(Distribution->Version) << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToRegisterUnregisterDistro)
|
|
{
|
|
g_logfile << "OnDistributionRegistered: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT OnDistributionUnregistered(const WSLSessionInformation* Session, const WslOfflineDistributionInformation* Distribution)
|
|
{
|
|
g_logfile << "Distribution unregistered, name=" << wsl::shared::string::WideToMultiByte(Distribution->Name)
|
|
<< ", package=" << wsl::shared::string::WideToMultiByte(Distribution->PackageFamilyName)
|
|
<< ", Flavor=" << wsl::shared::string::WideToMultiByte(Distribution->Flavor)
|
|
<< ", Version=" << wsl::shared::string::WideToMultiByte(Distribution->Version) << std::endl;
|
|
|
|
if (g_testType == PluginTestType::FailToRegisterUnregisterDistro)
|
|
{
|
|
g_logfile << "OnDistributionUnregistered: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
EXTERN_C __declspec(dllexport) HRESULT WSLPLUGINAPI_ENTRYPOINTV1(const WSLPluginAPIV1* Api, WSLPluginHooksV1* Hooks)
|
|
{
|
|
try
|
|
{
|
|
const auto key = OpenTestRegistryKey(KEY_READ);
|
|
|
|
const std::wstring outputFile = ReadString(key.get(), nullptr, c_logFile);
|
|
g_logfile.open(outputFile);
|
|
THROW_HR_IF(E_UNEXPECTED, !g_logfile);
|
|
|
|
g_testType = static_cast<PluginTestType>(ReadDword(key.get(), nullptr, c_testType, static_cast<DWORD>(PluginTestType::Invalid)));
|
|
THROW_HR_IF(E_INVALIDARG, static_cast<DWORD>(g_testType) <= 0 || static_cast<DWORD>(g_testType) > static_cast<DWORD>(PluginTestType::GetUsername));
|
|
|
|
g_logfile << "Plugin loaded. TestMode=" << static_cast<DWORD>(g_testType) << std::endl;
|
|
g_api = Api;
|
|
Hooks->OnVMStarted = &OnVmStarted;
|
|
Hooks->OnVMStopping = &OnVmStopping;
|
|
Hooks->OnDistributionStarted = &OnDistroStarted;
|
|
Hooks->OnDistributionStopping = &OnDistroStopping;
|
|
Hooks->OnDistributionRegistered = &OnDistributionRegistered;
|
|
Hooks->OnDistributionUnregistered = &OnDistributionUnregistered;
|
|
|
|
if (g_testType == PluginTestType::FailToLoad)
|
|
{
|
|
g_logfile << "OnLoad: E_UNEXPECTED" << std::endl;
|
|
return E_UNEXPECTED;
|
|
}
|
|
else if (g_testType == PluginTestType::PluginRequiresUpdate)
|
|
{
|
|
g_logfile << "OnLoad: WSL_E_PLUGINREQUIRESUPDATE" << std::endl;
|
|
|
|
WSL_PLUGIN_REQUIRE_VERSION(9999, 99, 99, Api);
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
const auto error = wil::ResultFromCaughtException();
|
|
if (g_logfile)
|
|
{
|
|
g_logfile << "Failed to initialize plugin, " << error << std::endl;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
return S_OK;
|
|
} |