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