Update wstring converter

PiperOrigin-RevId: 682112846
This commit is contained in:
Eiden Kim
2024-10-03 18:32:59 -07:00
committed by Copybara-Service
parent ab00092c6c
commit 25d4aca219
10 changed files with 413 additions and 46 deletions
+38 -1
View File
@@ -41,7 +41,9 @@ cc_library(
"utils.h",
],
defines = ["_SILENCE_CLANG_COROUTINE_MESSAGE"],
visibility = ["//sharing/internal/impl/windows:__pkg__"],
visibility = [
"//sharing/internal/impl/windows:__pkg__",
],
deps = [
":comm",
"//internal/base:bluetooth_address",
@@ -143,6 +145,26 @@ cc_library(
],
)
cc_library(
name = "string_utils",
srcs = [
"string_utils.cc",
],
hdrs = [
"string_utils.h",
],
compatible_with = ["//buildenv/target:non_prod"],
visibility = [
"//internal/platform:__subpackages__",
"//location/nearby:__subpackages__",
],
deps = [
"//internal/platform:logging",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
)
cc_library(
name = "windows",
srcs = [
@@ -209,6 +231,7 @@ cc_library(
deps = [
":comm",
":crypto", # build_cleaner: keep
":string_utils",
":types",
"//connections/implementation/flags:connections_flags",
"//internal/account",
@@ -313,3 +336,17 @@ cc_test(
"@nlohmann_json//:json",
],
)
cc_test(
name = "string_utils_test",
size = "small",
timeout = "short",
srcs = [
"string_utils_test.cc",
],
deps = [
":string_utils",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
@@ -24,7 +24,7 @@
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/logging.h"
namespace nearby {
@@ -38,7 +38,8 @@ std::unique_ptr<IOFile> IOFile::CreateInputFile(absl::string_view file_path,
IOFile::IOFile(absl::string_view file_path, size_t size) : path_(file_path) {
// Always open input file path as wide string on Windows platform.
std::wstring wide_path = string_to_wstring(std::string(file_path));
std::wstring wide_path = string_utils::StringToWideString(
std::string(file_path));
file_.open(wide_path, std::ios::binary | std::ios::in | std::ios::ate);
total_size_ = file_.tellg();
@@ -59,7 +60,8 @@ std::unique_ptr<IOFile> IOFile::CreateOutputFile(absl::string_view path) {
IOFile::IOFile(absl::string_view file_path)
: file_(), path_(file_path), total_size_(0) {
// Always open input file path as wide string on Windows platform.
std::wstring wide_path = string_to_wstring(path_);
std::wstring wide_path =
string_utils::StringToWideString(path_);
file_.open(wide_path, std::ios::binary | std::ios::out);
}
@@ -38,6 +38,7 @@
#include "absl/types/span.h"
#include "connections/implementation/flags/nearby_connections_feature_flags.h"
#include "internal/flags/nearby_flags.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/logging.h"
@@ -177,8 +178,8 @@ std::wstring FilePath::CreateOutputFileWithRename(std::wstring path) {
}
if (count > 0) {
LOG(INFO) << "Renamed " << wstring_to_string(path) << " to "
<< wstring_to_string(target);
LOG(INFO) << "Renamed " << string_utils::WideStringToString(path) << " to "
<< string_utils::WideStringToString(target);
}
// The above leaves the file open, so close it.
@@ -216,8 +217,9 @@ std::wstring FilePath::MutateForbiddenPathElements(std::wstring& str) {
if (tmp_path_element.size() == 1 && tmp_path_element[0] == kDot) {
// Change the dot path name to an underscore.
tmp_path_element[0] = kReplacementChar;
LOG(INFO) << "Renamed path element " << wstring_to_string(path_element)
<< " to " << wstring_to_string(tmp_path_element);
LOG(INFO) << "Renamed path element "
<< string_utils::WideStringToString(path_element) << " to "
<< string_utils::WideStringToString(tmp_path_element);
path_element[0] = kReplacementChar;
}
@@ -228,8 +230,9 @@ std::wstring FilePath::MutateForbiddenPathElements(std::wstring& str) {
while (std::find(forbidden.begin(), forbidden.end(), tmp_path_element) !=
forbidden.end()) {
tmp_path_element.insert(tmp_path_element.begin(), kReplacementChar);
LOG(INFO) << "Renamed path element " << wstring_to_string(path_element)
<< " to " << wstring_to_string(tmp_path_element);
LOG(INFO) << "Renamed path element "
<< string_utils::WideStringToString(path_element) << " to "
<< string_utils::WideStringToString(tmp_path_element);
path_element.insert(path_element.begin(), kReplacementChar);
}
@@ -263,21 +266,21 @@ void FilePath::ReplaceInvalidCharacters(std::wstring& path) {
for (; it != path.end(); it++) {
// If 0 < character < 32, it's illegal, replace it
if (*it > 0 && *it < 32) {
LOG(INFO) << "In path " << wstring_to_string(path) << " replaced \'"
<< std::string(1, *it) << "\' with \'"
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
<< " replaced \'" << std::string(1, *it) << "\' with \'"
<< std::string(1, kReplacementChar);
*it = kReplacementChar;
}
if (*it == 0) { // character is null
LOG(INFO) << "In path " << wstring_to_string(path)
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
<< " replaced \'NULL\' with \'"
<< std::string(1, kReplacementChar) << "\'";
*it = kReplacementChar;
}
for (auto illegal_character : kIllegalFileCharacters) {
if (*it == illegal_character) {
LOG(INFO) << "In path " << wstring_to_string(path) << " replaced \'"
<< std::string(1, *it) << "\' with \'"
LOG(INFO) << "In path " << string_utils::WideStringToString(path)
<< " replaced \'" << std::string(1, *it) << "\' with \'"
<< std::string(1, kReplacementChar);
*it = kReplacementChar;
}
@@ -69,6 +69,7 @@
#include "internal/platform/implementation/windows/preferences_manager.h"
#include "internal/platform/implementation/windows/scheduled_executor.h"
#include "internal/platform/implementation/windows/server_sync.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/implementation/windows/submittable_executor.h"
#include "internal/platform/implementation/windows/timer.h"
#include "internal/platform/implementation/windows/utils.h"
@@ -114,28 +115,28 @@ std::string GetApplicationName(DWORD pid) {
std::string ImplementationPlatform::GetCustomSavePath(
const std::string& parent_folder, const std::string& file_name) {
auto parent = windows::string_to_wstring(parent_folder);
auto file = windows::string_to_wstring(file_name);
auto parent = windows::string_utils::StringToWideString(parent_folder);
auto file = windows::string_utils::StringToWideString(file_name);
return windows::wstring_to_string(
return windows::string_utils::WideStringToString(
windows::FilePath::GetCustomSavePath(parent, file));
}
std::string ImplementationPlatform::GetDownloadPath(
const std::string& parent_folder, const std::string& file_name) {
auto parent = windows::string_to_wstring(std::string(parent_folder));
auto file = windows::string_to_wstring(std::string(file_name));
auto parent = windows::string_utils::StringToWideString(parent_folder);
auto file = windows::string_utils::StringToWideString(file_name);
return windows::wstring_to_string(
return windows::string_utils::WideStringToString(
windows::FilePath::GetDownloadPath(parent, file));
}
std::string ImplementationPlatform::GetDownloadPath(
const std::string& file_name) {
std::wstring fake_parent_path;
auto file = windows::string_to_wstring(std::string(file_name));
auto file = windows::string_utils::StringToWideString(file_name);
return windows::wstring_to_string(
return windows::string_utils::WideStringToString(
windows::FilePath::GetDownloadPath(fake_parent_path, file));
}
@@ -229,8 +230,8 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
const std::string& file_path) {
std::string path(file_path);
auto folder_path =
windows::string_to_wstring(path.substr(0, path.find_last_of('/')));
auto folder_path = windows::string_utils::StringToWideString(
path.substr(0, path.find_last_of('/')));
// Verifies that a path is a valid directory.
// https://docs.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathisdirectoryw
if (!PathIsDirectoryW(folder_path.data())) {
@@ -0,0 +1,113 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/implementation/windows/string_utils.h"
#include <windows.h>
#include <string>
#include "internal/platform/logging.h"
namespace nearby::windows::string_utils {
// Converts std::string to wstring
std::wstring StringToWideString(std::string str) {
if (str.empty()) {
return L"";
}
// https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
int output_length =
MultiByteToWideChar(/*CodePage=*/CP_UTF8,
/*dwFlags=*/0,
/*lpMultiByteStr=*/str.c_str(),
/*cbMultiByte=*/static_cast<int>(str.length()),
/*lpWideCharStr=*/nullptr,
/*cchWideChar=*/0);
if (output_length == 0) {
return L"";
}
std::wstring output(output_length, L'\0');
int result = MultiByteToWideChar(
/*CodePage=*/CP_UTF8, /*dwFlags=*/0, /*lpMultiByteStr=*/str.c_str(),
/*cbMultiByte=*/static_cast<int>(str.length()),
/*lpWideCharStr=*/&output[0],
/*cchWideChar=*/output_length);
if (result == 0) {
LOG(INFO) << "Error converting String to Wstring. Error code: "
<< GetLastError();
return L"";
}
return output;
}
// Converts wstring to std::string
std::string WideStringToString(std::wstring wstr) {
if (wstr.empty()) {
return "";
}
std::string output;
size_t start = 0;
size_t index = 0;
// Iterate over the wstring buffer, chop it into wchar chunks and convert them
// one-by-one
do {
index = wstr.find(L'\0', start);
if (index == std::wstring::npos) index = wstr.length();
if (start <= wstr.length()) {
// https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
int size =
WideCharToMultiByte(/*CodePage=*/CP_UTF8,
/*dwFlags=*/WC_ERR_INVALID_CHARS,
/*lpWideCharStr=*/&wstr[start],
/*cchWideChar=*/static_cast<int>(index - start),
/*lpMultiByteStr=*/nullptr,
/*cbMultiByte=*/0,
/*lpDefaultChar=*/nullptr,
/*lpUsedDefaultChar=*/nullptr);
if (size == 0) {
return "";
}
std::string converted_chunk = std::string(size, '\0');
int result = WideCharToMultiByte(
/*CodePage=*/CP_UTF8, /*dwFlags=*/WC_ERR_INVALID_CHARS,
/*lpWideCharStr=*/&wstr[start],
/*cchWideChar=*/static_cast<int>(index - start),
/*lpMultiByteStr=*/&converted_chunk[0],
/*cbMultiByte=*/static_cast<int>(converted_chunk.size()),
/*lpDefaultChar=*/nullptr,
/*lpUsedDefaultChar=*/nullptr);
if (result == 0) {
LOG(INFO) << "Error converting Wstring to String. Error code: "
<< GetLastError();
return "";
}
output.append(converted_chunk);
// Append '\0' to handle the case of {wstring \0 wstring \0 wstring} ->
// {string \0 string \0 string}
if (index < wstr.length()) {
LOG(INFO) << "Appending a null byte to string";
output.append(1, '\0');
}
}
start = index + 1;
} while (index != std::wstring::npos && start < wstr.length());
return output;
}
} // namespace nearby::windows::string_utils
@@ -0,0 +1,29 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
#include <string>
namespace nearby::windows::string_utils {
// Converts UTF-8 encoded string to wstring
std::wstring StringToWideString(std::string str);
// Converts wstring to UTF-8 encoded string
std::string WideStringToString(std::wstring wstr);
} // namespace nearby::windows::string_utils
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_STRING_UTILS_H_
@@ -0,0 +1,190 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/implementation/windows/string_utils.h"
#include <sstream>
#include <string>
#include "gtest/gtest.h"
namespace nearby::windows::string_utils {
const wchar_t* const kConvertRoundtripCasesWide[] = {
L"Hello World!",
L"Quick Share for Windows",
// "附近分享 蓝牙 无线传送 »"
L"\x9644\x8fd1\x5206\x4eab\x0020\x84dd\x7259\x0020\x65e0\x7ebf\x4f20\x9001"
L"\x0020\x00bb",
// "近隣のシェア"
L"\x8fd1\x96a3\x306e\x30b7\x30a7\x30a2",
// "주변 공유"
L"\xc8fc\xbcc0\x0020\xacf5\xc720",
// "आस-पास साझा करें"
L"\x0906\x0938\x002d\x092a\x093e\x0938\x0020\x0938\x093e\x091d\x093e\x0020"
L"\x0915\x0930\x0947\x0902",
// "அருகிலுள்ள பகிர்வு"
L"\x0b85\x0bb0\x0bc1\x0b95\x0bbf\x0bb2\x0bc1\x0bb3\x0bcd\x0bb3\x0020\x0baa"
L"\x0b95\x0bbf\x0bb0\x0bcd\x0bb5\x0bc1",
};
const wchar_t* const kWideStringWithNull[] = {
L"A" L"\0" L"B" L"\0" L"C",
L"Hello World!"
L"\0"
L"Quick Share for Windows"
L"\0"
// "附近分享 蓝牙 无线传送 »"
L"\x9644\x8fd1\x5206\x4eab\x0020\x84dd\x7259\x0020\x65e0\x7ebf\x4f20\x9001"
L"\x0020\x00bb",
};
const wchar_t* const kSymbolsWideString[] = {
// ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 :
// A,B,C,D,E)
L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44",
};
const char* const kConvertRoundtripCases[] = {
"Hello World!",
"Quick Share for Windows",
"附近分享 蓝牙 无线传送 »",
"近隣のシェア",
"주변 공유",
"आस-पास साझा करें",
"அருகிலுள்ள பகிர்வு",
};
const char* const kStringWithNull[] = {
"A" "\0" "B" "\0" "C",
"Hello World!"
"\0"
"Quick Share for Windows"
"\0"
"附近分享 蓝牙 无线传送 »",
};
const char* const kStringWithoutNull[] = {
"ABC",
"Hello World!"
"Quick Share for Windows"
"附近分享 蓝牙 无线传送 »",
};
const char* const kIllegalString[] = {
"™©pj·žÅ", // base64 decoded string of "malware.exe"
};
TEST(StringUtilsTests, ConvertWideStringToString) {
int count = sizeof(kConvertRoundtripCasesWide) /
sizeof(kConvertRoundtripCasesWide[0]);
for (int i = 0; i < count; ++i) {
std::ostringstream utf8;
utf8 << WideStringToString(kConvertRoundtripCasesWide[i]);
EXPECT_EQ(utf8.str(), kConvertRoundtripCases[i]);
}
count = sizeof(kWideStringWithNull) /
sizeof(kWideStringWithNull[0]);
for (int i = 0; i < count; ++i) {
std::ostringstream utf8;
utf8 << WideStringToString(kWideStringWithNull[i]);
EXPECT_EQ(utf8.str(), kStringWithNull[i]);
EXPECT_NE(utf8.str(), kStringWithoutNull[i]);
}
}
TEST(StringUtilsTests, ConvertWideStringToStringRoundTrip) {
// we round-trip all the wide strings through UTF-8 to make sure everything
// agrees on the conversion. This uses the stream operators to test them
// simultaneously.
for (auto* i : kConvertRoundtripCasesWide) {
std::ostringstream utf8;
utf8 << WideStringToString(i);
std::wostringstream wide;
wide << StringToWideString(utf8.str());
EXPECT_EQ(i, wide.str());
}
for (auto* i : kSymbolsWideString) {
std::ostringstream utf8;
utf8 << WideStringToString(i);
std::wostringstream wide;
wide << StringToWideString(utf8.str());
EXPECT_EQ(i, wide.str());
}
for (auto* i : kWideStringWithNull) {
std::ostringstream utf8;
utf8 << WideStringToString(i);
std::wostringstream wide;
wide << StringToWideString(utf8.str());
EXPECT_EQ(i, wide.str());
}
}
TEST(StringUtilsTests, ConvertStringToWideString) {
int count = sizeof(kConvertRoundtripCasesWide) /
sizeof(kConvertRoundtripCasesWide[0]);
for (int i = 0; i < count; ++i) {
std::wostringstream wide;
wide << StringToWideString(kConvertRoundtripCases[i]);
EXPECT_EQ(wide.str(), kConvertRoundtripCasesWide[i]);
}
}
TEST(StringUtilsTests, ConvertStringToWideStringRoundTrip) {
// we round-trip all the wide strings through UTF-8 to make sure everything
// agrees on the conversion. This uses the stream operators to test them
// simultaneously.
for (auto* i : kConvertRoundtripCases) {
std::wostringstream wide;
wide << StringToWideString(i);
std::ostringstream utf8;
utf8 << WideStringToString(wide.str());
EXPECT_EQ(i, utf8.str());
}
for (auto* i : kIllegalString) {
std::wostringstream wide;
wide << StringToWideString(i);
std::ostringstream utf8;
utf8 << WideStringToString(wide.str());
EXPECT_EQ(i, utf8.str());
}
for (auto* i : kStringWithNull) {
std::wostringstream wide;
wide << StringToWideString(i);
std::ostringstream utf8;
utf8 << WideStringToString(wide.str());
EXPECT_EQ(i, utf8.str());
}
}
TEST(StringUtilsTests, ConvertEmptyStringAndWideString) {
// An empty std::wstring should be converted to an empty std::string,
// and vice versa.
std::wstring wide_empty;
std::string empty;
EXPECT_EQ(empty, WideStringToString(wide_empty));
EXPECT_EQ(wide_empty, StringToWideString(empty));
}
} // namespace nearby::windows::string_utils
@@ -1,4 +1,4 @@
// Copyright 2020 Google LLC
// Copyright 2020-2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
#include "internal/platform/bluetooth_utils.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/crypto.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/logging.h"
#include "internal/platform/uuid.h"
#include "winrt/Windows.Foundation.Collections.h"
@@ -106,16 +107,6 @@ std::string ipaddr_dotdecimal_to_4bytes_string(std::string ipv4_s) {
return std::string(ipv4_b, 4);
}
std::wstring string_to_wstring(std::string str) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(str);
}
std::string wstring_to_string(std::wstring wstr) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(wstr);
}
std::vector<std::string> GetIpv4Addresses() {
std::vector<std::string> result;
std::vector<std::string> wifi_addresses;
@@ -298,7 +289,8 @@ std::string InspectableReader::ReadString(IInspectable inspectable) {
throw std::invalid_argument("not string data type.");
}
return wstring_to_string(property_value.GetString().c_str());
return nearby::windows::string_utils::WideStringToString(
property_value.GetString().c_str());
}
std::vector<std::string> InspectableReader::ReadStringArray(
@@ -39,8 +39,6 @@ std::string ipaddr_4bytes_to_dotdecimal_string(absl::string_view ipaddr_4bytes);
std::string ipaddr_dotdecimal_to_4bytes_string(std::string ipv4_s);
// Helpers to windows platform
std::wstring string_to_wstring(std::string str);
std::string wstring_to_string(std::wstring wstr);
ByteArray Sha256(absl::string_view input, size_t size);
// Reads the IPv4 addresses
@@ -41,6 +41,7 @@
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/exception.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/windows/string_utils.h"
#include "internal/platform/implementation/windows/utils.h"
#include "internal/platform/logging.h"
#include "internal/platform/nsd_service_info.h"
@@ -120,7 +121,7 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
LOG(INFO) << "mDNS instance name is " << instance_name;
dnssd_service_instance_ = DnssdServiceInstance{
string_to_wstring(instance_name),
string_utils::StringToWideString(instance_name),
nullptr, // let windows use default computer's local name
(uint16)nsd_service_info.GetPort()};
@@ -131,8 +132,8 @@ bool WifiLanMedium::StartAdvertising(const NsdServiceInfo& nsd_service_info) {
nsd_service_info.GetTxtRecords();
auto it = text_records.begin();
while (it != text_records.end()) {
text_attributes.Insert(string_to_wstring(it->first),
string_to_wstring(it->second));
text_attributes.Insert(string_utils::StringToWideString(it->first),
string_utils::StringToWideString(it->second));
it++;
}
@@ -205,8 +206,8 @@ bool WifiLanMedium::StopAdvertising(const NsdServiceInfo& nsd_service_info) {
kMdnsInstanceNameFormat.data(), nsd_service_info.GetServiceName(),
nsd_service_info.GetServiceType());
int port = nsd_service_info.GetPort();
dns_service_instance_name_ =
std::make_unique<std::wstring>(string_to_wstring(instance_name));
dns_service_instance_name_ = std::make_unique<std::wstring>(
string_utils::StringToWideString(instance_name));
dns_service_instance_.pszInstanceName =
(LPWSTR)dns_service_instance_name_->c_str();
@@ -278,7 +279,7 @@ bool WifiLanMedium::StartDiscovery(const std::string& service_type,
L"System.Devices.Dnssd.TextAttributes"};
device_watcher_ = DeviceInformation::CreateWatcher(
string_to_wstring(selector), requestedProperties,
string_utils::StringToWideString(selector), requestedProperties,
DeviceInformationKind::AssociationEndpointService);
device_watcher_added_event_token =
@@ -351,7 +352,8 @@ std::unique_ptr<api::WifiLanSocket> WifiLanMedium::ConnectToService(
std::unique_ptr<CancellationFlagListener> connection_cancellation_listener =
nullptr;
HostName host_name{string_to_wstring(std::string(ipv4_address))};
HostName host_name{
string_utils::StringToWideString(std::string(ipv4_address))};
winrt::hstring service_name{winrt::to_hstring(port)};
StreamSocket socket{};