Merge pull request #4788 from xmcclure/if-winrt
[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 MonoString *
50 mono_icall_get_machine_name (void)
51 {
52         gunichar2 *buf;
53         guint32 len;
54         MonoString *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                 MonoError error;
62                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
63                 mono_error_set_pending_exception (&error);
64         }
65
66         g_free (buf);
67         return result;
68 }
69 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
70
71 int
72 mono_icall_get_platform (void)
73 {
74         /* Win32NT */
75         return 2;
76 }
77
78 MonoString *
79 mono_icall_get_new_line (void)
80 {
81         return mono_string_new (mono_domain_get (), "\r\n");
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 (void)
100 {
101         MonoError error;
102         MonoArray *names;
103         MonoDomain *domain;
104         MonoString *str;
105         WCHAR* env_strings;
106         WCHAR* env_string;
107         WCHAR* equal_str;
108         int n = 0;
109
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         if (mono_error_set_pending_exception (&error))
127                 return NULL;
128
129         if (env_strings) {
130                 n = 0;
131                 env_string = env_strings;
132                 while (*env_string != '\0') {
133                         /* weird case that MS seems to skip */
134                         if (*env_string != '=') {
135                                 equal_str = wcschr(env_string, '=');
136                                 g_assert(equal_str);
137                                 str = mono_string_new_utf16_checked (domain, env_string, (gint32)(equal_str - env_string), &error);
138                                 if (mono_error_set_pending_exception (&error))
139                                         return NULL;
140
141                                 mono_array_setref (names, n, str);
142                                 n++;
143                         }
144                         while (*env_string != '\0')
145                                 env_string++;
146                         env_string++;
147                 }
148
149                 FreeEnvironmentStrings (env_strings);
150         }
151
152         return names;
153 }
154
155 void
156 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
157 {
158         gunichar2 *utf16_name, *utf16_value;
159
160         utf16_name = mono_string_to_utf16 (name);
161         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
162                 SetEnvironmentVariable (utf16_name, NULL);
163                 g_free (utf16_name);
164                 return;
165         }
166
167         utf16_value = mono_string_to_utf16 (value);
168
169         SetEnvironmentVariable (utf16_name, utf16_value);
170
171         g_free (utf16_name);
172         g_free (utf16_value);
173 }
174
175 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
176 MonoString *
177 mono_icall_get_windows_folder_path (int folder)
178 {
179         #ifndef CSIDL_FLAG_CREATE
180                 #define CSIDL_FLAG_CREATE       0x8000
181         #endif
182
183         WCHAR path [MAX_PATH];
184         /* Create directory if no existing */
185         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
186                 int len = 0;
187                 while (path [len])
188                         ++ len;
189                 MonoError error;
190                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
191                 mono_error_set_pending_exception (&error);
192                 return res;
193         }
194         return mono_string_new (mono_domain_get (), "");
195 }
196 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
197
198 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
199 void
200 mono_icall_broadcast_setting_change (void)
201 {
202         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
203 }
204
205 gint32
206 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
207 {
208         return WaitForInputIdle (handle, milliseconds);
209 }
210 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
211
212 void
213 mono_icall_write_windows_debug_string (MonoString *message)
214 {
215         OutputDebugString (mono_string_chars (message));
216 }
217
218 #endif /* HOST_WIN32 */