[sgen] Fix verify-before-allocs.
[mono.git] / mono / metadata / process-windows.c
1 /*
2  * process-windows.c: Windows process support.
3  *
4  * Copyright 2016 Microsoft
5  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
6  */
7
8 #include <config.h>
9 #include <glib.h>
10
11 #if defined(HOST_WIN32)
12 #include <WinSock2.h>
13 #include <Windows.h>
14 #include "mono/metadata/process-windows-internals.h"
15
16 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
17 static inline gboolean
18 mono_process_win_enum_processes (DWORD *pids, DWORD count, DWORD *needed)
19 {
20         return EnumProcesses (pids, count, needed);
21 }
22 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
23
24 MonoArray *
25 ves_icall_System_Diagnostics_Process_GetProcesses_internal (void)
26 {
27         MonoError error;
28         MonoArray *procs;
29         gboolean ret;
30         DWORD needed;
31         int count;
32         DWORD *pids;
33
34         count = 512;
35         do {
36                 pids = g_new0 (DWORD, count);
37                 ret = mono_process_win_enum_processes (pids, count * sizeof (guint32), &needed);
38                 if (ret == FALSE) {
39                         MonoException *exc;
40
41                         g_free (pids);
42                         pids = NULL;
43                         exc = mono_get_exception_not_supported ("This system does not support EnumProcesses");
44                         mono_set_pending_exception (exc);
45                         return NULL;
46                 }
47                 if (needed < (count * sizeof (guint32)))
48                         break;
49                 g_free (pids);
50                 pids = NULL;
51                 count = (count * 3) / 2;
52         } while (TRUE);
53
54         count = needed / sizeof (guint32);
55         procs = mono_array_new_checked (mono_domain_get (), mono_get_int32_class (), count, &error);
56         if (mono_error_set_pending_exception (&error)) {
57                 g_free (pids);
58                 return NULL;
59         }
60
61         memcpy (mono_array_addr (procs, guint32, 0), pids, needed);
62         g_free (pids);
63         pids = NULL;
64
65         return procs;
66 }
67
68 gchar*
69 mono_process_quote_path (const gchar *path)
70 {
71         gchar *res = g_shell_quote (path);
72         gchar *q = res;
73         while (*q) {
74                 if (*q == '\'')
75                         *q = '\"';
76                 q++;
77         }
78         return res;
79 }
80
81 gchar*
82 mono_process_unquote_application_name (gchar *appname)
83 {
84         size_t len = strlen (appname);
85         if (len) {
86                 if (appname[len-1] == '\"')
87                         appname[len-1] = '\0';
88                 if (appname[0] == '\"')
89                         appname++;
90         }
91
92         return appname;
93 }
94
95 gboolean
96 mono_process_get_shell_arguments (MonoProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
97 {
98         gchar           *spath = NULL;
99         gchar           *new_cmd, *cmd_utf8;
100         MonoError       mono_error;
101
102         *shell_path = NULL;
103         *cmd = proc_start_info->arguments;
104
105         mono_process_complete_path (mono_string_chars (proc_start_info->filename), &spath);
106         if (spath != NULL) {
107                 /* Seems like our CreateProcess does not work as the windows one.
108                  * This hack is needed to deal with paths containing spaces */
109                 if (*cmd) {
110                         cmd_utf8 = mono_string_to_utf8_checked (*cmd, &mono_error);
111                         if (!mono_error_set_pending_exception (&mono_error)) {
112                                 new_cmd = g_strdup_printf ("%s %s", spath, cmd_utf8);
113                                 *cmd = mono_string_new_wrapper (new_cmd);
114                                 g_free (cmd_utf8);
115                                 g_free (new_cmd);
116                         } else {
117                                 *cmd = NULL;
118                         }
119                 }
120                 else {
121                         *cmd = mono_string_new_wrapper (spath);
122                 }
123
124                 g_free (spath);
125         }
126
127         return (*cmd != NULL) ? TRUE : FALSE;
128 }
129 #endif /* HOST_WIN32 */