Build libmonoruntime under none desktop Windows API family.
[mono.git] / mono / metadata / process.c
index 96814db8480518f5f35f83caea8c66f18a9ec520..b1bff0b5ecad403e85d7f82ada5d42f06d08b8c5 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/process.h>
+#include <mono/metadata/process-internals.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/image.h>
 #define LOGDEBUG(...)  
 /* define LOGDEBUG(...) g_message(__VA_ARGS__)  */
 
-#ifdef _WIN32
+#if defined(HOST_WIN32) && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 #include <shellapi.h>
 #endif
 
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 HANDLE
 ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
 {
@@ -50,6 +52,7 @@ ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid)
                return NULL;
        return handle;
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
 static MonoImage *system_assembly;
 
@@ -196,11 +199,11 @@ process_set_field_bool (MonoObject *obj, const gchar *fieldname,
 #define SFI_SPECIALBUILD       "\\StringFileInfo\\%02X%02X%02X%02X\\SpecialBuild"
 #define EMPTY_STRING           (gunichar2*)"\000\000"
 
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 static void
 process_module_string_read (MonoObject *filever, gpointer data,
-                                                       const gchar *fieldname,
-                                                       guchar lang_hi, guchar lang_lo,
-                                                       const gchar *key, MonoError *error)
+                           const gchar *fieldname, guchar lang_hi, guchar lang_lo,
+                           const gchar *key, MonoError *error)
 {
        gchar *lang_key_utf8;
        gunichar2 *lang_key, *buffer;
@@ -367,6 +370,7 @@ process_get_fileversion (MonoObject *filever, gunichar2 *filename, MonoError *er
                g_free (data);
        }
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
 static void
 process_get_assembly_fileversion (MonoObject *filever, MonoAssembly *assembly)
@@ -409,6 +413,7 @@ get_process_module (MonoAssembly *assembly, MonoClass *proc_class, MonoError *er
        return item;
 }
 
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 static MonoObject*
 process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2 *modulename, MonoClass *proc_class, MonoError *error)
 {
@@ -451,6 +456,7 @@ process_add_module (HANDLE process, HMODULE mod, gunichar2 *filename, gunichar2
 
        return item;
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
 static GPtrArray*
 get_domain_assemblies (MonoDomain *domain)
@@ -476,6 +482,7 @@ get_domain_assemblies (MonoDomain *domain)
 }
 
 /* Returns an array of System.Diagnostics.ProcessModule */
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 MonoArray *
 ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process)
 {
@@ -546,6 +553,7 @@ ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj,
 
        return arr;
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
 void
 ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename)
@@ -569,53 +577,38 @@ ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject
 }
 
 /* Only used when UseShellExecute is false */
-static gchar *
-quote_path (const gchar *path)
+#ifndef HOST_WIN32
+static inline gchar *
+mono_process_quote_path (const gchar *path)
 {
-       gchar *res = g_shell_quote (path);
-#ifdef TARGET_WIN32
-       {
-       gchar *q = res;
-       while (*q) {
-               if (*q == '\'')
-                       *q = '\"';
-               q++;
-       }
-       }
-#endif
-       return res;
+       return g_shell_quote (path);
 }
 
+static inline gchar *
+mono_process_unquote_application_name (gchar *path)
+{
+       return path;
+}
+#endif /* !HOST_WIN32 */
+
 /* Only used when UseShellExecute is false */
-static gboolean
-complete_path (const gunichar2 *appname, gchar **completed)
+gboolean
+mono_process_complete_path (const gunichar2 *appname, gchar **completed)
 {
        gchar *utf8app, *utf8appmemory;
        gchar *found;
 
-       utf8appmemory = utf8app = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
-#ifdef TARGET_WIN32 // Should this happen on all platforms? 
-       {
-               // remove the quotes around utf8app.
-               size_t len;
-               len = strlen (utf8app);
-               if (len) {
-                       if (utf8app[len-1] == '\"')
-                               utf8app[len-1] = '\0';
-                       if (utf8app[0] == '\"')
-                               utf8app++;
-               }
-       }
-#endif
+       utf8appmemory = g_utf16_to_utf8 (appname, -1, NULL, NULL, NULL);
+       utf8app = mono_process_unquote_application_name (utf8appmemory);
 
        if (g_path_is_absolute (utf8app)) {
-               *completed = quote_path (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 = quote_path (utf8app);
+               *completed = mono_process_quote_path (utf8app);
                g_free (utf8appmemory);
                return TRUE;
        }
@@ -627,12 +620,13 @@ complete_path (const gunichar2 *appname, gchar **completed)
                return FALSE;
        }
 
-       *completed = quote_path (found);
+       *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 (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_info)
 {
@@ -684,62 +678,102 @@ ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartIn
 
        return ret;
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static inline void
+mono_process_init_startup_info (HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, STARTUPINFO *startinfo)
+{
+       startinfo->cb = sizeof(STARTUPINFO);
+       startinfo->dwFlags = STARTF_USESTDHANDLES;
+       startinfo->hStdInput = stdin_handle;
+       startinfo->hStdOutput = stdout_handle;
+       startinfo->hStdError = stderr_handle;
+       return;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
+
+#ifndef HOST_WIN32
+static gboolean
+mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+{
+       gchar *spath = NULL;
+
+       *shell_path = NULL;
+       *cmd = proc_start_info->arguments;
+
+       mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
+       if (spath != NULL) {
+               *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
+               g_free (spath);
+       }
+
+       return (*shell_path != NULL) ? TRUE : FALSE;
+}
+#endif /* !HOST_WIN32 */
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+static gboolean
+mono_process_create_process (MonoProcInfo *mono_process_info, gunichar2 *shell_path,
+                            MonoString *cmd, guint32 creation_flags, gchar *env_vars,
+                            gunichar2 *dir, STARTUPINFO *start_info, PROCESS_INFORMATION *process_info)
+{
+       gboolean result = FALSE;
+
+       if (mono_process_info->username) {
+               guint32 logon_flags = mono_process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
+
+               result = CreateProcessWithLogonW (mono_string_chars (mono_process_info->username),
+                                                 mono_process_info->domain ? mono_string_chars (mono_process_info->domain) : NULL,
+                                                 (const gunichar2 *)mono_process_info->password,
+                                                 logon_flags,
+                                                 shell_path,
+                                                 cmd ? mono_string_chars (cmd) : NULL,
+                                                 creation_flags,
+                                                 env_vars, dir, start_info, process_info);
+
+       } else {
+
+               result = CreateProcess (shell_path,
+                                       cmd ? mono_string_chars (cmd): NULL,
+                                       NULL,
+                                       NULL,
+                                       TRUE,
+                                       creation_flags,
+                                       env_vars,
+                                       dir,
+                                       start_info,
+                                       process_info);
+
+       }
+
+       return result;
+}
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
 MonoBoolean
-ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info)
+ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInfo *proc_start_info, HANDLE stdin_handle,
+                                                            HANDLE stdout_handle, HANDLE stderr_handle, MonoProcInfo *process_info)
 {
-       MonoError error G_GNUC_UNUSED;
        gboolean ret;
        gunichar2 *dir;
        STARTUPINFO startinfo={0};
        PROCESS_INFORMATION procinfo;
        gunichar2 *shell_path = NULL;
        gchar *env_vars = NULL;
-       gboolean free_shell_path = TRUE;
-       gchar *spath = NULL;
-       MonoString *cmd = proc_start_info->arguments;
-       guint32 creation_flags, logon_flags;
-       
-       startinfo.cb = sizeof(STARTUPINFO);
-       startinfo.dwFlags = STARTF_USESTDHANDLES;
-       startinfo.hStdInput = stdin_handle;
-       startinfo.hStdOutput = stdout_handle;
-       startinfo.hStdError = stderr_handle;
+       MonoString *cmd = NULL;
+       guint32 creation_flags;
+
+       mono_process_init_startup_info (stdin_handle, stdout_handle, stderr_handle, &startinfo);
 
        creation_flags = CREATE_UNICODE_ENVIRONMENT;
        if (proc_start_info->create_no_window)
                creation_flags |= CREATE_NO_WINDOW;
        
-       shell_path = mono_string_chars (proc_start_info->filename);
-       complete_path (shell_path, &spath);
-       if (spath == NULL) {
+       if (mono_process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
                process_info->pid = -ERROR_FILE_NOT_FOUND;
                return FALSE;
        }
-#ifdef TARGET_WIN32
-       /* Seems like our CreateProcess does not work as the windows one.
-        * This hack is needed to deal with paths containing spaces */
-       shell_path = NULL;
-       free_shell_path = FALSE;
-       if (cmd) {
-               gchar *newcmd, *tmp;
-               tmp = mono_string_to_utf8_checked (cmd, &error);
-               if (mono_error_set_pending_exception (&error)) {
-                       g_free (spath);
-                       return NULL;
-               }
-               newcmd = g_strdup_printf ("%s %s", spath, tmp);
-               cmd = mono_string_new_wrapper (newcmd);
-               g_free (tmp);
-               g_free (newcmd);
-       }
-       else {
-               cmd = mono_string_new_wrapper (spath);
-       }
-#else
-       shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
-#endif
-       g_free (spath);
 
        if (process_info->env_keys) {
                gint i, len; 
@@ -790,20 +824,10 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInf
        else
                dir = mono_string_chars (proc_start_info->working_directory);
 
-       if (process_info->username) {
-               logon_flags = process_info->load_user_profile ? LOGON_WITH_PROFILE : 0;
-               ret = CreateProcessWithLogonW (
-                       mono_string_chars (process_info->username),
-                       process_info->domain ? mono_string_chars (process_info->domain) : NULL,
-                       (const gunichar2 *)process_info->password, logon_flags, shell_path,
-                       cmd ? mono_string_chars (cmd) : NULL,
-                       creation_flags, env_vars, dir, &startinfo, &procinfo);
-       } else {
-               ret = CreateProcess (shell_path, cmd ? mono_string_chars (cmd): NULL, NULL, NULL, TRUE, creation_flags, env_vars, dir, &startinfo, &procinfo);
-       }
+       ret = mono_process_create_process (process_info, shell_path, cmd, creation_flags, env_vars, dir, &startinfo, &procinfo);
 
        g_free (env_vars);
-       if (free_shell_path)
+       if (shell_path != NULL)
                g_free (shell_path);
 
        if (ret) {
@@ -821,22 +845,24 @@ ves_icall_System_Diagnostics_Process_CreateProcess_internal (MonoProcessStartInf
        return ret;
 }
 
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
 MonoString *
 ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
 {
        MonoError error;
        MonoString *string;
+       gunichar2 name[MAX_PATH];
+       guint32 len;
        gboolean ok;
        HMODULE mod;
-       gunichar2 name[MAX_PATH];
        DWORD needed;
-       guint32 len;
-       
+
        ok = EnumProcessModules (process, &mod, sizeof(mod), &needed);
        if (!ok)
                return NULL;
        
        len = GetModuleBaseName (process, mod, name, MAX_PATH);
+
        if (len == 0)
                return NULL;
        
@@ -848,12 +874,13 @@ ves_icall_System_Diagnostics_Process_ProcessName_internal (HANDLE process)
        
        return string;
 }
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
 
+#ifndef HOST_WIN32
 /* Returns an array of pids */
 MonoArray *
 ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
 {
-#if !defined(HOST_WIN32)
        MonoError error;
        MonoArray *procs;
        gpointer *pidarray;
@@ -878,48 +905,8 @@ ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
        g_free (pidarray);
 
        return procs;
-#else
-       MonoError error;
-       MonoArray *procs;
-       gboolean ret;
-       DWORD needed;
-       int count;
-       guint32 *pids;
-
-       count = 512;
-       do {
-               pids = g_new0 (guint32, count);
-               ret = EnumProcesses (pids, count * sizeof (guint32), &needed);
-               if (ret == FALSE) {
-                       MonoException *exc;
-
-                       g_free (pids);
-                       pids = NULL;
-                       exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
-                       mono_set_pending_exception (exc);
-                       return NULL;
-               }
-               if (needed < (count * sizeof (guint32)))
-                       break;
-               g_free (pids);
-               pids = NULL;
-               count = (count * 3) / 2;
-       } while (TRUE);
-
-       count = needed / sizeof (guint32);
-       procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
-       if (mono_error_set_pending_exception (&error)) {
-               g_free (pids);
-               return NULL;
-       }
-
-       memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
-       g_free (pids);
-       pids = NULL;
-       
-       return procs;
-#endif
 }
+#endif /* !HOST_WIN32 */
 
 gint64
 ves_icall_System_Diagnostics_Process_GetProcessData (int pid, gint32 data_type, gint32 *error)