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