From d7e7bae79e7466e03074641a589515b64296a545 Mon Sep 17 00:00:00 2001 From: GustavoLCR Date: Fri, 27 Aug 2021 04:23:26 -0300 Subject: [PATCH] Use wide version of Windows APIs (#1531) * Use wide version of Windows APIs in subprocess functions * Use `wmain` on Windows to get UTF16 arguments * Use wide version of APIs in `rz_cons` * Always try to set console codepage to UTF8 Co-authored-by: Riccardo Schirone --- binrz/blob/main.c | 8 ++-- binrz/rizin/rizin.c | 13 +++++-- binrz/rz-agent/rz-agent.c | 7 +++- binrz/rz-asm/rz-asm.c | 7 +++- binrz/rz-ax/rz-ax.c | 7 +++- binrz/rz-bin/rz-bin.c | 7 +++- binrz/rz-diff/rz-diff.c | 7 +++- binrz/rz-find/rz-find.c | 7 +++- binrz/rz-gg/rz-gg.c | 7 +++- binrz/rz-hash/rz-hash.c | 7 +++- binrz/rz-run/rz-run.c | 7 +++- binrz/rz-sign/rz-sign.c | 7 +++- binrz/rz-test/rz-test.c | 10 ++++- librz/cons/cons.c | 58 ++++++++++++++-------------- librz/cons/dietline.c | 10 ++--- librz/cons/input.c | 12 ++++-- librz/include/rz_cons.h | 2 + librz/include/rz_main.h | 12 ++++++ librz/include/rz_util/rz_sys.h | 2 + librz/util/subprocess.c | 69 ++++++++++++++++++++++------------ librz/util/w32-sys.c | 20 ++++++++++ 21 files changed, 193 insertions(+), 93 deletions(-) diff --git a/binrz/blob/main.c b/binrz/blob/main.c index 9068b63969..85e8a23706 100644 --- a/binrz/blob/main.c +++ b/binrz/blob/main.c @@ -4,13 +4,15 @@ #include #include -int main(int argc, char **argv) { +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); int rc = 1; - const char *prog_name = rz_file_basename(argv[0]); + const char *prog_name = rz_file_basename(utf8_argv[0]); RzMain *m = rz_main_new(prog_name); if (m) { - rc = rz_main_run(m, argc, argv); + rc = rz_main_run(m, argc, (const char **)utf8_argv); rz_main_free(m); } + UTF8_ARGV_FREE(argc, utf8_argv); return rc; } diff --git a/binrz/rizin/rizin.c b/binrz/rizin/rizin.c index 6c449db6ba..78c80f071a 100644 --- a/binrz/rizin/rizin.c +++ b/binrz/rizin/rizin.c @@ -48,9 +48,14 @@ static int rz_main_rzpipe(int argc, const char **argv) { return rc; } -int main(int argc, const char **argv) { - if (argc > 0 && strstr(argv[0], "rzp")) { - return rz_main_rzpipe(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret; + if (argc > 0 && strstr(utf8_argv[0], "rzp")) { + ret = rz_main_rzpipe(argc, (const char **)utf8_argv); + } else { + ret = rz_main_rizin(argc, (const char **)utf8_argv); } - return rz_main_rizin(argc, argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-agent/rz-agent.c b/binrz/rz-agent/rz-agent.c index 7ecc7c9cf5..80ac475b04 100644 --- a/binrz/rz-agent/rz-agent.c +++ b/binrz/rz-agent/rz-agent.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_agent(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_agent(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-asm/rz-asm.c b/binrz/rz-asm/rz-asm.c index 3debb49e52..63eb7a538b 100644 --- a/binrz/rz-asm/rz-asm.c +++ b/binrz/rz-asm/rz-asm.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char *argv[]) { - return rz_main_rz_asm(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_asm(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-ax/rz-ax.c b/binrz/rz-ax/rz-ax.c index 38080996ed..8801fd8253 100644 --- a/binrz/rz-ax/rz-ax.c +++ b/binrz/rz-ax/rz-ax.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char *argv[]) { - return rz_main_rz_ax(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_ax(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-bin/rz-bin.c b/binrz/rz-bin/rz-bin.c index 74cd486369..a7ee295907 100644 --- a/binrz/rz-bin/rz-bin.c +++ b/binrz/rz-bin/rz-bin.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_bin(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_bin(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-diff/rz-diff.c b/binrz/rz-diff/rz-diff.c index 10f8a2a2cb..839fdc2b42 100644 --- a/binrz/rz-diff/rz-diff.c +++ b/binrz/rz-diff/rz-diff.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char *argv[]) { - return rz_main_rz_diff(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_diff(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-find/rz-find.c b/binrz/rz-find/rz-find.c index 678e1bad50..5b6e3b1ed2 100644 --- a/binrz/rz-find/rz-find.c +++ b/binrz/rz-find/rz-find.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_find(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_find(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-gg/rz-gg.c b/binrz/rz-gg/rz-gg.c index 100309ec11..6fefa739cb 100644 --- a/binrz/rz-gg/rz-gg.c +++ b/binrz/rz-gg/rz-gg.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_gg(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_gg(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-hash/rz-hash.c b/binrz/rz-hash/rz-hash.c index 6256b4f3ba..22b9a754f4 100644 --- a/binrz/rz-hash/rz-hash.c +++ b/binrz/rz-hash/rz-hash.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_hash(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_hash(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-run/rz-run.c b/binrz/rz-run/rz-run.c index 31d65a51d6..2cbda0cf33 100644 --- a/binrz/rz-run/rz-run.c +++ b/binrz/rz-run/rz-run.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_run(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_run(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-sign/rz-sign.c b/binrz/rz-sign/rz-sign.c index 23eb0fe295..509b490f1c 100644 --- a/binrz/rz-sign/rz-sign.c +++ b/binrz/rz-sign/rz-sign.c @@ -3,6 +3,9 @@ #include -int main(int argc, const char **argv) { - return rz_main_rz_sign(argc, argv); +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_main_rz_sign(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; } diff --git a/binrz/rz-test/rz-test.c b/binrz/rz-test/rz-test.c index e581259127..2a7385c22c 100644 --- a/binrz/rz-test/rz-test.c +++ b/binrz/rz-test/rz-test.c @@ -4,6 +4,7 @@ #include "rz_test.h" #include #include +#include #define Color_INSERT Color_BGREEN #define Color_DELETE Color_BRED @@ -169,7 +170,7 @@ static bool rz_test_chdir_fromtest(const char *test_path) { return found; } -int main(int argc, char **argv) { +int rz_test_main(int argc, const char **argv) { int workers_count = WORKERS_DEFAULT; bool verbose = false; bool nothing = false; @@ -1082,3 +1083,10 @@ static void interact_commands(RzTestResultInfo *result, RzPVector *fixup_results free(name); free(newcmds); } + +int MAIN_NAME(int argc, const ARGV_TYPE **argv) { + char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv); + int ret = rz_test_main(argc, (const char **)utf8_argv); + FREE_UTF8_ARGV(argc, utf8_argv); + return ret; +} diff --git a/librz/cons/cons.c b/librz/cons/cons.c index a5f4dbcd40..f1bdf229aa 100644 --- a/librz/cons/cons.c +++ b/librz/cons/cons.c @@ -528,6 +528,30 @@ RZ_API bool rz_cons_enable_mouse(const bool enable) { #endif } +#if __WINDOWS__ +static void set_console_codepage_to_utf8(void) { + if (IsValidCodePage(CP_UTF8)) { + if (!SetConsoleOutputCP(CP_UTF8)) { + rz_sys_perror("SetConsoleCP"); + } + if (!SetConsoleCP(CP_UTF8)) { + rz_sys_perror("SetConsoleCP"); + } + } else { + RZ_LOG_INFO("UTF-8 Codepage not installed.\n"); + } +} + +static void restore_console_codepage(void) { + if (!SetConsoleCP(I.old_cp)) { + rz_sys_perror("SetConsoleCP"); + } + if (!SetConsoleOutputCP(I.old_ocp)) { + rz_sys_perror("SetConsoleOutputCP"); + } +} +#endif + // Stub function that cb_main_output gets pointed to in util/log.c by rz_cons_new // This allows Cutter to set per-task logging redirection RZ_API RzCons *rz_cons_new(void) { @@ -563,8 +587,10 @@ RZ_API RzCons *rz_cons_new(void) { I.num = NULL; I.null = 0; #if __WINDOWS__ - I.old_cp = GetConsoleOutputCP(); + I.old_cp = GetConsoleCP(); + I.old_ocp = GetConsoleOutputCP(); I.vtmode = rz_cons_is_vtcompat(); + set_console_codepage_to_utf8(); #else I.vtmode = 2; #endif @@ -601,11 +627,7 @@ RZ_API RzCons *rz_cons_new(void) { RZ_API RzCons *rz_cons_free(void) { #if __WINDOWS__ rz_cons_enable_mouse(false); - if (I.old_cp) { - (void)SetConsoleOutputCP(I.old_cp); - // chcp doesn't pick up the code page switch for some reason - (void)rz_sys_cmdf("chcp %u > NUL", I.old_cp); - } + restore_console_codepage(); #endif I.refcnt--; if (I.refcnt != 0) { @@ -1600,30 +1622,6 @@ RZ_API void rz_cons_set_raw(bool is_raw) { RZ_API void rz_cons_set_utf8(bool b) { I.use_utf8 = b; -#if __WINDOWS__ - if (b) { - if (IsValidCodePage(CP_UTF8)) { - if (!SetConsoleOutputCP(CP_UTF8)) { - rz_sys_perror("rz_cons_set_utf8"); - } -#if UNICODE - UINT inCP = CP_UTF8; -#else - UINT inCP = GetACP(); -#endif - if (!SetConsoleCP(inCP)) { - rz_sys_perror("rz_cons_set_utf8"); - } - } else { - RZ_LOG_WARN("UTF-8 Codepage not installed.\n"); - } - } else { - UINT acp = GetACP(); - if (!SetConsoleCP(acp) || !SetConsoleOutputCP(acp)) { - rz_sys_perror("rz_cons_set_utf8"); - } - } -#endif } RZ_API void rz_cons_invert(int set, int color) { diff --git a/librz/cons/dietline.c b/librz/cons/dietline.c index b34a1c8d51..df00871a3d 100644 --- a/librz/cons/dietline.c +++ b/librz/cons/dietline.c @@ -243,7 +243,7 @@ do_it_again: if (rz_cons_singleton()->term_xterm) { ret = ReadFile(h, buf, 1, &out, NULL); } else { - ret = ReadConsoleInput(h, &irInBuf, 1, &out); + ret = ReadConsoleInputW(h, &irInBuf, 1, &out); } rz_cons_sleep_end(bed); if (ret < 1) { @@ -252,7 +252,7 @@ do_it_again: if (irInBuf.EventType == KEY_EVENT) { if (irInBuf.Event.KeyEvent.bKeyDown) { if (irInBuf.Event.KeyEvent.uChar.UnicodeChar) { - char *tmp = rz_sys_conv_win_to_utf8_l((PTCHAR)&irInBuf.Event.KeyEvent.uChar, 1); + char *tmp = rz_utf16_to_utf8_l(&irInBuf.Event.KeyEvent.uChar.UnicodeChar, 1); if (!tmp) { return 0; } @@ -1531,15 +1531,11 @@ RZ_API const char *rz_line_readline_cb(RzLineReadCallback cb, void *user) { HANDLE hClipBoard; PTCHAR clipText; if (OpenClipboard(NULL)) { -#if UNICODE hClipBoard = GetClipboardData(CF_UNICODETEXT); -#else - hClipBoard = GetClipboardData(CF_TEXT); -#endif if (hClipBoard) { clipText = GlobalLock(hClipBoard); if (clipText) { - char *txt = rz_sys_conv_win_to_utf8(clipText); + char *txt = rz_utf16_to_utf8(clipText); if (!txt) { RZ_LOG_ERROR("Failed to allocate memory\n"); break; diff --git a/librz/cons/input.c b/librz/cons/input.c index 337c53b290..d26de4bc9f 100644 --- a/librz/cons/input.c +++ b/librz/cons/input.c @@ -462,7 +462,7 @@ static int __cons_readchar_w32(ut32 usec) { return ch; } } else { - ret = ReadConsoleInput(h, &irInBuf, 1, &out); + ret = ReadConsoleInputW(h, &irInBuf, 1, &out); } rz_cons_sleep_end(bed); if (ret) { @@ -504,9 +504,15 @@ static int __cons_readchar_w32(ut32 usec) { if (irInBuf.EventType == KEY_EVENT) { if (irInBuf.Event.KeyEvent.bKeyDown) { - ch = irInBuf.Event.KeyEvent.uChar.AsciiChar; bCtrl = irInBuf.Event.KeyEvent.dwControlKeyState & 8; - if (irInBuf.Event.KeyEvent.uChar.AsciiChar == 0) { + if (irInBuf.Event.KeyEvent.uChar.UnicodeChar) { + char *tmp = rz_utf16_to_utf8_l(&irInBuf.Event.KeyEvent.uChar.UnicodeChar, 1); + if (tmp) { + int len = strlen(tmp); + memcpy(&ch, tmp, R_MIN(len, sizeof(ch))); + free(tmp); + } + } else { switch (irInBuf.Event.KeyEvent.wVirtualKeyCode) { case VK_DOWN: // key down case VK_RIGHT: // key right diff --git a/librz/include/rz_cons.h b/librz/include/rz_cons.h index 90c8dd7b4e..15e95212b4 100644 --- a/librz/include/rz_cons.h +++ b/librz/include/rz_cons.h @@ -17,6 +17,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -520,6 +521,7 @@ typedef struct rz_cons_t { #elif __WINDOWS__ DWORD term_raw, term_buf, term_xterm; UINT old_cp; + UINT old_ocp; #endif RNum *num; /* Pager (like more or less) to use if the output doesn't fit on the diff --git a/librz/include/rz_main.h b/librz/include/rz_main.h index ba2ad6f2c3..24889c55a3 100644 --- a/librz/include/rz_main.h +++ b/librz/include/rz_main.h @@ -15,6 +15,18 @@ typedef struct rz_main_t { // stdin/stdout } RzMain; +#if __WINDOWS__ +#define MAIN_NAME wmain +#define ARGV_TYPE wchar_t +#define ARGV_TYPE_TO_UTF8(argc, argv) rz_sys_utf8_argv_new(argc, argv) +#define FREE_UTF8_ARGV(argc, utf8_argv) rz_sys_utf8_argv_free(argc, utf8_argv) +#else +#define MAIN_NAME main +#define ARGV_TYPE char +#define ARGV_TYPE_TO_UTF8(argc, argv) (char **)argv +#define FREE_UTF8_ARGV(argc, utf8_argv) +#endif + typedef int (*RzMainCallback)(int argc, const char **argv); RZ_API RzMain *rz_main_new(const char *name); diff --git a/librz/include/rz_util/rz_sys.h b/librz/include/rz_util/rz_sys.h index a2b6b98e8e..1c8373ab50 100644 --- a/librz/include/rz_util/rz_sys.h +++ b/librz/include/rz_util/rz_sys.h @@ -126,6 +126,8 @@ RZ_API int rz_sys_cmd_str_full(const char *cmd, const char *input, char **output RZ_API char *rz_sys_get_src_dir_w32(void); RZ_API bool rz_sys_cmd_str_full_w32(const char *cmd, const char *input, char **output, int *outlen, char **sterr); RZ_API bool rz_sys_create_child_proc_w32(const char *cmdline, HANDLE in, HANDLE out, HANDLE err); +RZ_API char **rz_sys_utf8_argv_new(int argc, const wchar_t **argv); +RZ_API void rz_sys_utf8_argv_free(int argc, char **utf8_argv); #endif RZ_API int rz_sys_open_perms(int rizin_perms); RZ_API int rz_sys_open(const char *path, int perm, int mode); diff --git a/librz/util/subprocess.c b/librz/util/subprocess.c index 7d47ce7344..e166931e94 100644 --- a/librz/util/subprocess.c +++ b/librz/util/subprocess.c @@ -25,19 +25,19 @@ static bool create_pipe_overlap(HANDLE *pipe_read, HANDLE *pipe_write, LPSECURIT if (!sz) { sz = 4096; } - char name[MAX_PATH]; - snprintf(name, sizeof(name), "\\\\.\\pipe\\rz-pipe-subproc.%d.%ld", (int)GetCurrentProcessId(), (long)InterlockedIncrement(&pipe_id)); - *pipe_read = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, sz, sz, 120 * 1000, attrs); + WCHAR name[MAX_PATH]; + _snwprintf_s(name, _countof(name), sizeof(name), L"\\\\.\\pipe\\rz-pipe-subproc.%d.%ld", (int)GetCurrentProcessId(), (long)InterlockedIncrement(&pipe_id)); + *pipe_read = CreateNamedPipeW(name, PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, sz, sz, 120 * 1000, attrs); if (!*pipe_read) { return FALSE; } - *pipe_write = CreateFileA(name, GENERIC_WRITE, 0, attrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | write_mode, NULL); + *pipe_write = CreateFileW(name, GENERIC_WRITE, 0, attrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | write_mode, NULL); if (*pipe_write == INVALID_HANDLE_VALUE) { CloseHandle(*pipe_read); return FALSE; } - SetEnvironmentVariable(TEXT("RZ_PIPE_PATH"), name); + SetEnvironmentVariableW(L"RZ_PIPE_PATH", name); return true; } @@ -45,7 +45,7 @@ RZ_API bool rz_subprocess_init(void) { return true; } RZ_API void rz_subprocess_fini(void) { - SetEnvironmentVariable(TEXT("RZ_PIPE_PATH"), NULL); + SetEnvironmentVariableW(L"RZ_PIPE_PATH", NULL); } // Create an env block that inherits the current vars but overrides the given ones @@ -141,18 +141,31 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { HANDLE stdin_read = GetStdHandle(STD_INPUT_HANDLE); HANDLE stdout_write = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE stderr_write = GetStdHandle(STD_ERROR_HANDLE); - LPSTR lpFilePart; - char cmd_exe[MAX_PATH]; + LPWSTR lpFilePart; + WCHAR cmd_exe[MAX_PATH]; - if (!rz_file_exists(opt->file) && NeedCurrentDirectoryForExePathA(opt->file)) { + PWCHAR file = rz_utf8_to_utf16(opt->file); + if (!file) { + return NULL; + } + + if (!rz_file_exists(opt->file) && NeedCurrentDirectoryForExePathW(file)) { DWORD len; - if ((len = SearchPath(NULL, opt->file, ".exe", sizeof(cmd_exe), cmd_exe, &lpFilePart)) < 1) { + if ((len = SearchPathW(NULL, file, L".exe", _countof(cmd_exe), cmd_exe, &lpFilePart)) < 1) { RZ_LOG_DEBUG("SearchPath failed for %s\n", opt->file); + free(file); return NULL; } } else { - snprintf(cmd_exe, sizeof(cmd_exe), "%s", opt->file); + WCHAR *tmp = rz_utf8_to_utf16(opt->file); + if (!tmp) { + free(file); + return NULL; + } + _snwprintf_s(cmd_exe, _countof(cmd_exe), sizeof(cmd_exe), L"%s", tmp); + free(tmp); } + free(file); char **argv = calloc(opt->args_size + 1, sizeof(char *)); if (!argv) { @@ -162,11 +175,23 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { if (opt->args_size) { memcpy(argv + 1, opt->args, sizeof(char *) * opt->args_size); } - char *cmdline = rz_str_format_msvc_argv(opt->args_size + 1, argv); + char *cmd = rz_str_format_msvc_argv(opt->args_size + 1, argv); free(argv); - if (!cmdline) { + if (!cmd) { return NULL; } + PWCHAR cmdline = rz_utf8_to_utf16(cmd); + if (!cmdline) { + goto error; + } + + { + char *log_executable = rz_utf16_to_utf8(cmd_exe); + if (log_executable) { + RZ_LOG_DEBUG("%s%s\n", log_executable, cmd); + free(log_executable); + } + } proc = RZ_NEW0(RzSubprocess); if (!proc) { @@ -215,7 +240,7 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { } PROCESS_INFORMATION proc_info = { 0 }; - STARTUPINFOA start_info = { 0 }; + STARTUPINFOW start_info = { 0 }; start_info.cb = sizeof(start_info); start_info.hStdError = stderr_write; start_info.hStdOutput = stdout_write; @@ -223,8 +248,7 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { start_info.dwFlags = STARTF_USESTDHANDLES; LPWSTR env = override_env(opt->envvars, opt->envvals, opt->env_size); - RZ_LOG_DEBUG("%s%s\n", cmd_exe, cmdline); - if (!CreateProcessA( + if (!CreateProcessW( cmd_exe, // exe cmdline, // command line NULL, // process security attributes @@ -236,12 +260,7 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { &start_info, // STARTUPINFO pointer &proc_info)) { // receives PROCESS_INFORMATION free(env); - char err_msg[256]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - err_msg, sizeof(err_msg), NULL); - - RZ_LOG_ERROR("CreateProcess failed: %#x %s\n", (int)GetLastError(), err_msg); + rz_sys_perror("CreateProcess"); goto error; } free(env); @@ -251,13 +270,13 @@ RZ_API RzSubprocess *rz_subprocess_start_opt(RzSubprocessOpt *opt) { beach: - if (stdin_read != GetStdHandle(STD_INPUT_HANDLE)) { + if (stdin_read && stdin_read != GetStdHandle(STD_INPUT_HANDLE)) { CloseHandle(stdin_read); } - if (stderr_write != GetStdHandle(STD_ERROR_HANDLE) && stderr_write != stdout_write) { + if (stderr_write && stderr_write != GetStdHandle(STD_ERROR_HANDLE) && stderr_write != stdout_write) { CloseHandle(stderr_write); } - if (stdout_write != GetStdHandle(STD_OUTPUT_HANDLE)) { + if (stdout_write && stdout_write != GetStdHandle(STD_OUTPUT_HANDLE)) { CloseHandle(stdout_write); } free(cmdline); diff --git a/librz/util/w32-sys.c b/librz/util/w32-sys.c index 1ef6877a77..c68567d6e6 100644 --- a/librz/util/w32-sys.c +++ b/librz/util/w32-sys.c @@ -200,4 +200,24 @@ char *ReadFromPipe(HANDLE fh, int *outlen) { } return str; } + +RZ_API char **rz_sys_utf8_argv_new(int argc, const wchar_t **argv) { + char **utf8_argv = calloc(argc + 1, sizeof(wchar_t *)); + if (!utf8_argv) { + return NULL; + } + int i; + for (i = 0; i < argc; i++) { + utf8_argv[i] = rz_utf16_to_utf8(argv[i]); + } + return utf8_argv; +} + +RZ_API void rz_sys_utf8_argv_free(int argc, char **utf8_argv) { + int i; + for (i = 0; i < argc; i++) { + free(utf8_argv[i]); + } + free(utf8_argv); +} #endif