[jit] In native-to-managed wrappers, emit the initlocals code for vtypes after the...
[mono.git] / mono / tests / libtest.c
1 #include <config.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <glib.h>
6 #include <gmodule.h>
7 #include <errno.h>
8 #include <time.h>
9 #include <math.h>
10
11 #ifdef WIN32
12 #include <windows.h>
13 #include "initguid.h"
14 #else
15 #include <pthread.h>
16 #endif
17
18 #ifdef WIN32
19 #define STDCALL __stdcall
20 #else
21 #define STDCALL
22 #endif
23
24 #ifdef __GNUC__
25 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
26 #endif
27
28 #ifdef WIN32
29 extern __declspec(dllimport) void __stdcall CoTaskMemFree(void *ptr);
30 #endif
31
32 typedef int (STDCALL *SimpleDelegate) (int a);
33
34 #if defined(WIN32) && defined (_MSC_VER)
35 #define LIBTEST_API __declspec(dllexport)
36 #elif defined(__GNUC__)
37 #define LIBTEST_API  __attribute__ ((__visibility__ ("default")))
38 #else
39 #define LIBTEST_API
40 #endif
41
42 static void marshal_free (void *ptr)
43 {
44 #ifdef WIN32
45         CoTaskMemFree (ptr);
46 #else
47         g_free (ptr);
48 #endif
49 }
50
51 static void* marshal_alloc (gsize size)
52 {
53 #ifdef WIN32
54         return CoTaskMemAlloc (size);
55 #else
56         return g_malloc (size);
57 #endif
58 }
59
60 static void* marshal_alloc0 (gsize size)
61 {
62 #ifdef WIN32
63         void* ptr = CoTaskMemAlloc (size);
64         memset(ptr, 0, size);
65         return ptr;
66 #else
67         return g_malloc0 (size);
68 #endif
69 }
70
71 static char* marshal_strdup (const char *str)
72 {
73 #ifdef WIN32
74         int len;
75         char *buf;
76
77         if (!str)
78                 return NULL;
79
80         len = strlen (str);
81         buf = (char *) CoTaskMemAlloc (len + 1);
82         return strcpy (buf, str);
83 #else
84         return g_strdup (str);
85 #endif
86 }
87
88 static gunichar2* marshal_bstr_alloc(const gchar* str)
89 {
90 #ifdef WIN32
91         gunichar2* ret = NULL;
92         gunichar2* temp = NULL;
93         temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
94         ret = SysAllocString (temp);
95         g_free (temp);
96         return ret;
97 #else
98         gchar* ret = NULL;
99         int slen = strlen (str);
100         gunichar2* temp;
101         /* allocate len + 1 utf16 characters plus 4 byte integer for length*/
102         ret = (gchar *)g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32));
103         if (ret == NULL)
104                 return NULL;
105         temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
106         memcpy (ret + sizeof(guint32), temp, slen * sizeof(gunichar2));
107         * ((guint32 *) ret) = slen * sizeof(gunichar2);
108         ret [4 + slen * sizeof(gunichar2)] = 0;
109         ret [5 + slen * sizeof(gunichar2)] = 0;
110
111         return (gunichar2*)(ret + 4);
112 #endif
113 }
114
115 #define marshal_new0(type,size)       ((type *) marshal_alloc0 (sizeof (type)* (size)))
116
117 LIBTEST_API int STDCALL
118 mono_cominterop_is_supported (void)
119 {
120 #if defined(TARGET_X86) || defined(TARGET_AMD64)
121         return 1;
122 #endif
123         return 0;
124 }
125
126 LIBTEST_API unsigned short* STDCALL
127 test_lpwstr_marshal (unsigned short* chars, long length)
128 {
129         int i = 0;
130         unsigned short *res;
131
132         res = (unsigned short *)marshal_alloc (2 * (length + 1));
133
134         // printf("test_lpwstr_marshal()\n");
135         
136         while ( i < length ) {
137                 // printf("X|%u|\n", chars[i]);
138                 res [i] = chars[i];
139                 i++;
140         }
141
142         res [i] = 0;
143
144         return res;
145 }
146
147
148 LIBTEST_API void STDCALL
149 test_lpwstr_marshal_out (unsigned short** chars)
150 {
151         int i = 0;
152         const char abc[] = "ABC";
153         glong len = strlen(abc);
154
155         *chars = (unsigned short *)marshal_alloc (2 * (len + 1));
156         
157         while ( i < len ) {
158                 (*chars) [i] = abc[i];
159                 i++;
160         }
161
162         (*chars) [i] = 0;
163 }
164
165 typedef struct {
166         int b;
167         int a;
168         int c;
169 } union_test_1_type;
170
171 LIBTEST_API int STDCALL  
172 mono_union_test_1 (union_test_1_type u1) {
173         // printf ("Got values %d %d %d\n", u1.b, u1.a, u1.c);
174         return u1.a + u1.b + u1.c;
175 }
176
177 LIBTEST_API int STDCALL  
178 mono_return_int (int a) {
179         // printf ("Got value %d\n", a);
180         return a;
181 }
182
183 LIBTEST_API float STDCALL  
184 mono_test_marshal_pass_return_float (float f) {
185         return f + 1.0;
186 }
187
188 struct ss
189 {
190         int i;
191 };
192
193 LIBTEST_API int STDCALL 
194 mono_return_int_ss (struct ss a) {
195         // printf ("Got value %d\n", a.i);
196         return a.i;
197 }
198
199 LIBTEST_API struct ss STDCALL
200 mono_return_ss (struct ss a) {
201         // printf ("Got value %d\n", a.i);
202         a.i++;
203         return a;
204 }
205
206 struct sc1
207 {
208         char c[1];
209 };
210
211 LIBTEST_API struct sc1 STDCALL
212 mono_return_sc1 (struct sc1 a) {
213         // printf ("Got value %d\n", a.c[0]);
214         a.c[0]++;
215         return a;
216 }
217
218
219 struct sc3
220 {
221         char c[3];
222 };
223
224 LIBTEST_API struct sc3 STDCALL 
225 mono_return_sc3 (struct sc3 a) {
226         // printf ("Got values %d %d %d\n", a.c[0], a.c[1], a.c[2]);
227         a.c[0]++;
228         a.c[1] += 2;
229         a.c[2] += 3;
230         return a;
231 }
232
233 struct sc5
234 {
235         char c[5];
236 };
237
238 LIBTEST_API struct sc5 STDCALL 
239 mono_return_sc5 (struct sc5 a) {
240         // printf ("Got values %d %d %d %d %d\n", a.c[0], a.c[1], a.c[2], a.c[3], a.c[4]);
241         a.c[0]++;
242         a.c[1] += 2;
243         a.c[2] += 3;
244         a.c[3] += 4;
245         a.c[4] += 5;
246         return a;
247 }
248
249 union su
250 {
251         int i1;
252         int i2;
253 };
254
255 LIBTEST_API int STDCALL  
256 mono_return_int_su (union su a) {
257         // printf ("Got value %d\n", a.i1);
258         return a.i1;
259 }
260
261 struct FI {
262         float f1;
263         float f2;
264         float f3;
265 };
266
267 struct NestedFloat {
268         struct FI fi;
269         float f4;
270 };
271
272 LIBTEST_API struct NestedFloat STDCALL
273 mono_return_nested_float (void)
274 {
275         struct NestedFloat f;
276         f.fi.f1 = 1.0;
277         f.fi.f2 = 2.0;
278         f.fi.f3 = 3.0;
279         f.f4 = 4.0;
280         return f;
281 }
282
283 LIBTEST_API int STDCALL  
284 mono_test_many_int_arguments (int a, int b, int c, int d, int e,
285                                                           int f, int g, int h, int i, int j);
286 LIBTEST_API short STDCALL 
287 mono_test_many_short_arguments (short a, short b, short c, short d, short e,
288                                                                 short f, short g, short h, short i, short j);
289 LIBTEST_API char STDCALL 
290 mono_test_many_char_arguments (char a, char b, char c, char d, char e,
291                                                            char f, char g, char h, char i, char j);
292
293 LIBTEST_API int STDCALL 
294 mono_test_many_int_arguments (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j)
295 {
296         return a + b + c + d + e + f + g + h + i + j;
297 }
298
299 LIBTEST_API short STDCALL 
300 mono_test_many_short_arguments (short a, short b, short c, short d, short e, short f, short g, short h, short i, short j)
301 {
302         return a + b + c + d + e + f + g + h + i + j;
303 }
304
305 LIBTEST_API char STDCALL 
306 mono_test_many_byte_arguments (char a, char b, char c, char d, char e, char f, char g, char h, char i, char j)
307 {
308         return a + b + c + d + e + f + g + h + i + j;
309 }
310
311 LIBTEST_API float STDCALL 
312 mono_test_many_float_arguments (float a, float b, float c, float d, float e, float f, float g, float h, float i, float j)
313 {
314         return a + b + c + d + e + f + g + h + i + j;
315 }
316
317 LIBTEST_API double STDCALL 
318 mono_test_many_double_arguments (double a, double b, double c, double d, double e, double f, double g, double h, double i, double j)
319 {
320         return a + b + c + d + e + f + g + h + i + j;
321 }
322
323 LIBTEST_API double STDCALL 
324 mono_test_split_double_arguments (double a, double b, float c, double d, double e)
325 {
326         return a + b + c + d + e;
327 }
328
329 LIBTEST_API int STDCALL 
330 mono_test_puts_static (char *s)
331 {
332         // printf ("TEST %s\n", s);
333         return 1;
334 }
335
336 typedef int (STDCALL *SimpleDelegate3) (int a, int b);
337
338 LIBTEST_API int STDCALL 
339 mono_invoke_delegate (SimpleDelegate3 delegate)
340 {
341         int res;
342
343         // printf ("start invoke %p\n", delegate);
344
345         res = delegate (2, 3);
346
347         // printf ("end invoke\n");
348
349         return res;
350 }
351
352 LIBTEST_API int STDCALL
353 mono_invoke_simple_delegate (SimpleDelegate d)
354 {
355         return d (4);
356 }
357
358 LIBTEST_API int STDCALL  
359 mono_test_marshal_char (short a1)
360 {
361         if (a1 == 'a')
362                 return 0;
363         
364         return 1;
365 }
366
367 LIBTEST_API void STDCALL
368 mono_test_marshal_char_array (gunichar2 *s)
369 {
370         const char m[] = "abcdef";
371         gunichar2* s2;
372         glong len;
373
374         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
375         
376         len = (len * 2) + 2;
377         memcpy (s, s2, len);
378
379         g_free (s2);
380 }
381
382 LIBTEST_API int STDCALL
383 mono_test_marshal_ansi_char_array (char *s)
384 {
385         const char m[] = "abcdef";
386
387         if (strncmp ("qwer", s, 4))
388                 return 1;
389
390         memcpy (s, m, sizeof (m));
391         return 0;
392 }
393
394 LIBTEST_API int STDCALL
395 mono_test_marshal_unicode_char_array (gunichar2 *s)
396 {
397         const char m[] = "abcdef";
398         const char expected[] = "qwer";
399         gunichar2 *s1, *s2;
400         glong len1, len2;
401
402         s1 = g_utf8_to_utf16 (m, -1, NULL, &len1, NULL);
403         s2 = g_utf8_to_utf16 (expected, -1, NULL, &len2, NULL);
404         len1 = (len1 * 2);
405         len2 = (len2 * 2);
406
407         if (memcmp (s, s2, len2))
408                 return 1;
409
410         memcpy (s, s1, len1);
411         return 0;
412 }
413
414 LIBTEST_API int STDCALL 
415 mono_test_empty_pinvoke (int i)
416 {
417         return i;
418 }
419
420 LIBTEST_API int STDCALL  
421 mono_test_marshal_bool_byref (int a, int *b, int c)
422 {
423     int res = *b;
424
425         *b = 1;
426
427         return res;
428 }
429
430 LIBTEST_API int STDCALL 
431 mono_test_marshal_bool_in_as_I1_U1 (char bTrue, char bFalse)
432 {
433         if (!bTrue)
434                 return 1;
435         if (bFalse)
436                 return 2;
437         return 0;
438 }
439
440 LIBTEST_API int STDCALL 
441 mono_test_marshal_bool_out_as_I1_U1 (char* bTrue, char* bFalse)
442 {
443         if (!bTrue || !bFalse)
444                 return 3;
445
446         *bTrue = 1;
447         *bFalse = 0;
448
449         return 0;
450 }
451
452 LIBTEST_API int STDCALL 
453 mono_test_marshal_bool_ref_as_I1_U1 (char* bTrue, char* bFalse)
454 {
455         if (!bTrue || !bFalse)
456                 return 4;
457
458         if (!(*bTrue))
459                 return 5;
460         if (*bFalse)
461                 return 6;
462
463         *bFalse = 1;
464         *bTrue = 0;
465
466         return 0;
467 }
468
469 LIBTEST_API int STDCALL  
470 mono_test_marshal_array (int *a1)
471 {
472         int i, sum = 0;
473
474         for (i = 0; i < 50; i++)
475                 sum += a1 [i];
476         
477         return sum;
478 }
479
480 LIBTEST_API int STDCALL  
481 mono_test_marshal_inout_array (int *a1)
482 {
483         int i, sum = 0;
484
485         for (i = 0; i < 50; i++) {
486                 sum += a1 [i];
487                 a1 [i] = 50 - a1 [i];
488         }
489         
490         return sum;
491 }
492
493 LIBTEST_API int /* cdecl */
494 mono_test_marshal_inout_array_cdecl (int *a1)
495 {
496         return mono_test_marshal_inout_array (a1);
497 }
498
499 LIBTEST_API int STDCALL  
500 mono_test_marshal_out_array (int *a1)
501 {
502         int i;
503
504         for (i = 0; i < 50; i++) {
505                 a1 [i] = i;
506         }
507         
508         return 0;
509 }
510
511 LIBTEST_API int STDCALL
512 mono_test_marshal_out_byref_array_out_size_param (int **out_arr, int *out_len)
513 {
514         int *arr;
515         int i, len;
516
517         len = 4;
518         arr = (gint32 *)marshal_alloc (sizeof (gint32) * len);
519         for (i = 0; i < len; ++i)
520                 arr [i] = i;
521         *out_arr = arr;
522         *out_len = len;
523
524         return 0;
525 }
526
527 LIBTEST_API int STDCALL
528 mono_test_marshal_out_lparray_out_size_param (int *arr, int *out_len)
529 {
530         int i, len;
531
532         len = 4;
533         for (i = 0; i < len; ++i)
534                 arr [i] = i;
535         *out_len = len;
536
537         return 0;
538 }
539
540 LIBTEST_API int STDCALL  
541 mono_test_marshal_inout_nonblittable_array (gunichar2 *a1)
542 {
543         int i, sum = 0;
544
545         for (i = 0; i < 10; i++) {
546                 a1 [i] = 'F';
547         }
548         
549         return sum;
550 }
551
552 typedef struct {
553         int a;
554         int b;
555         int c;
556         const char *d;
557         gunichar2 *d2;
558 } simplestruct;
559
560 typedef struct {
561         double x;
562         double y;
563 } point;
564
565 LIBTEST_API simplestruct STDCALL 
566 mono_test_return_vtype (int i)
567 {
568         simplestruct res;
569         static gunichar2 test2 [] = { 'T', 'E', 'S', 'T', '2', 0 };
570
571         res.a = 0;
572         res.b = 1;
573         res.c = 0;
574         res.d = "TEST";
575         res.d2 = test2;
576
577         return res;
578 }
579
580 LIBTEST_API void STDCALL
581 mono_test_delegate_struct (void)
582 {
583         // printf ("TEST\n");
584 }
585
586 typedef char* (STDCALL *ReturnStringDelegate) (const char *s);
587
588 LIBTEST_API char * STDCALL 
589 mono_test_return_string (ReturnStringDelegate func)
590 {
591         char *res;
592
593         // printf ("mono_test_return_string\n");
594
595         res = func ("TEST");
596         marshal_free (res);
597
598         // printf ("got string: %s\n", res);
599         return marshal_strdup ("12345");
600 }
601
602 typedef int (STDCALL *RefVTypeDelegate) (int a, simplestruct *ss, int b);
603
604 LIBTEST_API int STDCALL 
605 mono_test_ref_vtype (int a, simplestruct *ss, int b, RefVTypeDelegate func)
606 {
607         if (a == 1 && b == 2 && ss->a == 0 && ss->b == 1 && ss->c == 0 &&
608             !strcmp (ss->d, "TEST1")) {
609                 ss->a = 1;
610                 ss->b = 0;
611                 ss->c = 1;
612                 ss->d = "TEST2";
613
614                 return func (a, ss, b);
615         }
616
617         return 1;
618 }
619
620 typedef int (STDCALL *OutVTypeDelegate) (int a, simplestruct *ss, int b);
621
622 LIBTEST_API int STDCALL 
623 mono_test_marshal_out_struct (int a, simplestruct *ss, int b, OutVTypeDelegate func)
624 {
625         /* Check that the input pointer is ignored */
626         ss->d = (const char *)0x12345678;
627
628         func (a, ss, b);
629
630         if (ss->a && ss->b && ss->c && !strcmp (ss->d, "TEST3"))
631                 return 0;
632         else
633                 return 1;
634 }
635
636 typedef int (STDCALL *InVTypeDelegate) (int a, simplestruct *ss, int b);
637
638 LIBTEST_API int STDCALL 
639 mono_test_marshal_in_struct (int a, simplestruct *ss, int b, InVTypeDelegate func)
640 {
641         simplestruct ss2;
642         int res;
643
644         memcpy (&ss2, ss, sizeof (simplestruct));
645
646         res = func (a, ss, b);
647         if (res) {
648                 printf ("mono_test_marshal_in_struct () failed: %d\n", res);
649                 return 1;
650         }
651
652         /* Check that no modifications is made to the struct */
653         if (ss2.a == ss->a && ss2.b == ss->b && ss2.c == ss->c && ss2.d == ss->d)
654                 return 0;
655         else
656                 return 1;
657 }
658
659 typedef struct {
660         int a;
661         SimpleDelegate func, func2, func3;
662 } DelegateStruct;
663
664 LIBTEST_API DelegateStruct STDCALL 
665 mono_test_marshal_delegate_struct (DelegateStruct ds)
666 {
667         DelegateStruct res;
668
669         res.a = ds.func (ds.a) + ds.func2 (ds.a) + (ds.func3 == NULL ? 0 : 1);
670         res.func = ds.func;
671         res.func2 = ds.func2;
672         res.func3 = NULL;
673
674         return res;
675 }
676
677 LIBTEST_API int STDCALL  
678 mono_test_marshal_struct (simplestruct ss)
679 {
680         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
681             !strcmp (ss.d, "TEST"))
682                 return 0;
683
684         return 1;
685 }
686
687 LIBTEST_API int STDCALL 
688 mono_test_marshal_byref_struct (simplestruct *ss, int a, int b, int c, char *d)
689 {
690         gboolean res = (ss->a == a && ss->b == b && ss->c == c && strcmp (ss->d, d) == 0);
691
692         marshal_free ((char*)ss->d);
693
694         ss->a = !ss->a;
695         ss->b = !ss->b;
696         ss->c = !ss->c;
697         ss->d = marshal_strdup ("DEF");
698
699         return res ? 0 : 1;
700 }
701
702 typedef struct {
703         int a;
704         int b;
705         int c;
706         char *d;
707         unsigned char e;
708         double f;
709         unsigned char g;
710         guint64 h;
711 } simplestruct2;
712
713 LIBTEST_API int STDCALL 
714 mono_test_marshal_struct2 (simplestruct2 ss)
715 {
716         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
717             !strcmp (ss.d, "TEST") && 
718             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
719                 return 0;
720
721         return 1;
722 }
723
724 /* on HP some of the struct should be on the stack and not in registers */
725 LIBTEST_API int STDCALL 
726 mono_test_marshal_struct2_2 (int i, int j, int k, simplestruct2 ss)
727 {
728         if (i != 10 || j != 11 || k != 12)
729                 return 1;
730         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
731             !strcmp (ss.d, "TEST") && 
732             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
733                 return 0;
734
735         return 1;
736 }
737
738 LIBTEST_API int STDCALL  
739 mono_test_marshal_lpstruct (simplestruct *ss)
740 {
741         if (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
742             !strcmp (ss->d, "TEST"))
743                 return 0;
744
745         return 1;
746 }
747
748 LIBTEST_API int STDCALL  
749 mono_test_marshal_lpstruct_blittable (point *p)
750 {
751         if (p->x == 1.0 && p->y == 2.0)
752                 return 0;
753         else
754                 return 1;
755 }
756
757 LIBTEST_API int STDCALL 
758 mono_test_marshal_struct_array (simplestruct2 *ss)
759 {
760         if (! (ss[0].a == 0 && ss[0].b == 1 && ss[0].c == 0 &&
761                    !strcmp (ss[0].d, "TEST") && 
762                    ss[0].e == 99 && ss[0].f == 1.5 && ss[0].g == 42 && ss[0].h == (guint64)123))
763                 return 1;
764
765         if (! (ss[1].a == 0 && ss[1].b == 0 && ss[1].c == 0 &&
766                    !strcmp (ss[1].d, "TEST2") && 
767                    ss[1].e == 100 && ss[1].f == 2.5 && ss[1].g == 43 && ss[1].h == (guint64)124))
768                 return 1;
769
770         return 0;
771 }
772
773 typedef struct long_align_struct {
774         gint32 a;
775         gint64 b;
776         gint64 c;
777 } long_align_struct;
778
779 LIBTEST_API int STDCALL 
780 mono_test_marshal_long_align_struct_array (long_align_struct *ss)
781 {
782         return ss[0].a + ss[0].b + ss[0].c + ss[1].a + ss[1].b + ss[1].c;
783 }
784
785 LIBTEST_API simplestruct2 * STDCALL 
786 mono_test_marshal_class (int i, int j, int k, simplestruct2 *ss, int l)
787 {
788         simplestruct2 *res;
789
790         if (!ss)
791                 return NULL;
792
793         if (i != 10 || j != 11 || k != 12 || l != 14)
794                 return NULL;
795         if (! (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
796                    !strcmp (ss->d, "TEST") && 
797                    ss->e == 99 && ss->f == 1.5 && ss->g == 42 && ss->h == (guint64)123))
798                 return NULL;
799
800         res = marshal_new0 (simplestruct2, 1);
801         memcpy (res, ss, sizeof (simplestruct2));
802         res->d = marshal_strdup ("TEST");
803         return res;
804 }
805
806 LIBTEST_API int STDCALL 
807 mono_test_marshal_byref_class (simplestruct2 **ssp)
808 {
809         simplestruct2 *ss = *ssp;
810         simplestruct2 *res;
811         
812         if (! (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
813                    !strcmp (ss->d, "TEST") && 
814                    ss->e == 99 && ss->f == 1.5 && ss->g == 42 && ss->h == (guint64)123))
815                 return 1;
816
817         res = marshal_new0 (simplestruct2, 1);
818         memcpy (res, ss, sizeof (simplestruct2));
819         res->d = marshal_strdup ("TEST-RES");
820
821         *ssp = res;
822         return 0;
823 }
824
825 static void *
826 get_sp (void)
827 {
828         int i;
829         void *p;
830
831         /* Yes, this is correct, we are only trying to determine the value of the stack here */
832         p = &i;
833         return p;
834 }
835
836 LIBTEST_API int STDCALL 
837 reliable_delegate (int a)
838 {
839         return a;
840 }
841
842 /*
843  * Checks whether get_sp() works as expected. It doesn't work with gcc-2.95.3 on linux.
844  */
845 static gboolean
846 is_get_sp_reliable (void)
847 {
848         void *sp1, *sp2;
849
850         reliable_delegate(1);
851         sp1 = get_sp();
852         reliable_delegate(1);
853         sp2 = get_sp();
854         return sp1 == sp2;
855
856
857 LIBTEST_API int STDCALL 
858 mono_test_marshal_delegate (SimpleDelegate delegate)
859 {
860         void *sp1, *sp2;
861
862         /* Check that the delegate wrapper is stdcall */
863         delegate (2);
864         sp1 = get_sp ();
865         delegate (2);
866         sp2 = get_sp ();
867         if (is_get_sp_reliable())
868                 g_assert (sp1 == sp2);
869
870         return delegate (2);
871 }
872
873 static int STDCALL inc_cb (int i)
874 {
875         return i + 1;
876 }
877
878 LIBTEST_API int STDCALL 
879 mono_test_marshal_out_delegate (SimpleDelegate *delegate)
880 {
881         *delegate = inc_cb;
882
883         return 0;
884 }
885
886 LIBTEST_API SimpleDelegate STDCALL 
887 mono_test_marshal_return_delegate (SimpleDelegate delegate)
888 {
889         return delegate;
890 }
891
892 typedef int (STDCALL *DelegateByrefDelegate) (void *);
893
894 LIBTEST_API int STDCALL
895 mono_test_marshal_delegate_ref_delegate (DelegateByrefDelegate del)
896 {
897         int (STDCALL *ptr) (int i);
898
899         del (&ptr);
900
901         return ptr (54);
902 }
903
904 static int STDCALL
905 return_plus_one (int i)
906 {
907         return i + 1;
908 }
909
910 LIBTEST_API SimpleDelegate STDCALL 
911 mono_test_marshal_return_delegate_2 (void)
912 {
913         return return_plus_one;
914 }
915
916 typedef simplestruct (STDCALL *SimpleDelegate2) (simplestruct ss);
917
918 static gboolean
919 is_utf16_equals (gunichar2 *s1, const char *s2)
920 {
921         char *s;
922         int res;
923
924         s = g_utf16_to_utf8 (s1, -1, NULL, NULL, NULL);
925         res = strcmp (s, s2);
926         g_free (s);
927
928         return res == 0;
929 }
930
931 LIBTEST_API int STDCALL 
932 mono_test_marshal_delegate2 (SimpleDelegate2 delegate)
933 {
934         simplestruct ss, res;
935
936         ss.a = 0;
937         ss.b = 1;
938         ss.c = 0;
939         ss.d = "TEST";
940         ss.d2 = g_utf8_to_utf16 ("TEST2", -1, NULL, NULL, NULL); 
941
942         res = delegate (ss);
943         if (! (res.a && !res.b && res.c && !strcmp (res.d, "TEST-RES") && is_utf16_equals (res.d2, "TEST2-RES")))
944                 return 1;
945
946         return 0;
947 }
948
949 typedef simplestruct* (STDCALL *SimpleDelegate4) (simplestruct *ss);
950
951 LIBTEST_API int STDCALL 
952 mono_test_marshal_delegate4 (SimpleDelegate4 delegate)
953 {
954         simplestruct ss;
955         simplestruct *res;
956
957         ss.a = 0;
958         ss.b = 1;
959         ss.c = 0;
960         ss.d = "TEST";
961
962         /* Check argument */
963         res = delegate (&ss);
964         if (!res)
965                 return 1;
966
967         /* Check return value */
968         if (! (!res->a && res->b && !res->c && !strcmp (res->d, "TEST")))
969                 return 2;
970
971         /* Check NULL argument and NULL result */
972         res = delegate (NULL);
973         if (res)
974                 return 3;
975
976         return 0;
977 }
978
979 typedef int (STDCALL *SimpleDelegate5) (simplestruct **ss);
980
981 LIBTEST_API int STDCALL 
982 mono_test_marshal_delegate5 (SimpleDelegate5 delegate)
983 {
984         simplestruct ss;
985         int res;
986         simplestruct *ptr;
987
988         ss.a = 0;
989         ss.b = 1;
990         ss.c = 0;
991         ss.d = "TEST";
992
993         ptr = &ss;
994
995         res = delegate (&ptr);
996         if (res != 0)
997                 return 1;
998
999         if (!(ptr->a && !ptr->b && ptr->c && !strcmp (ptr->d, "RES")))
1000                 return 2;
1001
1002         return 0;
1003 }
1004
1005 LIBTEST_API int STDCALL 
1006 mono_test_marshal_delegate6 (SimpleDelegate5 delegate)
1007 {
1008         delegate (NULL);
1009         return 0;
1010 }
1011
1012 typedef int (STDCALL *SimpleDelegate7) (simplestruct **ss);
1013
1014 LIBTEST_API int STDCALL 
1015 mono_test_marshal_delegate7 (SimpleDelegate7 delegate)
1016 {
1017         int res;
1018         simplestruct *ptr;
1019
1020         /* Check that the input pointer is ignored */
1021         ptr = (simplestruct *)0x12345678;
1022
1023         res = delegate (&ptr);
1024         if (res != 0)
1025                 return 1;
1026
1027         if (!(ptr->a && !ptr->b && ptr->c && !strcmp (ptr->d, "RES")))
1028                 return 2;
1029
1030         return 0;
1031 }
1032
1033 typedef int (STDCALL *InOutByvalClassDelegate) (simplestruct *ss);
1034
1035 LIBTEST_API int STDCALL 
1036 mono_test_marshal_inout_byval_class_delegate (InOutByvalClassDelegate delegate)
1037 {
1038         int res;
1039         simplestruct ss;
1040
1041         ss.a = FALSE;
1042         ss.b = TRUE;
1043         ss.c = FALSE;
1044         ss.d = g_strdup_printf ("%s", "FOO");
1045
1046         res = delegate (&ss);
1047         if (res != 0)
1048                 return 1;
1049
1050         if (!(ss.a && !ss.b && ss.c && !strcmp (ss.d, "RES")))
1051                 return 2;
1052
1053         return 0;
1054 }
1055
1056 typedef int (STDCALL *SimpleDelegate8) (gunichar2 *s);
1057
1058 LIBTEST_API int STDCALL 
1059 mono_test_marshal_delegate8 (SimpleDelegate8 delegate, gunichar2 *s)
1060 {
1061         return delegate (s);
1062 }
1063
1064 typedef int (STDCALL *return_int_fnt) (int i);
1065 typedef int (STDCALL *SimpleDelegate9) (return_int_fnt d);
1066
1067 LIBTEST_API int STDCALL 
1068 mono_test_marshal_delegate9 (SimpleDelegate9 delegate, gpointer ftn)
1069 {
1070         return delegate ((return_int_fnt)ftn);
1071 }
1072
1073 static int STDCALL 
1074 return_self (int i)
1075 {
1076         return i;
1077 }
1078
1079 LIBTEST_API int STDCALL 
1080 mono_test_marshal_delegate10 (SimpleDelegate9 delegate)
1081 {
1082         return delegate (return_self);
1083 }
1084
1085 typedef int (STDCALL *PrimitiveByrefDelegate) (int *i);
1086
1087 LIBTEST_API int STDCALL 
1088 mono_test_marshal_primitive_byref_delegate (PrimitiveByrefDelegate delegate)
1089 {
1090         int i = 1;
1091
1092         int res = delegate (&i);
1093         if (res != 0)
1094                 return res;
1095
1096         if (i != 2)
1097                 return 2;
1098
1099         return 0;
1100 }
1101
1102 typedef int (STDCALL *return_int_delegate) (int i);
1103
1104 typedef return_int_delegate (STDCALL *ReturnDelegateDelegate) (void);
1105
1106 LIBTEST_API int STDCALL 
1107 mono_test_marshal_return_delegate_delegate (ReturnDelegateDelegate d)
1108 {
1109         return (d ()) (55);
1110 }
1111
1112 typedef int (STDCALL *VirtualDelegate) (int);
1113
1114 LIBTEST_API int STDCALL
1115 mono_test_marshal_virtual_delegate (VirtualDelegate del)
1116 {
1117         return del (42);
1118 }
1119
1120 typedef char* (STDCALL *IcallDelegate) (const char *);
1121 LIBTEST_API int STDCALL
1122 mono_test_marshal_icall_delegate (IcallDelegate del)
1123 {
1124         char *res = del ("ABC");
1125         return strcmp (res, "ABC") == 0 ? 0 : 1;
1126 }
1127
1128 LIBTEST_API int STDCALL  
1129 mono_test_marshal_stringbuilder (char *s, int n)
1130 {
1131         const char m[] = "This is my message.  Isn't it nice?";
1132
1133         if (strcmp (s, "ABCD") != 0)
1134                 return 1;
1135         memcpy(s, m, n);
1136         s [n] = '\0';
1137         return 0;
1138 }
1139
1140 LIBTEST_API int STDCALL  
1141 mono_test_marshal_stringbuilder_append (char *s, int length)
1142 {
1143         const char out_sentinel[] = "CSHARP_";
1144         const char out_len = strlen (out_sentinel);
1145
1146         for (int i=0; i < length; i++) {
1147                 s [i] = out_sentinel [i % out_len];
1148         }
1149
1150         s [length] = '\0';
1151
1152
1153         return 0;
1154 }
1155
1156 LIBTEST_API int STDCALL  
1157 mono_test_marshal_stringbuilder_default (char *s, int n)
1158 {
1159         const char m[] = "This is my message.  Isn't it nice?";
1160
1161         memcpy(s, m, n);
1162         s [n] = '\0';
1163         return 0;
1164 }
1165
1166 LIBTEST_API int STDCALL  
1167 mono_test_marshal_stringbuilder_unicode (gunichar2 *s, int n)
1168 {
1169         const char m[] = "This is my message.  Isn't it nice?";
1170         gunichar2* s2;
1171         glong len;
1172
1173         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1174         
1175         len = (len * 2) + 2;
1176         if (len > (n * 2))
1177                 len = n * 2;
1178         memcpy (s, s2, len);
1179
1180         g_free (s2);
1181
1182         return 0;
1183 }
1184
1185 LIBTEST_API void STDCALL
1186 mono_test_marshal_stringbuilder_out (char **s)
1187 {
1188         const char m[] = "This is my message.  Isn't it nice?";
1189         char *str;
1190
1191         str = (char *)marshal_alloc (strlen (m) + 1);
1192         memcpy (str, m, strlen (m) + 1);
1193         
1194         *s = str;
1195 }
1196
1197 LIBTEST_API int STDCALL  
1198 mono_test_marshal_stringbuilder_out_unicode (gunichar2 **s)
1199 {
1200         const char m[] = "This is my message.  Isn't it nice?";
1201         gunichar2 *s2;
1202         glong len;
1203
1204         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1205         
1206         len = (len * 2) + 2;
1207         *s = (gunichar2 *)marshal_alloc (len);
1208         memcpy (*s, s2, len);
1209
1210         g_free (s2);
1211
1212         return 0;
1213 }
1214
1215 LIBTEST_API int STDCALL
1216 mono_test_marshal_stringbuilder_ref (char **s)
1217 {
1218         const char m[] = "This is my message.  Isn't it nice?";
1219         char *str;
1220
1221         if (strcmp (*s, "ABC"))
1222                 return 1;
1223
1224         str = (char *)marshal_alloc (strlen (m) + 1);
1225         memcpy (str, m, strlen (m) + 1);
1226         
1227         *s = str;
1228         return 0;
1229 }
1230
1231 #ifdef __GNUC__
1232 #pragma GCC diagnostic push
1233 #pragma GCC diagnostic ignored "-Wc++-compat"
1234 #endif
1235
1236 /*
1237 * Standard C and C++ doesn't allow empty structs, empty structs will always have a size of 1 byte.
1238 * GCC have an extension to allow empty structs, https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html.
1239 * This cause a little dilemma since runtime build using none GCC compiler will not be compatible with
1240 * GCC build C libraries and the other way around. On platforms where empty structs has size of 1 byte
1241 * it must be represented in call and cannot be dropped. On Windows x64 structs will always be represented in the call
1242 * meaning that an empty struct must have a representation in the callee in order to correctly follow the ABI used by the
1243 * C/C++ standard and the runtime.
1244 */
1245 typedef struct {
1246 #if !defined(__GNUC__) || defined(TARGET_WIN32)
1247     char a;
1248 #endif
1249 } EmptyStruct;
1250
1251 #ifdef __GNUC__
1252 #pragma GCC diagnostic pop
1253 #endif
1254
1255 LIBTEST_API int STDCALL 
1256 mono_test_marshal_empty_string_array (char **array)
1257 {
1258         return (array == NULL) ? 0 : 1;
1259 }
1260
1261 LIBTEST_API int STDCALL 
1262 mono_test_marshal_string_array (char **array)
1263 {
1264         if (strcmp (array [0], "ABC"))
1265                 return 1;
1266         if (strcmp (array [1], "DEF"))
1267                 return 2;
1268
1269         if (array [2] != NULL)
1270                 return 3;
1271
1272         return 0;
1273 }
1274
1275 LIBTEST_API int STDCALL 
1276 mono_test_marshal_byref_string_array (char ***array)
1277 {
1278         if (*array == NULL)
1279                 return 0;
1280
1281         if (strcmp ((*array) [0], "Alpha"))
1282                 return 2;
1283         if (strcmp ((*array) [1], "Beta"))
1284                 return 2;
1285         if (strcmp ((*array) [2], "Gamma"))
1286                 return 2;
1287
1288         return 1;
1289 }
1290
1291 LIBTEST_API int STDCALL 
1292 mono_test_marshal_stringbuilder_array (char **array)
1293 {
1294         if (strcmp (array [0], "ABC"))
1295                 return 1;
1296         if (strcmp (array [1], "DEF"))
1297                 return 2;
1298
1299         strcpy (array [0], "DEF");
1300         strcpy (array [1], "ABC");
1301
1302         return 0;
1303 }
1304
1305 LIBTEST_API int STDCALL 
1306 mono_test_marshal_unicode_string_array (gunichar2 **array, char **array2)
1307 {
1308         GError *error = NULL;
1309         char *s;
1310         
1311         s = g_utf16_to_utf8 (array [0], -1, NULL, NULL, &error);
1312         if (strcmp (s, "ABC")) {
1313                 g_free (s);
1314                 return 1;
1315         }
1316         else
1317                 g_free (s);
1318
1319         s = g_utf16_to_utf8 (array [1], -1, NULL, NULL, &error);
1320         if (strcmp (s, "DEF")) {
1321                 g_free (s);
1322                 return 2;
1323         }
1324         else
1325                 g_free (s);
1326
1327         if (strcmp (array2 [0], "ABC"))
1328                 return 3;
1329
1330         if (strcmp (array2 [1], "DEF")) 
1331                 return 4;
1332
1333         return 0;
1334 }
1335
1336 /* this does not work on Redhat gcc 2.96 */
1337 LIBTEST_API int STDCALL  
1338 mono_test_empty_struct (int a, EmptyStruct es, int b)
1339 {
1340         // printf ("mono_test_empty_struct %d %d\n", a, b);
1341
1342         // Intel icc on ia64 passes 'es' in 2 registers
1343 #if defined(__ia64) && defined(__INTEL_COMPILER)
1344         return 0;
1345 #else
1346         if (a == 1 && b == 2)
1347                 return 0;
1348         return 1;
1349 #endif
1350 }
1351
1352 LIBTEST_API EmptyStruct STDCALL
1353 mono_test_return_empty_struct (int a)
1354 {
1355         EmptyStruct s;
1356
1357         memset (&s, 0, sizeof (s));
1358
1359 #if !(defined(__i386__) && defined(__clang__))
1360         /* https://bugzilla.xamarin.com/show_bug.cgi?id=58901 */
1361         g_assert (a == 42);
1362 #endif
1363
1364         return s;
1365 }
1366
1367 typedef struct {
1368        char a[100];
1369 } ByValStrStruct;
1370
1371 LIBTEST_API ByValStrStruct * STDCALL 
1372 mono_test_byvalstr_gen (void)
1373 {
1374         ByValStrStruct *ret;
1375        
1376         ret = (ByValStrStruct *)malloc (sizeof (ByValStrStruct));
1377         memset(ret, 'a', sizeof(ByValStrStruct)-1);
1378         ret->a[sizeof(ByValStrStruct)-1] = 0;
1379
1380         return ret;
1381 }
1382
1383 LIBTEST_API int STDCALL 
1384 mono_test_byvalstr_check (ByValStrStruct* data, char* correctString)
1385 {
1386         int ret;
1387
1388         ret = strcmp(data->a, correctString);
1389         // printf ("T1: %s\n", data->a);
1390         // printf ("T2: %s\n", correctString);
1391
1392         /* we need g_free because the allocation was performed by mono_test_byvalstr_gen */
1393         g_free (data);
1394         return (ret != 0);
1395 }
1396
1397 typedef struct {
1398         guint16 a[4];
1399         int  flag;
1400 } ByValStrStruct_Unicode;
1401
1402 LIBTEST_API int STDCALL 
1403 mono_test_byvalstr_check_unicode (ByValStrStruct_Unicode *ref, int test)
1404 {
1405         if (ref->flag != 0x1234abcd){
1406                 printf ("overwritten data");
1407                 return 1;
1408         }
1409             
1410         if (test == 1 || test == 3){
1411                 if (ref->a [0] != '1' ||
1412                     ref->a [1] != '2'   ||
1413                     ref->a [2] != '3')
1414                         return 1;
1415                 return 0;
1416         }
1417         if (test == 2){
1418                 if (ref->a [0] != '1' ||
1419                     ref->a [1] != '2')
1420                         return 1;
1421                 return 0;
1422         }
1423         return 10;
1424 }
1425
1426 LIBTEST_API int STDCALL 
1427 NameManglingAnsi (char *data)
1428 {
1429         return data [0] + data [1] + data [2];
1430 }
1431
1432 LIBTEST_API int STDCALL 
1433 NameManglingAnsiA (char *data)
1434 {
1435         g_assert_not_reached ();
1436 }
1437
1438 LIBTEST_API int STDCALL 
1439 NameManglingAnsiW (char *data)
1440 {
1441         g_assert_not_reached ();
1442 }
1443
1444 LIBTEST_API int STDCALL 
1445 NameManglingAnsi2A (char *data)
1446 {
1447         return data [0] + data [1] + data [2];
1448 }
1449
1450 LIBTEST_API int STDCALL 
1451 NameManglingAnsi2W (char *data)
1452 {
1453         g_assert_not_reached ();
1454 }
1455
1456 LIBTEST_API int STDCALL 
1457 NameManglingUnicode (char *data)
1458 {
1459         g_assert_not_reached ();
1460 }
1461
1462 LIBTEST_API int STDCALL 
1463 NameManglingUnicodeW (gunichar2 *data)
1464 {
1465         return data [0] + data [1] + data [2];
1466 }
1467
1468 LIBTEST_API int STDCALL 
1469 NameManglingUnicode2 (gunichar2 *data)
1470 {
1471         return data [0] + data [1] + data [2];
1472 }
1473
1474 LIBTEST_API int STDCALL 
1475 NameManglingAutoW (char *data)
1476 {
1477 #ifdef WIN32
1478         return (data [0] + data [1] + data [2]) == 131 ? 0 : 1;
1479 #else
1480         g_assert_not_reached ();
1481 #endif
1482 }
1483
1484 LIBTEST_API int STDCALL 
1485 NameManglingAuto (char *data)
1486 {
1487 #ifndef WIN32
1488         return (data [0] + data [1] + data [2]) == 198 ? 0 : 1;
1489 #else
1490         g_assert_not_reached ();
1491 #endif
1492 }
1493
1494 typedef int (STDCALL *intcharFunc)(const char*);
1495
1496 LIBTEST_API void STDCALL 
1497 callFunction (intcharFunc f)
1498 {
1499         f ("ABC");
1500 }
1501
1502 typedef struct {
1503         const char* str;
1504         int i;
1505 } SimpleObj;
1506
1507 LIBTEST_API int STDCALL 
1508 class_marshal_test0 (SimpleObj *obj1)
1509 {
1510         // printf ("class_marshal_test0 %s %d\n", obj1->str, obj1->i);
1511
1512         if (strcmp(obj1->str, "T1"))
1513                 return -1;
1514         if (obj1->i != 4)
1515                 return -2;
1516
1517         return 0;
1518 }
1519
1520 LIBTEST_API int STDCALL 
1521 class_marshal_test4 (SimpleObj *obj1)
1522 {
1523         if (obj1)
1524                 return -1;
1525
1526         return 0;
1527 }
1528
1529 LIBTEST_API void STDCALL
1530 class_marshal_test1 (SimpleObj **obj1)
1531 {
1532         SimpleObj *res = (SimpleObj *)malloc (sizeof (SimpleObj));
1533
1534         res->str = marshal_strdup ("ABC");
1535         res->i = 5;
1536
1537         *obj1 = res;
1538 }
1539
1540 LIBTEST_API int STDCALL 
1541 class_marshal_test2 (SimpleObj **obj1)
1542 {
1543         // printf ("class_marshal_test2 %s %d\n", (*obj1)->str, (*obj1)->i);
1544
1545         if (strcmp((*obj1)->str, "ABC"))
1546                 return -1;
1547         if ((*obj1)->i != 5)
1548                 return -2;
1549
1550         return 0;
1551 }
1552
1553 LIBTEST_API int STDCALL 
1554 string_marshal_test0 (char *str)
1555 {
1556         if (strcmp (str, "TEST0"))
1557                 return -1;
1558
1559         return 0;
1560 }
1561
1562 LIBTEST_API void STDCALL
1563 string_marshal_test1 (const char **str)
1564 {
1565         *str = marshal_strdup ("TEST1");
1566 }
1567
1568 LIBTEST_API int STDCALL 
1569 string_marshal_test2 (char **str)
1570 {
1571         // printf ("string_marshal_test2 %s\n", *str);
1572
1573         if (strcmp (*str, "TEST1"))
1574                 return -1;
1575
1576         *str = marshal_strdup ("TEST2");
1577
1578         return 0;
1579 }
1580
1581 LIBTEST_API int STDCALL 
1582 string_marshal_test3 (char *str)
1583 {
1584         if (str)
1585                 return -1;
1586
1587         return 0;
1588 }
1589
1590 typedef struct {
1591         int a;
1592         int b;
1593 } BlittableClass;
1594
1595 LIBTEST_API BlittableClass* STDCALL 
1596 TestBlittableClass (BlittableClass *vl)
1597 {
1598         BlittableClass *res;
1599
1600         // printf ("TestBlittableClass %d %d\n", vl->a, vl->b);
1601
1602         if (vl) {
1603                 vl->a++;
1604                 vl->b++;
1605
1606                 res = marshal_new0 (BlittableClass, 1);
1607                 memcpy (res, vl, sizeof (BlittableClass));
1608         } else {
1609                 res = marshal_new0 (BlittableClass, 1);
1610                 res->a = 42;
1611                 res->b = 43;
1612         }
1613
1614         return res;
1615 }
1616
1617 typedef struct OSVERSIONINFO_STRUCT
1618
1619         int a; 
1620         int b; 
1621 } OSVERSIONINFO_STRUCT;
1622
1623 LIBTEST_API int STDCALL  
1624 MyGetVersionEx (OSVERSIONINFO_STRUCT *osvi)
1625 {
1626
1627         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1628
1629         osvi->a += 1;
1630         osvi->b += 1;
1631
1632         return osvi->a + osvi->b;
1633 }
1634
1635 LIBTEST_API int STDCALL  
1636 BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSIONINFO_STRUCT *osvi)
1637 {
1638
1639         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1640
1641         osvi->a += 1;
1642         osvi->b += 1;
1643
1644         return osvi->a + osvi->b;
1645 }
1646
1647 LIBTEST_API int STDCALL 
1648 mono_test_marshal_point (point pt)
1649 {
1650         // printf("point %g %g\n", pt.x, pt.y);
1651         if (pt.x == 1.25 && pt.y == 3.5)
1652                 return 0;
1653
1654         return 1;
1655 }
1656
1657 typedef struct {
1658         int x;
1659         double y;
1660 } mixed_point;
1661
1662 LIBTEST_API int STDCALL 
1663 mono_test_marshal_mixed_point (mixed_point pt)
1664 {
1665         // printf("mixed point %d %g\n", pt.x, pt.y);
1666         if (pt.x == 5 && pt.y == 6.75)
1667                 return 0;
1668
1669         return 1;
1670 }
1671
1672 LIBTEST_API int STDCALL 
1673 mono_test_marshal_mixed_point_2 (mixed_point *pt)
1674 {
1675         if (pt->x != 5 || pt->y != 6.75)
1676                 return 1;
1677
1678         pt->x = 10;
1679         pt->y = 12.35;
1680
1681         return 0;
1682 }
1683
1684 LIBTEST_API int STDCALL  
1685 marshal_test_ref_bool(int i, char *b1, short *b2, int *b3)
1686 {
1687     int res = 1;
1688     if (*b1 != 0 && *b1 != 1)
1689         return 1;
1690     if (*b2 != 0 && *b2 != -1) /* variant_bool */
1691         return 1;
1692     if (*b3 != 0 && *b3 != 1)
1693         return 1;
1694     if (i == ((*b1 << 2) | (-*b2 << 1) | *b3))
1695         res = 0;
1696     *b1 = !*b1;
1697     *b2 = ~*b2;
1698     *b3 = !*b3;
1699     return res;
1700 }
1701
1702 struct BoolStruct
1703 {
1704     int i;
1705     char b1;
1706     short b2; /* variant_bool */
1707     int b3;
1708 };
1709
1710 LIBTEST_API int STDCALL  
1711 marshal_test_bool_struct(struct BoolStruct *s)
1712 {
1713     int res = 1;
1714     if (s->b1 != 0 && s->b1 != 1)
1715         return 1;
1716     if (s->b2 != 0 && s->b2 != -1)
1717         return 1;
1718     if (s->b3 != 0 && s->b3 != 1)
1719         return 1;
1720     if (s->i == ((s->b1 << 2) | (-s->b2 << 1) | s->b3))
1721         res = 0;
1722     s->b1 = !s->b1;
1723     s->b2 = ~s->b2;
1724     s->b3 = !s->b3;
1725     return res;
1726 }
1727
1728 typedef struct {
1729         gint64 l;
1730 } LongStruct2;
1731
1732 typedef struct {
1733         int i;
1734         LongStruct2 l;
1735 } LongStruct;
1736
1737 LIBTEST_API int STDCALL
1738 mono_test_marshal_long_struct (LongStruct *s)
1739 {
1740         return s->i + s->l.l;
1741 }
1742
1743 LIBTEST_API void STDCALL
1744 mono_test_last_error (int err)
1745 {
1746 #ifdef WIN32
1747         SetLastError (err);
1748 #else
1749         errno = err;
1750 #endif
1751 }
1752
1753 LIBTEST_API int STDCALL 
1754 mono_test_asany (void *ptr, int what)
1755 {
1756         switch (what) {
1757         case 1:
1758                 return (*(int*)ptr == 5) ? 0 : 1;
1759         case 2:
1760                 return strcmp (ptr, "ABC") == 0 ? 0 : 1;
1761         case 3: {
1762                 simplestruct2 ss = *(simplestruct2*)ptr;
1763
1764                 if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
1765             !strcmp (ss.d, "TEST") && 
1766             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
1767                         return 0;
1768                 else
1769                         return 1;
1770         }
1771         case 4: {
1772                 GError *error = NULL;
1773                 char *s;
1774
1775                 s = g_utf16_to_utf8 ((const gunichar2 *)ptr, -1, NULL, NULL, &error);
1776
1777                 if (!s)
1778                         return 1;
1779
1780                 if (!strcmp (s, "ABC")) {
1781                         g_free (s);
1782                         return 0;
1783                 }
1784                 else {
1785                         g_free (s);
1786                         return 1;
1787                 }
1788         }
1789         default:
1790                 g_assert_not_reached ();
1791         }
1792
1793         return 1;
1794 }
1795
1796 typedef struct
1797 {
1798         int i;
1799         int j;
1800         int k;
1801         char *s;
1802 } AsAnyStruct;
1803
1804 LIBTEST_API int STDCALL 
1805 mono_test_marshal_asany_in (void* ptr)
1806 {
1807         AsAnyStruct *asAny = (AsAnyStruct *)ptr;
1808         int res = asAny->i + asAny->j + asAny->k;
1809
1810         return res;
1811 }
1812
1813 LIBTEST_API int STDCALL 
1814 mono_test_marshal_asany_inout (void* ptr)
1815 {
1816         AsAnyStruct *asAny = (AsAnyStruct *)ptr;
1817         int res = asAny->i + asAny->j + asAny->k;
1818
1819         marshal_free (asAny->s);
1820
1821         asAny->i = 10;
1822         asAny->j = 20;
1823         asAny->k = 30;
1824         asAny->s = 0;
1825
1826         return res;
1827 }
1828
1829 LIBTEST_API int STDCALL 
1830 mono_test_marshal_asany_out (void* ptr)
1831 {
1832         AsAnyStruct *asAny = (AsAnyStruct *)ptr;
1833         int res = asAny->i + asAny->j + asAny->k;
1834
1835         asAny->i = 10;
1836         asAny->j = 20;
1837         asAny->k = 30;
1838         asAny->s = 0;
1839
1840         return res;
1841 }
1842
1843 /*
1844  * AMD64 marshalling tests.
1845  */
1846
1847 typedef struct amd64_struct1 {
1848         int i;
1849         int j;
1850         int k;
1851         int l;
1852 } amd64_struct1;
1853
1854 LIBTEST_API amd64_struct1 STDCALL 
1855 mono_test_marshal_amd64_pass_return_struct1 (amd64_struct1 s)
1856 {
1857         s.i ++;
1858         s.j ++;
1859         s.k ++;
1860         s.l ++;
1861
1862         return s;
1863 }
1864
1865 LIBTEST_API amd64_struct1 STDCALL 
1866 mono_test_marshal_amd64_pass_return_struct1_many_args (amd64_struct1 s, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8)
1867 {
1868         s.i ++;
1869         s.j ++;
1870         s.k ++;
1871         s.l += 1 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
1872
1873         return s;
1874 }
1875
1876 typedef struct amd64_struct2 {
1877         int i;
1878         int j;
1879 } amd64_struct2;
1880
1881 LIBTEST_API amd64_struct2 STDCALL 
1882 mono_test_marshal_amd64_pass_return_struct2 (amd64_struct2 s)
1883 {
1884         s.i ++;
1885         s.j ++;
1886
1887         return s;
1888 }
1889
1890 typedef struct amd64_struct3 {
1891         int i;
1892 } amd64_struct3;
1893
1894 LIBTEST_API amd64_struct3 STDCALL 
1895 mono_test_marshal_amd64_pass_return_struct3 (amd64_struct3 s)
1896 {
1897         s.i ++;
1898
1899         return s;
1900 }
1901
1902 typedef struct amd64_struct4 {
1903         double d1, d2;
1904 } amd64_struct4;
1905
1906 LIBTEST_API amd64_struct4 STDCALL 
1907 mono_test_marshal_amd64_pass_return_struct4 (amd64_struct4 s)
1908 {
1909         s.d1 ++;
1910         s.d2 ++;
1911
1912         return s;
1913 }
1914
1915 /*
1916  * IA64 marshalling tests.
1917  */
1918 typedef struct test_struct5 {
1919         float d1, d2;
1920 } test_struct5;
1921
1922 LIBTEST_API test_struct5 STDCALL 
1923 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, test_struct5 s, int i, double d3, double d4)
1924 {
1925         s.d1 += d1 + d2 + i;
1926         s.d2 += d3 + d4 + i;
1927
1928         return s;
1929 }
1930
1931 typedef struct test_struct6 {
1932         double d1, d2;
1933 } test_struct6;
1934
1935 LIBTEST_API test_struct6 STDCALL 
1936 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, test_struct6 s, int i, double d3, double d4)
1937 {
1938         s.d1 += d1 + d2 + i;
1939         s.d2 += d3 + d4;
1940
1941         return s;
1942 }
1943
1944 static guint32 custom_res [2];
1945
1946 LIBTEST_API void* STDCALL
1947 mono_test_marshal_pass_return_custom (int i, guint32 *ptr, int j)
1948 {
1949         /* ptr will be freed by CleanupNative, so make a copy */
1950         custom_res [0] = 0; /* not allocated by AllocHGlobal */
1951         custom_res [1] = ptr [1];
1952
1953         return &custom_res;
1954 }
1955
1956 LIBTEST_API int STDCALL 
1957 mono_test_marshal_pass_out_custom (int i, guint32 **ptr, int j)
1958 {
1959         custom_res [0] = 0;
1960         custom_res [1] = i + j + 10;
1961
1962         *ptr = custom_res;
1963
1964         return 0;
1965 }
1966
1967 LIBTEST_API int STDCALL 
1968 mono_test_marshal_pass_inout_custom (int i, guint32 *ptr, int j)
1969 {
1970         ptr [0] = 0;
1971         ptr [1] = i + ptr [1] + j;
1972
1973         return 0;
1974 }
1975
1976 LIBTEST_API int STDCALL 
1977 mono_test_marshal_pass_out_byval_custom (int i, guint32 *ptr, int j)
1978 {
1979         return ptr == NULL ? 0 : 1;
1980 }
1981
1982 LIBTEST_API int STDCALL 
1983 mono_test_marshal_pass_byref_custom (int i, guint32 **ptr, int j)
1984 {
1985         (*ptr)[1] += i + j;
1986
1987         return 0;
1988 }
1989
1990 LIBTEST_API void* STDCALL
1991 mono_test_marshal_pass_return_custom2 (int i, guint32 *ptr, int j)
1992 {
1993         g_assert_not_reached ();
1994
1995         return NULL;
1996 }
1997
1998 LIBTEST_API void* STDCALL
1999 mono_test_marshal_pass_return_custom_null (int i, guint32 *ptr, int j)
2000 {
2001         g_assert (ptr == NULL);
2002
2003         return NULL;
2004 }
2005
2006 typedef void *(STDCALL *PassReturnPtrDelegate) (void *ptr);
2007
2008 LIBTEST_API int STDCALL 
2009 mono_test_marshal_pass_return_custom_in_delegate (PassReturnPtrDelegate del)
2010 {
2011         guint32 buf [2];
2012         guint32 res;
2013         guint32 *ptr;
2014
2015         buf [0] = 0;
2016         buf [1] = 10;
2017
2018         ptr = (guint32 *)del (&buf);
2019
2020         res = ptr [1];
2021
2022 #ifdef WIN32
2023         /* FIXME: Freed with FreeHGlobal */
2024 #else
2025         g_free (ptr);
2026 #endif
2027
2028         return res;
2029 }
2030
2031 LIBTEST_API int STDCALL 
2032 mono_test_marshal_pass_return_custom_null_in_delegate (PassReturnPtrDelegate del)
2033 {
2034         void *ptr = del (NULL);
2035
2036         return (ptr == NULL) ? 15 : 0;
2037 }
2038
2039 typedef void (STDCALL *CustomOutParamDelegate) (void **pptr);
2040
2041 LIBTEST_API int STDCALL 
2042 mono_test_marshal_custom_out_param_delegate (CustomOutParamDelegate del)
2043 {
2044         void* pptr = del;
2045
2046         del (&pptr);
2047
2048         if(pptr != NULL)
2049                 return 1;
2050
2051         return 0;
2052 }
2053
2054 typedef int (STDCALL *ReturnEnumDelegate) (int e);
2055
2056 LIBTEST_API int STDCALL 
2057 mono_test_marshal_return_enum_delegate (ReturnEnumDelegate func)
2058 {
2059         return func (1);
2060 }
2061
2062 typedef struct {
2063         int a, b, c;
2064         gint64 d;
2065 } BlittableStruct;
2066         
2067 typedef BlittableStruct (STDCALL *SimpleDelegate10) (BlittableStruct ss);
2068
2069 LIBTEST_API int STDCALL 
2070 mono_test_marshal_blittable_struct_delegate (SimpleDelegate10 delegate)
2071 {
2072         BlittableStruct ss, res;
2073
2074         ss.a = 1;
2075         ss.b = 2;
2076         ss.c = 3;
2077         ss.d = 55;
2078
2079         res = delegate (ss);
2080         if (! ((res.a == -1) && (res.b == -2) && (res.c == -3) && (res.d == -55)))
2081                 return 1;
2082
2083         return 0;
2084 }
2085
2086 LIBTEST_API int STDCALL 
2087 mono_test_stdcall_name_mangling (int a, int b, int c)
2088 {
2089         return a + b + c;
2090 }
2091
2092 LIBTEST_API int
2093 mono_test_stdcall_mismatch_1 (int a, int b, int c)
2094 {
2095         return a + b + c;
2096 }
2097
2098 LIBTEST_API int STDCALL
2099 mono_test_stdcall_mismatch_2 (int a, int b, int c)
2100 {
2101         return a + b + c;
2102 }
2103
2104 /*
2105  * PASSING AND RETURNING SMALL STRUCTURES FROM DELEGATES TESTS
2106  */
2107
2108 typedef struct {
2109         int i;
2110 } SmallStruct1;
2111         
2112 typedef SmallStruct1 (STDCALL *SmallStructDelegate1) (SmallStruct1 ss);
2113
2114 LIBTEST_API int STDCALL 
2115 mono_test_marshal_small_struct_delegate1 (SmallStructDelegate1 delegate)
2116 {
2117         SmallStruct1 ss, res;
2118
2119         ss.i = 1;
2120
2121         res = delegate (ss);
2122         if (! (res.i == -1))
2123                 return 1;
2124
2125         return 0;
2126 }
2127
2128 typedef struct {
2129         gint16 i, j;
2130 } SmallStruct2;
2131         
2132 typedef SmallStruct2 (STDCALL *SmallStructDelegate2) (SmallStruct2 ss);
2133
2134 LIBTEST_API int STDCALL 
2135 mono_test_marshal_small_struct_delegate2 (SmallStructDelegate2 delegate)
2136 {
2137         SmallStruct2 ss, res;
2138
2139         ss.i = 2;
2140         ss.j = 3;
2141
2142         res = delegate (ss);
2143         if (! ((res.i == -2) && (res.j == -3)))
2144                 return 1;
2145
2146         return 0;
2147 }
2148
2149 typedef struct {
2150         gint16 i;
2151         gint8 j;
2152 } SmallStruct3;
2153         
2154 typedef SmallStruct3 (STDCALL *SmallStructDelegate3) (SmallStruct3 ss);
2155
2156 LIBTEST_API int STDCALL 
2157 mono_test_marshal_small_struct_delegate3 (SmallStructDelegate3 delegate)
2158 {
2159         SmallStruct3 ss, res;
2160
2161         ss.i = 1;
2162         ss.j = 2;
2163
2164         res = delegate (ss);
2165         if (! ((res.i == -1) && (res.j == -2)))
2166                 return 1;
2167
2168         return 0;
2169 }
2170
2171 typedef struct {
2172         gint16 i;
2173 } SmallStruct4;
2174         
2175 typedef SmallStruct4 (STDCALL *SmallStructDelegate4) (SmallStruct4 ss);
2176
2177 LIBTEST_API int STDCALL 
2178 mono_test_marshal_small_struct_delegate4 (SmallStructDelegate4 delegate)
2179 {
2180         SmallStruct4 ss, res;
2181
2182         ss.i = 1;
2183
2184         res = delegate (ss);
2185         if (! (res.i == -1))
2186                 return 1;
2187
2188         return 0;
2189 }
2190
2191 typedef struct {
2192         gint64 i;
2193 } SmallStruct5;
2194         
2195 typedef SmallStruct5 (STDCALL *SmallStructDelegate5) (SmallStruct5 ss);
2196
2197 LIBTEST_API int STDCALL 
2198 mono_test_marshal_small_struct_delegate5 (SmallStructDelegate5 delegate)
2199 {
2200         SmallStruct5 ss, res;
2201
2202         ss.i = 5;
2203
2204         res = delegate (ss);
2205         if (! (res.i == -5))
2206                 return 1;
2207
2208         return 0;
2209 }
2210
2211 typedef struct {
2212         int i, j;
2213 } SmallStruct6;
2214         
2215 typedef SmallStruct6 (STDCALL *SmallStructDelegate6) (SmallStruct6 ss);
2216
2217 LIBTEST_API int STDCALL 
2218 mono_test_marshal_small_struct_delegate6 (SmallStructDelegate6 delegate)
2219 {
2220         SmallStruct6 ss, res;
2221
2222         ss.i = 1;
2223         ss.j = 2;
2224
2225         res = delegate (ss);
2226         if (! ((res.i == -1) && (res.j == -2)))
2227                 return 1;
2228
2229         return 0;
2230 }
2231
2232 typedef struct {
2233         int i;
2234         gint16 j;
2235 } SmallStruct7;
2236         
2237 typedef SmallStruct7 (STDCALL *SmallStructDelegate7) (SmallStruct7 ss);
2238
2239 LIBTEST_API int STDCALL 
2240 mono_test_marshal_small_struct_delegate7 (SmallStructDelegate7 delegate)
2241 {
2242         SmallStruct7 ss, res;
2243
2244         ss.i = 1;
2245         ss.j = 2;
2246
2247         res = delegate (ss);
2248         if (! ((res.i == -1) && (res.j == -2)))
2249                 return 1;
2250
2251         return 0;
2252 }
2253
2254 typedef struct {
2255         float i;
2256 } SmallStruct8;
2257         
2258 typedef SmallStruct8 (STDCALL *SmallStructDelegate8) (SmallStruct8 ss);
2259
2260 LIBTEST_API int STDCALL 
2261 mono_test_marshal_small_struct_delegate8 (SmallStructDelegate8 delegate)
2262 {
2263         SmallStruct8 ss, res;
2264
2265         ss.i = 1.0;
2266
2267         res = delegate (ss);
2268         if (! ((res.i == -1.0)))
2269                 return 1;
2270
2271         return 0;
2272 }
2273
2274 typedef struct {
2275         double i;
2276 } SmallStruct9;
2277         
2278 typedef SmallStruct9 (STDCALL *SmallStructDelegate9) (SmallStruct9 ss);
2279
2280 LIBTEST_API int STDCALL 
2281 mono_test_marshal_small_struct_delegate9 (SmallStructDelegate9 delegate)
2282 {
2283         SmallStruct9 ss, res;
2284
2285         ss.i = 1.0;
2286
2287         res = delegate (ss);
2288         if (! ((res.i == -1.0)))
2289                 return 1;
2290
2291         return 0;
2292 }
2293
2294 typedef struct {
2295         float i, j;
2296 } SmallStruct10;
2297         
2298 typedef SmallStruct10 (STDCALL *SmallStructDelegate10) (SmallStruct10 ss);
2299
2300 LIBTEST_API int STDCALL 
2301 mono_test_marshal_small_struct_delegate10 (SmallStructDelegate10 delegate)
2302 {
2303         SmallStruct10 ss, res;
2304
2305         ss.i = 1.0;
2306         ss.j = 2.0;
2307
2308         res = delegate (ss);
2309         if (! ((res.i == -1.0) && (res.j == -2.0)))
2310                 return 1;
2311
2312         return 0;
2313 }
2314
2315 typedef struct {
2316         float i;
2317         int j;
2318 } SmallStruct11;
2319         
2320 typedef SmallStruct11 (STDCALL *SmallStructDelegate11) (SmallStruct11 ss);
2321
2322 LIBTEST_API int STDCALL 
2323 mono_test_marshal_small_struct_delegate11 (SmallStructDelegate11 delegate)
2324 {
2325         SmallStruct11 ss, res;
2326
2327         ss.i = 1.0;
2328         ss.j = 2;
2329
2330         res = delegate (ss);
2331         if (! ((res.i == -1.0) && (res.j == -2)))
2332                 return 1;
2333
2334         return 0;
2335 }
2336
2337 typedef int (STDCALL *ArrayDelegate) (int i, char *j, void *arr);
2338
2339 LIBTEST_API int STDCALL 
2340 mono_test_marshal_array_delegate (void *arr, int len, ArrayDelegate del)
2341 {
2342         return del (len, NULL, arr);
2343 }
2344
2345 typedef int (STDCALL *ArrayDelegateLong) (gint64 i, char *j, void *arr);
2346
2347 LIBTEST_API int STDCALL 
2348 mono_test_marshal_array_delegate_long (void *arr, gint64 len, ArrayDelegateLong del)
2349 {
2350         return del (len, NULL, arr);
2351 }
2352
2353 LIBTEST_API int STDCALL 
2354 mono_test_marshal_out_array_delegate (int *arr, int len, ArrayDelegate del)
2355 {
2356         del (len, NULL, arr);
2357
2358         if ((arr [0] != 1) || (arr [1] != 2))
2359                 return 1;
2360         else
2361                 return 0;
2362 }
2363
2364 typedef gunichar2* (STDCALL *UnicodeStringDelegate) (gunichar2 *message);
2365
2366 LIBTEST_API int STDCALL 
2367 mono_test_marshal_return_unicode_string_delegate (UnicodeStringDelegate del)
2368 {
2369         const char m[] = "abcdef";
2370         gunichar2 *s2, *res;
2371         glong len;
2372
2373         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
2374
2375         res = del (s2);
2376
2377         marshal_free (res);
2378
2379         return 0;
2380 }
2381
2382 LIBTEST_API int STDCALL 
2383 mono_test_marshal_out_string_array_delegate (char **arr, int len, ArrayDelegate del)
2384 {
2385         del (len, NULL, arr);
2386
2387         if (!strcmp (arr [0], "ABC") && !strcmp (arr [1], "DEF"))
2388                 return 0;
2389         else
2390                 return 1;
2391 }
2392
2393 typedef int (*CdeclDelegate) (int i, int j);
2394
2395 LIBTEST_API int STDCALL 
2396 mono_test_marshal_cdecl_delegate (CdeclDelegate del)
2397 {
2398         int i;
2399
2400         for (i = 0; i < 1000; ++i)
2401                 del (1, 2);
2402
2403         return 0;
2404 }
2405
2406 typedef char** (STDCALL *ReturnStringArrayDelegate) (int i);
2407
2408 LIBTEST_API int STDCALL 
2409 mono_test_marshal_return_string_array_delegate (ReturnStringArrayDelegate d)
2410 {
2411         char **arr = d (2);
2412         int res;
2413
2414         if (arr == NULL)
2415                 return 3;
2416
2417         if (strcmp (arr [0], "ABC") || strcmp (arr [1], "DEF"))
2418                 res = 1;
2419         else
2420                 res = 0;
2421
2422         marshal_free (arr);
2423
2424         return res;
2425 }
2426
2427 typedef int (STDCALL *ByrefStringDelegate) (char **s);
2428
2429 LIBTEST_API int STDCALL 
2430 mono_test_marshal_byref_string_delegate (ByrefStringDelegate d)
2431 {
2432         char *s = (char*)"ABC";
2433         int res;
2434
2435         res = d (&s);
2436         if (res != 0)
2437                 return res;
2438
2439         if (!strcmp (s, "DEF"))
2440                 res = 0;
2441         else
2442                 res = 2;
2443
2444         marshal_free (s);
2445
2446         return res;
2447 }
2448
2449 LIBTEST_API int STDCALL 
2450 add_delegate (int i, int j)
2451 {
2452         return i + j;
2453 }
2454
2455 LIBTEST_API gpointer STDCALL 
2456 mono_test_marshal_return_fnptr (void)
2457 {
2458         return &add_delegate;
2459 }
2460
2461 LIBTEST_API int STDCALL 
2462 mono_xr (int code)
2463 {
2464         printf ("codigo %x\n", code);
2465         return code + 1234;
2466 }
2467
2468 typedef struct {
2469         int handle;
2470 } HandleRef;
2471
2472 LIBTEST_API HandleRef STDCALL 
2473 mono_xr_as_handle (int code)
2474 {
2475         HandleRef ref;
2476
2477         memset (&ref, 0, sizeof (ref));
2478
2479         return ref;
2480 }
2481  
2482 typedef struct {
2483         int   a;
2484         void *handle1;
2485         void *handle2;
2486         int   b;
2487 } HandleStructs;
2488
2489 LIBTEST_API int STDCALL 
2490 mono_safe_handle_struct_ref (HandleStructs *x)
2491 {
2492         printf ("Dingus Ref! \n");
2493         printf ("Values: %d %d %p %p\n", x->a, x->b, x->handle1, x->handle2);
2494         if (x->a != 1234)
2495                 return 1;
2496         if (x->b != 8743)
2497                 return 2;
2498
2499         if (x->handle1 != (void*) 0x7080feed)
2500                 return 3;
2501
2502         if (x->handle2 != (void*) 0x1234abcd)
2503                 return 4;
2504
2505         return 0xf00d;
2506 }
2507
2508 LIBTEST_API int STDCALL 
2509 mono_safe_handle_struct (HandleStructs x)
2510 {
2511         printf ("Dingus Standard! \n");
2512         printf ("Values: %d %d %p %p\n", x.a, x.b, x.handle1, x.handle2);
2513         if (x.a != 1234)
2514                 return 1;
2515         if (x.b != 8743)
2516                 return 2;
2517
2518         if (x.handle1 != (void*) 0x7080feed)
2519                 return 3;
2520
2521         if (x.handle2 != (void*) 0x1234abcd)
2522                 return 4;
2523         
2524         return 0xf00f;
2525 }
2526
2527 typedef struct {
2528         void *a;
2529 } TrivialHandle;
2530
2531 LIBTEST_API int STDCALL 
2532 mono_safe_handle_struct_simple (TrivialHandle x)
2533 {
2534         printf ("The value is %p\n", x.a);
2535         return ((int)(gsize)x.a) * 2;
2536 }
2537
2538 LIBTEST_API int STDCALL 
2539 mono_safe_handle_return (void)
2540 {
2541         return 0x1000f00d;
2542 }
2543
2544 LIBTEST_API void STDCALL
2545 mono_safe_handle_ref (void **handle)
2546 {
2547         if (*handle != 0){
2548                 *handle = (void *) 0xbad;
2549                 return;
2550         }
2551
2552         *handle = (void *) 0x800d;
2553 }
2554
2555 LIBTEST_API double STDCALL
2556 mono_test_marshal_date_time (double d, double *d2)
2557 {
2558         *d2 = d;
2559         return d;
2560 }
2561
2562 /*
2563  * COM INTEROP TESTS
2564  */
2565
2566 #ifndef WIN32
2567
2568 typedef struct {
2569         guint16 vt;
2570         guint16 wReserved1;
2571         guint16 wReserved2;
2572         guint16 wReserved3;
2573         union {
2574                 gint64 llVal;
2575                 gint32 lVal;
2576                 guint8  bVal;
2577                 gint16 iVal;
2578                 float  fltVal;
2579                 double dblVal;
2580                 gint16 boolVal;
2581                 gunichar2* bstrVal;
2582                 gint8 cVal;
2583                 guint16 uiVal;
2584                 guint32 ulVal;
2585                 guint64 ullVal;
2586                 gpointer byref;
2587                 struct {
2588                         gpointer pvRecord;
2589                         gpointer pRecInfo;
2590                 };
2591         };
2592 } VARIANT;
2593
2594 typedef enum {
2595         VARIANT_TRUE = -1,
2596         VARIANT_FALSE = 0
2597 } VariantBool;
2598
2599 typedef enum {
2600         VT_EMPTY = 0,
2601         VT_NULL = 1,
2602         VT_I2 = 2,
2603         VT_I4 = 3,
2604         VT_R4 = 4,
2605         VT_R8 = 5,
2606         VT_CY = 6,
2607         VT_DATE = 7,
2608         VT_BSTR = 8,
2609         VT_DISPATCH = 9,
2610         VT_ERROR = 10,
2611         VT_BOOL = 11,
2612         VT_VARIANT = 12,
2613         VT_UNKNOWN = 13,
2614         VT_DECIMAL = 14,
2615         VT_I1 = 16,
2616         VT_UI1 = 17,
2617         VT_UI2 = 18,
2618         VT_UI4 = 19,
2619         VT_I8 = 20,
2620         VT_UI8 = 21,
2621         VT_INT = 22,
2622         VT_UINT = 23,
2623         VT_VOID = 24,
2624         VT_HRESULT = 25,
2625         VT_PTR = 26,
2626         VT_SAFEARRAY = 27,
2627         VT_CARRAY = 28,
2628         VT_USERDEFINED = 29,
2629         VT_LPSTR = 30,
2630         VT_LPWSTR = 31,
2631         VT_RECORD = 36,
2632         VT_FILETIME = 64,
2633         VT_BLOB = 65,
2634         VT_STREAM = 66,
2635         VT_STORAGE = 67,
2636         VT_STREAMED_OBJECT = 68,
2637         VT_STORED_OBJECT = 69,
2638         VT_BLOB_OBJECT = 70,
2639         VT_CF = 71,
2640         VT_CLSID = 72,
2641         VT_VECTOR = 4096,
2642         VT_ARRAY = 8192,
2643         VT_BYREF = 16384
2644 } VarEnum;
2645
2646 void VariantInit(VARIANT* vt)
2647 {
2648         vt->vt = VT_EMPTY;
2649 }
2650
2651 typedef struct
2652 {
2653         guint32 a;
2654         guint16 b;
2655         guint16 c;
2656         guint8 d[8];
2657 } GUID;
2658
2659 #define S_OK 0
2660
2661 #endif
2662
2663 LIBTEST_API int STDCALL 
2664 mono_test_marshal_bstr_in(gunichar2* bstr)
2665 {
2666         gint32 result = 0;
2667         gchar* bstr_utf8 = g_utf16_to_utf8 (bstr, -1, NULL, NULL, NULL);
2668         result = strcmp("mono_test_marshal_bstr_in", bstr_utf8);
2669         g_free(bstr_utf8);
2670         if (result == 0)
2671                 return 0;
2672         return 1;
2673 }
2674
2675 LIBTEST_API int STDCALL 
2676 mono_test_marshal_bstr_out(gunichar2** bstr)
2677 {
2678         *bstr = marshal_bstr_alloc ("mono_test_marshal_bstr_out");
2679         return 0;
2680 }
2681
2682 LIBTEST_API int STDCALL 
2683 mono_test_marshal_bstr_in_null(gunichar2* bstr)
2684 {
2685         if (!bstr)
2686                 return 0;
2687         return 1;
2688 }
2689
2690 LIBTEST_API int STDCALL 
2691 mono_test_marshal_bstr_out_null(gunichar2** bstr)
2692 {
2693         *bstr = NULL;
2694         return 0;
2695 }
2696
2697 LIBTEST_API int STDCALL 
2698 mono_test_marshal_variant_in_sbyte(VARIANT variant)
2699 {
2700         if (variant.vt == VT_I1 && variant.cVal == 100)
2701                 return 0;
2702         return 1;
2703 }
2704
2705 LIBTEST_API int STDCALL 
2706 mono_test_marshal_variant_in_byte(VARIANT variant)
2707 {
2708         if (variant.vt == VT_UI1 && variant.bVal == 100)
2709                 return 0;
2710         return 1;
2711 }
2712
2713 LIBTEST_API int STDCALL 
2714 mono_test_marshal_variant_in_short(VARIANT variant)
2715 {
2716         if (variant.vt == VT_I2 && variant.iVal == 314)
2717                 return 0;
2718         return 1;
2719 }
2720
2721 LIBTEST_API int STDCALL 
2722 mono_test_marshal_variant_in_ushort(VARIANT variant)
2723 {
2724         if (variant.vt == VT_UI2 && variant.uiVal == 314)
2725                 return 0;
2726         return 1;
2727 }
2728
2729 LIBTEST_API int STDCALL 
2730 mono_test_marshal_variant_in_int(VARIANT variant)
2731 {
2732         if (variant.vt == VT_I4 && variant.lVal == 314)
2733                 return 0;
2734         return 1;
2735 }
2736
2737 LIBTEST_API int STDCALL 
2738 mono_test_marshal_variant_in_uint(VARIANT variant)
2739 {
2740         if (variant.vt == VT_UI4 && variant.ulVal == 314)
2741                 return 0;
2742         return 1;
2743 }
2744
2745 LIBTEST_API int STDCALL 
2746 mono_test_marshal_variant_in_long(VARIANT variant)
2747 {
2748         if (variant.vt == VT_I8 && variant.llVal == 314)
2749                 return 0;
2750         return 1;
2751 }
2752
2753 LIBTEST_API int STDCALL 
2754 mono_test_marshal_variant_in_ulong(VARIANT variant)
2755 {
2756         if (variant.vt == VT_UI8 && variant.ullVal == 314)
2757                 return 0;
2758         return 1;
2759 }
2760
2761 LIBTEST_API int STDCALL 
2762 mono_test_marshal_variant_in_float(VARIANT variant)
2763 {
2764         if (variant.vt == VT_R4 && (variant.fltVal - 3.14)/3.14 < .001)
2765                 return 0;
2766         return 1;
2767 }
2768
2769 LIBTEST_API int STDCALL 
2770 mono_test_marshal_variant_in_double(VARIANT variant)
2771 {
2772         if (variant.vt == VT_R8 && (variant.dblVal - 3.14)/3.14 < .001)
2773                 return 0;
2774         return 1;
2775 }
2776
2777 LIBTEST_API int STDCALL 
2778 mono_test_marshal_variant_in_bstr(VARIANT variant)
2779 {
2780         gint32 result = 0;
2781         gchar* bstr_utf8 = g_utf16_to_utf8 (variant.bstrVal, -1, NULL, NULL, NULL);
2782         result = strcmp("PI", bstr_utf8);
2783         g_free(bstr_utf8);
2784
2785         if (variant.vt == VT_BSTR && !result)
2786                 return 0;
2787         return 1;
2788 }
2789
2790 LIBTEST_API int STDCALL 
2791 mono_test_marshal_variant_in_bool_true (VARIANT variant)
2792 {
2793         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_TRUE)
2794                 return 0;
2795         return 1;
2796 }
2797
2798 LIBTEST_API int STDCALL 
2799 mono_test_marshal_variant_in_bool_false (VARIANT variant)
2800 {
2801         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_FALSE)
2802                 return 0;
2803         return 1;
2804 }
2805
2806 LIBTEST_API int STDCALL 
2807 mono_test_marshal_variant_out_sbyte(VARIANT* variant)
2808 {
2809         variant->vt = VT_I1;
2810         variant->cVal = 100;
2811
2812         return 0;
2813 }
2814
2815 LIBTEST_API int STDCALL 
2816 mono_test_marshal_variant_out_sbyte_byref(VARIANT* variant)
2817 {
2818         variant->vt = VT_I1|VT_BYREF;
2819         variant->byref = marshal_alloc(1);
2820         *((gint8*)variant->byref) = 100;
2821
2822         return 0;
2823 }
2824
2825 LIBTEST_API int STDCALL 
2826 mono_test_marshal_variant_out_byte(VARIANT* variant)
2827 {       
2828         variant->vt = VT_UI1;
2829         variant->bVal = 100;
2830
2831         return 0;
2832 }
2833
2834 LIBTEST_API int STDCALL 
2835 mono_test_marshal_variant_out_byte_byref(VARIANT* variant)
2836 {       
2837         variant->vt = VT_UI1|VT_BYREF;
2838         variant->byref = marshal_alloc(1);
2839         *((gint8*)variant->byref) = 100;
2840
2841         return 0;
2842 }
2843
2844 LIBTEST_API int STDCALL 
2845 mono_test_marshal_variant_out_short(VARIANT* variant)
2846 {
2847         variant->vt = VT_I2;
2848         variant->iVal = 314;
2849
2850         return 0;
2851 }
2852
2853 LIBTEST_API int STDCALL 
2854 mono_test_marshal_variant_out_short_byref(VARIANT* variant)
2855 {
2856         variant->vt = VT_I2|VT_BYREF;
2857         variant->byref = marshal_alloc(2);
2858         *((gint16*)variant->byref) = 314;
2859
2860         return 0;
2861 }
2862
2863 LIBTEST_API int STDCALL 
2864 mono_test_marshal_variant_out_ushort(VARIANT* variant)
2865 {
2866         variant->vt = VT_UI2;
2867         variant->uiVal = 314;
2868
2869         return 0;
2870 }
2871
2872 LIBTEST_API int STDCALL 
2873 mono_test_marshal_variant_out_ushort_byref(VARIANT* variant)
2874 {
2875         variant->vt = VT_UI2|VT_BYREF;
2876         variant->byref = marshal_alloc(2);
2877         *((guint16*)variant->byref) = 314;
2878
2879         return 0;
2880 }
2881
2882 LIBTEST_API int STDCALL 
2883 mono_test_marshal_variant_out_int(VARIANT* variant)
2884 {
2885         variant->vt = VT_I4;
2886         variant->lVal = 314;
2887
2888         return 0;
2889 }
2890
2891 LIBTEST_API int STDCALL 
2892 mono_test_marshal_variant_out_int_byref(VARIANT* variant)
2893 {
2894         variant->vt = VT_I4|VT_BYREF;
2895         variant->byref = marshal_alloc(4);
2896         *((gint32*)variant->byref) = 314;
2897
2898         return 0;
2899 }
2900
2901 LIBTEST_API int STDCALL 
2902 mono_test_marshal_variant_out_uint(VARIANT* variant)
2903 {
2904         variant->vt = VT_UI4;
2905         variant->ulVal = 314;
2906
2907         return 0;
2908 }
2909
2910 LIBTEST_API int STDCALL 
2911 mono_test_marshal_variant_out_uint_byref(VARIANT* variant)
2912 {
2913         variant->vt = VT_UI4|VT_BYREF;
2914         variant->byref = marshal_alloc(4);
2915         *((guint32*)variant->byref) = 314;
2916
2917         return 0;
2918 }
2919
2920 LIBTEST_API int STDCALL 
2921 mono_test_marshal_variant_out_long(VARIANT* variant)
2922 {
2923         variant->vt = VT_I8;
2924         variant->llVal = 314;
2925
2926         return 0;
2927 }
2928
2929 LIBTEST_API int STDCALL 
2930 mono_test_marshal_variant_out_long_byref(VARIANT* variant)
2931 {
2932         variant->vt = VT_I8|VT_BYREF;
2933         variant->byref = marshal_alloc(8);
2934         *((gint64*)variant->byref) = 314;
2935
2936         return 0;
2937 }
2938
2939 LIBTEST_API int STDCALL 
2940 mono_test_marshal_variant_out_ulong(VARIANT* variant)
2941 {
2942         variant->vt = VT_UI8;
2943         variant->ullVal = 314;
2944
2945         return 0;
2946 }
2947
2948 LIBTEST_API int STDCALL 
2949 mono_test_marshal_variant_out_ulong_byref(VARIANT* variant)
2950 {
2951         variant->vt = VT_UI8|VT_BYREF;
2952         variant->byref = marshal_alloc(8);
2953         *((guint64*)variant->byref) = 314;
2954
2955         return 0;
2956 }
2957
2958 LIBTEST_API int STDCALL 
2959 mono_test_marshal_variant_out_float(VARIANT* variant)
2960 {
2961         variant->vt = VT_R4;
2962         variant->fltVal = 3.14;
2963
2964         return 0;
2965 }
2966
2967 LIBTEST_API int STDCALL 
2968 mono_test_marshal_variant_out_float_byref(VARIANT* variant)
2969 {
2970         variant->vt = VT_R4|VT_BYREF;
2971         variant->byref = marshal_alloc(4);
2972         *((float*)variant->byref) = 3.14;
2973
2974         return 0;
2975 }
2976
2977 LIBTEST_API int STDCALL 
2978 mono_test_marshal_variant_out_double(VARIANT* variant)
2979 {
2980         variant->vt = VT_R8;
2981         variant->dblVal = 3.14;
2982
2983         return 0;
2984 }
2985
2986 LIBTEST_API int STDCALL 
2987 mono_test_marshal_variant_out_double_byref(VARIANT* variant)
2988 {
2989         variant->vt = VT_R8|VT_BYREF;
2990         variant->byref = marshal_alloc(8);
2991         *((double*)variant->byref) = 3.14;
2992
2993         return 0;
2994 }
2995
2996 LIBTEST_API int STDCALL 
2997 mono_test_marshal_variant_out_bstr(VARIANT* variant)
2998 {
2999         variant->vt = VT_BSTR;
3000         variant->bstrVal = marshal_bstr_alloc("PI");
3001
3002         return 0;
3003 }
3004
3005 LIBTEST_API int STDCALL 
3006 mono_test_marshal_variant_out_bstr_byref(VARIANT* variant)
3007 {
3008         variant->vt = VT_BSTR|VT_BYREF;
3009         variant->byref = marshal_alloc(sizeof(gpointer));
3010         *((gunichar**)variant->byref) = (gunichar*)marshal_bstr_alloc("PI");
3011
3012         return 0;
3013 }
3014
3015 LIBTEST_API int STDCALL 
3016 mono_test_marshal_variant_out_bool_true (VARIANT* variant)
3017 {
3018         variant->vt = VT_BOOL;
3019         variant->boolVal = VARIANT_TRUE;
3020
3021         return 0;
3022 }
3023
3024 LIBTEST_API int STDCALL 
3025 mono_test_marshal_variant_out_bool_true_byref (VARIANT* variant)
3026 {
3027         variant->vt = VT_BOOL|VT_BYREF;
3028         variant->byref = marshal_alloc(2);
3029         *((gint16*)variant->byref) = VARIANT_TRUE;
3030
3031         return 0;
3032 }
3033
3034 LIBTEST_API int STDCALL 
3035 mono_test_marshal_variant_out_bool_false (VARIANT* variant)
3036 {
3037         variant->vt = VT_BOOL;
3038         variant->boolVal = VARIANT_FALSE;
3039
3040         return 0;
3041 }
3042
3043 LIBTEST_API int STDCALL 
3044 mono_test_marshal_variant_out_bool_false_byref (VARIANT* variant)
3045 {
3046         variant->vt = VT_BOOL|VT_BYREF;
3047         variant->byref = marshal_alloc(2);
3048         *((gint16*)variant->byref) = VARIANT_FALSE;
3049
3050         return 0;
3051 }
3052
3053 typedef int (STDCALL *VarFunc) (int vt, VARIANT variant);
3054 typedef int (STDCALL *VarRefFunc) (int vt, VARIANT* variant);
3055
3056 LIBTEST_API int STDCALL 
3057 mono_test_marshal_variant_in_sbyte_unmanaged(VarFunc func)
3058 {
3059         VARIANT vt;
3060         vt.vt = VT_I1;
3061         vt.cVal = -100;
3062         return func (VT_I1, vt);
3063 }
3064
3065 LIBTEST_API int STDCALL 
3066 mono_test_marshal_variant_in_byte_unmanaged(VarFunc func)
3067 {
3068         VARIANT vt;
3069         vt.vt = VT_UI1;
3070         vt.bVal = 100;
3071         return func (VT_UI1, vt);
3072 }
3073
3074 LIBTEST_API int STDCALL 
3075 mono_test_marshal_variant_in_short_unmanaged(VarFunc func)
3076 {
3077         VARIANT vt;
3078         vt.vt = VT_I2;
3079         vt.iVal = -100;
3080         return func (VT_I2, vt);
3081 }
3082
3083 LIBTEST_API int STDCALL 
3084 mono_test_marshal_variant_in_ushort_unmanaged(VarFunc func)
3085 {
3086         VARIANT vt;
3087         vt.vt = VT_UI2;
3088         vt.uiVal = 100;
3089         return func (VT_UI2, vt);
3090 }
3091
3092 LIBTEST_API int STDCALL 
3093 mono_test_marshal_variant_in_int_unmanaged(VarFunc func)
3094 {
3095         VARIANT vt;
3096         vt.vt = VT_I4;
3097         vt.lVal = -100;
3098         return func (VT_I4, vt);
3099 }
3100
3101 LIBTEST_API int STDCALL 
3102 mono_test_marshal_variant_in_uint_unmanaged(VarFunc func)
3103 {
3104         VARIANT vt;
3105         vt.vt = VT_UI4;
3106         vt.ulVal = 100;
3107         return func (VT_UI4, vt);
3108 }
3109
3110 LIBTEST_API int STDCALL 
3111 mono_test_marshal_variant_in_long_unmanaged(VarFunc func)
3112 {
3113         VARIANT vt;
3114         vt.vt = VT_I8;
3115         vt.llVal = -100;
3116         return func (VT_I8, vt);
3117 }
3118
3119 LIBTEST_API int STDCALL 
3120 mono_test_marshal_variant_in_ulong_unmanaged(VarFunc func)
3121 {
3122         VARIANT vt;
3123         vt.vt = VT_UI8;
3124         vt.ullVal = 100;
3125         return func (VT_UI8, vt);
3126 }
3127
3128 LIBTEST_API int STDCALL 
3129 mono_test_marshal_variant_in_float_unmanaged(VarFunc func)
3130 {
3131         VARIANT vt;
3132         vt.vt = VT_R4;
3133         vt.fltVal = 3.14;
3134         return func (VT_R4, vt);
3135 }
3136
3137 LIBTEST_API int STDCALL 
3138 mono_test_marshal_variant_in_double_unmanaged(VarFunc func)
3139 {
3140         VARIANT vt;
3141         vt.vt = VT_R8;
3142         vt.dblVal = 3.14;
3143         return func (VT_R8, vt);
3144 }
3145
3146 LIBTEST_API int STDCALL 
3147 mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func)
3148 {
3149         VARIANT vt;
3150         vt.vt = VT_BSTR;
3151         vt.bstrVal = marshal_bstr_alloc("PI");
3152         return func (VT_BSTR, vt);
3153 }
3154
3155 LIBTEST_API int STDCALL 
3156 mono_test_marshal_variant_in_bool_true_unmanaged(VarFunc func)
3157 {
3158         VARIANT vt;
3159         vt.vt = VT_BOOL;
3160         vt.boolVal = VARIANT_TRUE;
3161         return func (VT_BOOL, vt);
3162 }
3163
3164 LIBTEST_API int STDCALL 
3165 mono_test_marshal_variant_in_bool_false_unmanaged(VarFunc func)
3166 {
3167         VARIANT vt;
3168         vt.vt = VT_BOOL;
3169         vt.boolVal = VARIANT_FALSE;
3170         return func (VT_BOOL, vt);
3171 }
3172
3173 LIBTEST_API int STDCALL 
3174 mono_test_marshal_variant_out_sbyte_unmanaged(VarRefFunc func)
3175 {
3176         VARIANT vt;
3177         VariantInit (&vt);
3178         func (VT_I1, &vt);
3179         if (vt.vt == VT_I1 && vt.cVal == -100)
3180                 return 0;
3181         return 1;
3182 }
3183
3184 LIBTEST_API int STDCALL 
3185 mono_test_marshal_variant_out_byte_unmanaged(VarRefFunc func)
3186 {
3187         VARIANT vt;
3188         VariantInit (&vt);
3189         func (VT_UI1, &vt);
3190         if (vt.vt == VT_UI1 && vt.bVal == 100)
3191                 return 0;
3192         return 1;
3193 }
3194
3195 LIBTEST_API int STDCALL 
3196 mono_test_marshal_variant_out_short_unmanaged(VarRefFunc func)
3197 {
3198         VARIANT vt;
3199         VariantInit (&vt);
3200         func (VT_I2, &vt);
3201         if (vt.vt == VT_I2 && vt.iVal == -100)
3202                 return 0;
3203         return 1;
3204 }
3205
3206 LIBTEST_API int STDCALL 
3207 mono_test_marshal_variant_out_ushort_unmanaged(VarRefFunc func)
3208 {
3209         VARIANT vt;
3210         VariantInit (&vt);
3211         func (VT_UI2, &vt);
3212         if (vt.vt == VT_UI2 && vt.uiVal == 100)
3213                 return 0;
3214         return 1;
3215 }
3216
3217 LIBTEST_API int STDCALL 
3218 mono_test_marshal_variant_out_int_unmanaged(VarRefFunc func)
3219 {
3220         VARIANT vt;
3221         VariantInit (&vt);
3222         func (VT_I4, &vt);
3223         if (vt.vt == VT_I4 && vt.lVal == -100)
3224                 return 0;
3225         return 1;
3226 }
3227
3228 LIBTEST_API int STDCALL 
3229 mono_test_marshal_variant_out_uint_unmanaged(VarRefFunc func)
3230 {
3231         VARIANT vt;
3232         VariantInit (&vt);
3233         func (VT_UI4, &vt);
3234         if (vt.vt == VT_UI4 && vt.ulVal == 100)
3235                 return 0;
3236         return 1;
3237 }
3238
3239 LIBTEST_API int STDCALL 
3240 mono_test_marshal_variant_out_long_unmanaged(VarRefFunc func)
3241 {
3242         VARIANT vt;
3243         VariantInit (&vt);
3244         func (VT_I8, &vt);
3245         if (vt.vt == VT_I8 && vt.llVal == -100)
3246                 return 0;
3247         return 1;
3248 }
3249
3250 LIBTEST_API int STDCALL 
3251 mono_test_marshal_variant_out_ulong_unmanaged(VarRefFunc func)
3252 {
3253         VARIANT vt;
3254         VariantInit (&vt);
3255         func (VT_UI8, &vt);
3256         if (vt.vt == VT_UI8 && vt.ullVal == 100)
3257                 return 0;
3258         return 1;
3259 }
3260
3261 LIBTEST_API int STDCALL 
3262 mono_test_marshal_variant_out_float_unmanaged(VarRefFunc func)
3263 {
3264         VARIANT vt;
3265         VariantInit (&vt);
3266         func (VT_R4, &vt);
3267         if (vt.vt == VT_R4 && fabs (vt.fltVal - 3.14f) < 1e-10)
3268                 return 0;
3269         return 1;
3270 }
3271
3272 LIBTEST_API int STDCALL 
3273 mono_test_marshal_variant_out_double_unmanaged(VarRefFunc func)
3274 {
3275         VARIANT vt;
3276         VariantInit (&vt);
3277         func (VT_R8, &vt);
3278         if (vt.vt == VT_R8 && fabs (vt.dblVal - 3.14) < 1e-10)
3279                 return 0;
3280         return 1;
3281 }
3282
3283 LIBTEST_API int STDCALL 
3284 mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func)
3285 {
3286         VARIANT vt;
3287         gchar* bstr_utf8;
3288         gint32 result = 0;
3289
3290
3291         VariantInit (&vt);
3292         func (VT_BSTR, &vt);
3293         bstr_utf8 = g_utf16_to_utf8 (vt.bstrVal, -1, NULL, NULL, NULL);
3294         result = strcmp("PI", bstr_utf8);
3295         g_free(bstr_utf8);
3296         if (vt.vt == VT_BSTR && !result)
3297                 return 0;
3298         return 1;
3299 }
3300
3301 LIBTEST_API int STDCALL 
3302 mono_test_marshal_variant_out_bool_true_unmanaged(VarRefFunc func)
3303 {
3304         VARIANT vt;
3305         VariantInit (&vt);
3306         func (VT_BOOL, &vt);
3307         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
3308                 return 0;
3309         return 1;
3310 }
3311
3312 LIBTEST_API int STDCALL 
3313 mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
3314 {
3315         VARIANT vt;
3316         VariantInit (&vt);
3317         func (VT_BOOL, &vt);
3318         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
3319                 return 0;
3320         return 1;
3321 }
3322
3323 typedef struct MonoComObject MonoComObject;
3324
3325 typedef struct
3326 {
3327         int (STDCALL *QueryInterface)(MonoComObject* pUnk, gpointer riid, gpointer* ppv);
3328         int (STDCALL *AddRef)(MonoComObject* pUnk);
3329         int (STDCALL *Release)(MonoComObject* pUnk);
3330         int (STDCALL *get_ITest)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3331         int (STDCALL *SByteIn)(MonoComObject* pUnk, char a);
3332         int (STDCALL *ByteIn)(MonoComObject* pUnk, unsigned char a);
3333         int (STDCALL *ShortIn)(MonoComObject* pUnk, short a);
3334         int (STDCALL *UShortIn)(MonoComObject* pUnk, unsigned short a);
3335         int (STDCALL *IntIn)(MonoComObject* pUnk, int a);
3336         int (STDCALL *UIntIn)(MonoComObject* pUnk, unsigned int a);
3337         int (STDCALL *LongIn)(MonoComObject* pUnk, gint64 a);
3338         int (STDCALL *ULongIn)(MonoComObject* pUnk, guint64 a);
3339         int (STDCALL *FloatIn)(MonoComObject* pUnk, float a);
3340         int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a);
3341         int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
3342         int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3343         int (STDCALL *Return22NoICall)(MonoComObject* pUnk);
3344 } MonoIUnknown;
3345
3346 struct MonoComObject
3347 {
3348         MonoIUnknown* vtbl;
3349         int m_ref;
3350 };
3351
3352 static GUID IID_ITest = {0, 0, 0, {0,0,0,0,0,0,0,1}};
3353 static GUID IID_IMonoUnknown = {0, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3354 static GUID IID_IMonoDispatch = {0x00020400, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3355
3356 LIBTEST_API int STDCALL
3357 MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv)
3358 {
3359
3360         *ppv = NULL;
3361         if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) {
3362                 *ppv = pUnk;
3363                 return S_OK;
3364         }
3365         else if (!memcmp(riid, &IID_ITest, sizeof(GUID))) {
3366                 *ppv = pUnk;
3367                 return S_OK;
3368         }
3369         else if (!memcmp(riid, &IID_IMonoDispatch, sizeof(GUID))) {
3370                 *ppv = pUnk;
3371                 return S_OK;
3372         }
3373         return 0x80004002; //E_NOINTERFACE;
3374 }
3375
3376 LIBTEST_API int STDCALL 
3377 MonoAddRef(MonoComObject* pUnk)
3378 {
3379         return ++(pUnk->m_ref);
3380 }
3381
3382 LIBTEST_API int STDCALL 
3383 MonoRelease(MonoComObject* pUnk)
3384 {
3385         return --(pUnk->m_ref);
3386 }
3387
3388 LIBTEST_API int STDCALL 
3389 SByteIn(MonoComObject* pUnk, char a)
3390 {
3391         return S_OK;
3392 }
3393
3394 LIBTEST_API int STDCALL 
3395 ByteIn(MonoComObject* pUnk, unsigned char a)
3396 {
3397         return S_OK;
3398 }
3399
3400 LIBTEST_API int STDCALL 
3401 ShortIn(MonoComObject* pUnk, short a)
3402 {
3403         return S_OK;
3404 }
3405
3406 LIBTEST_API int STDCALL 
3407 UShortIn(MonoComObject* pUnk, unsigned short a)
3408 {
3409         return S_OK;
3410 }
3411
3412 LIBTEST_API int STDCALL 
3413 IntIn(MonoComObject* pUnk, int a)
3414 {
3415         return S_OK;
3416 }
3417
3418 LIBTEST_API int STDCALL 
3419 UIntIn(MonoComObject* pUnk, unsigned int a)
3420 {
3421         return S_OK;
3422 }
3423
3424 LIBTEST_API int STDCALL 
3425 LongIn(MonoComObject* pUnk, gint64 a)
3426 {
3427         return S_OK;
3428 }
3429
3430 LIBTEST_API int STDCALL 
3431 ULongIn(MonoComObject* pUnk, guint64 a)
3432 {
3433         return S_OK;
3434 }
3435
3436 LIBTEST_API int STDCALL 
3437 FloatIn(MonoComObject* pUnk, float a)
3438 {
3439         return S_OK;
3440 }
3441
3442 LIBTEST_API int STDCALL 
3443 DoubleIn(MonoComObject* pUnk, double a)
3444 {
3445         return S_OK;
3446 }
3447
3448 LIBTEST_API int STDCALL 
3449 ITestIn(MonoComObject* pUnk, MonoComObject *pUnk2)
3450 {
3451         return S_OK;
3452 }
3453
3454 LIBTEST_API int STDCALL 
3455 ITestOut(MonoComObject* pUnk, MonoComObject* *ppUnk)
3456 {
3457         return S_OK;
3458 }
3459
3460 LIBTEST_API int STDCALL
3461 Return22NoICall(MonoComObject* pUnk)
3462 {
3463         return 22;
3464 }
3465
3466
3467 static void create_com_object (MonoComObject** pOut);
3468
3469 LIBTEST_API int STDCALL 
3470 get_ITest(MonoComObject* pUnk, MonoComObject* *ppUnk)
3471 {
3472         create_com_object (ppUnk);
3473         return S_OK;
3474 }
3475
3476 static void create_com_object (MonoComObject** pOut)
3477 {
3478         *pOut = marshal_new0 (MonoComObject, 1);
3479         (*pOut)->vtbl = marshal_new0 (MonoIUnknown, 1);
3480
3481         (*pOut)->m_ref = 1;
3482         (*pOut)->vtbl->QueryInterface = MonoQueryInterface;
3483         (*pOut)->vtbl->AddRef = MonoAddRef;
3484         (*pOut)->vtbl->Release = MonoRelease;
3485         (*pOut)->vtbl->SByteIn = SByteIn;
3486         (*pOut)->vtbl->ByteIn = ByteIn;
3487         (*pOut)->vtbl->ShortIn = ShortIn;
3488         (*pOut)->vtbl->UShortIn = UShortIn;
3489         (*pOut)->vtbl->IntIn = IntIn;
3490         (*pOut)->vtbl->UIntIn = UIntIn;
3491         (*pOut)->vtbl->LongIn = LongIn;
3492         (*pOut)->vtbl->ULongIn = ULongIn;
3493         (*pOut)->vtbl->FloatIn = FloatIn;
3494         (*pOut)->vtbl->DoubleIn = DoubleIn;
3495         (*pOut)->vtbl->ITestIn = ITestIn;
3496         (*pOut)->vtbl->ITestOut = ITestOut;
3497         (*pOut)->vtbl->get_ITest = get_ITest;
3498         (*pOut)->vtbl->Return22NoICall = Return22NoICall;
3499 }
3500
3501 static MonoComObject* same_object = NULL;
3502
3503 LIBTEST_API int STDCALL 
3504 mono_test_marshal_com_object_create(MonoComObject* *pUnk)
3505 {
3506         create_com_object (pUnk);
3507
3508         if (!same_object)
3509                 same_object = *pUnk;
3510
3511         return 0;
3512 }
3513
3514 LIBTEST_API int STDCALL 
3515 mono_test_marshal_com_object_same(MonoComObject* *pUnk)
3516 {
3517         *pUnk = same_object;
3518
3519         return 0;
3520 }
3521
3522 LIBTEST_API int STDCALL 
3523 mono_test_marshal_com_object_destroy(MonoComObject *pUnk)
3524 {
3525         int ref = --(pUnk->m_ref);
3526         g_free(pUnk->vtbl);
3527         g_free(pUnk);
3528
3529         return ref;
3530 }
3531
3532 LIBTEST_API int STDCALL 
3533 mono_test_marshal_com_object_ref_count(MonoComObject *pUnk)
3534 {
3535         return pUnk->m_ref;
3536 }
3537
3538 LIBTEST_API int STDCALL 
3539 mono_test_marshal_ccw_itest (MonoComObject *pUnk)
3540 {
3541         int hr = 0;
3542         MonoComObject* pTest;
3543
3544         if (!pUnk)
3545                 return 1;
3546
3547         hr = pUnk->vtbl->SByteIn (pUnk, -100);
3548         if (hr != 0)
3549                 return 2;
3550         hr = pUnk->vtbl->ByteIn (pUnk, 100);
3551         if (hr != 0)
3552                 return 3;
3553         hr = pUnk->vtbl->ShortIn (pUnk, -100);
3554         if (hr != 0)
3555                 return 4;
3556         hr = pUnk->vtbl->UShortIn (pUnk, 100);
3557         if (hr != 0)
3558                 return 5;
3559         hr = pUnk->vtbl->IntIn (pUnk, -100);
3560         if (hr != 0)
3561                 return 6;
3562         hr = pUnk->vtbl->UIntIn (pUnk, 100);
3563         if (hr != 0)
3564                 return 7;
3565         hr = pUnk->vtbl->LongIn (pUnk, -100);
3566         if (hr != 0)
3567                 return 8;
3568         hr = pUnk->vtbl->ULongIn (pUnk, 100);
3569         if (hr != 0)
3570                 return 9;
3571         hr = pUnk->vtbl->FloatIn (pUnk, 3.14f);
3572         if (hr != 0)
3573                 return 10;
3574         hr = pUnk->vtbl->DoubleIn (pUnk, 3.14);
3575         if (hr != 0)
3576                 return 11;
3577         hr = pUnk->vtbl->ITestIn (pUnk, pUnk);
3578         if (hr != 0)
3579                 return 12;
3580         hr = pUnk->vtbl->ITestOut (pUnk, &pTest);
3581         if (hr != 0)
3582                 return 13;
3583
3584         return 0;
3585 }
3586
3587 // Xamarin-47560
3588 LIBTEST_API int STDCALL
3589 mono_test_marshal_array_ccw_itest (int count, MonoComObject ** ppUnk)
3590 {
3591         int hr = 0;
3592
3593         if (!ppUnk)
3594                 return 1;
3595
3596         if (count < 1)
3597                 return 2;
3598
3599         if (!ppUnk[0])
3600                 return 3;
3601
3602         hr = ppUnk[0]->vtbl->SByteIn (ppUnk[0], -100);
3603         if (hr != 0)
3604                 return 4;
3605
3606         return 0;
3607 }
3608
3609 /*
3610  * mono_method_get_unmanaged_thunk tests
3611  */
3612
3613 #if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__) || defined(__OpenBSD__)) || (defined(__ppc__) && defined(__APPLE__)))
3614 #define ALIGN(size) __attribute__ ((__aligned__(size)))
3615 #else
3616 #define ALIGN(size)
3617 #endif
3618
3619
3620 /* thunks.cs:TestStruct */
3621 typedef struct _TestStruct {
3622         int A;
3623         double B;
3624 } TestStruct;
3625
3626 /* Searches for mono symbols in all loaded modules */
3627 static gpointer
3628 lookup_mono_symbol (const char *symbol_name)
3629 {
3630         gpointer symbol;
3631         if (g_module_symbol (g_module_open (NULL, G_MODULE_BIND_LAZY), symbol_name, &symbol))
3632                 return symbol;
3633         else
3634                 return NULL;
3635 }
3636
3637 LIBTEST_API gpointer STDCALL
3638 mono_test_marshal_lookup_symbol (const char *symbol_name)
3639 {
3640         return lookup_mono_symbol (symbol_name);
3641 }
3642
3643 #define MONO_BEGIN_EFRAME { void *__dummy; void *__region_cookie = mono_threads_enter_gc_unsafe_region ? mono_threads_enter_gc_unsafe_region (&__dummy) : NULL;
3644 #define MONO_END_EFRAME if (mono_threads_exit_gc_unsafe_region) mono_threads_exit_gc_unsafe_region (__region_cookie, &__dummy); }
3645
3646 /**
3647  * test_method_thunk:
3648  *
3649  * @test_id: the test number
3650  * @test_method_handle: MonoMethod* of the C# test method
3651  * @create_object_method_handle: MonoMethod* of thunks.cs:Test.CreateObject
3652  */
3653 LIBTEST_API int STDCALL  
3654 test_method_thunk (int test_id, gpointer test_method_handle, gpointer create_object_method_handle)
3655 {
3656         int ret = 0;
3657
3658         gpointer (*mono_method_get_unmanaged_thunk)(gpointer)
3659                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_method_get_unmanaged_thunk");
3660
3661         gpointer (*mono_string_new_wrapper)(const char *)
3662                 = (gpointer (*)(const char *))lookup_mono_symbol ("mono_string_new_wrapper");
3663
3664         char *(*mono_string_to_utf8)(gpointer)
3665                 = (char *(*)(gpointer))lookup_mono_symbol ("mono_string_to_utf8");
3666
3667         gpointer (*mono_object_unbox)(gpointer)
3668                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_object_unbox");
3669
3670         gpointer (*mono_threads_enter_gc_unsafe_region) (gpointer)
3671                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_threads_enter_gc_unsafe_region");
3672
3673         void (*mono_threads_exit_gc_unsafe_region) (gpointer, gpointer)
3674                 = (void (*)(gpointer, gpointer))lookup_mono_symbol ("mono_threads_exit_gc_unsafe_region");
3675
3676         
3677
3678         gpointer test_method, ex = NULL;
3679         gpointer (STDCALL *CreateObject)(gpointer*);
3680
3681         MONO_BEGIN_EFRAME;
3682
3683         if (!mono_method_get_unmanaged_thunk) {
3684                 ret = 1;
3685                 goto done;
3686         }
3687
3688         test_method =  mono_method_get_unmanaged_thunk (test_method_handle);
3689         if (!test_method) {
3690                 ret = 2;
3691                 goto done;
3692         }
3693
3694         CreateObject = (gpointer (STDCALL *)(gpointer *))mono_method_get_unmanaged_thunk (create_object_method_handle);
3695         if (!CreateObject) {
3696                 ret = 3;
3697                 goto done;
3698         }
3699         
3700
3701         switch (test_id) {
3702
3703         case 0: {
3704                 /* thunks.cs:Test.Test0 */
3705                 void (STDCALL *F)(gpointer *) = (void (STDCALL *)(gpointer *))test_method;
3706                 F (&ex);
3707                 break;
3708         }
3709
3710         case 1: {
3711                 /* thunks.cs:Test.Test1 */
3712                 int (STDCALL *F)(gpointer *) = (int (STDCALL *)(gpointer *))test_method;
3713                 if (F (&ex) != 42) {
3714                         ret = 4;
3715                         goto done;
3716                 }
3717                 break;
3718         }
3719
3720         case 2: {
3721                 /* thunks.cs:Test.Test2 */
3722                 gpointer (STDCALL *F)(gpointer, gpointer*) = (gpointer (STDCALL *)(gpointer, gpointer *))test_method;
3723                 gpointer str = mono_string_new_wrapper ("foo");
3724                 if (str != F (str, &ex)) {
3725                         ret = 4;
3726                         goto done;
3727                 }
3728                 break;
3729         }
3730
3731         case 3: {
3732                 /* thunks.cs:Test.Test3 */
3733                 gpointer (STDCALL *F)(gpointer, gpointer, gpointer*);
3734                 gpointer obj;
3735                 gpointer str;
3736
3737                 F = (gpointer (STDCALL *)(gpointer, gpointer, gpointer *))test_method;
3738                 obj = CreateObject (&ex);
3739                 str = mono_string_new_wrapper ("bar");
3740
3741                 if (str != F (obj, str, &ex)) {
3742                         ret = 4;
3743                         goto done;
3744                 }
3745                 break;
3746         }
3747
3748         case 4: {
3749                 /* thunks.cs:Test.Test4 */
3750                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3751                 gpointer obj;
3752                 gpointer str;
3753
3754                 F = (int (STDCALL *)(gpointer, gpointer, int, gpointer *))test_method;
3755                 obj = CreateObject (&ex);
3756                 str = mono_string_new_wrapper ("bar");
3757
3758                 if (42 != F (obj, str, 42, &ex)) {
3759                         ret = 4;
3760                         goto done;
3761                 }
3762
3763                 break;
3764         }
3765
3766         case 5: {
3767                 /* thunks.cs:Test.Test5 */
3768                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3769                 gpointer obj;
3770                 gpointer str;
3771
3772                 F = (int (STDCALL *)(gpointer, gpointer, int, gpointer *))test_method;
3773                 obj = CreateObject (&ex);
3774                 str = mono_string_new_wrapper ("bar");
3775
3776                 F (obj, str, 42, &ex);
3777                 if (!ex) {
3778                         ret = 4;
3779                         goto done;
3780                 }
3781
3782                 break;
3783         }
3784
3785         case 6: {
3786                 /* thunks.cs:Test.Test6 */
3787                 int (STDCALL *F)(gpointer, guint8, gint16, gint32, gint64, float, double,
3788                                  gpointer, gpointer*);
3789                 gpointer obj;
3790                 gpointer str = mono_string_new_wrapper ("Test6");
3791                 int res;
3792
3793                 F = (int (STDCALL *)(gpointer, guint8, gint16, gint32, gint64, float, double, gpointer, gpointer *))test_method;
3794                 obj = CreateObject (&ex);
3795
3796                 res = F (obj, 254, 32700, -245378, 6789600, 3.1415, 3.1415, str, &ex);
3797                 if (ex) {
3798                         ret = 4;
3799                         goto done;
3800                 }
3801
3802                 if (!res) {
3803                         ret = 5;
3804                         goto done;
3805                 }
3806
3807                 break;
3808         }
3809
3810         case 7: {
3811                 /* thunks.cs:Test.Test7 */
3812                 gint64 (STDCALL *F)(gpointer*) = (gint64 (STDCALL *)(gpointer *))test_method;
3813                 if (F (&ex) != G_MAXINT64) {
3814                         ret = 4;
3815                         goto done;
3816                 }
3817                 break;
3818         }
3819
3820         case 8: {
3821                 /* thunks.cs:Test.Test8 */
3822                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3823                                  gpointer*, gpointer*);
3824
3825                 guint8 a1;
3826                 gint16 a2;
3827                 gint32 a3;
3828                 gint64 a4;
3829                 float a5;
3830                 double a6;
3831                 gpointer a7;
3832
3833                 F = (void (STDCALL *)(guint8 *, gint16 *, gint32 *, gint64 *, float *, double *,
3834                         gpointer *, gpointer *))test_method;
3835
3836                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3837                 if (ex) {
3838                         ret = 4;
3839                         goto done;
3840                 }
3841
3842                 if (!(a1 == 254 &&
3843                       a2 == 32700 &&
3844                       a3 == -245378 &&
3845                       a4 == 6789600 &&
3846                       (fabs (a5 - 3.1415) < 0.001) &&
3847                       (fabs (a6 - 3.1415) < 0.001) &&
3848                       strcmp (mono_string_to_utf8 (a7), "Test8") == 0)){
3849                                 ret = 5;
3850                                 goto done;
3851                         }
3852
3853                 break;
3854         }
3855
3856         case 9: {
3857                 /* thunks.cs:Test.Test9 */
3858                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3859                         gpointer*, gpointer*);
3860
3861                 guint8 a1;
3862                 gint16 a2;
3863                 gint32 a3;
3864                 gint64 a4;
3865                 float a5;
3866                 double a6;
3867                 gpointer a7;
3868
3869                 F = (void (STDCALL *)(guint8 *, gint16 *, gint32 *, gint64 *, float *, double *,
3870                         gpointer *, gpointer *))test_method;
3871
3872                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3873                 if (!ex) {
3874                         ret = 4;
3875                         goto done;
3876                 }
3877
3878                 break;
3879         }
3880
3881         case 10: {
3882                 /* thunks.cs:Test.Test10 */
3883                 void (STDCALL *F)(gpointer*, gpointer*);
3884
3885                 gpointer obj1, obj2;
3886
3887                 obj1 = obj2 = CreateObject (&ex);
3888                 if (ex) {
3889                         ret = 4;
3890                         goto done;
3891                 }
3892
3893                 F = (void (STDCALL *)(gpointer *, gpointer *))test_method;
3894
3895                 F (&obj1, &ex);
3896                 if (ex) {
3897                         ret = 5;
3898                         goto done;
3899                 }
3900
3901                 if (obj1 == obj2) {
3902                         ret = 6;
3903                         goto done;
3904                 }
3905
3906                 break;
3907         }
3908
3909         case 100: {
3910                 /* thunks.cs:TestStruct.Test0 */
3911                 int (STDCALL *F)(gpointer*, gpointer*);
3912
3913                 gpointer obj;
3914                 TestStruct *a1;
3915                 int res;
3916
3917                 obj = CreateObject (&ex);
3918                 if (ex) {
3919                         ret = 4;
3920                         goto done;
3921                 }
3922
3923                 if (!obj) {
3924                         ret = 5;
3925                         goto done;
3926                 }
3927
3928                 a1 = (TestStruct *)mono_object_unbox (obj);
3929                 if (!a1) {
3930                         ret = 6;
3931                         goto done;
3932                 }
3933
3934                 a1->A = 42;
3935                 a1->B = 3.1415;
3936
3937                 F = (int (STDCALL *)(gpointer *, gpointer *))test_method;
3938
3939                 res = F ((gpointer *)obj, &ex);
3940                 if (ex) {
3941                         ret = 7;
3942                         goto done;
3943                 }
3944
3945                 if (!res) {
3946                         ret = 8;
3947                         goto done;
3948                 }
3949
3950                 /* check whether the call was really by value */
3951                 if (a1->A != 42 || a1->B != 3.1415) {
3952                         ret = 9;
3953                         goto done;
3954                 }
3955
3956                 break;
3957         }
3958
3959         case 101: {
3960                 /* thunks.cs:TestStruct.Test1 */
3961                 void (STDCALL *F)(gpointer, gpointer*);
3962
3963                 TestStruct *a1;
3964                 gpointer obj;
3965
3966                 obj = CreateObject (&ex);
3967                 if (ex) {
3968                         ret = 4;
3969                         goto done;
3970                 }
3971
3972                 if (!obj) {
3973                         ret = 5;
3974                         goto done;
3975                 }
3976
3977                 a1 = (TestStruct *)mono_object_unbox (obj);
3978                 if (!a1) {
3979                         ret = 6;
3980                         goto done;
3981                 }
3982
3983                 F = (void (STDCALL *)(gpointer, gpointer *))test_method;
3984
3985                 F (obj, &ex);
3986                 if (ex) {
3987                         ret = 7;
3988                         goto done;
3989                 }
3990
3991                 if (a1->A != 42) {
3992                         ret = 8;
3993                         goto done;
3994                 }
3995
3996                 if (!(fabs (a1->B - 3.1415) < 0.001)) {
3997                         ret = 9;
3998                         goto done;
3999                 }
4000
4001                 break;
4002         }
4003
4004         case 102: {
4005                 /* thunks.cs:TestStruct.Test2 */
4006                 gpointer (STDCALL *F)(gpointer*);
4007
4008                 TestStruct *a1;
4009                 gpointer obj;
4010
4011                 F = (gpointer (STDCALL *)(gpointer *))test_method;
4012
4013                 obj = F (&ex);
4014                 if (ex) {
4015                         ret = 4;
4016                         goto done;
4017                 }
4018
4019                 if (!obj) {
4020                         ret = 5;
4021                         goto done;
4022                 }
4023
4024                 a1 = (TestStruct *)mono_object_unbox (obj);
4025
4026                 if (a1->A != 42) {
4027                         ret = 5;
4028                         goto done;
4029                 }
4030
4031                 if (!(fabs (a1->B - 3.1415) < 0.001)) {
4032                         ret = 6;
4033                         goto done;
4034                 }
4035
4036                 break;
4037         }
4038
4039         case 103: {
4040                 /* thunks.cs:TestStruct.Test3 */
4041                 void (STDCALL *F)(gpointer, gpointer*);
4042
4043                 TestStruct *a1;
4044                 gpointer obj;
4045
4046                 obj = CreateObject (&ex);
4047                 if (ex) {
4048                         ret = 4;
4049                         goto done;
4050                 }
4051
4052                 if (!obj) {
4053                         ret = 5;
4054                         goto done;
4055                 }
4056                 
4057                 a1 = (TestStruct *)mono_object_unbox (obj);
4058
4059                 if (!a1) {
4060                         ret = 6;
4061                         goto done;
4062                 }
4063
4064                 a1->A = 42;
4065                 a1->B = 3.1415;
4066
4067                 F = (void (STDCALL *)(gpointer, gpointer *))test_method;
4068
4069                 F (obj, &ex);
4070                 if (ex) {
4071                         ret = 4;
4072                         goto done;
4073                 }
4074
4075                 if (a1->A != 1) {
4076                         ret = 5;
4077                         goto done;
4078                 }
4079
4080                 if (a1->B != 17) {
4081                         ret = 6;
4082                         goto done;
4083                 }
4084
4085                 break;
4086         }
4087
4088         default:
4089                 ret = 9;
4090
4091         }
4092 done:
4093         MONO_END_EFRAME;
4094
4095         return ret;
4096 }
4097
4098 typedef struct 
4099 {
4100         char a;
4101 } winx64_struct1;
4102
4103 LIBTEST_API int STDCALL  
4104 mono_test_Winx64_struct1_in (winx64_struct1 var)
4105 {
4106         if (var.a != 123)
4107                 return 1;
4108         return 0;
4109 }
4110
4111 typedef struct
4112 {
4113         char a;
4114         char b;
4115 } winx64_struct2;
4116
4117 LIBTEST_API int STDCALL  
4118 mono_test_Winx64_struct2_in (winx64_struct2 var)
4119 {
4120         if (var.a != 4)
4121                 return 1;
4122         if (var.b != 5)
4123                 return 2;
4124         return 0;
4125 }
4126
4127
4128 typedef struct
4129 {
4130         char a;
4131         char b;
4132         short c;
4133 } winx64_struct3;
4134
4135 LIBTEST_API int STDCALL  
4136 mono_test_Winx64_struct3_in (winx64_struct3 var)
4137 {
4138         if (var.a != 4)
4139                 return 1;
4140         if (var.b != 5)
4141                 return 2;
4142         if (var.c != 0x1234)
4143                 return 3;
4144         return 0;
4145 }
4146
4147 typedef struct
4148 {
4149         char a;
4150         char b;
4151         short c;
4152         unsigned int d;
4153 } winx64_struct4;
4154
4155 LIBTEST_API int STDCALL  
4156 mono_test_Winx64_struct4_in (winx64_struct4 var)
4157 {
4158         if (var.a != 4)
4159                 return 1;
4160         if (var.b != 5)
4161                 return 2;
4162         if (var.c != 0x1234)
4163                 return 3;
4164         if (var.d != 0x87654321)
4165                 return 4;
4166         return 0;
4167 }
4168
4169 typedef struct
4170 {
4171         char a;
4172         char b;
4173         char c;
4174 } winx64_struct5;
4175
4176 LIBTEST_API int STDCALL  
4177 mono_test_Winx64_struct5_in (winx64_struct5 var)
4178 {
4179         if (var.a != 4)
4180                 return 1;
4181         if (var.b != 5)
4182                 return 2;
4183         if (var.c != 6)
4184                 return 3;
4185         return 0;
4186 }
4187
4188 typedef struct
4189 {
4190         winx64_struct1 a;
4191         short b;
4192         char c;
4193 } winx64_struct6;
4194
4195 LIBTEST_API int STDCALL  
4196 mono_test_Winx64_struct6_in (winx64_struct6 var)
4197 {
4198         if (var.a.a != 4)
4199                 return 1;
4200         if (var.b != 5)
4201                 return 2;
4202         if (var.c != 6)
4203                 return 3;
4204         return 0;
4205 }
4206
4207 LIBTEST_API int STDCALL  
4208 mono_test_Winx64_structs_in1 (winx64_struct1 var1,
4209                          winx64_struct2 var2,
4210                          winx64_struct3 var3,
4211                          winx64_struct4 var4)
4212 {
4213         if (var1.a != 123)
4214                 return 1;
4215         
4216         if (var2.a != 4)
4217                 return 2;
4218         if (var2.b != 5)
4219                 return 3;
4220         
4221         if (var3.a != 4)
4222                 return 4;
4223         if (var3.b != 5)
4224                 return 2;
4225         if (var3.c != 0x1234)
4226                 return 5;
4227         
4228         if (var4.a != 4)
4229                 return 6;
4230         if (var4.b != 5)
4231                 return 7;
4232         if (var4.c != 0x1234)
4233                 return 8;
4234         if (var4.d != 0x87654321)
4235                 return 9;
4236         return 0;
4237 }
4238
4239 LIBTEST_API int STDCALL  
4240 mono_test_Winx64_structs_in2 (winx64_struct1 var1,
4241                          winx64_struct1 var2,
4242                          winx64_struct1 var3,
4243                          winx64_struct1 var4,
4244                          winx64_struct1 var5)
4245 {
4246         if (var1.a != 1)
4247                 return 1;
4248         if (var2.a != 2)
4249                 return 2;
4250         if (var3.a != 3)
4251                 return 3;
4252         if (var4.a != 4)
4253                 return 4;
4254         if (var5.a != 5)
4255                 return 5;
4256         
4257         return 0;
4258 }
4259
4260 LIBTEST_API int STDCALL  
4261 mono_test_Winx64_structs_in3 (winx64_struct1 var1,
4262                          winx64_struct5 var2,
4263                          winx64_struct1 var3,
4264                          winx64_struct5 var4,
4265                          winx64_struct1 var5,
4266                          winx64_struct5 var6)
4267 {
4268         if (var1.a != 1)
4269                 return 1;
4270         
4271         if (var2.a != 2)
4272                 return 2;
4273         if (var2.b != 3)
4274                 return 2;
4275         if (var2.c != 4)
4276                 return 4;
4277         
4278         if (var3.a != 5)
4279                 return 5;
4280         
4281         if (var4.a != 6)
4282                 return 6;
4283         if (var4.b != 7)
4284                 return 7;
4285         if (var4.c != 8)
4286                 return 8;
4287         
4288         if (var5.a != 9)
4289                 return 9;
4290
4291         if (var6.a != 10)
4292                 return 10;
4293         if (var6.b != 11)
4294                 return 11;
4295         if (var6.c != 12)
4296                 return 12;
4297         
4298         return 0;
4299 }
4300
4301 LIBTEST_API winx64_struct1 STDCALL  
4302 mono_test_Winx64_struct1_ret (void)
4303 {
4304         winx64_struct1 ret;
4305         ret.a = 123;
4306         return ret;
4307 }
4308
4309 LIBTEST_API winx64_struct2 STDCALL  
4310 mono_test_Winx64_struct2_ret (void)
4311 {
4312         winx64_struct2 ret;
4313         ret.a = 4;
4314         ret.b = 5;
4315         return ret;
4316 }
4317
4318 LIBTEST_API winx64_struct3 STDCALL  
4319 mono_test_Winx64_struct3_ret (void)
4320 {
4321         winx64_struct3 ret;
4322         ret.a = 4;
4323         ret.b = 5;
4324         ret.c = 0x1234;
4325         return ret;
4326 }
4327
4328 LIBTEST_API winx64_struct4 STDCALL  
4329 mono_test_Winx64_struct4_ret (void)
4330 {
4331         winx64_struct4 ret;
4332         ret.a = 4;
4333         ret.b = 5;
4334         ret.c = 0x1234;
4335         ret.d = 0x87654321;
4336         return ret;
4337 }
4338
4339 LIBTEST_API winx64_struct5 STDCALL  
4340 mono_test_Winx64_struct5_ret (void)
4341 {
4342         winx64_struct5 ret;
4343         ret.a = 4;
4344         ret.b = 5;
4345         ret.c = 6;
4346         return ret;
4347 }
4348
4349 LIBTEST_API winx64_struct1 STDCALL  
4350 mono_test_Winx64_struct1_ret_5_args (char a, char b, char c, char d, char e)
4351 {
4352         winx64_struct1 ret;
4353         ret.a = a + b + c + d + e;
4354         return ret;
4355 }
4356
4357 LIBTEST_API winx64_struct5 STDCALL
4358 mono_test_Winx64_struct5_ret6_args (char a, char b, char c, char d, char e)
4359 {
4360         winx64_struct5 ret;
4361         ret.a = a + b;
4362         ret.b = c + d;
4363         ret.c = e;
4364         return ret;
4365 }
4366
4367 typedef struct
4368 {
4369         float a;
4370         float b;
4371 } winx64_floatStruct;
4372
4373 LIBTEST_API int STDCALL  
4374 mono_test_Winx64_floatStruct (winx64_floatStruct a)
4375 {
4376         if (a.a > 5.6 || a.a < 5.4)
4377                 return 1;
4378
4379         if (a.b > 9.6 || a.b < 9.4)
4380                 return 2;
4381         
4382         return 0;
4383 }
4384
4385 typedef struct
4386 {
4387         double a;
4388 } winx64_doubleStruct;
4389
4390 LIBTEST_API int STDCALL  
4391 mono_test_Winx64_doubleStruct (winx64_doubleStruct a)
4392 {
4393         if (a.a > 5.6 || a.a < 5.4)
4394                 return 1;
4395         
4396         return 0;
4397 }
4398
4399 typedef int (STDCALL *managed_struct1_delegate) (winx64_struct1 a);
4400
4401 LIBTEST_API int STDCALL 
4402 mono_test_managed_Winx64_struct1_in(managed_struct1_delegate func)
4403 {
4404         winx64_struct1 val;
4405         val.a = 5;
4406         return func (val);
4407 }
4408
4409 typedef int (STDCALL *managed_struct5_delegate) (winx64_struct5 a);
4410
4411 LIBTEST_API int STDCALL 
4412 mono_test_managed_Winx64_struct5_in(managed_struct5_delegate func)
4413 {
4414         winx64_struct5 val;
4415         val.a = 5;
4416         val.b = 0x10;
4417         val.c = 0x99;
4418         return func (val);
4419 }
4420
4421 typedef int (STDCALL *managed_struct1_struct5_delegate) (winx64_struct1 a, winx64_struct5 b,
4422                                                          winx64_struct1 c, winx64_struct5 d,
4423                                                          winx64_struct1 e, winx64_struct5 f);
4424
4425 LIBTEST_API int STDCALL 
4426 mono_test_managed_Winx64_struct1_struct5_in(managed_struct1_struct5_delegate func)
4427 {
4428         winx64_struct1 a, c, e;
4429         winx64_struct5 b, d, f;
4430         a.a = 1;
4431         b.a = 2; b.b = 3; b.c = 4;
4432         c.a = 5;
4433         d.a = 6; d.b = 7; d.c = 8;
4434         e.a = 9;
4435         f.a = 10; f.b = 11; f.c = 12;
4436
4437         return func (a, b, c, d, e, f);
4438 }
4439
4440 typedef winx64_struct1 (STDCALL *managed_struct1_ret_delegate) (void);
4441
4442 LIBTEST_API int STDCALL 
4443 mono_test_Winx64_struct1_ret_managed (managed_struct1_ret_delegate func)
4444 {
4445         winx64_struct1 ret;
4446
4447         ret = func ();
4448
4449         if (ret.a != 0x45)
4450                 return 1;
4451         
4452         return 0;
4453 }
4454
4455 typedef winx64_struct5 (STDCALL *managed_struct5_ret_delegate) (void);
4456
4457 LIBTEST_API int STDCALL 
4458 mono_test_Winx64_struct5_ret_managed (managed_struct5_ret_delegate func)
4459 {
4460         winx64_struct5 ret;
4461
4462         ret = func ();
4463
4464         if (ret.a != 0x12)
4465                 return 1;
4466         if (ret.b != 0x34)
4467                 return 2;
4468         if (ret.c != 0x56)
4469                 return 3;
4470         
4471         return 0;
4472 }
4473
4474 LIBTEST_API int STDCALL 
4475 mono_test_marshal_bool_in (int arg, unsigned int expected, unsigned int bDefaultMarsh, unsigned int bBoolCustMarsh,
4476                            char bI1CustMarsh, unsigned char bU1CustMarsh, short bVBCustMarsh)
4477 {
4478         switch (arg) {
4479         case 1: 
4480                 if (bDefaultMarsh != expected)
4481                         return 1;
4482                 break;
4483         case 2: 
4484                 if (bBoolCustMarsh != expected)
4485                         return 2;
4486                 break;
4487         case 3: 
4488                 if (bI1CustMarsh != expected)
4489                         return 3;
4490                 break;
4491         case 4: 
4492                 if (bU1CustMarsh != expected)
4493                         return 4;
4494                 break;
4495         case 5: 
4496                 if (bVBCustMarsh != expected)
4497                         return 5;
4498                 break;
4499         default:
4500                 return 999;             
4501         }
4502         return 0;
4503 }
4504
4505 LIBTEST_API int STDCALL 
4506 mono_test_marshal_bool_out (int arg, unsigned int testVal, unsigned int* bDefaultMarsh, unsigned int* bBoolCustMarsh,
4507                            char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh)
4508 {
4509         switch (arg) {
4510         case 1: 
4511                 if (!bDefaultMarsh)
4512                         return 1;
4513                 *bDefaultMarsh = testVal;
4514                 break;  
4515         case 2: 
4516                 if (!bBoolCustMarsh)
4517                         return 2;
4518                 *bBoolCustMarsh = testVal;
4519                 break;  
4520         case 3: 
4521                 if (!bI1CustMarsh)
4522                         return 3;
4523                 *bI1CustMarsh = (char)testVal;
4524                 break;  
4525         case 4: 
4526                 if (!bU1CustMarsh)
4527                         return 4;
4528                 *bU1CustMarsh = (unsigned char)testVal;
4529                 break;  
4530         case 5: 
4531                 if (!bVBCustMarsh)
4532                         return 5;
4533                 *bVBCustMarsh = (unsigned short)testVal;
4534                 break;  
4535         default:
4536                 return 999;
4537         }
4538         return 0;
4539 }
4540
4541 LIBTEST_API int STDCALL 
4542 mono_test_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4543                             unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, 
4544                             unsigned short* bVBCustMarsh)
4545 {
4546         switch (arg) {
4547         case 1: 
4548                 if (!bDefaultMarsh)
4549                         return 1;
4550                 if (*bDefaultMarsh != expected)
4551                         return 2;
4552                 *bDefaultMarsh = testVal;
4553                 break;
4554         case 2: 
4555                 if (!bBoolCustMarsh)
4556                         return 3;
4557                 if (*bBoolCustMarsh != expected)
4558                         return 4;
4559                 *bBoolCustMarsh = testVal;
4560                 break;
4561         case 3: 
4562                 if (!bI1CustMarsh)
4563                         return 5;
4564                 if (*bI1CustMarsh != expected)
4565                         return 6;
4566                 *bI1CustMarsh = (char)testVal;
4567                 break;
4568         case 4: 
4569                 if (!bU1CustMarsh)
4570                         return 7;
4571                 if (*bU1CustMarsh != expected)
4572                         return 8;
4573                 *bU1CustMarsh = (unsigned char)testVal;
4574                 break;
4575         case 5: 
4576                 if (!bVBCustMarsh)
4577                         return 9;
4578                 if (*bVBCustMarsh != expected)
4579                         return 10;
4580                 *bVBCustMarsh = (unsigned short)testVal;
4581                 break;
4582         default:
4583                 return 999;             
4584         }
4585         return 0;
4586 }
4587
4588
4589 typedef int (STDCALL *MarshalBoolInDelegate) (int arg, unsigned int expected, unsigned int bDefaultMarsh,
4590         unsigned int bBoolCustMarsh, char bI1CustMarsh, unsigned char bU1CustMarsh, unsigned short bVBCustMarsh);
4591
4592 LIBTEST_API int STDCALL 
4593 mono_test_managed_marshal_bool_in (int arg, unsigned int expected, unsigned int testVal, MarshalBoolInDelegate pfcn)
4594 {
4595         if (!pfcn)
4596                 return 0x9900;
4597
4598         switch (arg) {
4599         case 1:
4600                 return pfcn (arg, expected, testVal, 0, 0, 0, 0);
4601         case 2:
4602                 return pfcn (arg, expected, 0, testVal,  0, 0, 0);
4603         case 3:
4604                 return pfcn (arg, expected, 0, 0, testVal, 0, 0);
4605         case 4:
4606                 return pfcn (arg, expected, 0, 0, 0, testVal, 0);
4607         case 5:
4608                 return pfcn (arg, expected, 0, 0, 0, 0, testVal);
4609         default:
4610                 return 0x9800;
4611         }
4612
4613         return 0;
4614 }
4615
4616 typedef int (STDCALL *MarshalBoolOutDelegate) (int arg, unsigned int expected, unsigned int* bDefaultMarsh,
4617         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4618
4619 LIBTEST_API int STDCALL 
4620 mono_test_managed_marshal_bool_out (int arg, unsigned int expected, unsigned int testVal, MarshalBoolOutDelegate pfcn)
4621 {
4622         int ret;
4623         unsigned int lDefaultMarsh, lBoolCustMarsh;
4624         char lI1CustMarsh = 0;
4625         unsigned char lU1CustMarsh = 0;
4626         unsigned short lVBCustMarsh = 0;
4627         lDefaultMarsh = lBoolCustMarsh = 0;
4628
4629         if (!pfcn)
4630                 return 0x9900;
4631
4632         switch (arg) {
4633         case 1: {
4634                 unsigned int ltVal = 0;
4635                 ret = pfcn (arg, testVal, &ltVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4636                 if (ret)
4637                         return 0x0100 + ret;
4638                 if (expected != ltVal)
4639                         return 0x0200;
4640                 break;
4641         }
4642         case 2: {
4643                 unsigned int ltVal = 0;
4644                 ret = pfcn (arg, testVal, &lDefaultMarsh, &ltVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4645                 if (ret)
4646                         return 0x0300 + ret;
4647                 if (expected != ltVal)
4648                         return 0x0400;
4649                 break;
4650         }
4651         case 3: {
4652                 char ltVal = 0;
4653                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &ltVal, &lU1CustMarsh, &lVBCustMarsh);
4654                 if (ret)
4655                         return 0x0500 + ret;
4656                 if (expected != ltVal)
4657                         return 0x0600;
4658                 break;
4659         }
4660         case 4: {
4661                 unsigned char ltVal = 0;
4662                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltVal, &lVBCustMarsh);
4663                 if (ret)
4664                         return 0x0700 + ret;
4665                 if (expected != ltVal)
4666                         return 0x0800;
4667                 break;
4668         }
4669         case 5: {
4670                 unsigned short ltVal = 0;
4671                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltVal);
4672                 if (ret)
4673                         return 0x0900 + ret;
4674                 if (expected != ltVal)
4675                         return 0x1000;
4676                 break;
4677         }
4678         default:
4679                 return 0x9800;
4680         }
4681
4682         return 0;
4683 }
4684
4685 typedef int (STDCALL *MarshalBoolRefDelegate) (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4686         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4687
4688 LIBTEST_API int STDCALL 
4689 mono_test_managed_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int outExpected,
4690                                     unsigned int outTestVal, MarshalBoolRefDelegate pfcn)
4691 {
4692         int ret;
4693         unsigned int lDefaultMarsh, lBoolCustMarsh;
4694         char lI1CustMarsh = 0;
4695         unsigned char lU1CustMarsh = 0;
4696         unsigned short lVBCustMarsh = 0;
4697         lDefaultMarsh = lBoolCustMarsh = 0;
4698
4699         if (!pfcn)
4700                 return 0x9900;
4701
4702         switch (arg) {
4703         case 1:
4704         {
4705                 unsigned int ltestVal = testVal;
4706                 ret = pfcn (arg, expected, outTestVal, &ltestVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4707                 if (ret)
4708                         return 0x0100 + ret;
4709                 if (outExpected != ltestVal)
4710                         return 0x0200;
4711                 break;
4712         }
4713         case 2:
4714         {
4715                 unsigned int ltestVal = testVal;
4716                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &ltestVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4717                 if (ret)
4718                         return 0x0300 + ret;
4719                 if (outExpected != ltestVal)
4720                         return 0x0400;
4721                 break;
4722         }
4723         case 3:
4724         {
4725                 char ltestVal = testVal;
4726                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &ltestVal, &lU1CustMarsh, &lVBCustMarsh);
4727                 if (ret)
4728                         return 0x0500 + ret;
4729                 if (outExpected != ltestVal)
4730                         return 0x0600;
4731                 break;
4732         }
4733         case 4:
4734         {
4735                 unsigned char ltestVal = testVal;
4736                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltestVal, &lVBCustMarsh);
4737                 if (ret)
4738                         return 0x0700 + ret;
4739                 if (outExpected != ltestVal)
4740                         return 0x0800;
4741                 break;
4742         }
4743         case 5:
4744         {
4745                 unsigned short ltestVal = testVal;
4746                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltestVal);
4747                 if (ret)
4748                         return 0x0900 + ret;
4749                 if (outExpected != ltestVal)
4750                         return 0x1000;
4751                 break;
4752         }
4753         default:
4754                 return 0x9800;
4755         }
4756
4757         return 0;
4758 }
4759
4760 #ifdef WIN32
4761
4762 LIBTEST_API int STDCALL 
4763 mono_test_marshal_safearray_out_1dim_vt_bstr_empty (SAFEARRAY** safearray)
4764 {
4765         /* Create an empty one-dimensional array of variants */
4766         SAFEARRAY *pSA;
4767         SAFEARRAYBOUND dimensions [1];
4768
4769         dimensions [0].lLbound = 0;
4770         dimensions [0].cElements = 0;
4771
4772         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4773         *safearray = pSA;
4774         return S_OK;
4775 }
4776
4777 LIBTEST_API int STDCALL 
4778 mono_test_marshal_safearray_out_1dim_vt_bstr (SAFEARRAY** safearray)
4779 {
4780         /* Create a one-dimensional array of 10 variants filled with "0" to "9" */
4781         SAFEARRAY *pSA;
4782         SAFEARRAYBOUND dimensions [1];
4783         long i;
4784         gchar buffer [20];
4785         HRESULT hr = S_OK;
4786         long indices [1];
4787
4788         dimensions [0].lLbound = 0;
4789         dimensions [0].cElements = 10;
4790
4791         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4792         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4793                 VARIANT vOut;
4794                 VariantInit (&vOut);
4795                 vOut.vt = VT_BSTR;
4796                 _ltoa (i,buffer,10);
4797                 vOut.bstrVal= marshal_bstr_alloc (buffer);
4798                 indices [0] = i;
4799                 if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4800                         VariantClear (&vOut);
4801                         SafeArrayDestroy (pSA);
4802                         return hr;
4803                 }
4804                 VariantClear (&vOut);
4805         }
4806         *safearray = pSA;
4807         return hr;
4808 }
4809
4810 LIBTEST_API int STDCALL 
4811 mono_test_marshal_safearray_out_2dim_vt_i4 (SAFEARRAY** safearray)
4812 {
4813         /* Create a two-dimensional array of 4x3 variants filled with 11, 12, 13, etc. */
4814         SAFEARRAY *pSA;
4815         SAFEARRAYBOUND dimensions [2];
4816         long i, j;
4817         HRESULT hr = S_OK;
4818         long indices [2];
4819
4820         dimensions [0].lLbound = 0;
4821         dimensions [0].cElements = 4;
4822         dimensions [1].lLbound = 0;
4823         dimensions [1].cElements = 3;
4824
4825         pSA= SafeArrayCreate(VT_VARIANT, 2, dimensions);
4826         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4827                 for (j= dimensions [1].lLbound; j< (dimensions [1].cElements + dimensions [1].lLbound); j++) {
4828                         VARIANT vOut;
4829                         VariantInit (&vOut);
4830                         vOut.vt = VT_I4;
4831                         vOut.lVal = (i+1)*10+(j+1);
4832                         indices [0] = i;
4833                         indices [1] = j;
4834                         if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4835                                 VariantClear (&vOut);
4836                                 SafeArrayDestroy (pSA);
4837                                 return hr;
4838                         }
4839                         VariantClear (&vOut);  // does a deep destroy of source VARIANT 
4840                 }
4841         }
4842         *safearray = pSA;
4843         return hr;
4844 }
4845
4846 LIBTEST_API int STDCALL 
4847 mono_test_marshal_safearray_out_4dim_vt_i4 (SAFEARRAY** safearray)
4848 {
4849         /* Create a four-dimensional array of 10x3x6x7 variants filled with their indices */
4850         /* Also use non zero lower bounds                                                 */
4851         SAFEARRAY *pSA;
4852         SAFEARRAYBOUND dimensions [4];
4853         long i;
4854         HRESULT hr = S_OK;
4855         VARIANT *pData;
4856
4857         dimensions [0].lLbound = 15;
4858         dimensions [0].cElements = 10;
4859         dimensions [1].lLbound = 20;
4860         dimensions [1].cElements = 3;
4861         dimensions [2].lLbound = 5;
4862         dimensions [2].cElements = 6;
4863         dimensions [3].lLbound = 12;
4864         dimensions [3].cElements = 7;
4865
4866         pSA= SafeArrayCreate (VT_VARIANT, 4, dimensions);
4867
4868         SafeArrayAccessData (pSA, (void **)&pData);
4869
4870         for (i= 0; i< 10*3*6*7; i++) {
4871                 VariantInit(&pData [i]);
4872                 pData [i].vt = VT_I4;
4873                 pData [i].lVal = i;
4874         }
4875         SafeArrayUnaccessData (pSA);
4876         *safearray = pSA;
4877         return hr;
4878 }
4879
4880 LIBTEST_API int STDCALL 
4881 mono_test_marshal_safearray_in_byval_1dim_empty (SAFEARRAY* safearray)
4882 {
4883         /* Check that array is one dimensional and empty */
4884
4885         UINT dim;
4886         long lbound, ubound;
4887         
4888         dim = SafeArrayGetDim (safearray);
4889         if (dim != 1)
4890                 return 1;
4891
4892         SafeArrayGetLBound (safearray, 1, &lbound);
4893         SafeArrayGetUBound (safearray, 1, &ubound);
4894
4895         if ((lbound > 0) || (ubound > 0))
4896                 return 1;
4897
4898         return 0;
4899 }
4900
4901 LIBTEST_API int STDCALL 
4902 mono_test_marshal_safearray_in_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4903 {
4904         /* Check that array is one dimensional containing integers from 1 to 10 */
4905
4906         UINT dim;
4907         long lbound, ubound;
4908         VARIANT *pData; 
4909         long i;
4910         int result=0;
4911
4912         dim = SafeArrayGetDim (safearray);
4913         if (dim != 1)
4914                 return 1;
4915
4916         SafeArrayGetLBound (safearray, 1, &lbound);
4917         SafeArrayGetUBound (safearray, 1, &ubound);
4918
4919         if ((lbound != 0) || (ubound != 9))
4920                 return 1;
4921
4922         SafeArrayAccessData (safearray, (void **)&pData);
4923         for (i= lbound; i <= ubound; i++) {
4924                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i + 1))
4925                         result = 1;
4926         }
4927         SafeArrayUnaccessData (safearray);
4928
4929         return result;
4930 }
4931
4932 LIBTEST_API int STDCALL 
4933 mono_test_marshal_safearray_in_byval_1dim_vt_mixed (SAFEARRAY* safearray)
4934 {
4935         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4936
4937         UINT dim;
4938         long lbound, ubound;
4939         VARIANT *pData; 
4940         long i;
4941         long indices [1];
4942         VARIANT element;
4943         int result=0;
4944
4945         VariantInit (&element);
4946
4947         dim = SafeArrayGetDim (safearray);
4948         if (dim != 1)
4949                 return 1;
4950
4951         SafeArrayGetLBound (safearray, 1, &lbound);
4952         SafeArrayGetUBound (safearray, 1, &ubound);
4953                 
4954         if ((lbound != 0) || (ubound != 12))
4955                 return 1;
4956
4957         SafeArrayAccessData (safearray, (void **)&pData);
4958         for (i= lbound; i <= ubound; i++) {
4959                 if ((i%2 == 0) && (pData [i].vt != VT_I4))
4960                         result = 1;
4961                 if ((i%2 == 1) && (pData [i].vt != VT_BSTR))
4962                         result = 1;
4963                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i))
4964                         result = 1;
4965         }
4966         SafeArrayUnaccessData (safearray);
4967
4968         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4969
4970         indices [0] = 0;
4971         element.vt = VT_I4;
4972         element.lVal = 333;
4973         SafeArrayPutElement (safearray, indices, &element);
4974         VariantClear (&element);
4975
4976         return result;
4977 }
4978
4979 LIBTEST_API int STDCALL 
4980 mono_test_marshal_safearray_in_byval_2dim_vt_i4 (SAFEARRAY* safearray)
4981 {
4982         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4983
4984         UINT dim;
4985         long lbound1, ubound1, lbound2, ubound2;
4986         long i, j, failed;
4987         long indices [2];
4988         VARIANT element;
4989
4990         VariantInit (&element);
4991
4992         dim = SafeArrayGetDim (safearray);
4993         if (dim != 2)
4994                 return 1;
4995
4996         SafeArrayGetLBound (safearray, 1, &lbound1);
4997         SafeArrayGetUBound (safearray, 1, &ubound1);
4998
4999         if ((lbound1 != 0) || (ubound1 != 1))
5000                 return 1;
5001
5002         SafeArrayGetLBound (safearray, 2, &lbound2);
5003         SafeArrayGetUBound (safearray, 2, &ubound2);
5004
5005         if ((lbound2 != 0) || (ubound2 != 3)) {
5006                 return 1;
5007         }
5008
5009         for (i= lbound1; i <= ubound1; i++) {
5010                 indices [0] = i;
5011                 for (j= lbound2; j <= ubound2; j++) {
5012                         indices [1] = j;
5013                         if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5014                                 return 1;
5015                         failed = ((element.vt != VT_I4) || (element.lVal != 10*(i+1)+(j+1)));
5016                         VariantClear (&element);
5017                         if (failed)
5018                                 return 1;
5019                 }
5020         }
5021
5022         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
5023
5024         indices [0] = 0;
5025         indices [1] = 0;
5026         element.vt = VT_I4;
5027         element.lVal = 333;
5028         SafeArrayPutElement (safearray, indices, &element);
5029         VariantClear (&element);
5030
5031         return 0;
5032 }
5033
5034 LIBTEST_API int STDCALL 
5035 mono_test_marshal_safearray_in_byval_3dim_vt_bstr (SAFEARRAY* safearray)
5036 {
5037         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
5038
5039         UINT dim;
5040         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5041         long i, j, k, failed;
5042         long indices [3];
5043         VARIANT element;
5044
5045         VariantInit (&element);
5046
5047         dim = SafeArrayGetDim (safearray);
5048         if (dim != 3)
5049                 return 1;
5050
5051         SafeArrayGetLBound (safearray, 1, &lbound1);
5052         SafeArrayGetUBound (safearray, 1, &ubound1);
5053
5054         if ((lbound1 != 0) || (ubound1 != 1))
5055                 return 1;
5056
5057         SafeArrayGetLBound (safearray, 2, &lbound2);
5058         SafeArrayGetUBound (safearray, 2, &ubound2);
5059
5060         if ((lbound2 != 0) || (ubound2 != 1))
5061                 return 1;
5062
5063         SafeArrayGetLBound (safearray, 3, &lbound3);
5064         SafeArrayGetUBound (safearray, 3, &ubound3);
5065
5066         if ((lbound3 != 0) || (ubound3 != 2))
5067                 return 1;
5068
5069         for (i= lbound1; i <= ubound1; i++) {
5070                 indices [0] = i;
5071                 for (j= lbound2; j <= ubound2; j++) {
5072                         indices [1] = j;
5073                 for (k= lbound3; k <= ubound3; k++) {
5074                                 indices [2] = k;
5075                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5076                                         return 1;
5077                                 failed = ((element.vt != VT_BSTR) 
5078                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5079                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5080                                 VariantClear (&element);
5081                                 if (failed)
5082                                         return 1;
5083                         }
5084                 }
5085         }
5086
5087         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
5088
5089         indices [0] = 0;
5090         indices [1] = 0;
5091         indices [2] = 0;
5092         element.vt = VT_BSTR;
5093         element.bstrVal = SysAllocString(L"Should not be copied");
5094         SafeArrayPutElement (safearray, indices, &element);
5095         VariantClear (&element);
5096
5097         return 0;
5098 }
5099
5100 LIBTEST_API int STDCALL 
5101 mono_test_marshal_safearray_in_byref_3dim_vt_bstr (SAFEARRAY** safearray)
5102 {
5103         return mono_test_marshal_safearray_in_byval_3dim_vt_bstr (*safearray);
5104 }
5105
5106 LIBTEST_API int STDCALL 
5107 mono_test_marshal_safearray_in_out_byref_1dim_empty (SAFEARRAY** safearray)
5108 {
5109         /* Check that the input array is what is expected and change it so the caller can check */
5110         /* correct marshalling back to managed code                                             */
5111
5112         UINT dim;
5113         long lbound, ubound;
5114         SAFEARRAYBOUND dimensions [1];
5115         long i;
5116         wchar_t buffer [20];
5117         HRESULT hr = S_OK;
5118         long indices [1];
5119
5120         /* Check that in array is one dimensional and empty */
5121
5122         dim = SafeArrayGetDim (*safearray);
5123         if (dim != 1) {
5124                 return 1;
5125         }
5126
5127         SafeArrayGetLBound (*safearray, 1, &lbound);
5128         SafeArrayGetUBound (*safearray, 1, &ubound);
5129                 
5130         if ((lbound > 0) || (ubound > 0)) {
5131                 return 1;
5132         }
5133
5134         /* Re-dimension the array and return a one-dimensional array of 8 variants filled with "0" to "7" */
5135
5136         dimensions [0].lLbound = 0;
5137         dimensions [0].cElements = 8;
5138
5139         hr = SafeArrayRedim (*safearray, dimensions);
5140         if (hr != S_OK)
5141                 return 1;
5142
5143         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
5144                 VARIANT vOut;
5145                 VariantInit (&vOut);
5146                 vOut.vt = VT_BSTR;
5147                 _ltow (i,buffer,10);
5148                 vOut.bstrVal = SysAllocString (buffer);
5149                 indices [0] = i;
5150                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
5151                         VariantClear (&vOut);
5152                         SafeArrayDestroy (*safearray);
5153                         return hr;
5154                 }
5155                 VariantClear (&vOut);
5156         }
5157         return hr;
5158 }
5159
5160 LIBTEST_API int STDCALL 
5161 mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (SAFEARRAY** safearray)
5162 {
5163         /* Check that the input array is what is expected and change it so the caller can check */
5164         /* correct marshalling back to managed code                                             */
5165
5166         UINT dim;
5167         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5168         SAFEARRAYBOUND dimensions [1];
5169         long i, j, k, failed;
5170         wchar_t buffer [20];
5171         HRESULT hr = S_OK;
5172         long indices [3];
5173         VARIANT element;
5174
5175         VariantInit (&element);
5176
5177         /* Check that in array is three dimensional and contains the expected values */
5178
5179         dim = SafeArrayGetDim (*safearray);
5180         if (dim != 3)
5181                 return 1;
5182
5183         SafeArrayGetLBound (*safearray, 1, &lbound1);
5184         SafeArrayGetUBound (*safearray, 1, &ubound1);
5185
5186         if ((lbound1 != 0) || (ubound1 != 1))
5187                 return 1;
5188
5189         SafeArrayGetLBound (*safearray, 2, &lbound2);
5190         SafeArrayGetUBound (*safearray, 2, &ubound2);
5191
5192         if ((lbound2 != 0) || (ubound2 != 1))
5193                 return 1;
5194
5195         SafeArrayGetLBound (*safearray, 3, &lbound3);
5196         SafeArrayGetUBound (*safearray, 3, &ubound3);
5197
5198         if ((lbound3 != 0) || (ubound3 != 2))
5199                 return 1;
5200
5201         for (i= lbound1; i <= ubound1; i++) {
5202                 indices [0] = i;
5203                 for (j= lbound2; j <= ubound2; j++) {
5204                         indices [1] = j;
5205                         for (k= lbound3; k <= ubound3; k++) {
5206                                 indices [2] = k;
5207                                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
5208                                         return 1;
5209                                 failed = ((element.vt != VT_BSTR) 
5210                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5211                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5212                                 VariantClear (&element);
5213                                 if (failed)
5214                                         return 1;
5215                         }
5216                 }
5217         }
5218
5219         hr = SafeArrayDestroy (*safearray);
5220         if (hr != S_OK)
5221                 return 1;
5222
5223         /* Return a new one-dimensional array of 8 variants filled with "0" to "7" */
5224
5225         dimensions [0].lLbound = 0;
5226         dimensions [0].cElements = 8;
5227
5228         *safearray = SafeArrayCreate (VT_VARIANT, 1, dimensions);
5229
5230         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
5231                 VARIANT vOut;
5232                 VariantInit (&vOut);
5233                 vOut.vt = VT_BSTR;
5234                 _ltow (i,buffer,10);
5235                 vOut.bstrVal = SysAllocString (buffer);
5236                 indices [0] = i;
5237                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
5238                         VariantClear (&vOut);
5239                         SafeArrayDestroy (*safearray);
5240                         return hr;
5241                 }
5242                 VariantClear (&vOut);
5243         }
5244         return hr;
5245 }
5246
5247 LIBTEST_API int STDCALL 
5248 mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (SAFEARRAY** safearray)
5249 {
5250         /* Check that the input array is what is expected and change it so the caller can check */
5251         /* correct marshalling back to managed code                                             */
5252
5253         UINT dim;
5254         long lbound1, ubound1;
5255         long i, failed;
5256         HRESULT hr = S_OK;
5257         long indices [1];
5258         VARIANT element;
5259         
5260         VariantInit (&element);
5261
5262         /* Check that in array is one dimensional and contains the expected value */
5263
5264         dim = SafeArrayGetDim (*safearray);
5265         if (dim != 1)
5266                 return 1;
5267
5268         SafeArrayGetLBound (*safearray, 1, &lbound1);
5269         SafeArrayGetUBound (*safearray, 1, &ubound1);
5270
5271         ubound1 = 1;
5272         if ((lbound1 != 0) || (ubound1 != 1))
5273                 return 1;
5274         ubound1 = 0;
5275
5276         for (i= lbound1; i <= ubound1; i++) {
5277                 indices [0] = i;
5278                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
5279                         return 1;
5280                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
5281                 VariantClear (&element);
5282                 if (failed)
5283                         return 1;
5284         }
5285
5286         /* Change one of the elements of the array to verify that [out] parameter is marshalled back to the managed side */
5287
5288         indices [0] = 0;
5289         element.vt = VT_I4;
5290         element.lVal = -1;
5291         SafeArrayPutElement (*safearray, indices, &element);
5292         VariantClear (&element);
5293
5294         return hr;
5295 }
5296
5297 LIBTEST_API int STDCALL 
5298 mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (SAFEARRAY* safearray)
5299 {
5300         /* Check that the input array is what is expected and change it so the caller can check */
5301         /* correct marshalling back to managed code                                             */
5302
5303         UINT dim;
5304         long lbound1, ubound1;
5305         SAFEARRAYBOUND dimensions [1];
5306         long i, failed;
5307         HRESULT hr = S_OK;
5308         long indices [1];
5309         VARIANT element;
5310
5311         VariantInit (&element);
5312
5313         /* Check that in array is one dimensional and contains the expected value */
5314
5315         dim = SafeArrayGetDim (safearray);
5316         if (dim != 1)
5317                 return 1;
5318
5319         SafeArrayGetLBound (safearray, 1, &lbound1);
5320         SafeArrayGetUBound (safearray, 1, &ubound1);
5321                 
5322         if ((lbound1 != 0) || (ubound1 != 0))
5323                 return 1;
5324
5325         for (i= lbound1; i <= ubound1; i++) {
5326                 indices [0] = i;
5327                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5328                         return 1;
5329                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
5330                 VariantClear (&element);
5331                 if (failed)
5332                         return 1;
5333         }
5334
5335         /* Change the array to verify how [out] parameter is marshalled back to the managed side */
5336
5337         /* Redimension the array */
5338         dimensions [0].lLbound = lbound1;
5339         dimensions [0].cElements = 2;
5340         hr = SafeArrayRedim(safearray, dimensions);
5341
5342         indices [0] = 0;
5343         element.vt = VT_I4;
5344         element.lVal = 12345;
5345         SafeArrayPutElement (safearray, indices, &element);
5346         VariantClear (&element);
5347
5348         indices [0] = 1;
5349         element.vt = VT_I4;
5350         element.lVal = -12345;
5351         SafeArrayPutElement (safearray, indices, &element);
5352         VariantClear (&element);
5353
5354         return hr;
5355 }
5356
5357 LIBTEST_API int STDCALL 
5358 mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (SAFEARRAY* safearray)
5359 {
5360         /* Check that the input array is what is expected and change it so the caller can check */
5361         /* correct marshalling back to managed code                                             */
5362
5363         UINT dim;
5364         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5365         long i, j, k, failed;
5366         HRESULT hr = S_OK;
5367         long indices [3];
5368         VARIANT element;
5369
5370         VariantInit (&element);
5371
5372         /* Check that in array is three dimensional and contains the expected values */
5373
5374         dim = SafeArrayGetDim (safearray);
5375         if (dim != 3)
5376                 return 1;
5377
5378         SafeArrayGetLBound (safearray, 1, &lbound1);
5379         SafeArrayGetUBound (safearray, 1, &ubound1);
5380
5381         if ((lbound1 != 0) || (ubound1 != 1))
5382                 return 1;
5383
5384         SafeArrayGetLBound (safearray, 2, &lbound2);
5385         SafeArrayGetUBound (safearray, 2, &ubound2);
5386
5387         if ((lbound2 != 0) || (ubound2 != 1))
5388                 return 1;
5389
5390         SafeArrayGetLBound (safearray, 3, &lbound3);
5391         SafeArrayGetUBound (safearray, 3, &ubound3);
5392
5393         if ((lbound3 != 0) || (ubound3 != 2))
5394                 return 1;
5395
5396         for (i= lbound1; i <= ubound1; i++) {
5397                 indices [0] = i;
5398                 for (j= lbound2; j <= ubound2; j++) {
5399                         indices [1] = j;
5400                         for (k= lbound3; k <= ubound3; k++) {
5401                                 indices [2] = k;
5402                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5403                                         return 1;
5404                                 failed = ((element.vt != VT_BSTR) 
5405                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5406                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5407                                 VariantClear (&element);
5408                                 if (failed)
5409                                         return 1;
5410                         }
5411                 }
5412         }
5413
5414         /* Change the elements of the array to verify that [out] parameter is marshalled back to the managed side */
5415
5416         indices [0] = 1;
5417         indices [1] = 1;
5418         indices [2] = 2;
5419         element.vt = VT_I4;
5420         element.lVal = 333;
5421         SafeArrayPutElement (safearray, indices, &element);
5422         VariantClear (&element);
5423
5424         indices [0] = 1;
5425         indices [1] = 1;
5426         indices [2] = 1;
5427         element.vt = VT_I4;
5428         element.lVal = 111;
5429         SafeArrayPutElement (safearray, indices, &element);
5430         VariantClear (&element);
5431
5432         indices [0] = 0;
5433         indices [1] = 1;
5434         indices [2] = 0;
5435         element.vt = VT_BSTR;
5436         element.bstrVal = marshal_bstr_alloc("ABCDEFG");
5437         SafeArrayPutElement (safearray, indices, &element);
5438         VariantClear (&element);
5439
5440         return hr;
5441 }
5442
5443 LIBTEST_API int STDCALL 
5444 mono_test_marshal_safearray_mixed(
5445                 SAFEARRAY  *safearray1,
5446                 SAFEARRAY **safearray2,
5447                 SAFEARRAY  *safearray3,
5448                 SAFEARRAY **safearray4
5449                 )
5450 {
5451         HRESULT hr = S_OK;
5452
5453         /* Initialize out parameters */
5454         *safearray2 = NULL;
5455
5456         /* array1: Check that in array is one dimensional and contains the expected value */
5457         hr = mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (safearray1);
5458
5459         /* array2: Fill in with some values to check on the managed side */
5460         if (hr == S_OK)
5461                 hr = mono_test_marshal_safearray_out_1dim_vt_bstr (safearray2);
5462
5463         /* array3: Check that in array is one dimensional and contains the expected value */
5464         if (hr == S_OK)
5465                 hr = mono_test_marshal_safearray_in_byval_1dim_vt_mixed(safearray3);
5466
5467         /* array4: Check input values and fill in with some values to check on the managed side */
5468         if (hr == S_OK)
5469                 hr = mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr(safearray4);
5470
5471         return hr;
5472 }
5473
5474 #endif
5475
5476 static int call_managed_res;
5477
5478 static void
5479 call_managed (gpointer arg)
5480 {
5481         SimpleDelegate del = (SimpleDelegate)arg;
5482
5483         call_managed_res = del (42);
5484 }
5485
5486 LIBTEST_API int STDCALL 
5487 mono_test_marshal_thread_attach (SimpleDelegate del)
5488 {
5489 #ifdef WIN32
5490         return 43;
5491 #else
5492         int res;
5493         pthread_t t;
5494
5495         res = pthread_create (&t, NULL, (gpointer (*)(gpointer))call_managed, del);
5496         g_assert (res == 0);
5497         pthread_join (t, NULL);
5498
5499         return call_managed_res;
5500 #endif
5501 }
5502
5503 typedef struct {
5504         char arr [4 * 1024];
5505 } LargeStruct;
5506
5507 typedef int (STDCALL *LargeStructDelegate) (LargeStruct *s);
5508
5509 static void
5510 call_managed_large_vt (gpointer arg)
5511 {
5512         LargeStructDelegate del = (LargeStructDelegate)arg;
5513         LargeStruct s;
5514
5515         call_managed_res = del (&s);
5516 }
5517
5518 LIBTEST_API int STDCALL
5519 mono_test_marshal_thread_attach_large_vt (SimpleDelegate del)
5520 {
5521 #ifdef WIN32
5522         return 43;
5523 #else
5524         int res;
5525         pthread_t t;
5526
5527         res = pthread_create (&t, NULL, (gpointer (*)(gpointer))call_managed_large_vt, del);
5528         g_assert (res == 0);
5529         pthread_join (t, NULL);
5530
5531         return call_managed_res;
5532 #endif
5533 }
5534
5535 typedef int (STDCALL *Callback) (void);
5536
5537 static Callback callback;
5538
5539 LIBTEST_API void STDCALL 
5540 mono_test_marshal_set_callback (Callback cb)
5541 {
5542         callback = cb;
5543 }
5544
5545 LIBTEST_API int STDCALL 
5546 mono_test_marshal_call_callback (void)
5547 {
5548         return callback ();
5549 }
5550
5551 LIBTEST_API int STDCALL
5552 mono_test_marshal_lpstr (char *str)
5553 {
5554         return strcmp ("ABC", str);
5555 }
5556
5557 LIBTEST_API int STDCALL
5558 mono_test_marshal_lpwstr (gunichar2 *str)
5559 {
5560         char *s;
5561         int res;
5562
5563         s = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
5564         res = strcmp ("ABC", s);
5565         g_free (s);
5566
5567         return res;
5568 }
5569
5570 LIBTEST_API char* STDCALL
5571 mono_test_marshal_return_lpstr (void)
5572 {
5573         char *res = (char *)marshal_alloc (4);
5574         strcpy (res, "XYZ");
5575         return res;
5576 }
5577
5578
5579 LIBTEST_API gunichar2* STDCALL
5580 mono_test_marshal_return_lpwstr (void)
5581 {
5582         gunichar2 *res = (gunichar2 *)marshal_alloc (8);
5583         gunichar2* tmp = g_utf8_to_utf16 ("XYZ", -1, NULL, NULL, NULL);
5584
5585         memcpy (res, tmp, 8);
5586         g_free (tmp);
5587
5588         return res;
5589 }
5590
5591 typedef struct {
5592         double d;
5593 } SingleDoubleStruct;
5594
5595 LIBTEST_API SingleDoubleStruct STDCALL
5596 mono_test_marshal_return_single_double_struct (void)
5597 {
5598         SingleDoubleStruct res;
5599
5600         res.d = 3.0;
5601
5602         return res;
5603 }
5604
5605
5606 #ifndef TARGET_X86
5607
5608 LIBTEST_API int STDCALL
5609 mono_test_has_thiscall (void)
5610 {
5611         return 1;
5612 }
5613
5614 LIBTEST_API int
5615 _mono_test_native_thiscall1 (int arg)
5616 {
5617         return arg;
5618 }
5619
5620 LIBTEST_API int
5621 _mono_test_native_thiscall2 (int arg, int arg2)
5622 {
5623         return arg + (arg2^1);
5624 }
5625
5626 LIBTEST_API int
5627 _mono_test_native_thiscall3 (int arg, int arg2, int arg3)
5628 {
5629         return arg + (arg2^1) + (arg3^2);
5630 }
5631
5632 #elif defined(__GNUC__)
5633
5634 LIBTEST_API int STDCALL
5635 mono_test_has_thiscall (void)
5636 {
5637         return 1;
5638 }
5639
5640 #define def_asm_fn(name) \
5641         "\t.align 4\n" \
5642         "\t.globl _" #name "\n" \
5643         "_" #name ":\n" \
5644         "\t.globl __" #name "\n" \
5645         "__" #name ":\n"
5646
5647 asm(".text\n"
5648
5649 def_asm_fn(mono_test_native_thiscall1)
5650 "\tmovl %ecx,%eax\n"
5651 "\tret\n"
5652
5653 def_asm_fn(mono_test_native_thiscall2)
5654 "\tmovl %ecx,%eax\n"
5655 "\tmovl 4(%esp),%ecx\n"
5656 "\txorl $1,%ecx\n"
5657 "\taddl %ecx,%eax\n"
5658 "\tret $4\n"
5659
5660 def_asm_fn(mono_test_native_thiscall3)
5661 "\tmovl %ecx,%eax\n"
5662 "\tmovl 4(%esp),%ecx\n"
5663 "\txorl $1,%ecx\n"
5664 "\taddl %ecx,%eax\n"
5665 "\tmovl 8(%esp),%ecx\n"
5666 "\txorl $2,%ecx\n"
5667 "\taddl %ecx,%eax\n"
5668 "\tret $8\n"
5669
5670 );
5671
5672 #else
5673
5674 LIBTEST_API int STDCALL
5675 mono_test_has_thiscall (void)
5676 {
5677         return 0;
5678 }
5679
5680 #endif
5681
5682
5683 typedef struct {
5684         char f1;
5685 } sbyte1;
5686
5687 LIBTEST_API sbyte1 STDCALL
5688 mono_return_sbyte1 (sbyte1 s1, int addend) {
5689         if (s1.f1 != 1) {
5690                 fprintf(stderr, "mono_return_sbyte1 s1.f1: got %d but expected %d\n", s1.f1, 1);
5691         }
5692         s1.f1+=addend; 
5693         return s1;
5694 }
5695
5696 typedef struct {
5697         char f1,f2;
5698 } sbyte2;
5699
5700 LIBTEST_API sbyte2 STDCALL
5701 mono_return_sbyte2 (sbyte2 s2, int addend) {
5702         if (s2.f1 != 1) {
5703                 fprintf(stderr, "mono_return_sbyte2 s2.f1: got %d but expected %d\n", s2.f1, 1);
5704         }
5705         if (s2.f2 != 2) {
5706                 fprintf(stderr, "mono_return_sbyte2 s2.f2: got %d but expected %d\n", s2.f2, 2);
5707         }
5708         s2.f1+=addend; s2.f2+=addend; 
5709         return s2;
5710 }
5711
5712 typedef struct {
5713         char f1,f2,f3;
5714 } sbyte3;
5715
5716 LIBTEST_API sbyte3 STDCALL
5717 mono_return_sbyte3 (sbyte3 s3, int addend) {
5718         if (s3.f1 != 1) {
5719                 fprintf(stderr, "mono_return_sbyte3 s3.f1: got %d but expected %d\n", s3.f1, 1);
5720         }
5721         if (s3.f2 != 2) {
5722                 fprintf(stderr, "mono_return_sbyte3 s3.f2: got %d but expected %d\n", s3.f2, 2);
5723         }
5724         if (s3.f3 != 3) {
5725                 fprintf(stderr, "mono_return_sbyte3 s3.f3: got %d but expected %d\n", s3.f3, 3);
5726         }
5727         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
5728         return s3;
5729 }
5730
5731 typedef struct {
5732         char f1,f2,f3,f4;
5733 } sbyte4;
5734
5735 LIBTEST_API sbyte4 STDCALL
5736 mono_return_sbyte4 (sbyte4 s4, int addend) {
5737         if (s4.f1 != 1) {
5738                 fprintf(stderr, "mono_return_sbyte4 s4.f1: got %d but expected %d\n", s4.f1, 1);
5739         }
5740         if (s4.f2 != 2) {
5741                 fprintf(stderr, "mono_return_sbyte4 s4.f2: got %d but expected %d\n", s4.f2, 2);
5742         }
5743         if (s4.f3 != 3) {
5744                 fprintf(stderr, "mono_return_sbyte4 s4.f3: got %d but expected %d\n", s4.f3, 3);
5745         }
5746         if (s4.f4 != 4) {
5747                 fprintf(stderr, "mono_return_sbyte4 s4.f4: got %d but expected %d\n", s4.f4, 4);
5748         }
5749         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
5750         return s4;
5751 }
5752
5753 typedef struct {
5754         char f1,f2,f3,f4,f5;
5755 } sbyte5;
5756
5757 LIBTEST_API sbyte5 STDCALL
5758 mono_return_sbyte5 (sbyte5 s5, int addend) {
5759         if (s5.f1 != 1) {
5760                 fprintf(stderr, "mono_return_sbyte5 s5.f1: got %d but expected %d\n", s5.f1, 1);
5761         }
5762         if (s5.f2 != 2) {
5763                 fprintf(stderr, "mono_return_sbyte5 s5.f2: got %d but expected %d\n", s5.f2, 2);
5764         }
5765         if (s5.f3 != 3) {
5766                 fprintf(stderr, "mono_return_sbyte5 s5.f3: got %d but expected %d\n", s5.f3, 3);
5767         }
5768         if (s5.f4 != 4) {
5769                 fprintf(stderr, "mono_return_sbyte5 s5.f4: got %d but expected %d\n", s5.f4, 4);
5770         }
5771         if (s5.f5 != 5) {
5772                 fprintf(stderr, "mono_return_sbyte5 s5.f5: got %d but expected %d\n", s5.f5, 5);
5773         }
5774         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
5775         return s5;
5776 }
5777
5778 typedef struct {
5779         char f1,f2,f3,f4,f5,f6;
5780 } sbyte6;
5781
5782 LIBTEST_API sbyte6 STDCALL
5783 mono_return_sbyte6 (sbyte6 s6, int addend) {
5784         if (s6.f1 != 1) {
5785                 fprintf(stderr, "mono_return_sbyte6 s6.f1: got %d but expected %d\n", s6.f1, 1);
5786         }
5787         if (s6.f2 != 2) {
5788                 fprintf(stderr, "mono_return_sbyte6 s6.f2: got %d but expected %d\n", s6.f2, 2);
5789         }
5790         if (s6.f3 != 3) {
5791                 fprintf(stderr, "mono_return_sbyte6 s6.f3: got %d but expected %d\n", s6.f3, 3);
5792         }
5793         if (s6.f4 != 4) {
5794                 fprintf(stderr, "mono_return_sbyte6 s6.f4: got %d but expected %d\n", s6.f4, 4);
5795         }
5796         if (s6.f5 != 5) {
5797                 fprintf(stderr, "mono_return_sbyte6 s6.f5: got %d but expected %d\n", s6.f5, 5);
5798         }
5799         if (s6.f6 != 6) {
5800                 fprintf(stderr, "mono_return_sbyte6 s6.f6: got %d but expected %d\n", s6.f6, 6);
5801         }
5802         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
5803         return s6;
5804 }
5805
5806 typedef struct {
5807         char f1,f2,f3,f4,f5,f6,f7;
5808 } sbyte7;
5809
5810 LIBTEST_API sbyte7 STDCALL
5811 mono_return_sbyte7 (sbyte7 s7, int addend) {
5812         if (s7.f1 != 1) {
5813                 fprintf(stderr, "mono_return_sbyte7 s7.f1: got %d but expected %d\n", s7.f1, 1);
5814         }
5815         if (s7.f2 != 2) {
5816                 fprintf(stderr, "mono_return_sbyte7 s7.f2: got %d but expected %d\n", s7.f2, 2);
5817         }
5818         if (s7.f3 != 3) {
5819                 fprintf(stderr, "mono_return_sbyte7 s7.f3: got %d but expected %d\n", s7.f3, 3);
5820         }
5821         if (s7.f4 != 4) {
5822                 fprintf(stderr, "mono_return_sbyte7 s7.f4: got %d but expected %d\n", s7.f4, 4);
5823         }
5824         if (s7.f5 != 5) {
5825                 fprintf(stderr, "mono_return_sbyte7 s7.f5: got %d but expected %d\n", s7.f5, 5);
5826         }
5827         if (s7.f6 != 6) {
5828                 fprintf(stderr, "mono_return_sbyte7 s7.f6: got %d but expected %d\n", s7.f6, 6);
5829         }
5830         if (s7.f7 != 7) {
5831                 fprintf(stderr, "mono_return_sbyte7 s7.f7: got %d but expected %d\n", s7.f7, 7);
5832         }
5833         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
5834         return s7;
5835 }
5836
5837 typedef struct {
5838         char f1,f2,f3,f4,f5,f6,f7,f8;
5839 } sbyte8;
5840
5841 LIBTEST_API sbyte8 STDCALL
5842 mono_return_sbyte8 (sbyte8 s8, int addend) {
5843         if (s8.f1 != 1) {
5844                 fprintf(stderr, "mono_return_sbyte8 s8.f1: got %d but expected %d\n", s8.f1, 1);
5845         }
5846         if (s8.f2 != 2) {
5847                 fprintf(stderr, "mono_return_sbyte8 s8.f2: got %d but expected %d\n", s8.f2, 2);
5848         }
5849         if (s8.f3 != 3) {
5850                 fprintf(stderr, "mono_return_sbyte8 s8.f3: got %d but expected %d\n", s8.f3, 3);
5851         }
5852         if (s8.f4 != 4) {
5853                 fprintf(stderr, "mono_return_sbyte8 s8.f4: got %d but expected %d\n", s8.f4, 4);
5854         }
5855         if (s8.f5 != 5) {
5856                 fprintf(stderr, "mono_return_sbyte8 s8.f5: got %d but expected %d\n", s8.f5, 5);
5857         }
5858         if (s8.f6 != 6) {
5859                 fprintf(stderr, "mono_return_sbyte8 s8.f6: got %d but expected %d\n", s8.f6, 6);
5860         }
5861         if (s8.f7 != 7) {
5862                 fprintf(stderr, "mono_return_sbyte8 s8.f7: got %d but expected %d\n", s8.f7, 7);
5863         }
5864         if (s8.f8 != 8) {
5865                 fprintf(stderr, "mono_return_sbyte8 s8.f8: got %d but expected %d\n", s8.f8, 8);
5866         }
5867         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
5868         return s8;
5869 }
5870
5871 typedef struct {
5872         char f1,f2,f3,f4,f5,f6,f7,f8,f9;
5873 } sbyte9;
5874
5875 LIBTEST_API sbyte9 STDCALL
5876 mono_return_sbyte9 (sbyte9 s9, int addend) {
5877         if (s9.f1 != 1) {
5878                 fprintf(stderr, "mono_return_sbyte9 s9.f1: got %d but expected %d\n", s9.f1, 1);
5879         }
5880         if (s9.f2 != 2) {
5881                 fprintf(stderr, "mono_return_sbyte9 s9.f2: got %d but expected %d\n", s9.f2, 2);
5882         }
5883         if (s9.f3 != 3) {
5884                 fprintf(stderr, "mono_return_sbyte9 s9.f3: got %d but expected %d\n", s9.f3, 3);
5885         }
5886         if (s9.f4 != 4) {
5887                 fprintf(stderr, "mono_return_sbyte9 s9.f4: got %d but expected %d\n", s9.f4, 4);
5888         }
5889         if (s9.f5 != 5) {
5890                 fprintf(stderr, "mono_return_sbyte9 s9.f5: got %d but expected %d\n", s9.f5, 5);
5891         }
5892         if (s9.f6 != 6) {
5893                 fprintf(stderr, "mono_return_sbyte9 s9.f6: got %d but expected %d\n", s9.f6, 6);
5894         }
5895         if (s9.f7 != 7) {
5896                 fprintf(stderr, "mono_return_sbyte9 s9.f7: got %d but expected %d\n", s9.f7, 7);
5897         }
5898         if (s9.f8 != 8) {
5899                 fprintf(stderr, "mono_return_sbyte9 s9.f8: got %d but expected %d\n", s9.f8, 8);
5900         }
5901         if (s9.f9 != 9) {
5902                 fprintf(stderr, "mono_return_sbyte9 s9.f9: got %d but expected %d\n", s9.f9, 9);
5903         }
5904         s9.f1+=addend; s9.f2+=addend; s9.f3+=addend; s9.f4+=addend; s9.f5+=addend; s9.f6+=addend; s9.f7+=addend; s9.f8+=addend; s9.f9+=addend; 
5905         return s9;
5906 }
5907
5908 typedef struct {
5909         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10;
5910 } sbyte10;
5911
5912 LIBTEST_API sbyte10 STDCALL
5913 mono_return_sbyte10 (sbyte10 s10, int addend) {
5914         if (s10.f1 != 1) {
5915                 fprintf(stderr, "mono_return_sbyte10 s10.f1: got %d but expected %d\n", s10.f1, 1);
5916         }
5917         if (s10.f2 != 2) {
5918                 fprintf(stderr, "mono_return_sbyte10 s10.f2: got %d but expected %d\n", s10.f2, 2);
5919         }
5920         if (s10.f3 != 3) {
5921                 fprintf(stderr, "mono_return_sbyte10 s10.f3: got %d but expected %d\n", s10.f3, 3);
5922         }
5923         if (s10.f4 != 4) {
5924                 fprintf(stderr, "mono_return_sbyte10 s10.f4: got %d but expected %d\n", s10.f4, 4);
5925         }
5926         if (s10.f5 != 5) {
5927                 fprintf(stderr, "mono_return_sbyte10 s10.f5: got %d but expected %d\n", s10.f5, 5);
5928         }
5929         if (s10.f6 != 6) {
5930                 fprintf(stderr, "mono_return_sbyte10 s10.f6: got %d but expected %d\n", s10.f6, 6);
5931         }
5932         if (s10.f7 != 7) {
5933                 fprintf(stderr, "mono_return_sbyte10 s10.f7: got %d but expected %d\n", s10.f7, 7);
5934         }
5935         if (s10.f8 != 8) {
5936                 fprintf(stderr, "mono_return_sbyte10 s10.f8: got %d but expected %d\n", s10.f8, 8);
5937         }
5938         if (s10.f9 != 9) {
5939                 fprintf(stderr, "mono_return_sbyte10 s10.f9: got %d but expected %d\n", s10.f9, 9);
5940         }
5941         if (s10.f10 != 10) {
5942                 fprintf(stderr, "mono_return_sbyte10 s10.f10: got %d but expected %d\n", s10.f10, 10);
5943         }
5944         s10.f1+=addend; s10.f2+=addend; s10.f3+=addend; s10.f4+=addend; s10.f5+=addend; s10.f6+=addend; s10.f7+=addend; s10.f8+=addend; s10.f9+=addend; s10.f10+=addend; 
5945         return s10;
5946 }
5947
5948 typedef struct {
5949         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11;
5950 } sbyte11;
5951
5952 LIBTEST_API sbyte11 STDCALL
5953 mono_return_sbyte11 (sbyte11 s11, int addend) {
5954         if (s11.f1 != 1) {
5955                 fprintf(stderr, "mono_return_sbyte11 s11.f1: got %d but expected %d\n", s11.f1, 1);
5956         }
5957         if (s11.f2 != 2) {
5958                 fprintf(stderr, "mono_return_sbyte11 s11.f2: got %d but expected %d\n", s11.f2, 2);
5959         }
5960         if (s11.f3 != 3) {
5961                 fprintf(stderr, "mono_return_sbyte11 s11.f3: got %d but expected %d\n", s11.f3, 3);
5962         }
5963         if (s11.f4 != 4) {
5964                 fprintf(stderr, "mono_return_sbyte11 s11.f4: got %d but expected %d\n", s11.f4, 4);
5965         }
5966         if (s11.f5 != 5) {
5967                 fprintf(stderr, "mono_return_sbyte11 s11.f5: got %d but expected %d\n", s11.f5, 5);
5968         }
5969         if (s11.f6 != 6) {
5970                 fprintf(stderr, "mono_return_sbyte11 s11.f6: got %d but expected %d\n", s11.f6, 6);
5971         }
5972         if (s11.f7 != 7) {
5973                 fprintf(stderr, "mono_return_sbyte11 s11.f7: got %d but expected %d\n", s11.f7, 7);
5974         }
5975         if (s11.f8 != 8) {
5976                 fprintf(stderr, "mono_return_sbyte11 s11.f8: got %d but expected %d\n", s11.f8, 8);
5977         }
5978         if (s11.f9 != 9) {
5979                 fprintf(stderr, "mono_return_sbyte11 s11.f9: got %d but expected %d\n", s11.f9, 9);
5980         }
5981         if (s11.f10 != 10) {
5982                 fprintf(stderr, "mono_return_sbyte11 s11.f10: got %d but expected %d\n", s11.f10, 10);
5983         }
5984         if (s11.f11 != 11) {
5985                 fprintf(stderr, "mono_return_sbyte11 s11.f11: got %d but expected %d\n", s11.f11, 11);
5986         }
5987         s11.f1+=addend; s11.f2+=addend; s11.f3+=addend; s11.f4+=addend; s11.f5+=addend; s11.f6+=addend; s11.f7+=addend; s11.f8+=addend; s11.f9+=addend; s11.f10+=addend; s11.f11+=addend; 
5988         return s11;
5989 }
5990
5991 typedef struct {
5992         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12;
5993 } sbyte12;
5994
5995 LIBTEST_API sbyte12 STDCALL
5996 mono_return_sbyte12 (sbyte12 s12, int addend) {
5997         if (s12.f1 != 1) {
5998                 fprintf(stderr, "mono_return_sbyte12 s12.f1: got %d but expected %d\n", s12.f1, 1);
5999         }
6000         if (s12.f2 != 2) {
6001                 fprintf(stderr, "mono_return_sbyte12 s12.f2: got %d but expected %d\n", s12.f2, 2);
6002         }
6003         if (s12.f3 != 3) {
6004                 fprintf(stderr, "mono_return_sbyte12 s12.f3: got %d but expected %d\n", s12.f3, 3);
6005         }
6006         if (s12.f4 != 4) {
6007                 fprintf(stderr, "mono_return_sbyte12 s12.f4: got %d but expected %d\n", s12.f4, 4);
6008         }
6009         if (s12.f5 != 5) {
6010                 fprintf(stderr, "mono_return_sbyte12 s12.f5: got %d but expected %d\n", s12.f5, 5);
6011         }
6012         if (s12.f6 != 6) {
6013                 fprintf(stderr, "mono_return_sbyte12 s12.f6: got %d but expected %d\n", s12.f6, 6);
6014         }
6015         if (s12.f7 != 7) {
6016                 fprintf(stderr, "mono_return_sbyte12 s12.f7: got %d but expected %d\n", s12.f7, 7);
6017         }
6018         if (s12.f8 != 8) {
6019                 fprintf(stderr, "mono_return_sbyte12 s12.f8: got %d but expected %d\n", s12.f8, 8);
6020         }
6021         if (s12.f9 != 9) {
6022                 fprintf(stderr, "mono_return_sbyte12 s12.f9: got %d but expected %d\n", s12.f9, 9);
6023         }
6024         if (s12.f10 != 10) {
6025                 fprintf(stderr, "mono_return_sbyte12 s12.f10: got %d but expected %d\n", s12.f10, 10);
6026         }
6027         if (s12.f11 != 11) {
6028                 fprintf(stderr, "mono_return_sbyte12 s12.f11: got %d but expected %d\n", s12.f11, 11);
6029         }
6030         if (s12.f12 != 12) {
6031                 fprintf(stderr, "mono_return_sbyte12 s12.f12: got %d but expected %d\n", s12.f12, 12);
6032         }
6033         s12.f1+=addend; s12.f2+=addend; s12.f3+=addend; s12.f4+=addend; s12.f5+=addend; s12.f6+=addend; s12.f7+=addend; s12.f8+=addend; s12.f9+=addend; s12.f10+=addend; s12.f11+=addend; s12.f12+=addend; 
6034         return s12;
6035 }
6036
6037 typedef struct {
6038         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13;
6039 } sbyte13;
6040
6041 LIBTEST_API sbyte13 STDCALL
6042 mono_return_sbyte13 (sbyte13 s13, int addend) {
6043         if (s13.f1 != 1) {
6044                 fprintf(stderr, "mono_return_sbyte13 s13.f1: got %d but expected %d\n", s13.f1, 1);
6045         }
6046         if (s13.f2 != 2) {
6047                 fprintf(stderr, "mono_return_sbyte13 s13.f2: got %d but expected %d\n", s13.f2, 2);
6048         }
6049         if (s13.f3 != 3) {
6050                 fprintf(stderr, "mono_return_sbyte13 s13.f3: got %d but expected %d\n", s13.f3, 3);
6051         }
6052         if (s13.f4 != 4) {
6053                 fprintf(stderr, "mono_return_sbyte13 s13.f4: got %d but expected %d\n", s13.f4, 4);
6054         }
6055         if (s13.f5 != 5) {
6056                 fprintf(stderr, "mono_return_sbyte13 s13.f5: got %d but expected %d\n", s13.f5, 5);
6057         }
6058         if (s13.f6 != 6) {
6059                 fprintf(stderr, "mono_return_sbyte13 s13.f6: got %d but expected %d\n", s13.f6, 6);
6060         }
6061         if (s13.f7 != 7) {
6062                 fprintf(stderr, "mono_return_sbyte13 s13.f7: got %d but expected %d\n", s13.f7, 7);
6063         }
6064         if (s13.f8 != 8) {
6065                 fprintf(stderr, "mono_return_sbyte13 s13.f8: got %d but expected %d\n", s13.f8, 8);
6066         }
6067         if (s13.f9 != 9) {
6068                 fprintf(stderr, "mono_return_sbyte13 s13.f9: got %d but expected %d\n", s13.f9, 9);
6069         }
6070         if (s13.f10 != 10) {
6071                 fprintf(stderr, "mono_return_sbyte13 s13.f10: got %d but expected %d\n", s13.f10, 10);
6072         }
6073         if (s13.f11 != 11) {
6074                 fprintf(stderr, "mono_return_sbyte13 s13.f11: got %d but expected %d\n", s13.f11, 11);
6075         }
6076         if (s13.f12 != 12) {
6077                 fprintf(stderr, "mono_return_sbyte13 s13.f12: got %d but expected %d\n", s13.f12, 12);
6078         }
6079         if (s13.f13 != 13) {
6080                 fprintf(stderr, "mono_return_sbyte13 s13.f13: got %d but expected %d\n", s13.f13, 13);
6081         }
6082         s13.f1+=addend; s13.f2+=addend; s13.f3+=addend; s13.f4+=addend; s13.f5+=addend; s13.f6+=addend; s13.f7+=addend; s13.f8+=addend; s13.f9+=addend; s13.f10+=addend; s13.f11+=addend; s13.f12+=addend; s13.f13+=addend; 
6083         return s13;
6084 }
6085
6086 typedef struct {
6087         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14;
6088 } sbyte14;
6089
6090 LIBTEST_API sbyte14 STDCALL
6091 mono_return_sbyte14 (sbyte14 s14, int addend) {
6092         if (s14.f1 != 1) {
6093                 fprintf(stderr, "mono_return_sbyte14 s14.f1: got %d but expected %d\n", s14.f1, 1);
6094         }
6095         if (s14.f2 != 2) {
6096                 fprintf(stderr, "mono_return_sbyte14 s14.f2: got %d but expected %d\n", s14.f2, 2);
6097         }
6098         if (s14.f3 != 3) {
6099                 fprintf(stderr, "mono_return_sbyte14 s14.f3: got %d but expected %d\n", s14.f3, 3);
6100         }
6101         if (s14.f4 != 4) {
6102                 fprintf(stderr, "mono_return_sbyte14 s14.f4: got %d but expected %d\n", s14.f4, 4);
6103         }
6104         if (s14.f5 != 5) {
6105                 fprintf(stderr, "mono_return_sbyte14 s14.f5: got %d but expected %d\n", s14.f5, 5);
6106         }
6107         if (s14.f6 != 6) {
6108                 fprintf(stderr, "mono_return_sbyte14 s14.f6: got %d but expected %d\n", s14.f6, 6);
6109         }
6110         if (s14.f7 != 7) {
6111                 fprintf(stderr, "mono_return_sbyte14 s14.f7: got %d but expected %d\n", s14.f7, 7);
6112         }
6113         if (s14.f8 != 8) {
6114                 fprintf(stderr, "mono_return_sbyte14 s14.f8: got %d but expected %d\n", s14.f8, 8);
6115         }
6116         if (s14.f9 != 9) {
6117                 fprintf(stderr, "mono_return_sbyte14 s14.f9: got %d but expected %d\n", s14.f9, 9);
6118         }
6119         if (s14.f10 != 10) {
6120                 fprintf(stderr, "mono_return_sbyte14 s14.f10: got %d but expected %d\n", s14.f10, 10);
6121         }
6122         if (s14.f11 != 11) {
6123                 fprintf(stderr, "mono_return_sbyte14 s14.f11: got %d but expected %d\n", s14.f11, 11);
6124         }
6125         if (s14.f12 != 12) {
6126                 fprintf(stderr, "mono_return_sbyte14 s14.f12: got %d but expected %d\n", s14.f12, 12);
6127         }
6128         if (s14.f13 != 13) {
6129                 fprintf(stderr, "mono_return_sbyte14 s14.f13: got %d but expected %d\n", s14.f13, 13);
6130         }
6131         if (s14.f14 != 14) {
6132                 fprintf(stderr, "mono_return_sbyte14 s14.f14: got %d but expected %d\n", s14.f14, 14);
6133         }
6134         s14.f1+=addend; s14.f2+=addend; s14.f3+=addend; s14.f4+=addend; s14.f5+=addend; s14.f6+=addend; s14.f7+=addend; s14.f8+=addend; s14.f9+=addend; s14.f10+=addend; s14.f11+=addend; s14.f12+=addend; s14.f13+=addend; s14.f14+=addend; 
6135         return s14;
6136 }
6137
6138 typedef struct {
6139         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
6140 } sbyte15;
6141
6142 LIBTEST_API sbyte15 STDCALL
6143 mono_return_sbyte15 (sbyte15 s15, int addend) {
6144         if (s15.f1 != 1) {
6145                 fprintf(stderr, "mono_return_sbyte15 s15.f1: got %d but expected %d\n", s15.f1, 1);
6146         }
6147         if (s15.f2 != 2) {
6148                 fprintf(stderr, "mono_return_sbyte15 s15.f2: got %d but expected %d\n", s15.f2, 2);
6149         }
6150         if (s15.f3 != 3) {
6151                 fprintf(stderr, "mono_return_sbyte15 s15.f3: got %d but expected %d\n", s15.f3, 3);
6152         }
6153         if (s15.f4 != 4) {
6154                 fprintf(stderr, "mono_return_sbyte15 s15.f4: got %d but expected %d\n", s15.f4, 4);
6155         }
6156         if (s15.f5 != 5) {
6157                 fprintf(stderr, "mono_return_sbyte15 s15.f5: got %d but expected %d\n", s15.f5, 5);
6158         }
6159         if (s15.f6 != 6) {
6160                 fprintf(stderr, "mono_return_sbyte15 s15.f6: got %d but expected %d\n", s15.f6, 6);
6161         }
6162         if (s15.f7 != 7) {
6163                 fprintf(stderr, "mono_return_sbyte15 s15.f7: got %d but expected %d\n", s15.f7, 7);
6164         }
6165         if (s15.f8 != 8) {
6166                 fprintf(stderr, "mono_return_sbyte15 s15.f8: got %d but expected %d\n", s15.f8, 8);
6167         }
6168         if (s15.f9 != 9) {
6169                 fprintf(stderr, "mono_return_sbyte15 s15.f9: got %d but expected %d\n", s15.f9, 9);
6170         }
6171         if (s15.f10 != 10) {
6172                 fprintf(stderr, "mono_return_sbyte15 s15.f10: got %d but expected %d\n", s15.f10, 10);
6173         }
6174         if (s15.f11 != 11) {
6175                 fprintf(stderr, "mono_return_sbyte15 s15.f11: got %d but expected %d\n", s15.f11, 11);
6176         }
6177         if (s15.f12 != 12) {
6178                 fprintf(stderr, "mono_return_sbyte15 s15.f12: got %d but expected %d\n", s15.f12, 12);
6179         }
6180         if (s15.f13 != 13) {
6181                 fprintf(stderr, "mono_return_sbyte15 s15.f13: got %d but expected %d\n", s15.f13, 13);
6182         }
6183         if (s15.f14 != 14) {
6184                 fprintf(stderr, "mono_return_sbyte15 s15.f14: got %d but expected %d\n", s15.f14, 14);
6185         }
6186         if (s15.f15 != 15) {
6187                 fprintf(stderr, "mono_return_sbyte15 s15.f15: got %d but expected %d\n", s15.f15, 15);
6188         }
6189         s15.f1+=addend; s15.f2+=addend; s15.f3+=addend; s15.f4+=addend; s15.f5+=addend; s15.f6+=addend; s15.f7+=addend; s15.f8+=addend; s15.f9+=addend; s15.f10+=addend; s15.f11+=addend; s15.f12+=addend; s15.f13+=addend; s15.f14+=addend; s15.f15+=addend; 
6190         return s15;
6191 }
6192
6193 typedef struct {
6194         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16;
6195 } sbyte16;
6196
6197 LIBTEST_API sbyte16 STDCALL
6198 mono_return_sbyte16 (sbyte16 s16, int addend) {
6199         if (s16.f1 != 1) {
6200                 fprintf(stderr, "mono_return_sbyte16 s16.f1: got %d but expected %d\n", s16.f1, 1);
6201         }
6202         if (s16.f2 != 2) {
6203                 fprintf(stderr, "mono_return_sbyte16 s16.f2: got %d but expected %d\n", s16.f2, 2);
6204         }
6205         if (s16.f3 != 3) {
6206                 fprintf(stderr, "mono_return_sbyte16 s16.f3: got %d but expected %d\n", s16.f3, 3);
6207         }
6208         if (s16.f4 != 4) {
6209                 fprintf(stderr, "mono_return_sbyte16 s16.f4: got %d but expected %d\n", s16.f4, 4);
6210         }
6211         if (s16.f5 != 5) {
6212                 fprintf(stderr, "mono_return_sbyte16 s16.f5: got %d but expected %d\n", s16.f5, 5);
6213         }
6214         if (s16.f6 != 6) {
6215                 fprintf(stderr, "mono_return_sbyte16 s16.f6: got %d but expected %d\n", s16.f6, 6);
6216         }
6217         if (s16.f7 != 7) {
6218                 fprintf(stderr, "mono_return_sbyte16 s16.f7: got %d but expected %d\n", s16.f7, 7);
6219         }
6220         if (s16.f8 != 8) {
6221                 fprintf(stderr, "mono_return_sbyte16 s16.f8: got %d but expected %d\n", s16.f8, 8);
6222         }
6223         if (s16.f9 != 9) {
6224                 fprintf(stderr, "mono_return_sbyte16 s16.f9: got %d but expected %d\n", s16.f9, 9);
6225         }
6226         if (s16.f10 != 10) {
6227                 fprintf(stderr, "mono_return_sbyte16 s16.f10: got %d but expected %d\n", s16.f10, 10);
6228         }
6229         if (s16.f11 != 11) {
6230                 fprintf(stderr, "mono_return_sbyte16 s16.f11: got %d but expected %d\n", s16.f11, 11);
6231         }
6232         if (s16.f12 != 12) {
6233                 fprintf(stderr, "mono_return_sbyte16 s16.f12: got %d but expected %d\n", s16.f12, 12);
6234         }
6235         if (s16.f13 != 13) {
6236                 fprintf(stderr, "mono_return_sbyte16 s16.f13: got %d but expected %d\n", s16.f13, 13);
6237         }
6238         if (s16.f14 != 14) {
6239                 fprintf(stderr, "mono_return_sbyte16 s16.f14: got %d but expected %d\n", s16.f14, 14);
6240         }
6241         if (s16.f15 != 15) {
6242                 fprintf(stderr, "mono_return_sbyte16 s16.f15: got %d but expected %d\n", s16.f15, 15);
6243         }
6244         if (s16.f16 != 16) {
6245                 fprintf(stderr, "mono_return_sbyte16 s16.f16: got %d but expected %d\n", s16.f16, 16);
6246         }
6247         s16.f1+=addend; s16.f2+=addend; s16.f3+=addend; s16.f4+=addend; s16.f5+=addend; s16.f6+=addend; s16.f7+=addend; s16.f8+=addend; s16.f9+=addend; s16.f10+=addend; s16.f11+=addend; s16.f12+=addend; s16.f13+=addend; s16.f14+=addend; s16.f15+=addend; s16.f16+=addend; 
6248         return s16;
6249 }
6250
6251 typedef struct {
6252         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17;
6253 } sbyte17;
6254
6255 LIBTEST_API sbyte17 STDCALL
6256 mono_return_sbyte17 (sbyte17 s17, int addend) {
6257         if (s17.f1 != 1) {
6258                 fprintf(stderr, "mono_return_sbyte17 s17.f1: got %d but expected %d\n", s17.f1, 1);
6259         }
6260         if (s17.f2 != 2) {
6261                 fprintf(stderr, "mono_return_sbyte17 s17.f2: got %d but expected %d\n", s17.f2, 2);
6262         }
6263         if (s17.f3 != 3) {
6264                 fprintf(stderr, "mono_return_sbyte17 s17.f3: got %d but expected %d\n", s17.f3, 3);
6265         }
6266         if (s17.f4 != 4) {
6267                 fprintf(stderr, "mono_return_sbyte17 s17.f4: got %d but expected %d\n", s17.f4, 4);
6268         }
6269         if (s17.f5 != 5) {
6270                 fprintf(stderr, "mono_return_sbyte17 s17.f5: got %d but expected %d\n", s17.f5, 5);
6271         }
6272         if (s17.f6 != 6) {
6273                 fprintf(stderr, "mono_return_sbyte17 s17.f6: got %d but expected %d\n", s17.f6, 6);
6274         }
6275         if (s17.f7 != 7) {
6276                 fprintf(stderr, "mono_return_sbyte17 s17.f7: got %d but expected %d\n", s17.f7, 7);
6277         }
6278         if (s17.f8 != 8) {
6279                 fprintf(stderr, "mono_return_sbyte17 s17.f8: got %d but expected %d\n", s17.f8, 8);
6280         }
6281         if (s17.f9 != 9) {
6282                 fprintf(stderr, "mono_return_sbyte17 s17.f9: got %d but expected %d\n", s17.f9, 9);
6283         }
6284         if (s17.f10 != 10) {
6285                 fprintf(stderr, "mono_return_sbyte17 s17.f10: got %d but expected %d\n", s17.f10, 10);
6286         }
6287         if (s17.f11 != 11) {
6288                 fprintf(stderr, "mono_return_sbyte17 s17.f11: got %d but expected %d\n", s17.f11, 11);
6289         }
6290         if (s17.f12 != 12) {
6291                 fprintf(stderr, "mono_return_sbyte17 s17.f12: got %d but expected %d\n", s17.f12, 12);
6292         }
6293         if (s17.f13 != 13) {
6294                 fprintf(stderr, "mono_return_sbyte17 s17.f13: got %d but expected %d\n", s17.f13, 13);
6295         }
6296         if (s17.f14 != 14) {
6297                 fprintf(stderr, "mono_return_sbyte17 s17.f14: got %d but expected %d\n", s17.f14, 14);
6298         }
6299         if (s17.f15 != 15) {
6300                 fprintf(stderr, "mono_return_sbyte17 s17.f15: got %d but expected %d\n", s17.f15, 15);
6301         }
6302         if (s17.f16 != 16) {
6303                 fprintf(stderr, "mono_return_sbyte17 s17.f16: got %d but expected %d\n", s17.f16, 16);
6304         }
6305         if (s17.f17 != 17) {
6306                 fprintf(stderr, "mono_return_sbyte17 s17.f17: got %d but expected %d\n", s17.f17, 17);
6307         }
6308         s17.f1+=addend; s17.f2+=addend; s17.f3+=addend; s17.f4+=addend; s17.f5+=addend; s17.f6+=addend; s17.f7+=addend; s17.f8+=addend; s17.f9+=addend; s17.f10+=addend; s17.f11+=addend; s17.f12+=addend; s17.f13+=addend; s17.f14+=addend; s17.f15+=addend; s17.f16+=addend; s17.f17+=addend; 
6309         return s17;
6310 }
6311
6312 typedef struct {
6313         struct {
6314                 char f1;
6315         } nested1;
6316         char f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
6317         struct {
6318                 char f16;
6319         } nested2;
6320 } sbyte16_nested;
6321
6322 LIBTEST_API sbyte16_nested STDCALL
6323 mono_return_sbyte16_nested (sbyte16_nested sn16, int addend) {
6324         if (sn16.nested1.f1 != 1) {
6325                 fprintf(stderr, "mono_return_sbyte16_nested sn16.nested1.f1: got %d but expected %d\n", sn16.nested1.f1, 1);
6326         }
6327         if (sn16.f2 != 2) {
6328                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f2: got %d but expected %d\n", sn16.f2, 2);
6329         }
6330         if (sn16.f3 != 3) {
6331                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f3: got %d but expected %d\n", sn16.f3, 3);
6332         }
6333         if (sn16.f4 != 4) {
6334                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f4: got %d but expected %d\n", sn16.f4, 4);
6335         }
6336         if (sn16.f5 != 5) {
6337                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f5: got %d but expected %d\n", sn16.f5, 5);
6338         }
6339         if (sn16.f6 != 6) {
6340                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f6: got %d but expected %d\n", sn16.f6, 6);
6341         }
6342         if (sn16.f7 != 7) {
6343                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f7: got %d but expected %d\n", sn16.f7, 7);
6344         }
6345         if (sn16.f8 != 8) {
6346                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f8: got %d but expected %d\n", sn16.f8, 8);
6347         }
6348         if (sn16.f9 != 9) {
6349                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f9: got %d but expected %d\n", sn16.f9, 9);
6350         }
6351         if (sn16.f10 != 10) {
6352                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f10: got %d but expected %d\n", sn16.f10, 10);
6353         }
6354         if (sn16.f11 != 11) {
6355                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f11: got %d but expected %d\n", sn16.f11, 11);
6356         }
6357         if (sn16.f12 != 12) {
6358                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f12: got %d but expected %d\n", sn16.f12, 12);
6359         }
6360         if (sn16.f13 != 13) {
6361                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f13: got %d but expected %d\n", sn16.f13, 13);
6362         }
6363         if (sn16.f14 != 14) {
6364                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f14: got %d but expected %d\n", sn16.f14, 14);
6365         }
6366         if (sn16.f15 != 15) {
6367                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f15: got %d but expected %d\n", sn16.f15, 15);
6368         }
6369         if (sn16.nested2.f16 != 16) {
6370                 fprintf(stderr, "mono_return_sbyte16_nested sn16.nested2.f16: got %d but expected %d\n", sn16.nested2.f16, 16);
6371         }
6372         sn16.nested1.f1+=addend; sn16.f2+=addend; sn16.f3+=addend; sn16.f4+=addend; sn16.f5+=addend; sn16.f6+=addend; sn16.f7+=addend; sn16.f8+=addend; sn16.f9+=addend; sn16.f10+=addend; sn16.f11+=addend; sn16.f12+=addend; sn16.f13+=addend; sn16.f14+=addend; sn16.f15+=addend; sn16.nested2.f16+=addend; 
6373         return sn16;
6374 }
6375
6376
6377 typedef struct {
6378         short f1;
6379 } short1;
6380
6381 LIBTEST_API short1 STDCALL
6382 mono_return_short1 (short1 s1, int addend) {
6383         if (s1.f1 != 1) {
6384                 fprintf(stderr, "mono_return_short1 s1.f1: got %d but expected %d\n", s1.f1, 1);
6385         }
6386         s1.f1+=addend; 
6387         return s1;
6388 }
6389
6390 typedef struct {
6391         short f1,f2;
6392 } short2;
6393
6394 LIBTEST_API short2 STDCALL
6395 mono_return_short2 (short2 s2, int addend) {
6396         if (s2.f1 != 1) {
6397                 fprintf(stderr, "mono_return_short2 s2.f1: got %d but expected %d\n", s2.f1, 1);
6398         }
6399         if (s2.f2 != 2) {
6400                 fprintf(stderr, "mono_return_short2 s2.f2: got %d but expected %d\n", s2.f2, 2);
6401         }
6402         s2.f1+=addend; s2.f2+=addend; 
6403         return s2;
6404 }
6405
6406 typedef struct {
6407         short f1,f2,f3;
6408 } short3;
6409
6410 LIBTEST_API short3 STDCALL
6411 mono_return_short3 (short3 s3, int addend) {
6412         if (s3.f1 != 1) {
6413                 fprintf(stderr, "mono_return_short3 s3.f1: got %d but expected %d\n", s3.f1, 1);
6414         }
6415         if (s3.f2 != 2) {
6416                 fprintf(stderr, "mono_return_short3 s3.f2: got %d but expected %d\n", s3.f2, 2);
6417         }
6418         if (s3.f3 != 3) {
6419                 fprintf(stderr, "mono_return_short3 s3.f3: got %d but expected %d\n", s3.f3, 3);
6420         }
6421         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6422         return s3;
6423 }
6424
6425 typedef struct {
6426         short f1,f2,f3,f4;
6427 } short4;
6428
6429 LIBTEST_API short4 STDCALL
6430 mono_return_short4 (short4 s4, int addend) {
6431         if (s4.f1 != 1) {
6432                 fprintf(stderr, "mono_return_short4 s4.f1: got %d but expected %d\n", s4.f1, 1);
6433         }
6434         if (s4.f2 != 2) {
6435                 fprintf(stderr, "mono_return_short4 s4.f2: got %d but expected %d\n", s4.f2, 2);
6436         }
6437         if (s4.f3 != 3) {
6438                 fprintf(stderr, "mono_return_short4 s4.f3: got %d but expected %d\n", s4.f3, 3);
6439         }
6440         if (s4.f4 != 4) {
6441                 fprintf(stderr, "mono_return_short4 s4.f4: got %d but expected %d\n", s4.f4, 4);
6442         }
6443         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6444         return s4;
6445 }
6446
6447 typedef struct {
6448         short f1,f2,f3,f4,f5;
6449 } short5;
6450
6451 LIBTEST_API short5 STDCALL
6452 mono_return_short5 (short5 s5, int addend) {
6453         if (s5.f1 != 1) {
6454                 fprintf(stderr, "mono_return_short5 s5.f1: got %d but expected %d\n", s5.f1, 1);
6455         }
6456         if (s5.f2 != 2) {
6457                 fprintf(stderr, "mono_return_short5 s5.f2: got %d but expected %d\n", s5.f2, 2);
6458         }
6459         if (s5.f3 != 3) {
6460                 fprintf(stderr, "mono_return_short5 s5.f3: got %d but expected %d\n", s5.f3, 3);
6461         }
6462         if (s5.f4 != 4) {
6463                 fprintf(stderr, "mono_return_short5 s5.f4: got %d but expected %d\n", s5.f4, 4);
6464         }
6465         if (s5.f5 != 5) {
6466                 fprintf(stderr, "mono_return_short5 s5.f5: got %d but expected %d\n", s5.f5, 5);
6467         }
6468         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6469         return s5;
6470 }
6471
6472 typedef struct {
6473         short f1,f2,f3,f4,f5,f6;
6474 } short6;
6475
6476 LIBTEST_API short6 STDCALL
6477 mono_return_short6 (short6 s6, int addend) {
6478         if (s6.f1 != 1) {
6479                 fprintf(stderr, "mono_return_short6 s6.f1: got %d but expected %d\n", s6.f1, 1);
6480         }
6481         if (s6.f2 != 2) {
6482                 fprintf(stderr, "mono_return_short6 s6.f2: got %d but expected %d\n", s6.f2, 2);
6483         }
6484         if (s6.f3 != 3) {
6485                 fprintf(stderr, "mono_return_short6 s6.f3: got %d but expected %d\n", s6.f3, 3);
6486         }
6487         if (s6.f4 != 4) {
6488                 fprintf(stderr, "mono_return_short6 s6.f4: got %d but expected %d\n", s6.f4, 4);
6489         }
6490         if (s6.f5 != 5) {
6491                 fprintf(stderr, "mono_return_short6 s6.f5: got %d but expected %d\n", s6.f5, 5);
6492         }
6493         if (s6.f6 != 6) {
6494                 fprintf(stderr, "mono_return_short6 s6.f6: got %d but expected %d\n", s6.f6, 6);
6495         }
6496         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
6497         return s6;
6498 }
6499
6500 typedef struct {
6501         short f1,f2,f3,f4,f5,f6,f7;
6502 } short7;
6503
6504 LIBTEST_API short7 STDCALL
6505 mono_return_short7 (short7 s7, int addend) {
6506         if (s7.f1 != 1) {
6507                 fprintf(stderr, "mono_return_short7 s7.f1: got %d but expected %d\n", s7.f1, 1);
6508         }
6509         if (s7.f2 != 2) {
6510                 fprintf(stderr, "mono_return_short7 s7.f2: got %d but expected %d\n", s7.f2, 2);
6511         }
6512         if (s7.f3 != 3) {
6513                 fprintf(stderr, "mono_return_short7 s7.f3: got %d but expected %d\n", s7.f3, 3);
6514         }
6515         if (s7.f4 != 4) {
6516                 fprintf(stderr, "mono_return_short7 s7.f4: got %d but expected %d\n", s7.f4, 4);
6517         }
6518         if (s7.f5 != 5) {
6519                 fprintf(stderr, "mono_return_short7 s7.f5: got %d but expected %d\n", s7.f5, 5);
6520         }
6521         if (s7.f6 != 6) {
6522                 fprintf(stderr, "mono_return_short7 s7.f6: got %d but expected %d\n", s7.f6, 6);
6523         }
6524         if (s7.f7 != 7) {
6525                 fprintf(stderr, "mono_return_short7 s7.f7: got %d but expected %d\n", s7.f7, 7);
6526         }
6527         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
6528         return s7;
6529 }
6530
6531 typedef struct {
6532         short f1,f2,f3,f4,f5,f6,f7,f8;
6533 } short8;
6534
6535 LIBTEST_API short8 STDCALL
6536 mono_return_short8 (short8 s8, int addend) {
6537         if (s8.f1 != 1) {
6538                 fprintf(stderr, "mono_return_short8 s8.f1: got %d but expected %d\n", s8.f1, 1);
6539         }
6540         if (s8.f2 != 2) {
6541                 fprintf(stderr, "mono_return_short8 s8.f2: got %d but expected %d\n", s8.f2, 2);
6542         }
6543         if (s8.f3 != 3) {
6544                 fprintf(stderr, "mono_return_short8 s8.f3: got %d but expected %d\n", s8.f3, 3);
6545         }
6546         if (s8.f4 != 4) {
6547                 fprintf(stderr, "mono_return_short8 s8.f4: got %d but expected %d\n", s8.f4, 4);
6548         }
6549         if (s8.f5 != 5) {
6550                 fprintf(stderr, "mono_return_short8 s8.f5: got %d but expected %d\n", s8.f5, 5);
6551         }
6552         if (s8.f6 != 6) {
6553                 fprintf(stderr, "mono_return_short8 s8.f6: got %d but expected %d\n", s8.f6, 6);
6554         }
6555         if (s8.f7 != 7) {
6556                 fprintf(stderr, "mono_return_short8 s8.f7: got %d but expected %d\n", s8.f7, 7);
6557         }
6558         if (s8.f8 != 8) {
6559                 fprintf(stderr, "mono_return_short8 s8.f8: got %d but expected %d\n", s8.f8, 8);
6560         }
6561         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
6562         return s8;
6563 }
6564
6565 typedef struct {
6566         short f1,f2,f3,f4,f5,f6,f7,f8,f9;
6567 } short9;
6568
6569 LIBTEST_API short9 STDCALL
6570 mono_return_short9 (short9 s9, int addend) {
6571         if (s9.f1 != 1) {
6572                 fprintf(stderr, "mono_return_short9 s9.f1: got %d but expected %d\n", s9.f1, 1);
6573         }
6574         if (s9.f2 != 2) {
6575                 fprintf(stderr, "mono_return_short9 s9.f2: got %d but expected %d\n", s9.f2, 2);
6576         }
6577         if (s9.f3 != 3) {
6578                 fprintf(stderr, "mono_return_short9 s9.f3: got %d but expected %d\n", s9.f3, 3);
6579         }
6580         if (s9.f4 != 4) {
6581                 fprintf(stderr, "mono_return_short9 s9.f4: got %d but expected %d\n", s9.f4, 4);
6582         }
6583         if (s9.f5 != 5) {
6584                 fprintf(stderr, "mono_return_short9 s9.f5: got %d but expected %d\n", s9.f5, 5);
6585         }
6586         if (s9.f6 != 6) {
6587                 fprintf(stderr, "mono_return_short9 s9.f6: got %d but expected %d\n", s9.f6, 6);
6588         }
6589         if (s9.f7 != 7) {
6590                 fprintf(stderr, "mono_return_short9 s9.f7: got %d but expected %d\n", s9.f7, 7);
6591         }
6592         if (s9.f8 != 8) {
6593                 fprintf(stderr, "mono_return_short9 s9.f8: got %d but expected %d\n", s9.f8, 8);
6594         }
6595         if (s9.f9 != 9) {
6596                 fprintf(stderr, "mono_return_short9 s9.f9: got %d but expected %d\n", s9.f9, 9);
6597         }
6598         s9.f1+=addend; s9.f2+=addend; s9.f3+=addend; s9.f4+=addend; s9.f5+=addend; s9.f6+=addend; s9.f7+=addend; s9.f8+=addend; s9.f9+=addend; 
6599         return s9;
6600 }
6601
6602 typedef struct {
6603         struct {
6604                 short f1;
6605         } nested1;
6606         short f2,f3,f4,f5,f6,f7;
6607         struct {
6608                 short f8;
6609         } nested2;
6610 } short8_nested;
6611
6612 LIBTEST_API short8_nested STDCALL
6613 mono_return_short8_nested (short8_nested sn8, int addend) {
6614         if (sn8.nested1.f1 != 1) {
6615                 fprintf(stderr, "mono_return_short8_nested sn8.nested1.f1: got %d but expected %d\n", sn8.nested1.f1, 1);
6616         }
6617         if (sn8.f2 != 2) {
6618                 fprintf(stderr, "mono_return_short8_nested sn8.f2: got %d but expected %d\n", sn8.f2, 2);
6619         }
6620         if (sn8.f3 != 3) {
6621                 fprintf(stderr, "mono_return_short8_nested sn8.f3: got %d but expected %d\n", sn8.f3, 3);
6622         }
6623         if (sn8.f4 != 4) {
6624                 fprintf(stderr, "mono_return_short8_nested sn8.f4: got %d but expected %d\n", sn8.f4, 4);
6625         }
6626         if (sn8.f5 != 5) {
6627                 fprintf(stderr, "mono_return_short8_nested sn8.f5: got %d but expected %d\n", sn8.f5, 5);
6628         }
6629         if (sn8.f6 != 6) {
6630                 fprintf(stderr, "mono_return_short8_nested sn8.f6: got %d but expected %d\n", sn8.f6, 6);
6631         }
6632         if (sn8.f7 != 7) {
6633                 fprintf(stderr, "mono_return_short8_nested sn8.f7: got %d but expected %d\n", sn8.f7, 7);
6634         }
6635         if (sn8.nested2.f8 != 8) {
6636                 fprintf(stderr, "mono_return_short8_nested sn8.nested2.f8: got %d but expected %d\n", sn8.nested2.f8, 8);
6637         }
6638         sn8.nested1.f1+=addend; sn8.f2+=addend; sn8.f3+=addend; sn8.f4+=addend; sn8.f5+=addend; sn8.f6+=addend; sn8.f7+=addend; sn8.nested2.f8+=addend; 
6639         return sn8;
6640 }
6641
6642
6643 typedef struct {
6644         int f1;
6645 } int1;
6646
6647 LIBTEST_API int1 STDCALL
6648 mono_return_int1 (int1 s1, int addend) {
6649         if (s1.f1 != 1) {
6650                 fprintf(stderr, "mono_return_int1 s1.f1: got %d but expected %d\n", s1.f1, 1);
6651         }
6652         s1.f1+=addend; 
6653         return s1;
6654 }
6655
6656 typedef struct {
6657         int f1,f2;
6658 } int2;
6659
6660 LIBTEST_API int2 STDCALL
6661 mono_return_int2 (int2 s2, int addend) {
6662         if (s2.f1 != 1) {
6663                 fprintf(stderr, "mono_return_int2 s2.f1: got %d but expected %d\n", s2.f1, 1);
6664         }
6665         if (s2.f2 != 2) {
6666                 fprintf(stderr, "mono_return_int2 s2.f2: got %d but expected %d\n", s2.f2, 2);
6667         }
6668         s2.f1+=addend; s2.f2+=addend; 
6669         return s2;
6670 }
6671
6672 typedef struct {
6673         int f1,f2,f3;
6674 } int3;
6675
6676 LIBTEST_API int3 STDCALL
6677 mono_return_int3 (int3 s3, int addend) {
6678         if (s3.f1 != 1) {
6679                 fprintf(stderr, "mono_return_int3 s3.f1: got %d but expected %d\n", s3.f1, 1);
6680         }
6681         if (s3.f2 != 2) {
6682                 fprintf(stderr, "mono_return_int3 s3.f2: got %d but expected %d\n", s3.f2, 2);
6683         }
6684         if (s3.f3 != 3) {
6685                 fprintf(stderr, "mono_return_int3 s3.f3: got %d but expected %d\n", s3.f3, 3);
6686         }
6687         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6688         return s3;
6689 }
6690
6691 typedef struct {
6692         int f1,f2,f3,f4;
6693 } int4;
6694
6695 LIBTEST_API int4 STDCALL
6696 mono_return_int4 (int4 s4, int addend) {
6697         if (s4.f1 != 1) {
6698                 fprintf(stderr, "mono_return_int4 s4.f1: got %d but expected %d\n", s4.f1, 1);
6699         }
6700         if (s4.f2 != 2) {
6701                 fprintf(stderr, "mono_return_int4 s4.f2: got %d but expected %d\n", s4.f2, 2);
6702         }
6703         if (s4.f3 != 3) {
6704                 fprintf(stderr, "mono_return_int4 s4.f3: got %d but expected %d\n", s4.f3, 3);
6705         }
6706         if (s4.f4 != 4) {
6707                 fprintf(stderr, "mono_return_int4 s4.f4: got %d but expected %d\n", s4.f4, 4);
6708         }
6709         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6710         return s4;
6711 }
6712
6713 typedef struct {
6714         int f1,f2,f3,f4,f5;
6715 } int5;
6716
6717 LIBTEST_API int5 STDCALL
6718 mono_return_int5 (int5 s5, int addend) {
6719         if (s5.f1 != 1) {
6720                 fprintf(stderr, "mono_return_int5 s5.f1: got %d but expected %d\n", s5.f1, 1);
6721         }
6722         if (s5.f2 != 2) {
6723                 fprintf(stderr, "mono_return_int5 s5.f2: got %d but expected %d\n", s5.f2, 2);
6724         }
6725         if (s5.f3 != 3) {
6726                 fprintf(stderr, "mono_return_int5 s5.f3: got %d but expected %d\n", s5.f3, 3);
6727         }
6728         if (s5.f4 != 4) {
6729                 fprintf(stderr, "mono_return_int5 s5.f4: got %d but expected %d\n", s5.f4, 4);
6730         }
6731         if (s5.f5 != 5) {
6732                 fprintf(stderr, "mono_return_int5 s5.f5: got %d but expected %d\n", s5.f5, 5);
6733         }
6734         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6735         return s5;
6736 }
6737
6738 typedef struct {
6739         struct {
6740                 int f1;
6741         } nested1;
6742         int f2,f3;
6743         struct {
6744                 int f4;
6745         } nested2;
6746 } int4_nested;
6747
6748 LIBTEST_API int4_nested STDCALL
6749 mono_return_int4_nested (int4_nested sn4, int addend) {
6750         if (sn4.nested1.f1 != 1) {
6751                 fprintf(stderr, "mono_return_int4_nested sn4.nested1.f1: got %d but expected %d\n", sn4.nested1.f1, 1);
6752         }
6753         if (sn4.f2 != 2) {
6754                 fprintf(stderr, "mono_return_int4_nested sn4.f2: got %d but expected %d\n", sn4.f2, 2);
6755         }
6756         if (sn4.f3 != 3) {
6757                 fprintf(stderr, "mono_return_int4_nested sn4.f3: got %d but expected %d\n", sn4.f3, 3);
6758         }
6759         if (sn4.nested2.f4 != 4) {
6760                 fprintf(stderr, "mono_return_int4_nested sn4.nested2.f4: got %d but expected %d\n", sn4.nested2.f4, 4);
6761         }
6762         sn4.nested1.f1+=addend; sn4.f2+=addend; sn4.f3+=addend; sn4.nested2.f4+=addend; 
6763         return sn4;
6764 }
6765
6766 typedef struct {
6767         float f1;
6768 } float1;
6769
6770 LIBTEST_API float1 STDCALL
6771 mono_return_float1 (float1 s1, int addend) {
6772         if (s1.f1 != 1) {
6773                 fprintf(stderr, "mono_return_float1 s1.f1: got %f but expected %d\n", s1.f1, 1);
6774         }
6775         s1.f1+=addend; 
6776         return s1;
6777 }
6778
6779 typedef struct {
6780         float f1,f2;
6781 } float2;
6782
6783 LIBTEST_API float2 STDCALL
6784 mono_return_float2 (float2 s2, int addend) {
6785         if (s2.f1 != 1) {
6786                 fprintf(stderr, "mono_return_float2 s2.f1: got %f but expected %d\n", s2.f1, 1);
6787         }
6788         if (s2.f2 != 2) {
6789                 fprintf(stderr, "mono_return_float2 s2.f2: got %f but expected %d\n", s2.f2, 2);
6790         }
6791         s2.f1+=addend; s2.f2+=addend; 
6792         return s2;
6793 }
6794
6795 typedef struct {
6796         float f1,f2,f3;
6797 } float3;
6798
6799 LIBTEST_API float3 STDCALL
6800 mono_return_float3 (float3 s3, int addend) {
6801         if (s3.f1 != 1) {
6802                 fprintf(stderr, "mono_return_float3 s3.f1: got %f but expected %d\n", s3.f1, 1);
6803         }
6804         if (s3.f2 != 2) {
6805                 fprintf(stderr, "mono_return_float3 s3.f2: got %f but expected %d\n", s3.f2, 2);
6806         }
6807         if (s3.f3 != 3) {
6808                 fprintf(stderr, "mono_return_float3 s3.f3: got %f but expected %d\n", s3.f3, 3);
6809         }
6810         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6811         return s3;
6812 }
6813
6814 typedef struct {
6815         float f1,f2,f3,f4;
6816 } float4;
6817
6818 LIBTEST_API float4 STDCALL
6819 mono_return_float4 (float4 s4, int addend) {
6820         if (s4.f1 != 1) {
6821                 fprintf(stderr, "mono_return_float4 s4.f1: got %f but expected %d\n", s4.f1, 1);
6822         }
6823         if (s4.f2 != 2) {
6824                 fprintf(stderr, "mono_return_float4 s4.f2: got %f but expected %d\n", s4.f2, 2);
6825         }
6826         if (s4.f3 != 3) {
6827                 fprintf(stderr, "mono_return_float4 s4.f3: got %f but expected %d\n", s4.f3, 3);
6828         }
6829         if (s4.f4 != 4) {
6830                 fprintf(stderr, "mono_return_float4 s4.f4: got %f but expected %d\n", s4.f4, 4);
6831         }
6832         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6833         return s4;
6834 }
6835
6836 typedef struct {
6837         float f1,f2,f3,f4,f5;
6838 } float5;
6839
6840 LIBTEST_API float5 STDCALL
6841 mono_return_float5 (float5 s5, int addend) {
6842         if (s5.f1 != 1) {
6843                 fprintf(stderr, "mono_return_float5 s5.f1: got %f but expected %d\n", s5.f1, 1);
6844         }
6845         if (s5.f2 != 2) {
6846                 fprintf(stderr, "mono_return_float5 s5.f2: got %f but expected %d\n", s5.f2, 2);
6847         }
6848         if (s5.f3 != 3) {
6849                 fprintf(stderr, "mono_return_float5 s5.f3: got %f but expected %d\n", s5.f3, 3);
6850         }
6851         if (s5.f4 != 4) {
6852                 fprintf(stderr, "mono_return_float5 s5.f4: got %f but expected %d\n", s5.f4, 4);
6853         }
6854         if (s5.f5 != 5) {
6855                 fprintf(stderr, "mono_return_float5 s5.f5: got %f but expected %d\n", s5.f5, 5);
6856         }
6857         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6858         return s5;
6859 }
6860
6861 typedef struct {
6862         float f1,f2,f3,f4,f5,f6;
6863 } float6;
6864
6865 LIBTEST_API float6 STDCALL
6866 mono_return_float6 (float6 s6, int addend) {
6867         if (s6.f1 != 1) {
6868                 fprintf(stderr, "mono_return_float6 s6.f1: got %f but expected %d\n", s6.f1, 1);
6869         }
6870         if (s6.f2 != 2) {
6871                 fprintf(stderr, "mono_return_float6 s6.f2: got %f but expected %d\n", s6.f2, 2);
6872         }
6873         if (s6.f3 != 3) {
6874                 fprintf(stderr, "mono_return_float6 s6.f3: got %f but expected %d\n", s6.f3, 3);
6875         }
6876         if (s6.f4 != 4) {
6877                 fprintf(stderr, "mono_return_float6 s6.f4: got %f but expected %d\n", s6.f4, 4);
6878         }
6879         if (s6.f5 != 5) {
6880                 fprintf(stderr, "mono_return_float6 s6.f5: got %f but expected %d\n", s6.f5, 5);
6881         }
6882         if (s6.f6 != 6) {
6883                 fprintf(stderr, "mono_return_float6 s6.f6: got %f but expected %d\n", s6.f6, 6);
6884         }
6885         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
6886         return s6;
6887 }
6888
6889 typedef struct {
6890         float f1,f2,f3,f4,f5,f6,f7;
6891 } float7;
6892
6893 LIBTEST_API float7 STDCALL
6894 mono_return_float7 (float7 s7, int addend) {
6895         if (s7.f1 != 1) {
6896                 fprintf(stderr, "mono_return_float7 s7.f1: got %f but expected %d\n", s7.f1, 1);
6897         }
6898         if (s7.f2 != 2) {
6899                 fprintf(stderr, "mono_return_float7 s7.f2: got %f but expected %d\n", s7.f2, 2);
6900         }
6901         if (s7.f3 != 3) {
6902                 fprintf(stderr, "mono_return_float7 s7.f3: got %f but expected %d\n", s7.f3, 3);
6903         }
6904         if (s7.f4 != 4) {
6905                 fprintf(stderr, "mono_return_float7 s7.f4: got %f but expected %d\n", s7.f4, 4);
6906         }
6907         if (s7.f5 != 5) {
6908                 fprintf(stderr, "mono_return_float7 s7.f5: got %f but expected %d\n", s7.f5, 5);
6909         }
6910         if (s7.f6 != 6) {
6911                 fprintf(stderr, "mono_return_float7 s7.f6: got %f but expected %d\n", s7.f6, 6);
6912         }
6913         if (s7.f7 != 7) {
6914                 fprintf(stderr, "mono_return_float7 s7.f7: got %f but expected %d\n", s7.f7, 7);
6915         }
6916         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
6917         return s7;
6918 }
6919
6920 typedef struct {
6921         float f1,f2,f3,f4,f5,f6,f7,f8;
6922 } float8;
6923
6924 LIBTEST_API float8 STDCALL
6925 mono_return_float8 (float8 s8, int addend) {
6926         if (s8.f1 != 1) {
6927                 fprintf(stderr, "mono_return_float8 s8.f1: got %f but expected %d\n", s8.f1, 1);
6928         }
6929         if (s8.f2 != 2) {
6930                 fprintf(stderr, "mono_return_float8 s8.f2: got %f but expected %d\n", s8.f2, 2);
6931         }
6932         if (s8.f3 != 3) {
6933                 fprintf(stderr, "mono_return_float8 s8.f3: got %f but expected %d\n", s8.f3, 3);
6934         }
6935         if (s8.f4 != 4) {
6936                 fprintf(stderr, "mono_return_float8 s8.f4: got %f but expected %d\n", s8.f4, 4);
6937         }
6938         if (s8.f5 != 5) {
6939                 fprintf(stderr, "mono_return_float8 s8.f5: got %f but expected %d\n", s8.f5, 5);
6940         }
6941         if (s8.f6 != 6) {
6942                 fprintf(stderr, "mono_return_float8 s8.f6: got %f but expected %d\n", s8.f6, 6);
6943         }
6944         if (s8.f7 != 7) {
6945                 fprintf(stderr, "mono_return_float8 s8.f7: got %f but expected %d\n", s8.f7, 7);
6946         }
6947         if (s8.f8 != 8) {
6948                 fprintf(stderr, "mono_return_float8 s8.f8: got %f but expected %d\n", s8.f8, 8);
6949         }
6950         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
6951         return s8;
6952 }
6953
6954 typedef struct {
6955         float f1,f2,f3,f4,f5,f6,f7,f8,f9;
6956 } float9;
6957
6958 LIBTEST_API float9 STDCALL
6959 mono_return_float9 (float9 s9, int addend) {
6960         if (s9.f1 != 1) {
6961                 fprintf(stderr, "mono_return_float9 s9.f1: got %f but expected %d\n", s9.f1, 1);
6962         }
6963         if (s9.f2 != 2) {
6964                 fprintf(stderr, "mono_return_float9 s9.f2: got %f but expected %d\n", s9.f2, 2);
6965         }
6966         if (s9.f3 != 3) {
6967                 fprintf(stderr, "mono_return_float9 s9.f3: got %f but expected %d\n", s9.f3, 3);
6968         }
6969         if (s9.f4 != 4) {
6970                 fprintf(stderr, "mono_return_float9 s9.f4: got %f but expected %d\n", s9.f4, 4);
6971         }
6972         if (s9.f5 != 5) {
6973                 fprintf(stderr, "mono_return_float9 s9.f5: got %f but expected %d\n", s9.f5, 5);
6974         }
6975         if (s9.f6 != 6) {
6976                 fprintf(stderr, "mono_return_float9 s9.f6: got %f but expected %d\n", s9.f6, 6);
6977         }
6978         if (s9.f7 != 7) {
6979                 fprintf(stderr, "mono_return_float9 s9.f7: got %f but expected %d\n", s9.f7, 7);
6980         }
6981         if (s9.f8 != 8) {
6982                 fprintf(stderr, "mono_return_float9 s9.f8: got %f but expected %d\n", s9.f8, 8);
6983         }
6984         if (s9.f9 != 9) {
6985                 fprintf(stderr, "mono_return_float9 s9.f9: got %f but expected %d\n", s9.f9, 9);
6986         }
6987         s9.f1+=addend; s9.f2+=addend; s9.f3+=addend; s9.f4+=addend; s9.f5+=addend; s9.f6+=addend; s9.f7+=addend; s9.f8+=addend; s9.f9+=addend; 
6988         return s9;
6989 }
6990
6991 typedef struct {
6992         struct {
6993                 float f1;
6994         } nested1;
6995         float f2,f3;
6996         struct {
6997                 float f4;
6998         } nested2;
6999 } float4_nested;
7000
7001 LIBTEST_API float4_nested STDCALL
7002 mono_return_float4_nested (float4_nested sn4, int addend) {
7003         if (sn4.nested1.f1 != 1) {
7004                 fprintf(stderr, "mono_return_float4_nested sn4.nested1.f1: got %f but expected %d\n", sn4.nested1.f1, 1);
7005         }
7006         if (sn4.f2 != 2) {
7007                 fprintf(stderr, "mono_return_float4_nested sn4.f2: got %f but expected %d\n", sn4.f2, 2);
7008         }
7009         if (sn4.f3 != 3) {
7010                 fprintf(stderr, "mono_return_float4_nested sn4.f3: got %f but expected %d\n", sn4.f3, 3);
7011         }
7012         if (sn4.nested2.f4 != 4) {
7013                 fprintf(stderr, "mono_return_float4_nested sn4.nested2.f4: got %f but expected %d\n", sn4.nested2.f4, 4);
7014         }
7015         sn4.nested1.f1+=addend; sn4.f2+=addend; sn4.f3+=addend; sn4.nested2.f4+=addend; 
7016         return sn4;
7017 }
7018
7019 typedef struct {
7020         double f1;
7021 } double1;
7022
7023 LIBTEST_API double1 STDCALL
7024 mono_return_double1 (double1 s1, int addend) {
7025         if (s1.f1 != 1) {
7026                 fprintf(stderr, "mono_return_double1 s1.f1: got %f but expected %d\n", s1.f1, 1);
7027         }
7028         s1.f1+=addend; 
7029         return s1;
7030 }
7031
7032 typedef struct {
7033         double f1,f2;
7034 } double2;
7035
7036 LIBTEST_API double2 STDCALL
7037 mono_return_double2 (double2 s2, int addend) {
7038         if (s2.f1 != 1) {
7039                 fprintf(stderr, "mono_return_double2 s2.f1: got %f but expected %d\n", s2.f1, 1);
7040         }
7041         if (s2.f2 != 2) {
7042                 fprintf(stderr, "mono_return_double2 s2.f2: got %f but expected %d\n", s2.f2, 2);
7043         }
7044         s2.f1+=addend; s2.f2+=addend; 
7045         return s2;
7046 }
7047
7048 typedef struct {
7049         double f1,f2,f3;
7050 } double3;
7051
7052 LIBTEST_API double3 STDCALL
7053 mono_return_double3 (double3 s3, int addend) {
7054         if (s3.f1 != 1) {
7055                 fprintf(stderr, "mono_return_double3 s3.f1: got %f but expected %d\n", s3.f1, 1);
7056         }
7057         if (s3.f2 != 2) {
7058                 fprintf(stderr, "mono_return_double3 s3.f2: got %f but expected %d\n", s3.f2, 2);
7059         }
7060         if (s3.f3 != 3) {
7061                 fprintf(stderr, "mono_return_double3 s3.f3: got %f but expected %d\n", s3.f3, 3);
7062         }
7063         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
7064         return s3;
7065 }
7066
7067 typedef struct {
7068         double f1,f2,f3,f4;
7069 } double4;
7070
7071 LIBTEST_API double4 STDCALL
7072 mono_return_double4 (double4 s4, int addend) {
7073         if (s4.f1 != 1) {
7074                 fprintf(stderr, "mono_return_double4 s4.f1: got %f but expected %d\n", s4.f1, 1);
7075         }
7076         if (s4.f2 != 2) {
7077                 fprintf(stderr, "mono_return_double4 s4.f2: got %f but expected %d\n", s4.f2, 2);
7078         }
7079         if (s4.f3 != 3) {
7080                 fprintf(stderr, "mono_return_double4 s4.f3: got %f but expected %d\n", s4.f3, 3);
7081         }
7082         if (s4.f4 != 4) {
7083                 fprintf(stderr, "mono_return_double4 s4.f4: got %f but expected %d\n", s4.f4, 4);
7084         }
7085         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
7086         return s4;
7087 }
7088
7089 typedef struct {
7090         double f1,f2,f3,f4,f5;
7091 } double5;
7092
7093 LIBTEST_API double5 STDCALL
7094 mono_return_double5 (double5 s5, int addend) {
7095         if (s5.f1 != 1) {
7096                 fprintf(stderr, "mono_return_double5 s5.f1: got %f but expected %d\n", s5.f1, 1);
7097         }
7098         if (s5.f2 != 2) {
7099                 fprintf(stderr, "mono_return_double5 s5.f2: got %f but expected %d\n", s5.f2, 2);
7100         }
7101         if (s5.f3 != 3) {
7102                 fprintf(stderr, "mono_return_double5 s5.f3: got %f but expected %d\n", s5.f3, 3);
7103         }
7104         if (s5.f4 != 4) {
7105                 fprintf(stderr, "mono_return_double5 s5.f4: got %f but expected %d\n", s5.f4, 4);
7106         }
7107         if (s5.f5 != 5) {
7108                 fprintf(stderr, "mono_return_double5 s5.f5: got %f but expected %d\n", s5.f5, 5);
7109         }
7110         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
7111         return s5;
7112 }
7113
7114 typedef struct {
7115         double f1,f2,f3,f4,f5,f6;
7116 } double6;
7117
7118 LIBTEST_API double6 STDCALL
7119 mono_return_double6 (double6 s6, int addend) {
7120         if (s6.f1 != 1) {
7121                 fprintf(stderr, "mono_return_double6 s6.f1: got %f but expected %d\n", s6.f1, 1);
7122         }
7123         if (s6.f2 != 2) {
7124                 fprintf(stderr, "mono_return_double6 s6.f2: got %f but expected %d\n", s6.f2, 2);
7125         }
7126         if (s6.f3 != 3) {
7127                 fprintf(stderr, "mono_return_double6 s6.f3: got %f but expected %d\n", s6.f3, 3);
7128         }
7129         if (s6.f4 != 4) {
7130                 fprintf(stderr, "mono_return_double6 s6.f4: got %f but expected %d\n", s6.f4, 4);
7131         }
7132         if (s6.f5 != 5) {
7133                 fprintf(stderr, "mono_return_double6 s6.f5: got %f but expected %d\n", s6.f5, 5);
7134         }
7135         if (s6.f6 != 6) {
7136                 fprintf(stderr, "mono_return_double6 s6.f6: got %f but expected %d\n", s6.f6, 6);
7137         }
7138         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
7139         return s6;
7140 }
7141
7142 typedef struct {
7143         double f1,f2,f3,f4,f5,f6,f7;
7144 } double7;
7145
7146 LIBTEST_API double7 STDCALL
7147 mono_return_double7 (double7 s7, int addend) {
7148         if (s7.f1 != 1) {
7149                 fprintf(stderr, "mono_return_double7 s7.f1: got %f but expected %d\n", s7.f1, 1);
7150         }
7151         if (s7.f2 != 2) {
7152                 fprintf(stderr, "mono_return_double7 s7.f2: got %f but expected %d\n", s7.f2, 2);
7153         }
7154         if (s7.f3 != 3) {
7155                 fprintf(stderr, "mono_return_double7 s7.f3: got %f but expected %d\n", s7.f3, 3);
7156         }
7157         if (s7.f4 != 4) {
7158                 fprintf(stderr, "mono_return_double7 s7.f4: got %f but expected %d\n", s7.f4, 4);
7159         }
7160         if (s7.f5 != 5) {
7161                 fprintf(stderr, "mono_return_double7 s7.f5: got %f but expected %d\n", s7.f5, 5);
7162         }
7163         if (s7.f6 != 6) {
7164                 fprintf(stderr, "mono_return_double7 s7.f6: got %f but expected %d\n", s7.f6, 6);
7165         }
7166         if (s7.f7 != 7) {
7167                 fprintf(stderr, "mono_return_double7 s7.f7: got %f but expected %d\n", s7.f7, 7);
7168         }
7169         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
7170         return s7;
7171 }
7172
7173 typedef struct {
7174         double f1,f2,f3,f4,f5,f6,f7,f8;
7175 } double8;
7176
7177 LIBTEST_API double8 STDCALL
7178 mono_return_double8 (double8 s8, int addend) {
7179         if (s8.f1 != 1) {
7180                 fprintf(stderr, "mono_return_double8 s8.f1: got %f but expected %d\n", s8.f1, 1);
7181         }
7182         if (s8.f2 != 2) {
7183                 fprintf(stderr, "mono_return_double8 s8.f2: got %f but expected %d\n", s8.f2, 2);
7184         }
7185         if (s8.f3 != 3) {
7186                 fprintf(stderr, "mono_return_double8 s8.f3: got %f but expected %d\n", s8.f3, 3);
7187         }
7188         if (s8.f4 != 4) {
7189                 fprintf(stderr, "mono_return_double8 s8.f4: got %f but expected %d\n", s8.f4, 4);
7190         }
7191         if (s8.f5 != 5) {
7192                 fprintf(stderr, "mono_return_double8 s8.f5: got %f but expected %d\n", s8.f5, 5);
7193         }
7194         if (s8.f6 != 6) {
7195                 fprintf(stderr, "mono_return_double8 s8.f6: got %f but expected %d\n", s8.f6, 6);
7196         }
7197         if (s8.f7 != 7) {
7198                 fprintf(stderr, "mono_return_double8 s8.f7: got %f but expected %d\n", s8.f7, 7);
7199         }
7200         if (s8.f8 != 8) {
7201                 fprintf(stderr, "mono_return_double8 s8.f8: got %f but expected %d\n", s8.f8, 8);
7202         }
7203         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
7204         return s8;
7205 }
7206
7207 typedef struct {
7208         double f1,f2,f3,f4,f5,f6,f7,f8,f9;
7209 } double9;
7210
7211 LIBTEST_API double9 STDCALL
7212 mono_return_double9 (double9 s9, int addend) {
7213         if (s9.f1 != 1) {
7214                 fprintf(stderr, "mono_return_double9 s9.f1: got %f but expected %d\n", s9.f1, 1);
7215         }
7216         if (s9.f2 != 2) {
7217                 fprintf(stderr, "mono_return_double9 s9.f2: got %f but expected %d\n", s9.f2, 2);
7218         }
7219         if (s9.f3 != 3) {
7220                 fprintf(stderr, "mono_return_double9 s9.f3: got %f but expected %d\n", s9.f3, 3);
7221         }
7222         if (s9.f4 != 4) {
7223                 fprintf(stderr, "mono_return_double9 s9.f4: got %f but expected %d\n", s9.f4, 4);
7224         }
7225         if (s9.f5 != 5) {
7226                 fprintf(stderr, "mono_return_double9 s9.f5: got %f but expected %d\n", s9.f5, 5);
7227         }
7228         if (s9.f6 != 6) {
7229                 fprintf(stderr, "mono_return_double9 s9.f6: got %f but expected %d\n", s9.f6, 6);
7230         }
7231         if (s9.f7 != 7) {
7232                 fprintf(stderr, "mono_return_double9 s9.f7: got %f but expected %d\n", s9.f7, 7);
7233         }
7234         if (s9.f8 != 8) {
7235                 fprintf(stderr, "mono_return_double9 s9.f8: got %f but expected %d\n", s9.f8, 8);
7236         }
7237         if (s9.f9 != 9) {
7238                 fprintf(stderr, "mono_return_double9 s9.f9: got %f but expected %d\n", s9.f9, 9);
7239         }
7240         s9.f1+=addend; s9.f2+=addend; s9.f3+=addend; s9.f4+=addend; s9.f5+=addend; s9.f6+=addend; s9.f7+=addend; s9.f8+=addend; s9.f9+=addend; 
7241         return s9;
7242 }
7243
7244 typedef struct {
7245         struct {
7246                 double f1;
7247         } nested1;
7248         struct {
7249                 double f2;
7250         } nested2;
7251 } double2_nested;
7252
7253 LIBTEST_API double2_nested STDCALL
7254 mono_return_double2_nested (double2_nested sn2, int addend) {
7255         if (sn2.nested1.f1 != 1) {
7256                 fprintf(stderr, "mono_return_double2_nested sn2.nested1.f1: got %f but expected %d\n", sn2.nested1.f1, 1);
7257         }
7258         if (sn2.nested2.f2 != 2) {
7259                 fprintf(stderr, "mono_return_double2_nested sn2.nested2.f2: got %f but expected %d\n", sn2.nested2.f2, 2);
7260         }
7261         sn2.nested1.f1+=addend; sn2.nested2.f2+=addend; 
7262         return sn2;
7263 }
7264
7265
7266
7267 typedef struct {
7268         double f1[4];
7269 } double_array4;
7270
7271 LIBTEST_API double_array4 STDCALL
7272 mono_return_double_array4 (double_array4 sa4, int addend) {
7273         if (sa4.f1[0] != 1) {
7274                 fprintf(stderr, "mono_return_double_array4 sa4.f1[0]: got %f but expected %d\n", sa4.f1[0], 1);
7275         }
7276         if (sa4.f1[1] != 2) {
7277                 fprintf(stderr, "mono_return_double_array4 sa4.f1[1]: got %f but expected %d\n", sa4.f1[1], 2);
7278         }
7279         if (sa4.f1[2] != 3) {
7280                 fprintf(stderr, "mono_return_double_array4 sa4.f1[2]: got %f but expected %d\n", sa4.f1[2], 3);
7281         }
7282         if (sa4.f1[3] != 4) {
7283                 fprintf(stderr, "mono_return_double_array4 sa4.f1[3]: got %f but expected %d\n", sa4.f1[3], 4);
7284         }
7285         sa4.f1[0]+=addend; sa4.f1[1]+=addend; sa4.f1[2]+=addend; sa4.f1[3]+=addend; 
7286         return sa4;
7287 }
7288
7289 typedef struct {
7290         int array [3];
7291 } FixedArrayStruct;
7292
7293 LIBTEST_API int STDCALL
7294 mono_test_marshal_fixed_array (FixedArrayStruct s)
7295 {
7296         return s.array [0] + s.array [1] + s.array [2];
7297 }
7298
7299 typedef struct {
7300         char array [16];
7301         char c;
7302 } FixedBufferChar;
7303
7304 LIBTEST_API int STDCALL
7305 mono_test_marshal_fixed_buffer_char (FixedBufferChar *s)
7306 {
7307         if (!(s->array [0] == 'A' && s->array [1] == 'B' && s->array [2] == 'C' && s->c == 'D'))
7308                 return 1;
7309         s->array [0] = 'E';
7310         s->array [1] = 'F';
7311         s->c = 'G';
7312         return 0;
7313 }
7314
7315 typedef struct {
7316         short array [16];
7317         short c;
7318 } FixedBufferUnicode;
7319
7320 LIBTEST_API int STDCALL
7321 mono_test_marshal_fixed_buffer_unicode (FixedBufferUnicode *s)
7322 {
7323         if (!(s->array [0] == 'A' && s->array [1] == 'B' && s->array [2] == 'C' && s->c == 'D'))
7324                 return 1;
7325         s->array [0] = 'E';
7326         s->array [1] = 'F';
7327         s->c = 'G';
7328         return 0;
7329 }
7330
7331 const int NSTRINGS = 6;
7332 //test strings
7333 const char  *utf8Strings[] = {  
7334                                 "Managed",
7335                                  "Sîne klâwen durh die wolken sint geslagen" ,
7336                                  "काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम्",
7337                                  "我能吞下玻璃而不伤身体",
7338                                  "ღმერთსი შემვედრე,შემვედრე, ნუთუ კვლა დამხსნას შემვედრე,სოფლისა შემვედრე, შემვედრე,შემვედრე,შემვედრე,შრომასა, ცეცხლს, წყალსა და მიწასა, ჰაერთა თანა მრომასა; მომცნეს ფრთენი და აღვფრინდე, მივჰხვდე მას ჩემსა ნდომასა, დღისით და ღამით ვჰხედვიდე მზისა ელვათა კრთომაასაშემვედრე,შემვედრე,",
7339                                  "Τη γλώσσα μου έδωσαν ελληνική",
7340 "\0"
7341 };
7342
7343 LIBTEST_API char *
7344 build_return_string(const char* pReturn)
7345 {
7346         char *ret = 0;
7347         if (pReturn == 0 || *pReturn == 0)
7348                 return ret;
7349
7350         size_t strLength = strlen(pReturn);
7351         ret = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7352         memcpy(ret, pReturn, strLength);
7353         ret [strLength] = '\0';
7354         return ret;
7355 }
7356
7357 LIBTEST_API char *
7358 StringParameterInOut(/*[In,Out]*/ char *s, int index)
7359 {
7360         // return a copy
7361         return build_return_string(s);
7362 }
7363
7364 LIBTEST_API void
7365 StringParameterRefOut(/*out*/ char **s, int index)
7366 {
7367         char *pszTextutf8 = (char*)utf8Strings[index];
7368         size_t strLength = strlen(pszTextutf8);
7369         *s = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7370         memcpy(*s, pszTextutf8, strLength);
7371         (*s)[strLength] = '\0';
7372 }
7373
7374 LIBTEST_API void
7375 StringParameterRef(/*ref*/ char **s, int index)
7376 {
7377     char *pszTextutf8 = (char*)utf8Strings[index];
7378     size_t strLength = strlen(pszTextutf8);
7379     // do byte by byte validation of in string
7380     size_t szLen = strlen(*s);
7381     for (size_t i = 0; i < szLen; i++)
7382     {
7383         if ((*s)[i] != pszTextutf8[i])
7384         {
7385             printf("[in] managed string do not match native string\n");
7386             abort ();
7387         }
7388     }
7389
7390     if (*s)
7391     {
7392        marshal_free (*s);
7393     }
7394     // overwrite the orginal 
7395     *s = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7396     memcpy(*s, pszTextutf8, strLength);
7397     (*s)[strLength] = '\0';
7398 }
7399
7400 LIBTEST_API void
7401 StringBuilderParameterInOut(/*[In,Out] StringBuilder*/ char *s, int index)
7402 {
7403     // if string.empty 
7404     if (s == 0 || *s == 0)
7405         return;
7406
7407     char *pszTextutf8 = (char*)utf8Strings[index];
7408
7409     // do byte by byte validation of in string
7410     size_t szLen = strlen(s);
7411     for (size_t i = 0; i < szLen; i++) 
7412     {
7413         if (s[i] != pszTextutf8[i])
7414         {
7415             printf("[in] managed string do not match native string\n");
7416             abort ();
7417         }
7418     }  
7419
7420     // modify the string inplace 
7421     size_t outLen = strlen(pszTextutf8);
7422     for (size_t i = 0; i < outLen; i++) {
7423         s[i] = pszTextutf8[i];
7424     }
7425     s[outLen] = '\0';
7426 }
7427
7428 //out string builder
7429 LIBTEST_API void
7430 StringBuilderParameterOut(/*[Out] StringBuilder*/ char *s, int index)
7431 {
7432     char *pszTextutf8 = (char*)utf8Strings[index];
7433
7434     printf ("SBPO: Receiving %s\n", s);
7435     // modify the string inplace 
7436     size_t outLen = strlen(pszTextutf8);
7437     for (size_t i = 0; i < outLen; i++) {
7438         s[i] = pszTextutf8[i];
7439     }
7440     s[outLen] = '\0';
7441 }
7442
7443 LIBTEST_API char *
7444 StringParameterOut(/*[Out]*/ char *s, int index)
7445 {
7446     // return a copy
7447     return build_return_string(s);
7448 }
7449
7450 // Utf8 field
7451 typedef struct FieldWithUtf8
7452 {
7453     char *pFirst;
7454     int index;
7455 }FieldWithUtf8;
7456
7457 //utf8 struct field
7458 LIBTEST_API void
7459 TestStructWithUtf8Field(struct FieldWithUtf8 fieldStruct)
7460 {
7461     char *pszManagedutf8 = fieldStruct.pFirst;
7462     int stringIndex = fieldStruct.index;
7463     char *pszNative = 0;
7464     size_t outLen = 0;
7465
7466     if (pszManagedutf8 == 0 || *pszManagedutf8 == 0)
7467         return;
7468
7469     pszNative = (char*)utf8Strings[stringIndex];
7470
7471     outLen = strlen(pszNative);
7472     // do byte by byte comparision
7473     for (size_t i = 0; i < outLen; i++) 
7474     {
7475         if (pszNative[i] != pszManagedutf8[i]) 
7476         {
7477             printf("Native and managed string do not match.\n");
7478             abort ();
7479         }
7480     }
7481 }
7482
7483 typedef void (* Callback2)(char *text, int index);
7484
7485 LIBTEST_API void
7486 Utf8DelegateAsParameter(Callback2 managedCallback)
7487 {
7488     for (int i = 0; i < NSTRINGS; ++i) 
7489     {
7490         char *pszNative = 0;
7491         pszNative = (char*)utf8Strings[i];
7492         managedCallback(pszNative, i);
7493     }
7494 }
7495
7496
7497 LIBTEST_API char*
7498 StringBuilderParameterReturn(int index)
7499 {
7500     char *pszTextutf8 = (char*)utf8Strings[index];
7501     size_t strLength = strlen(pszTextutf8);
7502     char * ret = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7503     memcpy(ret, pszTextutf8, strLength);
7504     ret[strLength] = '\0';
7505
7506     return  ret;
7507 }
7508
7509 LIBTEST_API int STDCALL
7510 mono_test_marshal_pointer_array (int *arr[])
7511 {
7512         int i;
7513
7514         for (i = 0; i < 10; ++i) {
7515                 if (*arr [i] != -1)
7516                         return 1;
7517         }
7518         return 0;
7519 }
7520
7521 #ifndef WIN32
7522
7523 typedef void (*NativeToManagedExceptionRethrowFunc) (void);
7524
7525 void *mono_test_native_to_managed_exception_rethrow_thread (void *arg)
7526 {
7527         NativeToManagedExceptionRethrowFunc func = (NativeToManagedExceptionRethrowFunc) arg;
7528         func ();
7529         return NULL;
7530 }
7531
7532 LIBTEST_API void STDCALL
7533 mono_test_native_to_managed_exception_rethrow (NativeToManagedExceptionRethrowFunc func)
7534 {
7535         pthread_t t;
7536         pthread_create (&t, NULL, mono_test_native_to_managed_exception_rethrow_thread, func);
7537         pthread_join (t, NULL);
7538 }
7539 #endif