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