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
mono_icall_make_platform_path(gchar * path)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 *
mono_icall_get_file_path_prefix(const gchar * path)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
mono_icall_module_get_hinstance(MonoReflectionModuleHandle module)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
mono_icall_get_machine_name(MonoError * error)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
mono_icall_get_platform(void)71 mono_icall_get_platform (void)
72 {
73 /* Win32NT */
74 return 2;
75 }
76
77 MonoStringHandle
mono_icall_get_new_line(MonoError * error)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
mono_icall_is_64bit_os(void)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 *
mono_icall_get_environment_variable_names(MonoError * error)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 goto_if_nok (error, cleanup);
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 }
148
149 cleanup:
150 if (env_strings)
151 FreeEnvironmentStrings (env_strings);
152 if (!is_ok (error))
153 return NULL;
154 return names;
155 }
156
157 void
mono_icall_set_environment_variable(MonoString * name,MonoString * value)158 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
159 {
160 gunichar2 *utf16_name, *utf16_value;
161
162 utf16_name = mono_string_to_utf16 (name);
163 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
164 SetEnvironmentVariable (utf16_name, NULL);
165 g_free (utf16_name);
166 return;
167 }
168
169 utf16_value = mono_string_to_utf16 (value);
170
171 SetEnvironmentVariable (utf16_name, utf16_value);
172
173 g_free (utf16_name);
174 g_free (utf16_value);
175 }
176
177 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
178 MonoStringHandle
mono_icall_get_windows_folder_path(int folder,MonoError * error)179 mono_icall_get_windows_folder_path (int folder, MonoError *error)
180 {
181 error_init (error);
182 #ifndef CSIDL_FLAG_CREATE
183 #define CSIDL_FLAG_CREATE 0x8000
184 #endif
185
186 WCHAR path [MAX_PATH];
187 /* Create directory if no existing */
188 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
189 int len = 0;
190 while (path [len])
191 ++ len;
192 return mono_string_new_utf16_handle (mono_domain_get (), path, len, error);
193 }
194 return mono_string_new_handle (mono_domain_get (), "", error);
195 }
196 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
197
198 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
199 MonoBoolean
mono_icall_broadcast_setting_change(MonoError * error)200 mono_icall_broadcast_setting_change (MonoError *error)
201 {
202 error_init (error);
203 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
204 return TRUE;
205 }
206
207 gint32
mono_icall_wait_for_input_idle(gpointer handle,gint32 milliseconds)208 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
209 {
210 return WaitForInputIdle (handle, milliseconds);
211 }
212 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
213
214 void
mono_icall_write_windows_debug_string(MonoString * message)215 mono_icall_write_windows_debug_string (MonoString *message)
216 {
217 OutputDebugString (mono_string_chars (message));
218 }
219
220 #endif /* HOST_WIN32 */
221