From 477c0a2cabbe59f9c9617a14c5d841be95dfe9c6 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Sun, 10 Feb 2019 12:53:03 +0100 Subject: [PATCH] Create process with wide chars on Windows Windows does not support UTF-8, so pushing a file with non-ASCII characters failed. Convert the UTF-8 command line to a wide characters string and call CreateProcessW(). Fixes --- app/src/str_util.c | 24 ++++++++++++++++++++++++ app/src/str_util.h | 6 ++++++ app/src/sys/win/command.c | 12 ++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/app/src/str_util.c b/app/src/str_util.c index f234346e..892883a6 100644 --- a/app/src/str_util.c +++ b/app/src/str_util.c @@ -3,6 +3,11 @@ #include #include +#ifdef _WIN32 +# include +# include +#endif + size_t xstrncpy(char *dest, const char *src, size_t n) { size_t i; for (i = 0; i < n - 1 && src[i] != '\0'; ++i) @@ -47,3 +52,22 @@ char *strquote(const char *src) { quoted[len + 2] = '\0'; return quoted; } + +#ifdef _WIN32 + +wchar_t *utf8_to_wide_char(const char *utf8) { + int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); + if (!len) { + return NULL; + } + + wchar_t *wide = malloc(len * sizeof(wchar_t)); + if (!wide) { + return NULL; + } + + MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, len); + return wide; +} + +#endif diff --git a/app/src/str_util.h b/app/src/str_util.h index 9433f768..6f4004f1 100644 --- a/app/src/str_util.h +++ b/app/src/str_util.h @@ -20,4 +20,10 @@ size_t xstrjoin(char *dst, const char *const tokens[], char sep, size_t n); // returns the new allocated string, to be freed by the caller char *strquote(const char *src); +#ifdef _WIN32 +// convert a UTF-8 string to a wchar_t string +// returns the new allocated string, to be freed by the caller +wchar_t *utf8_to_wide_char(const char *utf8); +#endif + #endif diff --git a/app/src/sys/win/command.c b/app/src/sys/win/command.c index d0f189f7..5e9876cd 100644 --- a/app/src/sys/win/command.c +++ b/app/src/sys/win/command.c @@ -18,7 +18,7 @@ static int build_cmd(char *cmd, size_t len, const char *const argv[]) { } enum process_result cmd_execute(const char *path, const char *const argv[], HANDLE *handle) { - STARTUPINFO si; + STARTUPINFOW si; PROCESS_INFORMATION pi; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); @@ -29,12 +29,19 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND return PROCESS_ERROR_GENERIC; } + wchar_t *wide = utf8_to_wide_char(cmd); + if (!wide) { + LOGC("Cannot allocate wide char string"); + return PROCESS_ERROR_GENERIC; + } + #ifdef WINDOWS_NOCONSOLE int flags = CREATE_NO_WINDOW; #else int flags = 0; #endif - if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) { + if (!CreateProcessW(NULL, wide, NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi)) { + free(wide); *handle = NULL; if (GetLastError() == ERROR_FILE_NOT_FOUND) { return PROCESS_ERROR_MISSING_BINARY; @@ -42,6 +49,7 @@ enum process_result cmd_execute(const char *path, const char *const argv[], HAND return PROCESS_ERROR_GENERIC; } + free(wide); *handle = pi.hProcess; return PROCESS_SUCCESS; }