Merge pull request #3988 from lambdageek/dev-handles-srmodule
[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 (MonoReflectionModuleHandle module)
39 {
40         MonoImage *image = MONO_HANDLE_GETVAL (module, image);
41         if (image && image->is_module_handle)
42                 return image->raw_data;
43
44         return (gpointer) (-1);
45 }
46
47 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
48 MonoString *
49 mono_icall_get_machine_name (void)
50 {
51         gunichar2 *buf;
52         guint32 len;
53         MonoString *result;
54
55         len = MAX_COMPUTERNAME_LENGTH + 1;
56         buf = g_new (gunichar2, len);
57
58         result = NULL;
59         if (GetComputerName (buf, (PDWORD) &len)) {
60                 MonoError error;
61                 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
62                 mono_error_set_pending_exception (&error);
63         }
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 MonoString *
78 mono_icall_get_new_line (void)
79 {
80         return mono_string_new (mono_domain_get (), "\r\n");
81 }
82
83 MonoBoolean
84 mono_icall_is_64bit_os (void)
85 {
86 #if SIZEOF_VOID_P == 8
87         return TRUE;
88 #else
89         gboolean isWow64Process = FALSE;
90         if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
91                 return (MonoBoolean)isWow64Process;
92         }
93         return FALSE;
94 #endif
95 }
96
97 MonoArray *
98 mono_icall_get_environment_variable_names (void)
99 {
100         MonoError error;
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         env_strings = GetEnvironmentStrings();
110
111         if (env_strings) {
112                 env_string = env_strings;
113                 while (*env_string != '\0') {
114                 /* weird case that MS seems to skip */
115                         if (*env_string != '=')
116                                 n++;
117                         while (*env_string != '\0')
118                                 env_string++;
119                         env_string++;
120                 }
121         }
122
123         domain = mono_domain_get ();
124         names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
125         if (mono_error_set_pending_exception (&error))
126                 return 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 (mono_error_set_pending_exception (&error))
138                                         return NULL;
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                 FreeEnvironmentStrings (env_strings);
149         }
150
151         return names;
152 }
153
154 void
155 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
156 {
157         gunichar2 *utf16_name, *utf16_value;
158
159         utf16_name = mono_string_to_utf16 (name);
160         if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
161                 SetEnvironmentVariable (utf16_name, NULL);
162                 g_free (utf16_name);
163                 return;
164         }
165
166         utf16_value = mono_string_to_utf16 (value);
167
168         SetEnvironmentVariable (utf16_name, utf16_value);
169
170         g_free (utf16_name);
171         g_free (utf16_value);
172 }
173
174 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
175 MonoString *
176 mono_icall_get_windows_folder_path (int folder)
177 {
178         #ifndef CSIDL_FLAG_CREATE
179                 #define CSIDL_FLAG_CREATE       0x8000
180         #endif
181
182         WCHAR path [MAX_PATH];
183         /* Create directory if no existing */
184         if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
185                 int len = 0;
186                 while (path [len])
187                         ++ len;
188                 MonoError error;
189                 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
190                 mono_error_set_pending_exception (&error);
191                 return res;
192         }
193         return mono_string_new (mono_domain_get (), "");
194 }
195 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
196
197 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
198 void
199 mono_icall_broadcast_setting_change (void)
200 {
201         SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
202 }
203
204 gint32
205 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
206 {
207         return WaitForInputIdle (handle, milliseconds);
208 }
209 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
210
211 void
212 mono_icall_write_windows_debug_string (MonoString *message)
213 {
214         OutputDebugString (mono_string_chars (message));
215 }
216
217 #endif /* HOST_WIN32 */