Merge pull request #4998 from kumpera/fix_56684
[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 /*
3585  * mono_method_get_unmanaged_thunk tests
3586  */
3587
3588 #if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__) || defined(__OpenBSD__)) || (defined(__ppc__) && defined(__APPLE__)))
3589 #define ALIGN(size) __attribute__ ((__aligned__(size)))
3590 #else
3591 #define ALIGN(size)
3592 #endif
3593
3594
3595 /* thunks.cs:TestStruct */
3596 typedef struct _TestStruct {
3597         int A;
3598         double B;
3599 } TestStruct;
3600
3601 /* Searches for mono symbols in all loaded modules */
3602 static gpointer
3603 lookup_mono_symbol (const char *symbol_name)
3604 {
3605         gpointer symbol;
3606         if (g_module_symbol (g_module_open (NULL, G_MODULE_BIND_LAZY), symbol_name, &symbol))
3607                 return symbol;
3608         else
3609                 return NULL;
3610 }
3611
3612 LIBTEST_API gpointer STDCALL
3613 mono_test_marshal_lookup_symbol (const char *symbol_name)
3614 {
3615         return lookup_mono_symbol (symbol_name);
3616 }
3617
3618 #define MONO_BEGIN_EFRAME { void *__dummy; void *__region_cookie = mono_threads_enter_gc_unsafe_region ? mono_threads_enter_gc_unsafe_region (&__dummy) : NULL;
3619 #define MONO_END_EFRAME if (mono_threads_exit_gc_unsafe_region) mono_threads_exit_gc_unsafe_region (__region_cookie, &__dummy); }
3620
3621 /**
3622  * test_method_thunk:
3623  *
3624  * @test_id: the test number
3625  * @test_method_handle: MonoMethod* of the C# test method
3626  * @create_object_method_handle: MonoMethod* of thunks.cs:Test.CreateObject
3627  */
3628 LIBTEST_API int STDCALL  
3629 test_method_thunk (int test_id, gpointer test_method_handle, gpointer create_object_method_handle)
3630 {
3631         int ret = 0;
3632
3633         gpointer (*mono_method_get_unmanaged_thunk)(gpointer)
3634                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_method_get_unmanaged_thunk");
3635
3636         gpointer (*mono_string_new_wrapper)(const char *)
3637                 = (gpointer (*)(const char *))lookup_mono_symbol ("mono_string_new_wrapper");
3638
3639         char *(*mono_string_to_utf8)(gpointer)
3640                 = (char *(*)(gpointer))lookup_mono_symbol ("mono_string_to_utf8");
3641
3642         gpointer (*mono_object_unbox)(gpointer)
3643                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_object_unbox");
3644
3645         gpointer (*mono_threads_enter_gc_unsafe_region) (gpointer)
3646                 = (gpointer (*)(gpointer))lookup_mono_symbol ("mono_threads_enter_gc_unsafe_region");
3647
3648         void (*mono_threads_exit_gc_unsafe_region) (gpointer, gpointer)
3649                 = (void (*)(gpointer, gpointer))lookup_mono_symbol ("mono_threads_exit_gc_unsafe_region");
3650
3651         
3652
3653         gpointer test_method, ex = NULL;
3654         gpointer (STDCALL *CreateObject)(gpointer*);
3655
3656         MONO_BEGIN_EFRAME;
3657
3658         if (!mono_method_get_unmanaged_thunk) {
3659                 ret = 1;
3660                 goto done;
3661         }
3662
3663         test_method =  mono_method_get_unmanaged_thunk (test_method_handle);
3664         if (!test_method) {
3665                 ret = 2;
3666                 goto done;
3667         }
3668
3669         CreateObject = (gpointer (STDCALL *)(gpointer *))mono_method_get_unmanaged_thunk (create_object_method_handle);
3670         if (!CreateObject) {
3671                 ret = 3;
3672                 goto done;
3673         }
3674         
3675
3676         switch (test_id) {
3677
3678         case 0: {
3679                 /* thunks.cs:Test.Test0 */
3680                 void (STDCALL *F)(gpointer *) = (void (STDCALL *)(gpointer *))test_method;
3681                 F (&ex);
3682                 break;
3683         }
3684
3685         case 1: {
3686                 /* thunks.cs:Test.Test1 */
3687                 int (STDCALL *F)(gpointer *) = (int (STDCALL *)(gpointer *))test_method;
3688                 if (F (&ex) != 42) {
3689                         ret = 4;
3690                         goto done;
3691                 }
3692                 break;
3693         }
3694
3695         case 2: {
3696                 /* thunks.cs:Test.Test2 */
3697                 gpointer (STDCALL *F)(gpointer, gpointer*) = (gpointer (STDCALL *)(gpointer, gpointer *))test_method;
3698                 gpointer str = mono_string_new_wrapper ("foo");
3699                 if (str != F (str, &ex)) {
3700                         ret = 4;
3701                         goto done;
3702                 }
3703                 break;
3704         }
3705
3706         case 3: {
3707                 /* thunks.cs:Test.Test3 */
3708                 gpointer (STDCALL *F)(gpointer, gpointer, gpointer*);
3709                 gpointer obj;
3710                 gpointer str;
3711
3712                 F = (gpointer (STDCALL *)(gpointer, gpointer, gpointer *))test_method;
3713                 obj = CreateObject (&ex);
3714                 str = mono_string_new_wrapper ("bar");
3715
3716                 if (str != F (obj, str, &ex)) {
3717                         ret = 4;
3718                         goto done;
3719                 }
3720                 break;
3721         }
3722
3723         case 4: {
3724                 /* thunks.cs:Test.Test4 */
3725                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3726                 gpointer obj;
3727                 gpointer str;
3728
3729                 F = (int (STDCALL *)(gpointer, gpointer, int, gpointer *))test_method;
3730                 obj = CreateObject (&ex);
3731                 str = mono_string_new_wrapper ("bar");
3732
3733                 if (42 != F (obj, str, 42, &ex)) {
3734                         ret = 4;
3735                         goto done;
3736                 }
3737
3738                 break;
3739         }
3740
3741         case 5: {
3742                 /* thunks.cs:Test.Test5 */
3743                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3744                 gpointer obj;
3745                 gpointer str;
3746
3747                 F = (int (STDCALL *)(gpointer, gpointer, int, gpointer *))test_method;
3748                 obj = CreateObject (&ex);
3749                 str = mono_string_new_wrapper ("bar");
3750
3751                 F (obj, str, 42, &ex);
3752                 if (!ex) {
3753                         ret = 4;
3754                         goto done;
3755                 }
3756
3757                 break;
3758         }
3759
3760         case 6: {
3761                 /* thunks.cs:Test.Test6 */
3762                 int (STDCALL *F)(gpointer, guint8, gint16, gint32, gint64, float, double,
3763                                  gpointer, gpointer*);
3764                 gpointer obj;
3765                 gpointer str = mono_string_new_wrapper ("Test6");
3766                 int res;
3767
3768                 F = (int (STDCALL *)(gpointer, guint8, gint16, gint32, gint64, float, double, gpointer, gpointer *))test_method;
3769                 obj = CreateObject (&ex);
3770
3771                 res = F (obj, 254, 32700, -245378, 6789600, 3.1415, 3.1415, str, &ex);
3772                 if (ex) {
3773                         ret = 4;
3774                         goto done;
3775                 }
3776
3777                 if (!res) {
3778                         ret = 5;
3779                         goto done;
3780                 }
3781
3782                 break;
3783         }
3784
3785         case 7: {
3786                 /* thunks.cs:Test.Test7 */
3787                 gint64 (STDCALL *F)(gpointer*) = (gint64 (STDCALL *)(gpointer *))test_method;
3788                 if (F (&ex) != G_MAXINT64) {
3789                         ret = 4;
3790                         goto done;
3791                 }
3792                 break;
3793         }
3794
3795         case 8: {
3796                 /* thunks.cs:Test.Test8 */
3797                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3798                                  gpointer*, gpointer*);
3799
3800                 guint8 a1;
3801                 gint16 a2;
3802                 gint32 a3;
3803                 gint64 a4;
3804                 float a5;
3805                 double a6;
3806                 gpointer a7;
3807
3808                 F = (void (STDCALL *)(guint8 *, gint16 *, gint32 *, gint64 *, float *, double *,
3809                         gpointer *, gpointer *))test_method;
3810
3811                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3812                 if (ex) {
3813                         ret = 4;
3814                         goto done;
3815                 }
3816
3817                 if (!(a1 == 254 &&
3818                       a2 == 32700 &&
3819                       a3 == -245378 &&
3820                       a4 == 6789600 &&
3821                       (fabs (a5 - 3.1415) < 0.001) &&
3822                       (fabs (a6 - 3.1415) < 0.001) &&
3823                       strcmp (mono_string_to_utf8 (a7), "Test8") == 0)){
3824                                 ret = 5;
3825                                 goto done;
3826                         }
3827
3828                 break;
3829         }
3830
3831         case 9: {
3832                 /* thunks.cs:Test.Test9 */
3833                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3834                         gpointer*, gpointer*);
3835
3836                 guint8 a1;
3837                 gint16 a2;
3838                 gint32 a3;
3839                 gint64 a4;
3840                 float a5;
3841                 double a6;
3842                 gpointer a7;
3843
3844                 F = (void (STDCALL *)(guint8 *, gint16 *, gint32 *, gint64 *, float *, double *,
3845                         gpointer *, gpointer *))test_method;
3846
3847                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3848                 if (!ex) {
3849                         ret = 4;
3850                         goto done;
3851                 }
3852
3853                 break;
3854         }
3855
3856         case 10: {
3857                 /* thunks.cs:Test.Test10 */
3858                 void (STDCALL *F)(gpointer*, gpointer*);
3859
3860                 gpointer obj1, obj2;
3861
3862                 obj1 = obj2 = CreateObject (&ex);
3863                 if (ex) {
3864                         ret = 4;
3865                         goto done;
3866                 }
3867
3868                 F = (void (STDCALL *)(gpointer *, gpointer *))test_method;
3869
3870                 F (&obj1, &ex);
3871                 if (ex) {
3872                         ret = 5;
3873                         goto done;
3874                 }
3875
3876                 if (obj1 == obj2) {
3877                         ret = 6;
3878                         goto done;
3879                 }
3880
3881                 break;
3882         }
3883
3884         case 100: {
3885                 /* thunks.cs:TestStruct.Test0 */
3886                 int (STDCALL *F)(gpointer*, gpointer*);
3887
3888                 gpointer obj;
3889                 TestStruct *a1;
3890                 int res;
3891
3892                 obj = CreateObject (&ex);
3893                 if (ex) {
3894                         ret = 4;
3895                         goto done;
3896                 }
3897
3898                 if (!obj) {
3899                         ret = 5;
3900                         goto done;
3901                 }
3902
3903                 a1 = (TestStruct *)mono_object_unbox (obj);
3904                 if (!a1) {
3905                         ret = 6;
3906                         goto done;
3907                 }
3908
3909                 a1->A = 42;
3910                 a1->B = 3.1415;
3911
3912                 F = (int (STDCALL *)(gpointer *, gpointer *))test_method;
3913
3914                 res = F ((gpointer *)obj, &ex);
3915                 if (ex) {
3916                         ret = 7;
3917                         goto done;
3918                 }
3919
3920                 if (!res) {
3921                         ret = 8;
3922                         goto done;
3923                 }
3924
3925                 /* check whether the call was really by value */
3926                 if (a1->A != 42 || a1->B != 3.1415) {
3927                         ret = 9;
3928                         goto done;
3929                 }
3930
3931                 break;
3932         }
3933
3934         case 101: {
3935                 /* thunks.cs:TestStruct.Test1 */
3936                 void (STDCALL *F)(gpointer, gpointer*);
3937
3938                 TestStruct *a1;
3939                 gpointer obj;
3940
3941                 obj = CreateObject (&ex);
3942                 if (ex) {
3943                         ret = 4;
3944                         goto done;
3945                 }
3946
3947                 if (!obj) {
3948                         ret = 5;
3949                         goto done;
3950                 }
3951
3952                 a1 = (TestStruct *)mono_object_unbox (obj);
3953                 if (!a1) {
3954                         ret = 6;
3955                         goto done;
3956                 }
3957
3958                 F = (void (STDCALL *)(gpointer, gpointer *))test_method;
3959
3960                 F (obj, &ex);
3961                 if (ex) {
3962                         ret = 7;
3963                         goto done;
3964                 }
3965
3966                 if (a1->A != 42) {
3967                         ret = 8;
3968                         goto done;
3969                 }
3970
3971                 if (!(fabs (a1->B - 3.1415) < 0.001)) {
3972                         ret = 9;
3973                         goto done;
3974                 }
3975
3976                 break;
3977         }
3978
3979         case 102: {
3980                 /* thunks.cs:TestStruct.Test2 */
3981                 gpointer (STDCALL *F)(gpointer*);
3982
3983                 TestStruct *a1;
3984                 gpointer obj;
3985
3986                 F = (gpointer (STDCALL *)(gpointer *))test_method;
3987
3988                 obj = F (&ex);
3989                 if (ex) {
3990                         ret = 4;
3991                         goto done;
3992                 }
3993
3994                 if (!obj) {
3995                         ret = 5;
3996                         goto done;
3997                 }
3998
3999                 a1 = (TestStruct *)mono_object_unbox (obj);
4000
4001                 if (a1->A != 42) {
4002                         ret = 5;
4003                         goto done;
4004                 }
4005
4006                 if (!(fabs (a1->B - 3.1415) < 0.001)) {
4007                         ret = 6;
4008                         goto done;
4009                 }
4010
4011                 break;
4012         }
4013
4014         case 103: {
4015                 /* thunks.cs:TestStruct.Test3 */
4016                 void (STDCALL *F)(gpointer, gpointer*);
4017
4018                 TestStruct *a1;
4019                 gpointer obj;
4020
4021                 obj = CreateObject (&ex);
4022                 if (ex) {
4023                         ret = 4;
4024                         goto done;
4025                 }
4026
4027                 if (!obj) {
4028                         ret = 5;
4029                         goto done;
4030                 }
4031                 
4032                 a1 = (TestStruct *)mono_object_unbox (obj);
4033
4034                 if (!a1) {
4035                         ret = 6;
4036                         goto done;
4037                 }
4038
4039                 a1->A = 42;
4040                 a1->B = 3.1415;
4041
4042                 F = (void (STDCALL *)(gpointer, gpointer *))test_method;
4043
4044                 F (obj, &ex);
4045                 if (ex) {
4046                         ret = 4;
4047                         goto done;
4048                 }
4049
4050                 if (a1->A != 1) {
4051                         ret = 5;
4052                         goto done;
4053                 }
4054
4055                 if (a1->B != 17) {
4056                         ret = 6;
4057                         goto done;
4058                 }
4059
4060                 break;
4061         }
4062
4063         default:
4064                 ret = 9;
4065
4066         }
4067 done:
4068         MONO_END_EFRAME;
4069
4070         return ret;
4071 }
4072
4073 typedef struct 
4074 {
4075         char a;
4076 } winx64_struct1;
4077
4078 LIBTEST_API int STDCALL  
4079 mono_test_Winx64_struct1_in (winx64_struct1 var)
4080 {
4081         if (var.a != 123)
4082                 return 1;
4083         return 0;
4084 }
4085
4086 typedef struct
4087 {
4088         char a;
4089         char b;
4090 } winx64_struct2;
4091
4092 LIBTEST_API int STDCALL  
4093 mono_test_Winx64_struct2_in (winx64_struct2 var)
4094 {
4095         if (var.a != 4)
4096                 return 1;
4097         if (var.b != 5)
4098                 return 2;
4099         return 0;
4100 }
4101
4102
4103 typedef struct
4104 {
4105         char a;
4106         char b;
4107         short c;
4108 } winx64_struct3;
4109
4110 LIBTEST_API int STDCALL  
4111 mono_test_Winx64_struct3_in (winx64_struct3 var)
4112 {
4113         if (var.a != 4)
4114                 return 1;
4115         if (var.b != 5)
4116                 return 2;
4117         if (var.c != 0x1234)
4118                 return 3;
4119         return 0;
4120 }
4121
4122 typedef struct
4123 {
4124         char a;
4125         char b;
4126         short c;
4127         unsigned int d;
4128 } winx64_struct4;
4129
4130 LIBTEST_API int STDCALL  
4131 mono_test_Winx64_struct4_in (winx64_struct4 var)
4132 {
4133         if (var.a != 4)
4134                 return 1;
4135         if (var.b != 5)
4136                 return 2;
4137         if (var.c != 0x1234)
4138                 return 3;
4139         if (var.d != 0x87654321)
4140                 return 4;
4141         return 0;
4142 }
4143
4144 typedef struct
4145 {
4146         char a;
4147         char b;
4148         char c;
4149 } winx64_struct5;
4150
4151 LIBTEST_API int STDCALL  
4152 mono_test_Winx64_struct5_in (winx64_struct5 var)
4153 {
4154         if (var.a != 4)
4155                 return 1;
4156         if (var.b != 5)
4157                 return 2;
4158         if (var.c != 6)
4159                 return 3;
4160         return 0;
4161 }
4162
4163 typedef struct
4164 {
4165         winx64_struct1 a;
4166         short b;
4167         char c;
4168 } winx64_struct6;
4169
4170 LIBTEST_API int STDCALL  
4171 mono_test_Winx64_struct6_in (winx64_struct6 var)
4172 {
4173         if (var.a.a != 4)
4174                 return 1;
4175         if (var.b != 5)
4176                 return 2;
4177         if (var.c != 6)
4178                 return 3;
4179         return 0;
4180 }
4181
4182 LIBTEST_API int STDCALL  
4183 mono_test_Winx64_structs_in1 (winx64_struct1 var1,
4184                          winx64_struct2 var2,
4185                          winx64_struct3 var3,
4186                          winx64_struct4 var4)
4187 {
4188         if (var1.a != 123)
4189                 return 1;
4190         
4191         if (var2.a != 4)
4192                 return 2;
4193         if (var2.b != 5)
4194                 return 3;
4195         
4196         if (var3.a != 4)
4197                 return 4;
4198         if (var3.b != 5)
4199                 return 2;
4200         if (var3.c != 0x1234)
4201                 return 5;
4202         
4203         if (var4.a != 4)
4204                 return 6;
4205         if (var4.b != 5)
4206                 return 7;
4207         if (var4.c != 0x1234)
4208                 return 8;
4209         if (var4.d != 0x87654321)
4210                 return 9;
4211         return 0;
4212 }
4213
4214 LIBTEST_API int STDCALL  
4215 mono_test_Winx64_structs_in2 (winx64_struct1 var1,
4216                          winx64_struct1 var2,
4217                          winx64_struct1 var3,
4218                          winx64_struct1 var4,
4219                          winx64_struct1 var5)
4220 {
4221         if (var1.a != 1)
4222                 return 1;
4223         if (var2.a != 2)
4224                 return 2;
4225         if (var3.a != 3)
4226                 return 3;
4227         if (var4.a != 4)
4228                 return 4;
4229         if (var5.a != 5)
4230                 return 5;
4231         
4232         return 0;
4233 }
4234
4235 LIBTEST_API int STDCALL  
4236 mono_test_Winx64_structs_in3 (winx64_struct1 var1,
4237                          winx64_struct5 var2,
4238                          winx64_struct1 var3,
4239                          winx64_struct5 var4,
4240                          winx64_struct1 var5,
4241                          winx64_struct5 var6)
4242 {
4243         if (var1.a != 1)
4244                 return 1;
4245         
4246         if (var2.a != 2)
4247                 return 2;
4248         if (var2.b != 3)
4249                 return 2;
4250         if (var2.c != 4)
4251                 return 4;
4252         
4253         if (var3.a != 5)
4254                 return 5;
4255         
4256         if (var4.a != 6)
4257                 return 6;
4258         if (var4.b != 7)
4259                 return 7;
4260         if (var4.c != 8)
4261                 return 8;
4262         
4263         if (var5.a != 9)
4264                 return 9;
4265
4266         if (var6.a != 10)
4267                 return 10;
4268         if (var6.b != 11)
4269                 return 11;
4270         if (var6.c != 12)
4271                 return 12;
4272         
4273         return 0;
4274 }
4275
4276 LIBTEST_API winx64_struct1 STDCALL  
4277 mono_test_Winx64_struct1_ret (void)
4278 {
4279         winx64_struct1 ret;
4280         ret.a = 123;
4281         return ret;
4282 }
4283
4284 LIBTEST_API winx64_struct2 STDCALL  
4285 mono_test_Winx64_struct2_ret (void)
4286 {
4287         winx64_struct2 ret;
4288         ret.a = 4;
4289         ret.b = 5;
4290         return ret;
4291 }
4292
4293 LIBTEST_API winx64_struct3 STDCALL  
4294 mono_test_Winx64_struct3_ret (void)
4295 {
4296         winx64_struct3 ret;
4297         ret.a = 4;
4298         ret.b = 5;
4299         ret.c = 0x1234;
4300         return ret;
4301 }
4302
4303 LIBTEST_API winx64_struct4 STDCALL  
4304 mono_test_Winx64_struct4_ret (void)
4305 {
4306         winx64_struct4 ret;
4307         ret.a = 4;
4308         ret.b = 5;
4309         ret.c = 0x1234;
4310         ret.d = 0x87654321;
4311         return ret;
4312 }
4313
4314 LIBTEST_API winx64_struct5 STDCALL  
4315 mono_test_Winx64_struct5_ret (void)
4316 {
4317         winx64_struct5 ret;
4318         ret.a = 4;
4319         ret.b = 5;
4320         ret.c = 6;
4321         return ret;
4322 }
4323
4324 LIBTEST_API winx64_struct1 STDCALL  
4325 mono_test_Winx64_struct1_ret_5_args (char a, char b, char c, char d, char e)
4326 {
4327         winx64_struct1 ret;
4328         ret.a = a + b + c + d + e;
4329         return ret;
4330 }
4331
4332 LIBTEST_API winx64_struct5 STDCALL
4333 mono_test_Winx64_struct5_ret6_args (char a, char b, char c, char d, char e)
4334 {
4335         winx64_struct5 ret;
4336         ret.a = a + b;
4337         ret.b = c + d;
4338         ret.c = e;
4339         return ret;
4340 }
4341
4342 typedef struct
4343 {
4344         float a;
4345         float b;
4346 } winx64_floatStruct;
4347
4348 LIBTEST_API int STDCALL  
4349 mono_test_Winx64_floatStruct (winx64_floatStruct a)
4350 {
4351         if (a.a > 5.6 || a.a < 5.4)
4352                 return 1;
4353
4354         if (a.b > 9.6 || a.b < 9.4)
4355                 return 2;
4356         
4357         return 0;
4358 }
4359
4360 typedef struct
4361 {
4362         double a;
4363 } winx64_doubleStruct;
4364
4365 LIBTEST_API int STDCALL  
4366 mono_test_Winx64_doubleStruct (winx64_doubleStruct a)
4367 {
4368         if (a.a > 5.6 || a.a < 5.4)
4369                 return 1;
4370         
4371         return 0;
4372 }
4373
4374 typedef int (STDCALL *managed_struct1_delegate) (winx64_struct1 a);
4375
4376 LIBTEST_API int STDCALL 
4377 mono_test_managed_Winx64_struct1_in(managed_struct1_delegate func)
4378 {
4379         winx64_struct1 val;
4380         val.a = 5;
4381         return func (val);
4382 }
4383
4384 typedef int (STDCALL *managed_struct5_delegate) (winx64_struct5 a);
4385
4386 LIBTEST_API int STDCALL 
4387 mono_test_managed_Winx64_struct5_in(managed_struct5_delegate func)
4388 {
4389         winx64_struct5 val;
4390         val.a = 5;
4391         val.b = 0x10;
4392         val.c = 0x99;
4393         return func (val);
4394 }
4395
4396 typedef int (STDCALL *managed_struct1_struct5_delegate) (winx64_struct1 a, winx64_struct5 b,
4397                                                          winx64_struct1 c, winx64_struct5 d,
4398                                                          winx64_struct1 e, winx64_struct5 f);
4399
4400 LIBTEST_API int STDCALL 
4401 mono_test_managed_Winx64_struct1_struct5_in(managed_struct1_struct5_delegate func)
4402 {
4403         winx64_struct1 a, c, e;
4404         winx64_struct5 b, d, f;
4405         a.a = 1;
4406         b.a = 2; b.b = 3; b.c = 4;
4407         c.a = 5;
4408         d.a = 6; d.b = 7; d.c = 8;
4409         e.a = 9;
4410         f.a = 10; f.b = 11; f.c = 12;
4411
4412         return func (a, b, c, d, e, f);
4413 }
4414
4415 typedef winx64_struct1 (STDCALL *managed_struct1_ret_delegate) (void);
4416
4417 LIBTEST_API int STDCALL 
4418 mono_test_Winx64_struct1_ret_managed (managed_struct1_ret_delegate func)
4419 {
4420         winx64_struct1 ret;
4421
4422         ret = func ();
4423
4424         if (ret.a != 0x45)
4425                 return 1;
4426         
4427         return 0;
4428 }
4429
4430 typedef winx64_struct5 (STDCALL *managed_struct5_ret_delegate) (void);
4431
4432 LIBTEST_API int STDCALL 
4433 mono_test_Winx64_struct5_ret_managed (managed_struct5_ret_delegate func)
4434 {
4435         winx64_struct5 ret;
4436
4437         ret = func ();
4438
4439         if (ret.a != 0x12)
4440                 return 1;
4441         if (ret.b != 0x34)
4442                 return 2;
4443         if (ret.c != 0x56)
4444                 return 3;
4445         
4446         return 0;
4447 }
4448
4449 LIBTEST_API int STDCALL 
4450 mono_test_marshal_bool_in (int arg, unsigned int expected, unsigned int bDefaultMarsh, unsigned int bBoolCustMarsh,
4451                            char bI1CustMarsh, unsigned char bU1CustMarsh, short bVBCustMarsh)
4452 {
4453         switch (arg) {
4454         case 1: 
4455                 if (bDefaultMarsh != expected)
4456                         return 1;
4457                 break;
4458         case 2: 
4459                 if (bBoolCustMarsh != expected)
4460                         return 2;
4461                 break;
4462         case 3: 
4463                 if (bI1CustMarsh != expected)
4464                         return 3;
4465                 break;
4466         case 4: 
4467                 if (bU1CustMarsh != expected)
4468                         return 4;
4469                 break;
4470         case 5: 
4471                 if (bVBCustMarsh != expected)
4472                         return 5;
4473                 break;
4474         default:
4475                 return 999;             
4476         }
4477         return 0;
4478 }
4479
4480 LIBTEST_API int STDCALL 
4481 mono_test_marshal_bool_out (int arg, unsigned int testVal, unsigned int* bDefaultMarsh, unsigned int* bBoolCustMarsh,
4482                            char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh)
4483 {
4484         switch (arg) {
4485         case 1: 
4486                 if (!bDefaultMarsh)
4487                         return 1;
4488                 *bDefaultMarsh = testVal;
4489                 break;  
4490         case 2: 
4491                 if (!bBoolCustMarsh)
4492                         return 2;
4493                 *bBoolCustMarsh = testVal;
4494                 break;  
4495         case 3: 
4496                 if (!bI1CustMarsh)
4497                         return 3;
4498                 *bI1CustMarsh = (char)testVal;
4499                 break;  
4500         case 4: 
4501                 if (!bU1CustMarsh)
4502                         return 4;
4503                 *bU1CustMarsh = (unsigned char)testVal;
4504                 break;  
4505         case 5: 
4506                 if (!bVBCustMarsh)
4507                         return 5;
4508                 *bVBCustMarsh = (unsigned short)testVal;
4509                 break;  
4510         default:
4511                 return 999;
4512         }
4513         return 0;
4514 }
4515
4516 LIBTEST_API int STDCALL 
4517 mono_test_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4518                             unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, 
4519                             unsigned short* bVBCustMarsh)
4520 {
4521         switch (arg) {
4522         case 1: 
4523                 if (!bDefaultMarsh)
4524                         return 1;
4525                 if (*bDefaultMarsh != expected)
4526                         return 2;
4527                 *bDefaultMarsh = testVal;
4528                 break;
4529         case 2: 
4530                 if (!bBoolCustMarsh)
4531                         return 3;
4532                 if (*bBoolCustMarsh != expected)
4533                         return 4;
4534                 *bBoolCustMarsh = testVal;
4535                 break;
4536         case 3: 
4537                 if (!bI1CustMarsh)
4538                         return 5;
4539                 if (*bI1CustMarsh != expected)
4540                         return 6;
4541                 *bI1CustMarsh = (char)testVal;
4542                 break;
4543         case 4: 
4544                 if (!bU1CustMarsh)
4545                         return 7;
4546                 if (*bU1CustMarsh != expected)
4547                         return 8;
4548                 *bU1CustMarsh = (unsigned char)testVal;
4549                 break;
4550         case 5: 
4551                 if (!bVBCustMarsh)
4552                         return 9;
4553                 if (*bVBCustMarsh != expected)
4554                         return 10;
4555                 *bVBCustMarsh = (unsigned short)testVal;
4556                 break;
4557         default:
4558                 return 999;             
4559         }
4560         return 0;
4561 }
4562
4563
4564 typedef int (STDCALL *MarshalBoolInDelegate) (int arg, unsigned int expected, unsigned int bDefaultMarsh,
4565         unsigned int bBoolCustMarsh, char bI1CustMarsh, unsigned char bU1CustMarsh, unsigned short bVBCustMarsh);
4566
4567 LIBTEST_API int STDCALL 
4568 mono_test_managed_marshal_bool_in (int arg, unsigned int expected, unsigned int testVal, MarshalBoolInDelegate pfcn)
4569 {
4570         if (!pfcn)
4571                 return 0x9900;
4572
4573         switch (arg) {
4574         case 1:
4575                 return pfcn (arg, expected, testVal, 0, 0, 0, 0);
4576         case 2:
4577                 return pfcn (arg, expected, 0, testVal,  0, 0, 0);
4578         case 3:
4579                 return pfcn (arg, expected, 0, 0, testVal, 0, 0);
4580         case 4:
4581                 return pfcn (arg, expected, 0, 0, 0, testVal, 0);
4582         case 5:
4583                 return pfcn (arg, expected, 0, 0, 0, 0, testVal);
4584         default:
4585                 return 0x9800;
4586         }
4587
4588         return 0;
4589 }
4590
4591 typedef int (STDCALL *MarshalBoolOutDelegate) (int arg, unsigned int expected, unsigned int* bDefaultMarsh,
4592         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4593
4594 LIBTEST_API int STDCALL 
4595 mono_test_managed_marshal_bool_out (int arg, unsigned int expected, unsigned int testVal, MarshalBoolOutDelegate pfcn)
4596 {
4597         int ret;
4598         unsigned int lDefaultMarsh, lBoolCustMarsh;
4599         char lI1CustMarsh = 0;
4600         unsigned char lU1CustMarsh = 0;
4601         unsigned short lVBCustMarsh = 0;
4602         lDefaultMarsh = lBoolCustMarsh = 0;
4603
4604         if (!pfcn)
4605                 return 0x9900;
4606
4607         switch (arg) {
4608         case 1: {
4609                 unsigned int ltVal = 0;
4610                 ret = pfcn (arg, testVal, &ltVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4611                 if (ret)
4612                         return 0x0100 + ret;
4613                 if (expected != ltVal)
4614                         return 0x0200;
4615                 break;
4616         }
4617         case 2: {
4618                 unsigned int ltVal = 0;
4619                 ret = pfcn (arg, testVal, &lDefaultMarsh, &ltVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4620                 if (ret)
4621                         return 0x0300 + ret;
4622                 if (expected != ltVal)
4623                         return 0x0400;
4624                 break;
4625         }
4626         case 3: {
4627                 char ltVal = 0;
4628                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &ltVal, &lU1CustMarsh, &lVBCustMarsh);
4629                 if (ret)
4630                         return 0x0500 + ret;
4631                 if (expected != ltVal)
4632                         return 0x0600;
4633                 break;
4634         }
4635         case 4: {
4636                 unsigned char ltVal = 0;
4637                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltVal, &lVBCustMarsh);
4638                 if (ret)
4639                         return 0x0700 + ret;
4640                 if (expected != ltVal)
4641                         return 0x0800;
4642                 break;
4643         }
4644         case 5: {
4645                 unsigned short ltVal = 0;
4646                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltVal);
4647                 if (ret)
4648                         return 0x0900 + ret;
4649                 if (expected != ltVal)
4650                         return 0x1000;
4651                 break;
4652         }
4653         default:
4654                 return 0x9800;
4655         }
4656
4657         return 0;
4658 }
4659
4660 typedef int (STDCALL *MarshalBoolRefDelegate) (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4661         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4662
4663 LIBTEST_API int STDCALL 
4664 mono_test_managed_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int outExpected,
4665                                     unsigned int outTestVal, MarshalBoolRefDelegate pfcn)
4666 {
4667         int ret;
4668         unsigned int lDefaultMarsh, lBoolCustMarsh;
4669         char lI1CustMarsh = 0;
4670         unsigned char lU1CustMarsh = 0;
4671         unsigned short lVBCustMarsh = 0;
4672         lDefaultMarsh = lBoolCustMarsh = 0;
4673
4674         if (!pfcn)
4675                 return 0x9900;
4676
4677         switch (arg) {
4678         case 1:
4679         {
4680                 unsigned int ltestVal = testVal;
4681                 ret = pfcn (arg, expected, outTestVal, &ltestVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4682                 if (ret)
4683                         return 0x0100 + ret;
4684                 if (outExpected != ltestVal)
4685                         return 0x0200;
4686                 break;
4687         }
4688         case 2:
4689         {
4690                 unsigned int ltestVal = testVal;
4691                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &ltestVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4692                 if (ret)
4693                         return 0x0300 + ret;
4694                 if (outExpected != ltestVal)
4695                         return 0x0400;
4696                 break;
4697         }
4698         case 3:
4699         {
4700                 char ltestVal = testVal;
4701                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &ltestVal, &lU1CustMarsh, &lVBCustMarsh);
4702                 if (ret)
4703                         return 0x0500 + ret;
4704                 if (outExpected != ltestVal)
4705                         return 0x0600;
4706                 break;
4707         }
4708         case 4:
4709         {
4710                 unsigned char ltestVal = testVal;
4711                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltestVal, &lVBCustMarsh);
4712                 if (ret)
4713                         return 0x0700 + ret;
4714                 if (outExpected != ltestVal)
4715                         return 0x0800;
4716                 break;
4717         }
4718         case 5:
4719         {
4720                 unsigned short ltestVal = testVal;
4721                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltestVal);
4722                 if (ret)
4723                         return 0x0900 + ret;
4724                 if (outExpected != ltestVal)
4725                         return 0x1000;
4726                 break;
4727         }
4728         default:
4729                 return 0x9800;
4730         }
4731
4732         return 0;
4733 }
4734
4735 #ifdef WIN32
4736
4737 LIBTEST_API int STDCALL 
4738 mono_test_marshal_safearray_out_1dim_vt_bstr_empty (SAFEARRAY** safearray)
4739 {
4740         /* Create an empty one-dimensional array of variants */
4741         SAFEARRAY *pSA;
4742         SAFEARRAYBOUND dimensions [1];
4743
4744         dimensions [0].lLbound = 0;
4745         dimensions [0].cElements = 0;
4746
4747         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4748         *safearray = pSA;
4749         return S_OK;
4750 }
4751
4752 LIBTEST_API int STDCALL 
4753 mono_test_marshal_safearray_out_1dim_vt_bstr (SAFEARRAY** safearray)
4754 {
4755         /* Create a one-dimensional array of 10 variants filled with "0" to "9" */
4756         SAFEARRAY *pSA;
4757         SAFEARRAYBOUND dimensions [1];
4758         long i;
4759         gchar buffer [20];
4760         HRESULT hr = S_OK;
4761         long indices [1];
4762
4763         dimensions [0].lLbound = 0;
4764         dimensions [0].cElements = 10;
4765
4766         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4767         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4768                 VARIANT vOut;
4769                 VariantInit (&vOut);
4770                 vOut.vt = VT_BSTR;
4771                 _ltoa (i,buffer,10);
4772                 vOut.bstrVal= marshal_bstr_alloc (buffer);
4773                 indices [0] = i;
4774                 if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4775                         VariantClear (&vOut);
4776                         SafeArrayDestroy (pSA);
4777                         return hr;
4778                 }
4779                 VariantClear (&vOut);
4780         }
4781         *safearray = pSA;
4782         return hr;
4783 }
4784
4785 LIBTEST_API int STDCALL 
4786 mono_test_marshal_safearray_out_2dim_vt_i4 (SAFEARRAY** safearray)
4787 {
4788         /* Create a two-dimensional array of 4x3 variants filled with 11, 12, 13, etc. */
4789         SAFEARRAY *pSA;
4790         SAFEARRAYBOUND dimensions [2];
4791         long i, j;
4792         HRESULT hr = S_OK;
4793         long indices [2];
4794
4795         dimensions [0].lLbound = 0;
4796         dimensions [0].cElements = 4;
4797         dimensions [1].lLbound = 0;
4798         dimensions [1].cElements = 3;
4799
4800         pSA= SafeArrayCreate(VT_VARIANT, 2, dimensions);
4801         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4802                 for (j= dimensions [1].lLbound; j< (dimensions [1].cElements + dimensions [1].lLbound); j++) {
4803                         VARIANT vOut;
4804                         VariantInit (&vOut);
4805                         vOut.vt = VT_I4;
4806                         vOut.lVal = (i+1)*10+(j+1);
4807                         indices [0] = i;
4808                         indices [1] = j;
4809                         if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4810                                 VariantClear (&vOut);
4811                                 SafeArrayDestroy (pSA);
4812                                 return hr;
4813                         }
4814                         VariantClear (&vOut);  // does a deep destroy of source VARIANT 
4815                 }
4816         }
4817         *safearray = pSA;
4818         return hr;
4819 }
4820
4821 LIBTEST_API int STDCALL 
4822 mono_test_marshal_safearray_out_4dim_vt_i4 (SAFEARRAY** safearray)
4823 {
4824         /* Create a four-dimensional array of 10x3x6x7 variants filled with their indices */
4825         /* Also use non zero lower bounds                                                 */
4826         SAFEARRAY *pSA;
4827         SAFEARRAYBOUND dimensions [4];
4828         long i;
4829         HRESULT hr = S_OK;
4830         VARIANT *pData;
4831
4832         dimensions [0].lLbound = 15;
4833         dimensions [0].cElements = 10;
4834         dimensions [1].lLbound = 20;
4835         dimensions [1].cElements = 3;
4836         dimensions [2].lLbound = 5;
4837         dimensions [2].cElements = 6;
4838         dimensions [3].lLbound = 12;
4839         dimensions [3].cElements = 7;
4840
4841         pSA= SafeArrayCreate (VT_VARIANT, 4, dimensions);
4842
4843         SafeArrayAccessData (pSA, (void **)&pData);
4844
4845         for (i= 0; i< 10*3*6*7; i++) {
4846                 VariantInit(&pData [i]);
4847                 pData [i].vt = VT_I4;
4848                 pData [i].lVal = i;
4849         }
4850         SafeArrayUnaccessData (pSA);
4851         *safearray = pSA;
4852         return hr;
4853 }
4854
4855 LIBTEST_API int STDCALL 
4856 mono_test_marshal_safearray_in_byval_1dim_empty (SAFEARRAY* safearray)
4857 {
4858         /* Check that array is one dimensional and empty */
4859
4860         UINT dim;
4861         long lbound, ubound;
4862         
4863         dim = SafeArrayGetDim (safearray);
4864         if (dim != 1)
4865                 return 1;
4866
4867         SafeArrayGetLBound (safearray, 1, &lbound);
4868         SafeArrayGetUBound (safearray, 1, &ubound);
4869
4870         if ((lbound > 0) || (ubound > 0))
4871                 return 1;
4872
4873         return 0;
4874 }
4875
4876 LIBTEST_API int STDCALL 
4877 mono_test_marshal_safearray_in_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4878 {
4879         /* Check that array is one dimensional containing integers from 1 to 10 */
4880
4881         UINT dim;
4882         long lbound, ubound;
4883         VARIANT *pData; 
4884         long i;
4885         int result=0;
4886
4887         dim = SafeArrayGetDim (safearray);
4888         if (dim != 1)
4889                 return 1;
4890
4891         SafeArrayGetLBound (safearray, 1, &lbound);
4892         SafeArrayGetUBound (safearray, 1, &ubound);
4893
4894         if ((lbound != 0) || (ubound != 9))
4895                 return 1;
4896
4897         SafeArrayAccessData (safearray, (void **)&pData);
4898         for (i= lbound; i <= ubound; i++) {
4899                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i + 1))
4900                         result = 1;
4901         }
4902         SafeArrayUnaccessData (safearray);
4903
4904         return result;
4905 }
4906
4907 LIBTEST_API int STDCALL 
4908 mono_test_marshal_safearray_in_byval_1dim_vt_mixed (SAFEARRAY* safearray)
4909 {
4910         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4911
4912         UINT dim;
4913         long lbound, ubound;
4914         VARIANT *pData; 
4915         long i;
4916         long indices [1];
4917         VARIANT element;
4918         int result=0;
4919
4920         VariantInit (&element);
4921
4922         dim = SafeArrayGetDim (safearray);
4923         if (dim != 1)
4924                 return 1;
4925
4926         SafeArrayGetLBound (safearray, 1, &lbound);
4927         SafeArrayGetUBound (safearray, 1, &ubound);
4928                 
4929         if ((lbound != 0) || (ubound != 12))
4930                 return 1;
4931
4932         SafeArrayAccessData (safearray, (void **)&pData);
4933         for (i= lbound; i <= ubound; i++) {
4934                 if ((i%2 == 0) && (pData [i].vt != VT_I4))
4935                         result = 1;
4936                 if ((i%2 == 1) && (pData [i].vt != VT_BSTR))
4937                         result = 1;
4938                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i))
4939                         result = 1;
4940         }
4941         SafeArrayUnaccessData (safearray);
4942
4943         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4944
4945         indices [0] = 0;
4946         element.vt = VT_I4;
4947         element.lVal = 333;
4948         SafeArrayPutElement (safearray, indices, &element);
4949         VariantClear (&element);
4950
4951         return result;
4952 }
4953
4954 LIBTEST_API int STDCALL 
4955 mono_test_marshal_safearray_in_byval_2dim_vt_i4 (SAFEARRAY* safearray)
4956 {
4957         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4958
4959         UINT dim;
4960         long lbound1, ubound1, lbound2, ubound2;
4961         long i, j, failed;
4962         long indices [2];
4963         VARIANT element;
4964
4965         VariantInit (&element);
4966
4967         dim = SafeArrayGetDim (safearray);
4968         if (dim != 2)
4969                 return 1;
4970
4971         SafeArrayGetLBound (safearray, 1, &lbound1);
4972         SafeArrayGetUBound (safearray, 1, &ubound1);
4973
4974         if ((lbound1 != 0) || (ubound1 != 1))
4975                 return 1;
4976
4977         SafeArrayGetLBound (safearray, 2, &lbound2);
4978         SafeArrayGetUBound (safearray, 2, &ubound2);
4979
4980         if ((lbound2 != 0) || (ubound2 != 3)) {
4981                 return 1;
4982         }
4983
4984         for (i= lbound1; i <= ubound1; i++) {
4985                 indices [0] = i;
4986                 for (j= lbound2; j <= ubound2; j++) {
4987                         indices [1] = j;
4988                         if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4989                                 return 1;
4990                         failed = ((element.vt != VT_I4) || (element.lVal != 10*(i+1)+(j+1)));
4991                         VariantClear (&element);
4992                         if (failed)
4993                                 return 1;
4994                 }
4995         }
4996
4997         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4998
4999         indices [0] = 0;
5000         indices [1] = 0;
5001         element.vt = VT_I4;
5002         element.lVal = 333;
5003         SafeArrayPutElement (safearray, indices, &element);
5004         VariantClear (&element);
5005
5006         return 0;
5007 }
5008
5009 LIBTEST_API int STDCALL 
5010 mono_test_marshal_safearray_in_byval_3dim_vt_bstr (SAFEARRAY* safearray)
5011 {
5012         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
5013
5014         UINT dim;
5015         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5016         long i, j, k, failed;
5017         long indices [3];
5018         VARIANT element;
5019
5020         VariantInit (&element);
5021
5022         dim = SafeArrayGetDim (safearray);
5023         if (dim != 3)
5024                 return 1;
5025
5026         SafeArrayGetLBound (safearray, 1, &lbound1);
5027         SafeArrayGetUBound (safearray, 1, &ubound1);
5028
5029         if ((lbound1 != 0) || (ubound1 != 1))
5030                 return 1;
5031
5032         SafeArrayGetLBound (safearray, 2, &lbound2);
5033         SafeArrayGetUBound (safearray, 2, &ubound2);
5034
5035         if ((lbound2 != 0) || (ubound2 != 1))
5036                 return 1;
5037
5038         SafeArrayGetLBound (safearray, 3, &lbound3);
5039         SafeArrayGetUBound (safearray, 3, &ubound3);
5040
5041         if ((lbound3 != 0) || (ubound3 != 2))
5042                 return 1;
5043
5044         for (i= lbound1; i <= ubound1; i++) {
5045                 indices [0] = i;
5046                 for (j= lbound2; j <= ubound2; j++) {
5047                         indices [1] = j;
5048                 for (k= lbound3; k <= ubound3; k++) {
5049                                 indices [2] = k;
5050                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5051                                         return 1;
5052                                 failed = ((element.vt != VT_BSTR) 
5053                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5054                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5055                                 VariantClear (&element);
5056                                 if (failed)
5057                                         return 1;
5058                         }
5059                 }
5060         }
5061
5062         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
5063
5064         indices [0] = 0;
5065         indices [1] = 0;
5066         indices [2] = 0;
5067         element.vt = VT_BSTR;
5068         element.bstrVal = SysAllocString(L"Should not be copied");
5069         SafeArrayPutElement (safearray, indices, &element);
5070         VariantClear (&element);
5071
5072         return 0;
5073 }
5074
5075 LIBTEST_API int STDCALL 
5076 mono_test_marshal_safearray_in_byref_3dim_vt_bstr (SAFEARRAY** safearray)
5077 {
5078         return mono_test_marshal_safearray_in_byval_3dim_vt_bstr (*safearray);
5079 }
5080
5081 LIBTEST_API int STDCALL 
5082 mono_test_marshal_safearray_in_out_byref_1dim_empty (SAFEARRAY** safearray)
5083 {
5084         /* Check that the input array is what is expected and change it so the caller can check */
5085         /* correct marshalling back to managed code                                             */
5086
5087         UINT dim;
5088         long lbound, ubound;
5089         SAFEARRAYBOUND dimensions [1];
5090         long i;
5091         wchar_t buffer [20];
5092         HRESULT hr = S_OK;
5093         long indices [1];
5094
5095         /* Check that in array is one dimensional and empty */
5096
5097         dim = SafeArrayGetDim (*safearray);
5098         if (dim != 1) {
5099                 return 1;
5100         }
5101
5102         SafeArrayGetLBound (*safearray, 1, &lbound);
5103         SafeArrayGetUBound (*safearray, 1, &ubound);
5104                 
5105         if ((lbound > 0) || (ubound > 0)) {
5106                 return 1;
5107         }
5108
5109         /* Re-dimension the array and return a one-dimensional array of 8 variants filled with "0" to "7" */
5110
5111         dimensions [0].lLbound = 0;
5112         dimensions [0].cElements = 8;
5113
5114         hr = SafeArrayRedim (*safearray, dimensions);
5115         if (hr != S_OK)
5116                 return 1;
5117
5118         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
5119                 VARIANT vOut;
5120                 VariantInit (&vOut);
5121                 vOut.vt = VT_BSTR;
5122                 _ltow (i,buffer,10);
5123                 vOut.bstrVal = SysAllocString (buffer);
5124                 indices [0] = i;
5125                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
5126                         VariantClear (&vOut);
5127                         SafeArrayDestroy (*safearray);
5128                         return hr;
5129                 }
5130                 VariantClear (&vOut);
5131         }
5132         return hr;
5133 }
5134
5135 LIBTEST_API int STDCALL 
5136 mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (SAFEARRAY** safearray)
5137 {
5138         /* Check that the input array is what is expected and change it so the caller can check */
5139         /* correct marshalling back to managed code                                             */
5140
5141         UINT dim;
5142         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5143         SAFEARRAYBOUND dimensions [1];
5144         long i, j, k, failed;
5145         wchar_t buffer [20];
5146         HRESULT hr = S_OK;
5147         long indices [3];
5148         VARIANT element;
5149
5150         VariantInit (&element);
5151
5152         /* Check that in array is three dimensional and contains the expected values */
5153
5154         dim = SafeArrayGetDim (*safearray);
5155         if (dim != 3)
5156                 return 1;
5157
5158         SafeArrayGetLBound (*safearray, 1, &lbound1);
5159         SafeArrayGetUBound (*safearray, 1, &ubound1);
5160
5161         if ((lbound1 != 0) || (ubound1 != 1))
5162                 return 1;
5163
5164         SafeArrayGetLBound (*safearray, 2, &lbound2);
5165         SafeArrayGetUBound (*safearray, 2, &ubound2);
5166
5167         if ((lbound2 != 0) || (ubound2 != 1))
5168                 return 1;
5169
5170         SafeArrayGetLBound (*safearray, 3, &lbound3);
5171         SafeArrayGetUBound (*safearray, 3, &ubound3);
5172
5173         if ((lbound3 != 0) || (ubound3 != 2))
5174                 return 1;
5175
5176         for (i= lbound1; i <= ubound1; i++) {
5177                 indices [0] = i;
5178                 for (j= lbound2; j <= ubound2; j++) {
5179                         indices [1] = j;
5180                         for (k= lbound3; k <= ubound3; k++) {
5181                                 indices [2] = k;
5182                                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
5183                                         return 1;
5184                                 failed = ((element.vt != VT_BSTR) 
5185                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5186                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5187                                 VariantClear (&element);
5188                                 if (failed)
5189                                         return 1;
5190                         }
5191                 }
5192         }
5193
5194         hr = SafeArrayDestroy (*safearray);
5195         if (hr != S_OK)
5196                 return 1;
5197
5198         /* Return a new one-dimensional array of 8 variants filled with "0" to "7" */
5199
5200         dimensions [0].lLbound = 0;
5201         dimensions [0].cElements = 8;
5202
5203         *safearray = SafeArrayCreate (VT_VARIANT, 1, dimensions);
5204
5205         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
5206                 VARIANT vOut;
5207                 VariantInit (&vOut);
5208                 vOut.vt = VT_BSTR;
5209                 _ltow (i,buffer,10);
5210                 vOut.bstrVal = SysAllocString (buffer);
5211                 indices [0] = i;
5212                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
5213                         VariantClear (&vOut);
5214                         SafeArrayDestroy (*safearray);
5215                         return hr;
5216                 }
5217                 VariantClear (&vOut);
5218         }
5219         return hr;
5220 }
5221
5222 LIBTEST_API int STDCALL 
5223 mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (SAFEARRAY** safearray)
5224 {
5225         /* Check that the input array is what is expected and change it so the caller can check */
5226         /* correct marshalling back to managed code                                             */
5227
5228         UINT dim;
5229         long lbound1, ubound1;
5230         long i, failed;
5231         HRESULT hr = S_OK;
5232         long indices [1];
5233         VARIANT element;
5234         
5235         VariantInit (&element);
5236
5237         /* Check that in array is one dimensional and contains the expected value */
5238
5239         dim = SafeArrayGetDim (*safearray);
5240         if (dim != 1)
5241                 return 1;
5242
5243         SafeArrayGetLBound (*safearray, 1, &lbound1);
5244         SafeArrayGetUBound (*safearray, 1, &ubound1);
5245
5246         ubound1 = 1;
5247         if ((lbound1 != 0) || (ubound1 != 1))
5248                 return 1;
5249         ubound1 = 0;
5250
5251         for (i= lbound1; i <= ubound1; i++) {
5252                 indices [0] = i;
5253                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
5254                         return 1;
5255                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
5256                 VariantClear (&element);
5257                 if (failed)
5258                         return 1;
5259         }
5260
5261         /* Change one of the elements of the array to verify that [out] parameter is marshalled back to the managed side */
5262
5263         indices [0] = 0;
5264         element.vt = VT_I4;
5265         element.lVal = -1;
5266         SafeArrayPutElement (*safearray, indices, &element);
5267         VariantClear (&element);
5268
5269         return hr;
5270 }
5271
5272 LIBTEST_API int STDCALL 
5273 mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (SAFEARRAY* safearray)
5274 {
5275         /* Check that the input array is what is expected and change it so the caller can check */
5276         /* correct marshalling back to managed code                                             */
5277
5278         UINT dim;
5279         long lbound1, ubound1;
5280         SAFEARRAYBOUND dimensions [1];
5281         long i, failed;
5282         HRESULT hr = S_OK;
5283         long indices [1];
5284         VARIANT element;
5285
5286         VariantInit (&element);
5287
5288         /* Check that in array is one dimensional and contains the expected value */
5289
5290         dim = SafeArrayGetDim (safearray);
5291         if (dim != 1)
5292                 return 1;
5293
5294         SafeArrayGetLBound (safearray, 1, &lbound1);
5295         SafeArrayGetUBound (safearray, 1, &ubound1);
5296                 
5297         if ((lbound1 != 0) || (ubound1 != 0))
5298                 return 1;
5299
5300         for (i= lbound1; i <= ubound1; i++) {
5301                 indices [0] = i;
5302                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5303                         return 1;
5304                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
5305                 VariantClear (&element);
5306                 if (failed)
5307                         return 1;
5308         }
5309
5310         /* Change the array to verify how [out] parameter is marshalled back to the managed side */
5311
5312         /* Redimension the array */
5313         dimensions [0].lLbound = lbound1;
5314         dimensions [0].cElements = 2;
5315         hr = SafeArrayRedim(safearray, dimensions);
5316
5317         indices [0] = 0;
5318         element.vt = VT_I4;
5319         element.lVal = 12345;
5320         SafeArrayPutElement (safearray, indices, &element);
5321         VariantClear (&element);
5322
5323         indices [0] = 1;
5324         element.vt = VT_I4;
5325         element.lVal = -12345;
5326         SafeArrayPutElement (safearray, indices, &element);
5327         VariantClear (&element);
5328
5329         return hr;
5330 }
5331
5332 LIBTEST_API int STDCALL 
5333 mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (SAFEARRAY* safearray)
5334 {
5335         /* Check that the input array is what is expected and change it so the caller can check */
5336         /* correct marshalling back to managed code                                             */
5337
5338         UINT dim;
5339         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
5340         long i, j, k, failed;
5341         HRESULT hr = S_OK;
5342         long indices [3];
5343         VARIANT element;
5344
5345         VariantInit (&element);
5346
5347         /* Check that in array is three dimensional and contains the expected values */
5348
5349         dim = SafeArrayGetDim (safearray);
5350         if (dim != 3)
5351                 return 1;
5352
5353         SafeArrayGetLBound (safearray, 1, &lbound1);
5354         SafeArrayGetUBound (safearray, 1, &ubound1);
5355
5356         if ((lbound1 != 0) || (ubound1 != 1))
5357                 return 1;
5358
5359         SafeArrayGetLBound (safearray, 2, &lbound2);
5360         SafeArrayGetUBound (safearray, 2, &ubound2);
5361
5362         if ((lbound2 != 0) || (ubound2 != 1))
5363                 return 1;
5364
5365         SafeArrayGetLBound (safearray, 3, &lbound3);
5366         SafeArrayGetUBound (safearray, 3, &ubound3);
5367
5368         if ((lbound3 != 0) || (ubound3 != 2))
5369                 return 1;
5370
5371         for (i= lbound1; i <= ubound1; i++) {
5372                 indices [0] = i;
5373                 for (j= lbound2; j <= ubound2; j++) {
5374                         indices [1] = j;
5375                         for (k= lbound3; k <= ubound3; k++) {
5376                                 indices [2] = k;
5377                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
5378                                         return 1;
5379                                 failed = ((element.vt != VT_BSTR) 
5380                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
5381                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
5382                                 VariantClear (&element);
5383                                 if (failed)
5384                                         return 1;
5385                         }
5386                 }
5387         }
5388
5389         /* Change the elements of the array to verify that [out] parameter is marshalled back to the managed side */
5390
5391         indices [0] = 1;
5392         indices [1] = 1;
5393         indices [2] = 2;
5394         element.vt = VT_I4;
5395         element.lVal = 333;
5396         SafeArrayPutElement (safearray, indices, &element);
5397         VariantClear (&element);
5398
5399         indices [0] = 1;
5400         indices [1] = 1;
5401         indices [2] = 1;
5402         element.vt = VT_I4;
5403         element.lVal = 111;
5404         SafeArrayPutElement (safearray, indices, &element);
5405         VariantClear (&element);
5406
5407         indices [0] = 0;
5408         indices [1] = 1;
5409         indices [2] = 0;
5410         element.vt = VT_BSTR;
5411         element.bstrVal = marshal_bstr_alloc("ABCDEFG");
5412         SafeArrayPutElement (safearray, indices, &element);
5413         VariantClear (&element);
5414
5415         return hr;
5416 }
5417
5418 LIBTEST_API int STDCALL 
5419 mono_test_marshal_safearray_mixed(
5420                 SAFEARRAY  *safearray1,
5421                 SAFEARRAY **safearray2,
5422                 SAFEARRAY  *safearray3,
5423                 SAFEARRAY **safearray4
5424                 )
5425 {
5426         HRESULT hr = S_OK;
5427
5428         /* Initialize out parameters */
5429         *safearray2 = NULL;
5430
5431         /* array1: Check that in array is one dimensional and contains the expected value */
5432         hr = mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (safearray1);
5433
5434         /* array2: Fill in with some values to check on the managed side */
5435         if (hr == S_OK)
5436                 hr = mono_test_marshal_safearray_out_1dim_vt_bstr (safearray2);
5437
5438         /* array3: Check that in array is one dimensional and contains the expected value */
5439         if (hr == S_OK)
5440                 hr = mono_test_marshal_safearray_in_byval_1dim_vt_mixed(safearray3);
5441
5442         /* array4: Check input values and fill in with some values to check on the managed side */
5443         if (hr == S_OK)
5444                 hr = mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr(safearray4);
5445
5446         return hr;
5447 }
5448
5449 #endif
5450
5451 static int call_managed_res;
5452
5453 static void
5454 call_managed (gpointer arg)
5455 {
5456         SimpleDelegate del = (SimpleDelegate)arg;
5457
5458         call_managed_res = del (42);
5459 }
5460
5461 LIBTEST_API int STDCALL 
5462 mono_test_marshal_thread_attach (SimpleDelegate del)
5463 {
5464 #ifdef WIN32
5465         return 43;
5466 #else
5467         int res;
5468         pthread_t t;
5469
5470         res = pthread_create (&t, NULL, (gpointer (*)(gpointer))call_managed, del);
5471         g_assert (res == 0);
5472         pthread_join (t, NULL);
5473
5474         return call_managed_res;
5475 #endif
5476 }
5477
5478 typedef int (STDCALL *Callback) (void);
5479
5480 static Callback callback;
5481
5482 LIBTEST_API void STDCALL 
5483 mono_test_marshal_set_callback (Callback cb)
5484 {
5485         callback = cb;
5486 }
5487
5488 LIBTEST_API int STDCALL 
5489 mono_test_marshal_call_callback (void)
5490 {
5491         return callback ();
5492 }
5493
5494 LIBTEST_API int STDCALL
5495 mono_test_marshal_lpstr (char *str)
5496 {
5497         return strcmp ("ABC", str);
5498 }
5499
5500 LIBTEST_API int STDCALL
5501 mono_test_marshal_lpwstr (gunichar2 *str)
5502 {
5503         char *s;
5504         int res;
5505
5506         s = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
5507         res = strcmp ("ABC", s);
5508         g_free (s);
5509
5510         return res;
5511 }
5512
5513 LIBTEST_API char* STDCALL
5514 mono_test_marshal_return_lpstr (void)
5515 {
5516         char *res = (char *)marshal_alloc (4);
5517         strcpy (res, "XYZ");
5518         return res;
5519 }
5520
5521
5522 LIBTEST_API gunichar2* STDCALL
5523 mono_test_marshal_return_lpwstr (void)
5524 {
5525         gunichar2 *res = (gunichar2 *)marshal_alloc (8);
5526         gunichar2* tmp = g_utf8_to_utf16 ("XYZ", -1, NULL, NULL, NULL);
5527
5528         memcpy (res, tmp, 8);
5529         g_free (tmp);
5530
5531         return res;
5532 }
5533
5534 typedef struct {
5535         double d;
5536 } SingleDoubleStruct;
5537
5538 LIBTEST_API SingleDoubleStruct STDCALL
5539 mono_test_marshal_return_single_double_struct (void)
5540 {
5541         SingleDoubleStruct res;
5542
5543         res.d = 3.0;
5544
5545         return res;
5546 }
5547
5548
5549 #ifndef TARGET_X86
5550
5551 LIBTEST_API int STDCALL
5552 mono_test_has_thiscall (void)
5553 {
5554         return 1;
5555 }
5556
5557 LIBTEST_API int
5558 _mono_test_native_thiscall1 (int arg)
5559 {
5560         return arg;
5561 }
5562
5563 LIBTEST_API int
5564 _mono_test_native_thiscall2 (int arg, int arg2)
5565 {
5566         return arg + (arg2^1);
5567 }
5568
5569 LIBTEST_API int
5570 _mono_test_native_thiscall3 (int arg, int arg2, int arg3)
5571 {
5572         return arg + (arg2^1) + (arg3^2);
5573 }
5574
5575 #elif defined(__GNUC__)
5576
5577 LIBTEST_API int STDCALL
5578 mono_test_has_thiscall (void)
5579 {
5580         return 1;
5581 }
5582
5583 #define def_asm_fn(name) \
5584         "\t.align 4\n" \
5585         "\t.globl _" #name "\n" \
5586         "_" #name ":\n" \
5587         "\t.globl __" #name "\n" \
5588         "__" #name ":\n"
5589
5590 asm(".text\n"
5591
5592 def_asm_fn(mono_test_native_thiscall1)
5593 "\tmovl %ecx,%eax\n"
5594 "\tret\n"
5595
5596 def_asm_fn(mono_test_native_thiscall2)
5597 "\tmovl %ecx,%eax\n"
5598 "\tmovl 4(%esp),%ecx\n"
5599 "\txorl $1,%ecx\n"
5600 "\taddl %ecx,%eax\n"
5601 "\tret $4\n"
5602
5603 def_asm_fn(mono_test_native_thiscall3)
5604 "\tmovl %ecx,%eax\n"
5605 "\tmovl 4(%esp),%ecx\n"
5606 "\txorl $1,%ecx\n"
5607 "\taddl %ecx,%eax\n"
5608 "\tmovl 8(%esp),%ecx\n"
5609 "\txorl $2,%ecx\n"
5610 "\taddl %ecx,%eax\n"
5611 "\tret $8\n"
5612
5613 );
5614
5615 #else
5616
5617 LIBTEST_API int STDCALL
5618 mono_test_has_thiscall (void)
5619 {
5620         return 0;
5621 }
5622
5623 #endif
5624
5625
5626 typedef struct {
5627         char f1;
5628 } sbyte1;
5629
5630 LIBTEST_API sbyte1 STDCALL
5631 mono_return_sbyte1 (sbyte1 s1, int addend) {
5632         if (s1.f1 != 1) {
5633                 fprintf(stderr, "mono_return_sbyte1 s1.f1: got %d but expected %d\n", s1.f1, 1);
5634         }
5635         s1.f1+=addend; 
5636         return s1;
5637 }
5638
5639 typedef struct {
5640         char f1,f2;
5641 } sbyte2;
5642
5643 LIBTEST_API sbyte2 STDCALL
5644 mono_return_sbyte2 (sbyte2 s2, int addend) {
5645         if (s2.f1 != 1) {
5646                 fprintf(stderr, "mono_return_sbyte2 s2.f1: got %d but expected %d\n", s2.f1, 1);
5647         }
5648         if (s2.f2 != 2) {
5649                 fprintf(stderr, "mono_return_sbyte2 s2.f2: got %d but expected %d\n", s2.f2, 2);
5650         }
5651         s2.f1+=addend; s2.f2+=addend; 
5652         return s2;
5653 }
5654
5655 typedef struct {
5656         char f1,f2,f3;
5657 } sbyte3;
5658
5659 LIBTEST_API sbyte3 STDCALL
5660 mono_return_sbyte3 (sbyte3 s3, int addend) {
5661         if (s3.f1 != 1) {
5662                 fprintf(stderr, "mono_return_sbyte3 s3.f1: got %d but expected %d\n", s3.f1, 1);
5663         }
5664         if (s3.f2 != 2) {
5665                 fprintf(stderr, "mono_return_sbyte3 s3.f2: got %d but expected %d\n", s3.f2, 2);
5666         }
5667         if (s3.f3 != 3) {
5668                 fprintf(stderr, "mono_return_sbyte3 s3.f3: got %d but expected %d\n", s3.f3, 3);
5669         }
5670         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
5671         return s3;
5672 }
5673
5674 typedef struct {
5675         char f1,f2,f3,f4;
5676 } sbyte4;
5677
5678 LIBTEST_API sbyte4 STDCALL
5679 mono_return_sbyte4 (sbyte4 s4, int addend) {
5680         if (s4.f1 != 1) {
5681                 fprintf(stderr, "mono_return_sbyte4 s4.f1: got %d but expected %d\n", s4.f1, 1);
5682         }
5683         if (s4.f2 != 2) {
5684                 fprintf(stderr, "mono_return_sbyte4 s4.f2: got %d but expected %d\n", s4.f2, 2);
5685         }
5686         if (s4.f3 != 3) {
5687                 fprintf(stderr, "mono_return_sbyte4 s4.f3: got %d but expected %d\n", s4.f3, 3);
5688         }
5689         if (s4.f4 != 4) {
5690                 fprintf(stderr, "mono_return_sbyte4 s4.f4: got %d but expected %d\n", s4.f4, 4);
5691         }
5692         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
5693         return s4;
5694 }
5695
5696 typedef struct {
5697         char f1,f2,f3,f4,f5;
5698 } sbyte5;
5699
5700 LIBTEST_API sbyte5 STDCALL
5701 mono_return_sbyte5 (sbyte5 s5, int addend) {
5702         if (s5.f1 != 1) {
5703                 fprintf(stderr, "mono_return_sbyte5 s5.f1: got %d but expected %d\n", s5.f1, 1);
5704         }
5705         if (s5.f2 != 2) {
5706                 fprintf(stderr, "mono_return_sbyte5 s5.f2: got %d but expected %d\n", s5.f2, 2);
5707         }
5708         if (s5.f3 != 3) {
5709                 fprintf(stderr, "mono_return_sbyte5 s5.f3: got %d but expected %d\n", s5.f3, 3);
5710         }
5711         if (s5.f4 != 4) {
5712                 fprintf(stderr, "mono_return_sbyte5 s5.f4: got %d but expected %d\n", s5.f4, 4);
5713         }
5714         if (s5.f5 != 5) {
5715                 fprintf(stderr, "mono_return_sbyte5 s5.f5: got %d but expected %d\n", s5.f5, 5);
5716         }
5717         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
5718         return s5;
5719 }
5720
5721 typedef struct {
5722         char f1,f2,f3,f4,f5,f6;
5723 } sbyte6;
5724
5725 LIBTEST_API sbyte6 STDCALL
5726 mono_return_sbyte6 (sbyte6 s6, int addend) {
5727         if (s6.f1 != 1) {
5728                 fprintf(stderr, "mono_return_sbyte6 s6.f1: got %d but expected %d\n", s6.f1, 1);
5729         }
5730         if (s6.f2 != 2) {
5731                 fprintf(stderr, "mono_return_sbyte6 s6.f2: got %d but expected %d\n", s6.f2, 2);
5732         }
5733         if (s6.f3 != 3) {
5734                 fprintf(stderr, "mono_return_sbyte6 s6.f3: got %d but expected %d\n", s6.f3, 3);
5735         }
5736         if (s6.f4 != 4) {
5737                 fprintf(stderr, "mono_return_sbyte6 s6.f4: got %d but expected %d\n", s6.f4, 4);
5738         }
5739         if (s6.f5 != 5) {
5740                 fprintf(stderr, "mono_return_sbyte6 s6.f5: got %d but expected %d\n", s6.f5, 5);
5741         }
5742         if (s6.f6 != 6) {
5743                 fprintf(stderr, "mono_return_sbyte6 s6.f6: got %d but expected %d\n", s6.f6, 6);
5744         }
5745         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
5746         return s6;
5747 }
5748
5749 typedef struct {
5750         char f1,f2,f3,f4,f5,f6,f7;
5751 } sbyte7;
5752
5753 LIBTEST_API sbyte7 STDCALL
5754 mono_return_sbyte7 (sbyte7 s7, int addend) {
5755         if (s7.f1 != 1) {
5756                 fprintf(stderr, "mono_return_sbyte7 s7.f1: got %d but expected %d\n", s7.f1, 1);
5757         }
5758         if (s7.f2 != 2) {
5759                 fprintf(stderr, "mono_return_sbyte7 s7.f2: got %d but expected %d\n", s7.f2, 2);
5760         }
5761         if (s7.f3 != 3) {
5762                 fprintf(stderr, "mono_return_sbyte7 s7.f3: got %d but expected %d\n", s7.f3, 3);
5763         }
5764         if (s7.f4 != 4) {
5765                 fprintf(stderr, "mono_return_sbyte7 s7.f4: got %d but expected %d\n", s7.f4, 4);
5766         }
5767         if (s7.f5 != 5) {
5768                 fprintf(stderr, "mono_return_sbyte7 s7.f5: got %d but expected %d\n", s7.f5, 5);
5769         }
5770         if (s7.f6 != 6) {
5771                 fprintf(stderr, "mono_return_sbyte7 s7.f6: got %d but expected %d\n", s7.f6, 6);
5772         }
5773         if (s7.f7 != 7) {
5774                 fprintf(stderr, "mono_return_sbyte7 s7.f7: got %d but expected %d\n", s7.f7, 7);
5775         }
5776         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
5777         return s7;
5778 }
5779
5780 typedef struct {
5781         char f1,f2,f3,f4,f5,f6,f7,f8;
5782 } sbyte8;
5783
5784 LIBTEST_API sbyte8 STDCALL
5785 mono_return_sbyte8 (sbyte8 s8, int addend) {
5786         if (s8.f1 != 1) {
5787                 fprintf(stderr, "mono_return_sbyte8 s8.f1: got %d but expected %d\n", s8.f1, 1);
5788         }
5789         if (s8.f2 != 2) {
5790                 fprintf(stderr, "mono_return_sbyte8 s8.f2: got %d but expected %d\n", s8.f2, 2);
5791         }
5792         if (s8.f3 != 3) {
5793                 fprintf(stderr, "mono_return_sbyte8 s8.f3: got %d but expected %d\n", s8.f3, 3);
5794         }
5795         if (s8.f4 != 4) {
5796                 fprintf(stderr, "mono_return_sbyte8 s8.f4: got %d but expected %d\n", s8.f4, 4);
5797         }
5798         if (s8.f5 != 5) {
5799                 fprintf(stderr, "mono_return_sbyte8 s8.f5: got %d but expected %d\n", s8.f5, 5);
5800         }
5801         if (s8.f6 != 6) {
5802                 fprintf(stderr, "mono_return_sbyte8 s8.f6: got %d but expected %d\n", s8.f6, 6);
5803         }
5804         if (s8.f7 != 7) {
5805                 fprintf(stderr, "mono_return_sbyte8 s8.f7: got %d but expected %d\n", s8.f7, 7);
5806         }
5807         if (s8.f8 != 8) {
5808                 fprintf(stderr, "mono_return_sbyte8 s8.f8: got %d but expected %d\n", s8.f8, 8);
5809         }
5810         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
5811         return s8;
5812 }
5813
5814 typedef struct {
5815         char f1,f2,f3,f4,f5,f6,f7,f8,f9;
5816 } sbyte9;
5817
5818 LIBTEST_API sbyte9 STDCALL
5819 mono_return_sbyte9 (sbyte9 s9, int addend) {
5820         if (s9.f1 != 1) {
5821                 fprintf(stderr, "mono_return_sbyte9 s9.f1: got %d but expected %d\n", s9.f1, 1);
5822         }
5823         if (s9.f2 != 2) {
5824                 fprintf(stderr, "mono_return_sbyte9 s9.f2: got %d but expected %d\n", s9.f2, 2);
5825         }
5826         if (s9.f3 != 3) {
5827                 fprintf(stderr, "mono_return_sbyte9 s9.f3: got %d but expected %d\n", s9.f3, 3);
5828         }
5829         if (s9.f4 != 4) {
5830                 fprintf(stderr, "mono_return_sbyte9 s9.f4: got %d but expected %d\n", s9.f4, 4);
5831         }
5832         if (s9.f5 != 5) {
5833                 fprintf(stderr, "mono_return_sbyte9 s9.f5: got %d but expected %d\n", s9.f5, 5);
5834         }
5835         if (s9.f6 != 6) {
5836                 fprintf(stderr, "mono_return_sbyte9 s9.f6: got %d but expected %d\n", s9.f6, 6);
5837         }
5838         if (s9.f7 != 7) {
5839                 fprintf(stderr, "mono_return_sbyte9 s9.f7: got %d but expected %d\n", s9.f7, 7);
5840         }
5841         if (s9.f8 != 8) {
5842                 fprintf(stderr, "mono_return_sbyte9 s9.f8: got %d but expected %d\n", s9.f8, 8);
5843         }
5844         if (s9.f9 != 9) {
5845                 fprintf(stderr, "mono_return_sbyte9 s9.f9: got %d but expected %d\n", s9.f9, 9);
5846         }
5847         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; 
5848         return s9;
5849 }
5850
5851 typedef struct {
5852         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10;
5853 } sbyte10;
5854
5855 LIBTEST_API sbyte10 STDCALL
5856 mono_return_sbyte10 (sbyte10 s10, int addend) {
5857         if (s10.f1 != 1) {
5858                 fprintf(stderr, "mono_return_sbyte10 s10.f1: got %d but expected %d\n", s10.f1, 1);
5859         }
5860         if (s10.f2 != 2) {
5861                 fprintf(stderr, "mono_return_sbyte10 s10.f2: got %d but expected %d\n", s10.f2, 2);
5862         }
5863         if (s10.f3 != 3) {
5864                 fprintf(stderr, "mono_return_sbyte10 s10.f3: got %d but expected %d\n", s10.f3, 3);
5865         }
5866         if (s10.f4 != 4) {
5867                 fprintf(stderr, "mono_return_sbyte10 s10.f4: got %d but expected %d\n", s10.f4, 4);
5868         }
5869         if (s10.f5 != 5) {
5870                 fprintf(stderr, "mono_return_sbyte10 s10.f5: got %d but expected %d\n", s10.f5, 5);
5871         }
5872         if (s10.f6 != 6) {
5873                 fprintf(stderr, "mono_return_sbyte10 s10.f6: got %d but expected %d\n", s10.f6, 6);
5874         }
5875         if (s10.f7 != 7) {
5876                 fprintf(stderr, "mono_return_sbyte10 s10.f7: got %d but expected %d\n", s10.f7, 7);
5877         }
5878         if (s10.f8 != 8) {
5879                 fprintf(stderr, "mono_return_sbyte10 s10.f8: got %d but expected %d\n", s10.f8, 8);
5880         }
5881         if (s10.f9 != 9) {
5882                 fprintf(stderr, "mono_return_sbyte10 s10.f9: got %d but expected %d\n", s10.f9, 9);
5883         }
5884         if (s10.f10 != 10) {
5885                 fprintf(stderr, "mono_return_sbyte10 s10.f10: got %d but expected %d\n", s10.f10, 10);
5886         }
5887         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; 
5888         return s10;
5889 }
5890
5891 typedef struct {
5892         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11;
5893 } sbyte11;
5894
5895 LIBTEST_API sbyte11 STDCALL
5896 mono_return_sbyte11 (sbyte11 s11, int addend) {
5897         if (s11.f1 != 1) {
5898                 fprintf(stderr, "mono_return_sbyte11 s11.f1: got %d but expected %d\n", s11.f1, 1);
5899         }
5900         if (s11.f2 != 2) {
5901                 fprintf(stderr, "mono_return_sbyte11 s11.f2: got %d but expected %d\n", s11.f2, 2);
5902         }
5903         if (s11.f3 != 3) {
5904                 fprintf(stderr, "mono_return_sbyte11 s11.f3: got %d but expected %d\n", s11.f3, 3);
5905         }
5906         if (s11.f4 != 4) {
5907                 fprintf(stderr, "mono_return_sbyte11 s11.f4: got %d but expected %d\n", s11.f4, 4);
5908         }
5909         if (s11.f5 != 5) {
5910                 fprintf(stderr, "mono_return_sbyte11 s11.f5: got %d but expected %d\n", s11.f5, 5);
5911         }
5912         if (s11.f6 != 6) {
5913                 fprintf(stderr, "mono_return_sbyte11 s11.f6: got %d but expected %d\n", s11.f6, 6);
5914         }
5915         if (s11.f7 != 7) {
5916                 fprintf(stderr, "mono_return_sbyte11 s11.f7: got %d but expected %d\n", s11.f7, 7);
5917         }
5918         if (s11.f8 != 8) {
5919                 fprintf(stderr, "mono_return_sbyte11 s11.f8: got %d but expected %d\n", s11.f8, 8);
5920         }
5921         if (s11.f9 != 9) {
5922                 fprintf(stderr, "mono_return_sbyte11 s11.f9: got %d but expected %d\n", s11.f9, 9);
5923         }
5924         if (s11.f10 != 10) {
5925                 fprintf(stderr, "mono_return_sbyte11 s11.f10: got %d but expected %d\n", s11.f10, 10);
5926         }
5927         if (s11.f11 != 11) {
5928                 fprintf(stderr, "mono_return_sbyte11 s11.f11: got %d but expected %d\n", s11.f11, 11);
5929         }
5930         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; 
5931         return s11;
5932 }
5933
5934 typedef struct {
5935         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12;
5936 } sbyte12;
5937
5938 LIBTEST_API sbyte12 STDCALL
5939 mono_return_sbyte12 (sbyte12 s12, int addend) {
5940         if (s12.f1 != 1) {
5941                 fprintf(stderr, "mono_return_sbyte12 s12.f1: got %d but expected %d\n", s12.f1, 1);
5942         }
5943         if (s12.f2 != 2) {
5944                 fprintf(stderr, "mono_return_sbyte12 s12.f2: got %d but expected %d\n", s12.f2, 2);
5945         }
5946         if (s12.f3 != 3) {
5947                 fprintf(stderr, "mono_return_sbyte12 s12.f3: got %d but expected %d\n", s12.f3, 3);
5948         }
5949         if (s12.f4 != 4) {
5950                 fprintf(stderr, "mono_return_sbyte12 s12.f4: got %d but expected %d\n", s12.f4, 4);
5951         }
5952         if (s12.f5 != 5) {
5953                 fprintf(stderr, "mono_return_sbyte12 s12.f5: got %d but expected %d\n", s12.f5, 5);
5954         }
5955         if (s12.f6 != 6) {
5956                 fprintf(stderr, "mono_return_sbyte12 s12.f6: got %d but expected %d\n", s12.f6, 6);
5957         }
5958         if (s12.f7 != 7) {
5959                 fprintf(stderr, "mono_return_sbyte12 s12.f7: got %d but expected %d\n", s12.f7, 7);
5960         }
5961         if (s12.f8 != 8) {
5962                 fprintf(stderr, "mono_return_sbyte12 s12.f8: got %d but expected %d\n", s12.f8, 8);
5963         }
5964         if (s12.f9 != 9) {
5965                 fprintf(stderr, "mono_return_sbyte12 s12.f9: got %d but expected %d\n", s12.f9, 9);
5966         }
5967         if (s12.f10 != 10) {
5968                 fprintf(stderr, "mono_return_sbyte12 s12.f10: got %d but expected %d\n", s12.f10, 10);
5969         }
5970         if (s12.f11 != 11) {
5971                 fprintf(stderr, "mono_return_sbyte12 s12.f11: got %d but expected %d\n", s12.f11, 11);
5972         }
5973         if (s12.f12 != 12) {
5974                 fprintf(stderr, "mono_return_sbyte12 s12.f12: got %d but expected %d\n", s12.f12, 12);
5975         }
5976         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; 
5977         return s12;
5978 }
5979
5980 typedef struct {
5981         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13;
5982 } sbyte13;
5983
5984 LIBTEST_API sbyte13 STDCALL
5985 mono_return_sbyte13 (sbyte13 s13, int addend) {
5986         if (s13.f1 != 1) {
5987                 fprintf(stderr, "mono_return_sbyte13 s13.f1: got %d but expected %d\n", s13.f1, 1);
5988         }
5989         if (s13.f2 != 2) {
5990                 fprintf(stderr, "mono_return_sbyte13 s13.f2: got %d but expected %d\n", s13.f2, 2);
5991         }
5992         if (s13.f3 != 3) {
5993                 fprintf(stderr, "mono_return_sbyte13 s13.f3: got %d but expected %d\n", s13.f3, 3);
5994         }
5995         if (s13.f4 != 4) {
5996                 fprintf(stderr, "mono_return_sbyte13 s13.f4: got %d but expected %d\n", s13.f4, 4);
5997         }
5998         if (s13.f5 != 5) {
5999                 fprintf(stderr, "mono_return_sbyte13 s13.f5: got %d but expected %d\n", s13.f5, 5);
6000         }
6001         if (s13.f6 != 6) {
6002                 fprintf(stderr, "mono_return_sbyte13 s13.f6: got %d but expected %d\n", s13.f6, 6);
6003         }
6004         if (s13.f7 != 7) {
6005                 fprintf(stderr, "mono_return_sbyte13 s13.f7: got %d but expected %d\n", s13.f7, 7);
6006         }
6007         if (s13.f8 != 8) {
6008                 fprintf(stderr, "mono_return_sbyte13 s13.f8: got %d but expected %d\n", s13.f8, 8);
6009         }
6010         if (s13.f9 != 9) {
6011                 fprintf(stderr, "mono_return_sbyte13 s13.f9: got %d but expected %d\n", s13.f9, 9);
6012         }
6013         if (s13.f10 != 10) {
6014                 fprintf(stderr, "mono_return_sbyte13 s13.f10: got %d but expected %d\n", s13.f10, 10);
6015         }
6016         if (s13.f11 != 11) {
6017                 fprintf(stderr, "mono_return_sbyte13 s13.f11: got %d but expected %d\n", s13.f11, 11);
6018         }
6019         if (s13.f12 != 12) {
6020                 fprintf(stderr, "mono_return_sbyte13 s13.f12: got %d but expected %d\n", s13.f12, 12);
6021         }
6022         if (s13.f13 != 13) {
6023                 fprintf(stderr, "mono_return_sbyte13 s13.f13: got %d but expected %d\n", s13.f13, 13);
6024         }
6025         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; 
6026         return s13;
6027 }
6028
6029 typedef struct {
6030         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14;
6031 } sbyte14;
6032
6033 LIBTEST_API sbyte14 STDCALL
6034 mono_return_sbyte14 (sbyte14 s14, int addend) {
6035         if (s14.f1 != 1) {
6036                 fprintf(stderr, "mono_return_sbyte14 s14.f1: got %d but expected %d\n", s14.f1, 1);
6037         }
6038         if (s14.f2 != 2) {
6039                 fprintf(stderr, "mono_return_sbyte14 s14.f2: got %d but expected %d\n", s14.f2, 2);
6040         }
6041         if (s14.f3 != 3) {
6042                 fprintf(stderr, "mono_return_sbyte14 s14.f3: got %d but expected %d\n", s14.f3, 3);
6043         }
6044         if (s14.f4 != 4) {
6045                 fprintf(stderr, "mono_return_sbyte14 s14.f4: got %d but expected %d\n", s14.f4, 4);
6046         }
6047         if (s14.f5 != 5) {
6048                 fprintf(stderr, "mono_return_sbyte14 s14.f5: got %d but expected %d\n", s14.f5, 5);
6049         }
6050         if (s14.f6 != 6) {
6051                 fprintf(stderr, "mono_return_sbyte14 s14.f6: got %d but expected %d\n", s14.f6, 6);
6052         }
6053         if (s14.f7 != 7) {
6054                 fprintf(stderr, "mono_return_sbyte14 s14.f7: got %d but expected %d\n", s14.f7, 7);
6055         }
6056         if (s14.f8 != 8) {
6057                 fprintf(stderr, "mono_return_sbyte14 s14.f8: got %d but expected %d\n", s14.f8, 8);
6058         }
6059         if (s14.f9 != 9) {
6060                 fprintf(stderr, "mono_return_sbyte14 s14.f9: got %d but expected %d\n", s14.f9, 9);
6061         }
6062         if (s14.f10 != 10) {
6063                 fprintf(stderr, "mono_return_sbyte14 s14.f10: got %d but expected %d\n", s14.f10, 10);
6064         }
6065         if (s14.f11 != 11) {
6066                 fprintf(stderr, "mono_return_sbyte14 s14.f11: got %d but expected %d\n", s14.f11, 11);
6067         }
6068         if (s14.f12 != 12) {
6069                 fprintf(stderr, "mono_return_sbyte14 s14.f12: got %d but expected %d\n", s14.f12, 12);
6070         }
6071         if (s14.f13 != 13) {
6072                 fprintf(stderr, "mono_return_sbyte14 s14.f13: got %d but expected %d\n", s14.f13, 13);
6073         }
6074         if (s14.f14 != 14) {
6075                 fprintf(stderr, "mono_return_sbyte14 s14.f14: got %d but expected %d\n", s14.f14, 14);
6076         }
6077         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; 
6078         return s14;
6079 }
6080
6081 typedef struct {
6082         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
6083 } sbyte15;
6084
6085 LIBTEST_API sbyte15 STDCALL
6086 mono_return_sbyte15 (sbyte15 s15, int addend) {
6087         if (s15.f1 != 1) {
6088                 fprintf(stderr, "mono_return_sbyte15 s15.f1: got %d but expected %d\n", s15.f1, 1);
6089         }
6090         if (s15.f2 != 2) {
6091                 fprintf(stderr, "mono_return_sbyte15 s15.f2: got %d but expected %d\n", s15.f2, 2);
6092         }
6093         if (s15.f3 != 3) {
6094                 fprintf(stderr, "mono_return_sbyte15 s15.f3: got %d but expected %d\n", s15.f3, 3);
6095         }
6096         if (s15.f4 != 4) {
6097                 fprintf(stderr, "mono_return_sbyte15 s15.f4: got %d but expected %d\n", s15.f4, 4);
6098         }
6099         if (s15.f5 != 5) {
6100                 fprintf(stderr, "mono_return_sbyte15 s15.f5: got %d but expected %d\n", s15.f5, 5);
6101         }
6102         if (s15.f6 != 6) {
6103                 fprintf(stderr, "mono_return_sbyte15 s15.f6: got %d but expected %d\n", s15.f6, 6);
6104         }
6105         if (s15.f7 != 7) {
6106                 fprintf(stderr, "mono_return_sbyte15 s15.f7: got %d but expected %d\n", s15.f7, 7);
6107         }
6108         if (s15.f8 != 8) {
6109                 fprintf(stderr, "mono_return_sbyte15 s15.f8: got %d but expected %d\n", s15.f8, 8);
6110         }
6111         if (s15.f9 != 9) {
6112                 fprintf(stderr, "mono_return_sbyte15 s15.f9: got %d but expected %d\n", s15.f9, 9);
6113         }
6114         if (s15.f10 != 10) {
6115                 fprintf(stderr, "mono_return_sbyte15 s15.f10: got %d but expected %d\n", s15.f10, 10);
6116         }
6117         if (s15.f11 != 11) {
6118                 fprintf(stderr, "mono_return_sbyte15 s15.f11: got %d but expected %d\n", s15.f11, 11);
6119         }
6120         if (s15.f12 != 12) {
6121                 fprintf(stderr, "mono_return_sbyte15 s15.f12: got %d but expected %d\n", s15.f12, 12);
6122         }
6123         if (s15.f13 != 13) {
6124                 fprintf(stderr, "mono_return_sbyte15 s15.f13: got %d but expected %d\n", s15.f13, 13);
6125         }
6126         if (s15.f14 != 14) {
6127                 fprintf(stderr, "mono_return_sbyte15 s15.f14: got %d but expected %d\n", s15.f14, 14);
6128         }
6129         if (s15.f15 != 15) {
6130                 fprintf(stderr, "mono_return_sbyte15 s15.f15: got %d but expected %d\n", s15.f15, 15);
6131         }
6132         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; 
6133         return s15;
6134 }
6135
6136 typedef struct {
6137         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16;
6138 } sbyte16;
6139
6140 LIBTEST_API sbyte16 STDCALL
6141 mono_return_sbyte16 (sbyte16 s16, int addend) {
6142         if (s16.f1 != 1) {
6143                 fprintf(stderr, "mono_return_sbyte16 s16.f1: got %d but expected %d\n", s16.f1, 1);
6144         }
6145         if (s16.f2 != 2) {
6146                 fprintf(stderr, "mono_return_sbyte16 s16.f2: got %d but expected %d\n", s16.f2, 2);
6147         }
6148         if (s16.f3 != 3) {
6149                 fprintf(stderr, "mono_return_sbyte16 s16.f3: got %d but expected %d\n", s16.f3, 3);
6150         }
6151         if (s16.f4 != 4) {
6152                 fprintf(stderr, "mono_return_sbyte16 s16.f4: got %d but expected %d\n", s16.f4, 4);
6153         }
6154         if (s16.f5 != 5) {
6155                 fprintf(stderr, "mono_return_sbyte16 s16.f5: got %d but expected %d\n", s16.f5, 5);
6156         }
6157         if (s16.f6 != 6) {
6158                 fprintf(stderr, "mono_return_sbyte16 s16.f6: got %d but expected %d\n", s16.f6, 6);
6159         }
6160         if (s16.f7 != 7) {
6161                 fprintf(stderr, "mono_return_sbyte16 s16.f7: got %d but expected %d\n", s16.f7, 7);
6162         }
6163         if (s16.f8 != 8) {
6164                 fprintf(stderr, "mono_return_sbyte16 s16.f8: got %d but expected %d\n", s16.f8, 8);
6165         }
6166         if (s16.f9 != 9) {
6167                 fprintf(stderr, "mono_return_sbyte16 s16.f9: got %d but expected %d\n", s16.f9, 9);
6168         }
6169         if (s16.f10 != 10) {
6170                 fprintf(stderr, "mono_return_sbyte16 s16.f10: got %d but expected %d\n", s16.f10, 10);
6171         }
6172         if (s16.f11 != 11) {
6173                 fprintf(stderr, "mono_return_sbyte16 s16.f11: got %d but expected %d\n", s16.f11, 11);
6174         }
6175         if (s16.f12 != 12) {
6176                 fprintf(stderr, "mono_return_sbyte16 s16.f12: got %d but expected %d\n", s16.f12, 12);
6177         }
6178         if (s16.f13 != 13) {
6179                 fprintf(stderr, "mono_return_sbyte16 s16.f13: got %d but expected %d\n", s16.f13, 13);
6180         }
6181         if (s16.f14 != 14) {
6182                 fprintf(stderr, "mono_return_sbyte16 s16.f14: got %d but expected %d\n", s16.f14, 14);
6183         }
6184         if (s16.f15 != 15) {
6185                 fprintf(stderr, "mono_return_sbyte16 s16.f15: got %d but expected %d\n", s16.f15, 15);
6186         }
6187         if (s16.f16 != 16) {
6188                 fprintf(stderr, "mono_return_sbyte16 s16.f16: got %d but expected %d\n", s16.f16, 16);
6189         }
6190         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; 
6191         return s16;
6192 }
6193
6194 typedef struct {
6195         char f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17;
6196 } sbyte17;
6197
6198 LIBTEST_API sbyte17 STDCALL
6199 mono_return_sbyte17 (sbyte17 s17, int addend) {
6200         if (s17.f1 != 1) {
6201                 fprintf(stderr, "mono_return_sbyte17 s17.f1: got %d but expected %d\n", s17.f1, 1);
6202         }
6203         if (s17.f2 != 2) {
6204                 fprintf(stderr, "mono_return_sbyte17 s17.f2: got %d but expected %d\n", s17.f2, 2);
6205         }
6206         if (s17.f3 != 3) {
6207                 fprintf(stderr, "mono_return_sbyte17 s17.f3: got %d but expected %d\n", s17.f3, 3);
6208         }
6209         if (s17.f4 != 4) {
6210                 fprintf(stderr, "mono_return_sbyte17 s17.f4: got %d but expected %d\n", s17.f4, 4);
6211         }
6212         if (s17.f5 != 5) {
6213                 fprintf(stderr, "mono_return_sbyte17 s17.f5: got %d but expected %d\n", s17.f5, 5);
6214         }
6215         if (s17.f6 != 6) {
6216                 fprintf(stderr, "mono_return_sbyte17 s17.f6: got %d but expected %d\n", s17.f6, 6);
6217         }
6218         if (s17.f7 != 7) {
6219                 fprintf(stderr, "mono_return_sbyte17 s17.f7: got %d but expected %d\n", s17.f7, 7);
6220         }
6221         if (s17.f8 != 8) {
6222                 fprintf(stderr, "mono_return_sbyte17 s17.f8: got %d but expected %d\n", s17.f8, 8);
6223         }
6224         if (s17.f9 != 9) {
6225                 fprintf(stderr, "mono_return_sbyte17 s17.f9: got %d but expected %d\n", s17.f9, 9);
6226         }
6227         if (s17.f10 != 10) {
6228                 fprintf(stderr, "mono_return_sbyte17 s17.f10: got %d but expected %d\n", s17.f10, 10);
6229         }
6230         if (s17.f11 != 11) {
6231                 fprintf(stderr, "mono_return_sbyte17 s17.f11: got %d but expected %d\n", s17.f11, 11);
6232         }
6233         if (s17.f12 != 12) {
6234                 fprintf(stderr, "mono_return_sbyte17 s17.f12: got %d but expected %d\n", s17.f12, 12);
6235         }
6236         if (s17.f13 != 13) {
6237                 fprintf(stderr, "mono_return_sbyte17 s17.f13: got %d but expected %d\n", s17.f13, 13);
6238         }
6239         if (s17.f14 != 14) {
6240                 fprintf(stderr, "mono_return_sbyte17 s17.f14: got %d but expected %d\n", s17.f14, 14);
6241         }
6242         if (s17.f15 != 15) {
6243                 fprintf(stderr, "mono_return_sbyte17 s17.f15: got %d but expected %d\n", s17.f15, 15);
6244         }
6245         if (s17.f16 != 16) {
6246                 fprintf(stderr, "mono_return_sbyte17 s17.f16: got %d but expected %d\n", s17.f16, 16);
6247         }
6248         if (s17.f17 != 17) {
6249                 fprintf(stderr, "mono_return_sbyte17 s17.f17: got %d but expected %d\n", s17.f17, 17);
6250         }
6251         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; 
6252         return s17;
6253 }
6254
6255 typedef struct {
6256         struct {
6257                 char f1;
6258         } nested1;
6259         char f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15;
6260         struct {
6261                 char f16;
6262         } nested2;
6263 } sbyte16_nested;
6264
6265 LIBTEST_API sbyte16_nested STDCALL
6266 mono_return_sbyte16_nested (sbyte16_nested sn16, int addend) {
6267         if (sn16.nested1.f1 != 1) {
6268                 fprintf(stderr, "mono_return_sbyte16_nested sn16.nested1.f1: got %d but expected %d\n", sn16.nested1.f1, 1);
6269         }
6270         if (sn16.f2 != 2) {
6271                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f2: got %d but expected %d\n", sn16.f2, 2);
6272         }
6273         if (sn16.f3 != 3) {
6274                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f3: got %d but expected %d\n", sn16.f3, 3);
6275         }
6276         if (sn16.f4 != 4) {
6277                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f4: got %d but expected %d\n", sn16.f4, 4);
6278         }
6279         if (sn16.f5 != 5) {
6280                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f5: got %d but expected %d\n", sn16.f5, 5);
6281         }
6282         if (sn16.f6 != 6) {
6283                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f6: got %d but expected %d\n", sn16.f6, 6);
6284         }
6285         if (sn16.f7 != 7) {
6286                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f7: got %d but expected %d\n", sn16.f7, 7);
6287         }
6288         if (sn16.f8 != 8) {
6289                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f8: got %d but expected %d\n", sn16.f8, 8);
6290         }
6291         if (sn16.f9 != 9) {
6292                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f9: got %d but expected %d\n", sn16.f9, 9);
6293         }
6294         if (sn16.f10 != 10) {
6295                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f10: got %d but expected %d\n", sn16.f10, 10);
6296         }
6297         if (sn16.f11 != 11) {
6298                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f11: got %d but expected %d\n", sn16.f11, 11);
6299         }
6300         if (sn16.f12 != 12) {
6301                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f12: got %d but expected %d\n", sn16.f12, 12);
6302         }
6303         if (sn16.f13 != 13) {
6304                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f13: got %d but expected %d\n", sn16.f13, 13);
6305         }
6306         if (sn16.f14 != 14) {
6307                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f14: got %d but expected %d\n", sn16.f14, 14);
6308         }
6309         if (sn16.f15 != 15) {
6310                 fprintf(stderr, "mono_return_sbyte16_nested sn16.f15: got %d but expected %d\n", sn16.f15, 15);
6311         }
6312         if (sn16.nested2.f16 != 16) {
6313                 fprintf(stderr, "mono_return_sbyte16_nested sn16.nested2.f16: got %d but expected %d\n", sn16.nested2.f16, 16);
6314         }
6315         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; 
6316         return sn16;
6317 }
6318
6319
6320 typedef struct {
6321         short f1;
6322 } short1;
6323
6324 LIBTEST_API short1 STDCALL
6325 mono_return_short1 (short1 s1, int addend) {
6326         if (s1.f1 != 1) {
6327                 fprintf(stderr, "mono_return_short1 s1.f1: got %d but expected %d\n", s1.f1, 1);
6328         }
6329         s1.f1+=addend; 
6330         return s1;
6331 }
6332
6333 typedef struct {
6334         short f1,f2;
6335 } short2;
6336
6337 LIBTEST_API short2 STDCALL
6338 mono_return_short2 (short2 s2, int addend) {
6339         if (s2.f1 != 1) {
6340                 fprintf(stderr, "mono_return_short2 s2.f1: got %d but expected %d\n", s2.f1, 1);
6341         }
6342         if (s2.f2 != 2) {
6343                 fprintf(stderr, "mono_return_short2 s2.f2: got %d but expected %d\n", s2.f2, 2);
6344         }
6345         s2.f1+=addend; s2.f2+=addend; 
6346         return s2;
6347 }
6348
6349 typedef struct {
6350         short f1,f2,f3;
6351 } short3;
6352
6353 LIBTEST_API short3 STDCALL
6354 mono_return_short3 (short3 s3, int addend) {
6355         if (s3.f1 != 1) {
6356                 fprintf(stderr, "mono_return_short3 s3.f1: got %d but expected %d\n", s3.f1, 1);
6357         }
6358         if (s3.f2 != 2) {
6359                 fprintf(stderr, "mono_return_short3 s3.f2: got %d but expected %d\n", s3.f2, 2);
6360         }
6361         if (s3.f3 != 3) {
6362                 fprintf(stderr, "mono_return_short3 s3.f3: got %d but expected %d\n", s3.f3, 3);
6363         }
6364         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6365         return s3;
6366 }
6367
6368 typedef struct {
6369         short f1,f2,f3,f4;
6370 } short4;
6371
6372 LIBTEST_API short4 STDCALL
6373 mono_return_short4 (short4 s4, int addend) {
6374         if (s4.f1 != 1) {
6375                 fprintf(stderr, "mono_return_short4 s4.f1: got %d but expected %d\n", s4.f1, 1);
6376         }
6377         if (s4.f2 != 2) {
6378                 fprintf(stderr, "mono_return_short4 s4.f2: got %d but expected %d\n", s4.f2, 2);
6379         }
6380         if (s4.f3 != 3) {
6381                 fprintf(stderr, "mono_return_short4 s4.f3: got %d but expected %d\n", s4.f3, 3);
6382         }
6383         if (s4.f4 != 4) {
6384                 fprintf(stderr, "mono_return_short4 s4.f4: got %d but expected %d\n", s4.f4, 4);
6385         }
6386         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6387         return s4;
6388 }
6389
6390 typedef struct {
6391         short f1,f2,f3,f4,f5;
6392 } short5;
6393
6394 LIBTEST_API short5 STDCALL
6395 mono_return_short5 (short5 s5, int addend) {
6396         if (s5.f1 != 1) {
6397                 fprintf(stderr, "mono_return_short5 s5.f1: got %d but expected %d\n", s5.f1, 1);
6398         }
6399         if (s5.f2 != 2) {
6400                 fprintf(stderr, "mono_return_short5 s5.f2: got %d but expected %d\n", s5.f2, 2);
6401         }
6402         if (s5.f3 != 3) {
6403                 fprintf(stderr, "mono_return_short5 s5.f3: got %d but expected %d\n", s5.f3, 3);
6404         }
6405         if (s5.f4 != 4) {
6406                 fprintf(stderr, "mono_return_short5 s5.f4: got %d but expected %d\n", s5.f4, 4);
6407         }
6408         if (s5.f5 != 5) {
6409                 fprintf(stderr, "mono_return_short5 s5.f5: got %d but expected %d\n", s5.f5, 5);
6410         }
6411         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6412         return s5;
6413 }
6414
6415 typedef struct {
6416         short f1,f2,f3,f4,f5,f6;
6417 } short6;
6418
6419 LIBTEST_API short6 STDCALL
6420 mono_return_short6 (short6 s6, int addend) {
6421         if (s6.f1 != 1) {
6422                 fprintf(stderr, "mono_return_short6 s6.f1: got %d but expected %d\n", s6.f1, 1);
6423         }
6424         if (s6.f2 != 2) {
6425                 fprintf(stderr, "mono_return_short6 s6.f2: got %d but expected %d\n", s6.f2, 2);
6426         }
6427         if (s6.f3 != 3) {
6428                 fprintf(stderr, "mono_return_short6 s6.f3: got %d but expected %d\n", s6.f3, 3);
6429         }
6430         if (s6.f4 != 4) {
6431                 fprintf(stderr, "mono_return_short6 s6.f4: got %d but expected %d\n", s6.f4, 4);
6432         }
6433         if (s6.f5 != 5) {
6434                 fprintf(stderr, "mono_return_short6 s6.f5: got %d but expected %d\n", s6.f5, 5);
6435         }
6436         if (s6.f6 != 6) {
6437                 fprintf(stderr, "mono_return_short6 s6.f6: got %d but expected %d\n", s6.f6, 6);
6438         }
6439         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
6440         return s6;
6441 }
6442
6443 typedef struct {
6444         short f1,f2,f3,f4,f5,f6,f7;
6445 } short7;
6446
6447 LIBTEST_API short7 STDCALL
6448 mono_return_short7 (short7 s7, int addend) {
6449         if (s7.f1 != 1) {
6450                 fprintf(stderr, "mono_return_short7 s7.f1: got %d but expected %d\n", s7.f1, 1);
6451         }
6452         if (s7.f2 != 2) {
6453                 fprintf(stderr, "mono_return_short7 s7.f2: got %d but expected %d\n", s7.f2, 2);
6454         }
6455         if (s7.f3 != 3) {
6456                 fprintf(stderr, "mono_return_short7 s7.f3: got %d but expected %d\n", s7.f3, 3);
6457         }
6458         if (s7.f4 != 4) {
6459                 fprintf(stderr, "mono_return_short7 s7.f4: got %d but expected %d\n", s7.f4, 4);
6460         }
6461         if (s7.f5 != 5) {
6462                 fprintf(stderr, "mono_return_short7 s7.f5: got %d but expected %d\n", s7.f5, 5);
6463         }
6464         if (s7.f6 != 6) {
6465                 fprintf(stderr, "mono_return_short7 s7.f6: got %d but expected %d\n", s7.f6, 6);
6466         }
6467         if (s7.f7 != 7) {
6468                 fprintf(stderr, "mono_return_short7 s7.f7: got %d but expected %d\n", s7.f7, 7);
6469         }
6470         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
6471         return s7;
6472 }
6473
6474 typedef struct {
6475         short f1,f2,f3,f4,f5,f6,f7,f8;
6476 } short8;
6477
6478 LIBTEST_API short8 STDCALL
6479 mono_return_short8 (short8 s8, int addend) {
6480         if (s8.f1 != 1) {
6481                 fprintf(stderr, "mono_return_short8 s8.f1: got %d but expected %d\n", s8.f1, 1);
6482         }
6483         if (s8.f2 != 2) {
6484                 fprintf(stderr, "mono_return_short8 s8.f2: got %d but expected %d\n", s8.f2, 2);
6485         }
6486         if (s8.f3 != 3) {
6487                 fprintf(stderr, "mono_return_short8 s8.f3: got %d but expected %d\n", s8.f3, 3);
6488         }
6489         if (s8.f4 != 4) {
6490                 fprintf(stderr, "mono_return_short8 s8.f4: got %d but expected %d\n", s8.f4, 4);
6491         }
6492         if (s8.f5 != 5) {
6493                 fprintf(stderr, "mono_return_short8 s8.f5: got %d but expected %d\n", s8.f5, 5);
6494         }
6495         if (s8.f6 != 6) {
6496                 fprintf(stderr, "mono_return_short8 s8.f6: got %d but expected %d\n", s8.f6, 6);
6497         }
6498         if (s8.f7 != 7) {
6499                 fprintf(stderr, "mono_return_short8 s8.f7: got %d but expected %d\n", s8.f7, 7);
6500         }
6501         if (s8.f8 != 8) {
6502                 fprintf(stderr, "mono_return_short8 s8.f8: got %d but expected %d\n", s8.f8, 8);
6503         }
6504         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
6505         return s8;
6506 }
6507
6508 typedef struct {
6509         short f1,f2,f3,f4,f5,f6,f7,f8,f9;
6510 } short9;
6511
6512 LIBTEST_API short9 STDCALL
6513 mono_return_short9 (short9 s9, int addend) {
6514         if (s9.f1 != 1) {
6515                 fprintf(stderr, "mono_return_short9 s9.f1: got %d but expected %d\n", s9.f1, 1);
6516         }
6517         if (s9.f2 != 2) {
6518                 fprintf(stderr, "mono_return_short9 s9.f2: got %d but expected %d\n", s9.f2, 2);
6519         }
6520         if (s9.f3 != 3) {
6521                 fprintf(stderr, "mono_return_short9 s9.f3: got %d but expected %d\n", s9.f3, 3);
6522         }
6523         if (s9.f4 != 4) {
6524                 fprintf(stderr, "mono_return_short9 s9.f4: got %d but expected %d\n", s9.f4, 4);
6525         }
6526         if (s9.f5 != 5) {
6527                 fprintf(stderr, "mono_return_short9 s9.f5: got %d but expected %d\n", s9.f5, 5);
6528         }
6529         if (s9.f6 != 6) {
6530                 fprintf(stderr, "mono_return_short9 s9.f6: got %d but expected %d\n", s9.f6, 6);
6531         }
6532         if (s9.f7 != 7) {
6533                 fprintf(stderr, "mono_return_short9 s9.f7: got %d but expected %d\n", s9.f7, 7);
6534         }
6535         if (s9.f8 != 8) {
6536                 fprintf(stderr, "mono_return_short9 s9.f8: got %d but expected %d\n", s9.f8, 8);
6537         }
6538         if (s9.f9 != 9) {
6539                 fprintf(stderr, "mono_return_short9 s9.f9: got %d but expected %d\n", s9.f9, 9);
6540         }
6541         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; 
6542         return s9;
6543 }
6544
6545 typedef struct {
6546         struct {
6547                 short f1;
6548         } nested1;
6549         short f2,f3,f4,f5,f6,f7;
6550         struct {
6551                 short f8;
6552         } nested2;
6553 } short8_nested;
6554
6555 LIBTEST_API short8_nested STDCALL
6556 mono_return_short8_nested (short8_nested sn8, int addend) {
6557         if (sn8.nested1.f1 != 1) {
6558                 fprintf(stderr, "mono_return_short8_nested sn8.nested1.f1: got %d but expected %d\n", sn8.nested1.f1, 1);
6559         }
6560         if (sn8.f2 != 2) {
6561                 fprintf(stderr, "mono_return_short8_nested sn8.f2: got %d but expected %d\n", sn8.f2, 2);
6562         }
6563         if (sn8.f3 != 3) {
6564                 fprintf(stderr, "mono_return_short8_nested sn8.f3: got %d but expected %d\n", sn8.f3, 3);
6565         }
6566         if (sn8.f4 != 4) {
6567                 fprintf(stderr, "mono_return_short8_nested sn8.f4: got %d but expected %d\n", sn8.f4, 4);
6568         }
6569         if (sn8.f5 != 5) {
6570                 fprintf(stderr, "mono_return_short8_nested sn8.f5: got %d but expected %d\n", sn8.f5, 5);
6571         }
6572         if (sn8.f6 != 6) {
6573                 fprintf(stderr, "mono_return_short8_nested sn8.f6: got %d but expected %d\n", sn8.f6, 6);
6574         }
6575         if (sn8.f7 != 7) {
6576                 fprintf(stderr, "mono_return_short8_nested sn8.f7: got %d but expected %d\n", sn8.f7, 7);
6577         }
6578         if (sn8.nested2.f8 != 8) {
6579                 fprintf(stderr, "mono_return_short8_nested sn8.nested2.f8: got %d but expected %d\n", sn8.nested2.f8, 8);
6580         }
6581         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; 
6582         return sn8;
6583 }
6584
6585
6586 typedef struct {
6587         int f1;
6588 } int1;
6589
6590 LIBTEST_API int1 STDCALL
6591 mono_return_int1 (int1 s1, int addend) {
6592         if (s1.f1 != 1) {
6593                 fprintf(stderr, "mono_return_int1 s1.f1: got %d but expected %d\n", s1.f1, 1);
6594         }
6595         s1.f1+=addend; 
6596         return s1;
6597 }
6598
6599 typedef struct {
6600         int f1,f2;
6601 } int2;
6602
6603 LIBTEST_API int2 STDCALL
6604 mono_return_int2 (int2 s2, int addend) {
6605         if (s2.f1 != 1) {
6606                 fprintf(stderr, "mono_return_int2 s2.f1: got %d but expected %d\n", s2.f1, 1);
6607         }
6608         if (s2.f2 != 2) {
6609                 fprintf(stderr, "mono_return_int2 s2.f2: got %d but expected %d\n", s2.f2, 2);
6610         }
6611         s2.f1+=addend; s2.f2+=addend; 
6612         return s2;
6613 }
6614
6615 typedef struct {
6616         int f1,f2,f3;
6617 } int3;
6618
6619 LIBTEST_API int3 STDCALL
6620 mono_return_int3 (int3 s3, int addend) {
6621         if (s3.f1 != 1) {
6622                 fprintf(stderr, "mono_return_int3 s3.f1: got %d but expected %d\n", s3.f1, 1);
6623         }
6624         if (s3.f2 != 2) {
6625                 fprintf(stderr, "mono_return_int3 s3.f2: got %d but expected %d\n", s3.f2, 2);
6626         }
6627         if (s3.f3 != 3) {
6628                 fprintf(stderr, "mono_return_int3 s3.f3: got %d but expected %d\n", s3.f3, 3);
6629         }
6630         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6631         return s3;
6632 }
6633
6634 typedef struct {
6635         int f1,f2,f3,f4;
6636 } int4;
6637
6638 LIBTEST_API int4 STDCALL
6639 mono_return_int4 (int4 s4, int addend) {
6640         if (s4.f1 != 1) {
6641                 fprintf(stderr, "mono_return_int4 s4.f1: got %d but expected %d\n", s4.f1, 1);
6642         }
6643         if (s4.f2 != 2) {
6644                 fprintf(stderr, "mono_return_int4 s4.f2: got %d but expected %d\n", s4.f2, 2);
6645         }
6646         if (s4.f3 != 3) {
6647                 fprintf(stderr, "mono_return_int4 s4.f3: got %d but expected %d\n", s4.f3, 3);
6648         }
6649         if (s4.f4 != 4) {
6650                 fprintf(stderr, "mono_return_int4 s4.f4: got %d but expected %d\n", s4.f4, 4);
6651         }
6652         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6653         return s4;
6654 }
6655
6656 typedef struct {
6657         int f1,f2,f3,f4,f5;
6658 } int5;
6659
6660 LIBTEST_API int5 STDCALL
6661 mono_return_int5 (int5 s5, int addend) {
6662         if (s5.f1 != 1) {
6663                 fprintf(stderr, "mono_return_int5 s5.f1: got %d but expected %d\n", s5.f1, 1);
6664         }
6665         if (s5.f2 != 2) {
6666                 fprintf(stderr, "mono_return_int5 s5.f2: got %d but expected %d\n", s5.f2, 2);
6667         }
6668         if (s5.f3 != 3) {
6669                 fprintf(stderr, "mono_return_int5 s5.f3: got %d but expected %d\n", s5.f3, 3);
6670         }
6671         if (s5.f4 != 4) {
6672                 fprintf(stderr, "mono_return_int5 s5.f4: got %d but expected %d\n", s5.f4, 4);
6673         }
6674         if (s5.f5 != 5) {
6675                 fprintf(stderr, "mono_return_int5 s5.f5: got %d but expected %d\n", s5.f5, 5);
6676         }
6677         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6678         return s5;
6679 }
6680
6681 typedef struct {
6682         struct {
6683                 int f1;
6684         } nested1;
6685         int f2,f3;
6686         struct {
6687                 int f4;
6688         } nested2;
6689 } int4_nested;
6690
6691 LIBTEST_API int4_nested STDCALL
6692 mono_return_int4_nested (int4_nested sn4, int addend) {
6693         if (sn4.nested1.f1 != 1) {
6694                 fprintf(stderr, "mono_return_int4_nested sn4.nested1.f1: got %d but expected %d\n", sn4.nested1.f1, 1);
6695         }
6696         if (sn4.f2 != 2) {
6697                 fprintf(stderr, "mono_return_int4_nested sn4.f2: got %d but expected %d\n", sn4.f2, 2);
6698         }
6699         if (sn4.f3 != 3) {
6700                 fprintf(stderr, "mono_return_int4_nested sn4.f3: got %d but expected %d\n", sn4.f3, 3);
6701         }
6702         if (sn4.nested2.f4 != 4) {
6703                 fprintf(stderr, "mono_return_int4_nested sn4.nested2.f4: got %d but expected %d\n", sn4.nested2.f4, 4);
6704         }
6705         sn4.nested1.f1+=addend; sn4.f2+=addend; sn4.f3+=addend; sn4.nested2.f4+=addend; 
6706         return sn4;
6707 }
6708
6709 typedef struct {
6710         float f1;
6711 } float1;
6712
6713 LIBTEST_API float1 STDCALL
6714 mono_return_float1 (float1 s1, int addend) {
6715         if (s1.f1 != 1) {
6716                 fprintf(stderr, "mono_return_float1 s1.f1: got %f but expected %d\n", s1.f1, 1);
6717         }
6718         s1.f1+=addend; 
6719         return s1;
6720 }
6721
6722 typedef struct {
6723         float f1,f2;
6724 } float2;
6725
6726 LIBTEST_API float2 STDCALL
6727 mono_return_float2 (float2 s2, int addend) {
6728         if (s2.f1 != 1) {
6729                 fprintf(stderr, "mono_return_float2 s2.f1: got %f but expected %d\n", s2.f1, 1);
6730         }
6731         if (s2.f2 != 2) {
6732                 fprintf(stderr, "mono_return_float2 s2.f2: got %f but expected %d\n", s2.f2, 2);
6733         }
6734         s2.f1+=addend; s2.f2+=addend; 
6735         return s2;
6736 }
6737
6738 typedef struct {
6739         float f1,f2,f3;
6740 } float3;
6741
6742 LIBTEST_API float3 STDCALL
6743 mono_return_float3 (float3 s3, int addend) {
6744         if (s3.f1 != 1) {
6745                 fprintf(stderr, "mono_return_float3 s3.f1: got %f but expected %d\n", s3.f1, 1);
6746         }
6747         if (s3.f2 != 2) {
6748                 fprintf(stderr, "mono_return_float3 s3.f2: got %f but expected %d\n", s3.f2, 2);
6749         }
6750         if (s3.f3 != 3) {
6751                 fprintf(stderr, "mono_return_float3 s3.f3: got %f but expected %d\n", s3.f3, 3);
6752         }
6753         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
6754         return s3;
6755 }
6756
6757 typedef struct {
6758         float f1,f2,f3,f4;
6759 } float4;
6760
6761 LIBTEST_API float4 STDCALL
6762 mono_return_float4 (float4 s4, int addend) {
6763         if (s4.f1 != 1) {
6764                 fprintf(stderr, "mono_return_float4 s4.f1: got %f but expected %d\n", s4.f1, 1);
6765         }
6766         if (s4.f2 != 2) {
6767                 fprintf(stderr, "mono_return_float4 s4.f2: got %f but expected %d\n", s4.f2, 2);
6768         }
6769         if (s4.f3 != 3) {
6770                 fprintf(stderr, "mono_return_float4 s4.f3: got %f but expected %d\n", s4.f3, 3);
6771         }
6772         if (s4.f4 != 4) {
6773                 fprintf(stderr, "mono_return_float4 s4.f4: got %f but expected %d\n", s4.f4, 4);
6774         }
6775         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
6776         return s4;
6777 }
6778
6779 typedef struct {
6780         float f1,f2,f3,f4,f5;
6781 } float5;
6782
6783 LIBTEST_API float5 STDCALL
6784 mono_return_float5 (float5 s5, int addend) {
6785         if (s5.f1 != 1) {
6786                 fprintf(stderr, "mono_return_float5 s5.f1: got %f but expected %d\n", s5.f1, 1);
6787         }
6788         if (s5.f2 != 2) {
6789                 fprintf(stderr, "mono_return_float5 s5.f2: got %f but expected %d\n", s5.f2, 2);
6790         }
6791         if (s5.f3 != 3) {
6792                 fprintf(stderr, "mono_return_float5 s5.f3: got %f but expected %d\n", s5.f3, 3);
6793         }
6794         if (s5.f4 != 4) {
6795                 fprintf(stderr, "mono_return_float5 s5.f4: got %f but expected %d\n", s5.f4, 4);
6796         }
6797         if (s5.f5 != 5) {
6798                 fprintf(stderr, "mono_return_float5 s5.f5: got %f but expected %d\n", s5.f5, 5);
6799         }
6800         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
6801         return s5;
6802 }
6803
6804 typedef struct {
6805         float f1,f2,f3,f4,f5,f6;
6806 } float6;
6807
6808 LIBTEST_API float6 STDCALL
6809 mono_return_float6 (float6 s6, int addend) {
6810         if (s6.f1 != 1) {
6811                 fprintf(stderr, "mono_return_float6 s6.f1: got %f but expected %d\n", s6.f1, 1);
6812         }
6813         if (s6.f2 != 2) {
6814                 fprintf(stderr, "mono_return_float6 s6.f2: got %f but expected %d\n", s6.f2, 2);
6815         }
6816         if (s6.f3 != 3) {
6817                 fprintf(stderr, "mono_return_float6 s6.f3: got %f but expected %d\n", s6.f3, 3);
6818         }
6819         if (s6.f4 != 4) {
6820                 fprintf(stderr, "mono_return_float6 s6.f4: got %f but expected %d\n", s6.f4, 4);
6821         }
6822         if (s6.f5 != 5) {
6823                 fprintf(stderr, "mono_return_float6 s6.f5: got %f but expected %d\n", s6.f5, 5);
6824         }
6825         if (s6.f6 != 6) {
6826                 fprintf(stderr, "mono_return_float6 s6.f6: got %f but expected %d\n", s6.f6, 6);
6827         }
6828         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
6829         return s6;
6830 }
6831
6832 typedef struct {
6833         float f1,f2,f3,f4,f5,f6,f7;
6834 } float7;
6835
6836 LIBTEST_API float7 STDCALL
6837 mono_return_float7 (float7 s7, int addend) {
6838         if (s7.f1 != 1) {
6839                 fprintf(stderr, "mono_return_float7 s7.f1: got %f but expected %d\n", s7.f1, 1);
6840         }
6841         if (s7.f2 != 2) {
6842                 fprintf(stderr, "mono_return_float7 s7.f2: got %f but expected %d\n", s7.f2, 2);
6843         }
6844         if (s7.f3 != 3) {
6845                 fprintf(stderr, "mono_return_float7 s7.f3: got %f but expected %d\n", s7.f3, 3);
6846         }
6847         if (s7.f4 != 4) {
6848                 fprintf(stderr, "mono_return_float7 s7.f4: got %f but expected %d\n", s7.f4, 4);
6849         }
6850         if (s7.f5 != 5) {
6851                 fprintf(stderr, "mono_return_float7 s7.f5: got %f but expected %d\n", s7.f5, 5);
6852         }
6853         if (s7.f6 != 6) {
6854                 fprintf(stderr, "mono_return_float7 s7.f6: got %f but expected %d\n", s7.f6, 6);
6855         }
6856         if (s7.f7 != 7) {
6857                 fprintf(stderr, "mono_return_float7 s7.f7: got %f but expected %d\n", s7.f7, 7);
6858         }
6859         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
6860         return s7;
6861 }
6862
6863 typedef struct {
6864         float f1,f2,f3,f4,f5,f6,f7,f8;
6865 } float8;
6866
6867 LIBTEST_API float8 STDCALL
6868 mono_return_float8 (float8 s8, int addend) {
6869         if (s8.f1 != 1) {
6870                 fprintf(stderr, "mono_return_float8 s8.f1: got %f but expected %d\n", s8.f1, 1);
6871         }
6872         if (s8.f2 != 2) {
6873                 fprintf(stderr, "mono_return_float8 s8.f2: got %f but expected %d\n", s8.f2, 2);
6874         }
6875         if (s8.f3 != 3) {
6876                 fprintf(stderr, "mono_return_float8 s8.f3: got %f but expected %d\n", s8.f3, 3);
6877         }
6878         if (s8.f4 != 4) {
6879                 fprintf(stderr, "mono_return_float8 s8.f4: got %f but expected %d\n", s8.f4, 4);
6880         }
6881         if (s8.f5 != 5) {
6882                 fprintf(stderr, "mono_return_float8 s8.f5: got %f but expected %d\n", s8.f5, 5);
6883         }
6884         if (s8.f6 != 6) {
6885                 fprintf(stderr, "mono_return_float8 s8.f6: got %f but expected %d\n", s8.f6, 6);
6886         }
6887         if (s8.f7 != 7) {
6888                 fprintf(stderr, "mono_return_float8 s8.f7: got %f but expected %d\n", s8.f7, 7);
6889         }
6890         if (s8.f8 != 8) {
6891                 fprintf(stderr, "mono_return_float8 s8.f8: got %f but expected %d\n", s8.f8, 8);
6892         }
6893         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
6894         return s8;
6895 }
6896
6897 typedef struct {
6898         float f1,f2,f3,f4,f5,f6,f7,f8,f9;
6899 } float9;
6900
6901 LIBTEST_API float9 STDCALL
6902 mono_return_float9 (float9 s9, int addend) {
6903         if (s9.f1 != 1) {
6904                 fprintf(stderr, "mono_return_float9 s9.f1: got %f but expected %d\n", s9.f1, 1);
6905         }
6906         if (s9.f2 != 2) {
6907                 fprintf(stderr, "mono_return_float9 s9.f2: got %f but expected %d\n", s9.f2, 2);
6908         }
6909         if (s9.f3 != 3) {
6910                 fprintf(stderr, "mono_return_float9 s9.f3: got %f but expected %d\n", s9.f3, 3);
6911         }
6912         if (s9.f4 != 4) {
6913                 fprintf(stderr, "mono_return_float9 s9.f4: got %f but expected %d\n", s9.f4, 4);
6914         }
6915         if (s9.f5 != 5) {
6916                 fprintf(stderr, "mono_return_float9 s9.f5: got %f but expected %d\n", s9.f5, 5);
6917         }
6918         if (s9.f6 != 6) {
6919                 fprintf(stderr, "mono_return_float9 s9.f6: got %f but expected %d\n", s9.f6, 6);
6920         }
6921         if (s9.f7 != 7) {
6922                 fprintf(stderr, "mono_return_float9 s9.f7: got %f but expected %d\n", s9.f7, 7);
6923         }
6924         if (s9.f8 != 8) {
6925                 fprintf(stderr, "mono_return_float9 s9.f8: got %f but expected %d\n", s9.f8, 8);
6926         }
6927         if (s9.f9 != 9) {
6928                 fprintf(stderr, "mono_return_float9 s9.f9: got %f but expected %d\n", s9.f9, 9);
6929         }
6930         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; 
6931         return s9;
6932 }
6933
6934 typedef struct {
6935         struct {
6936                 float f1;
6937         } nested1;
6938         float f2,f3;
6939         struct {
6940                 float f4;
6941         } nested2;
6942 } float4_nested;
6943
6944 LIBTEST_API float4_nested STDCALL
6945 mono_return_float4_nested (float4_nested sn4, int addend) {
6946         if (sn4.nested1.f1 != 1) {
6947                 fprintf(stderr, "mono_return_float4_nested sn4.nested1.f1: got %f but expected %d\n", sn4.nested1.f1, 1);
6948         }
6949         if (sn4.f2 != 2) {
6950                 fprintf(stderr, "mono_return_float4_nested sn4.f2: got %f but expected %d\n", sn4.f2, 2);
6951         }
6952         if (sn4.f3 != 3) {
6953                 fprintf(stderr, "mono_return_float4_nested sn4.f3: got %f but expected %d\n", sn4.f3, 3);
6954         }
6955         if (sn4.nested2.f4 != 4) {
6956                 fprintf(stderr, "mono_return_float4_nested sn4.nested2.f4: got %f but expected %d\n", sn4.nested2.f4, 4);
6957         }
6958         sn4.nested1.f1+=addend; sn4.f2+=addend; sn4.f3+=addend; sn4.nested2.f4+=addend; 
6959         return sn4;
6960 }
6961
6962 typedef struct {
6963         double f1;
6964 } double1;
6965
6966 LIBTEST_API double1 STDCALL
6967 mono_return_double1 (double1 s1, int addend) {
6968         if (s1.f1 != 1) {
6969                 fprintf(stderr, "mono_return_double1 s1.f1: got %f but expected %d\n", s1.f1, 1);
6970         }
6971         s1.f1+=addend; 
6972         return s1;
6973 }
6974
6975 typedef struct {
6976         double f1,f2;
6977 } double2;
6978
6979 LIBTEST_API double2 STDCALL
6980 mono_return_double2 (double2 s2, int addend) {
6981         if (s2.f1 != 1) {
6982                 fprintf(stderr, "mono_return_double2 s2.f1: got %f but expected %d\n", s2.f1, 1);
6983         }
6984         if (s2.f2 != 2) {
6985                 fprintf(stderr, "mono_return_double2 s2.f2: got %f but expected %d\n", s2.f2, 2);
6986         }
6987         s2.f1+=addend; s2.f2+=addend; 
6988         return s2;
6989 }
6990
6991 typedef struct {
6992         double f1,f2,f3;
6993 } double3;
6994
6995 LIBTEST_API double3 STDCALL
6996 mono_return_double3 (double3 s3, int addend) {
6997         if (s3.f1 != 1) {
6998                 fprintf(stderr, "mono_return_double3 s3.f1: got %f but expected %d\n", s3.f1, 1);
6999         }
7000         if (s3.f2 != 2) {
7001                 fprintf(stderr, "mono_return_double3 s3.f2: got %f but expected %d\n", s3.f2, 2);
7002         }
7003         if (s3.f3 != 3) {
7004                 fprintf(stderr, "mono_return_double3 s3.f3: got %f but expected %d\n", s3.f3, 3);
7005         }
7006         s3.f1+=addend; s3.f2+=addend; s3.f3+=addend; 
7007         return s3;
7008 }
7009
7010 typedef struct {
7011         double f1,f2,f3,f4;
7012 } double4;
7013
7014 LIBTEST_API double4 STDCALL
7015 mono_return_double4 (double4 s4, int addend) {
7016         if (s4.f1 != 1) {
7017                 fprintf(stderr, "mono_return_double4 s4.f1: got %f but expected %d\n", s4.f1, 1);
7018         }
7019         if (s4.f2 != 2) {
7020                 fprintf(stderr, "mono_return_double4 s4.f2: got %f but expected %d\n", s4.f2, 2);
7021         }
7022         if (s4.f3 != 3) {
7023                 fprintf(stderr, "mono_return_double4 s4.f3: got %f but expected %d\n", s4.f3, 3);
7024         }
7025         if (s4.f4 != 4) {
7026                 fprintf(stderr, "mono_return_double4 s4.f4: got %f but expected %d\n", s4.f4, 4);
7027         }
7028         s4.f1+=addend; s4.f2+=addend; s4.f3+=addend; s4.f4+=addend; 
7029         return s4;
7030 }
7031
7032 typedef struct {
7033         double f1,f2,f3,f4,f5;
7034 } double5;
7035
7036 LIBTEST_API double5 STDCALL
7037 mono_return_double5 (double5 s5, int addend) {
7038         if (s5.f1 != 1) {
7039                 fprintf(stderr, "mono_return_double5 s5.f1: got %f but expected %d\n", s5.f1, 1);
7040         }
7041         if (s5.f2 != 2) {
7042                 fprintf(stderr, "mono_return_double5 s5.f2: got %f but expected %d\n", s5.f2, 2);
7043         }
7044         if (s5.f3 != 3) {
7045                 fprintf(stderr, "mono_return_double5 s5.f3: got %f but expected %d\n", s5.f3, 3);
7046         }
7047         if (s5.f4 != 4) {
7048                 fprintf(stderr, "mono_return_double5 s5.f4: got %f but expected %d\n", s5.f4, 4);
7049         }
7050         if (s5.f5 != 5) {
7051                 fprintf(stderr, "mono_return_double5 s5.f5: got %f but expected %d\n", s5.f5, 5);
7052         }
7053         s5.f1+=addend; s5.f2+=addend; s5.f3+=addend; s5.f4+=addend; s5.f5+=addend; 
7054         return s5;
7055 }
7056
7057 typedef struct {
7058         double f1,f2,f3,f4,f5,f6;
7059 } double6;
7060
7061 LIBTEST_API double6 STDCALL
7062 mono_return_double6 (double6 s6, int addend) {
7063         if (s6.f1 != 1) {
7064                 fprintf(stderr, "mono_return_double6 s6.f1: got %f but expected %d\n", s6.f1, 1);
7065         }
7066         if (s6.f2 != 2) {
7067                 fprintf(stderr, "mono_return_double6 s6.f2: got %f but expected %d\n", s6.f2, 2);
7068         }
7069         if (s6.f3 != 3) {
7070                 fprintf(stderr, "mono_return_double6 s6.f3: got %f but expected %d\n", s6.f3, 3);
7071         }
7072         if (s6.f4 != 4) {
7073                 fprintf(stderr, "mono_return_double6 s6.f4: got %f but expected %d\n", s6.f4, 4);
7074         }
7075         if (s6.f5 != 5) {
7076                 fprintf(stderr, "mono_return_double6 s6.f5: got %f but expected %d\n", s6.f5, 5);
7077         }
7078         if (s6.f6 != 6) {
7079                 fprintf(stderr, "mono_return_double6 s6.f6: got %f but expected %d\n", s6.f6, 6);
7080         }
7081         s6.f1+=addend; s6.f2+=addend; s6.f3+=addend; s6.f4+=addend; s6.f5+=addend; s6.f6+=addend; 
7082         return s6;
7083 }
7084
7085 typedef struct {
7086         double f1,f2,f3,f4,f5,f6,f7;
7087 } double7;
7088
7089 LIBTEST_API double7 STDCALL
7090 mono_return_double7 (double7 s7, int addend) {
7091         if (s7.f1 != 1) {
7092                 fprintf(stderr, "mono_return_double7 s7.f1: got %f but expected %d\n", s7.f1, 1);
7093         }
7094         if (s7.f2 != 2) {
7095                 fprintf(stderr, "mono_return_double7 s7.f2: got %f but expected %d\n", s7.f2, 2);
7096         }
7097         if (s7.f3 != 3) {
7098                 fprintf(stderr, "mono_return_double7 s7.f3: got %f but expected %d\n", s7.f3, 3);
7099         }
7100         if (s7.f4 != 4) {
7101                 fprintf(stderr, "mono_return_double7 s7.f4: got %f but expected %d\n", s7.f4, 4);
7102         }
7103         if (s7.f5 != 5) {
7104                 fprintf(stderr, "mono_return_double7 s7.f5: got %f but expected %d\n", s7.f5, 5);
7105         }
7106         if (s7.f6 != 6) {
7107                 fprintf(stderr, "mono_return_double7 s7.f6: got %f but expected %d\n", s7.f6, 6);
7108         }
7109         if (s7.f7 != 7) {
7110                 fprintf(stderr, "mono_return_double7 s7.f7: got %f but expected %d\n", s7.f7, 7);
7111         }
7112         s7.f1+=addend; s7.f2+=addend; s7.f3+=addend; s7.f4+=addend; s7.f5+=addend; s7.f6+=addend; s7.f7+=addend; 
7113         return s7;
7114 }
7115
7116 typedef struct {
7117         double f1,f2,f3,f4,f5,f6,f7,f8;
7118 } double8;
7119
7120 LIBTEST_API double8 STDCALL
7121 mono_return_double8 (double8 s8, int addend) {
7122         if (s8.f1 != 1) {
7123                 fprintf(stderr, "mono_return_double8 s8.f1: got %f but expected %d\n", s8.f1, 1);
7124         }
7125         if (s8.f2 != 2) {
7126                 fprintf(stderr, "mono_return_double8 s8.f2: got %f but expected %d\n", s8.f2, 2);
7127         }
7128         if (s8.f3 != 3) {
7129                 fprintf(stderr, "mono_return_double8 s8.f3: got %f but expected %d\n", s8.f3, 3);
7130         }
7131         if (s8.f4 != 4) {
7132                 fprintf(stderr, "mono_return_double8 s8.f4: got %f but expected %d\n", s8.f4, 4);
7133         }
7134         if (s8.f5 != 5) {
7135                 fprintf(stderr, "mono_return_double8 s8.f5: got %f but expected %d\n", s8.f5, 5);
7136         }
7137         if (s8.f6 != 6) {
7138                 fprintf(stderr, "mono_return_double8 s8.f6: got %f but expected %d\n", s8.f6, 6);
7139         }
7140         if (s8.f7 != 7) {
7141                 fprintf(stderr, "mono_return_double8 s8.f7: got %f but expected %d\n", s8.f7, 7);
7142         }
7143         if (s8.f8 != 8) {
7144                 fprintf(stderr, "mono_return_double8 s8.f8: got %f but expected %d\n", s8.f8, 8);
7145         }
7146         s8.f1+=addend; s8.f2+=addend; s8.f3+=addend; s8.f4+=addend; s8.f5+=addend; s8.f6+=addend; s8.f7+=addend; s8.f8+=addend; 
7147         return s8;
7148 }
7149
7150 typedef struct {
7151         double f1,f2,f3,f4,f5,f6,f7,f8,f9;
7152 } double9;
7153
7154 LIBTEST_API double9 STDCALL
7155 mono_return_double9 (double9 s9, int addend) {
7156         if (s9.f1 != 1) {
7157                 fprintf(stderr, "mono_return_double9 s9.f1: got %f but expected %d\n", s9.f1, 1);
7158         }
7159         if (s9.f2 != 2) {
7160                 fprintf(stderr, "mono_return_double9 s9.f2: got %f but expected %d\n", s9.f2, 2);
7161         }
7162         if (s9.f3 != 3) {
7163                 fprintf(stderr, "mono_return_double9 s9.f3: got %f but expected %d\n", s9.f3, 3);
7164         }
7165         if (s9.f4 != 4) {
7166                 fprintf(stderr, "mono_return_double9 s9.f4: got %f but expected %d\n", s9.f4, 4);
7167         }
7168         if (s9.f5 != 5) {
7169                 fprintf(stderr, "mono_return_double9 s9.f5: got %f but expected %d\n", s9.f5, 5);
7170         }
7171         if (s9.f6 != 6) {
7172                 fprintf(stderr, "mono_return_double9 s9.f6: got %f but expected %d\n", s9.f6, 6);
7173         }
7174         if (s9.f7 != 7) {
7175                 fprintf(stderr, "mono_return_double9 s9.f7: got %f but expected %d\n", s9.f7, 7);
7176         }
7177         if (s9.f8 != 8) {
7178                 fprintf(stderr, "mono_return_double9 s9.f8: got %f but expected %d\n", s9.f8, 8);
7179         }
7180         if (s9.f9 != 9) {
7181                 fprintf(stderr, "mono_return_double9 s9.f9: got %f but expected %d\n", s9.f9, 9);
7182         }
7183         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; 
7184         return s9;
7185 }
7186
7187 typedef struct {
7188         struct {
7189                 double f1;
7190         } nested1;
7191         struct {
7192                 double f2;
7193         } nested2;
7194 } double2_nested;
7195
7196 LIBTEST_API double2_nested STDCALL
7197 mono_return_double2_nested (double2_nested sn2, int addend) {
7198         if (sn2.nested1.f1 != 1) {
7199                 fprintf(stderr, "mono_return_double2_nested sn2.nested1.f1: got %f but expected %d\n", sn2.nested1.f1, 1);
7200         }
7201         if (sn2.nested2.f2 != 2) {
7202                 fprintf(stderr, "mono_return_double2_nested sn2.nested2.f2: got %f but expected %d\n", sn2.nested2.f2, 2);
7203         }
7204         sn2.nested1.f1+=addend; sn2.nested2.f2+=addend; 
7205         return sn2;
7206 }
7207
7208
7209
7210 typedef struct {
7211         double f1[4];
7212 } double_array4;
7213
7214 LIBTEST_API double_array4 STDCALL
7215 mono_return_double_array4 (double_array4 sa4, int addend) {
7216         if (sa4.f1[0] != 1) {
7217                 fprintf(stderr, "mono_return_double_array4 sa4.f1[0]: got %f but expected %d\n", sa4.f1[0], 1);
7218         }
7219         if (sa4.f1[1] != 2) {
7220                 fprintf(stderr, "mono_return_double_array4 sa4.f1[1]: got %f but expected %d\n", sa4.f1[1], 2);
7221         }
7222         if (sa4.f1[2] != 3) {
7223                 fprintf(stderr, "mono_return_double_array4 sa4.f1[2]: got %f but expected %d\n", sa4.f1[2], 3);
7224         }
7225         if (sa4.f1[3] != 4) {
7226                 fprintf(stderr, "mono_return_double_array4 sa4.f1[3]: got %f but expected %d\n", sa4.f1[3], 4);
7227         }
7228         sa4.f1[0]+=addend; sa4.f1[1]+=addend; sa4.f1[2]+=addend; sa4.f1[3]+=addend; 
7229         return sa4;
7230 }
7231
7232 typedef struct {
7233         int array [3];
7234 } FixedArrayStruct;
7235
7236 LIBTEST_API int STDCALL
7237 mono_test_marshal_fixed_array (FixedArrayStruct s)
7238 {
7239         return s.array [0] + s.array [1] + s.array [2];
7240 }
7241
7242 typedef struct {
7243         char array [16];
7244         char c;
7245 } FixedBufferChar;
7246
7247 LIBTEST_API int STDCALL
7248 mono_test_marshal_fixed_buffer_char (FixedBufferChar *s)
7249 {
7250         if (!(s->array [0] == 'A' && s->array [1] == 'B' && s->array [2] == 'C' && s->c == 'D'))
7251                 return 1;
7252         s->array [0] = 'E';
7253         s->array [1] = 'F';
7254         s->c = 'G';
7255         return 0;
7256 }
7257
7258 typedef struct {
7259         short array [16];
7260         short c;
7261 } FixedBufferUnicode;
7262
7263 LIBTEST_API int STDCALL
7264 mono_test_marshal_fixed_buffer_unicode (FixedBufferUnicode *s)
7265 {
7266         if (!(s->array [0] == 'A' && s->array [1] == 'B' && s->array [2] == 'C' && s->c == 'D'))
7267                 return 1;
7268         s->array [0] = 'E';
7269         s->array [1] = 'F';
7270         s->c = 'G';
7271         return 0;
7272 }
7273
7274 const int NSTRINGS = 6;
7275 //test strings
7276 const char  *utf8Strings[] = {  
7277                                 "Managed",
7278                                  "Sîne klâwen durh die wolken sint geslagen" ,
7279                                  "काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम्",
7280                                  "我能吞下玻璃而不伤身体",
7281                                  "ღმერთსი შემვედრე,შემვედრე, ნუთუ კვლა დამხსნას შემვედრე,სოფლისა შემვედრე, შემვედრე,შემვედრე,შემვედრე,შრომასა, ცეცხლს, წყალსა და მიწასა, ჰაერთა თანა მრომასა; მომცნეს ფრთენი და აღვფრინდე, მივჰხვდე მას ჩემსა ნდომასა, დღისით და ღამით ვჰხედვიდე მზისა ელვათა კრთომაასაშემვედრე,შემვედრე,",
7282                                  "Τη γλώσσα μου έδωσαν ελληνική",
7283 "\0"
7284 };
7285
7286 LIBTEST_API char *
7287 build_return_string(const char* pReturn)
7288 {
7289         char *ret = 0;
7290         if (pReturn == 0 || *pReturn == 0)
7291                 return ret;
7292
7293         size_t strLength = strlen(pReturn);
7294         ret = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7295         memcpy(ret, pReturn, strLength);
7296         ret [strLength] = '\0';
7297         return ret;
7298 }
7299
7300 LIBTEST_API char *
7301 StringParameterInOut(/*[In,Out]*/ char *s, int index)
7302 {
7303         // return a copy
7304         return build_return_string(s);
7305 }
7306
7307 LIBTEST_API void
7308 StringParameterRefOut(/*out*/ char **s, int index)
7309 {
7310         char *pszTextutf8 = (char*)utf8Strings[index];
7311         size_t strLength = strlen(pszTextutf8);
7312         *s = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7313         memcpy(*s, pszTextutf8, strLength);
7314         (*s)[strLength] = '\0';
7315 }
7316
7317 LIBTEST_API void
7318 StringParameterRef(/*ref*/ char **s, int index)
7319 {
7320     char *pszTextutf8 = (char*)utf8Strings[index];
7321     size_t strLength = strlen(pszTextutf8);
7322     // do byte by byte validation of in string
7323     size_t szLen = strlen(*s);
7324     for (size_t i = 0; i < szLen; i++)
7325     {
7326         if ((*s)[i] != pszTextutf8[i])
7327         {
7328             printf("[in] managed string do not match native string\n");
7329             abort ();
7330         }
7331     }
7332
7333     if (*s)
7334     {
7335        marshal_free (*s);
7336     }
7337     // overwrite the orginal 
7338     *s = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7339     memcpy(*s, pszTextutf8, strLength);
7340     (*s)[strLength] = '\0';
7341 }
7342
7343 LIBTEST_API void
7344 StringBuilderParameterInOut(/*[In,Out] StringBuilder*/ char *s, int index)
7345 {
7346     // if string.empty 
7347     if (s == 0 || *s == 0)
7348         return;
7349
7350     char *pszTextutf8 = (char*)utf8Strings[index];
7351
7352     // do byte by byte validation of in string
7353     size_t szLen = strlen(s);
7354     for (size_t i = 0; i < szLen; i++) 
7355     {
7356         if (s[i] != pszTextutf8[i])
7357         {
7358             printf("[in] managed string do not match native string\n");
7359             abort ();
7360         }
7361     }  
7362
7363     // modify the string inplace 
7364     size_t outLen = strlen(pszTextutf8);
7365     for (size_t i = 0; i < outLen; i++) {
7366         s[i] = pszTextutf8[i];
7367     }
7368     s[outLen] = '\0';
7369 }
7370
7371 //out string builder
7372 LIBTEST_API void
7373 StringBuilderParameterOut(/*[Out] StringBuilder*/ char *s, int index)
7374 {
7375     char *pszTextutf8 = (char*)utf8Strings[index];
7376
7377     printf ("SBPO: Receiving %s\n", s);
7378     // modify the string inplace 
7379     size_t outLen = strlen(pszTextutf8);
7380     for (size_t i = 0; i < outLen; i++) {
7381         s[i] = pszTextutf8[i];
7382     }
7383     s[outLen] = '\0';
7384 }
7385
7386 LIBTEST_API char *
7387 StringParameterOut(/*[Out]*/ char *s, int index)
7388 {
7389     // return a copy
7390     return build_return_string(s);
7391 }
7392
7393 // Utf8 field
7394 typedef struct FieldWithUtf8
7395 {
7396     char *pFirst;
7397     int index;
7398 }FieldWithUtf8;
7399
7400 //utf8 struct field
7401 LIBTEST_API void
7402 TestStructWithUtf8Field(struct FieldWithUtf8 fieldStruct)
7403 {
7404     char *pszManagedutf8 = fieldStruct.pFirst;
7405     int stringIndex = fieldStruct.index;
7406     char *pszNative = 0;
7407     size_t outLen = 0;
7408
7409     if (pszManagedutf8 == 0 || *pszManagedutf8 == 0)
7410         return;
7411
7412     pszNative = (char*)utf8Strings[stringIndex];
7413
7414     outLen = strlen(pszNative);
7415     // do byte by byte comparision
7416     for (size_t i = 0; i < outLen; i++) 
7417     {
7418         if (pszNative[i] != pszManagedutf8[i]) 
7419         {
7420             printf("Native and managed string do not match.\n");
7421             abort ();
7422         }
7423     }
7424 }
7425
7426 typedef void (* Callback2)(char *text, int index);
7427
7428 LIBTEST_API void
7429 Utf8DelegateAsParameter(Callback2 managedCallback)
7430 {
7431     for (int i = 0; i < NSTRINGS; ++i) 
7432     {
7433         char *pszNative = 0;
7434         pszNative = (char*)utf8Strings[i];
7435         managedCallback(pszNative, i);
7436     }
7437 }
7438
7439
7440 LIBTEST_API char*
7441 StringBuilderParameterReturn(int index)
7442 {
7443     char *pszTextutf8 = (char*)utf8Strings[index];
7444     size_t strLength = strlen(pszTextutf8);
7445     char * ret = (char *)(marshal_alloc (sizeof(char)* (strLength + 1)));
7446     memcpy(ret, pszTextutf8, strLength);
7447     ret[strLength] = '\0';
7448
7449     return  ret;
7450 }
7451
7452 LIBTEST_API int STDCALL
7453 mono_test_marshal_pointer_array (int *arr[])
7454 {
7455         int i;
7456
7457         for (i = 0; i < 10; ++i) {
7458                 if (*arr [i] != -1)
7459                         return 1;
7460         }
7461         return 0;
7462 }