Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions src/common/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#ifdef WIN32
#include <cassert>
#include <codecvt>
#include <compat/compat.h>
#include <windows.h>
#else
Expand Down Expand Up @@ -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<std::codecvt_utf8_utf16<wchar_t>,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);
Expand Down
5 changes: 0 additions & 5 deletions src/leveldb/util/env_windows.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/util/exec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <util/exec.h>

#include <util/fs.h>
#include <util/string.h>
#include <util/subprocess.h>

#include <string>
Expand All @@ -24,16 +25,16 @@ int ExecVp(const char* file, char* const argv[])
return execvp(file, argv);
#else
std::vector<std::wstring> escaped_args;
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> 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<const wchar_t*> 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
}

Expand Down
38 changes: 38 additions & 0 deletions src/util/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

#include <util/string.h>

#ifdef WIN32
#include <util/syserror.h>

#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

#include <limits>
#include <stdexcept>
#endif

#include <regex>
#include <string>

Expand All @@ -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<size_t>(std::numeric_limits<int>::max())) {
throw std::runtime_error("UTF-8 string is too long to convert");
}

const int src_size{static_cast<int>(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
4 changes: 4 additions & 0 deletions src/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ template <typename T1, size_t PREFIX_LEN>
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
14 changes: 8 additions & 6 deletions src/util/subprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Documentation for C++ subprocessing library.
#define BITCOIN_UTIL_SUBPROCESS_H

#include <util/syserror.h>
#include <util/string.h>

#include <algorithm>
#include <cassert>
Expand All @@ -59,10 +60,6 @@ Documentation for C++ subprocessing library.
#define __USING_WINDOWS__
#endif

#ifdef __USING_WINDOWS__
#include <codecvt>
#endif

extern "C" {
#ifdef __USING_WINDOWS__
#include <windows.h>
Expand Down Expand Up @@ -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:
Expand All @@ -759,6 +757,7 @@ class Child
Popen* parent_ = nullptr;
int err_wr_pipe_ = -1;
};
#endif // !__USING_WINDOWS__

// Fwd Decl.
class Streams;
Expand Down Expand Up @@ -932,7 +931,9 @@ class Popen
{
public:
friend struct detail::ArgumentDeducer;
#ifndef __USING_WINDOWS__
friend class detail::Child;
#endif

template <typename... Args>
Popen(const std::string& cmd_args, Args&& ...args):
Expand Down Expand Up @@ -1035,7 +1036,9 @@ class Popen
std::vector<char*> cargv_;

// Pid of the child process
#ifndef __USING_WINDOWS__
int child_pid_ = -1;
#endif

int retcode_ = -1;
};
Expand Down Expand Up @@ -1102,7 +1105,6 @@ inline void Popen::execute_process() noexcept(false)
}
this->exe_name_ = vargs_[0];

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring argument;
std::wstring command_line;
bool first_arg = true;
Expand All @@ -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);
}

Expand Down
Loading