CLI: Unify session resolution, add WSLC_E_SESSION_NOT_FOUND, and refactor session service (#40832)
David Bennett committed
Jun 19, 2026 at 13:58 UTC
14b78c929050f49b42b415011c930dd0d7bb2ef6
58 files changed
+229
-232
localization/strings/en-US/Resources.resw
+4
-3
@@ -2066,6 +2066,10 @@ Usage:
2066
<value>OpenSessionByName('{}') failed</value>
2067
<comment>{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
2068
</data>
2069
+ <data name="MessageWslcSessionOptionNotSupported" xml:space="preserve">
2070
+ <value>The --session option cannot be used with this command.</value>
2071
+ <comment>{Locked="--session "}Command line arguments, file names and string inserts should not be translated</comment>
2072
+ </data>
2073
<data name="MessageWslcFailedToLaunchCommand" xml:space="preserve">
2074
<value>Failed to launch command {}. Errno = {}</value>
2075
<comment>{FixedPlaceholder="{}"}{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated</comment>
@@ -2903,9 +2907,6 @@ On first run, creates the file with all settings commented out at their defaults
2907
<value>Size of /dev/shm (e.g. 64M, 1G)</value>
2908
<comment>{Locked="/dev/shm"}Command line arguments should not be translated</comment>
2909
</data>
2906
- <data name="WSLCCLI_SessionIdPositionalArgDescription" xml:space="preserve">
2907
- <value>Session ID</value>
2908
- </data>
2910
<data name="WSLCCLI_SessionStoragePositionalArgDescription" xml:space="preserve">
2911
<value>Session storage path</value>
2912
</data>
src/windows/WslcSDK/wslcsdk.h
+1
@@ -41,6 +41,7 @@ EXTERN_C_START
41
#define WSLC_E_CONTAINER_DISABLED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 12) /* 0x8004060C */
42
#define WSLC_E_REGISTRY_BLOCKED_BY_POLICY MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 13) /* 0x8004060D */
43
#define WSLC_E_VOLUME_NOT_AVAILABLE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 14) /* 0x8004060E */
44
+#define WSLC_E_SESSION_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 15) /* 0x8004060F */
45
46
// Session values
47
#define WSLC_SESSION_OPTIONS_SIZE 72
src/windows/common/wslutil.cpp
+1
@@ -160,6 +160,7 @@ static const std::map<HRESULT, LPCWSTR> g_commonErrors{
160
X(WSLC_E_SESSION_RESERVED),
161
X(WSLC_E_INVALID_SESSION_NAME),
162
X(WSLC_E_NETWORK_NOT_FOUND),
163
+ X(WSLC_E_SESSION_NOT_FOUND),
164
X(WSLC_E_WU_SEARCH_FAILED),
165
X_WIN32(RPC_S_SERVER_UNAVAILABLE),
166
X_WIN32(ERROR_ELEVATION_REQUIRED)};
src/windows/service/exe/WSLCSessionManager.cpp
+7
-3
@@ -38,6 +38,7 @@ Abstract:
38
#include "wslutil.h"
39
#include "filesystem.hpp"
40
#include "APICompat.h"
41
+#include "Localization.h"
42
43
extern wsl::windows::service::PluginManager g_pluginManager;
44
@@ -361,7 +362,7 @@ void WSLCSessionManagerImpl::OpenSession(ULONG Id, IWSLCSession** Session)
362
return S_OK;
363
});
364
364
- THROW_IF_FAILED_MSG(result.value_or(HRESULT_FROM_WIN32(ERROR_NOT_FOUND)), "Session '%lu' not found", Id);
365
+ THROW_IF_FAILED_MSG(result.value_or(WSLC_E_SESSION_NOT_FOUND), "Session '%lu' not found", Id);
366
}
367
368
void WSLCSessionManagerImpl::OpenSessionByName(LPCWSTR DisplayName, IWSLCSession** Session)
@@ -391,7 +392,10 @@ void WSLCSessionManagerImpl::OpenSessionByName(LPCWSTR DisplayName, IWSLCSession
392
return S_OK;
393
});
394
394
- THROW_IF_FAILED_MSG(result.value_or(HRESULT_FROM_WIN32(ERROR_NOT_FOUND)), "Session '%ls' not found", DisplayName);
395
+ THROW_HR_WITH_USER_ERROR_IF(
396
+ WSLC_E_SESSION_NOT_FOUND, wsl::shared::Localization::MessageWslcSessionNotFound(DisplayName), !result.has_value());
397
+
398
+ THROW_IF_FAILED_MSG(result.value(), "Failed to open session '%ls'", DisplayName);
399
}
400
401
void WSLCSessionManagerImpl::ListSessions(_Out_ WSLCSessionListEntry** Sessions, _Out_ ULONG* SessionsCount)
@@ -663,7 +667,7 @@ wil::com_ptr<IWSLCSession> WSLCSessionManagerImpl::FindSession(ULONG Id)
667
return S_OK;
668
});
669
666
- THROW_HR_IF_MSG(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), !result, "WSLC session %lu not found", Id);
670
+ THROW_HR_IF_MSG(WSLC_E_SESSION_NOT_FOUND, !result, "WSLC session %lu not found", Id);
671
return result;
672
}
673
src/windows/service/inc/wslc.idl
+1
@@ -725,3 +725,4 @@ cpp_quote("#define WSLC_E_SDK_UPDATE_NEEDED MAKE_HRESULT(SEVERITY_ERROR, FACILIT
725
cpp_quote("#define WSLC_E_CONTAINER_DISABLED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 12) /* 0x8004060C */")
726
cpp_quote("#define WSLC_E_REGISTRY_BLOCKED_BY_POLICY MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 13) /* 0x8004060D */")
727
cpp_quote("#define WSLC_E_VOLUME_NOT_AVAILABLE MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 14) /* 0x8004060E */")
728
+cpp_quote("#define WSLC_E_SESSION_NOT_FOUND MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, WSLC_E_BASE + 15) /* 0x8004060F */")
src/windows/wslc/arguments/ArgumentDefinitions.h
-1
@@ -98,7 +98,6 @@ _(Remove, "rm", NO_ALIAS, Kind::Flag, L
98
/*_(Scheme, "scheme", NO_ALIAS, Kind::Value, Localization::WSLCCLI_SchemeArgDescription())*/ \
99
_(Server, "server", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_LoginServerArgDescription()) \
100
_(Session, "session", NO_ALIAS, Kind::Value, Localization::WSLCCLI_SessionIdArgDescription()) \
101
-_(SessionId, "session-id", NO_ALIAS, Kind::Positional, Localization::WSLCCLI_SessionIdPositionalArgDescription()) \
101
_(ShmSize, "shm-size", NO_ALIAS, Kind::Value, Localization::WSLCCLI_ShmSizeArgDescription()) \
102
_(StoragePath, "storage-path", NO_ALIAS, Kind::Positional, L"Path to the session storage directory") \
103
_(Signal, "signal", L"s", Kind::Value, Localization::WSLCCLI_SignalArgDescription()) \
src/windows/wslc/commands/ContainerAttachCommand.cpp
+2
-2
@@ -43,8 +43,8 @@ std::wstring ContainerAttachCommand::LongDescription() const
43
44
void ContainerAttachCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
- context //
47
- << CreateSession //
46
+ context //
47
+ << ResolveSession //
48
<< AttachContainer(context.Args.Get<ArgType::ContainerId>());
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerCreateCommand.cpp
+1
-1
@@ -83,7 +83,7 @@ std::wstring ContainerCreateCommand::LongDescription() const
83
void ContainerCreateCommand::ExecuteInternal(CLIExecutionContext& context) const
84
{
85
context
86
- << CreateSession
86
+ << ResolveSession
87
<< SetContainerOptionsFromArgs
88
<< CreateContainer;
89
}
src/windows/wslc/commands/ContainerExecCommand.cpp
+1
-1
@@ -53,7 +53,7 @@ std::wstring ContainerExecCommand::LongDescription() const
53
void ContainerExecCommand::ExecuteInternal(CLIExecutionContext& context) const
54
{
55
context
56
- << CreateSession
56
+ << ResolveSession
57
<< SetContainerOptionsFromArgs
58
<< ExecContainer;
59
}
src/windows/wslc/commands/ContainerExportCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ContainerExportCommand::LongDescription() const
44
45
void ContainerExportCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< ExportContainer;
50
}
51
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerInspectCommand.cpp
+1
-1
@@ -45,7 +45,7 @@ std::wstring ContainerInspectCommand::LongDescription() const
45
void ContainerInspectCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
context
48
- << CreateSession
48
+ << ResolveSession
49
<< InspectContainers;
50
}
51
// clang-format on
src/windows/wslc/commands/ContainerKillCommand.cpp
+1
-1
@@ -46,7 +46,7 @@ std::wstring ContainerKillCommand::LongDescription() const
46
void ContainerKillCommand::ExecuteInternal(CLIExecutionContext& context) const
47
{
48
context
49
- << CreateSession
49
+ << ResolveSession
50
<< KillContainers;
51
}
52
// clang-format on
src/windows/wslc/commands/ContainerListCommand.cpp
+1
-1
@@ -52,7 +52,7 @@ std::wstring ContainerListCommand::LongDescription() const
52
void ContainerListCommand::ExecuteInternal(CLIExecutionContext& context) const
53
{
54
context
55
- << CreateSession
55
+ << ResolveSession
56
<< GetContainers
57
<< ListContainers;
58
}
src/windows/wslc/commands/ContainerLogsCommand.cpp
+2
-2
@@ -48,8 +48,8 @@ std::wstring ContainerLogsCommand::LongDescription() const
48
49
void ContainerLogsCommand::ExecuteInternal(CLIExecutionContext& context) const
50
{
51
- context //
52
- << CreateSession //
51
+ context //
52
+ << ResolveSession //
53
<< ViewContainerLogs;
54
}
55
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ContainerPruneCommand.cpp
+2
-2
@@ -41,8 +41,8 @@ std::wstring ContainerPruneCommand::LongDescription() const
41
42
void ContainerPruneCommand::ExecuteInternal(CLIExecutionContext& context) const
43
{
44
- context //
45
- << CreateSession //
44
+ context //
45
+ << ResolveSession //
46
<< PruneContainers;
47
}
48
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerRemoveCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ContainerRemoveCommand::LongDescription() const
44
45
void ContainerRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< RemoveContainers;
50
}
51
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ContainerRunCommand.cpp
+1
-1
@@ -84,7 +84,7 @@ std::wstring ContainerRunCommand::LongDescription() const
84
void ContainerRunCommand::ExecuteInternal(CLIExecutionContext& context) const
85
{
86
context
87
- << CreateSession
87
+ << ResolveSession
88
<< SetContainerOptionsFromArgs
89
<< RunContainer;
90
}
src/windows/wslc/commands/ContainerStartCommand.cpp
+1
-1
@@ -45,6 +45,6 @@ std::wstring ContainerStartCommand::LongDescription() const
45
46
void ContainerStartCommand::ExecuteInternal(CLIExecutionContext& context) const
47
{
48
- context << CreateSession << StartContainer;
48
+ context << ResolveSession << StartContainer;
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerStatsCommand.cpp
+2
-2
@@ -58,8 +58,8 @@ void ContainerStatsCommand::ValidateArgumentsInternal(const ArgMap& execArgs) co
58
59
void ContainerStatsCommand::ExecuteInternal(CLIExecutionContext& context) const
60
{
61
- context //
62
- << CreateSession //
61
+ context //
62
+ << ResolveSession //
63
<< ShowContainerStats;
64
}
65
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ContainerStopCommand.cpp
+1
-1
@@ -47,7 +47,7 @@ std::wstring ContainerStopCommand::LongDescription() const
47
void ContainerStopCommand::ExecuteInternal(CLIExecutionContext& context) const
48
{
49
context
50
- << CreateSession
50
+ << ResolveSession
51
<< StopContainers;
52
}
53
// clang-format on
src/windows/wslc/commands/ImageBuildCommand.cpp
+2
-2
@@ -50,8 +50,8 @@ std::wstring ImageBuildCommand::LongDescription() const
50
51
void ImageBuildCommand::ExecuteInternal(CLIExecutionContext& context) const
52
{
53
- context //
54
- << CreateSession //
53
+ context //
54
+ << ResolveSession //
55
<< BuildImage;
56
}
57
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImageImportCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ImageImportCommand::LongDescription() const
44
45
void ImageImportCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< ImportImage;
50
}
51
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ImageInspectCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ImageInspectCommand::LongDescription() const
44
45
void ImageInspectCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< InspectImages;
50
}
51
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImageListCommand.cpp
+3
-3
@@ -47,9 +47,9 @@ std::wstring ImageListCommand::LongDescription() const
47
48
void ImageListCommand::ExecuteInternal(CLIExecutionContext& context) const
49
{
50
- context //
51
- << CreateSession //
52
- << GetImages //
50
+ context //
51
+ << ResolveSession //
52
+ << GetImages //
53
<< ListImages;
54
}
55
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImageLoadCommand.cpp
+2
-2
@@ -43,8 +43,8 @@ std::wstring ImageLoadCommand::LongDescription() const
43
44
void ImageLoadCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
- context //
47
- << CreateSession //
46
+ context //
47
+ << ResolveSession //
48
<< LoadImage;
49
}
50
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImagePruneCommand.cpp
+2
-2
@@ -45,8 +45,8 @@ std::wstring ImagePruneCommand::LongDescription() const
45
46
void ImagePruneCommand::ExecuteInternal(CLIExecutionContext& context) const
47
{
48
- context //
49
- << CreateSession //
48
+ context //
49
+ << ResolveSession //
50
<< PruneImages;
51
}
52
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ImagePullCommand.cpp
+2
-2
@@ -45,8 +45,8 @@ std::wstring ImagePullCommand::LongDescription() const
45
46
void ImagePullCommand::ExecuteInternal(CLIExecutionContext& context) const
47
{
48
- context //
49
- << CreateSession //
48
+ context //
49
+ << ResolveSession //
50
<< PullImage;
51
}
52
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImagePushCommand.cpp
+2
-2
@@ -43,8 +43,8 @@ std::wstring ImagePushCommand::LongDescription() const
43
44
void ImagePushCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
- context //
47
- << CreateSession //
46
+ context //
47
+ << ResolveSession //
48
<< PushImage;
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ImageRemoveCommand.cpp
+2
-2
@@ -46,8 +46,8 @@ std::wstring ImageRemoveCommand::LongDescription() const
46
47
void ImageRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
48
{
49
- context //
50
- << CreateSession //
49
+ context //
50
+ << ResolveSession //
51
<< DeleteImage;
52
}
53
} // namespace wsl::windows::wslc
src/windows/wslc/commands/ImageSaveCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ImageSaveCommand::LongDescription() const
44
45
void ImageSaveCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< SaveImage;
50
}
51
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/ImageTagCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring ImageTagCommand::LongDescription() const
44
45
void ImageTagCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< TagImage;
50
}
51
} // namespace wsl::windows::wslc
src/windows/wslc/commands/InspectCommand.cpp
+1
-1
@@ -39,7 +39,7 @@ std::wstring InspectCommand::LongDescription() const
39
40
void InspectCommand::ExecuteInternal(CLIExecutionContext& context) const
41
{
42
- context << CreateSession //
42
+ context << ResolveSession //
43
<< Inspect;
44
}
45
} // namespace wsl::windows::wslc
src/windows/wslc/commands/NetworkCreateCommand.cpp
+1
-1
@@ -46,7 +46,7 @@ std::wstring NetworkCreateCommand::LongDescription() const
46
47
void NetworkCreateCommand::ExecuteInternal(CLIExecutionContext& context) const
48
{
49
- context << CreateSession //
49
+ context << ResolveSession //
50
<< CreateNetwork;
51
}
52
} // namespace wsl::windows::wslc
src/windows/wslc/commands/NetworkInspectCommand.cpp
+1
-1
@@ -43,7 +43,7 @@ std::wstring NetworkInspectCommand::LongDescription() const
43
44
void NetworkInspectCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
- context << CreateSession //
46
+ context << ResolveSession //
47
<< InspectNetworks;
48
}
49
} // namespace wsl::windows::wslc
src/windows/wslc/commands/NetworkListCommand.cpp
+2
-2
@@ -57,8 +57,8 @@ void NetworkListCommand::ValidateArgumentsInternal(const ArgMap& execArgs) const
57
58
void NetworkListCommand::ExecuteInternal(CLIExecutionContext& context) const
59
{
60
- context << CreateSession //
61
- << GetNetworks //
60
+ context << ResolveSession //
61
+ << GetNetworks //
62
<< ListNetworks;
63
}
64
} // namespace wsl::windows::wslc
src/windows/wslc/commands/NetworkPruneCommand.cpp
+2
-3
@@ -28,7 +28,6 @@ std::vector<Argument> NetworkPruneCommand::GetArguments() const
28
{
29
return {
30
Argument::Create(ArgType::Filter, false, NO_LIMIT),
31
- Argument::Create(ArgType::Session),
31
};
32
}
33
@@ -44,8 +43,8 @@ std::wstring NetworkPruneCommand::LongDescription() const
43
44
void NetworkPruneCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
47
- context //
48
- << CreateSession //
46
+ context //
47
+ << ResolveSession //
48
<< PruneNetworks;
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/commands/NetworkRemoveCommand.cpp
+1
-1
@@ -44,7 +44,7 @@ std::wstring NetworkRemoveCommand::LongDescription() const
44
45
void NetworkRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context << CreateSession //
47
+ context << ResolveSession //
48
<< DeleteNetworks;
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/commands/RegistryCommand.cpp
+1
-1
@@ -151,7 +151,7 @@ void RegistryLoginCommand::ExecuteInternal(CLIExecutionContext& context) const
151
}
152
153
context //
154
- << CreateSession << Login;
154
+ << ResolveSession << Login;
155
}
156
157
// Registry Logout Command
src/windows/wslc/commands/SessionEnterCommand.cpp
+5
@@ -43,6 +43,11 @@ std::wstring SessionEnterCommand::LongDescription() const
43
44
void SessionEnterCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
+ if (context.GlobalArgs.Contains(ArgType::Session))
47
+ {
48
+ throw CommandException(Localization::MessageWslcSessionOptionNotSupported());
49
+ }
50
+
51
context << EnterSession;
52
}
53
} // namespace wsl::windows::wslc
src/windows/wslc/commands/SessionRunCommand.cpp
+1
-1
@@ -42,6 +42,6 @@ std::wstring SessionRunCommand::LongDescription() const
42
43
void SessionRunCommand::ExecuteInternal(CLIExecutionContext& context) const
44
{
45
- context << RunInSession;
45
+ context << ResolveSession << RunInSession;
46
}
47
} // namespace wsl::windows::wslc
src/windows/wslc/commands/SessionShellCommand.cpp
+2
-4
@@ -24,9 +24,7 @@ namespace wsl::windows::wslc {
24
// Session Shell Command
25
std::vector<Argument> SessionShellCommand::GetArguments() const
26
{
27
- return {
28
- Argument::Create(ArgType::SessionId),
29
- };
27
+ return {};
28
}
29
30
std::wstring SessionShellCommand::ShortDescription() const
@@ -41,6 +39,6 @@ std::wstring SessionShellCommand::LongDescription() const
39
40
void SessionShellCommand::ExecuteInternal(CLIExecutionContext& context) const
41
{
44
- context << AttachToSession;
42
+ context << ResolveSession << AttachToSession;
43
}
44
} // namespace wsl::windows::wslc
src/windows/wslc/commands/SessionTerminateCommand.cpp
+5
-4
@@ -24,9 +24,7 @@ namespace wsl::windows::wslc {
24
// Session Terminate Command
25
std::vector<Argument> SessionTerminateCommand::GetArguments() const
26
{
27
- return {
28
- Argument::Create(ArgType::SessionId),
29
- };
27
+ return {};
28
}
29
30
std::wstring SessionTerminateCommand::ShortDescription() const
@@ -41,6 +39,9 @@ std::wstring SessionTerminateCommand::LongDescription() const
39
40
void SessionTerminateCommand::ExecuteInternal(CLIExecutionContext& context) const
41
{
44
- context << TerminateSession;
42
+ context //
43
+ << OpenSessionIfSpecified //
44
+ << OpenDefaultSession //
45
+ << TerminateSession;
46
}
47
} // namespace wsl::windows::wslc
\ No newline at end of file
src/windows/wslc/commands/VolumeCreateCommand.cpp
+1
-1
@@ -46,7 +46,7 @@ std::wstring VolumeCreateCommand::LongDescription() const
46
47
void VolumeCreateCommand::ExecuteInternal(CLIExecutionContext& context) const
48
{
49
- context << CreateSession //
49
+ context << ResolveSession //
50
<< CreateVolume;
51
}
52
} // namespace wsl::windows::wslc
src/windows/wslc/commands/VolumeInspectCommand.cpp
+1
-1
@@ -43,7 +43,7 @@ std::wstring VolumeInspectCommand::LongDescription() const
43
44
void VolumeInspectCommand::ExecuteInternal(CLIExecutionContext& context) const
45
{
46
- context << CreateSession //
46
+ context << ResolveSession //
47
<< InspectVolumes;
48
}
49
} // namespace wsl::windows::wslc
src/windows/wslc/commands/VolumeListCommand.cpp
+2
-2
@@ -57,8 +57,8 @@ void VolumeListCommand::ValidateArgumentsInternal(const ArgMap& execArgs) const
57
58
void VolumeListCommand::ExecuteInternal(CLIExecutionContext& context) const
59
{
60
- context << CreateSession //
61
- << GetVolumes //
60
+ context << ResolveSession //
61
+ << GetVolumes //
62
<< ListVolumes;
63
}
64
} // namespace wsl::windows::wslc
src/windows/wslc/commands/VolumePruneCommand.cpp
+2
-2
@@ -44,8 +44,8 @@ std::wstring VolumePruneCommand::LongDescription() const
44
45
void VolumePruneCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context //
48
- << CreateSession //
47
+ context //
48
+ << ResolveSession //
49
<< PruneVolumes;
50
}
51
} // namespace wsl::windows::wslc
src/windows/wslc/commands/VolumeRemoveCommand.cpp
+1
-1
@@ -44,7 +44,7 @@ std::wstring VolumeRemoveCommand::LongDescription() const
44
45
void VolumeRemoveCommand::ExecuteInternal(CLIExecutionContext& context) const
46
{
47
- context << CreateSession //
47
+ context << ResolveSession //
48
<< DeleteVolumes;
49
}
50
} // namespace wsl::windows::wslc
src/windows/wslc/services/SessionModel.h
+15
@@ -19,16 +19,31 @@ namespace wsl::windows::wslc::models {
19
20
struct Session
21
{
22
+ NON_COPYABLE(Session);
23
+ DEFAULT_MOVABLE(Session);
24
+
25
explicit Session(wil::com_ptr<IWSLCSession> session) : m_session(std::move(session))
26
{
27
}
28
+
29
IWSLCSession* Get() const noexcept
30
{
31
return m_session.get();
32
}
33
34
+ const std::optional<std::wstring>& DisplayName() const noexcept
35
+ {
36
+ return m_displayName;
37
+ }
38
+
39
+ void SetDisplayName(std::wstring name)
40
+ {
41
+ m_displayName = std::move(name);
42
+ }
43
+
44
private:
45
wil::com_ptr<IWSLCSession> m_session;
46
+ std::optional<std::wstring> m_displayName;
47
};
48
49
} // namespace wsl::windows::wslc::models
\ No newline at end of file
src/windows/wslc/services/SessionService.cpp
+53
-95
@@ -24,44 +24,53 @@ using namespace wsl::shared;
24
using namespace wsl::windows::wslc::models;
25
namespace wslutil = wsl::windows::common::wslutil;
26
27
-namespace {
28
-
29
- wil::com_ptr<IWSLCSession> OpenOrCreateSession(const std::wstring& sessionName)
30
- {
31
- wil::com_ptr<IWSLCSessionManager> manager;
32
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&manager)));
33
- wsl::windows::common::security::ConfigureForCOMImpersonation(manager.get());
27
+static wil::com_ptr<IWSLCSessionManager> CreateSessionManager()
28
+{
29
+ wil::com_ptr<IWSLCSessionManager> manager;
30
+ THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&manager)));
31
+ wsl::windows::common::security::ConfigureForCOMImpersonation(manager.get());
32
+ return manager;
33
+}
34
35
- wil::com_ptr<IWSLCSession> session;
36
- if (sessionName.empty())
37
- {
38
- // Default session: open it if it exists, otherwise create it.
39
- auto warningCallback = Microsoft::WRL::Make<WarningCallback>();
40
- THROW_IF_FAILED(manager->CreateSession(nullptr, WSLCSessionFlagsNone, warningCallback.Get(), &session));
41
- wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
42
- return session;
43
- }
35
+Session SessionService::OpenSessionByName(const wil::com_ptr<IWSLCSessionManager>& manager, LPCWSTR displayName)
36
+{
37
+ wil::com_ptr<IWSLCSession> session;
38
+ THROW_IF_FAILED(manager->OpenSessionByName(displayName, &session));
39
45
- HRESULT hr = manager->OpenSessionByName(sessionName.c_str(), &session);
46
- if (FAILED(hr))
47
- {
48
- THROW_HR_WITH_USER_ERROR_IF(
49
- hr, Localization::MessageWslcSessionNotFound(sessionName.c_str()), hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
40
+ wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
41
+ Session result(std::move(session));
42
+ if (displayName)
43
+ {
44
+ result.SetDisplayName(displayName);
45
+ }
46
+ return result;
47
+}
48
51
- THROW_HR_WITH_USER_ERROR(hr, Localization::MessageWslcOpenSessionFailed(sessionName.c_str()));
52
- }
49
+Session SessionService::OpenSession(const std::wstring& sessionName)
50
+{
51
+ return OpenSessionByName(CreateSessionManager(), sessionName.c_str());
52
+}
53
54
- wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
54
+Session SessionService::OpenDefaultSession()
55
+{
56
+ // Null DisplayName = default session, resolved from caller's token by the server.
57
+ return OpenSessionByName(CreateSessionManager(), nullptr);
58
+}
59
56
- return session;
57
- }
60
+Session SessionService::OpenOrCreateDefaultSession()
61
+{
62
+ auto manager = CreateSessionManager();
63
59
-} // namespace
64
+ // Null Settings = default session with server-determined name and settings.
65
+ wil::com_ptr<IWSLCSession> session;
66
+ auto warningCallback = Microsoft::WRL::Make<WarningCallback>();
67
+ THROW_IF_FAILED(manager->CreateSession(nullptr, WSLCSessionFlagsNone, warningCallback.Get(), &session));
68
+ wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
69
+ return Session(std::move(session));
70
+}
71
61
-int SessionService::Attach(const std::wstring& sessionName)
72
+int SessionService::Attach(const Session& session)
73
{
63
- auto session = OpenOrCreateSession(sessionName);
64
-
74
// Configure console for interactive usage.
75
wsl::windows::common::ConsoleState console{};
76
console.SetInteractiveMode();
@@ -72,7 +81,7 @@ int SessionService::Attach(const std::wstring& sessionName)
81
// Launch with terminal fds (PTY).
82
wsl::windows::common::WSLCProcessLauncher launcher{shell, {shell, "--login"}, {"TERM=xterm-256color"}, WSLCProcessFlagsTty | WSLCProcessFlagsStdin};
83
launcher.SetTtySize(windowSize.Y, windowSize.X);
75
- auto process = launcher.Launch(*session);
84
+ auto process = launcher.Launch(*session.Get());
85
auto tty = process.GetStdHandle(WSLCFDTty);
86
auto updateTerminalSize = [&]() {
87
const auto windowSize = console.GetWindowSize();
@@ -114,28 +123,12 @@ int SessionService::Attach(const std::wstring& sessionName)
123
return static_cast<int>(exitCode);
124
}
125
117
-Session SessionService::CreateDefaultSession()
118
-{
119
- wil::com_ptr<IWSLCSessionManager> sessionManager;
120
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
121
- wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get());
122
-
123
- // Null Settings = default session with server-determined name and settings.
124
- wil::com_ptr<IWSLCSession> session;
125
- auto warningCallback = Microsoft::WRL::Make<WarningCallback>();
126
- THROW_IF_FAILED(sessionManager->CreateSession(nullptr, WSLCSessionFlagsNone, warningCallback.Get(), &session));
127
- wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
128
- return Session(std::move(session));
129
-}
130
-
126
int SessionService::Enter(const std::wstring& storagePath, const std::wstring& displayName)
127
{
128
THROW_HR_IF(E_INVALIDARG, storagePath.empty());
129
THROW_HR_IF(E_INVALIDARG, displayName.empty());
130
136
- wil::com_ptr<IWSLCSessionManager> sessionManager;
137
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
138
- wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get());
131
+ auto sessionManager = CreateSessionManager();
132
133
wil::com_ptr<IWSLCSession> session;
134
auto warningCallback = Microsoft::WRL::Make<WarningCallback>();
@@ -156,9 +149,7 @@ int SessionService::Enter(const std::wstring& storagePath, const std::wstring& d
149
std::vector<SessionInformation> SessionService::List()
150
{
151
std::vector<SessionInformation> result;
159
- wil::com_ptr<IWSLCSessionManager> sessionManager;
160
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
161
- wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get());
152
+ auto sessionManager = CreateSessionManager();
153
154
wil::unique_cotaskmem_array_ptr<WSLCSessionListEntry> sessions;
155
THROW_IF_FAILED(sessionManager->ListSessions(&sessions, sessions.size_address<ULONG>()));
@@ -175,29 +166,15 @@ std::vector<SessionInformation> SessionService::List()
166
return result;
167
}
168
178
-Session SessionService::OpenSession(const std::wstring& displayName)
179
-{
180
- wil::com_ptr<IWSLCSessionManager> sessionManager;
181
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
182
- wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get());
183
-
184
- wil::com_ptr<IWSLCSession> session;
185
- THROW_IF_FAILED(sessionManager->OpenSessionByName(displayName.c_str(), &session));
186
- wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
187
- return Session(std::move(session));
188
-}
189
-
190
-int SessionService::Run(const std::wstring& sessionName, const std::vector<std::string>& arguments)
169
+int SessionService::Run(const Session& session, const std::vector<std::string>& arguments)
170
{
171
WI_ASSERT(!arguments.empty());
172
194
- auto session = OpenOrCreateSession(sessionName);
195
-
173
// Pass a default $PATH environment for convenience.
174
const std::vector<std::string> environment{"PATH=/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/sbin"};
175
wsl::windows::common::WSLCProcessLauncher launcher{arguments.front(), arguments, environment, WSLCProcessFlagsStdin};
176
200
- auto [result, process, error] = launcher.LaunchNoThrow(*session);
177
+ auto [result, process, error] = launcher.LaunchNoThrow(*session.Get());
178
THROW_HR_WITH_USER_ERROR_IF(result, Localization::MessageWslcFailedToLaunchCommand(arguments.front(), error), FAILED(result) && error != 0);
179
180
THROW_IF_FAILED(result);
@@ -206,40 +183,21 @@ int SessionService::Run(const std::wstring& sessionName, const std::vector<std::
183
return ConsoleService::AttachToCurrentConsole(console, std::move(process.value()));
184
}
185
209
-int SessionService::TerminateSession(const std::wstring& displayName)
186
+int SessionService::TerminateSession(const Session& session)
187
{
211
- wil::com_ptr<IWSLCSessionManager> sessionManager;
212
- THROW_IF_FAILED(CoCreateInstance(__uuidof(WSLCSessionManager), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&sessionManager)));
213
- wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get());
214
-
215
- wil::com_ptr<IWSLCSession> session;
216
- HRESULT hr = sessionManager->OpenSessionByName(displayName.empty() ? nullptr : displayName.c_str(), &session);
188
+ HRESULT hr = session.Get()->Terminate();
189
if (FAILED(hr))
190
{
219
- if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
191
+ auto errorString = wsl::windows::common::wslutil::ErrorCodeToString(hr);
192
+ if (session.DisplayName().has_value())
193
{
194
wslutil::PrintMessage(
222
- displayName.empty() ? Localization::MessageWslcDefaultSessionNotFound()
223
- : Localization::MessageWslcSessionNotFound(displayName.c_str()),
224
- stderr);
225
- return 1;
195
+ Localization::MessageErrorCode(Localization::MessageWslcTerminateSessionFailed(session.DisplayName().value()), errorString), stderr);
196
+ }
197
+ else
198
+ {
199
+ wslutil::PrintMessage(Localization::MessageErrorCode(Localization::MessageWslcTerminateDefaultSessionFailed(), errorString), stderr);
200
}
227
-
228
- THROW_HR(hr);
229
- }
230
-
231
- wsl::windows::common::security::ConfigureForCOMImpersonation(session.get());
232
-
233
- hr = session->Terminate();
234
- if (FAILED(hr))
235
- {
236
- auto errorString = wsl::windows::common::wslutil::ErrorCodeToString(hr);
237
- wslutil::PrintMessage(
238
- Localization::MessageErrorCode(
239
- displayName.empty() ? Localization::MessageWslcTerminateDefaultSessionFailed()
240
- : Localization::MessageWslcTerminateSessionFailed(displayName.c_str()),
241
- errorString),
242
- stderr);
201
return 1;
202
}
203
src/windows/wslc/services/SessionService.h
+13
-6
@@ -26,14 +26,21 @@ struct SessionInformation
26
27
struct SessionService
28
{
29
- static int Attach(const std::wstring& name);
30
- // Creates a default session with server-determined name and settings.
31
- static wsl::windows::wslc::models::Session CreateDefaultSession();
29
+ static int Attach(const wsl::windows::wslc::models::Session& session);
30
static int Enter(const std::wstring& storagePath, const std::wstring& displayName);
31
static std::vector<SessionInformation> List();
34
- static wsl::windows::wslc::models::Session OpenSession(const std::wstring& displayName);
32
+ // Opens an existing session by name. Throws if not found.
33
+ static wsl::windows::wslc::models::Session OpenSession(const std::wstring& name);
34
+ // Opens the default session. Throws WSLC_E_SESSION_NOT_FOUND if no default session exists.
35
+ static wsl::windows::wslc::models::Session OpenDefaultSession();
36
+ // Opens or creates the default session.
37
+ static wsl::windows::wslc::models::Session OpenOrCreateDefaultSession();
38
// Runs the given command and arguments in a session without a TTY, resolving the executable from PATH.
36
- static int Run(const std::wstring& name, const std::vector<std::string>& arguments);
37
- static int TerminateSession(const std::wstring& displayName);
39
+ static int Run(const wsl::windows::wslc::models::Session& session, const std::vector<std::string>& arguments);
40
+ static int TerminateSession(const wsl::windows::wslc::models::Session& session);
41
+
42
+private:
43
+ // Common open-only session lookup with unified error handling.
44
+ static wsl::windows::wslc::models::Session OpenSessionByName(const wil::com_ptr<IWSLCSessionManager>& manager, LPCWSTR displayName);
45
};
46
} // namespace wsl::windows::wslc::services
src/windows/wslc/tasks/SessionTasks.cpp
+28
-25
@@ -29,27 +29,39 @@ namespace wsl::windows::wslc::task {
29
30
void AttachToSession(CLIExecutionContext& context)
31
{
32
- std::wstring sessionId;
33
- if (context.Args.Contains(ArgType::SessionId))
34
- {
35
- sessionId = context.Args.Get<ArgType::SessionId>();
36
- }
37
-
38
- context.ExitCode = SessionService::Attach(sessionId);
32
+ auto& session = context.Data.Get<Data::Session>();
33
+ context.ExitCode = SessionService::Attach(session);
34
}
35
41
-void CreateSession(CLIExecutionContext& context)
36
+void OpenSessionIfSpecified(CLIExecutionContext& context)
37
{
38
if (context.GlobalArgs.Contains(ArgType::Session))
39
{
45
- // User specified a session name — open only, don't create.
40
const auto& sessionName = context.GlobalArgs.Get<ArgType::Session>();
41
context.Data.Add<Data::Session>(SessionService::OpenSession(sessionName));
48
- return;
42
}
43
+}
44
+
45
+void OpenOrCreateDefaultSession(CLIExecutionContext& context)
46
+{
47
+ if (!context.Data.Contains(Data::Session))
48
+ {
49
+ context.Data.Add<Data::Session>(SessionService::OpenOrCreateDefaultSession());
50
+ }
51
+}
52
+
53
+void OpenDefaultSession(CLIExecutionContext& context)
54
+{
55
+ if (!context.Data.Contains(Data::Session))
56
+ {
57
+ context.Data.Add<Data::Session>(SessionService::OpenDefaultSession());
58
+ }
59
+}
60
51
- // Create/open the default session.
52
- context.Data.Add<Data::Session>(SessionService::CreateDefaultSession());
61
+void ResolveSession(CLIExecutionContext& context)
62
+{
63
+ OpenSessionIfSpecified(context);
64
+ OpenOrCreateDefaultSession(context);
65
}
66
67
void ListSessions(CLIExecutionContext& context)
@@ -78,22 +90,13 @@ void ListSessions(CLIExecutionContext& context)
90
91
void TerminateSession(CLIExecutionContext& context)
92
{
81
- std::wstring sessionId;
82
- if (context.Args.Contains(ArgType::SessionId))
83
- {
84
- sessionId = context.Args.Get<ArgType::SessionId>();
85
- }
86
-
87
- context.ExitCode = SessionService::TerminateSession(sessionId);
93
+ auto& session = context.Data.Get<Data::Session>();
94
+ context.ExitCode = SessionService::TerminateSession(session);
95
}
96
97
void RunInSession(CLIExecutionContext& context)
98
{
92
- std::wstring sessionName;
93
- if (context.GlobalArgs.Contains(ArgType::Session))
94
- {
95
- sessionName = context.GlobalArgs.Get<ArgType::Session>();
96
- }
99
+ auto& session = context.Data.Get<Data::Session>();
100
101
std::vector<std::string> arguments;
102
arguments.emplace_back(wsl::windows::common::string::WideToMultiByte(context.Args.Get<ArgType::Command>()));
@@ -105,7 +108,7 @@ void RunInSession(CLIExecutionContext& context)
108
}
109
}
110
108
- context.ExitCode = SessionService::Run(sessionName, arguments);
111
+ context.ExitCode = SessionService::Run(session, arguments);
112
}
113
114
void EnterSession(CLIExecutionContext& context)
src/windows/wslc/tasks/SessionTasks.h
+3
-1
@@ -18,9 +18,11 @@ using wsl::windows::wslc::execution::CLIExecutionContext;
18
19
namespace wsl::windows::wslc::task {
20
void AttachToSession(CLIExecutionContext& context);
21
-void CreateSession(CLIExecutionContext& context);
21
void EnterSession(CLIExecutionContext& context);
22
void ListSessions(CLIExecutionContext& context);
23
+void OpenDefaultSession(CLIExecutionContext& context);
24
+void OpenSessionIfSpecified(CLIExecutionContext& context);
25
+void ResolveSession(CLIExecutionContext& context);
26
void RunInSession(CLIExecutionContext& context);
27
void TerminateSession(CLIExecutionContext& context);
28
} // namespace wsl::windows::wslc::task
test/windows/WSLCTests.cpp
+2
-2
@@ -403,10 +403,10 @@ class WSLCTests
403
VERIFY_SUCCEEDED(sessionManager->OpenSessionByName(c_testSessionName, &opened));
404
VERIFY_IS_NOT_NULL(opened.get());
405
406
- // And verify we get ERROR_NOT_FOUND for a nonexistent name
406
+ // And verify we get WSLC_E_SESSION_NOT_FOUND for a nonexistent name
407
wil::com_ptr<IWSLCSession> notFound;
408
auto hr = sessionManager->OpenSessionByName(L"this-name-does-not-exist", ¬Found);
409
- VERIFY_ARE_EQUAL(hr, HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
409
+ VERIFY_ARE_EQUAL(hr, WSLC_E_SESSION_NOT_FOUND);
410
}
411
412
WSLC_TEST_METHOD(CreateSessionValidation)
test/windows/wslc/CommandLineTestCases.h
+2
-2
@@ -41,7 +41,7 @@ COMMAND_LINE_TEST_CASE(L"system session list --verbose", L"list", true)
41
COMMAND_LINE_TEST_CASE(L"system session list --verbose --help", L"list", true)
42
COMMAND_LINE_TEST_CASE(L"system session list --notanarg", L"list", false)
43
COMMAND_LINE_TEST_CASE(L"system session list extraarg", L"list", false)
44
-COMMAND_LINE_TEST_CASE(L"system session shell session1", L"shell", true)
44
+COMMAND_LINE_TEST_CASE(L"--session session1 system session shell", L"shell", true)
45
COMMAND_LINE_TEST_CASE(L"system session shell", L"shell", true)
46
COMMAND_LINE_TEST_CASE(L"system session run ls", L"run", true)
47
COMMAND_LINE_TEST_CASE(L"system session run echo foo", L"run", true) // Command with trailing arguments
@@ -52,7 +52,7 @@ COMMAND_LINE_TEST_CASE(L"system session run \"ls -la /tmp\"", L"run", true)
52
COMMAND_LINE_TEST_CASE(L"system session run", L"run", false) // Missing required command positional
53
COMMAND_LINE_TEST_CASE(L"--session session1 system session run", L"run", false) // Missing required command positional
54
COMMAND_LINE_TEST_CASE(L"system session run --notanarg ls", L"run", false) // Invalid flag before command
55
-COMMAND_LINE_TEST_CASE(L"system session terminate session1", L"terminate", true)
55
+COMMAND_LINE_TEST_CASE(L"--session session1 system session terminate", L"terminate", true)
56
COMMAND_LINE_TEST_CASE(L"system session terminate", L"terminate", true)
57
COMMAND_LINE_TEST_CASE(L"system session enter C:\\storage", L"enter", true)
58
COMMAND_LINE_TEST_CASE(L"system session enter C:\\storage --name my-session", L"enter", true)
test/windows/wslc/e2e/WSLCE2EGlobalTests.cpp
+19
-18
@@ -116,7 +116,7 @@ class WSLCE2EGlobalTests
116
117
// Try to explicitly target the admin session from non-elevated process
118
auto adminName = GetExpectedDefaultSessionName(true);
119
- result = RunWslc(std::format(L"--session {} container list", adminName), ElevationType::NonElevated);
119
+ result = RunWslc(std::format(L"--session \"{}\" container list", adminName), ElevationType::NonElevated);
120
121
// Should fail with access denied.
122
result.Verify({.Stderr = L"The requested operation requires elevation. \r\nError code: ERROR_ELEVATION_REQUIRED\r\n", .ExitCode = 1});
@@ -130,7 +130,7 @@ class WSLCE2EGlobalTests
130
131
// Elevated user should be able to explicitly target the non-admin session
132
auto nonAdminName = GetExpectedDefaultSessionName(false);
133
- result = RunWslc(std::format(L"--session {} container list", nonAdminName), ElevationType::Elevated);
133
+ result = RunWslc(std::format(L"--session \"{}\" container list", nonAdminName), ElevationType::Elevated);
134
135
// This should work - elevated users can access non-elevated sessions
136
result.Verify({.Stderr = L"", .ExitCode = 0});
@@ -144,12 +144,12 @@ class WSLCE2EGlobalTests
144
// Ensure elevated cannot create the non-elevated session.
145
auto nonAdminName = GetExpectedDefaultSessionName(false);
146
auto adminName = GetExpectedDefaultSessionName(true);
147
- auto result = RunWslc(std::format(L"--session {} container list", nonAdminName), ElevationType::Elevated);
148
- result.Verify({.Stderr = L"Element not found. \r\nError code: ERROR_NOT_FOUND\r\n", .ExitCode = 1});
147
+ auto result = RunWslc(std::format(L"--session \"{}\" container list", nonAdminName), ElevationType::Elevated);
148
+ result.Verify({.Stderr = std::format(L"Session not found: '{}'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", nonAdminName), .ExitCode = 1});
149
150
// Ensure non-elevated cannot create the elevated session.
151
- result = RunWslc(std::format(L"--session {} container list", adminName), ElevationType::NonElevated);
152
- result.Verify({.Stderr = L"Element not found. \r\nError code: ERROR_NOT_FOUND\r\n", .ExitCode = 1});
151
+ result = RunWslc(std::format(L"--session \"{}\" container list", adminName), ElevationType::NonElevated);
152
+ result.Verify({.Stderr = std::format(L"Session not found: '{}'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", adminName), .ExitCode = 1});
153
}
154
155
// Regression test for session name squatting vulnerability.
@@ -298,7 +298,7 @@ class WSLCE2EGlobalTests
298
VERIFY_IS_TRUE(result.Stdout->find(adminName) != std::wstring::npos);
299
300
// Terminate the session
301
- result = RunWslc(std::format(L"system session terminate {}", adminName));
301
+ result = RunWslc(std::format(L"--session \"{}\" system session terminate", adminName));
302
result.Verify({.Stderr = L"", .ExitCode = 0});
303
304
// Verify session no longer shows up
@@ -320,7 +320,7 @@ class WSLCE2EGlobalTests
320
VERIFY_IS_TRUE(result.Stdout->find(nonAdminName + L"\r\n") != std::wstring::npos);
321
322
// Terminate the session
323
- result = RunWslc(std::format(L"system session terminate {}", nonAdminName), ElevationType::NonElevated);
323
+ result = RunWslc(std::format(L"--session \"{}\" system session terminate", nonAdminName), ElevationType::NonElevated);
324
result.Verify({.Stderr = L"", .ExitCode = 0});
325
326
// Verify session no longer shows up
@@ -349,11 +349,11 @@ class WSLCE2EGlobalTests
349
VERIFY_IS_TRUE(result.Stdout->find(nonAdminName + L"\r\n") != std::wstring::npos);
350
351
// Attempt to terminate the admin session from the non-elevated process and fail.
352
- result = RunWslc(std::format(L"system session terminate {}", adminName), ElevationType::NonElevated);
352
+ result = RunWslc(std::format(L"--session \"{}\" system session terminate", adminName), ElevationType::NonElevated);
353
result.Verify({.Stderr = L"The requested operation requires elevation. \r\nError code: ERROR_ELEVATION_REQUIRED\r\n", .ExitCode = 1});
354
355
// Terminate the non-elevated session from the elevated process.
356
- result = RunWslc(std::format(L"system session terminate {}", nonAdminName), ElevationType::Elevated);
356
+ result = RunWslc(std::format(L"--session \"{}\" system session terminate", nonAdminName), ElevationType::Elevated);
357
result.Verify({.Stderr = L"", .ExitCode = 0});
358
359
// Verify non-elevated session no longer shows up
@@ -379,7 +379,8 @@ class WSLCE2EGlobalTests
379
380
// Verify targeting a non-existent session fails.
381
auto result = RunWslc(L"--session INVALID_SESSION_NAME container list");
382
- result.Verify({.Stdout = L"", .Stderr = L"Element not found. \r\nError code: ERROR_NOT_FOUND\r\n", .ExitCode = 1});
382
+ result.Verify(
383
+ {.Stdout = L"", .Stderr = L"Session not found: 'INVALID_SESSION_NAME'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", .ExitCode = 1});
384
385
// Verify session list
386
result = RunWslc(L"system session list");
@@ -391,12 +392,12 @@ class WSLCE2EGlobalTests
392
VERIFY_ARE_NOT_EQUAL(findResult, std::wstring::npos);
393
394
// Run container list in the test session, which should succeed if the session is valid.
394
- result = RunWslc(std::format(L"--session {} container list", session.Name()));
395
+ result = RunWslc(std::format(L"--session \"{}\" container list", session.Name()));
396
result.Verify({.Stderr = L"", .ExitCode = 0});
397
398
// Add a container to the new session.
398
- result = RunWslc(
399
- std::format(L"--session {} container create --name {} {}", session.Name(), L"test-cont", DebianTestImage().NameAndTag()));
399
+ result = RunWslc(std::format(
400
+ L"--session \"{}\" container create --name {} {}", session.Name(), L"test-cont", DebianTestImage().NameAndTag()));
401
result.Dump(); // Dump so it is easier to find any potential issues with the pull in the test output.
402
result.Verify({.ExitCode = 0});
403
@@ -444,7 +445,7 @@ class WSLCE2EGlobalTests
445
Log::Comment(L"Testing non-elevated interactive session with explicit session name");
446
// Non-Elevated session shell should attach to the wslc by name also.
447
auto nonAdminName = GetExpectedDefaultSessionName(false);
447
- auto session = RunWslcInteractive(std::format(L"system session shell {}", nonAdminName), ElevationType::NonElevated);
448
+ auto session = RunWslcInteractive(std::format(L"--session \"{}\" system session shell", nonAdminName), ElevationType::NonElevated);
449
VERIFY_IS_TRUE(session.IsRunning(), L"Session should be running");
450
451
session.ExpectStdout(VT::SESSION_PROMPT);
@@ -469,7 +470,7 @@ class WSLCE2EGlobalTests
470
Log::Comment(L"Testing elevated interactive session with explicit admin session name");
471
// Elevated session shell should attach to the wslc by name also.
472
auto adminName = GetExpectedDefaultSessionName(true);
472
- auto session = RunWslcInteractive(std::format(L"system session shell {}", adminName), ElevationType::Elevated);
473
+ auto session = RunWslcInteractive(std::format(L"--session \"{}\" system session shell", adminName), ElevationType::Elevated);
474
VERIFY_IS_TRUE(session.IsRunning(), L"Session should be running");
475
476
session.ExpectStdout(VT::SESSION_PROMPT);
@@ -500,13 +501,13 @@ class WSLCE2EGlobalTests
501
}
502
503
{
503
- auto result = RunWslc(std::format(L"--session {} system session run echo OK", GetExpectedDefaultSessionName(true)));
504
+ auto result = RunWslc(std::format(L"--session \"{}\" system session run echo OK", GetExpectedDefaultSessionName(true)));
505
result.Verify({.Stdout = L"OK\n", .Stderr = L"", .ExitCode = 0});
506
}
507
508
{
509
auto result = RunWslc(L"--session not-found system session run echo OK");
509
- result.Verify({.Stdout = L"", .Stderr = L"Session not found: 'not-found'\r\nError code: ERROR_NOT_FOUND\r\n", .ExitCode = 1});
510
+ result.Verify({.Stderr = L"Session not found: 'not-found'\r\nError code: WSLC_E_SESSION_NOT_FOUND\r\n", .ExitCode = 1});
511
}
512
513
{
test/windows/wslc/e2e/WSLCE2EHelpers.cpp
+2
-2
@@ -145,7 +145,7 @@ void VerifyContainerIsListed(const std::wstring& containerNameOrId, const std::w
145
std::wstring command = L"container list --no-trunc --all";
146
if (!sessionName.empty())
147
{
148
- command = std::format(L"--session {} container list --no-trunc --all", sessionName);
148
+ command = std::format(L"--session \"{}\" container list --no-trunc --all", sessionName);
149
}
150
151
auto result = RunWslc(command);
@@ -429,7 +429,7 @@ void EnsureSessionIsTerminated(const std::wstring& sessionName)
429
// Check if the line ends with the target session name
430
if (line.size() >= targetSession.size() && line.compare(line.size() - targetSession.size(), targetSession.size(), targetSession) == 0)
431
{
432
- auto result = RunWslc(std::format(L"system session terminate \"{}\"", targetSession));
432
+ auto result = RunWslc(std::format(L"--session \"{}\" system session terminate", targetSession));
433
result.Verify({.Stdout = L"", .Stderr = L"", .ExitCode = 0});
434
break;
435
}
test/windows/wslc/e2e/WSLCE2ENetworkPruneTests.cpp
-1
@@ -244,7 +244,6 @@ private:
244
std::wstringstream options;
245
options << L"The following options are available:\r\n"
246
<< L" -f,--filter " << Localization::WSLCCLI_FilterArgDescription() << L"\r\n"
247
- << L" --session " << Localization::WSLCCLI_SessionIdArgDescription() << L"\r\n"
247
<< L" -?,--help " << Localization::WSLCCLI_HelpArgDescription() << L"\r\n"
248
<< L"\r\n";
249
return options.str();
test/windows/wslc/e2e/WSLCE2ETlsRegistryTests.cpp
+6
-4
@@ -227,9 +227,10 @@ class WSLCE2ETlsRegistryTests
227
auto [registry, address] = StartLocalRegistry(session.Session(), "", "", c_registryPort, certDir.wstring());
228
VERIFY_ARE_EQUAL(std::format("{}:{}", c_registryIp, c_registryPort), address);
229
230
- RunWslcAndVerify(std::format(L"--session {} image tag {} {}", session.Name(), image.NameAndTag(), registryImage), {.ExitCode = 0});
230
+ RunWslcAndVerify(
231
+ std::format(L"--session \"{}\" image tag {} {}", session.Name(), image.NameAndTag(), registryImage), {.ExitCode = 0});
232
232
- auto result = RunWslc(std::format(L"--session {} push {}", session.Name(), registryImage));
233
+ auto result = RunWslc(std::format(L"--session \"{}\" push {}", session.Name(), registryImage));
234
VERIFY_ARE_EQUAL(1u, result.ExitCode.value_or(0), L"Push should fail while the CA is not trusted");
235
VERIFY_IS_TRUE(result.Stderr.has_value());
236
VERIFY_IS_TRUE(
@@ -251,9 +252,10 @@ class WSLCE2ETlsRegistryTests
252
auto [registry, address] = StartLocalRegistry(session.Session(), "", "", c_registryPort, certDir.wstring());
253
VERIFY_ARE_EQUAL(std::format("{}:{}", c_registryIp, c_registryPort), address);
254
254
- RunWslcAndVerify(std::format(L"--session {} image tag {} {}", session.Name(), image.NameAndTag(), registryImage), {.ExitCode = 0});
255
+ RunWslcAndVerify(
256
+ std::format(L"--session \"{}\" image tag {} {}", session.Name(), image.NameAndTag(), registryImage), {.ExitCode = 0});
257
256
- auto result = RunWslc(std::format(L"--session {} push {}", session.Name(), registryImage));
258
+ auto result = RunWslc(std::format(L"--session \"{}\" push {}", session.Name(), registryImage));
259
VERIFY_ARE_EQUAL(0u, result.ExitCode.value_or(1), L"Push should succeed once the CA is trusted");
260
}
261
}