Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 6 additions & 72 deletions src/shared/inc/stringshared.h
Original file line number Diff line number Diff line change
Expand Up @@ -927,81 +927,15 @@ struct std::formatter<std::source_location, wchar_t>
template <typename TCtx>
auto format(const std::source_location& location, TCtx& ctx) const
{
return std::format_to(ctx.out(), L"{}[{}:{}]", location.function_name(), location.file_name(), location.line());
return std::format_to(
ctx.out(),
L"{}[{}:{}]",
wsl::shared::string::MultiByteToWide(location.function_name()),
wsl::shared::string::MultiByteToWide(location.file_name()),
location.line());
}
};

// char -> wchar_t formatting is only used by the Windows components. libc++ (used to
// build the Linux components) now provides these as deleted specializations per C++23
// [format.formatter.spec], which would collide, so restrict them to Windows.
#ifdef WIN32

template <>
struct std::formatter<char*, wchar_t>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}

template <typename TCtx>
auto format(const char* str, TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
}
};

template <>
struct std::formatter<const char*, wchar_t>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}

template <typename TCtx>
auto format(const char* str, TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
}
};

template <std::size_t N>
struct std::formatter<char[N], wchar_t>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}

template <typename TCtx>
auto format(const char str[N], TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
}
};

template <class Traits, class Allocator>
struct std::formatter<std::basic_string<char, Traits, Allocator>, wchar_t>
{
template <typename TCtx>
static constexpr auto parse(TCtx& ctx)
{
return ctx.begin();
}

template <typename TCtx>
auto format(const std::basic_string<char, Traits, Allocator>& str, TCtx& ctx) const
{
return std::format_to(ctx.out(), "{}", wsl::shared::string::MultiByteToWide(str));
}
};

#endif // WIN32

template <>
struct std::formatter<std::filesystem::path, wchar_t>
{
Expand Down
3 changes: 1 addition & 2 deletions src/windows/common/WSLCUserSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,7 @@ namespace {
}
catch (const std::exception& e)
{
warnings.push_back(
{wsl::shared::Localization::WSLCUserSettings_Warning_ParseError(path.wstring(), MultiByteToWide(e.what())), {}});
warnings.push_back({wsl::shared::Localization::WSLCUserSettings_Warning_ParseError(path.wstring(), e.what()), {}});
return std::nullopt;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/commands/VersionCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ std::wstring VersionCommand::LongDescription() const

void VersionCommand::PrintVersion(Reporter& reporter)
{
reporter.Output(L"{} {}\n", s_ExecutableName, WSL_PACKAGE_VERSION);
reporter.Output(L"{} {}\n", s_ExecutableName, STRING_TO_WIDE_STRING(WSL_PACKAGE_VERSION));
}

void VersionCommand::ExecuteInternal(CLIExecutionContext& context) const
Expand Down
4 changes: 2 additions & 2 deletions src/windows/wslc/services/BuildImageCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ try
{
for (const auto& line : m_allLines)
{
m_reporter.Info(L"{}", line);
m_reporter.Info(L"{}", wsl::shared::string::MultiByteToWide(line));
}
}
}
Expand Down Expand Up @@ -100,7 +100,7 @@ try
// Skip pull progress updates when output is redirected, show only major steps
if (!isPullProgress)
{
m_reporter.Info(L"{}", status);
m_reporter.Info(L"{}", wsl::shared::string::MultiByteToWide(status));
}
return S_OK;
}
Expand Down
16 changes: 8 additions & 8 deletions src/windows/wslc/services/ContainerModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ PublishPort::PortRange PublishPort::PortRange::ParsePortPart(const std::string&
// Ensure the value is not empty and contains only digits before parsing
if (value.empty() || !std::all_of(value.begin(), value.end(), ::isdigit))
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, errorMessage);
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, MultiByteToWide(errorMessage));
}

// Parse the port number and validate the range
auto port = std::stoul(value, nullptr, 10);
if (!PublishPort::IsValidPort(port))
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, errorMessage);
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, MultiByteToWide(errorMessage));
}
return static_cast<uint16_t>(port);
}
catch (const std::exception&)
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, errorMessage);
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, MultiByteToWide(errorMessage));
}
};

Expand Down Expand Up @@ -84,7 +84,7 @@ PublishPort PublishPort::Parse(const std::string& value)
else
{
THROW_HR_WITH_USER_ERROR(
E_INVALIDARG, "Invalid protocol specified in port mapping. Only 'tcp' and 'udp' are supported.");
E_INVALIDARG, L"Invalid protocol specified in port mapping. Only 'tcp' and 'udp' are supported.");
}
Comment thread
benhillis marked this conversation as resolved.
Comment on lines 86 to 88
}

Expand Down Expand Up @@ -128,24 +128,24 @@ void PublishPort::Validate() const
{
if (m_containerPort.Count() == 0)
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, "Container port must specify at least one port.");
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, L"Container port must specify at least one port.");
}

if (!m_containerPort.IsValid())
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, "Container port must be a valid port number (1-65535).");
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, L"Container port must be a valid port number (1-65535).");
}

if (!m_hostPort.IsEphemeral())
{
if (!m_hostPort.IsValid())
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, "Host port must be a valid port number (1-65535).");
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, L"Host port must be a valid port number (1-65535).");
}

if (m_hostPort.Count() != m_containerPort.Count())
{
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, "Host port range must match the container port range.");
THROW_HR_WITH_USER_ERROR(E_INVALIDARG, L"Host port range must match the container port range.");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/services/ContainerService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static wsl::windows::common::RunningWSLCContainer CreateInternal(Reporter& repor
// Implicit pull for run/create: progress goes to Info (stderr), keeping stdout for the
// container id/output.
ImageProgressCallback callback(reporter, Reporter::Level::Info);
reporter.Info(L"{}\n", Localization::WSLCCLI_ImageNotFoundPulling(wsl::shared::string::MultiByteToWide(image)));
reporter.Info(L"{}\n", Localization::WSLCCLI_ImageNotFoundPulling(image));
ImageService imageService;
imageService.Pull(reporter, session, image, &callback);
}
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/services/FileCredStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ void FileCredStorage::Erase(const std::string& serverAddress)
});
}

THROW_HR_WITH_USER_ERROR_IF(E_NOT_SET, Localization::WSLCCLI_LogoutNotFound(wsl::shared::string::MultiByteToWide(serverAddress)), !erased);
THROW_HR_WITH_USER_ERROR_IF(E_NOT_SET, Localization::WSLCCLI_LogoutNotFound(serverAddress), !erased);
}

std::vector<std::wstring> FileCredStorage::List()
Expand Down
17 changes: 11 additions & 6 deletions src/windows/wslc/services/ImageProgressCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ HRESULT ImageProgressCallback::OnProgress(LPCSTR status, LPCSTR id, ULONGLONG cu
{
if (id == nullptr || *id == '\0')
{
m_reporter.Write(m_level, L"{}\n", status);
m_reporter.Write(m_level, L"{}\n", wsl::shared::string::MultiByteToWide(status));
}
else
{
auto [it, inserted] = m_lastStatusById.try_emplace(id, status);
if (inserted || it->second != status)
{
it->second = status;
m_reporter.Write(m_level, L"{}: {}\n", id, status);
m_reporter.Write(m_level, L"{}: {}\n", wsl::shared::string::MultiByteToWide(id), wsl::shared::string::MultiByteToWide(status));
}
}

Expand All @@ -79,7 +79,7 @@ HRESULT ImageProgressCallback::OnProgress(LPCSTR status, LPCSTR id, ULONGLONG cu

if (id == nullptr || *id == '\0') // Print all 'global' statuses on their own line
{
m_reporter.Write(m_level, L"{}\n", status);
m_reporter.Write(m_level, L"{}\n", wsl::shared::string::MultiByteToWide(status));
m_currentLine++;
return S_OK;
}
Expand Down Expand Up @@ -144,15 +144,20 @@ std::wstring ImageProgressCallback::GenerateStatusLine(LPCSTR status, LPCSTR id,
progress += std::format(L"/{}", wsl::shared::string::FormatBytes(total));
}

line = std::format(L"{}: {} [{}] {}", safeId, safeStatus, bar, progress);
line = std::format(
L"{}: {} [{}] {}", wsl::shared::string::MultiByteToWide(safeId), wsl::shared::string::MultiByteToWide(safeStatus), bar, progress);
}
else if (current != 0)
{
line = std::format(L"{}: {} {}", safeId, safeStatus, wsl::shared::string::FormatBytes(current));
line = std::format(
L"{}: {} {}",
wsl::shared::string::MultiByteToWide(safeId),
wsl::shared::string::MultiByteToWide(safeStatus),
wsl::shared::string::FormatBytes(current));
}
else
{
line = std::format(L"{}: {}", safeId, safeStatus);
line = std::format(L"{}: {}", wsl::shared::string::MultiByteToWide(safeId), wsl::shared::string::MultiByteToWide(safeStatus));
}

// Truncate to the console width to prevent wrapping that breaks cursor repositioning, then pad
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/services/SessionService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ int SessionService::Attach(Reporter& reporter, const Session& session)

auto exitCode = process.GetExitCode();

reporter.Output(L"{}\n", wsl::shared::Localization::MessageWslcShellExited(string::MultiByteToWide(shell), static_cast<int>(exitCode)));
reporter.Output(L"{}\n", wsl::shared::Localization::MessageWslcShellExited(shell, static_cast<int>(exitCode)));

return static_cast<int>(exitCode);
}
Expand Down
3 changes: 1 addition & 2 deletions src/windows/wslc/services/WinCredStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ void WinCredStorage::Erase(const std::string& serverAddress)
if (!CredDeleteW(targetName.c_str(), CRED_TYPE_GENERIC, 0))
{
auto error = GetLastError();
THROW_HR_WITH_USER_ERROR_IF(
E_NOT_SET, Localization::WSLCCLI_LogoutNotFound(wsl::shared::string::MultiByteToWide(serverAddress)), error == ERROR_NOT_FOUND);
THROW_HR_WITH_USER_ERROR_IF(E_NOT_SET, Localization::WSLCCLI_LogoutNotFound(serverAddress), error == ERROR_NOT_FOUND);

THROW_WIN32(error);
}
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/tasks/ImageTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void ListImages(CLIExecutionContext& context)
bool trunc = !context.Args.Contains(ArgType::NoTrunc);
for (const auto& image : images)
{
context.Reporter.Output(L"{}\n", trunc ? TruncateId(image.Id, true) : image.Id);
context.Reporter.Output(L"{}\n", wsl::shared::string::MultiByteToWide(trunc ? TruncateId(image.Id, true) : image.Id));
}

return;
Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/tasks/NetworkTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ void PruneNetworks(CLIExecutionContext& context)

for (const auto& networkName : result.PrunedNetworks)
{
context.Reporter.Output(L"{}\n", Localization::WSLCCLI_NetworkPruneDeleted(MultiByteToWide(networkName)));
context.Reporter.Output(L"{}\n", Localization::WSLCCLI_NetworkPruneDeleted(networkName));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/windows/wslc/tasks/RegistryTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void Logout(CLIExecutionContext& context)

RegistryService::Erase(serverAddress);

context.Reporter.Output(L"{}\n", Localization::WSLCCLI_LogoutSucceeded(MultiByteToWide(serverAddress)));
context.Reporter.Output(L"{}\n", Localization::WSLCCLI_LogoutSucceeded(serverAddress));
}

} // namespace wsl::windows::wslc::task
2 changes: 1 addition & 1 deletion src/windows/wslc/tasks/VolumeTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ void PruneVolumes(CLIExecutionContext& context)

for (const auto& volumeName : result.PrunedVolumes)
{
context.Reporter.Output(L"{}\n", Localization::WSLCCLI_VolumePruneDeleted(MultiByteToWide(volumeName)));
context.Reporter.Output(L"{}\n", Localization::WSLCCLI_VolumePruneDeleted(volumeName));
}

context.Reporter.Output(L"\n");
Expand Down
5 changes: 4 additions & 1 deletion src/windows/wslcsession/DockerHTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ Module Name:
if ((_Ex).HasErrorMessage()) \
{ \
THROW_HR_WITH_USER_ERROR_MSG( \
(_Ex).HResultFromStatusCode(), (_Ex).DockerMessage<wsl::windows::common::docker_schema::ErrorResponse>().message, _Msg, ##__VA_ARGS__); \
(_Ex).HResultFromStatusCode(), \
wsl::shared::string::MultiByteToWide((_Ex).DockerMessage<wsl::windows::common::docker_schema::ErrorResponse>().message), \
_Msg, \
##__VA_ARGS__); \
} \
else \
{ \
Expand Down
15 changes: 9 additions & 6 deletions src/windows/wslcsession/WSLCContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1193,8 +1193,9 @@ void WSLCContainerImpl::Export(WSLCHandle OutHandle) const
// Export failed, parse the error message.
auto error = wsl::shared::FromJson<common::docker_schema::ErrorResponse>(errorJson.c_str());

THROW_HR_WITH_USER_ERROR_IF(WSLC_E_CONTAINER_NOT_FOUND, error.message, SocketCodePair.first == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
const auto wideErrorMessage = wsl::shared::string::MultiByteToWide(error.message);
THROW_HR_WITH_USER_ERROR_IF(WSLC_E_CONTAINER_NOT_FOUND, wideErrorMessage, SocketCodePair.first == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, wideErrorMessage);
}
}

Expand Down Expand Up @@ -1254,8 +1255,9 @@ void WSLCContainerImpl::UploadArchive(WSLCHandle TarHandle, LPCSTR DestPath, ULO
{
auto error = wsl::shared::FromJson<ErrorResponse>(pendingErrorJson->c_str());

THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), error.message, httpStatusCode == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
const auto wideErrorMessage = wsl::shared::string::MultiByteToWide(error.message);
THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), wideErrorMessage, httpStatusCode == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, wideErrorMessage);
}
}

Expand Down Expand Up @@ -1301,8 +1303,9 @@ void WSLCContainerImpl::DownloadArchive(LPCSTR SrcPath, WSLCHandle OutHandle) co
{
auto error = wsl::shared::FromJson<ErrorResponse>(errorJson.c_str());

THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), error.message, statusCode == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, error.message);
const auto wideErrorMessage = wsl::shared::string::MultiByteToWide(error.message);
THROW_HR_WITH_USER_ERROR_IF(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), wideErrorMessage, statusCode == 404);
THROW_HR_WITH_USER_ERROR(E_FAIL, wideErrorMessage);
}
}

Expand Down
Loading