4545#include " src/logging.h"
4646#include " src/platform/common.h"
4747#include " src/utility.h"
48+ #include " utf_utils.h"
4849
4950// UDP_SEND_MSG_SIZE was added in the Windows 10 20H1 SDK
5051#ifndef UDP_SEND_MSG_SIZE
@@ -314,7 +315,7 @@ namespace platf {
314315 // Parse the environment block and populate env
315316 for (auto c = (PWCHAR) env_block; *c != UNICODE_NULL; c += wcslen (c) + 1 ) {
316317 // Environment variable entries end with a null-terminator, so std::wstring() will get an entire entry.
317- std::string env_tuple = to_utf8 (std::wstring {c});
318+ std::string env_tuple = utf_utils:: to_utf8 (std::wstring {c});
318319 std::string env_name = env_tuple.substr (0 , env_tuple.find (' =' ));
319320 std::string env_val = env_tuple.substr (env_tuple.find (' =' ) + 1 );
320321
@@ -384,7 +385,7 @@ namespace platf {
384385 for (const auto &entry : env) {
385386 auto name = entry.get_name ();
386387 auto value = entry.to_string ();
387- size += from_utf8 (name).length () + 1 /* L'=' */ + from_utf8 (value).length () + 1 /* L'\0' */ ;
388+ size += utf_utils:: from_utf8 (name).length () + 1 /* L'=' */ + utf_utils:: from_utf8 (value).length () + 1 /* L'\0' */ ;
388389 }
389390
390391 size += 1 /* L'\0' */ ;
@@ -396,9 +397,9 @@ namespace platf {
396397 auto value = entry.to_string ();
397398
398399 // Construct the NAME=VAL\0 string
399- append_string_to_environment_block (env_block, offset, from_utf8 (name));
400+ append_string_to_environment_block (env_block, offset, utf_utils:: from_utf8 (name));
400401 env_block[offset++] = L' =' ;
401- append_string_to_environment_block (env_block, offset, from_utf8 (value));
402+ append_string_to_environment_block (env_block, offset, utf_utils:: from_utf8 (value));
402403 env_block[offset++] = L' \0 ' ;
403404 }
404405
@@ -676,14 +677,14 @@ namespace platf {
676677 * @return A command string suitable for use by CreateProcess().
677678 */
678679 std::wstring resolve_command_string (const std::string &raw_cmd, const std::wstring &working_dir, HANDLE token, DWORD &creation_flags) {
679- std::wstring raw_cmd_w = from_utf8 (raw_cmd);
680+ std::wstring raw_cmd_w = utf_utils:: from_utf8 (raw_cmd);
680681
681682 // First, convert the given command into parts so we can get the executable/file/URL without parameters
682683 auto raw_cmd_parts = boost::program_options::split_winmain (raw_cmd_w);
683684 if (raw_cmd_parts.empty ()) {
684685 // This is highly unexpected, but we'll just return the raw string and hope for the best.
685686 BOOST_LOG (warning) << " Failed to split command string: " sv << raw_cmd;
686- return from_utf8 (raw_cmd);
687+ return utf_utils:: from_utf8 (raw_cmd);
687688 }
688689
689690 auto raw_target = raw_cmd_parts.at (0 );
@@ -697,7 +698,7 @@ namespace platf {
697698 res = UrlGetPartW (raw_target.c_str (), scheme.data (), &out_len, URL_PART_SCHEME, 0 );
698699 if (res != S_OK) {
699700 BOOST_LOG (warning) << " Failed to extract URL scheme from URL: " sv << raw_target << " [" sv << util::hex (res).to_string_view () << ' ]' ;
700- return from_utf8 (raw_cmd);
701+ return utf_utils:: from_utf8 (raw_cmd);
701702 }
702703
703704 // If the target is a URL, the class is found using the URL scheme (prior to and not including the ':')
@@ -708,13 +709,13 @@ namespace platf {
708709 if (extension == nullptr || *extension == 0 ) {
709710 // If the file has no extension, assume it's a command and allow CreateProcess()
710711 // to try to find it via PATH
711- return from_utf8 (raw_cmd);
712+ return utf_utils:: from_utf8 (raw_cmd);
712713 } else if (boost::iequals (extension, L" .exe" )) {
713714 // If the file has an .exe extension, we will bypass the resolution here and
714715 // directly pass the unmodified command string to CreateProcess(). The argument
715716 // escaping rules are subtly different between CreateProcess() and ShellExecute(),
716717 // and we want to preserve backwards compatibility with older configs.
717- return from_utf8 (raw_cmd);
718+ return utf_utils:: from_utf8 (raw_cmd);
718719 }
719720
720721 // For regular files, the class is found using the file extension (including the dot)
@@ -731,7 +732,7 @@ namespace platf {
731732
732733 // Override HKEY_CLASSES_ROOT and HKEY_CURRENT_USER to ensure we query the correct class info
733734 if (!override_per_user_predefined_keys (token)) {
734- return from_utf8 (raw_cmd);
735+ return utf_utils:: from_utf8 (raw_cmd);
735736 }
736737
737738 // Find the command string for the specified class
@@ -762,7 +763,7 @@ namespace platf {
762763
763764 if (res != S_OK) {
764765 BOOST_LOG (warning) << " Failed to query command string for raw command: " sv << raw_cmd << " [" sv << util::hex (res).to_string_view () << ' ]' ;
765- return from_utf8 (raw_cmd);
766+ return utf_utils:: from_utf8 (raw_cmd);
766767 }
767768
768769 // Finally, construct the real command string that will be passed into CreateProcess().
@@ -896,7 +897,7 @@ namespace platf {
896897 * @return A `bp::child` object representing the new process, or an empty `bp::child` object if the launch fails.
897898 */
898899 bp::child run_command (bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, const bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) {
899- std::wstring start_dir = from_utf8 (working_dir.string ());
900+ std::wstring start_dir = utf_utils:: from_utf8 (working_dir.string ());
900901 HANDLE job = group ? group->native_handle () : nullptr ;
901902 STARTUPINFOEXW startup_info = create_startup_info (file, job ? &job : nullptr , ec);
902903 PROCESS_INFORMATION process_info;
@@ -1687,65 +1688,13 @@ namespace platf {
16871688 return {};
16881689 }
16891690
1690- std::wstring from_utf8 (const std::string &string) {
1691- // No conversion needed if the string is empty
1692- if (string.empty ()) {
1693- return {};
1694- }
1695-
1696- // Get the output size required to store the string
1697- auto output_size = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, string.data (), string.size (), nullptr , 0 );
1698- if (output_size == 0 ) {
1699- auto winerr = GetLastError ();
1700- BOOST_LOG (error) << " Failed to get UTF-16 buffer size: " sv << winerr;
1701- return {};
1702- }
1703-
1704- // Perform the conversion
1705- std::wstring output (output_size, L' \0 ' );
1706- output_size = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, string.data (), string.size (), output.data (), output.size ());
1707- if (output_size == 0 ) {
1708- auto winerr = GetLastError ();
1709- BOOST_LOG (error) << " Failed to convert string to UTF-16: " sv << winerr;
1710- return {};
1711- }
1712-
1713- return output;
1714- }
1715-
1716- std::string to_utf8 (const std::wstring &string) {
1717- // No conversion needed if the string is empty
1718- if (string.empty ()) {
1719- return {};
1720- }
1721-
1722- // Get the output size required to store the string
1723- auto output_size = WideCharToMultiByte (CP_UTF8, WC_ERR_INVALID_CHARS, string.data (), string.size (), nullptr , 0 , nullptr , nullptr );
1724- if (output_size == 0 ) {
1725- auto winerr = GetLastError ();
1726- BOOST_LOG (error) << " Failed to get UTF-8 buffer size: " sv << winerr;
1727- return {};
1728- }
1729-
1730- // Perform the conversion
1731- std::string output (output_size, ' \0 ' );
1732- output_size = WideCharToMultiByte (CP_UTF8, WC_ERR_INVALID_CHARS, string.data (), string.size (), output.data (), output.size (), nullptr , nullptr );
1733- if (output_size == 0 ) {
1734- auto winerr = GetLastError ();
1735- BOOST_LOG (error) << " Failed to convert string to UTF-8: " sv << winerr;
1736- return {};
1737- }
1738-
1739- return output;
1740- }
1741-
17421691 std::string get_host_name () {
17431692 WCHAR hostname[256 ];
17441693 if (GetHostNameW (hostname, ARRAYSIZE (hostname)) == SOCKET_ERROR) {
17451694 BOOST_LOG (error) << " GetHostNameW() failed: " sv << WSAGetLastError ();
17461695 return " Sunshine" s;
17471696 }
1748- return to_utf8 (hostname);
1697+ return utf_utils:: to_utf8 (hostname);
17491698 }
17501699
17511700 class win32_high_precision_timer : public high_precision_timer {
0 commit comments