1 /**
2  * \file
3  * Windows marshal 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 <objbase.h>
15 #include "mono/metadata/marshal-windows-internals.h"
16 
17 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
18 void*
mono_marshal_alloc_hglobal(size_t size)19 mono_marshal_alloc_hglobal (size_t size)
20 {
21 	return GlobalAlloc (GMEM_FIXED, size);
22 }
23 
24 gpointer
mono_marshal_realloc_hglobal(gpointer ptr,size_t size)25 mono_marshal_realloc_hglobal (gpointer ptr, size_t size)
26 {
27 	return GlobalReAlloc (ptr, size, GMEM_MOVEABLE);
28 }
29 
30 void
mono_marshal_free_hglobal(gpointer ptr)31 mono_marshal_free_hglobal (gpointer ptr)
32 {
33 	GlobalFree (ptr);
34 	return;
35 }
36 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
37 
38 void*
mono_marshal_alloc_co_task_mem(size_t size)39 mono_marshal_alloc_co_task_mem (size_t size)
40 {
41 	return CoTaskMemAlloc (size);
42 }
43 
44 void
mono_marshal_free_co_task_mem(void * ptr)45 mono_marshal_free_co_task_mem (void *ptr)
46 {
47 	CoTaskMemFree (ptr);
48 	return;
49 }
50 
51 gpointer
mono_marshal_realloc_co_task_mem(gpointer ptr,size_t size)52 mono_marshal_realloc_co_task_mem (gpointer ptr, size_t size)
53 {
54 	return CoTaskMemRealloc (ptr, size);
55 }
56 
57 gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi(MonoString * string)58 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString *string)
59 {
60 	MonoError error;
61 	char* tres, *ret;
62 	size_t len;
63 	tres = mono_string_to_utf8_checked (string, &error);
64 	if (mono_error_set_pending_exception (&error))
65 		return NULL;
66 	if (!tres)
67 		return tres;
68 
69 	/*
70 	 * mono_string_to_utf8_checked() returns a memory area at least as large as the size of the
71 	 * MonoString, even if it contains NULL characters. The copy we allocate here has to be equally
72 	 * large.
73 	 */
74 	len = MAX (strlen (tres) + 1, string->length);
75 	ret = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal ((gpointer)len);
76 	memcpy (ret, tres, len);
77 	g_free (tres);
78 	return ret;
79 }
80 
81 gpointer
ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni(MonoString * string)82 ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni (MonoString *string)
83 {
84 	if (string == NULL)
85 		return NULL;
86 	else {
87 		size_t len = ((mono_string_length (string) + 1) * 2);
88 		gunichar2 *res = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal ((gpointer)len);
89 
90 		memcpy (res, mono_string_chars (string), mono_string_length (string) * 2);
91 		res [mono_string_length (string)] = 0;
92 		return res;
93 	}
94 }
95 
96 gpointer
mono_string_to_utf8str(MonoString * s)97 mono_string_to_utf8str (MonoString *s)
98 {
99 	char *as, *tmp;
100 	glong len;
101 	GError *error = NULL;
102 
103 	if (s == NULL)
104 		return NULL;
105 
106 	if (!s->length) {
107 		as = CoTaskMemAlloc (1);
108 		as [0] = '\0';
109 		return as;
110 	}
111 
112 	tmp = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, &len, &error);
113 	if (error) {
114 		MonoException *exc = mono_get_exception_argument ("string", error->message);
115 		g_error_free (error);
116 		mono_set_pending_exception (exc);
117 		return NULL;
118 	} else {
119 		as = CoTaskMemAlloc (len + 1);
120 		memcpy (as, tmp, len + 1);
121 		g_free (tmp);
122 		return as;
123 	}
124 }
125 
126 #endif /* HOST_WIN32 */
127