Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / w32process-win32.c
index 15cfd4d61a230e8f590535c808aeaed513605e0a..24fb97ce4d499e116c6361dd080ee65cc5611fc0 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * process.c: System.Diagnostics.Process support
+/**
+ * \file
+ * System.Diagnostics.Process support
  *
  * Author:
  *     Dick Porter (dick@ximian.com)
 #include <mono/metadata/image.h>
 #include <mono/metadata/cil-coff.h>
 #include <mono/metadata/exception.h>
-#include <mono/metadata/threadpool-ms-io.h>
+#include <mono/metadata/threadpool-io.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-proclib.h>
-#include <mono/io-layer/io-layer.h>
 /* FIXME: fix this code to not depend so much on the internals */
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/w32handle.h>
+#include <mono/utils/w32api.h>
 
 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 #include <shellapi.h>
@@ -47,6 +48,11 @@ mono_w32process_cleanup (void)
 {
 }
 
+void
+mono_w32process_signal_finished (void)
+{
+}
+
 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 HANDLE
 ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
@@ -64,68 +70,6 @@ ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
 }
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
-static gchar*
-mono_process_unquote_application_name (gchar *appname)
-{
-       size_t len = strlen (appname);
-       if (len) {
-               if (appname[len-1] == '\"')
-                       appname[len-1] = '\0';
-               if (appname[0] == '\"')
-                       appname++;
-       }
-
-       return appname;
-}
-
-static gchar*
-mono_process_quote_path (const gchar *path)
-{
-       gchar *res = g_shell_quote (path);
-       gchar *q = res;
-       while (*q) {
-               if (*q == '\'')
-                       *q = '\"';
-               q++;
-       }
-       return res;
-}
-
-/* Only used when UseShellExecute is false */
-static gboolean
-mono_process_complete_path (const gunichar2 *appname, gchar **completed)
-{
-       gchar *utf8app, *utf8appmemory;
-       gchar *found;
-
-       utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
-       utf8app = mono_process_unquote_application_name (utf8appmemory);
-
-       if (g_path_is_absolute (utf8app)) {
-               *completed = mono_process_quote_path (utf8app);
-               g_free (utf8appmemory);
-               return TRUE;
-       }
-
-       if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
-               *completed = mono_process_quote_path (utf8app);
-               g_free (utf8appmemory);
-               return TRUE;
-       }
-       
-       found = g_find_program_in_path (utf8app);
-       if (found == NULL) {
-               *completed = NULL;
-               g_free (utf8appmemory);
-               return FALSE;
-       }
-
-       *completed = mono_process_quote_path (found);
-       g_free (found);
-       g_free (utf8appmemory);
-       return TRUE;
-}
-
 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 MonoBoolean
 ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoW32ProcessStartInfo *proc_start_info, MonoW32ProcessInfo *process_info)
@@ -191,13 +135,10 @@ mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDL
        startinfo->hStdError = stderr_handle;
        return;
 }
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 static gboolean
-mono_process_create_process (MonoW32ProcessInfo *mono_process_info, gunichar2 *shell_path,
-                            MonoString *cmd, guint32 creation_flags, gchar *env_vars,
-                            gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+mono_process_create_process (MonoW32ProcessInfo *mono_process_info, MonoString *cmd, guint32 creation_flags,
+       gunichar2 *env_vars, gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
 {
        gboolean result = FALSE;
 
@@ -208,14 +149,14 @@ mono_process_create_process (MonoW32ProcessInfo *mono_process_info, gunichar2 *s
                                                  mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
                                                  (const gunichar2 *)mono_process_info->password,
                                                  logon_flags,
-                                                 shell_path,
+                                                 NULL,
                                                  cmd ? mono_string_chars (cmd) : NULL,
                                                  creation_flags,
                                                  env_vars, dir, start_info, process_info);
 
        } else {
 
-               result = CreateProcess (shell_path,
+               result = CreateProcessW (NULL,
                                        cmd ? mono_string_chars (cmd): NULL,
                                        NULL,
                                        NULL,
@@ -232,18 +173,78 @@ mono_process_create_process (MonoW32ProcessInfo *mono_process_info, gunichar2 *s
 }
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
+static gchar*
+process_unquote_application_name (gchar *appname)
+{
+       size_t len = strlen (appname);
+       if (len) {
+               if (appname[len-1] == '\"')
+                       appname[len-1] = '\0';
+               if (appname[0] == '\"')
+                       appname++;
+       }
+
+       return appname;
+}
+
+static gchar*
+process_quote_path (const gchar *path)
+{
+       gchar *res = g_shell_quote (path);
+       gchar *q = res;
+       while (*q) {
+               if (*q == '\'')
+                       *q = '\"';
+               q++;
+       }
+       return res;
+}
+
+/* Only used when UseShellExecute is false */
+static gboolean
+process_complete_path (const gunichar2 *appname, gchar **completed)
+{
+       gchar *utf8app, *utf8appmemory;
+       gchar *found;
+
+       utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+       utf8app = process_unquote_application_name (utf8appmemory);
+
+       if (g_path_is_absolute (utf8app)) {
+               *completed = process_quote_path (utf8app);
+               g_free (utf8appmemory);
+               return TRUE;
+       }
+
+       if (g_file_test (utf8app, G_FILE_TEST_IS_EXECUTABLE) && !g_file_test (utf8app, G_FILE_TEST_IS_DIR)) {
+               *completed = process_quote_path (utf8app);
+               g_free (utf8appmemory);
+               return TRUE;
+       }
+       
+       found = g_find_program_in_path (utf8app);
+       if (found == NULL) {
+               *completed = NULL;
+               g_free (utf8appmemory);
+               return FALSE;
+       }
+
+       *completed = process_quote_path (found);
+       g_free (found);
+       g_free (utf8appmemory);
+       return TRUE;
+}
+
 static gboolean
-mono_process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, MonoString **cmd)
 {
        gchar           *spath = NULL;
        gchar           *new_cmd, *cmd_utf8;
        MonoError       mono_error;
 
-       *shell_path = NULL;
        *cmd = proc_start_info->arguments;
 
-       mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
-       if (spath != NULL) {
+       if (process_complete_path (mono_string_chars (proc_start_info->filename), &spath)) {
                /* Seems like our CreateProcess does not work as the windows one.
                 * This hack is needed to deal with paths containing spaces */
                if (*cmd) {
@@ -275,8 +276,7 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStart
        gunichar2 *dir;
        STARTUPINFO startinfo={0};
        PROCESS_INFORMATION procinfo;
-       gunichar2 *shell_path = NULL;
-       gchar *env_vars = NULL;
+       gunichar2 *env_vars = NULL;
        MonoString *cmd = NULL;
        guint32 creation_flags;
 
@@ -286,50 +286,38 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStart
        if (proc_start_info->create_no_window)
                creation_flags |= CREATE_NO_WINDOW;
        
-       if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+       if (process_get_shell_arguments (proc_start_info, &cmd) == FALSE) {
                process_info->pid = -ERROR_FILE_NOT_FOUND;
                return FALSE;
        }
 
-       if (process_info->env_keys) {
-               gint i, len; 
-               MonoString *ms;
-               MonoString *key, *value;
+       if (process_info->env_variables) {
+               gint i, len;
+               MonoString *var;
                gunichar2 *str, *ptr;
-               gunichar2 *equals16;
 
-               for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
-                       ms = mono_array_get (process_info->env_values, MonoString *, i);
-                       if (ms == NULL)
-                               continue;
+               len = 0;
 
-                       len += mono_string_length (ms) * sizeof (gunichar2);
-                       ms = mono_array_get (process_info->env_keys, MonoString *, i);
-                       len += mono_string_length (ms) * sizeof (gunichar2);
-                       len += 2 * sizeof (gunichar2);
-               }
+               for (i = 0; i < mono_array_length (process_info->env_variables); i++) {
+                       var = mono_array_get (process_info->env_variables, MonoString*, i);
 
-               equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
-               ptr = str = g_new0 (gunichar2, len + 1);
-               for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
-                       value = mono_array_get (process_info->env_values, MonoString *, i);
-                       if (value == NULL)
-                               continue;
+                       len += mono_string_length (var) * sizeof (gunichar2);
 
-                       key = mono_array_get (process_info->env_keys, MonoString *, i);
-                       memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
-                       ptr += mono_string_length (key);
+                       /* null-separated */
+                       len += sizeof (gunichar2);
+               }
+               /* null-terminated */
+               len += sizeof (gunichar2);
 
-                       memcpy (ptr, equals16, sizeof (gunichar2));
-                       ptr++;
+               env_vars = ptr = g_new0 (gunichar2, len);
 
-                       memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
-                       ptr += mono_string_length (value);
-                       ptr++;
-               }
+               for (i = 0; i < mono_array_length (process_info->env_variables); i++) {
+                       var = mono_array_get (process_info->env_variables, MonoString*, i);
 
-               g_free (equals16);
-               env_vars = (gchar *) str;
+                       memcpy (ptr, mono_string_chars (var), mono_string_length (var) * sizeof (gunichar2));
+                       ptr += mono_string_length (var);
+                       ptr += 1; // Skip over the null-separator
+               }
        }
        
        /* The default dir name is "".  Turn that into NULL to mean
@@ -340,11 +328,9 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoW32ProcessStart
        else
                dir = mono_string_chars (proc_start_info->working_directory);
 
-       ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
+       ret = mono_process_create_process (process_info, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
 
        g_free (env_vars);
-       if (shell_path != NULL)
-               g_free (shell_path);
 
        if (ret) {
                process_info->process_handle = procinfo.hProcess;