[xbuild] Evaluate Import with MSBuildThisFile* properties set.
[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 #else 
37 #define LIBTEST_API
38 #endif
39
40 static void marshal_free (void *ptr)
41 {
42 #ifdef WIN32
43         CoTaskMemFree (ptr);
44 #else
45         g_free (ptr);
46 #endif
47 }
48
49 static void* marshal_alloc (gsize size)
50 {
51 #ifdef WIN32
52         return CoTaskMemAlloc (size);
53 #else
54         return g_malloc (size);
55 #endif
56 }
57
58 static void* marshal_alloc0 (gsize size)
59 {
60 #ifdef WIN32
61         void* ptr = CoTaskMemAlloc (size);
62         memset(ptr, 0, size);
63         return ptr;
64 #else
65         return g_malloc0 (size);
66 #endif
67 }
68
69 static char* marshal_strdup (const char *str)
70 {
71 #ifdef WIN32
72         int len;
73         char *buf;
74
75         if (!str)
76                 return NULL;
77
78         len = strlen (str);
79         buf = (char *) CoTaskMemAlloc (len + 1);
80         return strcpy (buf, str);
81 #else
82         return g_strdup (str);
83 #endif
84 }
85
86 static gunichar2* marshal_bstr_alloc(const gchar* str)
87 {
88 #ifdef WIN32
89         gunichar2* ret = NULL;
90         gunichar2* temp = NULL;
91         temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
92         ret = SysAllocString (temp);
93         g_free (temp);
94         return ret;
95 #else
96         gchar* ret = NULL;
97         int slen = strlen (str);
98         gunichar2* temp;
99         /* allocate len + 1 utf16 characters plus 4 byte integer for length*/
100         ret = g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32));
101         if (ret == NULL)
102                 return NULL;
103         temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
104         memcpy (ret + sizeof(guint32), temp, slen * sizeof(gunichar2));
105         * ((guint32 *) ret) = slen * sizeof(gunichar2);
106         ret [4 + slen * sizeof(gunichar2)] = 0;
107         ret [5 + slen * sizeof(gunichar2)] = 0;
108
109         return (gunichar2*)(ret + 4);
110 #endif
111 }
112
113 #define marshal_new0(type,size)       ((type *) marshal_alloc0 (sizeof (type)* (size)))
114
115 LIBTEST_API int STDCALL
116 mono_cominterop_is_supported (void)
117 {
118 #if defined(TARGET_X86) || defined(TARGET_AMD64)
119         return 1;
120 #endif
121         return 0;
122 }
123
124 LIBTEST_API unsigned short* STDCALL
125 test_lpwstr_marshal (unsigned short* chars, long length)
126 {
127         int i = 0;
128         unsigned short *res;
129
130         res = marshal_alloc (2 * (length + 1));
131
132         // printf("test_lpwstr_marshal()\n");
133         
134         while ( i < length ) {
135                 // printf("X|%u|\n", chars[i]);
136                 res [i] = chars[i];
137                 i++;
138         }
139
140         res [i] = 0;
141
142         return res;
143 }
144
145
146 LIBTEST_API void STDCALL
147 test_lpwstr_marshal_out (unsigned short** chars)
148 {
149         int i = 0;
150         const char abc[] = "ABC";
151         glong len = strlen(abc);
152
153         *chars = marshal_alloc (2 * (len + 1));
154         
155         while ( i < len ) {
156                 (*chars) [i] = abc[i];
157                 i++;
158         }
159
160         (*chars) [i] = 0;
161 }
162
163 typedef struct {
164         int b;
165         int a;
166         int c;
167 } union_test_1_type;
168
169 LIBTEST_API int STDCALL  
170 mono_union_test_1 (union_test_1_type u1) {
171         // printf ("Got values %d %d %d\n", u1.b, u1.a, u1.c);
172         return u1.a + u1.b + u1.c;
173 }
174
175 LIBTEST_API int STDCALL  
176 mono_return_int (int a) {
177         // printf ("Got value %d\n", a);
178         return a;
179 }
180
181 LIBTEST_API float STDCALL  
182 mono_test_marshal_pass_return_float (float f) {
183         return f + 1.0;
184 }
185
186 struct ss
187 {
188         int i;
189 };
190
191 LIBTEST_API int STDCALL 
192 mono_return_int_ss (struct ss a) {
193         // printf ("Got value %d\n", a.i);
194         return a.i;
195 }
196
197 LIBTEST_API struct ss STDCALL
198 mono_return_ss (struct ss a) {
199         // printf ("Got value %d\n", a.i);
200         a.i++;
201         return a;
202 }
203
204 struct sc1
205 {
206         char c[1];
207 };
208
209 LIBTEST_API struct sc1 STDCALL
210 mono_return_sc1 (struct sc1 a) {
211         // printf ("Got value %d\n", a.c[0]);
212         a.c[0]++;
213         return a;
214 }
215
216
217 struct sc3
218 {
219         char c[3];
220 };
221
222 LIBTEST_API struct sc3 STDCALL 
223 mono_return_sc3 (struct sc3 a) {
224         // printf ("Got values %d %d %d\n", a.c[0], a.c[1], a.c[2]);
225         a.c[0]++;
226         a.c[1] += 2;
227         a.c[2] += 3;
228         return a;
229 }
230
231 struct sc5
232 {
233         char c[5];
234 };
235
236 LIBTEST_API struct sc5 STDCALL 
237 mono_return_sc5 (struct sc5 a) {
238         // printf ("Got values %d %d %d %d %d\n", a.c[0], a.c[1], a.c[2], a.c[3], a.c[4]);
239         a.c[0]++;
240         a.c[1] += 2;
241         a.c[2] += 3;
242         a.c[3] += 4;
243         a.c[4] += 5;
244         return a;
245 }
246
247 union su
248 {
249         int i1;
250         int i2;
251 };
252
253 LIBTEST_API int STDCALL  
254 mono_return_int_su (union su a) {
255         // printf ("Got value %d\n", a.i1);
256         return a.i1;
257 }
258
259 LIBTEST_API int STDCALL  
260 mono_test_many_int_arguments (int a, int b, int c, int d, int e,
261                                                           int f, int g, int h, int i, int j);
262 LIBTEST_API short STDCALL 
263 mono_test_many_short_arguments (short a, short b, short c, short d, short e,
264                                                                 short f, short g, short h, short i, short j);
265 LIBTEST_API char STDCALL 
266 mono_test_many_char_arguments (char a, char b, char c, char d, char e,
267                                                            char f, char g, char h, char i, char j);
268
269 LIBTEST_API int STDCALL 
270 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)
271 {
272         return a + b + c + d + e + f + g + h + i + j;
273 }
274
275 LIBTEST_API short STDCALL 
276 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)
277 {
278         return a + b + c + d + e + f + g + h + i + j;
279 }
280
281 LIBTEST_API char STDCALL 
282 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)
283 {
284         return a + b + c + d + e + f + g + h + i + j;
285 }
286
287 LIBTEST_API float STDCALL 
288 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)
289 {
290         return a + b + c + d + e + f + g + h + i + j;
291 }
292
293 LIBTEST_API double STDCALL 
294 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)
295 {
296         return a + b + c + d + e + f + g + h + i + j;
297 }
298
299 LIBTEST_API double STDCALL 
300 mono_test_split_double_arguments (double a, double b, float c, double d, double e)
301 {
302         return a + b + c + d + e;
303 }
304
305 LIBTEST_API int STDCALL 
306 mono_test_puts_static (char *s)
307 {
308         // printf ("TEST %s\n", s);
309         return 1;
310 }
311
312 typedef int (STDCALL *SimpleDelegate3) (int a, int b);
313
314 LIBTEST_API int STDCALL 
315 mono_invoke_delegate (SimpleDelegate3 delegate)
316 {
317         int res;
318
319         // printf ("start invoke %p\n", delegate);
320
321         res = delegate (2, 3);
322
323         // printf ("end invoke\n");
324
325         return res;
326 }
327
328 LIBTEST_API int STDCALL
329 mono_invoke_simple_delegate (SimpleDelegate d)
330 {
331         return d (4);
332 }
333
334 LIBTEST_API int STDCALL  
335 mono_test_marshal_char (short a1)
336 {
337         if (a1 == 'a')
338                 return 0;
339         
340         return 1;
341 }
342
343 LIBTEST_API void STDCALL
344 mono_test_marshal_char_array (gunichar2 *s)
345 {
346         const char m[] = "abcdef";
347         gunichar2* s2;
348         glong len;
349
350         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
351         
352         len = (len * 2) + 2;
353         memcpy (s, s2, len);
354
355         g_free (s2);
356 }
357
358 LIBTEST_API int STDCALL
359 mono_test_marshal_ansi_char_array (char *s)
360 {
361         const char m[] = "abcdef";
362
363         if (strncmp ("qwer", s, 4))
364                 return 1;
365
366         memcpy (s, m, sizeof (m));
367         return 0;
368 }
369
370 LIBTEST_API int STDCALL
371 mono_test_marshal_unicode_char_array (gunichar2 *s)
372 {
373         const char m[] = "abcdef";
374         const char expected[] = "qwer";
375         gunichar2 *s1, *s2;
376         glong len1, len2;
377
378         s1 = g_utf8_to_utf16 (m, -1, NULL, &len1, NULL);
379         s2 = g_utf8_to_utf16 (expected, -1, NULL, &len2, NULL);
380         len1 = (len1 * 2);
381         len2 = (len2 * 2);
382
383         if (memcmp (s, s2, len2))
384                 return 1;
385
386         memcpy (s, s1, len1);
387         return 0;
388 }
389
390
391 LIBTEST_API int STDCALL 
392 mono_test_empty_pinvoke (int i)
393 {
394         return i;
395 }
396
397 LIBTEST_API int STDCALL  
398 mono_test_marshal_bool_byref (int a, int *b, int c)
399 {
400     int res = *b;
401
402         *b = 1;
403
404         return res;
405 }
406
407 LIBTEST_API int STDCALL 
408 mono_test_marshal_bool_in_as_I1_U1 (char bTrue, char bFalse)
409 {
410         if (!bTrue)
411                 return 1;
412         if (bFalse)
413                 return 2;
414         return 0;
415 }
416
417 LIBTEST_API int STDCALL 
418 mono_test_marshal_bool_out_as_I1_U1 (char* bTrue, char* bFalse)
419 {
420         if (!bTrue || !bFalse)
421                 return 3;
422
423         *bTrue = 1;
424         *bFalse = 0;
425
426         return 0;
427 }
428
429 LIBTEST_API int STDCALL 
430 mono_test_marshal_bool_ref_as_I1_U1 (char* bTrue, char* bFalse)
431 {
432         if (!bTrue || !bFalse)
433                 return 4;
434
435         if (!(*bTrue))
436                 return 5;
437         if (*bFalse)
438                 return 6;
439
440         *bFalse = 1;
441         *bTrue = 0;
442
443         return 0;
444 }
445
446 LIBTEST_API int STDCALL  
447 mono_test_marshal_array (int *a1)
448 {
449         int i, sum = 0;
450
451         for (i = 0; i < 50; i++)
452                 sum += a1 [i];
453         
454         return sum;
455 }
456
457 LIBTEST_API int STDCALL  
458 mono_test_marshal_inout_array (int *a1)
459 {
460         int i, sum = 0;
461
462         for (i = 0; i < 50; i++) {
463                 sum += a1 [i];
464                 a1 [i] = 50 - a1 [i];
465         }
466         
467         return sum;
468 }
469
470 LIBTEST_API int /* cdecl */
471 mono_test_marshal_inout_array_cdecl (int *a1)
472 {
473         return mono_test_marshal_inout_array (a1);
474 }
475
476 LIBTEST_API int STDCALL  
477 mono_test_marshal_out_array (int *a1)
478 {
479         int i;
480
481         for (i = 0; i < 50; i++) {
482                 a1 [i] = i;
483         }
484         
485         return 0;
486 }
487
488 LIBTEST_API int STDCALL  
489 mono_test_marshal_inout_nonblittable_array (gunichar2 *a1)
490 {
491         int i, sum = 0;
492
493         for (i = 0; i < 10; i++) {
494                 a1 [i] = 'F';
495         }
496         
497         return sum;
498 }
499
500 typedef struct {
501         int a;
502         int b;
503         int c;
504         const char *d;
505         gunichar2 *d2;
506 } simplestruct;
507
508 typedef struct {
509         double x;
510         double y;
511 } point;
512
513 LIBTEST_API simplestruct STDCALL 
514 mono_test_return_vtype (int i)
515 {
516         simplestruct res;
517         static gunichar2 test2 [] = { 'T', 'E', 'S', 'T', '2', 0 };
518
519         res.a = 0;
520         res.b = 1;
521         res.c = 0;
522         res.d = "TEST";
523         res.d2 = test2;
524
525         return res;
526 }
527
528 LIBTEST_API void STDCALL
529 mono_test_delegate_struct (void)
530 {
531         // printf ("TEST\n");
532 }
533
534 typedef char* (STDCALL *ReturnStringDelegate) (const char *s);
535
536 LIBTEST_API char * STDCALL 
537 mono_test_return_string (ReturnStringDelegate func)
538 {
539         char *res;
540
541         // printf ("mono_test_return_string\n");
542
543         res = func ("TEST");
544         marshal_free (res);
545
546         // printf ("got string: %s\n", res);
547         return marshal_strdup ("12345");
548 }
549
550 typedef int (STDCALL *RefVTypeDelegate) (int a, simplestruct *ss, int b);
551
552 LIBTEST_API int STDCALL 
553 mono_test_ref_vtype (int a, simplestruct *ss, int b, RefVTypeDelegate func)
554 {
555         if (a == 1 && b == 2 && ss->a == 0 && ss->b == 1 && ss->c == 0 &&
556             !strcmp (ss->d, "TEST1")) {
557                 ss->a = 1;
558                 ss->b = 0;
559                 ss->c = 1;
560                 ss->d = "TEST2";
561
562                 return func (a, ss, b);
563         }
564
565         return 1;
566 }
567
568 typedef int (STDCALL *OutVTypeDelegate) (int a, simplestruct *ss, int b);
569
570 LIBTEST_API int STDCALL 
571 mono_test_marshal_out_struct (int a, simplestruct *ss, int b, OutVTypeDelegate func)
572 {
573         /* Check that the input pointer is ignored */
574         ss->d = (gpointer)0x12345678;
575
576         func (a, ss, b);
577
578         if (ss->a && ss->b && ss->c && !strcmp (ss->d, "TEST3"))
579                 return 0;
580         else
581                 return 1;
582 }
583
584 typedef struct {
585         int a;
586         SimpleDelegate func, func2, func3;
587 } DelegateStruct;
588
589 LIBTEST_API DelegateStruct STDCALL 
590 mono_test_marshal_delegate_struct (DelegateStruct ds)
591 {
592         DelegateStruct res;
593
594         res.a = ds.func (ds.a) + ds.func2 (ds.a) + (ds.func3 == NULL ? 0 : 1);
595         res.func = ds.func;
596         res.func2 = ds.func2;
597         res.func3 = NULL;
598
599         return res;
600 }
601
602 LIBTEST_API int STDCALL  
603 mono_test_marshal_struct (simplestruct ss)
604 {
605         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
606             !strcmp (ss.d, "TEST"))
607                 return 0;
608
609         return 1;
610 }
611
612 LIBTEST_API int STDCALL 
613 mono_test_marshal_byref_struct (simplestruct *ss, int a, int b, int c, char *d)
614 {
615         gboolean res = (ss->a == a && ss->b == b && ss->c == c && strcmp (ss->d, d) == 0);
616
617         marshal_free ((char*)ss->d);
618
619         ss->a = !ss->a;
620         ss->b = !ss->b;
621         ss->c = !ss->c;
622         ss->d = marshal_strdup ("DEF");
623
624         return res ? 0 : 1;
625 }
626
627 typedef struct {
628         int a;
629         int b;
630         int c;
631         char *d;
632         unsigned char e;
633         double f;
634         unsigned char g;
635         guint64 h;
636 } simplestruct2;
637
638 LIBTEST_API int STDCALL 
639 mono_test_marshal_struct2 (simplestruct2 ss)
640 {
641         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
642             !strcmp (ss.d, "TEST") && 
643             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
644                 return 0;
645
646         return 1;
647 }
648
649 /* on HP some of the struct should be on the stack and not in registers */
650 LIBTEST_API int STDCALL 
651 mono_test_marshal_struct2_2 (int i, int j, int k, simplestruct2 ss)
652 {
653         if (i != 10 || j != 11 || k != 12)
654                 return 1;
655         if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
656             !strcmp (ss.d, "TEST") && 
657             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
658                 return 0;
659
660         return 1;
661 }
662
663 LIBTEST_API int STDCALL  
664 mono_test_marshal_lpstruct (simplestruct *ss)
665 {
666         if (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
667             !strcmp (ss->d, "TEST"))
668                 return 0;
669
670         return 1;
671 }
672
673 LIBTEST_API int STDCALL  
674 mono_test_marshal_lpstruct_blittable (point *p)
675 {
676         if (p->x == 1.0 && p->y == 2.0)
677                 return 0;
678         else
679                 return 1;
680 }
681
682 LIBTEST_API int STDCALL 
683 mono_test_marshal_struct_array (simplestruct2 *ss)
684 {
685         if (! (ss[0].a == 0 && ss[0].b == 1 && ss[0].c == 0 &&
686                    !strcmp (ss[0].d, "TEST") && 
687                    ss[0].e == 99 && ss[0].f == 1.5 && ss[0].g == 42 && ss[0].h == (guint64)123))
688                 return 1;
689
690         if (! (ss[1].a == 0 && ss[1].b == 0 && ss[1].c == 0 &&
691                    !strcmp (ss[1].d, "TEST2") && 
692                    ss[1].e == 100 && ss[1].f == 2.5 && ss[1].g == 43 && ss[1].h == (guint64)124))
693                 return 1;
694
695         return 0;
696 }
697
698 typedef struct long_align_struct {
699         gint32 a;
700         gint64 b;
701         gint64 c;
702 } long_align_struct;
703
704 LIBTEST_API int STDCALL 
705 mono_test_marshal_long_align_struct_array (long_align_struct *ss)
706 {
707         return ss[0].a + ss[0].b + ss[0].c + ss[1].a + ss[1].b + ss[1].c;
708 }
709
710 LIBTEST_API simplestruct2 * STDCALL 
711 mono_test_marshal_class (int i, int j, int k, simplestruct2 *ss, int l)
712 {
713         simplestruct2 *res;
714
715         if (!ss)
716                 return NULL;
717
718         if (i != 10 || j != 11 || k != 12 || l != 14)
719                 return NULL;
720         if (! (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
721                    !strcmp (ss->d, "TEST") && 
722                    ss->e == 99 && ss->f == 1.5 && ss->g == 42 && ss->h == (guint64)123))
723                 return NULL;
724
725         res = marshal_new0 (simplestruct2, 1);
726         memcpy (res, ss, sizeof (simplestruct2));
727         res->d = marshal_strdup ("TEST");
728         return res;
729 }
730
731 LIBTEST_API int STDCALL 
732 mono_test_marshal_byref_class (simplestruct2 **ssp)
733 {
734         simplestruct2 *ss = *ssp;
735         simplestruct2 *res;
736         
737         if (! (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
738                    !strcmp (ss->d, "TEST") && 
739                    ss->e == 99 && ss->f == 1.5 && ss->g == 42 && ss->h == (guint64)123))
740                 return 1;
741
742         res = marshal_new0 (simplestruct2, 1);
743         memcpy (res, ss, sizeof (simplestruct2));
744         res->d = marshal_strdup ("TEST-RES");
745
746         *ssp = res;
747         return 0;
748 }
749
750 static void *
751 get_sp (void)
752 {
753         int i;
754         void *p;
755
756         /* Yes, this is correct, we are only trying to determine the value of the stack here */
757         p = &i;
758         return p;
759 }
760
761 LIBTEST_API int STDCALL 
762 reliable_delegate (int a)
763 {
764         return a;
765 }
766
767 /*
768  * Checks whether get_sp() works as expected. It doesn't work with gcc-2.95.3 on linux.
769  */
770 static gboolean
771 is_get_sp_reliable (void)
772 {
773         void *sp1, *sp2;
774
775         reliable_delegate(1);
776         sp1 = get_sp();
777         reliable_delegate(1);
778         sp2 = get_sp();
779         return sp1 == sp2;
780
781
782 LIBTEST_API int STDCALL 
783 mono_test_marshal_delegate (SimpleDelegate delegate)
784 {
785         void *sp1, *sp2;
786
787         /* Check that the delegate wrapper is stdcall */
788         delegate (2);
789         sp1 = get_sp ();
790         delegate (2);
791         sp2 = get_sp ();
792         if (is_get_sp_reliable())
793                 g_assert (sp1 == sp2);
794
795         return delegate (2);
796 }
797
798 static int STDCALL inc_cb (int i)
799 {
800         return i + 1;
801 }
802
803 LIBTEST_API int STDCALL 
804 mono_test_marshal_out_delegate (SimpleDelegate *delegate)
805 {
806         *delegate = inc_cb;
807
808         return 0;
809 }
810
811 LIBTEST_API SimpleDelegate STDCALL 
812 mono_test_marshal_return_delegate (SimpleDelegate delegate)
813 {
814         return delegate;
815 }
816
817 static int STDCALL
818 return_plus_one (int i)
819 {
820         return i + 1;
821 }
822
823 LIBTEST_API SimpleDelegate STDCALL 
824 mono_test_marshal_return_delegate_2 (void)
825 {
826         return return_plus_one;
827 }
828
829 typedef simplestruct (STDCALL *SimpleDelegate2) (simplestruct ss);
830
831 static gboolean
832 is_utf16_equals (gunichar2 *s1, const char *s2)
833 {
834         char *s;
835         int res;
836
837         s = g_utf16_to_utf8 (s1, -1, NULL, NULL, NULL);
838         res = strcmp (s, s2);
839         g_free (s);
840
841         return res == 0;
842 }
843
844 LIBTEST_API int STDCALL 
845 mono_test_marshal_delegate2 (SimpleDelegate2 delegate)
846 {
847         simplestruct ss, res;
848
849         ss.a = 0;
850         ss.b = 1;
851         ss.c = 0;
852         ss.d = "TEST";
853         ss.d2 = g_utf8_to_utf16 ("TEST2", -1, NULL, NULL, NULL); 
854
855         res = delegate (ss);
856         if (! (res.a && !res.b && res.c && !strcmp (res.d, "TEST-RES") && is_utf16_equals (res.d2, "TEST2-RES")))
857                 return 1;
858
859         return 0;
860 }
861
862 typedef simplestruct* (STDCALL *SimpleDelegate4) (simplestruct *ss);
863
864 LIBTEST_API int STDCALL 
865 mono_test_marshal_delegate4 (SimpleDelegate4 delegate)
866 {
867         simplestruct ss;
868         simplestruct *res;
869
870         ss.a = 0;
871         ss.b = 1;
872         ss.c = 0;
873         ss.d = "TEST";
874
875         /* Check argument */
876         res = delegate (&ss);
877         if (!res)
878                 return 1;
879
880         /* Check return value */
881         if (! (!res->a && res->b && !res->c && !strcmp (res->d, "TEST")))
882                 return 2;
883
884         /* Check NULL argument and NULL result */
885         res = delegate (NULL);
886         if (res)
887                 return 3;
888
889         return 0;
890 }
891
892 typedef int (STDCALL *SimpleDelegate5) (simplestruct **ss);
893
894 LIBTEST_API int STDCALL 
895 mono_test_marshal_delegate5 (SimpleDelegate5 delegate)
896 {
897         simplestruct ss;
898         int res;
899         simplestruct *ptr;
900
901         ss.a = 0;
902         ss.b = 1;
903         ss.c = 0;
904         ss.d = "TEST";
905
906         ptr = &ss;
907
908         res = delegate (&ptr);
909         if (res != 0)
910                 return 1;
911
912         if (!(ptr->a && !ptr->b && ptr->c && !strcmp (ptr->d, "RES")))
913                 return 2;
914
915         return 0;
916 }
917
918 LIBTEST_API int STDCALL 
919 mono_test_marshal_delegate6 (SimpleDelegate5 delegate)
920 {
921         int res;
922
923         res = delegate (NULL);
924
925         return 0;
926 }
927
928 typedef int (STDCALL *SimpleDelegate7) (simplestruct **ss);
929
930 LIBTEST_API int STDCALL 
931 mono_test_marshal_delegate7 (SimpleDelegate7 delegate)
932 {
933         int res;
934         simplestruct *ptr;
935
936         /* Check that the input pointer is ignored */
937         ptr = (gpointer)0x12345678;
938
939         res = delegate (&ptr);
940         if (res != 0)
941                 return 1;
942
943         if (!(ptr->a && !ptr->b && ptr->c && !strcmp (ptr->d, "RES")))
944                 return 2;
945
946         return 0;
947 }
948
949 typedef int (STDCALL *InOutByvalClassDelegate) (simplestruct *ss);
950
951 LIBTEST_API int STDCALL 
952 mono_test_marshal_inout_byval_class_delegate (InOutByvalClassDelegate delegate)
953 {
954         int res;
955         simplestruct ss;
956
957         ss.a = FALSE;
958         ss.b = TRUE;
959         ss.c = FALSE;
960         ss.d = g_strdup_printf ("%s", "FOO");
961
962         res = delegate (&ss);
963         if (res != 0)
964                 return 1;
965
966         if (!(ss.a && !ss.b && ss.c && !strcmp (ss.d, "RES")))
967                 return 2;
968
969         return 0;
970 }
971
972 typedef int (STDCALL *SimpleDelegate8) (gunichar2 *s);
973
974 LIBTEST_API int STDCALL 
975 mono_test_marshal_delegate8 (SimpleDelegate8 delegate, gunichar2 *s)
976 {
977         return delegate (s);
978 }
979
980 typedef int (STDCALL *return_int_fnt) (int i);
981 typedef int (STDCALL *SimpleDelegate9) (return_int_fnt d);
982
983 LIBTEST_API int STDCALL 
984 mono_test_marshal_delegate9 (SimpleDelegate9 delegate, gpointer ftn)
985 {
986         return delegate (ftn);
987 }
988
989 static int STDCALL 
990 return_self (int i)
991 {
992         return i;
993 }
994
995 LIBTEST_API int STDCALL 
996 mono_test_marshal_delegate10 (SimpleDelegate9 delegate)
997 {
998         return delegate (return_self);
999 }
1000
1001 typedef int (STDCALL *PrimitiveByrefDelegate) (int *i);
1002
1003 LIBTEST_API int STDCALL 
1004 mono_test_marshal_primitive_byref_delegate (PrimitiveByrefDelegate delegate)
1005 {
1006         int i = 1;
1007
1008         int res = delegate (&i);
1009         if (res != 0)
1010                 return res;
1011
1012         if (i != 2)
1013                 return 2;
1014
1015         return 0;
1016 }
1017
1018 typedef int (STDCALL *return_int_delegate) (int i);
1019
1020 typedef return_int_delegate (STDCALL *ReturnDelegateDelegate) (void);
1021
1022 LIBTEST_API int STDCALL 
1023 mono_test_marshal_return_delegate_delegate (ReturnDelegateDelegate d)
1024 {
1025         return (d ()) (55);
1026 }
1027
1028 LIBTEST_API int STDCALL  
1029 mono_test_marshal_stringbuilder (char *s, int n)
1030 {
1031         const char m[] = "This is my message.  Isn't it nice?";
1032
1033         if (strcmp (s, "ABCD") != 0)
1034                 return 1;
1035         strncpy(s, m, n);
1036         s [n] = '\0';
1037         return 0;
1038 }
1039
1040 LIBTEST_API int STDCALL  
1041 mono_test_marshal_stringbuilder_default (char *s, int n)
1042 {
1043         const char m[] = "This is my message.  Isn't it nice?";
1044
1045         strncpy(s, m, n);
1046         s [n] = '\0';
1047         return 0;
1048 }
1049
1050 LIBTEST_API int STDCALL  
1051 mono_test_marshal_stringbuilder_unicode (gunichar2 *s, int n)
1052 {
1053         const char m[] = "This is my message.  Isn't it nice?";
1054         gunichar2* s2;
1055         glong len;
1056
1057         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1058         
1059         len = (len * 2) + 2;
1060         if (len > (n * 2))
1061                 len = n * 2;
1062         memcpy (s, s2, len);
1063
1064         g_free (s2);
1065
1066         return 0;
1067 }
1068
1069 LIBTEST_API void STDCALL
1070 mono_test_marshal_stringbuilder_out (char **s)
1071 {
1072         const char m[] = "This is my message.  Isn't it nice?";
1073         char *str;
1074
1075         str = marshal_alloc (strlen (m) + 1);
1076         memcpy (str, m, strlen (m) + 1);
1077         
1078         *s = str;
1079 }
1080
1081 LIBTEST_API int STDCALL  
1082 mono_test_marshal_stringbuilder_out_unicode (gunichar2 **s)
1083 {
1084         const char m[] = "This is my message.  Isn't it nice?";
1085         gunichar2 *s2;
1086         glong len;
1087
1088         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1089         
1090         len = (len * 2) + 2;
1091         *s = marshal_alloc (len);
1092         memcpy (*s, s2, len);
1093
1094         g_free (s2);
1095
1096         return 0;
1097 }
1098
1099 typedef struct {
1100 #ifndef __GNUC__
1101     char a;
1102 #endif
1103 } EmptyStruct;
1104
1105 LIBTEST_API int STDCALL 
1106 mono_test_marshal_empty_string_array (char **array)
1107 {
1108         return (array == NULL) ? 0 : 1;
1109 }
1110
1111 LIBTEST_API int STDCALL 
1112 mono_test_marshal_string_array (char **array)
1113 {
1114         if (strcmp (array [0], "ABC"))
1115                 return 1;
1116         if (strcmp (array [1], "DEF"))
1117                 return 2;
1118
1119         if (array [2] != NULL)
1120                 return 3;
1121
1122         return 0;
1123 }
1124
1125 LIBTEST_API int STDCALL 
1126 mono_test_marshal_byref_string_array (char ***array)
1127 {
1128         if (*array == NULL)
1129                 return 0;
1130
1131         if (strcmp ((*array) [0], "Alpha"))
1132                 return 2;
1133         if (strcmp ((*array) [1], "Beta"))
1134                 return 2;
1135         if (strcmp ((*array) [2], "Gamma"))
1136                 return 2;
1137
1138         return 1;
1139 }
1140
1141 LIBTEST_API int STDCALL 
1142 mono_test_marshal_stringbuilder_array (char **array)
1143 {
1144         if (strcmp (array [0], "ABC"))
1145                 return 1;
1146         if (strcmp (array [1], "DEF"))
1147                 return 2;
1148
1149         strcpy (array [0], "DEF");
1150         strcpy (array [1], "ABC");
1151
1152         return 0;
1153 }
1154
1155 LIBTEST_API int STDCALL 
1156 mono_test_marshal_unicode_string_array (gunichar2 **array, char **array2)
1157 {
1158         GError *error = NULL;
1159         char *s;
1160         
1161         s = g_utf16_to_utf8 (array [0], -1, NULL, NULL, &error);
1162         if (strcmp (s, "ABC")) {
1163                 g_free (s);
1164                 return 1;
1165         }
1166         else
1167                 g_free (s);
1168
1169         s = g_utf16_to_utf8 (array [1], -1, NULL, NULL, &error);
1170         if (strcmp (s, "DEF")) {
1171                 g_free (s);
1172                 return 2;
1173         }
1174         else
1175                 g_free (s);
1176
1177         if (strcmp (array2 [0], "ABC"))
1178                 return 3;
1179
1180         if (strcmp (array2 [1], "DEF")) 
1181                 return 4;
1182
1183         return 0;
1184 }
1185
1186 /* this does not work on Redhat gcc 2.96 */
1187 LIBTEST_API int STDCALL  
1188 mono_test_empty_struct (int a, EmptyStruct es, int b)
1189 {
1190         // printf ("mono_test_empty_struct %d %d\n", a, b);
1191
1192         // Intel icc on ia64 passes 'es' in 2 registers
1193 #if defined(__ia64) && defined(__INTEL_COMPILER)
1194         return 0;
1195 #else
1196         if (a == 1 && b == 2)
1197                 return 0;
1198         return 1;
1199 #endif
1200 }
1201
1202 typedef struct {
1203        char a[100];
1204 } ByValStrStruct;
1205
1206 LIBTEST_API ByValStrStruct * STDCALL 
1207 mono_test_byvalstr_gen (void)
1208 {
1209         ByValStrStruct *ret;
1210        
1211         ret = malloc(sizeof(ByValStrStruct));
1212         memset(ret, 'a', sizeof(ByValStrStruct)-1);
1213         ret->a[sizeof(ByValStrStruct)-1] = 0;
1214
1215         return ret;
1216 }
1217
1218 LIBTEST_API int STDCALL 
1219 mono_test_byvalstr_check (ByValStrStruct* data, char* correctString)
1220 {
1221         int ret;
1222
1223         ret = strcmp(data->a, correctString);
1224         // printf ("T1: %s\n", data->a);
1225         // printf ("T2: %s\n", correctString);
1226
1227         /* we need g_free because the allocation was performed by mono_test_byvalstr_gen */
1228         g_free (data);
1229         return (ret != 0);
1230 }
1231
1232 typedef struct {
1233         guint16 a[4];
1234         int  flag;
1235 } ByValStrStruct_Unicode;
1236
1237 LIBTEST_API int STDCALL 
1238 mono_test_byvalstr_check_unicode (ByValStrStruct_Unicode *ref, int test)
1239 {
1240         if (ref->flag != 0x1234abcd){
1241                 printf ("overwritten data");
1242                 return 1;
1243         }
1244             
1245         if (test == 1 || test == 3){
1246                 if (ref->a [0] != '1' ||
1247                     ref->a [1] != '2'   ||
1248                     ref->a [2] != '3')
1249                         return 1;
1250                 return 0;
1251         }
1252         if (test == 2){
1253                 if (ref->a [0] != '1' ||
1254                     ref->a [1] != '2')
1255                         return 1;
1256                 return 0;
1257         }
1258         return 10;
1259 }
1260
1261 LIBTEST_API int STDCALL 
1262 NameManglingAnsi (char *data)
1263 {
1264         return data [0] + data [1] + data [2];
1265 }
1266
1267 LIBTEST_API int STDCALL 
1268 NameManglingAnsiA (char *data)
1269 {
1270         g_assert_not_reached ();
1271 }
1272
1273 LIBTEST_API int STDCALL 
1274 NameManglingAnsiW (char *data)
1275 {
1276         g_assert_not_reached ();
1277 }
1278
1279 LIBTEST_API int STDCALL 
1280 NameManglingAnsi2A (char *data)
1281 {
1282         return data [0] + data [1] + data [2];
1283 }
1284
1285 LIBTEST_API int STDCALL 
1286 NameManglingAnsi2W (char *data)
1287 {
1288         g_assert_not_reached ();
1289 }
1290
1291 LIBTEST_API int STDCALL 
1292 NameManglingUnicode (char *data)
1293 {
1294         g_assert_not_reached ();
1295 }
1296
1297 LIBTEST_API int STDCALL 
1298 NameManglingUnicodeW (gunichar2 *data)
1299 {
1300         return data [0] + data [1] + data [2];
1301 }
1302
1303 LIBTEST_API int STDCALL 
1304 NameManglingUnicode2 (gunichar2 *data)
1305 {
1306         return data [0] + data [1] + data [2];
1307 }
1308
1309 LIBTEST_API int STDCALL 
1310 NameManglingAutoW (char *data)
1311 {
1312 #ifdef WIN32
1313         return (data [0] + data [1] + data [2]) == 131 ? 0 : 1;
1314 #else
1315         g_assert_not_reached ();
1316 #endif
1317 }
1318
1319 LIBTEST_API int STDCALL 
1320 NameManglingAuto (char *data)
1321 {
1322 #ifndef WIN32
1323         return (data [0] + data [1] + data [2]) == 198 ? 0 : 1;
1324 #else
1325         g_assert_not_reached ();
1326 #endif
1327 }
1328
1329 typedef int (STDCALL *intcharFunc)(const char*);
1330
1331 LIBTEST_API void STDCALL 
1332 callFunction (intcharFunc f)
1333 {
1334         f ("ABC");
1335 }
1336
1337 typedef struct {
1338         const char* str;
1339         int i;
1340 } SimpleObj;
1341
1342 LIBTEST_API int STDCALL 
1343 class_marshal_test0 (SimpleObj *obj1)
1344 {
1345         // printf ("class_marshal_test0 %s %d\n", obj1->str, obj1->i);
1346
1347         if (strcmp(obj1->str, "T1"))
1348                 return -1;
1349         if (obj1->i != 4)
1350                 return -2;
1351
1352         return 0;
1353 }
1354
1355 LIBTEST_API int STDCALL 
1356 class_marshal_test4 (SimpleObj *obj1)
1357 {
1358         if (obj1)
1359                 return -1;
1360
1361         return 0;
1362 }
1363
1364 LIBTEST_API void STDCALL
1365 class_marshal_test1 (SimpleObj **obj1)
1366 {
1367         SimpleObj *res = malloc (sizeof (SimpleObj));
1368
1369         res->str = marshal_strdup ("ABC");
1370         res->i = 5;
1371
1372         *obj1 = res;
1373 }
1374
1375 LIBTEST_API int STDCALL 
1376 class_marshal_test2 (SimpleObj **obj1)
1377 {
1378         // printf ("class_marshal_test2 %s %d\n", (*obj1)->str, (*obj1)->i);
1379
1380         if (strcmp((*obj1)->str, "ABC"))
1381                 return -1;
1382         if ((*obj1)->i != 5)
1383                 return -2;
1384
1385         return 0;
1386 }
1387
1388 LIBTEST_API int STDCALL 
1389 string_marshal_test0 (char *str)
1390 {
1391         if (strcmp (str, "TEST0"))
1392                 return -1;
1393
1394         return 0;
1395 }
1396
1397 LIBTEST_API void STDCALL
1398 string_marshal_test1 (const char **str)
1399 {
1400         *str = marshal_strdup ("TEST1");
1401 }
1402
1403 LIBTEST_API int STDCALL 
1404 string_marshal_test2 (char **str)
1405 {
1406         // printf ("string_marshal_test2 %s\n", *str);
1407
1408         if (strcmp (*str, "TEST1"))
1409                 return -1;
1410
1411         return 0;
1412 }
1413
1414 LIBTEST_API int STDCALL 
1415 string_marshal_test3 (char *str)
1416 {
1417         if (str)
1418                 return -1;
1419
1420         return 0;
1421 }
1422
1423 typedef struct {
1424         int a;
1425         int b;
1426 } BlittableClass;
1427
1428 LIBTEST_API BlittableClass* STDCALL 
1429 TestBlittableClass (BlittableClass *vl)
1430 {
1431         BlittableClass *res;
1432
1433         // printf ("TestBlittableClass %d %d\n", vl->a, vl->b);
1434
1435         if (vl) {
1436                 vl->a++;
1437                 vl->b++;
1438
1439                 res = marshal_new0 (BlittableClass, 1);
1440                 memcpy (res, vl, sizeof (BlittableClass));
1441         } else {
1442                 res = marshal_new0 (BlittableClass, 1);
1443                 res->a = 42;
1444                 res->b = 43;
1445         }
1446
1447         return res;
1448 }
1449
1450 typedef struct OSVERSIONINFO_STRUCT
1451
1452         int a; 
1453         int b; 
1454 } OSVERSIONINFO_STRUCT;
1455
1456 LIBTEST_API int STDCALL  
1457 MyGetVersionEx (OSVERSIONINFO_STRUCT *osvi)
1458 {
1459
1460         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1461
1462         osvi->a += 1;
1463         osvi->b += 1;
1464
1465         return osvi->a + osvi->b;
1466 }
1467
1468 LIBTEST_API int STDCALL  
1469 BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSIONINFO_STRUCT *osvi)
1470 {
1471
1472         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1473
1474         osvi->a += 1;
1475         osvi->b += 1;
1476
1477         return osvi->a + osvi->b;
1478 }
1479
1480 LIBTEST_API int STDCALL 
1481 mono_test_marshal_point (point pt)
1482 {
1483         // printf("point %g %g\n", pt.x, pt.y);
1484         if (pt.x == 1.25 && pt.y == 3.5)
1485                 return 0;
1486
1487         return 1;
1488 }
1489
1490 typedef struct {
1491         int x;
1492         double y;
1493 } mixed_point;
1494
1495 LIBTEST_API int STDCALL 
1496 mono_test_marshal_mixed_point (mixed_point pt)
1497 {
1498         // printf("mixed point %d %g\n", pt.x, pt.y);
1499         if (pt.x == 5 && pt.y == 6.75)
1500                 return 0;
1501
1502         return 1;
1503 }
1504
1505 LIBTEST_API int STDCALL 
1506 mono_test_marshal_mixed_point_2 (mixed_point *pt)
1507 {
1508         if (pt->x != 5 || pt->y != 6.75)
1509                 return 1;
1510
1511         pt->x = 10;
1512         pt->y = 12.35;
1513
1514         return 0;
1515 }
1516
1517 LIBTEST_API int STDCALL  
1518 marshal_test_ref_bool(int i, char *b1, short *b2, int *b3)
1519 {
1520     int res = 1;
1521     if (*b1 != 0 && *b1 != 1)
1522         return 1;
1523     if (*b2 != 0 && *b2 != -1) /* variant_bool */
1524         return 1;
1525     if (*b3 != 0 && *b3 != 1)
1526         return 1;
1527     if (i == ((*b1 << 2) | (-*b2 << 1) | *b3))
1528         res = 0;
1529     *b1 = !*b1;
1530     *b2 = ~*b2;
1531     *b3 = !*b3;
1532     return res;
1533 }
1534
1535 struct BoolStruct
1536 {
1537     int i;
1538     char b1;
1539     short b2; /* variant_bool */
1540     int b3;
1541 };
1542
1543 LIBTEST_API int STDCALL  
1544 marshal_test_bool_struct(struct BoolStruct *s)
1545 {
1546     int res = 1;
1547     if (s->b1 != 0 && s->b1 != 1)
1548         return 1;
1549     if (s->b2 != 0 && s->b2 != -1)
1550         return 1;
1551     if (s->b3 != 0 && s->b3 != 1)
1552         return 1;
1553     if (s->i == ((s->b1 << 2) | (-s->b2 << 1) | s->b3))
1554         res = 0;
1555     s->b1 = !s->b1;
1556     s->b2 = ~s->b2;
1557     s->b3 = !s->b3;
1558     return res;
1559 }
1560
1561 typedef struct {
1562         gint64 l;
1563 } LongStruct2;
1564
1565 typedef struct {
1566         int i;
1567         LongStruct2 l;
1568 } LongStruct;
1569
1570 LIBTEST_API int STDCALL
1571 mono_test_marshal_long_struct (LongStruct *s)
1572 {
1573         return s->i + s->l.l;
1574 }
1575
1576 LIBTEST_API void STDCALL
1577 mono_test_last_error (int err)
1578 {
1579 #ifdef WIN32
1580         SetLastError (err);
1581 #else
1582         errno = err;
1583 #endif
1584 }
1585
1586 LIBTEST_API int STDCALL 
1587 mono_test_asany (void *ptr, int what)
1588 {
1589         switch (what) {
1590         case 1:
1591                 return (*(int*)ptr == 5) ? 0 : 1;
1592         case 2:
1593                 return strcmp (ptr, "ABC") == 0 ? 0 : 1;
1594         case 3: {
1595                 simplestruct2 ss = *(simplestruct2*)ptr;
1596
1597                 if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
1598             !strcmp (ss.d, "TEST") && 
1599             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
1600                         return 0;
1601                 else
1602                         return 1;
1603         }
1604         case 4: {
1605                 GError *error = NULL;
1606                 char *s;
1607
1608                 s = g_utf16_to_utf8 (ptr, -1, NULL, NULL, &error);
1609
1610                 if (!s)
1611                         return 1;
1612
1613                 if (!strcmp (s, "ABC")) {
1614                         g_free (s);
1615                         return 0;
1616                 }
1617                 else {
1618                         g_free (s);
1619                         return 1;
1620                 }
1621         }
1622         default:
1623                 g_assert_not_reached ();
1624         }
1625
1626         return 1;
1627 }
1628
1629 typedef struct
1630 {
1631         int i;
1632         int j;
1633         int k;
1634         char *s;
1635 } AsAnyStruct;
1636
1637 LIBTEST_API int STDCALL 
1638 mono_test_marshal_asany_in (void* ptr)
1639 {
1640         AsAnyStruct* asAny = ptr;
1641         int res = asAny->i + asAny->j + asAny->k;
1642
1643         return res;
1644 }
1645
1646 LIBTEST_API int STDCALL 
1647 mono_test_marshal_asany_inout (void* ptr)
1648 {
1649         AsAnyStruct* asAny = ptr;
1650         int res = asAny->i + asAny->j + asAny->k;
1651
1652         marshal_free (asAny->s);
1653
1654         asAny->i = 10;
1655         asAny->j = 20;
1656         asAny->k = 30;
1657         asAny->s = 0;
1658
1659         return res;
1660 }
1661
1662 LIBTEST_API int STDCALL 
1663 mono_test_marshal_asany_out (void* ptr)
1664 {
1665         AsAnyStruct* asAny = ptr;
1666         int res = asAny->i + asAny->j + asAny->k;
1667
1668         asAny->i = 10;
1669         asAny->j = 20;
1670         asAny->k = 30;
1671         asAny->s = 0;
1672
1673         return res;
1674 }
1675
1676 /*
1677  * AMD64 marshalling tests.
1678  */
1679
1680 typedef struct amd64_struct1 {
1681         int i;
1682         int j;
1683         int k;
1684         int l;
1685 } amd64_struct1;
1686
1687 LIBTEST_API amd64_struct1 STDCALL 
1688 mono_test_marshal_amd64_pass_return_struct1 (amd64_struct1 s)
1689 {
1690         s.i ++;
1691         s.j ++;
1692         s.k ++;
1693         s.l ++;
1694
1695         return s;
1696 }
1697
1698 LIBTEST_API amd64_struct1 STDCALL 
1699 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)
1700 {
1701         s.i ++;
1702         s.j ++;
1703         s.k ++;
1704         s.l += 1 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
1705
1706         return s;
1707 }
1708
1709 typedef struct amd64_struct2 {
1710         int i;
1711         int j;
1712 } amd64_struct2;
1713
1714 LIBTEST_API amd64_struct2 STDCALL 
1715 mono_test_marshal_amd64_pass_return_struct2 (amd64_struct2 s)
1716 {
1717         s.i ++;
1718         s.j ++;
1719
1720         return s;
1721 }
1722
1723 typedef struct amd64_struct3 {
1724         int i;
1725 } amd64_struct3;
1726
1727 LIBTEST_API amd64_struct3 STDCALL 
1728 mono_test_marshal_amd64_pass_return_struct3 (amd64_struct3 s)
1729 {
1730         s.i ++;
1731
1732         return s;
1733 }
1734
1735 typedef struct amd64_struct4 {
1736         double d1, d2;
1737 } amd64_struct4;
1738
1739 LIBTEST_API amd64_struct4 STDCALL 
1740 mono_test_marshal_amd64_pass_return_struct4 (amd64_struct4 s)
1741 {
1742         s.d1 ++;
1743         s.d2 ++;
1744
1745         return s;
1746 }
1747
1748 /*
1749  * IA64 marshalling tests.
1750  */
1751 typedef struct test_struct5 {
1752         float d1, d2;
1753 } test_struct5;
1754
1755 LIBTEST_API test_struct5 STDCALL 
1756 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, test_struct5 s, int i, double d3, double d4)
1757 {
1758         s.d1 += d1 + d2 + i;
1759         s.d2 += d3 + d4 + i;
1760
1761         return s;
1762 }
1763
1764 typedef struct test_struct6 {
1765         double d1, d2;
1766 } test_struct6;
1767
1768 LIBTEST_API test_struct6 STDCALL 
1769 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, test_struct6 s, int i, double d3, double d4)
1770 {
1771         s.d1 += d1 + d2 + i;
1772         s.d2 += d3 + d4;
1773
1774         return s;
1775 }
1776
1777 static guint32 custom_res [2];
1778
1779 LIBTEST_API void* STDCALL
1780 mono_test_marshal_pass_return_custom (int i, guint32 *ptr, int j)
1781 {
1782         /* ptr will be freed by CleanupNative, so make a copy */
1783         custom_res [0] = 0; /* not allocated by AllocHGlobal */
1784         custom_res [1] = ptr [1];
1785
1786         return &custom_res;
1787 }
1788
1789 LIBTEST_API int STDCALL 
1790 mono_test_marshal_pass_out_custom (int i, guint32 **ptr, int j)
1791 {
1792         custom_res [0] = 0;
1793         custom_res [1] = i + j + 10;
1794
1795         *ptr = custom_res;
1796
1797         return 0;
1798 }
1799
1800 LIBTEST_API int STDCALL 
1801 mono_test_marshal_pass_inout_custom (int i, guint32 *ptr, int j)
1802 {
1803         ptr [0] = 0;
1804         ptr [1] = i + ptr [1] + j;
1805
1806         return 0;
1807 }
1808
1809 LIBTEST_API int STDCALL 
1810 mono_test_marshal_pass_out_byval_custom (int i, guint32 *ptr, int j)
1811 {
1812         return ptr == NULL ? 0 : 1;
1813 }
1814
1815 LIBTEST_API int STDCALL 
1816 mono_test_marshal_pass_byref_custom (int i, guint32 **ptr, int j)
1817 {
1818         (*ptr)[1] += i + j;
1819
1820         return 0;
1821 }
1822
1823 LIBTEST_API void* STDCALL
1824 mono_test_marshal_pass_return_custom2 (int i, guint32 *ptr, int j)
1825 {
1826         g_assert_not_reached ();
1827
1828         return NULL;
1829 }
1830
1831 LIBTEST_API void* STDCALL
1832 mono_test_marshal_pass_return_custom_null (int i, guint32 *ptr, int j)
1833 {
1834         g_assert (ptr == NULL);
1835
1836         return NULL;
1837 }
1838
1839 typedef void *(STDCALL *PassReturnPtrDelegate) (void *ptr);
1840
1841 LIBTEST_API int STDCALL 
1842 mono_test_marshal_pass_return_custom_in_delegate (PassReturnPtrDelegate del)
1843 {
1844         guint32 buf [2];
1845         guint32 res;
1846         guint32 *ptr;
1847
1848         buf [0] = 0;
1849         buf [1] = 10;
1850
1851         ptr = del (&buf);
1852
1853         res = ptr [1];
1854
1855 #ifdef WIN32
1856         /* FIXME: Freed with FreeHGlobal */
1857 #else
1858         g_free (ptr);
1859 #endif
1860
1861         return res;
1862 }
1863
1864 LIBTEST_API int STDCALL 
1865 mono_test_marshal_pass_return_custom_null_in_delegate (PassReturnPtrDelegate del)
1866 {
1867         void *ptr = del (NULL);
1868
1869         return (ptr == NULL) ? 15 : 0;
1870 }
1871
1872 typedef void (STDCALL *CustomOutParamDelegate) (void **pptr);
1873
1874 LIBTEST_API int STDCALL 
1875 mono_test_marshal_custom_out_param_delegate (CustomOutParamDelegate del)
1876 {
1877         void* pptr = del;
1878
1879         del (&pptr);
1880
1881         if(pptr != NULL)
1882                 return 1;
1883
1884         return 0;
1885 }
1886
1887 typedef int (STDCALL *ReturnEnumDelegate) (int e);
1888
1889 LIBTEST_API int STDCALL 
1890 mono_test_marshal_return_enum_delegate (ReturnEnumDelegate func)
1891 {
1892         return func (1);
1893 }
1894
1895 typedef struct {
1896         int a, b, c;
1897         gint64 d;
1898 } BlittableStruct;
1899         
1900 typedef BlittableStruct (STDCALL *SimpleDelegate10) (BlittableStruct ss);
1901
1902 LIBTEST_API int STDCALL 
1903 mono_test_marshal_blittable_struct_delegate (SimpleDelegate10 delegate)
1904 {
1905         BlittableStruct ss, res;
1906
1907         ss.a = 1;
1908         ss.b = 2;
1909         ss.c = 3;
1910         ss.d = 55;
1911
1912         res = delegate (ss);
1913         if (! ((res.a == -1) && (res.b == -2) && (res.c == -3) && (res.d == -55)))
1914                 return 1;
1915
1916         return 0;
1917 }
1918
1919 LIBTEST_API int STDCALL 
1920 mono_test_stdcall_name_mangling (int a, int b, int c)
1921 {
1922         return a + b + c;
1923 }
1924
1925 /*
1926  * PASSING AND RETURNING SMALL STRUCTURES FROM DELEGATES TESTS
1927  */
1928
1929 typedef struct {
1930         int i;
1931 } SmallStruct1;
1932         
1933 typedef SmallStruct1 (STDCALL *SmallStructDelegate1) (SmallStruct1 ss);
1934
1935 LIBTEST_API int STDCALL 
1936 mono_test_marshal_small_struct_delegate1 (SmallStructDelegate1 delegate)
1937 {
1938         SmallStruct1 ss, res;
1939
1940         ss.i = 1;
1941
1942         res = delegate (ss);
1943         if (! (res.i == -1))
1944                 return 1;
1945
1946         return 0;
1947 }
1948
1949 typedef struct {
1950         gint16 i, j;
1951 } SmallStruct2;
1952         
1953 typedef SmallStruct2 (STDCALL *SmallStructDelegate2) (SmallStruct2 ss);
1954
1955 LIBTEST_API int STDCALL 
1956 mono_test_marshal_small_struct_delegate2 (SmallStructDelegate2 delegate)
1957 {
1958         SmallStruct2 ss, res;
1959
1960         ss.i = 2;
1961         ss.j = 3;
1962
1963         res = delegate (ss);
1964         if (! ((res.i == -2) && (res.j == -3)))
1965                 return 1;
1966
1967         return 0;
1968 }
1969
1970 typedef struct {
1971         gint16 i;
1972         gint8 j;
1973 } SmallStruct3;
1974         
1975 typedef SmallStruct3 (STDCALL *SmallStructDelegate3) (SmallStruct3 ss);
1976
1977 LIBTEST_API int STDCALL 
1978 mono_test_marshal_small_struct_delegate3 (SmallStructDelegate3 delegate)
1979 {
1980         SmallStruct3 ss, res;
1981
1982         ss.i = 1;
1983         ss.j = 2;
1984
1985         res = delegate (ss);
1986         if (! ((res.i == -1) && (res.j == -2)))
1987                 return 1;
1988
1989         return 0;
1990 }
1991
1992 typedef struct {
1993         gint16 i;
1994 } SmallStruct4;
1995         
1996 typedef SmallStruct4 (STDCALL *SmallStructDelegate4) (SmallStruct4 ss);
1997
1998 LIBTEST_API int STDCALL 
1999 mono_test_marshal_small_struct_delegate4 (SmallStructDelegate4 delegate)
2000 {
2001         SmallStruct4 ss, res;
2002
2003         ss.i = 1;
2004
2005         res = delegate (ss);
2006         if (! (res.i == -1))
2007                 return 1;
2008
2009         return 0;
2010 }
2011
2012 typedef struct {
2013         gint64 i;
2014 } SmallStruct5;
2015         
2016 typedef SmallStruct5 (STDCALL *SmallStructDelegate5) (SmallStruct5 ss);
2017
2018 LIBTEST_API int STDCALL 
2019 mono_test_marshal_small_struct_delegate5 (SmallStructDelegate5 delegate)
2020 {
2021         SmallStruct5 ss, res;
2022
2023         ss.i = 5;
2024
2025         res = delegate (ss);
2026         if (! (res.i == -5))
2027                 return 1;
2028
2029         return 0;
2030 }
2031
2032 typedef struct {
2033         int i, j;
2034 } SmallStruct6;
2035         
2036 typedef SmallStruct6 (STDCALL *SmallStructDelegate6) (SmallStruct6 ss);
2037
2038 LIBTEST_API int STDCALL 
2039 mono_test_marshal_small_struct_delegate6 (SmallStructDelegate6 delegate)
2040 {
2041         SmallStruct6 ss, res;
2042
2043         ss.i = 1;
2044         ss.j = 2;
2045
2046         res = delegate (ss);
2047         if (! ((res.i == -1) && (res.j == -2)))
2048                 return 1;
2049
2050         return 0;
2051 }
2052
2053 typedef struct {
2054         int i;
2055         gint16 j;
2056 } SmallStruct7;
2057         
2058 typedef SmallStruct7 (STDCALL *SmallStructDelegate7) (SmallStruct7 ss);
2059
2060 LIBTEST_API int STDCALL 
2061 mono_test_marshal_small_struct_delegate7 (SmallStructDelegate7 delegate)
2062 {
2063         SmallStruct7 ss, res;
2064
2065         ss.i = 1;
2066         ss.j = 2;
2067
2068         res = delegate (ss);
2069         if (! ((res.i == -1) && (res.j == -2)))
2070                 return 1;
2071
2072         return 0;
2073 }
2074
2075 typedef struct {
2076         float i;
2077 } SmallStruct8;
2078         
2079 typedef SmallStruct8 (STDCALL *SmallStructDelegate8) (SmallStruct8 ss);
2080
2081 LIBTEST_API int STDCALL 
2082 mono_test_marshal_small_struct_delegate8 (SmallStructDelegate8 delegate)
2083 {
2084         SmallStruct8 ss, res;
2085
2086         ss.i = 1.0;
2087
2088         res = delegate (ss);
2089         if (! ((res.i == -1.0)))
2090                 return 1;
2091
2092         return 0;
2093 }
2094
2095 typedef struct {
2096         double i;
2097 } SmallStruct9;
2098         
2099 typedef SmallStruct9 (STDCALL *SmallStructDelegate9) (SmallStruct9 ss);
2100
2101 LIBTEST_API int STDCALL 
2102 mono_test_marshal_small_struct_delegate9 (SmallStructDelegate9 delegate)
2103 {
2104         SmallStruct9 ss, res;
2105
2106         ss.i = 1.0;
2107
2108         res = delegate (ss);
2109         if (! ((res.i == -1.0)))
2110                 return 1;
2111
2112         return 0;
2113 }
2114
2115 typedef struct {
2116         float i, j;
2117 } SmallStruct10;
2118         
2119 typedef SmallStruct10 (STDCALL *SmallStructDelegate10) (SmallStruct10 ss);
2120
2121 LIBTEST_API int STDCALL 
2122 mono_test_marshal_small_struct_delegate10 (SmallStructDelegate10 delegate)
2123 {
2124         SmallStruct10 ss, res;
2125
2126         ss.i = 1.0;
2127         ss.j = 2.0;
2128
2129         res = delegate (ss);
2130         if (! ((res.i == -1.0) && (res.j == -2.0)))
2131                 return 1;
2132
2133         return 0;
2134 }
2135
2136 typedef struct {
2137         float i;
2138         int j;
2139 } SmallStruct11;
2140         
2141 typedef SmallStruct11 (STDCALL *SmallStructDelegate11) (SmallStruct11 ss);
2142
2143 LIBTEST_API int STDCALL 
2144 mono_test_marshal_small_struct_delegate11 (SmallStructDelegate11 delegate)
2145 {
2146         SmallStruct11 ss, res;
2147
2148         ss.i = 1.0;
2149         ss.j = 2;
2150
2151         res = delegate (ss);
2152         if (! ((res.i == -1.0) && (res.j == -2)))
2153                 return 1;
2154
2155         return 0;
2156 }
2157
2158 typedef int (STDCALL *ArrayDelegate) (int i, char *j, void *arr);
2159
2160 LIBTEST_API int STDCALL 
2161 mono_test_marshal_array_delegate (void *arr, int len, ArrayDelegate del)
2162 {
2163         return del (len, NULL, arr);
2164 }
2165
2166 typedef int (STDCALL *ArrayDelegateLong) (gint64 i, char *j, void *arr);
2167
2168 LIBTEST_API int STDCALL 
2169 mono_test_marshal_array_delegate_long (void *arr, gint64 len, ArrayDelegateLong del)
2170 {
2171         return del (len, NULL, arr);
2172 }
2173
2174 LIBTEST_API int STDCALL 
2175 mono_test_marshal_out_array_delegate (int *arr, int len, ArrayDelegate del)
2176 {
2177         del (len, NULL, arr);
2178
2179         if ((arr [0] != 1) || (arr [1] != 2))
2180                 return 1;
2181         else
2182                 return 0;
2183 }
2184
2185 typedef gunichar2* (STDCALL *UnicodeStringDelegate) (gunichar2 *message);
2186
2187 LIBTEST_API int STDCALL 
2188 mono_test_marshal_return_unicode_string_delegate (UnicodeStringDelegate del)
2189 {
2190         const char m[] = "abcdef";
2191         gunichar2 *s2, *res;
2192         glong len;
2193
2194         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
2195
2196         res = del (s2);
2197
2198         marshal_free (res);
2199
2200         return 0;
2201 }
2202
2203 LIBTEST_API int STDCALL 
2204 mono_test_marshal_out_string_array_delegate (char **arr, int len, ArrayDelegate del)
2205 {
2206         del (len, NULL, arr);
2207
2208         if (!strcmp (arr [0], "ABC") && !strcmp (arr [1], "DEF"))
2209                 return 0;
2210         else
2211                 return 1;
2212 }
2213
2214 typedef int (*CdeclDelegate) (int i, int j);
2215
2216 LIBTEST_API int STDCALL 
2217 mono_test_marshal_cdecl_delegate (CdeclDelegate del)
2218 {
2219         int i;
2220
2221         for (i = 0; i < 1000; ++i)
2222                 del (1, 2);
2223
2224         return 0;
2225 }
2226
2227 typedef char** (STDCALL *ReturnStringArrayDelegate) (int i);
2228
2229 LIBTEST_API int STDCALL 
2230 mono_test_marshal_return_string_array_delegate (ReturnStringArrayDelegate d)
2231 {
2232         char **arr = d (2);
2233         int res;
2234
2235         if (arr == NULL)
2236                 return 3;
2237
2238         if (strcmp (arr [0], "ABC") || strcmp (arr [1], "DEF"))
2239                 res = 1;
2240         else
2241                 res = 0;
2242
2243         marshal_free (arr);
2244
2245         return res;
2246 }
2247
2248 typedef int (STDCALL *ByrefStringDelegate) (char **s);
2249
2250 LIBTEST_API int STDCALL 
2251 mono_test_marshal_byref_string_delegate (ByrefStringDelegate d)
2252 {
2253         char *s = (char*)"ABC";
2254         int res;
2255
2256         res = d (&s);
2257         if (res != 0)
2258                 return res;
2259
2260         if (!strcmp (s, "DEF"))
2261                 res = 0;
2262         else
2263                 res = 2;
2264
2265         marshal_free (s);
2266
2267         return res;
2268 }
2269
2270 LIBTEST_API int STDCALL 
2271 add_delegate (int i, int j)
2272 {
2273         return i + j;
2274 }
2275
2276 LIBTEST_API gpointer STDCALL 
2277 mono_test_marshal_return_fnptr (void)
2278 {
2279         return &add_delegate;
2280 }
2281
2282 LIBTEST_API int STDCALL 
2283 mono_xr (int code)
2284 {
2285         printf ("codigo %x\n", code);
2286         return code + 1234;
2287 }
2288
2289 typedef struct {
2290         int handle;
2291 } HandleRef;
2292
2293 LIBTEST_API HandleRef STDCALL 
2294 mono_xr_as_handle (int code)
2295 {
2296         HandleRef ref;
2297
2298         memset (&ref, 0, sizeof (ref));
2299
2300         return ref;
2301 }
2302  
2303 typedef struct {
2304         int   a;
2305         void *handle1;
2306         void *handle2;
2307         int   b;
2308 } HandleStructs;
2309
2310 LIBTEST_API int STDCALL 
2311 mono_safe_handle_struct_ref (HandleStructs *x)
2312 {
2313         printf ("Dingus Ref! \n");
2314         printf ("Values: %d %d %p %p\n", x->a, x->b, x->handle1, x->handle2);
2315         if (x->a != 1234)
2316                 return 1;
2317         if (x->b != 8743)
2318                 return 2;
2319
2320         if (x->handle1 != (void*) 0x7080feed)
2321                 return 3;
2322
2323         if (x->handle2 != (void*) 0x1234abcd)
2324                 return 4;
2325
2326         return 0xf00d;
2327 }
2328
2329 LIBTEST_API int STDCALL 
2330 mono_safe_handle_struct (HandleStructs x)
2331 {
2332         printf ("Dingus Standard! \n");
2333         printf ("Values: %d %d %p %p\n", x.a, x.b, x.handle1, x.handle2);
2334         if (x.a != 1234)
2335                 return 1;
2336         if (x.b != 8743)
2337                 return 2;
2338
2339         if (x.handle1 != (void*) 0x7080feed)
2340                 return 3;
2341
2342         if (x.handle2 != (void*) 0x1234abcd)
2343                 return 4;
2344         
2345         return 0xf00f;
2346 }
2347
2348 typedef struct {
2349         void *a;
2350 } TrivialHandle;
2351
2352 LIBTEST_API int STDCALL 
2353 mono_safe_handle_struct_simple (TrivialHandle x)
2354 {
2355         printf ("The value is %p\n", x.a);
2356         return ((int)(gsize)x.a) * 2;
2357 }
2358
2359 LIBTEST_API int STDCALL 
2360 mono_safe_handle_return (void)
2361 {
2362         return 0x1000f00d;
2363 }
2364
2365 LIBTEST_API void STDCALL
2366 mono_safe_handle_ref (void **handle)
2367 {
2368         if (*handle != 0){
2369                 *handle = (void *) 0xbad;
2370                 return;
2371         }
2372
2373         *handle = (void *) 0x800d;
2374 }
2375
2376 LIBTEST_API double STDCALL
2377 mono_test_marshal_date_time (double d, double *d2)
2378 {
2379         *d2 = d;
2380         return d;
2381 }
2382
2383 /*
2384  * COM INTEROP TESTS
2385  */
2386
2387 #ifndef WIN32
2388
2389 typedef struct {
2390         guint16 vt;
2391         guint16 wReserved1;
2392         guint16 wReserved2;
2393         guint16 wReserved3;
2394         union {
2395                 gint64 llVal;
2396                 gint32 lVal;
2397                 guint8  bVal;
2398                 gint16 iVal;
2399                 float  fltVal;
2400                 double dblVal;
2401                 gint16 boolVal;
2402                 gunichar2* bstrVal;
2403                 gint8 cVal;
2404                 guint16 uiVal;
2405                 guint32 ulVal;
2406                 guint64 ullVal;
2407                 struct {
2408                         gpointer pvRecord;
2409                         gpointer pRecInfo;
2410                 };
2411         };
2412 } VARIANT;
2413
2414 typedef enum {
2415         VARIANT_TRUE = -1,
2416         VARIANT_FALSE = 0
2417 } VariantBool;
2418
2419 typedef enum {
2420         VT_EMPTY = 0,
2421         VT_NULL = 1,
2422         VT_I2 = 2,
2423         VT_I4 = 3,
2424         VT_R4 = 4,
2425         VT_R8 = 5,
2426         VT_CY = 6,
2427         VT_DATE = 7,
2428         VT_BSTR = 8,
2429         VT_DISPATCH = 9,
2430         VT_ERROR = 10,
2431         VT_BOOL = 11,
2432         VT_VARIANT = 12,
2433         VT_UNKNOWN = 13,
2434         VT_DECIMAL = 14,
2435         VT_I1 = 16,
2436         VT_UI1 = 17,
2437         VT_UI2 = 18,
2438         VT_UI4 = 19,
2439         VT_I8 = 20,
2440         VT_UI8 = 21,
2441         VT_INT = 22,
2442         VT_UINT = 23,
2443         VT_VOID = 24,
2444         VT_HRESULT = 25,
2445         VT_PTR = 26,
2446         VT_SAFEARRAY = 27,
2447         VT_CARRAY = 28,
2448         VT_USERDEFINED = 29,
2449         VT_LPSTR = 30,
2450         VT_LPWSTR = 31,
2451         VT_RECORD = 36,
2452         VT_FILETIME = 64,
2453         VT_BLOB = 65,
2454         VT_STREAM = 66,
2455         VT_STORAGE = 67,
2456         VT_STREAMED_OBJECT = 68,
2457         VT_STORED_OBJECT = 69,
2458         VT_BLOB_OBJECT = 70,
2459         VT_CF = 71,
2460         VT_CLSID = 72,
2461         VT_VECTOR = 4096,
2462         VT_ARRAY = 8192,
2463         VT_BYREF = 16384
2464 } VarEnum;
2465
2466 void VariantInit(VARIANT* vt)
2467 {
2468         vt->vt = VT_EMPTY;
2469 }
2470
2471 typedef struct
2472 {
2473         guint32 a;
2474         guint16 b;
2475         guint16 c;
2476         guint8 d[8];
2477 } GUID;
2478
2479 #define S_OK 0
2480
2481 #endif
2482
2483 LIBTEST_API int STDCALL 
2484 mono_test_marshal_bstr_in(gunichar2* bstr)
2485 {
2486         gint32 result = 0;
2487         gchar* bstr_utf8 = g_utf16_to_utf8 (bstr, -1, NULL, NULL, NULL);
2488         result = strcmp("mono_test_marshal_bstr_in", bstr_utf8);
2489         g_free(bstr_utf8);
2490         if (result == 0)
2491                 return 0;
2492         return 1;
2493 }
2494
2495 LIBTEST_API int STDCALL 
2496 mono_test_marshal_bstr_out(gunichar2** bstr)
2497 {
2498         *bstr = marshal_bstr_alloc ("mono_test_marshal_bstr_out");
2499         return 0;
2500 }
2501
2502 LIBTEST_API int STDCALL 
2503 mono_test_marshal_bstr_in_null(gunichar2* bstr)
2504 {
2505         if (!bstr)
2506                 return 0;
2507         return 1;
2508 }
2509
2510 LIBTEST_API int STDCALL 
2511 mono_test_marshal_bstr_out_null(gunichar2** bstr)
2512 {
2513         *bstr = NULL;
2514         return 0;
2515 }
2516
2517 LIBTEST_API int STDCALL 
2518 mono_test_marshal_variant_in_sbyte(VARIANT variant)
2519 {
2520         if (variant.vt == VT_I1 && variant.cVal == 100)
2521                 return 0;
2522         return 1;
2523 }
2524
2525 LIBTEST_API int STDCALL 
2526 mono_test_marshal_variant_in_byte(VARIANT variant)
2527 {
2528         if (variant.vt == VT_UI1 && variant.bVal == 100)
2529                 return 0;
2530         return 1;
2531 }
2532
2533 LIBTEST_API int STDCALL 
2534 mono_test_marshal_variant_in_short(VARIANT variant)
2535 {
2536         if (variant.vt == VT_I2 && variant.iVal == 314)
2537                 return 0;
2538         return 1;
2539 }
2540
2541 LIBTEST_API int STDCALL 
2542 mono_test_marshal_variant_in_ushort(VARIANT variant)
2543 {
2544         if (variant.vt == VT_UI2 && variant.uiVal == 314)
2545                 return 0;
2546         return 1;
2547 }
2548
2549 LIBTEST_API int STDCALL 
2550 mono_test_marshal_variant_in_int(VARIANT variant)
2551 {
2552         if (variant.vt == VT_I4 && variant.lVal == 314)
2553                 return 0;
2554         return 1;
2555 }
2556
2557 LIBTEST_API int STDCALL 
2558 mono_test_marshal_variant_in_uint(VARIANT variant)
2559 {
2560         if (variant.vt == VT_UI4 && variant.ulVal == 314)
2561                 return 0;
2562         return 1;
2563 }
2564
2565 LIBTEST_API int STDCALL 
2566 mono_test_marshal_variant_in_long(VARIANT variant)
2567 {
2568         if (variant.vt == VT_I8 && variant.llVal == 314)
2569                 return 0;
2570         return 1;
2571 }
2572
2573 LIBTEST_API int STDCALL 
2574 mono_test_marshal_variant_in_ulong(VARIANT variant)
2575 {
2576         if (variant.vt == VT_UI8 && variant.ullVal == 314)
2577                 return 0;
2578         return 1;
2579 }
2580
2581 LIBTEST_API int STDCALL 
2582 mono_test_marshal_variant_in_float(VARIANT variant)
2583 {
2584         if (variant.vt == VT_R4 && (variant.fltVal - 3.14)/3.14 < .001)
2585                 return 0;
2586         return 1;
2587 }
2588
2589 LIBTEST_API int STDCALL 
2590 mono_test_marshal_variant_in_double(VARIANT variant)
2591 {
2592         if (variant.vt == VT_R8 && (variant.dblVal - 3.14)/3.14 < .001)
2593                 return 0;
2594         return 1;
2595 }
2596
2597 LIBTEST_API int STDCALL 
2598 mono_test_marshal_variant_in_bstr(VARIANT variant)
2599 {
2600         gint32 result = 0;
2601         gchar* bstr_utf8 = g_utf16_to_utf8 (variant.bstrVal, -1, NULL, NULL, NULL);
2602         result = strcmp("PI", bstr_utf8);
2603         g_free(bstr_utf8);
2604
2605         if (variant.vt == VT_BSTR && !result)
2606                 return 0;
2607         return 1;
2608 }
2609
2610 LIBTEST_API int STDCALL 
2611 mono_test_marshal_variant_in_bool_true (VARIANT variant)
2612 {
2613         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_TRUE)
2614                 return 0;
2615         return 1;
2616 }
2617
2618 LIBTEST_API int STDCALL 
2619 mono_test_marshal_variant_in_bool_false (VARIANT variant)
2620 {
2621         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_FALSE)
2622                 return 0;
2623         return 1;
2624 }
2625
2626 LIBTEST_API int STDCALL 
2627 mono_test_marshal_variant_out_sbyte(VARIANT* variant)
2628 {
2629         variant->vt = VT_I1;
2630         variant->cVal = 100;
2631
2632         return 0;
2633 }
2634
2635 LIBTEST_API int STDCALL 
2636 mono_test_marshal_variant_out_byte(VARIANT* variant)
2637 {       
2638         variant->vt = VT_UI1;
2639         variant->bVal = 100;
2640
2641         return 0;
2642 }
2643
2644 LIBTEST_API int STDCALL 
2645 mono_test_marshal_variant_out_short(VARIANT* variant)
2646 {
2647         variant->vt = VT_I2;
2648         variant->iVal = 314;
2649
2650         return 0;
2651 }
2652
2653 LIBTEST_API int STDCALL 
2654 mono_test_marshal_variant_out_ushort(VARIANT* variant)
2655 {
2656         variant->vt = VT_UI2;
2657         variant->uiVal = 314;
2658
2659         return 0;
2660 }
2661
2662 LIBTEST_API int STDCALL 
2663 mono_test_marshal_variant_out_int(VARIANT* variant)
2664 {
2665         variant->vt = VT_I4;
2666         variant->lVal = 314;
2667
2668         return 0;
2669 }
2670
2671 LIBTEST_API int STDCALL 
2672 mono_test_marshal_variant_out_uint(VARIANT* variant)
2673 {
2674         variant->vt = VT_UI4;
2675         variant->ulVal = 314;
2676
2677         return 0;
2678 }
2679
2680 LIBTEST_API int STDCALL 
2681 mono_test_marshal_variant_out_long(VARIANT* variant)
2682 {
2683         variant->vt = VT_I8;
2684         variant->llVal = 314;
2685
2686         return 0;
2687 }
2688
2689 LIBTEST_API int STDCALL 
2690 mono_test_marshal_variant_out_ulong(VARIANT* variant)
2691 {
2692         variant->vt = VT_UI8;
2693         variant->ullVal = 314;
2694
2695         return 0;
2696 }
2697
2698 LIBTEST_API int STDCALL 
2699 mono_test_marshal_variant_out_float(VARIANT* variant)
2700 {
2701         variant->vt = VT_R4;
2702         variant->fltVal = 3.14;
2703
2704         return 0;
2705 }
2706
2707 LIBTEST_API int STDCALL 
2708 mono_test_marshal_variant_out_double(VARIANT* variant)
2709 {
2710         variant->vt = VT_R8;
2711         variant->dblVal = 3.14;
2712
2713         return 0;
2714 }
2715
2716 LIBTEST_API int STDCALL 
2717 mono_test_marshal_variant_out_bstr(VARIANT* variant)
2718 {
2719         variant->vt = VT_BSTR;
2720         variant->bstrVal = marshal_bstr_alloc("PI");
2721
2722         return 0;
2723 }
2724
2725 LIBTEST_API int STDCALL 
2726 mono_test_marshal_variant_out_bool_true (VARIANT* variant)
2727 {
2728         variant->vt = VT_BOOL;
2729         variant->boolVal = VARIANT_TRUE;
2730
2731         return 0;
2732 }
2733
2734 LIBTEST_API int STDCALL 
2735 mono_test_marshal_variant_out_bool_false (VARIANT* variant)
2736 {
2737         variant->vt = VT_BOOL;
2738         variant->boolVal = VARIANT_FALSE;
2739
2740         return 0;
2741 }
2742
2743 typedef int (STDCALL *VarFunc) (int vt, VARIANT variant);
2744 typedef int (STDCALL *VarRefFunc) (int vt, VARIANT* variant);
2745
2746 LIBTEST_API int STDCALL 
2747 mono_test_marshal_variant_in_sbyte_unmanaged(VarFunc func)
2748 {
2749         VARIANT vt;
2750         vt.vt = VT_I1;
2751         vt.cVal = -100;
2752         return func (VT_I1, vt);
2753 }
2754
2755 LIBTEST_API int STDCALL 
2756 mono_test_marshal_variant_in_byte_unmanaged(VarFunc func)
2757 {
2758         VARIANT vt;
2759         vt.vt = VT_UI1;
2760         vt.bVal = 100;
2761         return func (VT_UI1, vt);
2762 }
2763
2764 LIBTEST_API int STDCALL 
2765 mono_test_marshal_variant_in_short_unmanaged(VarFunc func)
2766 {
2767         VARIANT vt;
2768         vt.vt = VT_I2;
2769         vt.iVal = -100;
2770         return func (VT_I2, vt);
2771 }
2772
2773 LIBTEST_API int STDCALL 
2774 mono_test_marshal_variant_in_ushort_unmanaged(VarFunc func)
2775 {
2776         VARIANT vt;
2777         vt.vt = VT_UI2;
2778         vt.uiVal = 100;
2779         return func (VT_UI2, vt);
2780 }
2781
2782 LIBTEST_API int STDCALL 
2783 mono_test_marshal_variant_in_int_unmanaged(VarFunc func)
2784 {
2785         VARIANT vt;
2786         vt.vt = VT_I4;
2787         vt.lVal = -100;
2788         return func (VT_I4, vt);
2789 }
2790
2791 LIBTEST_API int STDCALL 
2792 mono_test_marshal_variant_in_uint_unmanaged(VarFunc func)
2793 {
2794         VARIANT vt;
2795         vt.vt = VT_UI4;
2796         vt.ulVal = 100;
2797         return func (VT_UI4, vt);
2798 }
2799
2800 LIBTEST_API int STDCALL 
2801 mono_test_marshal_variant_in_long_unmanaged(VarFunc func)
2802 {
2803         VARIANT vt;
2804         vt.vt = VT_I8;
2805         vt.llVal = -100;
2806         return func (VT_I8, vt);
2807 }
2808
2809 LIBTEST_API int STDCALL 
2810 mono_test_marshal_variant_in_ulong_unmanaged(VarFunc func)
2811 {
2812         VARIANT vt;
2813         vt.vt = VT_UI8;
2814         vt.ullVal = 100;
2815         return func (VT_UI8, vt);
2816 }
2817
2818 LIBTEST_API int STDCALL 
2819 mono_test_marshal_variant_in_float_unmanaged(VarFunc func)
2820 {
2821         VARIANT vt;
2822         vt.vt = VT_R4;
2823         vt.fltVal = 3.14;
2824         return func (VT_R4, vt);
2825 }
2826
2827 LIBTEST_API int STDCALL 
2828 mono_test_marshal_variant_in_double_unmanaged(VarFunc func)
2829 {
2830         VARIANT vt;
2831         vt.vt = VT_R8;
2832         vt.dblVal = 3.14;
2833         return func (VT_R8, vt);
2834 }
2835
2836 LIBTEST_API int STDCALL 
2837 mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func)
2838 {
2839         VARIANT vt;
2840         vt.vt = VT_BSTR;
2841         vt.bstrVal = marshal_bstr_alloc("PI");
2842         return func (VT_BSTR, vt);
2843 }
2844
2845 LIBTEST_API int STDCALL 
2846 mono_test_marshal_variant_in_bool_true_unmanaged(VarFunc func)
2847 {
2848         VARIANT vt;
2849         vt.vt = VT_BOOL;
2850         vt.boolVal = VARIANT_TRUE;
2851         return func (VT_BOOL, vt);
2852 }
2853
2854 LIBTEST_API int STDCALL 
2855 mono_test_marshal_variant_in_bool_false_unmanaged(VarFunc func)
2856 {
2857         VARIANT vt;
2858         vt.vt = VT_BOOL;
2859         vt.boolVal = VARIANT_FALSE;
2860         return func (VT_BOOL, vt);
2861 }
2862
2863 LIBTEST_API int STDCALL 
2864 mono_test_marshal_variant_out_sbyte_unmanaged(VarRefFunc func)
2865 {
2866         VARIANT vt;
2867         VariantInit (&vt);
2868         func (VT_I1, &vt);
2869         if (vt.vt == VT_I1 && vt.cVal == -100)
2870                 return 0;
2871         return 1;
2872 }
2873
2874 LIBTEST_API int STDCALL 
2875 mono_test_marshal_variant_out_byte_unmanaged(VarRefFunc func)
2876 {
2877         VARIANT vt;
2878         VariantInit (&vt);
2879         func (VT_UI1, &vt);
2880         if (vt.vt == VT_UI1 && vt.bVal == 100)
2881                 return 0;
2882         return 1;
2883 }
2884
2885 LIBTEST_API int STDCALL 
2886 mono_test_marshal_variant_out_short_unmanaged(VarRefFunc func)
2887 {
2888         VARIANT vt;
2889         VariantInit (&vt);
2890         func (VT_I2, &vt);
2891         if (vt.vt == VT_I2 && vt.iVal == -100)
2892                 return 0;
2893         return 1;
2894 }
2895
2896 LIBTEST_API int STDCALL 
2897 mono_test_marshal_variant_out_ushort_unmanaged(VarRefFunc func)
2898 {
2899         VARIANT vt;
2900         VariantInit (&vt);
2901         func (VT_UI2, &vt);
2902         if (vt.vt == VT_UI2 && vt.uiVal == 100)
2903                 return 0;
2904         return 1;
2905 }
2906
2907 LIBTEST_API int STDCALL 
2908 mono_test_marshal_variant_out_int_unmanaged(VarRefFunc func)
2909 {
2910         VARIANT vt;
2911         VariantInit (&vt);
2912         func (VT_I4, &vt);
2913         if (vt.vt == VT_I4 && vt.lVal == -100)
2914                 return 0;
2915         return 1;
2916 }
2917
2918 LIBTEST_API int STDCALL 
2919 mono_test_marshal_variant_out_uint_unmanaged(VarRefFunc func)
2920 {
2921         VARIANT vt;
2922         VariantInit (&vt);
2923         func (VT_UI4, &vt);
2924         if (vt.vt == VT_UI4 && vt.ulVal == 100)
2925                 return 0;
2926         return 1;
2927 }
2928
2929 LIBTEST_API int STDCALL 
2930 mono_test_marshal_variant_out_long_unmanaged(VarRefFunc func)
2931 {
2932         VARIANT vt;
2933         VariantInit (&vt);
2934         func (VT_I8, &vt);
2935         if (vt.vt == VT_I8 && vt.llVal == -100)
2936                 return 0;
2937         return 1;
2938 }
2939
2940 LIBTEST_API int STDCALL 
2941 mono_test_marshal_variant_out_ulong_unmanaged(VarRefFunc func)
2942 {
2943         VARIANT vt;
2944         VariantInit (&vt);
2945         func (VT_UI8, &vt);
2946         if (vt.vt == VT_UI8 && vt.ullVal == 100)
2947                 return 0;
2948         return 1;
2949 }
2950
2951 LIBTEST_API int STDCALL 
2952 mono_test_marshal_variant_out_float_unmanaged(VarRefFunc func)
2953 {
2954         VARIANT vt;
2955         VariantInit (&vt);
2956         func (VT_R4, &vt);
2957         if (vt.vt == VT_R4 && fabs (vt.fltVal - 3.14f) < 1e-10)
2958                 return 0;
2959         return 1;
2960 }
2961
2962 LIBTEST_API int STDCALL 
2963 mono_test_marshal_variant_out_double_unmanaged(VarRefFunc func)
2964 {
2965         VARIANT vt;
2966         VariantInit (&vt);
2967         func (VT_R8, &vt);
2968         if (vt.vt == VT_R8 && fabs (vt.dblVal - 3.14) < 1e-10)
2969                 return 0;
2970         return 1;
2971 }
2972
2973 LIBTEST_API int STDCALL 
2974 mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func)
2975 {
2976         VARIANT vt;
2977         gchar* bstr_utf8;
2978         gint32 result = 0;
2979
2980
2981         VariantInit (&vt);
2982         func (VT_BSTR, &vt);
2983         bstr_utf8 = g_utf16_to_utf8 (vt.bstrVal, -1, NULL, NULL, NULL);
2984         result = strcmp("PI", bstr_utf8);
2985         g_free(bstr_utf8);
2986         if (vt.vt == VT_BSTR && !result)
2987                 return 0;
2988         return 1;
2989 }
2990
2991 LIBTEST_API int STDCALL 
2992 mono_test_marshal_variant_out_bool_true_unmanaged(VarRefFunc func)
2993 {
2994         VARIANT vt;
2995         VariantInit (&vt);
2996         func (VT_BOOL, &vt);
2997         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
2998                 return 0;
2999         return 1;
3000 }
3001
3002 LIBTEST_API int STDCALL 
3003 mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
3004 {
3005         VARIANT vt;
3006         VariantInit (&vt);
3007         func (VT_BOOL, &vt);
3008         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
3009                 return 0;
3010         return 1;
3011 }
3012
3013 typedef struct MonoComObject MonoComObject;
3014
3015 typedef struct
3016 {
3017         int (STDCALL *QueryInterface)(MonoComObject* pUnk, gpointer riid, gpointer* ppv);
3018         int (STDCALL *AddRef)(MonoComObject* pUnk);
3019         int (STDCALL *Release)(MonoComObject* pUnk);
3020         int (STDCALL *get_ITest)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3021         int (STDCALL *SByteIn)(MonoComObject* pUnk, char a);
3022         int (STDCALL *ByteIn)(MonoComObject* pUnk, unsigned char a);
3023         int (STDCALL *ShortIn)(MonoComObject* pUnk, short a);
3024         int (STDCALL *UShortIn)(MonoComObject* pUnk, unsigned short a);
3025         int (STDCALL *IntIn)(MonoComObject* pUnk, int a);
3026         int (STDCALL *UIntIn)(MonoComObject* pUnk, unsigned int a);
3027         int (STDCALL *LongIn)(MonoComObject* pUnk, gint64 a);
3028         int (STDCALL *ULongIn)(MonoComObject* pUnk, guint64 a);
3029         int (STDCALL *FloatIn)(MonoComObject* pUnk, float a);
3030         int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a);
3031         int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
3032         int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3033 } MonoIUnknown;
3034
3035 struct MonoComObject
3036 {
3037         MonoIUnknown* vtbl;
3038         int m_ref;
3039 };
3040
3041 static GUID IID_ITest = {0, 0, 0, {0,0,0,0,0,0,0,1}};
3042 static GUID IID_IMonoUnknown = {0, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3043 static GUID IID_IMonoDispatch = {0x00020400, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3044
3045 LIBTEST_API int STDCALL
3046 MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv)
3047 {
3048
3049         *ppv = NULL;
3050         if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) {
3051                 *ppv = pUnk;
3052                 return S_OK;
3053         }
3054         else if (!memcmp(riid, &IID_ITest, sizeof(GUID))) {
3055                 *ppv = pUnk;
3056                 return S_OK;
3057         }
3058         else if (!memcmp(riid, &IID_IMonoDispatch, sizeof(GUID))) {
3059                 *ppv = pUnk;
3060                 return S_OK;
3061         }
3062         return 0x80004002; //E_NOINTERFACE;
3063 }
3064
3065 LIBTEST_API int STDCALL 
3066 MonoAddRef(MonoComObject* pUnk)
3067 {
3068         return ++(pUnk->m_ref);
3069 }
3070
3071 LIBTEST_API int STDCALL 
3072 MonoRelease(MonoComObject* pUnk)
3073 {
3074         return --(pUnk->m_ref);
3075 }
3076
3077 LIBTEST_API int STDCALL 
3078 SByteIn(MonoComObject* pUnk, char a)
3079 {
3080         return S_OK;
3081 }
3082
3083 LIBTEST_API int STDCALL 
3084 ByteIn(MonoComObject* pUnk, unsigned char a)
3085 {
3086         return S_OK;
3087 }
3088
3089 LIBTEST_API int STDCALL 
3090 ShortIn(MonoComObject* pUnk, short a)
3091 {
3092         return S_OK;
3093 }
3094
3095 LIBTEST_API int STDCALL 
3096 UShortIn(MonoComObject* pUnk, unsigned short a)
3097 {
3098         return S_OK;
3099 }
3100
3101 LIBTEST_API int STDCALL 
3102 IntIn(MonoComObject* pUnk, int a)
3103 {
3104         return S_OK;
3105 }
3106
3107 LIBTEST_API int STDCALL 
3108 UIntIn(MonoComObject* pUnk, unsigned int a)
3109 {
3110         return S_OK;
3111 }
3112
3113 LIBTEST_API int STDCALL 
3114 LongIn(MonoComObject* pUnk, gint64 a)
3115 {
3116         return S_OK;
3117 }
3118
3119 LIBTEST_API int STDCALL 
3120 ULongIn(MonoComObject* pUnk, guint64 a)
3121 {
3122         return S_OK;
3123 }
3124
3125 LIBTEST_API int STDCALL 
3126 FloatIn(MonoComObject* pUnk, float a)
3127 {
3128         return S_OK;
3129 }
3130
3131 LIBTEST_API int STDCALL 
3132 DoubleIn(MonoComObject* pUnk, double a)
3133 {
3134         return S_OK;
3135 }
3136
3137 LIBTEST_API int STDCALL 
3138 ITestIn(MonoComObject* pUnk, MonoComObject *pUnk2)
3139 {
3140         return S_OK;
3141 }
3142
3143 LIBTEST_API int STDCALL 
3144 ITestOut(MonoComObject* pUnk, MonoComObject* *ppUnk)
3145 {
3146         return S_OK;
3147 }
3148
3149 LIBTEST_API int STDCALL 
3150 get_ITest(MonoComObject* pUnk, MonoComObject* *ppUnk)
3151 {
3152         return S_OK;
3153 }
3154
3155 static void create_com_object (MonoComObject** pOut)
3156 {
3157         *pOut = marshal_new0 (MonoComObject, 1);
3158         (*pOut)->vtbl = marshal_new0 (MonoIUnknown, 1);
3159
3160         (*pOut)->m_ref = 1;
3161         (*pOut)->vtbl->QueryInterface = MonoQueryInterface;
3162         (*pOut)->vtbl->AddRef = MonoAddRef;
3163         (*pOut)->vtbl->Release = MonoRelease;
3164         (*pOut)->vtbl->SByteIn = SByteIn;
3165         (*pOut)->vtbl->ByteIn = ByteIn;
3166         (*pOut)->vtbl->ShortIn = ShortIn;
3167         (*pOut)->vtbl->UShortIn = UShortIn;
3168         (*pOut)->vtbl->IntIn = IntIn;
3169         (*pOut)->vtbl->UIntIn = UIntIn;
3170         (*pOut)->vtbl->LongIn = LongIn;
3171         (*pOut)->vtbl->ULongIn = ULongIn;
3172         (*pOut)->vtbl->FloatIn = FloatIn;
3173         (*pOut)->vtbl->DoubleIn = DoubleIn;
3174         (*pOut)->vtbl->ITestIn = ITestIn;
3175         (*pOut)->vtbl->ITestOut = ITestOut;
3176         (*pOut)->vtbl->get_ITest = get_ITest;
3177 }
3178
3179 static MonoComObject* same_object = NULL;
3180
3181 LIBTEST_API int STDCALL 
3182 mono_test_marshal_com_object_create(MonoComObject* *pUnk)
3183 {
3184         create_com_object (pUnk);
3185
3186         if (!same_object)
3187                 same_object = *pUnk;
3188
3189         return 0;
3190 }
3191
3192 LIBTEST_API int STDCALL 
3193 mono_test_marshal_com_object_same(MonoComObject* *pUnk)
3194 {
3195         *pUnk = same_object;
3196
3197         return 0;
3198 }
3199
3200 LIBTEST_API int STDCALL 
3201 mono_test_marshal_com_object_destroy(MonoComObject *pUnk)
3202 {
3203         int ref = --(pUnk->m_ref);
3204         g_free(pUnk->vtbl);
3205         g_free(pUnk);
3206
3207         return ref;
3208 }
3209
3210 LIBTEST_API int STDCALL 
3211 mono_test_marshal_com_object_ref_count(MonoComObject *pUnk)
3212 {
3213         return pUnk->m_ref;
3214 }
3215
3216 LIBTEST_API int STDCALL 
3217 mono_test_marshal_ccw_itest (MonoComObject *pUnk)
3218 {
3219         int hr = 0;
3220         MonoComObject* pTest;
3221
3222         if (!pUnk)
3223                 return 1;
3224
3225         hr = pUnk->vtbl->SByteIn (pUnk, -100);
3226         if (hr != 0)
3227                 return 2;
3228         hr = pUnk->vtbl->ByteIn (pUnk, 100);
3229         if (hr != 0)
3230                 return 3;
3231         hr = pUnk->vtbl->ShortIn (pUnk, -100);
3232         if (hr != 0)
3233                 return 4;
3234         hr = pUnk->vtbl->UShortIn (pUnk, 100);
3235         if (hr != 0)
3236                 return 5;
3237         hr = pUnk->vtbl->IntIn (pUnk, -100);
3238         if (hr != 0)
3239                 return 6;
3240         hr = pUnk->vtbl->UIntIn (pUnk, 100);
3241         if (hr != 0)
3242                 return 7;
3243         hr = pUnk->vtbl->LongIn (pUnk, -100);
3244         if (hr != 0)
3245                 return 8;
3246         hr = pUnk->vtbl->ULongIn (pUnk, 100);
3247         if (hr != 0)
3248                 return 9;
3249         hr = pUnk->vtbl->FloatIn (pUnk, 3.14f);
3250         if (hr != 0)
3251                 return 10;
3252         hr = pUnk->vtbl->DoubleIn (pUnk, 3.14);
3253         if (hr != 0)
3254                 return 11;
3255         hr = pUnk->vtbl->ITestIn (pUnk, pUnk);
3256         if (hr != 0)
3257                 return 12;
3258         hr = pUnk->vtbl->ITestOut (pUnk, &pTest);
3259         if (hr != 0)
3260                 return 13;
3261
3262         return 0;
3263 }
3264
3265 /*
3266  * mono_method_get_unmanaged_thunk tests
3267  */
3268
3269 #if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__) || defined(__OpenBSD__)) || (defined(__ppc__) && defined(__APPLE__)))
3270 #define ALIGN(size) __attribute__ ((aligned(size)))
3271 #else
3272 #define ALIGN(size)
3273 #endif
3274
3275
3276 /* thunks.cs:TestStruct */
3277 typedef struct _TestStruct {
3278         int A;
3279         double B ALIGN(8);  /* align according to  mono's struct layout */
3280 } TestStruct;
3281
3282 /* Searches for mono symbols in all loaded modules */
3283 static gpointer
3284 lookup_mono_symbol (const char *symbol_name)
3285 {
3286         gpointer symbol;
3287         if (g_module_symbol (g_module_open (NULL, G_MODULE_BIND_LAZY), symbol_name, &symbol))
3288                 return symbol;
3289         else
3290                 return NULL;
3291 }
3292
3293 LIBTEST_API gpointer STDCALL
3294 mono_test_marshal_lookup_symbol (const char *symbol_name)
3295 {
3296         return lookup_mono_symbol (symbol_name);
3297 }
3298
3299 /**
3300  * test_method_thunk:
3301  *
3302  * @test_id: the test number
3303  * @test_method_handle: MonoMethod* of the C# test method
3304  * @create_object_method_handle: MonoMethod* of thunks.cs:Test.CreateObject
3305  */
3306 LIBTEST_API int STDCALL  
3307 test_method_thunk (int test_id, gpointer test_method_handle, gpointer create_object_method_handle)
3308 {
3309         gpointer (*mono_method_get_unmanaged_thunk)(gpointer)
3310                 = lookup_mono_symbol ("mono_method_get_unmanaged_thunk");
3311
3312         gpointer (*mono_string_new_wrapper)(const char *)
3313                 = lookup_mono_symbol ("mono_string_new_wrapper");
3314
3315         char* (*mono_string_to_utf8)(gpointer)
3316                 = lookup_mono_symbol ("mono_string_to_utf8");
3317
3318         gpointer (*mono_object_unbox)(gpointer)
3319                 = lookup_mono_symbol ("mono_object_unbox");
3320
3321         gpointer test_method, ex = NULL;
3322         gpointer (STDCALL *CreateObject)(gpointer*);
3323
3324
3325         if (!mono_method_get_unmanaged_thunk)
3326                 return 1;
3327
3328         test_method =  mono_method_get_unmanaged_thunk (test_method_handle);
3329         if (!test_method)
3330                 return 2;
3331
3332         CreateObject = mono_method_get_unmanaged_thunk (create_object_method_handle);
3333         if (!CreateObject)
3334                 return 3;
3335
3336
3337         switch (test_id) {
3338
3339         case 0: {
3340                 /* thunks.cs:Test.Test0 */
3341                 void (STDCALL *F)(gpointer*) = test_method;
3342                 F (&ex);
3343                 break;
3344         }
3345
3346         case 1: {
3347                 /* thunks.cs:Test.Test1 */
3348                 int (STDCALL *F)(gpointer*) = test_method;
3349                 if (F (&ex) != 42)
3350                         return 4;
3351                 break;
3352         }
3353
3354         case 2: {
3355                 /* thunks.cs:Test.Test2 */
3356                 gpointer (STDCALL *F)(gpointer, gpointer*) = test_method;
3357                 gpointer str = mono_string_new_wrapper ("foo");
3358                 if (str != F (str, &ex))
3359                         return 4;
3360                 break;
3361         }
3362
3363         case 3: {
3364                 /* thunks.cs:Test.Test3 */
3365                 gpointer (STDCALL *F)(gpointer, gpointer, gpointer*);
3366                 gpointer obj;
3367                 gpointer str;
3368
3369                 F = test_method;
3370                 obj = CreateObject (&ex);
3371                 str = mono_string_new_wrapper ("bar");
3372
3373                 if (str != F (obj, str, &ex))
3374                         return 4;
3375                 break;
3376         }
3377
3378         case 4: {
3379                 /* thunks.cs:Test.Test4 */
3380                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3381                 gpointer obj;
3382                 gpointer str;
3383
3384                 F = test_method;
3385                 obj = CreateObject (&ex);
3386                 str = mono_string_new_wrapper ("bar");
3387
3388                 if (42 != F (obj, str, 42, &ex))
3389                         return 4;
3390
3391                 break;
3392         }
3393
3394         case 5: {
3395                 /* thunks.cs:Test.Test5 */
3396                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3397                 gpointer obj;
3398                 gpointer str;
3399
3400                 F = test_method;
3401                 obj = CreateObject (&ex);
3402                 str = mono_string_new_wrapper ("bar");
3403
3404                 F (obj, str, 42, &ex);
3405                 if (!ex)
3406                     return 4;
3407
3408                 break;
3409         }
3410
3411         case 6: {
3412                 /* thunks.cs:Test.Test6 */
3413                 int (STDCALL *F)(gpointer, guint8, gint16, gint32, gint64, float, double,
3414                                  gpointer, gpointer*);
3415                 gpointer obj;
3416                 gpointer str = mono_string_new_wrapper ("Test6");
3417                 int res;
3418
3419                 F = test_method;
3420                 obj = CreateObject (&ex);
3421
3422                 res = F (obj, 254, 32700, -245378, 6789600, 3.1415, 3.1415, str, &ex);
3423                 if (ex)
3424                         return 4;
3425
3426                 if (!res)
3427                         return 5;
3428
3429                 break;
3430         }
3431
3432         case 7: {
3433                 /* thunks.cs:Test.Test7 */
3434                 gint64 (STDCALL *F)(gpointer*) = test_method;
3435                 if (F (&ex) != G_MAXINT64)
3436                         return 4;
3437                 break;
3438         }
3439
3440         case 8: {
3441                 /* thunks.cs:Test.Test8 */
3442                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3443                                  gpointer*, gpointer*);
3444
3445                 guint8 a1;
3446                 gint16 a2;
3447                 gint32 a3;
3448                 gint64 a4;
3449                 float a5;
3450                 double a6;
3451                 gpointer a7;
3452
3453                 F = test_method;
3454
3455                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3456                 if (ex)
3457                         return 4;
3458
3459                 if (!(a1 == 254 &&
3460                       a2 == 32700 &&
3461                       a3 == -245378 &&
3462                       a4 == 6789600 &&
3463                       (fabs (a5 - 3.1415) < 0.001) &&
3464                       (fabs (a6 - 3.1415) < 0.001) &&
3465                       strcmp (mono_string_to_utf8 (a7), "Test8") == 0))
3466                         return 5;
3467
3468                 break;
3469         }
3470
3471         case 9: {
3472                 /* thunks.cs:Test.Test9 */
3473                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3474                                  gpointer*, gpointer*);
3475
3476                 guint8 a1;
3477                 gint16 a2;
3478                 gint32 a3;
3479                 gint64 a4;
3480                 float a5;
3481                 double a6;
3482                 gpointer a7;
3483
3484                 F = test_method;
3485
3486                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3487                 if (!ex)
3488                         return 4;
3489
3490                 break;
3491         }
3492
3493         case 10: {
3494                 /* thunks.cs:Test.Test10 */
3495                 void (STDCALL *F)(gpointer*, gpointer*);
3496
3497                 gpointer obj1, obj2;
3498
3499                 obj1 = obj2 = CreateObject (&ex);
3500                 if (ex)
3501                         return 4;
3502
3503                 F = test_method;
3504
3505                 F (&obj1, &ex);
3506                 if (ex)
3507                         return 5;
3508
3509                 if (obj1 == obj2)
3510                         return 6;
3511
3512                 break;
3513         }
3514
3515         case 100: {
3516                 /* thunks.cs:TestStruct.Test0 */
3517                 int (STDCALL *F)(gpointer*, gpointer*);
3518
3519                 gpointer obj;
3520                 TestStruct *a1;
3521                 int res;
3522
3523                 obj = CreateObject (&ex);
3524                 if (ex)
3525                         return 4;
3526
3527                 if (!obj)
3528                         return 5;
3529
3530                 a1 = mono_object_unbox (obj);
3531                 if (!a1)
3532                         return 6;
3533
3534                 a1->A = 42;
3535                 a1->B = 3.1415;
3536
3537                 F = test_method;
3538
3539                 res = F (obj, &ex);
3540                 if (ex)
3541                         return 7;
3542
3543                 if (!res)
3544                         return 8;
3545
3546                 /* check whether the call was really by value */
3547                 if (a1->A != 42 || a1->B != 3.1415)
3548                         return 9;
3549
3550                 break;
3551         }
3552
3553         case 101: {
3554                 /* thunks.cs:TestStruct.Test1 */
3555                 void (STDCALL *F)(gpointer, gpointer*);
3556
3557                 TestStruct *a1;
3558                 gpointer obj;
3559
3560                 obj = CreateObject (&ex);
3561                 if (ex)
3562                         return 4;
3563
3564                 if (!obj)
3565                         return 5;
3566
3567                 a1 = mono_object_unbox (obj);
3568                 if (!a1)
3569                         return 6;
3570
3571                 F = test_method;
3572
3573                 F (obj, &ex);
3574                 if (ex)
3575                         return 7;
3576
3577                 if (a1->A != 42)
3578                         return 8;
3579
3580                 if (!fabs (a1->B - 3.1415) < 0.001)
3581                         return 9;
3582
3583                 break;
3584         }
3585
3586         case 102: {
3587                 /* thunks.cs:TestStruct.Test2 */
3588                 gpointer (STDCALL *F)(gpointer*);
3589
3590                 TestStruct *a1;
3591                 gpointer obj;
3592
3593                 F = test_method;
3594
3595                 obj = F (&ex);
3596                 if (ex)
3597                         return 4;
3598
3599                 if (!obj)
3600                         return 5;
3601
3602                 a1 = mono_object_unbox (obj);
3603
3604                 if (a1->A != 42)
3605                         return 5;
3606
3607                 if (!fabs (a1->B - 3.1415) < 0.001)
3608                         return 6;
3609
3610                 break;
3611         }
3612
3613         case 103: {
3614                 /* thunks.cs:TestStruct.Test3 */
3615                 void (STDCALL *F)(gpointer, gpointer*);
3616
3617                 TestStruct *a1;
3618                 gpointer obj;
3619
3620                 obj = CreateObject (&ex);
3621                 if (ex)
3622                         return 4;
3623
3624                 if (!obj)
3625                         return 5;
3626                 
3627                 a1 = mono_object_unbox (obj);
3628
3629                 if (!a1)
3630                         return 6;
3631
3632                 a1->A = 42;
3633                 a1->B = 3.1415;
3634
3635                 F = test_method;
3636
3637                 F (obj, &ex);
3638                 if (ex)
3639                         return 4;
3640
3641                 if (a1->A != 1)
3642                         return 5;
3643
3644                 if (a1->B != 17)
3645                         return 6;
3646
3647                 break;
3648         }
3649
3650         default:
3651                 return 9;
3652
3653         }
3654
3655         return 0;
3656 }
3657
3658 typedef struct 
3659 {
3660         char a;
3661 } winx64_struct1;
3662
3663 LIBTEST_API int STDCALL  
3664 mono_test_Winx64_struct1_in (winx64_struct1 var)
3665 {
3666         if (var.a != 123)
3667                 return 1;
3668         return 0;
3669 }
3670
3671 typedef struct
3672 {
3673         char a;
3674         char b;
3675 } winx64_struct2;
3676
3677 LIBTEST_API int STDCALL  
3678 mono_test_Winx64_struct2_in (winx64_struct2 var)
3679 {
3680         if (var.a != 4)
3681                 return 1;
3682         if (var.b != 5)
3683                 return 2;
3684         return 0;
3685 }
3686
3687
3688 typedef struct
3689 {
3690         char a;
3691         char b;
3692         short c;
3693 } winx64_struct3;
3694
3695 LIBTEST_API int STDCALL  
3696 mono_test_Winx64_struct3_in (winx64_struct3 var)
3697 {
3698         if (var.a != 4)
3699                 return 1;
3700         if (var.b != 5)
3701                 return 2;
3702         if (var.c != 0x1234)
3703                 return 3;
3704         return 0;
3705 }
3706
3707 typedef struct
3708 {
3709         char a;
3710         char b;
3711         short c;
3712         unsigned int d;
3713 } winx64_struct4;
3714
3715 LIBTEST_API int STDCALL  
3716 mono_test_Winx64_struct4_in (winx64_struct4 var)
3717 {
3718         if (var.a != 4)
3719                 return 1;
3720         if (var.b != 5)
3721                 return 2;
3722         if (var.c != 0x1234)
3723                 return 3;
3724         if (var.d != 0x87654321)
3725                 return 4;
3726         return 0;
3727 }
3728
3729 typedef struct
3730 {
3731         char a;
3732         char b;
3733         char c;
3734 } winx64_struct5;
3735
3736 LIBTEST_API int STDCALL  
3737 mono_test_Winx64_struct5_in (winx64_struct5 var)
3738 {
3739         if (var.a != 4)
3740                 return 1;
3741         if (var.b != 5)
3742                 return 2;
3743         if (var.c != 6)
3744                 return 3;
3745         return 0;
3746 }
3747
3748 typedef struct
3749 {
3750         winx64_struct1 a;
3751         short b;
3752         char c;
3753 } winx64_struct6;
3754
3755 LIBTEST_API int STDCALL  
3756 mono_test_Winx64_struct6_in (winx64_struct6 var)
3757 {
3758         if (var.a.a != 4)
3759                 return 1;
3760         if (var.b != 5)
3761                 return 2;
3762         if (var.c != 6)
3763                 return 3;
3764         return 0;
3765 }
3766
3767 LIBTEST_API int STDCALL  
3768 mono_test_Winx64_structs_in1 (winx64_struct1 var1,
3769                          winx64_struct2 var2,
3770                          winx64_struct3 var3,
3771                          winx64_struct4 var4)
3772 {
3773         if (var1.a != 123)
3774                 return 1;
3775         
3776         if (var2.a != 4)
3777                 return 2;
3778         if (var2.b != 5)
3779                 return 3;
3780         
3781         if (var3.a != 4)
3782                 return 4;
3783         if (var3.b != 5)
3784                 return 2;
3785         if (var3.c != 0x1234)
3786                 return 5;
3787         
3788         if (var4.a != 4)
3789                 return 6;
3790         if (var4.b != 5)
3791                 return 7;
3792         if (var4.c != 0x1234)
3793                 return 8;
3794         if (var4.d != 0x87654321)
3795                 return 9;
3796         return 0;
3797 }
3798
3799 LIBTEST_API int STDCALL  
3800 mono_test_Winx64_structs_in2 (winx64_struct1 var1,
3801                          winx64_struct1 var2,
3802                          winx64_struct1 var3,
3803                          winx64_struct1 var4,
3804                          winx64_struct1 var5)
3805 {
3806         if (var1.a != 1)
3807                 return 1;
3808         if (var2.a != 2)
3809                 return 2;
3810         if (var3.a != 3)
3811                 return 3;
3812         if (var4.a != 4)
3813                 return 4;
3814         if (var5.a != 5)
3815                 return 5;
3816         
3817         return 0;
3818 }
3819
3820 LIBTEST_API int STDCALL  
3821 mono_test_Winx64_structs_in3 (winx64_struct1 var1,
3822                          winx64_struct5 var2,
3823                          winx64_struct1 var3,
3824                          winx64_struct5 var4,
3825                          winx64_struct1 var5,
3826                          winx64_struct5 var6)
3827 {
3828         if (var1.a != 1)
3829                 return 1;
3830         
3831         if (var2.a != 2)
3832                 return 2;
3833         if (var2.b != 3)
3834                 return 2;
3835         if (var2.c != 4)
3836                 return 4;
3837         
3838         if (var3.a != 5)
3839                 return 5;
3840         
3841         if (var4.a != 6)
3842                 return 6;
3843         if (var4.b != 7)
3844                 return 7;
3845         if (var4.c != 8)
3846                 return 8;
3847         
3848         if (var5.a != 9)
3849                 return 9;
3850
3851         if (var6.a != 10)
3852                 return 10;
3853         if (var6.b != 11)
3854                 return 11;
3855         if (var6.c != 12)
3856                 return 12;
3857         
3858         return 0;
3859 }
3860
3861 LIBTEST_API winx64_struct1 STDCALL  
3862 mono_test_Winx64_struct1_ret (void)
3863 {
3864         winx64_struct1 ret;
3865         ret.a = 123;
3866         return ret;
3867 }
3868
3869 LIBTEST_API winx64_struct2 STDCALL  
3870 mono_test_Winx64_struct2_ret (void)
3871 {
3872         winx64_struct2 ret;
3873         ret.a = 4;
3874         ret.b = 5;
3875         return ret;
3876 }
3877
3878 LIBTEST_API winx64_struct3 STDCALL  
3879 mono_test_Winx64_struct3_ret (void)
3880 {
3881         winx64_struct3 ret;
3882         ret.a = 4;
3883         ret.b = 5;
3884         ret.c = 0x1234;
3885         return ret;
3886 }
3887
3888 LIBTEST_API winx64_struct4 STDCALL  
3889 mono_test_Winx64_struct4_ret (void)
3890 {
3891         winx64_struct4 ret;
3892         ret.a = 4;
3893         ret.b = 5;
3894         ret.c = 0x1234;
3895         ret.d = 0x87654321;
3896         return ret;
3897 }
3898
3899 LIBTEST_API winx64_struct5 STDCALL  
3900 mono_test_Winx64_struct5_ret (void)
3901 {
3902         winx64_struct5 ret;
3903         ret.a = 4;
3904         ret.b = 5;
3905         ret.c = 6;
3906         return ret;
3907 }
3908
3909 LIBTEST_API winx64_struct1 STDCALL  
3910 mono_test_Winx64_struct1_ret_5_args (char a, char b, char c, char d, char e)
3911 {
3912         winx64_struct1 ret;
3913         ret.a = a + b + c + d + e;
3914         return ret;
3915 }
3916
3917 LIBTEST_API winx64_struct5 STDCALL
3918 mono_test_Winx64_struct5_ret6_args (char a, char b, char c, char d, char e)
3919 {
3920         winx64_struct5 ret;
3921         ret.a = a + b;
3922         ret.b = c + d;
3923         ret.c = e;
3924         return ret;
3925 }
3926
3927 typedef struct
3928 {
3929         float a;
3930         float b;
3931 } winx64_floatStruct;
3932
3933 LIBTEST_API int STDCALL  
3934 mono_test_Winx64_floatStruct (winx64_floatStruct a)
3935 {
3936         if (a.a > 5.6 || a.a < 5.4)
3937                 return 1;
3938
3939         if (a.b > 9.6 || a.b < 9.4)
3940                 return 2;
3941         
3942         return 0;
3943 }
3944
3945 typedef struct
3946 {
3947         double a;
3948 } winx64_doubleStruct;
3949
3950 LIBTEST_API int STDCALL  
3951 mono_test_Winx64_doubleStruct (winx64_doubleStruct a)
3952 {
3953         if (a.a > 5.6 || a.a < 5.4)
3954                 return 1;
3955         
3956         return 0;
3957 }
3958
3959 typedef int (STDCALL *managed_struct1_delegate) (winx64_struct1 a);
3960
3961 LIBTEST_API int STDCALL 
3962 mono_test_managed_Winx64_struct1_in(managed_struct1_delegate func)
3963 {
3964         winx64_struct1 val;
3965         val.a = 5;
3966         return func (val);
3967 }
3968
3969 typedef int (STDCALL *managed_struct5_delegate) (winx64_struct5 a);
3970
3971 LIBTEST_API int STDCALL 
3972 mono_test_managed_Winx64_struct5_in(managed_struct5_delegate func)
3973 {
3974         winx64_struct5 val;
3975         val.a = 5;
3976         val.b = 0x10;
3977         val.c = 0x99;
3978         return func (val);
3979 }
3980
3981 typedef int (STDCALL *managed_struct1_struct5_delegate) (winx64_struct1 a, winx64_struct5 b,
3982                                                          winx64_struct1 c, winx64_struct5 d,
3983                                                          winx64_struct1 e, winx64_struct5 f);
3984
3985 LIBTEST_API int STDCALL 
3986 mono_test_managed_Winx64_struct1_struct5_in(managed_struct1_struct5_delegate func)
3987 {
3988         winx64_struct1 a, c, e;
3989         winx64_struct5 b, d, f;
3990         a.a = 1;
3991         b.a = 2; b.b = 3; b.c = 4;
3992         c.a = 5;
3993         d.a = 6; d.b = 7; d.c = 8;
3994         e.a = 9;
3995         f.a = 10; f.b = 11; f.c = 12;
3996
3997         return func (a, b, c, d, e, f);
3998 }
3999
4000 typedef winx64_struct1 (STDCALL *managed_struct1_ret_delegate) (void);
4001
4002 LIBTEST_API int STDCALL 
4003 mono_test_Winx64_struct1_ret_managed (managed_struct1_ret_delegate func)
4004 {
4005         winx64_struct1 ret;
4006
4007         ret = func ();
4008
4009         if (ret.a != 0x45)
4010                 return 1;
4011         
4012         return 0;
4013 }
4014
4015 typedef winx64_struct5 (STDCALL *managed_struct5_ret_delegate) (void);
4016
4017 LIBTEST_API int STDCALL 
4018 mono_test_Winx64_struct5_ret_managed (managed_struct5_ret_delegate func)
4019 {
4020         winx64_struct5 ret;
4021
4022         ret = func ();
4023
4024         if (ret.a != 0x12)
4025                 return 1;
4026         if (ret.b != 0x34)
4027                 return 2;
4028         if (ret.c != 0x56)
4029                 return 3;
4030         
4031         return 0;
4032 }
4033
4034 LIBTEST_API int STDCALL 
4035 mono_test_marshal_bool_in (int arg, unsigned int expected, unsigned int bDefaultMarsh, unsigned int bBoolCustMarsh,
4036                            char bI1CustMarsh, unsigned char bU1CustMarsh, short bVBCustMarsh)
4037 {
4038         switch (arg) {
4039         case 1: 
4040                 if (bDefaultMarsh != expected)
4041                         return 1;
4042                 break;
4043         case 2: 
4044                 if (bBoolCustMarsh != expected)
4045                         return 2;
4046                 break;
4047         case 3: 
4048                 if (bI1CustMarsh != expected)
4049                         return 3;
4050                 break;
4051         case 4: 
4052                 if (bU1CustMarsh != expected)
4053                         return 4;
4054                 break;
4055         case 5: 
4056                 if (bVBCustMarsh != expected)
4057                         return 5;
4058                 break;
4059         default:
4060                 return 999;             
4061         }
4062         return 0;
4063 }
4064
4065 LIBTEST_API int STDCALL 
4066 mono_test_marshal_bool_out (int arg, unsigned int testVal, unsigned int* bDefaultMarsh, unsigned int* bBoolCustMarsh,
4067                            char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh)
4068 {
4069         switch (arg) {
4070         case 1: 
4071                 if (!bDefaultMarsh)
4072                         return 1;
4073                 *bDefaultMarsh = testVal;
4074                 break;  
4075         case 2: 
4076                 if (!bBoolCustMarsh)
4077                         return 2;
4078                 *bBoolCustMarsh = testVal;
4079                 break;  
4080         case 3: 
4081                 if (!bI1CustMarsh)
4082                         return 3;
4083                 *bI1CustMarsh = (char)testVal;
4084                 break;  
4085         case 4: 
4086                 if (!bU1CustMarsh)
4087                         return 4;
4088                 *bU1CustMarsh = (unsigned char)testVal;
4089                 break;  
4090         case 5: 
4091                 if (!bVBCustMarsh)
4092                         return 5;
4093                 *bVBCustMarsh = (unsigned short)testVal;
4094                 break;  
4095         default:
4096                 return 999;
4097         }
4098         return 0;
4099 }
4100
4101 LIBTEST_API int STDCALL 
4102 mono_test_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4103                             unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, 
4104                             unsigned short* bVBCustMarsh)
4105 {
4106         switch (arg) {
4107         case 1: 
4108                 if (!bDefaultMarsh)
4109                         return 1;
4110                 if (*bDefaultMarsh != expected)
4111                         return 2;
4112                 *bDefaultMarsh = testVal;
4113                 break;
4114         case 2: 
4115                 if (!bBoolCustMarsh)
4116                         return 3;
4117                 if (*bBoolCustMarsh != expected)
4118                         return 4;
4119                 *bBoolCustMarsh = testVal;
4120                 break;
4121         case 3: 
4122                 if (!bI1CustMarsh)
4123                         return 5;
4124                 if (*bI1CustMarsh != expected)
4125                         return 6;
4126                 *bI1CustMarsh = (char)testVal;
4127                 break;
4128         case 4: 
4129                 if (!bU1CustMarsh)
4130                         return 7;
4131                 if (*bU1CustMarsh != expected)
4132                         return 8;
4133                 *bU1CustMarsh = (unsigned char)testVal;
4134                 break;
4135         case 5: 
4136                 if (!bVBCustMarsh)
4137                         return 9;
4138                 if (*bVBCustMarsh != expected)
4139                         return 10;
4140                 *bVBCustMarsh = (unsigned short)testVal;
4141                 break;
4142         default:
4143                 return 999;             
4144         }
4145         return 0;
4146 }
4147
4148
4149 typedef int (STDCALL *MarshalBoolInDelegate) (int arg, unsigned int expected, unsigned int bDefaultMarsh,
4150         unsigned int bBoolCustMarsh, char bI1CustMarsh, unsigned char bU1CustMarsh, unsigned short bVBCustMarsh);
4151
4152 LIBTEST_API int STDCALL 
4153 mono_test_managed_marshal_bool_in (int arg, unsigned int expected, unsigned int testVal, MarshalBoolInDelegate pfcn)
4154 {
4155         if (!pfcn)
4156                 return 0x9900;
4157
4158         switch (arg) {
4159         case 1:
4160                 return pfcn (arg, expected, testVal, 0, 0, 0, 0);
4161         case 2:
4162                 return pfcn (arg, expected, 0, testVal,  0, 0, 0);
4163         case 3:
4164                 return pfcn (arg, expected, 0, 0, testVal, 0, 0);
4165         case 4:
4166                 return pfcn (arg, expected, 0, 0, 0, testVal, 0);
4167         case 5:
4168                 return pfcn (arg, expected, 0, 0, 0, 0, testVal);
4169         default:
4170                 return 0x9800;
4171         }
4172
4173         return 0;
4174 }
4175
4176 typedef int (STDCALL *MarshalBoolOutDelegate) (int arg, unsigned int expected, unsigned int* bDefaultMarsh,
4177         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4178
4179 LIBTEST_API int STDCALL 
4180 mono_test_managed_marshal_bool_out (int arg, unsigned int expected, unsigned int testVal, MarshalBoolOutDelegate pfcn)
4181 {
4182         int ret;
4183         unsigned int lDefaultMarsh, lBoolCustMarsh;
4184         char lI1CustMarsh = 0;
4185         unsigned char lU1CustMarsh = 0;
4186         unsigned short lVBCustMarsh = 0;
4187         lDefaultMarsh = lBoolCustMarsh = 0;
4188
4189         if (!pfcn)
4190                 return 0x9900;
4191
4192         switch (arg) {
4193         case 1: {
4194                 unsigned int ltVal = 0;
4195                 ret = pfcn (arg, testVal, &ltVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4196                 if (ret)
4197                         return 0x0100 + ret;
4198                 if (expected != ltVal)
4199                         return 0x0200;
4200                 break;
4201         }
4202         case 2: {
4203                 unsigned int ltVal = 0;
4204                 ret = pfcn (arg, testVal, &lDefaultMarsh, &ltVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4205                 if (ret)
4206                         return 0x0300 + ret;
4207                 if (expected != ltVal)
4208                         return 0x0400;
4209                 break;
4210         }
4211         case 3: {
4212                 char ltVal = 0;
4213                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &ltVal, &lU1CustMarsh, &lVBCustMarsh);
4214                 if (ret)
4215                         return 0x0500 + ret;
4216                 if (expected != ltVal)
4217                         return 0x0600;
4218                 break;
4219         }
4220         case 4: {
4221                 unsigned char ltVal = 0;
4222                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltVal, &lVBCustMarsh);
4223                 if (ret)
4224                         return 0x0700 + ret;
4225                 if (expected != ltVal)
4226                         return 0x0800;
4227                 break;
4228         }
4229         case 5: {
4230                 unsigned short ltVal = 0;
4231                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltVal);
4232                 if (ret)
4233                         return 0x0900 + ret;
4234                 if (expected != ltVal)
4235                         return 0x1000;
4236                 break;
4237         }
4238         default:
4239                 return 0x9800;
4240         }
4241
4242         return 0;
4243 }
4244
4245 typedef int (STDCALL *MarshalBoolRefDelegate) (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4246         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4247
4248 LIBTEST_API int STDCALL 
4249 mono_test_managed_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int outExpected,
4250                                     unsigned int outTestVal, MarshalBoolRefDelegate pfcn)
4251 {
4252         int ret;
4253         unsigned int lDefaultMarsh, lBoolCustMarsh;
4254         char lI1CustMarsh = 0;
4255         unsigned char lU1CustMarsh = 0;
4256         unsigned short lVBCustMarsh = 0;
4257         lDefaultMarsh = lBoolCustMarsh = 0;
4258
4259         if (!pfcn)
4260                 return 0x9900;
4261
4262         switch (arg) {
4263         case 1:
4264         {
4265                 unsigned int ltestVal = testVal;
4266                 ret = pfcn (arg, expected, outTestVal, &ltestVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4267                 if (ret)
4268                         return 0x0100 + ret;
4269                 if (outExpected != ltestVal)
4270                         return 0x0200;
4271                 break;
4272         }
4273         case 2:
4274         {
4275                 unsigned int ltestVal = testVal;
4276                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &ltestVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4277                 if (ret)
4278                         return 0x0300 + ret;
4279                 if (outExpected != ltestVal)
4280                         return 0x0400;
4281                 break;
4282         }
4283         case 3:
4284         {
4285                 char ltestVal = testVal;
4286                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &ltestVal, &lU1CustMarsh, &lVBCustMarsh);
4287                 if (ret)
4288                         return 0x0500 + ret;
4289                 if (outExpected != ltestVal)
4290                         return 0x0600;
4291                 break;
4292         }
4293         case 4:
4294         {
4295                 unsigned char ltestVal = testVal;
4296                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltestVal, &lVBCustMarsh);
4297                 if (ret)
4298                         return 0x0700 + ret;
4299                 if (outExpected != ltestVal)
4300                         return 0x0800;
4301                 break;
4302         }
4303         case 5:
4304         {
4305                 unsigned short ltestVal = testVal;
4306                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltestVal);
4307                 if (ret)
4308                         return 0x0900 + ret;
4309                 if (outExpected != ltestVal)
4310                         return 0x1000;
4311                 break;
4312         }
4313         default:
4314                 return 0x9800;
4315         }
4316
4317         return 0;
4318 }
4319
4320 #ifdef WIN32
4321
4322 LIBTEST_API int STDCALL 
4323 mono_test_marshal_safearray_out_1dim_vt_bstr_empty (SAFEARRAY** safearray)
4324 {
4325         /* Create an empty one-dimensional array of variants */
4326         SAFEARRAY *pSA;
4327         SAFEARRAYBOUND dimensions [1];
4328
4329         dimensions [0].lLbound = 0;
4330         dimensions [0].cElements = 0;
4331
4332         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4333         *safearray = pSA;
4334         return S_OK;
4335 }
4336
4337 LIBTEST_API int STDCALL 
4338 mono_test_marshal_safearray_out_1dim_vt_bstr (SAFEARRAY** safearray)
4339 {
4340         /* Create a one-dimensional array of 10 variants filled with "0" to "9" */
4341         SAFEARRAY *pSA;
4342         SAFEARRAYBOUND dimensions [1];
4343         long i;
4344         gchar buffer [20];
4345         HRESULT hr = S_OK;
4346         long indices [1];
4347
4348         dimensions [0].lLbound = 0;
4349         dimensions [0].cElements = 10;
4350
4351         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4352         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4353                 VARIANT vOut;
4354                 VariantInit (&vOut);
4355                 vOut.vt = VT_BSTR;
4356                 _ltoa (i,buffer,10);
4357                 vOut.bstrVal= marshal_bstr_alloc (buffer);
4358                 indices [0] = i;
4359                 if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4360                         VariantClear (&vOut);
4361                         SafeArrayDestroy (pSA);
4362                         return hr;
4363                 }
4364                 VariantClear (&vOut);
4365         }
4366         *safearray = pSA;
4367         return hr;
4368 }
4369
4370 LIBTEST_API int STDCALL 
4371 mono_test_marshal_safearray_out_2dim_vt_i4 (SAFEARRAY** safearray)
4372 {
4373         /* Create a two-dimensional array of 4x3 variants filled with 11, 12, 13, etc. */
4374         SAFEARRAY *pSA;
4375         SAFEARRAYBOUND dimensions [2];
4376         long i, j;
4377         HRESULT hr = S_OK;
4378         long indices [2];
4379
4380         dimensions [0].lLbound = 0;
4381         dimensions [0].cElements = 4;
4382         dimensions [1].lLbound = 0;
4383         dimensions [1].cElements = 3;
4384
4385         pSA= SafeArrayCreate(VT_VARIANT, 2, dimensions);
4386         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4387                 for (j= dimensions [1].lLbound; j< (dimensions [1].cElements + dimensions [1].lLbound); j++) {
4388                         VARIANT vOut;
4389                         VariantInit (&vOut);
4390                         vOut.vt = VT_I4;
4391                         vOut.lVal = (i+1)*10+(j+1);
4392                         indices [0] = i;
4393                         indices [1] = j;
4394                         if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4395                                 VariantClear (&vOut);
4396                                 SafeArrayDestroy (pSA);
4397                                 return hr;
4398                         }
4399                         VariantClear (&vOut);  // does a deep destroy of source VARIANT 
4400                 }
4401         }
4402         *safearray = pSA;
4403         return hr;
4404 }
4405
4406 LIBTEST_API int STDCALL 
4407 mono_test_marshal_safearray_out_4dim_vt_i4 (SAFEARRAY** safearray)
4408 {
4409         /* Create a four-dimensional array of 10x3x6x7 variants filled with their indices */
4410         /* Also use non zero lower bounds                                                 */
4411         SAFEARRAY *pSA;
4412         SAFEARRAYBOUND dimensions [4];
4413         long i;
4414         HRESULT hr = S_OK;
4415         VARIANT *pData;
4416
4417         dimensions [0].lLbound = 15;
4418         dimensions [0].cElements = 10;
4419         dimensions [1].lLbound = 20;
4420         dimensions [1].cElements = 3;
4421         dimensions [2].lLbound = 5;
4422         dimensions [2].cElements = 6;
4423         dimensions [3].lLbound = 12;
4424         dimensions [3].cElements = 7;
4425
4426         pSA= SafeArrayCreate (VT_VARIANT, 4, dimensions);
4427
4428         SafeArrayAccessData (pSA, (void **)&pData);
4429
4430         for (i= 0; i< 10*3*6*7; i++) {
4431                 VariantInit(&pData [i]);
4432                 pData [i].vt = VT_I4;
4433                 pData [i].lVal = i;
4434         }
4435         SafeArrayUnaccessData (pSA);
4436         *safearray = pSA;
4437         return hr;
4438 }
4439
4440 LIBTEST_API int STDCALL 
4441 mono_test_marshal_safearray_in_byval_1dim_empty (SAFEARRAY* safearray)
4442 {
4443         /* Check that array is one dimensional and empty */
4444
4445         UINT dim;
4446         long lbound, ubound;
4447         
4448         dim = SafeArrayGetDim (safearray);
4449         if (dim != 1)
4450                 return 1;
4451
4452         SafeArrayGetLBound (safearray, 1, &lbound);
4453         SafeArrayGetUBound (safearray, 1, &ubound);
4454
4455         if ((lbound > 0) || (ubound > 0))
4456                 return 1;
4457
4458         return 0;
4459 }
4460
4461 LIBTEST_API int STDCALL 
4462 mono_test_marshal_safearray_in_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4463 {
4464         /* Check that array is one dimensional containing integers from 1 to 10 */
4465
4466         UINT dim;
4467         long lbound, ubound;
4468         VARIANT *pData; 
4469         long i;
4470         int result=0;
4471
4472         dim = SafeArrayGetDim (safearray);
4473         if (dim != 1)
4474                 return 1;
4475
4476         SafeArrayGetLBound (safearray, 1, &lbound);
4477         SafeArrayGetUBound (safearray, 1, &ubound);
4478
4479         if ((lbound != 0) || (ubound != 9))
4480                 return 1;
4481
4482         SafeArrayAccessData (safearray, (void **)&pData);
4483         for (i= lbound; i <= ubound; i++) {
4484                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i + 1))
4485                         result = 1;
4486         }
4487         SafeArrayUnaccessData (safearray);
4488
4489         return result;
4490 }
4491
4492 LIBTEST_API int STDCALL 
4493 mono_test_marshal_safearray_in_byval_1dim_vt_mixed (SAFEARRAY* safearray)
4494 {
4495         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4496
4497         UINT dim;
4498         long lbound, ubound;
4499         VARIANT *pData; 
4500         long i;
4501         long indices [1];
4502         VARIANT element;
4503         int result=0;
4504
4505         VariantInit (&element);
4506
4507         dim = SafeArrayGetDim (safearray);
4508         if (dim != 1)
4509                 return 1;
4510
4511         SafeArrayGetLBound (safearray, 1, &lbound);
4512         SafeArrayGetUBound (safearray, 1, &ubound);
4513                 
4514         if ((lbound != 0) || (ubound != 12))
4515                 return 1;
4516
4517         SafeArrayAccessData (safearray, (void **)&pData);
4518         for (i= lbound; i <= ubound; i++) {
4519                 if ((i%2 == 0) && (pData [i].vt != VT_I4))
4520                         result = 1;
4521                 if ((i%2 == 1) && (pData [i].vt != VT_BSTR))
4522                         result = 1;
4523                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i))
4524                         result = 1;
4525         }
4526         SafeArrayUnaccessData (safearray);
4527
4528         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4529
4530         indices [0] = 0;
4531         element.vt = VT_I4;
4532         element.lVal = 333;
4533         SafeArrayPutElement (safearray, indices, &element);
4534         VariantClear (&element);
4535
4536         return result;
4537 }
4538
4539 LIBTEST_API int STDCALL 
4540 mono_test_marshal_safearray_in_byval_2dim_vt_i4 (SAFEARRAY* safearray)
4541 {
4542         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4543
4544         UINT dim;
4545         long lbound1, ubound1, lbound2, ubound2;
4546         long i, j, failed;
4547         long indices [2];
4548         VARIANT element;
4549
4550         VariantInit (&element);
4551
4552         dim = SafeArrayGetDim (safearray);
4553         if (dim != 2)
4554                 return 1;
4555
4556         SafeArrayGetLBound (safearray, 1, &lbound1);
4557         SafeArrayGetUBound (safearray, 1, &ubound1);
4558
4559         if ((lbound1 != 0) || (ubound1 != 1))
4560                 return 1;
4561
4562         SafeArrayGetLBound (safearray, 2, &lbound2);
4563         SafeArrayGetUBound (safearray, 2, &ubound2);
4564
4565         if ((lbound2 != 0) || (ubound2 != 3)) {
4566                 return 1;
4567         }
4568
4569         for (i= lbound1; i <= ubound1; i++) {
4570                 indices [0] = i;
4571                 for (j= lbound2; j <= ubound2; j++) {
4572                         indices [1] = j;
4573                         if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4574                                 return 1;
4575                         failed = ((element.vt != VT_I4) || (element.lVal != 10*(i+1)+(j+1)));
4576                         VariantClear (&element);
4577                         if (failed)
4578                                 return 1;
4579                 }
4580         }
4581
4582         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4583
4584         indices [0] = 0;
4585         indices [1] = 0;
4586         element.vt = VT_I4;
4587         element.lVal = 333;
4588         SafeArrayPutElement (safearray, indices, &element);
4589         VariantClear (&element);
4590
4591         return 0;
4592 }
4593
4594 LIBTEST_API int STDCALL 
4595 mono_test_marshal_safearray_in_byval_3dim_vt_bstr (SAFEARRAY* safearray)
4596 {
4597         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4598
4599         UINT dim;
4600         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4601         long i, j, k, failed;
4602         long indices [3];
4603         VARIANT element;
4604
4605         VariantInit (&element);
4606
4607         dim = SafeArrayGetDim (safearray);
4608         if (dim != 3)
4609                 return 1;
4610
4611         SafeArrayGetLBound (safearray, 1, &lbound1);
4612         SafeArrayGetUBound (safearray, 1, &ubound1);
4613
4614         if ((lbound1 != 0) || (ubound1 != 1))
4615                 return 1;
4616
4617         SafeArrayGetLBound (safearray, 2, &lbound2);
4618         SafeArrayGetUBound (safearray, 2, &ubound2);
4619
4620         if ((lbound2 != 0) || (ubound2 != 1))
4621                 return 1;
4622
4623         SafeArrayGetLBound (safearray, 3, &lbound3);
4624         SafeArrayGetUBound (safearray, 3, &ubound3);
4625
4626         if ((lbound3 != 0) || (ubound3 != 2))
4627                 return 1;
4628
4629         for (i= lbound1; i <= ubound1; i++) {
4630                 indices [0] = i;
4631                 for (j= lbound2; j <= ubound2; j++) {
4632                         indices [1] = j;
4633                 for (k= lbound3; k <= ubound3; k++) {
4634                                 indices [2] = k;
4635                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4636                                         return 1;
4637                                 failed = ((element.vt != VT_BSTR) 
4638                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4639                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4640                                 VariantClear (&element);
4641                                 if (failed)
4642                                         return 1;
4643                         }
4644                 }
4645         }
4646
4647         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4648
4649         indices [0] = 0;
4650         indices [1] = 0;
4651         indices [2] = 0;
4652         element.vt = VT_BSTR;
4653         element.bstrVal = SysAllocString(L"Should not be copied");
4654         SafeArrayPutElement (safearray, indices, &element);
4655         VariantClear (&element);
4656
4657         return 0;
4658 }
4659
4660 LIBTEST_API int STDCALL 
4661 mono_test_marshal_safearray_in_byref_3dim_vt_bstr (SAFEARRAY** safearray)
4662 {
4663         return mono_test_marshal_safearray_in_byval_3dim_vt_bstr (*safearray);
4664 }
4665
4666 LIBTEST_API int STDCALL 
4667 mono_test_marshal_safearray_in_out_byref_1dim_empty (SAFEARRAY** safearray)
4668 {
4669         /* Check that the input array is what is expected and change it so the caller can check */
4670         /* correct marshalling back to managed code                                             */
4671
4672         UINT dim;
4673         long lbound, ubound;
4674         SAFEARRAYBOUND dimensions [1];
4675         long i;
4676         wchar_t buffer [20];
4677         HRESULT hr = S_OK;
4678         long indices [1];
4679
4680         /* Check that in array is one dimensional and empty */
4681
4682         dim = SafeArrayGetDim (*safearray);
4683         if (dim != 1) {
4684                 return 1;
4685         }
4686
4687         SafeArrayGetLBound (*safearray, 1, &lbound);
4688         SafeArrayGetUBound (*safearray, 1, &ubound);
4689                 
4690         if ((lbound > 0) || (ubound > 0)) {
4691                 return 1;
4692         }
4693
4694         /* Re-dimension the array and return a one-dimensional array of 8 variants filled with "0" to "7" */
4695
4696         dimensions [0].lLbound = 0;
4697         dimensions [0].cElements = 8;
4698
4699         hr = SafeArrayRedim (*safearray, dimensions);
4700         if (hr != S_OK)
4701                 return 1;
4702
4703         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
4704                 VARIANT vOut;
4705                 VariantInit (&vOut);
4706                 vOut.vt = VT_BSTR;
4707                 _ltow (i,buffer,10);
4708                 vOut.bstrVal = SysAllocString (buffer);
4709                 indices [0] = i;
4710                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
4711                         VariantClear (&vOut);
4712                         SafeArrayDestroy (*safearray);
4713                         return hr;
4714                 }
4715                 VariantClear (&vOut);
4716         }
4717         return hr;
4718 }
4719
4720 LIBTEST_API int STDCALL 
4721 mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (SAFEARRAY** safearray)
4722 {
4723         /* Check that the input array is what is expected and change it so the caller can check */
4724         /* correct marshalling back to managed code                                             */
4725
4726         UINT dim;
4727         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4728         SAFEARRAYBOUND dimensions [1];
4729         long i, j, k, failed;
4730         wchar_t buffer [20];
4731         HRESULT hr = S_OK;
4732         long indices [3];
4733         VARIANT element;
4734
4735         VariantInit (&element);
4736
4737         /* Check that in array is three dimensional and contains the expected values */
4738
4739         dim = SafeArrayGetDim (*safearray);
4740         if (dim != 3)
4741                 return 1;
4742
4743         SafeArrayGetLBound (*safearray, 1, &lbound1);
4744         SafeArrayGetUBound (*safearray, 1, &ubound1);
4745
4746         if ((lbound1 != 0) || (ubound1 != 1))
4747                 return 1;
4748
4749         SafeArrayGetLBound (*safearray, 2, &lbound2);
4750         SafeArrayGetUBound (*safearray, 2, &ubound2);
4751
4752         if ((lbound2 != 0) || (ubound2 != 1))
4753                 return 1;
4754
4755         SafeArrayGetLBound (*safearray, 3, &lbound3);
4756         SafeArrayGetUBound (*safearray, 3, &ubound3);
4757
4758         if ((lbound3 != 0) || (ubound3 != 2))
4759                 return 1;
4760
4761         for (i= lbound1; i <= ubound1; i++) {
4762                 indices [0] = i;
4763                 for (j= lbound2; j <= ubound2; j++) {
4764                         indices [1] = j;
4765                         for (k= lbound3; k <= ubound3; k++) {
4766                                 indices [2] = k;
4767                                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
4768                                         return 1;
4769                                 failed = ((element.vt != VT_BSTR) 
4770                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4771                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4772                                 VariantClear (&element);
4773                                 if (failed)
4774                                         return 1;
4775                         }
4776                 }
4777         }
4778
4779         hr = SafeArrayDestroy (*safearray);
4780         if (hr != S_OK)
4781                 return 1;
4782
4783         /* Return a new one-dimensional array of 8 variants filled with "0" to "7" */
4784
4785         dimensions [0].lLbound = 0;
4786         dimensions [0].cElements = 8;
4787
4788         *safearray = SafeArrayCreate (VT_VARIANT, 1, dimensions);
4789
4790         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
4791                 VARIANT vOut;
4792                 VariantInit (&vOut);
4793                 vOut.vt = VT_BSTR;
4794                 _ltow (i,buffer,10);
4795                 vOut.bstrVal = SysAllocString (buffer);
4796                 indices [0] = i;
4797                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
4798                         VariantClear (&vOut);
4799                         SafeArrayDestroy (*safearray);
4800                         return hr;
4801                 }
4802                 VariantClear (&vOut);
4803         }
4804         return hr;
4805 }
4806
4807 LIBTEST_API int STDCALL 
4808 mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (SAFEARRAY** safearray)
4809 {
4810         /* Check that the input array is what is expected and change it so the caller can check */
4811         /* correct marshalling back to managed code                                             */
4812
4813         UINT dim;
4814         long lbound1, ubound1;
4815         long i, failed;
4816         HRESULT hr = S_OK;
4817         long indices [1];
4818         VARIANT element;
4819         
4820         VariantInit (&element);
4821
4822         /* Check that in array is one dimensional and contains the expected value */
4823
4824         dim = SafeArrayGetDim (*safearray);
4825         if (dim != 1)
4826                 return 1;
4827
4828         SafeArrayGetLBound (*safearray, 1, &lbound1);
4829         SafeArrayGetUBound (*safearray, 1, &ubound1);
4830
4831         ubound1 = 1;
4832         if ((lbound1 != 0) || (ubound1 != 1))
4833                 return 1;
4834         ubound1 = 0;
4835
4836         for (i= lbound1; i <= ubound1; i++) {
4837                 indices [0] = i;
4838                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
4839                         return 1;
4840                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
4841                 VariantClear (&element);
4842                 if (failed)
4843                         return 1;
4844         }
4845
4846         /* Change one of the elements of the array to verify that [out] parameter is marshalled back to the managed side */
4847
4848         indices [0] = 0;
4849         element.vt = VT_I4;
4850         element.lVal = -1;
4851         SafeArrayPutElement (*safearray, indices, &element);
4852         VariantClear (&element);
4853
4854         return hr;
4855 }
4856
4857 LIBTEST_API int STDCALL 
4858 mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4859 {
4860         /* Check that the input array is what is expected and change it so the caller can check */
4861         /* correct marshalling back to managed code                                             */
4862
4863         UINT dim;
4864         long lbound1, ubound1;
4865         SAFEARRAYBOUND dimensions [1];
4866         long i, failed;
4867         HRESULT hr = S_OK;
4868         long indices [1];
4869         VARIANT element;
4870
4871         VariantInit (&element);
4872
4873         /* Check that in array is one dimensional and contains the expected value */
4874
4875         dim = SafeArrayGetDim (safearray);
4876         if (dim != 1)
4877                 return 1;
4878
4879         SafeArrayGetLBound (safearray, 1, &lbound1);
4880         SafeArrayGetUBound (safearray, 1, &ubound1);
4881                 
4882         if ((lbound1 != 0) || (ubound1 != 0))
4883                 return 1;
4884
4885         for (i= lbound1; i <= ubound1; i++) {
4886                 indices [0] = i;
4887                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4888                         return 1;
4889                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
4890                 VariantClear (&element);
4891                 if (failed)
4892                         return 1;
4893         }
4894
4895         /* Change the array to verify how [out] parameter is marshalled back to the managed side */
4896
4897         /* Redimension the array */
4898         dimensions [0].lLbound = lbound1;
4899         dimensions [0].cElements = 2;
4900         hr = SafeArrayRedim(safearray, dimensions);
4901
4902         indices [0] = 0;
4903         element.vt = VT_I4;
4904         element.lVal = 12345;
4905         SafeArrayPutElement (safearray, indices, &element);
4906         VariantClear (&element);
4907
4908         indices [0] = 1;
4909         element.vt = VT_I4;
4910         element.lVal = -12345;
4911         SafeArrayPutElement (safearray, indices, &element);
4912         VariantClear (&element);
4913
4914         return hr;
4915 }
4916
4917 LIBTEST_API int STDCALL 
4918 mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (SAFEARRAY* safearray)
4919 {
4920         /* Check that the input array is what is expected and change it so the caller can check */
4921         /* correct marshalling back to managed code                                             */
4922
4923         UINT dim;
4924         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4925         long i, j, k, failed;
4926         HRESULT hr = S_OK;
4927         long indices [3];
4928         VARIANT element;
4929
4930         VariantInit (&element);
4931
4932         /* Check that in array is three dimensional and contains the expected values */
4933
4934         dim = SafeArrayGetDim (safearray);
4935         if (dim != 3)
4936                 return 1;
4937
4938         SafeArrayGetLBound (safearray, 1, &lbound1);
4939         SafeArrayGetUBound (safearray, 1, &ubound1);
4940
4941         if ((lbound1 != 0) || (ubound1 != 1))
4942                 return 1;
4943
4944         SafeArrayGetLBound (safearray, 2, &lbound2);
4945         SafeArrayGetUBound (safearray, 2, &ubound2);
4946
4947         if ((lbound2 != 0) || (ubound2 != 1))
4948                 return 1;
4949
4950         SafeArrayGetLBound (safearray, 3, &lbound3);
4951         SafeArrayGetUBound (safearray, 3, &ubound3);
4952
4953         if ((lbound3 != 0) || (ubound3 != 2))
4954                 return 1;
4955
4956         for (i= lbound1; i <= ubound1; i++) {
4957                 indices [0] = i;
4958                 for (j= lbound2; j <= ubound2; j++) {
4959                         indices [1] = j;
4960                         for (k= lbound3; k <= ubound3; k++) {
4961                                 indices [2] = k;
4962                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4963                                         return 1;
4964                                 failed = ((element.vt != VT_BSTR) 
4965                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4966                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4967                                 VariantClear (&element);
4968                                 if (failed)
4969                                         return 1;
4970                         }
4971                 }
4972         }
4973
4974         /* Change the elements of the array to verify that [out] parameter is marshalled back to the managed side */
4975
4976         indices [0] = 1;
4977         indices [1] = 1;
4978         indices [2] = 2;
4979         element.vt = VT_I4;
4980         element.lVal = 333;
4981         SafeArrayPutElement (safearray, indices, &element);
4982         VariantClear (&element);
4983
4984         indices [0] = 1;
4985         indices [1] = 1;
4986         indices [2] = 1;
4987         element.vt = VT_I4;
4988         element.lVal = 111;
4989         SafeArrayPutElement (safearray, indices, &element);
4990         VariantClear (&element);
4991
4992         indices [0] = 0;
4993         indices [1] = 1;
4994         indices [2] = 0;
4995         element.vt = VT_BSTR;
4996         element.bstrVal = marshal_bstr_alloc("ABCDEFG");
4997         SafeArrayPutElement (safearray, indices, &element);
4998         VariantClear (&element);
4999
5000         return hr;
5001 }
5002
5003 LIBTEST_API int STDCALL 
5004 mono_test_marshal_safearray_mixed(
5005                 SAFEARRAY  *safearray1,
5006                 SAFEARRAY **safearray2,
5007                 SAFEARRAY  *safearray3,
5008                 SAFEARRAY **safearray4
5009                 )
5010 {
5011         HRESULT hr = S_OK;
5012
5013         /* Initialize out parameters */
5014         *safearray2 = NULL;
5015
5016         /* array1: Check that in array is one dimensional and contains the expected value */
5017         hr = mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (safearray1);
5018
5019         /* array2: Fill in with some values to check on the managed side */
5020         if (hr == S_OK)
5021                 hr = mono_test_marshal_safearray_out_1dim_vt_bstr (safearray2);
5022
5023         /* array3: Check that in array is one dimensional and contains the expected value */
5024         if (hr == S_OK)
5025                 hr = mono_test_marshal_safearray_in_byval_1dim_vt_mixed(safearray3);
5026
5027         /* array4: Check input values and fill in with some values to check on the managed side */
5028         if (hr == S_OK)
5029                 hr = mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr(safearray4);
5030
5031         return hr;
5032 }
5033
5034 #endif
5035
5036 static int call_managed_res;
5037
5038 static void
5039 call_managed (gpointer arg)
5040 {
5041         SimpleDelegate del = arg;
5042
5043         call_managed_res = del (42);
5044 }
5045
5046 LIBTEST_API int STDCALL 
5047 mono_test_marshal_thread_attach (SimpleDelegate del)
5048 {
5049 #ifdef WIN32
5050         return 43;
5051 #else
5052         int res;
5053         pthread_t t;
5054
5055         res = pthread_create (&t, NULL, (gpointer)call_managed, del);
5056         g_assert (res == 0);
5057         pthread_join (t, NULL);
5058
5059         return call_managed_res;
5060 #endif
5061 }