* Initial support for image tag command
* Init test
* Init e2e test
* Adde E2E tests
* Added more tests
* Added more tests
* Resolve copilot comment
* Clang format
* Clang format
* Fix build
* Update parser
* Update loc
* Fix test
* Added more tests
* Clang format
* Loc
* Addressed comments
Replace runtime WSL2_TEST_ONLY()/WSL1_TEST_ONLY() skip macros with
TAEF metadata-based test selection. Tests that don't apply to the
current WSL version are now excluded by /select: queries at selection
time rather than skipped at runtime, eliminating hundreds of 'skipped'
results from test output.
Changes:
- Add WSL2_TEST_METHOD, WSL1_TEST_METHOD, WSLC_TEST_METHOD macros
in Common.h that tag tests with WSLVersion metadata property
- Convert ~430 test methods across 26 files to use new macros
- Update run-tests.ps1 to auto-add /select: version filter
- Update CloudTest XML configs with version selection queries
- Remove WSL2_TEST_ONLY() from composite macros in NetworkTests.cpp
- Update test README with new macro documentation
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix race condition when building multiple IDL files
* Use the header as output
* Use a single target
* Use a separate command to set the stamp file
* Remove stamp file
* Add DCOM LaunchPermission for WSLCSessionFactory
WSLCSessionFactory (wslcsession.exe) was registered without an AppId or
explicit DCOM LaunchPermission. When wslservice (SYSTEM) impersonates a
non-interactive caller such as Network Service and calls
CreateComServerAsUser to launch the per-user session factory, DCOM falls
back to machine-default launch permissions which do not include service
accounts. This causes E_ACCESSDENIED during session creation.
Add an AppId with the same LaunchPermission and AccessPermission SDDL
used by the other WSL COM servers (LxssUserSession, WSLCSessionManager,
WslDeviceHost), granting launch/activate rights to Authenticated Users
(AU), Principal Self (PS), and Local System (SY).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Extract DCOM permission blob into CMake variable
The same binary security descriptor was duplicated 8 times across 4 AppId
registrations. Extract it into a DCOM_PERMISSION CMake variable defined in
msipackage/CMakeLists.txt so future permission changes only need one edit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* [WSLC] Add 'wslc version' subcommand
Adds a 'version' subcommand to the WSLC CLI as an alternative to the
existing '--version' flag, following the subcommand pattern used by
other WSLC commands. Includes unit tests for command structure and
command-line parsing.
Co-authored-by: Pooja Trivedi <trivedipooja@microsoft.com>
Co-Authored-By: Claude Sonnet 4.6
* [WSLC] Fix E2E help/invalid-command tests after version subcommand addition
Update expected help output in WSLCE2EGlobalTests to include the newly
added 'version' subcommand, fixing WSLCE2E_HelpCommand and
WSLCE2E_InvalidCommand_DisplaysErrorMessage test failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* [WSLC] Add E2E version command test and strengthen unit test
- Add WSLCE2E_VersionCommand E2E test in WSLCE2EGlobalTests verifying
stdout, empty stderr, and exit code for 'wslc version'
- Add assertion to VersionCommand_HasNoArguments unit test to verify
only the auto-added --help argument is present
Authored-By: Pooja Trivedi <trivedipooja@microsoft.com>
Co-Authored-By: Claude Sonnet 4.6
* Mark 'context' as UNREFERENCED_PARAMETER in
VersionCommand::ExecuteInternal to avoid build issues
* Address PR feedback on wslc version command
- Use Localization::WSLCCLI_VersionDesc/LongDesc instead of hard-coded strings; add entries to en-US Resources.resw
- Centralize version printing in VersionCommand::PrintVersion(); reuse from RootCommand --version flag
- Drop 'v' prefix from version output per OneBlue's feedback
- Add 'version' entry to E2E GetAvailableCommands() to fix WSLCE2E_HelpCommand and WSLCE2E_InvalidCommand_DisplaysErrorMessage
Co-Authored-By: Pooja Trivedi
* Fix build: add missing using namespace wsl::shared
Localization::WSLCCLI_VersionDesc() and WSLCCLI_VersionLongDesc() live in
wsl::shared::Localization. Without this using directive the compiler cannot
resolve the unqualified Localization:: references in VersionCommand.cpp.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Pooja Trivedi <trivedipooja@microsoft.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* wslc: implement dns tunneling for virtio proxy networking mode
This change implements dnstunneling for the virtio proxy networking mode. For now, this implementation uses the same socket-based approach, but in the fututure this will be moved over to the built-in dns support that is part of the wsldevicehost dll.
* wslc: enable DNS tunneling by default for virtio proxy
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove unused DNS test helpers
VerifyDnsResolutionDig and VerifyDnsResolutionRecordTypes are dead
code — VerifyDnsQueries is the superset that covers all record types
and TCP/UDP modes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make VMPortMapping::Unmap idempotent
Null out Vm after unmapping so a second call is a no-op. This prevents
double-unmap errors when ReleaseRuntimeResources is called from both
OnEvent(Stop) and a concurrent Delete(Force) path.
* Clear Vm before re-throwing on UnmapPort failure
Use a scope_exit to null Vm so that Unmap() is truly idempotent
even when UnmapPort() throws. Previously Vm stayed non-null on
the failure path, causing subsequent Unmap() calls to retry and
throw again.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Save state
* Save state
* Save state
* Cleanup
* Prepare for PR
* Cleanup
* Validate flags
* Apply PR suggestions
* Add comment
* Remove include
* Cleanup diff
* Format
* Format
* Restore session flags
* [WSLC] Add --workdir / -w option to 'wslc exec'
Adds a --workdir (-w) argument to the exec command that sets the working
directory inside the container for the executed process. Wires the value
through ContainerOptions into WSLAProcessLauncher::SetWorkingDirectory.
Co-authored-by: Pooja Trivedi <trivedipooja@microsoft.com>
Co-Authored-By: Claude Sonnet 4.6
* Update test/windows/wslc/CommandLineTestCases.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Update test/windows/wslc/CommandLineTestCases.h
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix clang formatting issues
* Update test/windows/wslc/WSLCCLIExecutionUnitTests.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add E2E tests for wslc container exec, including --workdir option
- Port existing exec E2E tests from feature branch
- Add WSLCE2E_Container_Exec_WorkDir and WSLCE2E_Container_Exec_WorkDir_ShortAlias tests
- Update help message in GetAvailableOptions to include -w,--workdir
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix clang formatting in WSLCE2EContainerExecTests.cpp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Validate --workdir is non-empty; add unit and parse test cases
- Reject empty or whitespace-only --workdir in Argument::Validate
- Add ExecCommand_ParseWorkDirEmptyValue_ThrowsArgumentException unit test
- Add empty-workdir failing case to CommandLineTestCases.h
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix clang formatting in CommandLineTestCases.h
Co-Authored-By: Claude Sonnet 4.6
* Trim exec E2E tests to --workdir coverage only
Remove tests that duplicate existing coverage in WSLCE2EContainerCreateTests.cpp.
Keep only the help message test (validates --workdir appears in output) and the
two workdir-specific E2E tests.
Co-Authored-By: Claude Sonnet 4.6
* Missed change from merge conflict resolution
* Fix --workdir whitespace validation to use std::iswspace for full Unicode coverage
Agent-Logs-Url: https://github.com/microsoft/WSL/sessions/b21d1a57-bb3f-4a12-84cf-8e414a453890
Co-authored-by: ptrivedi <1638019+ptrivedi@users.noreply.github.com>
* Use lambda with wint_t cast in iswspace call to avoid potential UB
Agent-Logs-Url: https://github.com/microsoft/WSL/sessions/b21d1a57-bb3f-4a12-84cf-8e414a453890
Co-authored-by: ptrivedi <1638019+ptrivedi@users.noreply.github.com>
* Missed change from merge conflict resolution
* Address Copilot PR feedback
- Revert Version ArgType alias from NO_ALIAS back to L"v" to preserve existing -v short option
- Restore WSLCE2EContainerExecTests.cpp lost in merge conflict resolution
Co-Authored-By: Pooja Trivedi
* Update src/windows/wslc/services/ContainerService.cpp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix ParserTest_StateMachine_PositionalForward: replace -v with -h in flag parse tests
The -v short alias was removed from --verbose (changed to NO_ALIAS) to
resolve a triple alias conflict with --version and --volume. The parser
test cases in the Run argument set still used -v expecting it to resolve
to --verbose, but since neither Version nor Volume are in the Run set,
-v became unresolvable and caused unexpected parse failures.
Replace -v with -h (help flag) in the flag parse test cases to preserve
the same combined-flag parsing coverage with a valid short alias.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix E2E exec help test: add --user option after base branch merge
After merging feature/wsl-for-apps, the --user argument is now active
in ContainerExecCommand (from PR #40101). Update the expected exec help
output to include -u,--user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Pooja Trivedi <trivedipooja@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ptrivedi <1638019+ptrivedi@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SendRequestAndReadResponse accumulates the entire response body into
a std::string with no size limit. While all current callers expect
small JSON metadata responses, a pathological or malformed response
could cause unbounded memory growth.
Add a 64 MB limit to prevent OOM. This is generous for JSON metadata
(list/inspect/create responses are typically <1 MB) while still
catching runaway responses early.
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Validate container path is absolute in VolumeMount::Parse
Add validation that non-empty container paths must start with '/' since
they are Linux paths inside the container. This catches cases where
Windows drive letter colons (e.g. C:\path) get misinterpreted as the
host:container separator, producing invalid container paths like
'\hostPath' instead of '/containerPath'.
Previously, 'C:\hostPath:ro' would silently parse as host='C',
container='\hostPath', mode=ro ΓÇö now it throws a clear error.
Updated tests to reflect the new validation and moved previously
'valid' but semantically incorrect cases to the invalid test set.
* Also validate host path is absolute, add format hint to error, cover forward-slash cases
- Reject non-absolute host paths (catches C:/hostPath where host='C')
- Add 'Expected format:' hint to container path error message for consistency
- Add forward-slash drive letter cases to invalid test set
- Move '::' case to invalid (host=':' is not absolute)
* Remove host path is_absolute check to allow future named volumes
Per review feedback: named volumes (e.g. 'test_vol:/path') would fail
an is_absolute() check on the host path. Keep only the container path
validation (must start with '/') which doesn't conflict with named
volume identifiers.
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Localize all user-facing wslc.exe CLI strings
Add localization entries for all hardcoded user-facing strings in the
WSLC CLI tool:
- 38 command description strings (Short + Long for all commands)
- 30 argument description strings in ArgumentDefinitions.h
- Settings reset confirmation string
- All entries added to en-US/Resources.resw with {Locked=...} comments
for CLI flags, product names, and technical terms
E2E tests updated to use Localization:: calls and dynamic column
formatting instead of hardcoded string copies, so they won't go
stale when descriptions change.
* formatting
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Release COM DLLs before installer test MSI operations
Add PrepareForMsiOperation() that calls CoFreeUnusedLibrariesEx(0)
before each msiexec invocation. This releases in-process COM DLLs
like wslserviceproxystub.dll loaded by prior test classes, preventing
the Restart Manager from detecting the test process as holding file
locks and failing the install on older Server SKUs like ni_release.
* fix CoFreeUnusedLibrariesEx
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Remove unused callback parameter from CreateInternal
The IProgressCallback* parameter was always passed as nullptr by both
callers. The auto-pull path creates its own PullImageCallback locally.
Remove the dead parameter entirely per review feedback.
* format
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Both static functions in ContainerService.cpp are defined but never
called from anywhere in the codebase. They appear to be remnants of
an earlier implementation before the WSLCContainerLauncher and
WSLCProcessLauncher classes took over this responsibility.
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
* Add week/month/year support to FormatRelativeTime
Previously only handled seconds, minutes, hours, and days. Containers
older than a week would show e.g. '720 days ago' instead of '2 years ago'.
Now matches Docker-style output with weeks, months, and years.
Also refactors repeated pluralization logic into a lambda.
* Handle timestamp==0 sentinel in FormatRelativeTime
Callers pass 0 to mean 'unknown' (e.g. ImageTasks when Created <= 0).
Previously this would produce '56 years ago'. Now returns empty string.
---------
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Replace manual PrintMessage + THROW_HR(E_FAIL) with the standard
THROW_HR_WITH_USER_ERROR pattern used throughout the codebase. This
ensures the error message is properly captured by the ExecutionContext
error collection system rather than being printed directly to stderr.
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
When the WSL MSIX package is updated via the Microsoft Store, the
WslInstaller service automatically upgrades the MSI package by calling
MsiInstallProduct. This call was made with INSTALLUILEVEL_NONE (silent
install) but without setting the REBOOT=ReallySuppress property.
Per Windows Installer documentation, when a silent install encounters
files in use and REBOOT is not suppressed, the system reboots
automatically without any user prompt. This could cause unexpected
machine restarts after a Store update when WSL binaries (e.g.
wslservice.exe) were in use during the upgrade.
Every deployment script in the repo already passes /norestart to
msiexec (deploy-to-host.ps1, deploy-to-vm.ps1, install-latest-wsl.ps1,
test-setup.ps1), but the programmatic MsiInstallProduct path used by
the WslInstaller service lacked the equivalent property.
This change:
- Always appends REBOOT=ReallySuppress to MsiInstallProduct arguments
in UpgradeViaMsi, preventing Windows Installer from ever initiating
a system restart during install/upgrade.
- Switches UninstallViaMsi from MsiConfigureProduct to
MsiConfigureProductEx so we can pass REBOOT=ReallySuppress during
uninstall as well.
- Propagates ERROR_SUCCESS_REBOOT_REQUIRED (3010) to callers instead
of swallowing it. User-facing paths (wsl --update, wsl --uninstall)
print a reboot-needed message to stderr. The background WslInstaller
service silently treats 3010 as success since it has no console.
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>