[geany/geany] a45091: spawn: Use Wide API on Windows

Colomban Wendling git-noreply at geany.org
Sun Nov 13 13:55:40 UTC 2016


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Enrico Tröger <enrico.troeger at uvena.de>
Date:        Sun, 13 Nov 2016 13:55:40 UTC
Commit:      a45091413a0dae1bc72546281210674fa250db5c
             https://github.com/geany/geany/commit/a45091413a0dae1bc72546281210674fa250db5c

Log Message:
-----------
spawn: Use Wide API on Windows

Try and use Unicode variants of the Windows process creation API in
order to support filenames (and possibly environment) outside the
locale codepage.

WARNING: Implications on using Unicode environment are unknown.
It might affect the called process, or not, not sure.


Modified Paths:
--------------
    src/spawn.c

Modified: src/spawn.c
123 lines changed, 66 insertions(+), 57 deletions(-)
===================================================================
@@ -67,6 +67,7 @@
 #else
 # include "support.h"
 #endif
+#include "utils.h"
 
 #if ! GLIB_CHECK_VERSION(2, 31, 20) && ! defined(G_SPAWN_ERROR_TOO_BIG)
 # define G_SPAWN_ERROR_TOO_BIG G_SPAWN_ERROR_2BIG
@@ -307,11 +308,11 @@ gboolean spawn_kill_process(GPid pid, GError **error)
 
 
 #ifdef G_OS_WIN32
-static gchar *spawn_create_process_with_pipes(char *command_line, const char *working_directory,
-	void *environment, HANDLE *hprocess, int *stdin_fd, int *stdout_fd, int *stderr_fd)
+static gchar *spawn_create_process_with_pipes(wchar_t *w_command_line, const wchar_t *w_working_directory,
+	void *w_environment, HANDLE *hprocess, int *stdin_fd, int *stdout_fd, int *stderr_fd)
 {
 	enum { WRITE_STDIN, READ_STDOUT, READ_STDERR, READ_STDIN, WRITE_STDOUT, WRITE_STDERR };
-	STARTUPINFO startup;
+	STARTUPINFOW startup;
 	PROCESS_INFORMATION process;
 	HANDLE hpipe[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
 	int *fd[3] = { stdin_fd, stdout_fd, stderr_fd };
@@ -372,8 +373,9 @@ static gchar *spawn_create_process_with_pipes(char *command_line, const char *wo
 	startup.hStdOutput = hpipe[WRITE_STDOUT];
 	startup.hStdError = hpipe[WRITE_STDERR];
 
-	if (!CreateProcess(NULL, command_line, NULL, NULL, TRUE, pipe_io ? CREATE_NO_WINDOW : 0,
-		environment, working_directory, &startup, &process))
+	if (!CreateProcessW(NULL, w_command_line, NULL, NULL, TRUE,
+		CREATE_UNICODE_ENVIRONMENT | (pipe_io ? CREATE_NO_WINDOW : 0),
+		w_environment, w_working_directory, &startup, &process))
 	{
 		failed = "";  /* report the message only */
 		/* further errors will not be reported */
@@ -521,9 +523,9 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
 
 #ifdef G_OS_WIN32
 	GString *command;
-	GArray *environment;
-	gchar *locale_working_directory = NULL;
-	gchar *locale_command = NULL;
+	GArray *w_environment;
+	wchar_t *w_working_directory = NULL;
+	wchar_t *w_command = NULL;
 	gboolean success = TRUE;
 
 	if (command_line)
@@ -555,7 +557,7 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
 	else
 		command = g_string_new(NULL);
 
-	environment = g_array_new(TRUE, FALSE, sizeof(char));
+	w_environment = g_array_new(TRUE, FALSE, sizeof(wchar_t));
 
 	while (argv && *argv)
 		spawn_append_argument(command, *argv++);
@@ -566,81 +568,88 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
 
 	while (envp && *envp && success)
 	{
-		gsize locale_entry_len;
-		gchar *locale_entry;
+		glong w_entry_len;
+		wchar_t *w_entry;
+		gchar *tmp = NULL;
 
-		if (g_utf8_validate(*envp, -1, NULL))
+		// FIXME: remove this and rely on UTF-8 input
+		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);
+			tmp = utils_get_utf8_from_locale(*envp);
+			*envp = tmp;
 		}
+		/* TODO: better error message */
+		w_entry = g_utf8_to_utf16(*envp, -1, NULL, &w_entry_len, error);
 
-		if (! locale_entry)
+		if (! w_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);
+			g_array_append_vals(w_environment, w_entry, w_entry_len + 1);
+			g_free(w_entry);
 		}
 
+		g_free(tmp);
 		envp++;
 	}
 
 	/* convert working directory into locale encoding */
 	if (success && working_directory)
 	{
-		if (g_utf8_validate(working_directory, -1, NULL))
-		{
-			GError *gerror = NULL;
+		GError *gerror = NULL;
+		const gchar *utf8_working_directory;
+		gchar *tmp = 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;
-			}
-		}
+		// FIXME: remove this and rely on UTF-8 input
+		if (! g_utf8_validate(working_directory, -1, NULL))
+			utf8_working_directory = tmp = utils_get_utf8_from_locale(working_directory);
 		else
-			locale_working_directory = g_strdup(working_directory);
+			utf8_working_directory = working_directory;
+
+		w_working_directory = g_utf8_to_utf16(utf8_working_directory, -1, NULL, NULL, &gerror);
+		if (! w_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;
+		}
+		g_free(tmp);
 	}
 	/* convert command into locale encoding */
 	if (success)
 	{
-		if (g_utf8_validate(command->str, -1, NULL))
-		{
-			GError *gerror = NULL;
+		GError *gerror = NULL;
+		const gchar *utf8_cmd;
+		gchar *tmp = 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;
-			}
-		}
+		// FIXME: remove this and rely on UTF-8 input
+		if (! g_utf8_validate(command->str, -1, NULL))
+			utf8_cmd = tmp = utils_get_utf8_from_locale(command->str);
 		else
-			locale_command = g_strdup(command->str);
+			utf8_cmd = command->str;
+
+		w_command = g_utf8_to_utf16(utf8_cmd, -1, NULL, NULL, &gerror);
+		if (! w_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;
+		}
 	}
 
 	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);
+		failure = spawn_create_process_with_pipes(w_command, w_working_directory,
+			envp ? w_environment->data : NULL, child_pid, stdin_fd, stdout_fd, stderr_fd);
 
 		if (failure)
 		{
@@ -652,9 +661,9 @@ static gboolean spawn_async_with_pipes(const gchar *working_directory, const gch
 	}
 
 	g_string_free(command, TRUE);
-	g_array_free(environment, TRUE);
-	g_free(locale_working_directory);
-	g_free(locale_command);
+	g_array_free(w_environment, TRUE);
+	g_free(w_working_directory);
+	g_free(w_command);
 
 	return success;
 #else  /* G_OS_WIN32 */



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list