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