diff --git a/src/common/system.cpp b/src/common/system.cpp index 72e9de100be6..2c302378c151 100644 --- a/src/common/system.cpp +++ b/src/common/system.cpp @@ -13,7 +13,6 @@ #ifdef WIN32 #include -#include #include #include #else @@ -56,7 +55,8 @@ void runCommand(const std::string& strCommand) #ifndef WIN32 int nErr = ::system(strCommand.c_str()); #else - int nErr = ::_wsystem(std::wstring_convert,wchar_t>().from_bytes(strCommand).c_str()); + const std::wstring wide_command{util::Utf8ToWide(strCommand)}; + int nErr = ::_wsystem(wide_command.c_str()); #endif if (nErr) { LogWarning("runCommand error: system(%s) returned %d", strCommand, nErr); diff --git a/src/leveldb/util/env_windows.cc b/src/leveldb/util/env_windows.cc index 8897e2aa26b9..e33f83c813b5 100644 --- a/src/leveldb/util/env_windows.cc +++ b/src/leveldb/util/env_windows.cc @@ -81,11 +81,6 @@ class ScopedHandle { ScopedHandle& operator=(const ScopedHandle&) = delete; - ScopedHandle& operator=(ScopedHandle&& rhs) noexcept { - if (this != &rhs) handle_ = rhs.Release(); - return *this; - } - bool Close() { if (!is_valid()) { return true; diff --git a/src/util/exec.cpp b/src/util/exec.cpp index 6b1406134268..af293d828096 100644 --- a/src/util/exec.cpp +++ b/src/util/exec.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -24,16 +25,16 @@ int ExecVp(const char* file, char* const argv[]) return execvp(file, argv); #else std::vector escaped_args; - std::wstring_convert> converter; for (char* const* arg_ptr{argv}; *arg_ptr; ++arg_ptr) { - subprocess::util::quote_argument(converter.from_bytes(*arg_ptr), escaped_args.emplace_back(), false); + subprocess::util::quote_argument(util::Utf8ToWide(*arg_ptr), escaped_args.emplace_back(), false); } std::vector new_argv; new_argv.reserve(escaped_args.size() + 1); for (const auto& s : escaped_args) new_argv.push_back(s.c_str()); new_argv.push_back(nullptr); - return _wexecvp(converter.from_bytes(file).c_str(), new_argv.data()); + const std::wstring wide_file{util::Utf8ToWide(file)}; + return _wexecvp(wide_file.c_str(), new_argv.data()); #endif } diff --git a/src/util/string.cpp b/src/util/string.cpp index 507d9d317182..56cd78871256 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -4,6 +4,18 @@ #include +#ifdef WIN32 +#include + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include + +#include +#include +#endif + #include #include @@ -13,4 +25,30 @@ void ReplaceAll(std::string& in_out, const std::string& search, const std::strin if (search.empty()) return; in_out = std::regex_replace(in_out, std::regex(search), substitute); } + +#ifdef WIN32 +std::wstring Utf8ToWide(std::string_view utf8) +{ + if (utf8.empty()) return {}; + if (utf8.size() > static_cast(std::numeric_limits::max())) { + throw std::runtime_error("UTF-8 string is too long to convert"); + } + + const int src_size{static_cast(utf8.size())}; + const int dst_size{MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.data(), src_size, nullptr, 0)}; + if (dst_size == 0) { + const auto err{GetLastError()}; + throw std::runtime_error("MultiByteToWideChar failed: " + Win32ErrorString(err)); + } + + std::wstring wide(dst_size, 0); + const int result{MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.data(), src_size, wide.data(), dst_size)}; + if (result != dst_size) { + const auto err{GetLastError()}; + throw std::runtime_error("MultiByteToWideChar failed: " + Win32ErrorString(err)); + } + + return wide; +} +#endif } // namespace util diff --git a/src/util/string.h b/src/util/string.h index 330c2a2a61e0..d12e4c616472 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -260,6 +260,10 @@ template return obj.size() >= PREFIX_LEN && std::equal(std::begin(prefix), std::end(prefix), std::begin(obj)); } + +#ifdef WIN32 +std::wstring Utf8ToWide(std::string_view utf8); +#endif } // namespace util #endif // BITCOIN_UTIL_STRING_H diff --git a/src/util/subprocess.h b/src/util/subprocess.h index e90c165205ee..4ec0a09265f6 100644 --- a/src/util/subprocess.h +++ b/src/util/subprocess.h @@ -37,6 +37,7 @@ Documentation for C++ subprocessing library. #define BITCOIN_UTIL_SUBPROCESS_H #include +#include #include #include @@ -59,10 +60,6 @@ Documentation for C++ subprocessing library. #define __USING_WINDOWS__ #endif -#ifdef __USING_WINDOWS__ - #include -#endif - extern "C" { #ifdef __USING_WINDOWS__ #include @@ -743,6 +740,7 @@ struct ArgumentDeducer * This takes care of all the fork-exec logic * in the execute_child API. */ +#ifndef __USING_WINDOWS__ class Child { public: @@ -759,6 +757,7 @@ class Child Popen* parent_ = nullptr; int err_wr_pipe_ = -1; }; +#endif // !__USING_WINDOWS__ // Fwd Decl. class Streams; @@ -932,7 +931,9 @@ class Popen { public: friend struct detail::ArgumentDeducer; +#ifndef __USING_WINDOWS__ friend class detail::Child; +#endif template Popen(const std::string& cmd_args, Args&& ...args): @@ -1035,7 +1036,9 @@ class Popen std::vector cargv_; // Pid of the child process +#ifndef __USING_WINDOWS__ int child_pid_ = -1; +#endif int retcode_ = -1; }; @@ -1102,7 +1105,6 @@ inline void Popen::execute_process() noexcept(false) } this->exe_name_ = vargs_[0]; - std::wstring_convert> converter; std::wstring argument; std::wstring command_line; bool first_arg = true; @@ -1113,7 +1115,7 @@ inline void Popen::execute_process() noexcept(false) } else { first_arg = false; } - argument = converter.from_bytes(arg); + argument = ::util::Utf8ToWide(arg); util::quote_argument(argument, command_line, false); }