Merge pull request #3716 from vargaz/unbox-stobj-null
[mono.git] / mono / metadata / icall-windows.c
1 /*
2  * icall-windows.c: Windows icall 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 #include <config.h>
8 #include <glib.h>
9
10 #if defined(HOST_WIN32)
11 #include <WinSock2.h>
12 #include <Windows.h>
13 #include "mono/metadata/icall-windows-internals.h"
14
15 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
16 #include <shlobj.h>
17 #endif
18
19 void
20 mono_icall_make_platform_path (gchar *path)
21 {
22         for (size_t i = strlen (path); i > 0; i--)
23                 if (path [i-1] == '\\')
24                         path [i-1] = '/';
25 }
26
27 const gchar *
28 mono_icall_get_file_path_prefix (const gchar *path)
29 {
30         if (*path == '/' && *(path + 1) == '/') {
31                 return "file:";
32         } else {
33                 return "file:///";
34         }
35 }
36
37 gpointer
38 mono_icall_module_get_hinstance (MonoReflectionModule *module)
39 {
40         if (module->image && module->image->is_module_handle)
41                 return module->image->raw_data;
42
43         return (gpointer) (-1);
44 }
45
46 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
47 MonoString *
48 mono_icall_get_machine_name (void)
49 {
50         gunichar2 *buf;
51         guint32 len;
52         MonoString *result;
53
54         len = MAX_COMPUTERNAME_LENGTH + 1;
55         buf = g_new (gunichar2, len);
56
57         result = NULL;
58         if (GetComputerName (buf, (PDWORD) &len)) {
59                 MonoError error;
60                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
61                 mono_error_set_pending_exception (&error);
62         }
63
64         g_free (buf);
65         return result;
66 }
67 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
68
69 int
70 mono_icall_get_platform (void)
71 {
72         /* Win32NT */
73         return 2;
74 }
75
76 MonoString *
77 mono_icall_get_new_line (void)
78 {
79         return mono_string_new (mono_domain_get (), "\r\n");
80 }
81
82 MonoBoolean
83 mono_icall_is_64bit_os (void)
84 {
85 #if SIZEOF_VOID_P == 8
86         return TRUE;
87 #else
88         gboolean isWow64Process = FALSE;
89         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
90                 return (MonoBoolean)isWow64Process;
91         }
92         return FALSE;
93 #endif
94 }
95
96 MonoArray *
97 mono_icall_get_environment_variable_names (void)
98 {
99         MonoError error;
100         MonoArray *names;
101         MonoDomain *domain;
102         MonoString *str;
103         WCHAR* env_strings;
104         WCHAR* env_string;
105         WCHAR* equal_str;
106         int n = 0;
107
108         env_strings = GetEnvironmentStrings();
109
110         if (env_strings) {
111                 env_string = env_strings;
112                 while (*env_string != '\0') {
113                 /* weird case that MS seems to skip */
114                         if (*env_string != '=')
115                                 n++;
116                         while (*env_string != '\0')
117                                 env_string++;
118                         env_string++;
119                 }
120         }
121
122         domain = mono_domain_get ();
123         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
124         if (mono_error_set_pending_exception (&error))
125                 return NULL;
126
127         if (env_strings) {
128                 n = 0;
129                 env_string = env_strings;
130                 while (*env_string != '\0') {
131                         /* weird case that MS seems to skip */
132                         if (*env_string != '=') {
133                                 equal_str = wcschr(env_string, '=');
134                                 g_assert(equal_str);
135                                 str = mono_string_new_utf16_checked (domain, env_string, (gint32)(equal_str - env_string), &error);
136                                 if (mono_error_set_pending_exception (&error))
137                                         return NULL;
138
139                                 mono_array_setref (names, n, str);
140                                 n++;
141                         }
142                         while (*env_string != '\0')
143                                 env_string++;
144                         env_string++;
145                 }
146
147                 FreeEnvironmentStrings (env_strings);
148         }
149
150         return names;
151 }
152
153 void
154 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
155 {
156         gunichar2 *utf16_name, *utf16_value;
157
158         utf16_name = mono_string_to_utf16 (name);
159         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
160                 SetEnvironmentVariable (utf16_name, NULL);
161                 g_free (utf16_name);
162                 return;
163         }
164
165         utf16_value = mono_string_to_utf16 (value);
166
167         SetEnvironmentVariable (utf16_name, utf16_value);
168
169         g_free (utf16_name);
170         g_free (utf16_value);
171 }
172
173 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
174 MonoString *
175 mono_icall_get_windows_folder_path (int folder)
176 {
177         #ifndef CSIDL_FLAG_CREATE
178                 #define CSIDL_FLAG_CREATE       0x8000
179         #endif
180
181         WCHAR path [MAX_PATH];
182         /* Create directory if no existing */
183         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
184                 int len = 0;
185                 while (path [len])
186                         ++ len;
187                 MonoError error;
188                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
189                 mono_error_set_pending_exception (&error);
190                 return res;
191         }
192         return mono_string_new (mono_domain_get (), "");
193 }
194 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
195
196 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
197 void
198 mono_icall_broadcast_setting_change (void)
199 {
200         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
201 }
202
203 gint32
204 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
205 {
206         return WaitForInputIdle (handle, milliseconds);
207 }
208 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
209
210 void
211 mono_icall_write_windows_debug_string (MonoString *message)
212 {
213         OutputDebugString (mono_string_chars (message));
214 }
215
216 MonoBoolean
217 mono_icall_close_process (gpointer handle)
218 {
219         return (MonoBoolean)(CloseHandle (handle));
220 }
221 #endif /* HOST_WIN32 */