296 lines
9.2 KiB
Diff
296 lines
9.2 KiB
Diff
Index: glib/gspawn.h
|
|
===================================================================
|
|
--- glib/gspawn.h (revision 6301)
|
|
+++ glib/gspawn.h (working copy)
|
|
@@ -67,6 +67,9 @@ typedef enum
|
|
G_SPAWN_STDERR_TO_DEV_NULL = 1 << 4,
|
|
G_SPAWN_CHILD_INHERITS_STDIN = 1 << 5,
|
|
G_SPAWN_FILE_AND_ARGV_ZERO = 1 << 6
|
|
+#ifdef G_OS_WIN32
|
|
+ , G_SPAWN_WIN32_HIDDEN_CONSOLE = 1 << 7
|
|
+#endif
|
|
} GSpawnFlags;
|
|
|
|
GQuark g_spawn_error_quark (void);
|
|
Index: glib/gspawn-win32.c
|
|
===================================================================
|
|
--- glib/gspawn-win32.c (revision 6301)
|
|
+++ glib/gspawn-win32.c (working copy)
|
|
@@ -95,7 +95,8 @@ enum
|
|
};
|
|
|
|
enum {
|
|
- ARG_CHILD_ERR_REPORT = 1,
|
|
+ ARG_HANDLES_IN_ARGV = 1,
|
|
+ ARG_CHILD_ERR_REPORT,
|
|
ARG_STDIN,
|
|
ARG_STDOUT,
|
|
ARG_STDERR,
|
|
@@ -334,7 +335,11 @@ read_helper_report (int fd,
|
|
}
|
|
|
|
if (bytes < sizeof(gint)*2)
|
|
- return FALSE;
|
|
+ {
|
|
+ g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
|
+ _("Failed to read from child pipe"));
|
|
+ return FALSE;
|
|
+ }
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -500,6 +505,60 @@ do_spawn_directly (gint
|
|
return TRUE;
|
|
}
|
|
|
|
+static int
|
|
+spawn_with_hidden_console (wchar_t **wargv,
|
|
+ wchar_t **wenvp,
|
|
+ GError **error)
|
|
+{
|
|
+ GArray *cmd_line;
|
|
+ STARTUPINFOW sinfo;
|
|
+ PROCESS_INFORMATION pinfo;
|
|
+ wchar_t **p;
|
|
+ int rc = -1;
|
|
+
|
|
+ cmd_line = g_array_new (FALSE, FALSE, sizeof (wchar_t));
|
|
+ for (p = wargv; *p; p++)
|
|
+ {
|
|
+ if (p > wargv)
|
|
+ g_array_append_vals (cmd_line, L" ", 1);
|
|
+ g_array_append_vals (cmd_line, *p, wcslen (*p));
|
|
+ }
|
|
+ g_array_append_vals (cmd_line, L"", 1);
|
|
+
|
|
+ memset (&sinfo, 0, sizeof sinfo);
|
|
+ sinfo.cb = sizeof (STARTUPINFO);
|
|
+ sinfo.dwFlags = STARTF_USESHOWWINDOW;
|
|
+ sinfo.wShowWindow = SW_HIDE;
|
|
+
|
|
+ if (CreateProcessW (NULL, (wchar_t*) cmd_line->data, NULL, NULL, TRUE,
|
|
+ CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
|
|
+ wenvp, NULL, &sinfo, &pinfo))
|
|
+ {
|
|
+ rc = (int) pinfo.hProcess;
|
|
+ CloseHandle (pinfo.hThread);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
|
+ _("Failed to execute helper program (%s)"),
|
|
+ g_win32_error_message (GetLastError ()));
|
|
+ }
|
|
+
|
|
+ g_array_free (cmd_line, TRUE);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+static void
|
|
+sprintf_file_descriptor (gchar *dest,
|
|
+ gint fd,
|
|
+ gboolean print_handle)
|
|
+{
|
|
+ if (print_handle)
|
|
+ _g_sprintf (dest, "%ld", _get_osfhandle (fd));
|
|
+ else
|
|
+ _g_sprintf (dest, "%d", fd);
|
|
+}
|
|
+
|
|
static gboolean
|
|
do_spawn_with_pipes (gint *exit_status,
|
|
gboolean do_return_handle,
|
|
@@ -534,7 +593,9 @@ do_spawn_with_pipes (gint
|
|
gchar *helper_process;
|
|
CONSOLE_CURSOR_INFO cursor_info;
|
|
wchar_t *whelper, **wargv, **wenvp;
|
|
-
|
|
+ gboolean error_set = FALSE;
|
|
+ gboolean handles_in_argv = FALSE;
|
|
+
|
|
SETUP_DEBUG();
|
|
|
|
if (child_setup && !warned_about_child_setup)
|
|
@@ -546,6 +607,7 @@ do_spawn_with_pipes (gint
|
|
argc = protect_argv (argv, &protected_argv);
|
|
|
|
if (!standard_input && !standard_output && !standard_error &&
|
|
+ !(flags & G_SPAWN_WIN32_HIDDEN_CONSOLE) &&
|
|
(flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
|
|
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
|
|
!(flags & G_SPAWN_STDERR_TO_DEV_NULL) &&
|
|
@@ -575,12 +637,21 @@ do_spawn_with_pipes (gint
|
|
goto cleanup_and_fail;
|
|
|
|
new_argv = g_new (char *, argc + 1 + ARG_COUNT);
|
|
- if (GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
|
|
+ if ((flags & G_SPAWN_WIN32_HIDDEN_CONSOLE) ||
|
|
+ GetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cursor_info))
|
|
helper_process = HELPER_PROCESS "-console.exe";
|
|
else
|
|
helper_process = HELPER_PROCESS ".exe";
|
|
new_argv[0] = helper_process;
|
|
- _g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);
|
|
+
|
|
+ if (flags & G_SPAWN_WIN32_HIDDEN_CONSOLE)
|
|
+ handles_in_argv = TRUE;
|
|
+
|
|
+ strcpy (args[ARG_HANDLES_IN_ARGV], handles_in_argv ? "y" : "n");
|
|
+ new_argv[ARG_HANDLES_IN_ARGV] = args[ARG_HANDLES_IN_ARGV];
|
|
+
|
|
+ sprintf_file_descriptor (args[ARG_CHILD_ERR_REPORT],
|
|
+ child_err_report_pipe[1], handles_in_argv);
|
|
new_argv[ARG_CHILD_ERR_REPORT] = args[ARG_CHILD_ERR_REPORT];
|
|
|
|
if (flags & G_SPAWN_FILE_AND_ARGV_ZERO)
|
|
@@ -593,7 +664,7 @@ do_spawn_with_pipes (gint
|
|
|
|
if (standard_input)
|
|
{
|
|
- _g_sprintf (args[ARG_STDIN], "%d", stdin_pipe[0]);
|
|
+ sprintf_file_descriptor (args[ARG_STDIN], stdin_pipe[0], handles_in_argv);
|
|
new_argv[ARG_STDIN] = args[ARG_STDIN];
|
|
}
|
|
else if (flags & G_SPAWN_CHILD_INHERITS_STDIN)
|
|
@@ -609,7 +680,7 @@ do_spawn_with_pipes (gint
|
|
|
|
if (standard_output)
|
|
{
|
|
- _g_sprintf (args[ARG_STDOUT], "%d", stdout_pipe[1]);
|
|
+ sprintf_file_descriptor (args[ARG_STDOUT], stdout_pipe[1], handles_in_argv);
|
|
new_argv[ARG_STDOUT] = args[ARG_STDOUT];
|
|
}
|
|
else if (flags & G_SPAWN_STDOUT_TO_DEV_NULL)
|
|
@@ -623,7 +694,7 @@ do_spawn_with_pipes (gint
|
|
|
|
if (standard_error)
|
|
{
|
|
- _g_sprintf (args[ARG_STDERR], "%d", stderr_pipe[1]);
|
|
+ sprintf_file_descriptor (args[ARG_STDERR], stderr_pipe[1], handles_in_argv);
|
|
new_argv[ARG_STDERR] = args[ARG_STDERR];
|
|
}
|
|
else if (flags & G_SPAWN_STDERR_TO_DEV_NULL)
|
|
@@ -704,7 +775,13 @@ do_spawn_with_pipes (gint
|
|
if (child_setup)
|
|
(* child_setup) (user_data);
|
|
|
|
- if (wenvp != NULL)
|
|
+ if (flags & G_SPAWN_WIN32_HIDDEN_CONSOLE)
|
|
+ {
|
|
+ rc = spawn_with_hidden_console (wargv, wenvp, error);
|
|
+ if (rc == -1)
|
|
+ error_set = TRUE;
|
|
+ }
|
|
+ else if (wenvp != NULL)
|
|
/* Let's hope envp hasn't mucked with PATH so that
|
|
* gspawn-win32-helper.exe isn't found.
|
|
*/
|
|
@@ -732,11 +809,12 @@ do_spawn_with_pipes (gint
|
|
g_free (new_argv);
|
|
|
|
/* Check if gspawn-win32-helper couldn't be run */
|
|
- if (rc == -1 && saved_errno != 0)
|
|
+ if (rc == -1 && (saved_errno != 0 || error_set))
|
|
{
|
|
- g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
|
- _("Failed to execute helper program (%s)"),
|
|
- g_strerror (saved_errno));
|
|
+ if (!error_set)
|
|
+ g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED,
|
|
+ _("Failed to execute helper program (%s)"),
|
|
+ g_strerror (saved_errno));
|
|
goto cleanup_and_fail;
|
|
}
|
|
|
|
Index: glib/gspawn-win32-helper.c
|
|
===================================================================
|
|
--- glib/gspawn-win32-helper.c (revision 6301)
|
|
+++ glib/gspawn-win32-helper.c (working copy)
|
|
@@ -145,6 +145,16 @@ protect_wargv (wchar_t **wargv,
|
|
return argc;
|
|
}
|
|
|
|
+static int
|
|
+get_file_descriptor (const gchar *arg,
|
|
+ gboolean is_handle)
|
|
+{
|
|
+ if (is_handle)
|
|
+ return _open_osfhandle (atoi (arg), 0);
|
|
+ else
|
|
+ return atoi (arg);
|
|
+}
|
|
+
|
|
int _stdcall
|
|
WinMain (struct HINSTANCE__ *hInstance,
|
|
struct HINSTANCE__ *hPrevInstance,
|
|
@@ -163,6 +173,7 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
wchar_t **new_wargv;
|
|
int argc;
|
|
wchar_t **wargv, **wenvp;
|
|
+ gboolean handles_in_argv;
|
|
_startupinfo si = { 0 };
|
|
|
|
g_assert (__argc >= ARG_COUNT);
|
|
@@ -176,10 +187,17 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
*/
|
|
g_assert (argc == __argc);
|
|
|
|
- /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor number onto
|
|
+ /* argv[ARG_HANDLES_IN_ARGV] is "y" or "n" telling whether
|
|
+ * file handle arguments contain HANDLE's or file descriptors.
|
|
+ */
|
|
+ handles_in_argv = __argv[ARG_HANDLES_IN_ARGV][0] == 'y';
|
|
+
|
|
+ /* argv[ARG_CHILD_ERR_REPORT] is the pipe handle onto
|
|
* which write error messages.
|
|
*/
|
|
- child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]);
|
|
+ child_err_report_fd = get_file_descriptor (__argv[ARG_CHILD_ERR_REPORT], handles_in_argv);
|
|
+ if (child_err_report_fd < 0)
|
|
+ g_error ("child_err_report_fd not set");
|
|
|
|
/* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO. If
|
|
* argv[ARG_CHILD_ERR_REPORT] is suffixed with a '#' it means we get
|
|
@@ -188,7 +206,7 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#')
|
|
argv_zero_offset++;
|
|
|
|
- /* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that
|
|
+ /* argv[ARG_STDIN..ARG_STDERR] are the pipe handles that
|
|
* should be dup2'd to 0, 1 and 2. '-' if the corresponding fd
|
|
* should be left alone, and 'z' if it should be connected to the
|
|
* bit bucket NUL:.
|
|
@@ -206,7 +224,9 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
}
|
|
else
|
|
{
|
|
- fd = atoi (__argv[ARG_STDIN]);
|
|
+ fd = get_file_descriptor (__argv[ARG_STDIN], handles_in_argv);
|
|
+ if (fd < 0)
|
|
+ g_error ("could not open stdin pipe");
|
|
if (fd != 0)
|
|
{
|
|
dup2 (fd, 0);
|
|
@@ -227,7 +247,9 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
}
|
|
else
|
|
{
|
|
- fd = atoi (__argv[ARG_STDOUT]);
|
|
+ fd = get_file_descriptor (__argv[ARG_STDOUT], handles_in_argv);
|
|
+ if (fd < 0)
|
|
+ g_error ("could not open stdout pipe");
|
|
if (fd != 1)
|
|
{
|
|
dup2 (fd, 1);
|
|
@@ -248,7 +270,9 @@ WinMain (struct HINSTANCE__ *hInstance,
|
|
}
|
|
else
|
|
{
|
|
- fd = atoi (__argv[ARG_STDERR]);
|
|
+ fd = get_file_descriptor (__argv[ARG_STDERR], handles_in_argv);
|
|
+ if (fd < 0)
|
|
+ g_error ("could not open stderr pipe");
|
|
if (fd != 2)
|
|
{
|
|
dup2 (fd, 2);
|