Kaydet (Commit) 26adcabd authored tarafından Enrico Tröger's avatar Enrico Tröger

Windows: Convert generated batch script into system codepage

Instead of fiddling with the "chcp" command in the generated batch
script on Windows, convert the whole script content into the system
codepage before executing it.
üst 127e9419
......@@ -1070,7 +1070,7 @@ static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cm
gboolean success = TRUE;
#ifdef G_OS_WIN32
gchar *expanded_cmd;
guint codepage;
gchar *utf8_script_content;
#else
gchar *escaped_dir;
#endif
......@@ -1080,16 +1080,17 @@ static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cm
close(fd);
#ifdef G_OS_WIN32
/* We set the console codepage to UTF-8 (65001) before changing the working directory
* because the working directory is in UTF-8 encoding.
* Then we reset it again to the default value before executing the command. */
codepage = win32_get_console_codepage();
/* Expand environment variables like %blah%. */
expanded_cmd = win32_expand_environment_variables(cmd);
str = g_strdup_printf(
"chcp 65001 > nul\ncd \"%s\"\nchcp %u > nul\n\n%s\n\n%s\ndel \"%%0\"\n\npause\n",
working_dir, codepage, expanded_cmd, (autoclose) ? "" : "pause");
"cd \"%s\"\n\n\n%s\n\n%s\ndel \"%%0\"\n\npause\n",
working_dir, expanded_cmd, (autoclose) ? "" : "pause");
g_free(expanded_cmd);
/* Convert script content into system codepage */
utf8_script_content = win32_convert_to_system_codepage(str, error);
if (utf8_script_content == NULL)
return NULL;
SETPTR(str, utf8_script_content);
#else
escaped_dir = g_shell_quote(working_dir);
str = g_strdup_printf(
......
......@@ -522,10 +522,9 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
#ifdef G_OS_WIN32
GString *command;
GArray *environment;
GError *gerror = NULL;
gchar *locale_working_directory;
gchar *locale_command;
gchar *failure;
gchar *locale_working_directory = NULL;
gchar *locale_command = NULL;
gboolean success = TRUE;
if (command_line)
{
......@@ -565,67 +564,99 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
g_message("full spawn command line: %s", command->str);
#endif
while (envp && *envp)
while (envp && *envp && success)
{
g_array_append_vals(environment, *envp, strlen(*envp) + 1);
gsize locale_entry_len;
gchar *locale_entry;
if (g_utf8_validate(*envp, -1, NULL))
{
/* TODO: better error message */
locale_entry = g_locale_from_utf8(*envp, -1, NULL, &locale_entry_len, error);
}
else
{
locale_entry_len = strlen(*envp);
locale_entry = g_memdup(*envp, locale_entry_len + 1);
}
if (! locale_entry)
success = FALSE;
else
{
/* copy the entry, including NUL terminator */
g_array_append_vals(environment, locale_entry, locale_entry_len + 1);
g_free(locale_entry);
}
envp++;
}
// convert working directory into locale encoding
if (g_utf8_validate(working_directory, -1, NULL))
/* convert working directory into locale encoding */
if (success && working_directory)
{
locale_working_directory = g_locale_from_utf8(working_directory, -1, NULL, NULL, &gerror);
if (gerror) {
/* TODO use the code below post-1.28 as it introduces a new string
gchar *msg = g_strdup_printf(
_("Failed to convert working directory into locale encoding: %s"), gerror->message);
g_set_error_literal(error, gerror->domain, gerror->code, msg);
*/
g_set_error_literal(error, gerror->domain, gerror->code, gerror->message);
g_error_free(gerror);
g_string_free(command, TRUE);
g_array_free(environment, TRUE);
g_free(locale_working_directory);
/*g_free(msg);*/
return FALSE;
if (g_utf8_validate(working_directory, -1, NULL))
{
GError *gerror = NULL;
locale_working_directory = g_locale_from_utf8(working_directory, -1, NULL, NULL, &gerror);
if (! locale_working_directory)
{
/* TODO use the code below post-1.28 as it introduces a new string
g_set_error(error, gerror->domain, gerror->code,
_("Failed to convert working directory into locale encoding: %s"), gerror->message);
*/
g_propagate_error(error, gerror);
success = FALSE;
}
}
else
locale_working_directory = g_strdup(working_directory);
}
// convert command into locale encoding
if (g_utf8_validate(command->str, -1, NULL))
/* convert command into locale encoding */
if (success)
{
locale_command = g_locale_from_utf8(command->str, -1, NULL, NULL, &gerror);
if (gerror) {
/* TODO use the code below post-1.28 as it introduces a new string
gchar *msg = g_strdup_printf(
_("Failed to convert command into locale encoding: %s"), gerror->message);
g_set_error_literal(error, gerror->domain, gerror->code, msg);
*/
g_set_error_literal(error, gerror->domain, gerror->code, gerror->message);
g_error_free(gerror);
g_string_free(command, TRUE);
g_array_free(environment, TRUE);
g_free(locale_working_directory);
g_free(locale_command);
/*g_free(msg);*/
return FALSE;
if (g_utf8_validate(command->str, -1, NULL))
{
GError *gerror = NULL;
locale_command = g_locale_from_utf8(command->str, -1, NULL, NULL, &gerror);
if (! locale_command)
{
/* TODO use the code below post-1.28 as it introduces a new string
g_set_error(error, gerror->domain, gerror->code,
_("Failed to convert command into locale encoding: %s"), gerror->message);
*/
g_propagate_error(error, gerror);
success = FALSE;
}
}
else
locale_command = g_strdup(command->str);
}
if (success)
{
gchar *failure;
failure = spawn_create_process_with_pipes(locale_command, locale_working_directory,
envp ? environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd);
if (failure)
{
g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, failure);
g_free(failure);
}
success = failure == NULL;
}
failure = spawn_create_process_with_pipes(locale_command, locale_working_directory,
envp ? environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd);
g_string_free(command, TRUE);
g_array_free(environment, TRUE);
g_free(locale_working_directory);
g_free(locale_command);
if (failure)
{
g_set_error_literal(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, failure);
g_free(failure);
return FALSE;
}
return TRUE;
return success;
#else /* G_OS_WIN32 */
int cl_argc;
char **full_argv;
......
......@@ -1034,14 +1034,32 @@ gchar *win32_get_user_config_dir(void)
/* Retrieve the console codepage
* In case GetConsoleOutputCP() returns 0 (i.e. the application doesn't have an own console window
* In case GetConsoleCP() returns 0 (i.e. the application doesn't have an own console window
* fallback to GetOEMCP(). */
guint win32_get_console_codepage(void)
{
guint codepage = GetConsoleOutputCP();
guint codepage = GetConsoleCP();
if (codepage == 0)
codepage = GetOEMCP();
return codepage;
}
/* Convert a string into the system's default codepage, this is different from the
* locale (e.g. default codepage is 850 but locale is CP1252).
* This assumes the input string is encoded as UTF-8, otherwise a copy of
* the input string is returned. */
gchar *win32_convert_to_system_codepage(const gchar *str, GError **error)
{
if (g_utf8_validate(str, -1, NULL))
{
guint codepage_code = win32_get_console_codepage();
gchar codepage[8] = { 0 };
g_snprintf(codepage, G_N_ELEMENTS(codepage), "%u", codepage_code);
return g_convert(str, -1, codepage, "utf-8", NULL, NULL, error);
}
else
return g_strdup(str);
}
#endif
......@@ -70,6 +70,8 @@ gchar *win32_get_user_config_dir(void);
guint win32_get_console_codepage(void);
gchar *win32_convert_to_system_codepage(const gchar *str, GError **error);
G_END_DECLS
#endif /* G_OS_WIN32 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment