Merge pull request #409 from Alkarex/patch-1
[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_stringbuilder2 (char *s, int n)
1042 {
1043         const char m[] = "EFGH";
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_default (char *s, int n)
1052 {
1053         const char m[] = "This is my message.  Isn't it nice?";
1054
1055         strncpy(s, m, n);
1056         s [n] = '\0';
1057         return 0;
1058 }
1059
1060 LIBTEST_API int STDCALL  
1061 mono_test_marshal_stringbuilder_unicode (gunichar2 *s, int n)
1062 {
1063         const char m[] = "This is my message.  Isn't it nice?";
1064         gunichar2* s2;
1065         glong len;
1066
1067         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1068         
1069         len = (len * 2) + 2;
1070         if (len > (n * 2))
1071                 len = n * 2;
1072         memcpy (s, s2, len);
1073
1074         g_free (s2);
1075
1076         return 0;
1077 }
1078
1079 LIBTEST_API void STDCALL
1080 mono_test_marshal_stringbuilder_out (char **s)
1081 {
1082         const char m[] = "This is my message.  Isn't it nice?";
1083         char *str;
1084
1085         str = marshal_alloc (strlen (m) + 1);
1086         memcpy (str, m, strlen (m) + 1);
1087         
1088         *s = str;
1089 }
1090
1091 LIBTEST_API int STDCALL  
1092 mono_test_marshal_stringbuilder_out_unicode (gunichar2 **s)
1093 {
1094         const char m[] = "This is my message.  Isn't it nice?";
1095         gunichar2 *s2;
1096         glong len;
1097
1098         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
1099         
1100         len = (len * 2) + 2;
1101         *s = marshal_alloc (len);
1102         memcpy (*s, s2, len);
1103
1104         g_free (s2);
1105
1106         return 0;
1107 }
1108
1109 LIBTEST_API int STDCALL
1110 mono_test_marshal_stringbuilder_ref (char **s)
1111 {
1112         const char m[] = "This is my message.  Isn't it nice?";
1113         char *str;
1114
1115         if (strcmp (*s, "ABC"))
1116                 return 1;
1117
1118         str = marshal_alloc (strlen (m) + 1);
1119         memcpy (str, m, strlen (m) + 1);
1120         
1121         *s = str;
1122         return 0;
1123 }
1124
1125 typedef struct {
1126 #ifndef __GNUC__
1127     char a;
1128 #endif
1129 } EmptyStruct;
1130
1131 LIBTEST_API int STDCALL 
1132 mono_test_marshal_empty_string_array (char **array)
1133 {
1134         return (array == NULL) ? 0 : 1;
1135 }
1136
1137 LIBTEST_API int STDCALL 
1138 mono_test_marshal_string_array (char **array)
1139 {
1140         if (strcmp (array [0], "ABC"))
1141                 return 1;
1142         if (strcmp (array [1], "DEF"))
1143                 return 2;
1144
1145         if (array [2] != NULL)
1146                 return 3;
1147
1148         return 0;
1149 }
1150
1151 LIBTEST_API int STDCALL 
1152 mono_test_marshal_byref_string_array (char ***array)
1153 {
1154         if (*array == NULL)
1155                 return 0;
1156
1157         if (strcmp ((*array) [0], "Alpha"))
1158                 return 2;
1159         if (strcmp ((*array) [1], "Beta"))
1160                 return 2;
1161         if (strcmp ((*array) [2], "Gamma"))
1162                 return 2;
1163
1164         return 1;
1165 }
1166
1167 LIBTEST_API int STDCALL 
1168 mono_test_marshal_stringbuilder_array (char **array)
1169 {
1170         if (strcmp (array [0], "ABC"))
1171                 return 1;
1172         if (strcmp (array [1], "DEF"))
1173                 return 2;
1174
1175         strcpy (array [0], "DEF");
1176         strcpy (array [1], "ABC");
1177
1178         return 0;
1179 }
1180
1181 LIBTEST_API int STDCALL 
1182 mono_test_marshal_unicode_string_array (gunichar2 **array, char **array2)
1183 {
1184         GError *error = NULL;
1185         char *s;
1186         
1187         s = g_utf16_to_utf8 (array [0], -1, NULL, NULL, &error);
1188         if (strcmp (s, "ABC")) {
1189                 g_free (s);
1190                 return 1;
1191         }
1192         else
1193                 g_free (s);
1194
1195         s = g_utf16_to_utf8 (array [1], -1, NULL, NULL, &error);
1196         if (strcmp (s, "DEF")) {
1197                 g_free (s);
1198                 return 2;
1199         }
1200         else
1201                 g_free (s);
1202
1203         if (strcmp (array2 [0], "ABC"))
1204                 return 3;
1205
1206         if (strcmp (array2 [1], "DEF")) 
1207                 return 4;
1208
1209         return 0;
1210 }
1211
1212 /* this does not work on Redhat gcc 2.96 */
1213 LIBTEST_API int STDCALL  
1214 mono_test_empty_struct (int a, EmptyStruct es, int b)
1215 {
1216         // printf ("mono_test_empty_struct %d %d\n", a, b);
1217
1218         // Intel icc on ia64 passes 'es' in 2 registers
1219 #if defined(__ia64) && defined(__INTEL_COMPILER)
1220         return 0;
1221 #else
1222         if (a == 1 && b == 2)
1223                 return 0;
1224         return 1;
1225 #endif
1226 }
1227
1228 typedef struct {
1229        char a[100];
1230 } ByValStrStruct;
1231
1232 LIBTEST_API ByValStrStruct * STDCALL 
1233 mono_test_byvalstr_gen (void)
1234 {
1235         ByValStrStruct *ret;
1236        
1237         ret = malloc(sizeof(ByValStrStruct));
1238         memset(ret, 'a', sizeof(ByValStrStruct)-1);
1239         ret->a[sizeof(ByValStrStruct)-1] = 0;
1240
1241         return ret;
1242 }
1243
1244 LIBTEST_API int STDCALL 
1245 mono_test_byvalstr_check (ByValStrStruct* data, char* correctString)
1246 {
1247         int ret;
1248
1249         ret = strcmp(data->a, correctString);
1250         // printf ("T1: %s\n", data->a);
1251         // printf ("T2: %s\n", correctString);
1252
1253         /* we need g_free because the allocation was performed by mono_test_byvalstr_gen */
1254         g_free (data);
1255         return (ret != 0);
1256 }
1257
1258 typedef struct {
1259         guint16 a[4];
1260         int  flag;
1261 } ByValStrStruct_Unicode;
1262
1263 LIBTEST_API int STDCALL 
1264 mono_test_byvalstr_check_unicode (ByValStrStruct_Unicode *ref, int test)
1265 {
1266         if (ref->flag != 0x1234abcd){
1267                 printf ("overwritten data");
1268                 return 1;
1269         }
1270             
1271         if (test == 1 || test == 3){
1272                 if (ref->a [0] != '1' ||
1273                     ref->a [1] != '2'   ||
1274                     ref->a [2] != '3')
1275                         return 1;
1276                 return 0;
1277         }
1278         if (test == 2){
1279                 if (ref->a [0] != '1' ||
1280                     ref->a [1] != '2')
1281                         return 1;
1282                 return 0;
1283         }
1284         return 10;
1285 }
1286
1287 LIBTEST_API int STDCALL 
1288 NameManglingAnsi (char *data)
1289 {
1290         return data [0] + data [1] + data [2];
1291 }
1292
1293 LIBTEST_API int STDCALL 
1294 NameManglingAnsiA (char *data)
1295 {
1296         g_assert_not_reached ();
1297 }
1298
1299 LIBTEST_API int STDCALL 
1300 NameManglingAnsiW (char *data)
1301 {
1302         g_assert_not_reached ();
1303 }
1304
1305 LIBTEST_API int STDCALL 
1306 NameManglingAnsi2A (char *data)
1307 {
1308         return data [0] + data [1] + data [2];
1309 }
1310
1311 LIBTEST_API int STDCALL 
1312 NameManglingAnsi2W (char *data)
1313 {
1314         g_assert_not_reached ();
1315 }
1316
1317 LIBTEST_API int STDCALL 
1318 NameManglingUnicode (char *data)
1319 {
1320         g_assert_not_reached ();
1321 }
1322
1323 LIBTEST_API int STDCALL 
1324 NameManglingUnicodeW (gunichar2 *data)
1325 {
1326         return data [0] + data [1] + data [2];
1327 }
1328
1329 LIBTEST_API int STDCALL 
1330 NameManglingUnicode2 (gunichar2 *data)
1331 {
1332         return data [0] + data [1] + data [2];
1333 }
1334
1335 LIBTEST_API int STDCALL 
1336 NameManglingAutoW (char *data)
1337 {
1338 #ifdef WIN32
1339         return (data [0] + data [1] + data [2]) == 131 ? 0 : 1;
1340 #else
1341         g_assert_not_reached ();
1342 #endif
1343 }
1344
1345 LIBTEST_API int STDCALL 
1346 NameManglingAuto (char *data)
1347 {
1348 #ifndef WIN32
1349         return (data [0] + data [1] + data [2]) == 198 ? 0 : 1;
1350 #else
1351         g_assert_not_reached ();
1352 #endif
1353 }
1354
1355 typedef int (STDCALL *intcharFunc)(const char*);
1356
1357 LIBTEST_API void STDCALL 
1358 callFunction (intcharFunc f)
1359 {
1360         f ("ABC");
1361 }
1362
1363 typedef struct {
1364         const char* str;
1365         int i;
1366 } SimpleObj;
1367
1368 LIBTEST_API int STDCALL 
1369 class_marshal_test0 (SimpleObj *obj1)
1370 {
1371         // printf ("class_marshal_test0 %s %d\n", obj1->str, obj1->i);
1372
1373         if (strcmp(obj1->str, "T1"))
1374                 return -1;
1375         if (obj1->i != 4)
1376                 return -2;
1377
1378         return 0;
1379 }
1380
1381 LIBTEST_API int STDCALL 
1382 class_marshal_test4 (SimpleObj *obj1)
1383 {
1384         if (obj1)
1385                 return -1;
1386
1387         return 0;
1388 }
1389
1390 LIBTEST_API void STDCALL
1391 class_marshal_test1 (SimpleObj **obj1)
1392 {
1393         SimpleObj *res = malloc (sizeof (SimpleObj));
1394
1395         res->str = marshal_strdup ("ABC");
1396         res->i = 5;
1397
1398         *obj1 = res;
1399 }
1400
1401 LIBTEST_API int STDCALL 
1402 class_marshal_test2 (SimpleObj **obj1)
1403 {
1404         // printf ("class_marshal_test2 %s %d\n", (*obj1)->str, (*obj1)->i);
1405
1406         if (strcmp((*obj1)->str, "ABC"))
1407                 return -1;
1408         if ((*obj1)->i != 5)
1409                 return -2;
1410
1411         return 0;
1412 }
1413
1414 LIBTEST_API int STDCALL 
1415 string_marshal_test0 (char *str)
1416 {
1417         if (strcmp (str, "TEST0"))
1418                 return -1;
1419
1420         return 0;
1421 }
1422
1423 LIBTEST_API void STDCALL
1424 string_marshal_test1 (const char **str)
1425 {
1426         *str = marshal_strdup ("TEST1");
1427 }
1428
1429 LIBTEST_API int STDCALL 
1430 string_marshal_test2 (char **str)
1431 {
1432         // printf ("string_marshal_test2 %s\n", *str);
1433
1434         if (strcmp (*str, "TEST1"))
1435                 return -1;
1436
1437         *str = marshal_strdup ("TEST2");
1438
1439         return 0;
1440 }
1441
1442 LIBTEST_API int STDCALL 
1443 string_marshal_test3 (char *str)
1444 {
1445         if (str)
1446                 return -1;
1447
1448         return 0;
1449 }
1450
1451 typedef struct {
1452         int a;
1453         int b;
1454 } BlittableClass;
1455
1456 LIBTEST_API BlittableClass* STDCALL 
1457 TestBlittableClass (BlittableClass *vl)
1458 {
1459         BlittableClass *res;
1460
1461         // printf ("TestBlittableClass %d %d\n", vl->a, vl->b);
1462
1463         if (vl) {
1464                 vl->a++;
1465                 vl->b++;
1466
1467                 res = marshal_new0 (BlittableClass, 1);
1468                 memcpy (res, vl, sizeof (BlittableClass));
1469         } else {
1470                 res = marshal_new0 (BlittableClass, 1);
1471                 res->a = 42;
1472                 res->b = 43;
1473         }
1474
1475         return res;
1476 }
1477
1478 typedef struct OSVERSIONINFO_STRUCT
1479
1480         int a; 
1481         int b; 
1482 } OSVERSIONINFO_STRUCT;
1483
1484 LIBTEST_API int STDCALL  
1485 MyGetVersionEx (OSVERSIONINFO_STRUCT *osvi)
1486 {
1487
1488         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1489
1490         osvi->a += 1;
1491         osvi->b += 1;
1492
1493         return osvi->a + osvi->b;
1494 }
1495
1496 LIBTEST_API int STDCALL  
1497 BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSIONINFO_STRUCT *osvi)
1498 {
1499
1500         // printf ("GOT %d %d\n", osvi->a, osvi->b);
1501
1502         osvi->a += 1;
1503         osvi->b += 1;
1504
1505         return osvi->a + osvi->b;
1506 }
1507
1508 LIBTEST_API int STDCALL 
1509 mono_test_marshal_point (point pt)
1510 {
1511         // printf("point %g %g\n", pt.x, pt.y);
1512         if (pt.x == 1.25 && pt.y == 3.5)
1513                 return 0;
1514
1515         return 1;
1516 }
1517
1518 typedef struct {
1519         int x;
1520         double y;
1521 } mixed_point;
1522
1523 LIBTEST_API int STDCALL 
1524 mono_test_marshal_mixed_point (mixed_point pt)
1525 {
1526         // printf("mixed point %d %g\n", pt.x, pt.y);
1527         if (pt.x == 5 && pt.y == 6.75)
1528                 return 0;
1529
1530         return 1;
1531 }
1532
1533 LIBTEST_API int STDCALL 
1534 mono_test_marshal_mixed_point_2 (mixed_point *pt)
1535 {
1536         if (pt->x != 5 || pt->y != 6.75)
1537                 return 1;
1538
1539         pt->x = 10;
1540         pt->y = 12.35;
1541
1542         return 0;
1543 }
1544
1545 LIBTEST_API int STDCALL  
1546 marshal_test_ref_bool(int i, char *b1, short *b2, int *b3)
1547 {
1548     int res = 1;
1549     if (*b1 != 0 && *b1 != 1)
1550         return 1;
1551     if (*b2 != 0 && *b2 != -1) /* variant_bool */
1552         return 1;
1553     if (*b3 != 0 && *b3 != 1)
1554         return 1;
1555     if (i == ((*b1 << 2) | (-*b2 << 1) | *b3))
1556         res = 0;
1557     *b1 = !*b1;
1558     *b2 = ~*b2;
1559     *b3 = !*b3;
1560     return res;
1561 }
1562
1563 struct BoolStruct
1564 {
1565     int i;
1566     char b1;
1567     short b2; /* variant_bool */
1568     int b3;
1569 };
1570
1571 LIBTEST_API int STDCALL  
1572 marshal_test_bool_struct(struct BoolStruct *s)
1573 {
1574     int res = 1;
1575     if (s->b1 != 0 && s->b1 != 1)
1576         return 1;
1577     if (s->b2 != 0 && s->b2 != -1)
1578         return 1;
1579     if (s->b3 != 0 && s->b3 != 1)
1580         return 1;
1581     if (s->i == ((s->b1 << 2) | (-s->b2 << 1) | s->b3))
1582         res = 0;
1583     s->b1 = !s->b1;
1584     s->b2 = ~s->b2;
1585     s->b3 = !s->b3;
1586     return res;
1587 }
1588
1589 typedef struct {
1590         gint64 l;
1591 } LongStruct2;
1592
1593 typedef struct {
1594         int i;
1595         LongStruct2 l;
1596 } LongStruct;
1597
1598 LIBTEST_API int STDCALL
1599 mono_test_marshal_long_struct (LongStruct *s)
1600 {
1601         return s->i + s->l.l;
1602 }
1603
1604 LIBTEST_API void STDCALL
1605 mono_test_last_error (int err)
1606 {
1607 #ifdef WIN32
1608         SetLastError (err);
1609 #else
1610         errno = err;
1611 #endif
1612 }
1613
1614 LIBTEST_API int STDCALL 
1615 mono_test_asany (void *ptr, int what)
1616 {
1617         switch (what) {
1618         case 1:
1619                 return (*(int*)ptr == 5) ? 0 : 1;
1620         case 2:
1621                 return strcmp (ptr, "ABC") == 0 ? 0 : 1;
1622         case 3: {
1623                 simplestruct2 ss = *(simplestruct2*)ptr;
1624
1625                 if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
1626             !strcmp (ss.d, "TEST") && 
1627             ss.e == 99 && ss.f == 1.5 && ss.g == 42 && ss.h == (guint64)123)
1628                         return 0;
1629                 else
1630                         return 1;
1631         }
1632         case 4: {
1633                 GError *error = NULL;
1634                 char *s;
1635
1636                 s = g_utf16_to_utf8 (ptr, -1, NULL, NULL, &error);
1637
1638                 if (!s)
1639                         return 1;
1640
1641                 if (!strcmp (s, "ABC")) {
1642                         g_free (s);
1643                         return 0;
1644                 }
1645                 else {
1646                         g_free (s);
1647                         return 1;
1648                 }
1649         }
1650         default:
1651                 g_assert_not_reached ();
1652         }
1653
1654         return 1;
1655 }
1656
1657 typedef struct
1658 {
1659         int i;
1660         int j;
1661         int k;
1662         char *s;
1663 } AsAnyStruct;
1664
1665 LIBTEST_API int STDCALL 
1666 mono_test_marshal_asany_in (void* ptr)
1667 {
1668         AsAnyStruct* asAny = ptr;
1669         int res = asAny->i + asAny->j + asAny->k;
1670
1671         return res;
1672 }
1673
1674 LIBTEST_API int STDCALL 
1675 mono_test_marshal_asany_inout (void* ptr)
1676 {
1677         AsAnyStruct* asAny = ptr;
1678         int res = asAny->i + asAny->j + asAny->k;
1679
1680         marshal_free (asAny->s);
1681
1682         asAny->i = 10;
1683         asAny->j = 20;
1684         asAny->k = 30;
1685         asAny->s = 0;
1686
1687         return res;
1688 }
1689
1690 LIBTEST_API int STDCALL 
1691 mono_test_marshal_asany_out (void* ptr)
1692 {
1693         AsAnyStruct* asAny = ptr;
1694         int res = asAny->i + asAny->j + asAny->k;
1695
1696         asAny->i = 10;
1697         asAny->j = 20;
1698         asAny->k = 30;
1699         asAny->s = 0;
1700
1701         return res;
1702 }
1703
1704 /*
1705  * AMD64 marshalling tests.
1706  */
1707
1708 typedef struct amd64_struct1 {
1709         int i;
1710         int j;
1711         int k;
1712         int l;
1713 } amd64_struct1;
1714
1715 LIBTEST_API amd64_struct1 STDCALL 
1716 mono_test_marshal_amd64_pass_return_struct1 (amd64_struct1 s)
1717 {
1718         s.i ++;
1719         s.j ++;
1720         s.k ++;
1721         s.l ++;
1722
1723         return s;
1724 }
1725
1726 LIBTEST_API amd64_struct1 STDCALL 
1727 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)
1728 {
1729         s.i ++;
1730         s.j ++;
1731         s.k ++;
1732         s.l += 1 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
1733
1734         return s;
1735 }
1736
1737 typedef struct amd64_struct2 {
1738         int i;
1739         int j;
1740 } amd64_struct2;
1741
1742 LIBTEST_API amd64_struct2 STDCALL 
1743 mono_test_marshal_amd64_pass_return_struct2 (amd64_struct2 s)
1744 {
1745         s.i ++;
1746         s.j ++;
1747
1748         return s;
1749 }
1750
1751 typedef struct amd64_struct3 {
1752         int i;
1753 } amd64_struct3;
1754
1755 LIBTEST_API amd64_struct3 STDCALL 
1756 mono_test_marshal_amd64_pass_return_struct3 (amd64_struct3 s)
1757 {
1758         s.i ++;
1759
1760         return s;
1761 }
1762
1763 typedef struct amd64_struct4 {
1764         double d1, d2;
1765 } amd64_struct4;
1766
1767 LIBTEST_API amd64_struct4 STDCALL 
1768 mono_test_marshal_amd64_pass_return_struct4 (amd64_struct4 s)
1769 {
1770         s.d1 ++;
1771         s.d2 ++;
1772
1773         return s;
1774 }
1775
1776 /*
1777  * IA64 marshalling tests.
1778  */
1779 typedef struct test_struct5 {
1780         float d1, d2;
1781 } test_struct5;
1782
1783 LIBTEST_API test_struct5 STDCALL 
1784 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, test_struct5 s, int i, double d3, double d4)
1785 {
1786         s.d1 += d1 + d2 + i;
1787         s.d2 += d3 + d4 + i;
1788
1789         return s;
1790 }
1791
1792 typedef struct test_struct6 {
1793         double d1, d2;
1794 } test_struct6;
1795
1796 LIBTEST_API test_struct6 STDCALL 
1797 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, test_struct6 s, int i, double d3, double d4)
1798 {
1799         s.d1 += d1 + d2 + i;
1800         s.d2 += d3 + d4;
1801
1802         return s;
1803 }
1804
1805 static guint32 custom_res [2];
1806
1807 LIBTEST_API void* STDCALL
1808 mono_test_marshal_pass_return_custom (int i, guint32 *ptr, int j)
1809 {
1810         /* ptr will be freed by CleanupNative, so make a copy */
1811         custom_res [0] = 0; /* not allocated by AllocHGlobal */
1812         custom_res [1] = ptr [1];
1813
1814         return &custom_res;
1815 }
1816
1817 LIBTEST_API int STDCALL 
1818 mono_test_marshal_pass_out_custom (int i, guint32 **ptr, int j)
1819 {
1820         custom_res [0] = 0;
1821         custom_res [1] = i + j + 10;
1822
1823         *ptr = custom_res;
1824
1825         return 0;
1826 }
1827
1828 LIBTEST_API int STDCALL 
1829 mono_test_marshal_pass_inout_custom (int i, guint32 *ptr, int j)
1830 {
1831         ptr [0] = 0;
1832         ptr [1] = i + ptr [1] + j;
1833
1834         return 0;
1835 }
1836
1837 LIBTEST_API int STDCALL 
1838 mono_test_marshal_pass_out_byval_custom (int i, guint32 *ptr, int j)
1839 {
1840         return ptr == NULL ? 0 : 1;
1841 }
1842
1843 LIBTEST_API int STDCALL 
1844 mono_test_marshal_pass_byref_custom (int i, guint32 **ptr, int j)
1845 {
1846         (*ptr)[1] += i + j;
1847
1848         return 0;
1849 }
1850
1851 LIBTEST_API void* STDCALL
1852 mono_test_marshal_pass_return_custom2 (int i, guint32 *ptr, int j)
1853 {
1854         g_assert_not_reached ();
1855
1856         return NULL;
1857 }
1858
1859 LIBTEST_API void* STDCALL
1860 mono_test_marshal_pass_return_custom_null (int i, guint32 *ptr, int j)
1861 {
1862         g_assert (ptr == NULL);
1863
1864         return NULL;
1865 }
1866
1867 typedef void *(STDCALL *PassReturnPtrDelegate) (void *ptr);
1868
1869 LIBTEST_API int STDCALL 
1870 mono_test_marshal_pass_return_custom_in_delegate (PassReturnPtrDelegate del)
1871 {
1872         guint32 buf [2];
1873         guint32 res;
1874         guint32 *ptr;
1875
1876         buf [0] = 0;
1877         buf [1] = 10;
1878
1879         ptr = del (&buf);
1880
1881         res = ptr [1];
1882
1883 #ifdef WIN32
1884         /* FIXME: Freed with FreeHGlobal */
1885 #else
1886         g_free (ptr);
1887 #endif
1888
1889         return res;
1890 }
1891
1892 LIBTEST_API int STDCALL 
1893 mono_test_marshal_pass_return_custom_null_in_delegate (PassReturnPtrDelegate del)
1894 {
1895         void *ptr = del (NULL);
1896
1897         return (ptr == NULL) ? 15 : 0;
1898 }
1899
1900 typedef void (STDCALL *CustomOutParamDelegate) (void **pptr);
1901
1902 LIBTEST_API int STDCALL 
1903 mono_test_marshal_custom_out_param_delegate (CustomOutParamDelegate del)
1904 {
1905         void* pptr = del;
1906
1907         del (&pptr);
1908
1909         if(pptr != NULL)
1910                 return 1;
1911
1912         return 0;
1913 }
1914
1915 typedef int (STDCALL *ReturnEnumDelegate) (int e);
1916
1917 LIBTEST_API int STDCALL 
1918 mono_test_marshal_return_enum_delegate (ReturnEnumDelegate func)
1919 {
1920         return func (1);
1921 }
1922
1923 typedef struct {
1924         int a, b, c;
1925         gint64 d;
1926 } BlittableStruct;
1927         
1928 typedef BlittableStruct (STDCALL *SimpleDelegate10) (BlittableStruct ss);
1929
1930 LIBTEST_API int STDCALL 
1931 mono_test_marshal_blittable_struct_delegate (SimpleDelegate10 delegate)
1932 {
1933         BlittableStruct ss, res;
1934
1935         ss.a = 1;
1936         ss.b = 2;
1937         ss.c = 3;
1938         ss.d = 55;
1939
1940         res = delegate (ss);
1941         if (! ((res.a == -1) && (res.b == -2) && (res.c == -3) && (res.d == -55)))
1942                 return 1;
1943
1944         return 0;
1945 }
1946
1947 LIBTEST_API int STDCALL 
1948 mono_test_stdcall_name_mangling (int a, int b, int c)
1949 {
1950         return a + b + c;
1951 }
1952
1953 /*
1954  * PASSING AND RETURNING SMALL STRUCTURES FROM DELEGATES TESTS
1955  */
1956
1957 typedef struct {
1958         int i;
1959 } SmallStruct1;
1960         
1961 typedef SmallStruct1 (STDCALL *SmallStructDelegate1) (SmallStruct1 ss);
1962
1963 LIBTEST_API int STDCALL 
1964 mono_test_marshal_small_struct_delegate1 (SmallStructDelegate1 delegate)
1965 {
1966         SmallStruct1 ss, res;
1967
1968         ss.i = 1;
1969
1970         res = delegate (ss);
1971         if (! (res.i == -1))
1972                 return 1;
1973
1974         return 0;
1975 }
1976
1977 typedef struct {
1978         gint16 i, j;
1979 } SmallStruct2;
1980         
1981 typedef SmallStruct2 (STDCALL *SmallStructDelegate2) (SmallStruct2 ss);
1982
1983 LIBTEST_API int STDCALL 
1984 mono_test_marshal_small_struct_delegate2 (SmallStructDelegate2 delegate)
1985 {
1986         SmallStruct2 ss, res;
1987
1988         ss.i = 2;
1989         ss.j = 3;
1990
1991         res = delegate (ss);
1992         if (! ((res.i == -2) && (res.j == -3)))
1993                 return 1;
1994
1995         return 0;
1996 }
1997
1998 typedef struct {
1999         gint16 i;
2000         gint8 j;
2001 } SmallStruct3;
2002         
2003 typedef SmallStruct3 (STDCALL *SmallStructDelegate3) (SmallStruct3 ss);
2004
2005 LIBTEST_API int STDCALL 
2006 mono_test_marshal_small_struct_delegate3 (SmallStructDelegate3 delegate)
2007 {
2008         SmallStruct3 ss, res;
2009
2010         ss.i = 1;
2011         ss.j = 2;
2012
2013         res = delegate (ss);
2014         if (! ((res.i == -1) && (res.j == -2)))
2015                 return 1;
2016
2017         return 0;
2018 }
2019
2020 typedef struct {
2021         gint16 i;
2022 } SmallStruct4;
2023         
2024 typedef SmallStruct4 (STDCALL *SmallStructDelegate4) (SmallStruct4 ss);
2025
2026 LIBTEST_API int STDCALL 
2027 mono_test_marshal_small_struct_delegate4 (SmallStructDelegate4 delegate)
2028 {
2029         SmallStruct4 ss, res;
2030
2031         ss.i = 1;
2032
2033         res = delegate (ss);
2034         if (! (res.i == -1))
2035                 return 1;
2036
2037         return 0;
2038 }
2039
2040 typedef struct {
2041         gint64 i;
2042 } SmallStruct5;
2043         
2044 typedef SmallStruct5 (STDCALL *SmallStructDelegate5) (SmallStruct5 ss);
2045
2046 LIBTEST_API int STDCALL 
2047 mono_test_marshal_small_struct_delegate5 (SmallStructDelegate5 delegate)
2048 {
2049         SmallStruct5 ss, res;
2050
2051         ss.i = 5;
2052
2053         res = delegate (ss);
2054         if (! (res.i == -5))
2055                 return 1;
2056
2057         return 0;
2058 }
2059
2060 typedef struct {
2061         int i, j;
2062 } SmallStruct6;
2063         
2064 typedef SmallStruct6 (STDCALL *SmallStructDelegate6) (SmallStruct6 ss);
2065
2066 LIBTEST_API int STDCALL 
2067 mono_test_marshal_small_struct_delegate6 (SmallStructDelegate6 delegate)
2068 {
2069         SmallStruct6 ss, res;
2070
2071         ss.i = 1;
2072         ss.j = 2;
2073
2074         res = delegate (ss);
2075         if (! ((res.i == -1) && (res.j == -2)))
2076                 return 1;
2077
2078         return 0;
2079 }
2080
2081 typedef struct {
2082         int i;
2083         gint16 j;
2084 } SmallStruct7;
2085         
2086 typedef SmallStruct7 (STDCALL *SmallStructDelegate7) (SmallStruct7 ss);
2087
2088 LIBTEST_API int STDCALL 
2089 mono_test_marshal_small_struct_delegate7 (SmallStructDelegate7 delegate)
2090 {
2091         SmallStruct7 ss, res;
2092
2093         ss.i = 1;
2094         ss.j = 2;
2095
2096         res = delegate (ss);
2097         if (! ((res.i == -1) && (res.j == -2)))
2098                 return 1;
2099
2100         return 0;
2101 }
2102
2103 typedef struct {
2104         float i;
2105 } SmallStruct8;
2106         
2107 typedef SmallStruct8 (STDCALL *SmallStructDelegate8) (SmallStruct8 ss);
2108
2109 LIBTEST_API int STDCALL 
2110 mono_test_marshal_small_struct_delegate8 (SmallStructDelegate8 delegate)
2111 {
2112         SmallStruct8 ss, res;
2113
2114         ss.i = 1.0;
2115
2116         res = delegate (ss);
2117         if (! ((res.i == -1.0)))
2118                 return 1;
2119
2120         return 0;
2121 }
2122
2123 typedef struct {
2124         double i;
2125 } SmallStruct9;
2126         
2127 typedef SmallStruct9 (STDCALL *SmallStructDelegate9) (SmallStruct9 ss);
2128
2129 LIBTEST_API int STDCALL 
2130 mono_test_marshal_small_struct_delegate9 (SmallStructDelegate9 delegate)
2131 {
2132         SmallStruct9 ss, res;
2133
2134         ss.i = 1.0;
2135
2136         res = delegate (ss);
2137         if (! ((res.i == -1.0)))
2138                 return 1;
2139
2140         return 0;
2141 }
2142
2143 typedef struct {
2144         float i, j;
2145 } SmallStruct10;
2146         
2147 typedef SmallStruct10 (STDCALL *SmallStructDelegate10) (SmallStruct10 ss);
2148
2149 LIBTEST_API int STDCALL 
2150 mono_test_marshal_small_struct_delegate10 (SmallStructDelegate10 delegate)
2151 {
2152         SmallStruct10 ss, res;
2153
2154         ss.i = 1.0;
2155         ss.j = 2.0;
2156
2157         res = delegate (ss);
2158         if (! ((res.i == -1.0) && (res.j == -2.0)))
2159                 return 1;
2160
2161         return 0;
2162 }
2163
2164 typedef struct {
2165         float i;
2166         int j;
2167 } SmallStruct11;
2168         
2169 typedef SmallStruct11 (STDCALL *SmallStructDelegate11) (SmallStruct11 ss);
2170
2171 LIBTEST_API int STDCALL 
2172 mono_test_marshal_small_struct_delegate11 (SmallStructDelegate11 delegate)
2173 {
2174         SmallStruct11 ss, res;
2175
2176         ss.i = 1.0;
2177         ss.j = 2;
2178
2179         res = delegate (ss);
2180         if (! ((res.i == -1.0) && (res.j == -2)))
2181                 return 1;
2182
2183         return 0;
2184 }
2185
2186 typedef int (STDCALL *ArrayDelegate) (int i, char *j, void *arr);
2187
2188 LIBTEST_API int STDCALL 
2189 mono_test_marshal_array_delegate (void *arr, int len, ArrayDelegate del)
2190 {
2191         return del (len, NULL, arr);
2192 }
2193
2194 typedef int (STDCALL *ArrayDelegateLong) (gint64 i, char *j, void *arr);
2195
2196 LIBTEST_API int STDCALL 
2197 mono_test_marshal_array_delegate_long (void *arr, gint64 len, ArrayDelegateLong del)
2198 {
2199         return del (len, NULL, arr);
2200 }
2201
2202 LIBTEST_API int STDCALL 
2203 mono_test_marshal_out_array_delegate (int *arr, int len, ArrayDelegate del)
2204 {
2205         del (len, NULL, arr);
2206
2207         if ((arr [0] != 1) || (arr [1] != 2))
2208                 return 1;
2209         else
2210                 return 0;
2211 }
2212
2213 typedef gunichar2* (STDCALL *UnicodeStringDelegate) (gunichar2 *message);
2214
2215 LIBTEST_API int STDCALL 
2216 mono_test_marshal_return_unicode_string_delegate (UnicodeStringDelegate del)
2217 {
2218         const char m[] = "abcdef";
2219         gunichar2 *s2, *res;
2220         glong len;
2221
2222         s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
2223
2224         res = del (s2);
2225
2226         marshal_free (res);
2227
2228         return 0;
2229 }
2230
2231 LIBTEST_API int STDCALL 
2232 mono_test_marshal_out_string_array_delegate (char **arr, int len, ArrayDelegate del)
2233 {
2234         del (len, NULL, arr);
2235
2236         if (!strcmp (arr [0], "ABC") && !strcmp (arr [1], "DEF"))
2237                 return 0;
2238         else
2239                 return 1;
2240 }
2241
2242 typedef int (*CdeclDelegate) (int i, int j);
2243
2244 LIBTEST_API int STDCALL 
2245 mono_test_marshal_cdecl_delegate (CdeclDelegate del)
2246 {
2247         int i;
2248
2249         for (i = 0; i < 1000; ++i)
2250                 del (1, 2);
2251
2252         return 0;
2253 }
2254
2255 typedef char** (STDCALL *ReturnStringArrayDelegate) (int i);
2256
2257 LIBTEST_API int STDCALL 
2258 mono_test_marshal_return_string_array_delegate (ReturnStringArrayDelegate d)
2259 {
2260         char **arr = d (2);
2261         int res;
2262
2263         if (arr == NULL)
2264                 return 3;
2265
2266         if (strcmp (arr [0], "ABC") || strcmp (arr [1], "DEF"))
2267                 res = 1;
2268         else
2269                 res = 0;
2270
2271         marshal_free (arr);
2272
2273         return res;
2274 }
2275
2276 typedef int (STDCALL *ByrefStringDelegate) (char **s);
2277
2278 LIBTEST_API int STDCALL 
2279 mono_test_marshal_byref_string_delegate (ByrefStringDelegate d)
2280 {
2281         char *s = (char*)"ABC";
2282         int res;
2283
2284         res = d (&s);
2285         if (res != 0)
2286                 return res;
2287
2288         if (!strcmp (s, "DEF"))
2289                 res = 0;
2290         else
2291                 res = 2;
2292
2293         marshal_free (s);
2294
2295         return res;
2296 }
2297
2298 LIBTEST_API int STDCALL 
2299 add_delegate (int i, int j)
2300 {
2301         return i + j;
2302 }
2303
2304 LIBTEST_API gpointer STDCALL 
2305 mono_test_marshal_return_fnptr (void)
2306 {
2307         return &add_delegate;
2308 }
2309
2310 LIBTEST_API int STDCALL 
2311 mono_xr (int code)
2312 {
2313         printf ("codigo %x\n", code);
2314         return code + 1234;
2315 }
2316
2317 typedef struct {
2318         int handle;
2319 } HandleRef;
2320
2321 LIBTEST_API HandleRef STDCALL 
2322 mono_xr_as_handle (int code)
2323 {
2324         HandleRef ref;
2325
2326         memset (&ref, 0, sizeof (ref));
2327
2328         return ref;
2329 }
2330  
2331 typedef struct {
2332         int   a;
2333         void *handle1;
2334         void *handle2;
2335         int   b;
2336 } HandleStructs;
2337
2338 LIBTEST_API int STDCALL 
2339 mono_safe_handle_struct_ref (HandleStructs *x)
2340 {
2341         printf ("Dingus Ref! \n");
2342         printf ("Values: %d %d %p %p\n", x->a, x->b, x->handle1, x->handle2);
2343         if (x->a != 1234)
2344                 return 1;
2345         if (x->b != 8743)
2346                 return 2;
2347
2348         if (x->handle1 != (void*) 0x7080feed)
2349                 return 3;
2350
2351         if (x->handle2 != (void*) 0x1234abcd)
2352                 return 4;
2353
2354         return 0xf00d;
2355 }
2356
2357 LIBTEST_API int STDCALL 
2358 mono_safe_handle_struct (HandleStructs x)
2359 {
2360         printf ("Dingus Standard! \n");
2361         printf ("Values: %d %d %p %p\n", x.a, x.b, x.handle1, x.handle2);
2362         if (x.a != 1234)
2363                 return 1;
2364         if (x.b != 8743)
2365                 return 2;
2366
2367         if (x.handle1 != (void*) 0x7080feed)
2368                 return 3;
2369
2370         if (x.handle2 != (void*) 0x1234abcd)
2371                 return 4;
2372         
2373         return 0xf00f;
2374 }
2375
2376 typedef struct {
2377         void *a;
2378 } TrivialHandle;
2379
2380 LIBTEST_API int STDCALL 
2381 mono_safe_handle_struct_simple (TrivialHandle x)
2382 {
2383         printf ("The value is %p\n", x.a);
2384         return ((int)(gsize)x.a) * 2;
2385 }
2386
2387 LIBTEST_API int STDCALL 
2388 mono_safe_handle_return (void)
2389 {
2390         return 0x1000f00d;
2391 }
2392
2393 LIBTEST_API void STDCALL
2394 mono_safe_handle_ref (void **handle)
2395 {
2396         if (*handle != 0){
2397                 *handle = (void *) 0xbad;
2398                 return;
2399         }
2400
2401         *handle = (void *) 0x800d;
2402 }
2403
2404 LIBTEST_API double STDCALL
2405 mono_test_marshal_date_time (double d, double *d2)
2406 {
2407         *d2 = d;
2408         return d;
2409 }
2410
2411 /*
2412  * COM INTEROP TESTS
2413  */
2414
2415 #ifndef WIN32
2416
2417 typedef struct {
2418         guint16 vt;
2419         guint16 wReserved1;
2420         guint16 wReserved2;
2421         guint16 wReserved3;
2422         union {
2423                 gint64 llVal;
2424                 gint32 lVal;
2425                 guint8  bVal;
2426                 gint16 iVal;
2427                 float  fltVal;
2428                 double dblVal;
2429                 gint16 boolVal;
2430                 gunichar2* bstrVal;
2431                 gint8 cVal;
2432                 guint16 uiVal;
2433                 guint32 ulVal;
2434                 guint64 ullVal;
2435                 struct {
2436                         gpointer pvRecord;
2437                         gpointer pRecInfo;
2438                 };
2439         };
2440 } VARIANT;
2441
2442 typedef enum {
2443         VARIANT_TRUE = -1,
2444         VARIANT_FALSE = 0
2445 } VariantBool;
2446
2447 typedef enum {
2448         VT_EMPTY = 0,
2449         VT_NULL = 1,
2450         VT_I2 = 2,
2451         VT_I4 = 3,
2452         VT_R4 = 4,
2453         VT_R8 = 5,
2454         VT_CY = 6,
2455         VT_DATE = 7,
2456         VT_BSTR = 8,
2457         VT_DISPATCH = 9,
2458         VT_ERROR = 10,
2459         VT_BOOL = 11,
2460         VT_VARIANT = 12,
2461         VT_UNKNOWN = 13,
2462         VT_DECIMAL = 14,
2463         VT_I1 = 16,
2464         VT_UI1 = 17,
2465         VT_UI2 = 18,
2466         VT_UI4 = 19,
2467         VT_I8 = 20,
2468         VT_UI8 = 21,
2469         VT_INT = 22,
2470         VT_UINT = 23,
2471         VT_VOID = 24,
2472         VT_HRESULT = 25,
2473         VT_PTR = 26,
2474         VT_SAFEARRAY = 27,
2475         VT_CARRAY = 28,
2476         VT_USERDEFINED = 29,
2477         VT_LPSTR = 30,
2478         VT_LPWSTR = 31,
2479         VT_RECORD = 36,
2480         VT_FILETIME = 64,
2481         VT_BLOB = 65,
2482         VT_STREAM = 66,
2483         VT_STORAGE = 67,
2484         VT_STREAMED_OBJECT = 68,
2485         VT_STORED_OBJECT = 69,
2486         VT_BLOB_OBJECT = 70,
2487         VT_CF = 71,
2488         VT_CLSID = 72,
2489         VT_VECTOR = 4096,
2490         VT_ARRAY = 8192,
2491         VT_BYREF = 16384
2492 } VarEnum;
2493
2494 void VariantInit(VARIANT* vt)
2495 {
2496         vt->vt = VT_EMPTY;
2497 }
2498
2499 typedef struct
2500 {
2501         guint32 a;
2502         guint16 b;
2503         guint16 c;
2504         guint8 d[8];
2505 } GUID;
2506
2507 #define S_OK 0
2508
2509 #endif
2510
2511 LIBTEST_API int STDCALL 
2512 mono_test_marshal_bstr_in(gunichar2* bstr)
2513 {
2514         gint32 result = 0;
2515         gchar* bstr_utf8 = g_utf16_to_utf8 (bstr, -1, NULL, NULL, NULL);
2516         result = strcmp("mono_test_marshal_bstr_in", bstr_utf8);
2517         g_free(bstr_utf8);
2518         if (result == 0)
2519                 return 0;
2520         return 1;
2521 }
2522
2523 LIBTEST_API int STDCALL 
2524 mono_test_marshal_bstr_out(gunichar2** bstr)
2525 {
2526         *bstr = marshal_bstr_alloc ("mono_test_marshal_bstr_out");
2527         return 0;
2528 }
2529
2530 LIBTEST_API int STDCALL 
2531 mono_test_marshal_bstr_in_null(gunichar2* bstr)
2532 {
2533         if (!bstr)
2534                 return 0;
2535         return 1;
2536 }
2537
2538 LIBTEST_API int STDCALL 
2539 mono_test_marshal_bstr_out_null(gunichar2** bstr)
2540 {
2541         *bstr = NULL;
2542         return 0;
2543 }
2544
2545 LIBTEST_API int STDCALL 
2546 mono_test_marshal_variant_in_sbyte(VARIANT variant)
2547 {
2548         if (variant.vt == VT_I1 && variant.cVal == 100)
2549                 return 0;
2550         return 1;
2551 }
2552
2553 LIBTEST_API int STDCALL 
2554 mono_test_marshal_variant_in_byte(VARIANT variant)
2555 {
2556         if (variant.vt == VT_UI1 && variant.bVal == 100)
2557                 return 0;
2558         return 1;
2559 }
2560
2561 LIBTEST_API int STDCALL 
2562 mono_test_marshal_variant_in_short(VARIANT variant)
2563 {
2564         if (variant.vt == VT_I2 && variant.iVal == 314)
2565                 return 0;
2566         return 1;
2567 }
2568
2569 LIBTEST_API int STDCALL 
2570 mono_test_marshal_variant_in_ushort(VARIANT variant)
2571 {
2572         if (variant.vt == VT_UI2 && variant.uiVal == 314)
2573                 return 0;
2574         return 1;
2575 }
2576
2577 LIBTEST_API int STDCALL 
2578 mono_test_marshal_variant_in_int(VARIANT variant)
2579 {
2580         if (variant.vt == VT_I4 && variant.lVal == 314)
2581                 return 0;
2582         return 1;
2583 }
2584
2585 LIBTEST_API int STDCALL 
2586 mono_test_marshal_variant_in_uint(VARIANT variant)
2587 {
2588         if (variant.vt == VT_UI4 && variant.ulVal == 314)
2589                 return 0;
2590         return 1;
2591 }
2592
2593 LIBTEST_API int STDCALL 
2594 mono_test_marshal_variant_in_long(VARIANT variant)
2595 {
2596         if (variant.vt == VT_I8 && variant.llVal == 314)
2597                 return 0;
2598         return 1;
2599 }
2600
2601 LIBTEST_API int STDCALL 
2602 mono_test_marshal_variant_in_ulong(VARIANT variant)
2603 {
2604         if (variant.vt == VT_UI8 && variant.ullVal == 314)
2605                 return 0;
2606         return 1;
2607 }
2608
2609 LIBTEST_API int STDCALL 
2610 mono_test_marshal_variant_in_float(VARIANT variant)
2611 {
2612         if (variant.vt == VT_R4 && (variant.fltVal - 3.14)/3.14 < .001)
2613                 return 0;
2614         return 1;
2615 }
2616
2617 LIBTEST_API int STDCALL 
2618 mono_test_marshal_variant_in_double(VARIANT variant)
2619 {
2620         if (variant.vt == VT_R8 && (variant.dblVal - 3.14)/3.14 < .001)
2621                 return 0;
2622         return 1;
2623 }
2624
2625 LIBTEST_API int STDCALL 
2626 mono_test_marshal_variant_in_bstr(VARIANT variant)
2627 {
2628         gint32 result = 0;
2629         gchar* bstr_utf8 = g_utf16_to_utf8 (variant.bstrVal, -1, NULL, NULL, NULL);
2630         result = strcmp("PI", bstr_utf8);
2631         g_free(bstr_utf8);
2632
2633         if (variant.vt == VT_BSTR && !result)
2634                 return 0;
2635         return 1;
2636 }
2637
2638 LIBTEST_API int STDCALL 
2639 mono_test_marshal_variant_in_bool_true (VARIANT variant)
2640 {
2641         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_TRUE)
2642                 return 0;
2643         return 1;
2644 }
2645
2646 LIBTEST_API int STDCALL 
2647 mono_test_marshal_variant_in_bool_false (VARIANT variant)
2648 {
2649         if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_FALSE)
2650                 return 0;
2651         return 1;
2652 }
2653
2654 LIBTEST_API int STDCALL 
2655 mono_test_marshal_variant_out_sbyte(VARIANT* variant)
2656 {
2657         variant->vt = VT_I1;
2658         variant->cVal = 100;
2659
2660         return 0;
2661 }
2662
2663 LIBTEST_API int STDCALL 
2664 mono_test_marshal_variant_out_byte(VARIANT* variant)
2665 {       
2666         variant->vt = VT_UI1;
2667         variant->bVal = 100;
2668
2669         return 0;
2670 }
2671
2672 LIBTEST_API int STDCALL 
2673 mono_test_marshal_variant_out_short(VARIANT* variant)
2674 {
2675         variant->vt = VT_I2;
2676         variant->iVal = 314;
2677
2678         return 0;
2679 }
2680
2681 LIBTEST_API int STDCALL 
2682 mono_test_marshal_variant_out_ushort(VARIANT* variant)
2683 {
2684         variant->vt = VT_UI2;
2685         variant->uiVal = 314;
2686
2687         return 0;
2688 }
2689
2690 LIBTEST_API int STDCALL 
2691 mono_test_marshal_variant_out_int(VARIANT* variant)
2692 {
2693         variant->vt = VT_I4;
2694         variant->lVal = 314;
2695
2696         return 0;
2697 }
2698
2699 LIBTEST_API int STDCALL 
2700 mono_test_marshal_variant_out_uint(VARIANT* variant)
2701 {
2702         variant->vt = VT_UI4;
2703         variant->ulVal = 314;
2704
2705         return 0;
2706 }
2707
2708 LIBTEST_API int STDCALL 
2709 mono_test_marshal_variant_out_long(VARIANT* variant)
2710 {
2711         variant->vt = VT_I8;
2712         variant->llVal = 314;
2713
2714         return 0;
2715 }
2716
2717 LIBTEST_API int STDCALL 
2718 mono_test_marshal_variant_out_ulong(VARIANT* variant)
2719 {
2720         variant->vt = VT_UI8;
2721         variant->ullVal = 314;
2722
2723         return 0;
2724 }
2725
2726 LIBTEST_API int STDCALL 
2727 mono_test_marshal_variant_out_float(VARIANT* variant)
2728 {
2729         variant->vt = VT_R4;
2730         variant->fltVal = 3.14;
2731
2732         return 0;
2733 }
2734
2735 LIBTEST_API int STDCALL 
2736 mono_test_marshal_variant_out_double(VARIANT* variant)
2737 {
2738         variant->vt = VT_R8;
2739         variant->dblVal = 3.14;
2740
2741         return 0;
2742 }
2743
2744 LIBTEST_API int STDCALL 
2745 mono_test_marshal_variant_out_bstr(VARIANT* variant)
2746 {
2747         variant->vt = VT_BSTR;
2748         variant->bstrVal = marshal_bstr_alloc("PI");
2749
2750         return 0;
2751 }
2752
2753 LIBTEST_API int STDCALL 
2754 mono_test_marshal_variant_out_bool_true (VARIANT* variant)
2755 {
2756         variant->vt = VT_BOOL;
2757         variant->boolVal = VARIANT_TRUE;
2758
2759         return 0;
2760 }
2761
2762 LIBTEST_API int STDCALL 
2763 mono_test_marshal_variant_out_bool_false (VARIANT* variant)
2764 {
2765         variant->vt = VT_BOOL;
2766         variant->boolVal = VARIANT_FALSE;
2767
2768         return 0;
2769 }
2770
2771 typedef int (STDCALL *VarFunc) (int vt, VARIANT variant);
2772 typedef int (STDCALL *VarRefFunc) (int vt, VARIANT* variant);
2773
2774 LIBTEST_API int STDCALL 
2775 mono_test_marshal_variant_in_sbyte_unmanaged(VarFunc func)
2776 {
2777         VARIANT vt;
2778         vt.vt = VT_I1;
2779         vt.cVal = -100;
2780         return func (VT_I1, vt);
2781 }
2782
2783 LIBTEST_API int STDCALL 
2784 mono_test_marshal_variant_in_byte_unmanaged(VarFunc func)
2785 {
2786         VARIANT vt;
2787         vt.vt = VT_UI1;
2788         vt.bVal = 100;
2789         return func (VT_UI1, vt);
2790 }
2791
2792 LIBTEST_API int STDCALL 
2793 mono_test_marshal_variant_in_short_unmanaged(VarFunc func)
2794 {
2795         VARIANT vt;
2796         vt.vt = VT_I2;
2797         vt.iVal = -100;
2798         return func (VT_I2, vt);
2799 }
2800
2801 LIBTEST_API int STDCALL 
2802 mono_test_marshal_variant_in_ushort_unmanaged(VarFunc func)
2803 {
2804         VARIANT vt;
2805         vt.vt = VT_UI2;
2806         vt.uiVal = 100;
2807         return func (VT_UI2, vt);
2808 }
2809
2810 LIBTEST_API int STDCALL 
2811 mono_test_marshal_variant_in_int_unmanaged(VarFunc func)
2812 {
2813         VARIANT vt;
2814         vt.vt = VT_I4;
2815         vt.lVal = -100;
2816         return func (VT_I4, vt);
2817 }
2818
2819 LIBTEST_API int STDCALL 
2820 mono_test_marshal_variant_in_uint_unmanaged(VarFunc func)
2821 {
2822         VARIANT vt;
2823         vt.vt = VT_UI4;
2824         vt.ulVal = 100;
2825         return func (VT_UI4, vt);
2826 }
2827
2828 LIBTEST_API int STDCALL 
2829 mono_test_marshal_variant_in_long_unmanaged(VarFunc func)
2830 {
2831         VARIANT vt;
2832         vt.vt = VT_I8;
2833         vt.llVal = -100;
2834         return func (VT_I8, vt);
2835 }
2836
2837 LIBTEST_API int STDCALL 
2838 mono_test_marshal_variant_in_ulong_unmanaged(VarFunc func)
2839 {
2840         VARIANT vt;
2841         vt.vt = VT_UI8;
2842         vt.ullVal = 100;
2843         return func (VT_UI8, vt);
2844 }
2845
2846 LIBTEST_API int STDCALL 
2847 mono_test_marshal_variant_in_float_unmanaged(VarFunc func)
2848 {
2849         VARIANT vt;
2850         vt.vt = VT_R4;
2851         vt.fltVal = 3.14;
2852         return func (VT_R4, vt);
2853 }
2854
2855 LIBTEST_API int STDCALL 
2856 mono_test_marshal_variant_in_double_unmanaged(VarFunc func)
2857 {
2858         VARIANT vt;
2859         vt.vt = VT_R8;
2860         vt.dblVal = 3.14;
2861         return func (VT_R8, vt);
2862 }
2863
2864 LIBTEST_API int STDCALL 
2865 mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func)
2866 {
2867         VARIANT vt;
2868         vt.vt = VT_BSTR;
2869         vt.bstrVal = marshal_bstr_alloc("PI");
2870         return func (VT_BSTR, vt);
2871 }
2872
2873 LIBTEST_API int STDCALL 
2874 mono_test_marshal_variant_in_bool_true_unmanaged(VarFunc func)
2875 {
2876         VARIANT vt;
2877         vt.vt = VT_BOOL;
2878         vt.boolVal = VARIANT_TRUE;
2879         return func (VT_BOOL, vt);
2880 }
2881
2882 LIBTEST_API int STDCALL 
2883 mono_test_marshal_variant_in_bool_false_unmanaged(VarFunc func)
2884 {
2885         VARIANT vt;
2886         vt.vt = VT_BOOL;
2887         vt.boolVal = VARIANT_FALSE;
2888         return func (VT_BOOL, vt);
2889 }
2890
2891 LIBTEST_API int STDCALL 
2892 mono_test_marshal_variant_out_sbyte_unmanaged(VarRefFunc func)
2893 {
2894         VARIANT vt;
2895         VariantInit (&vt);
2896         func (VT_I1, &vt);
2897         if (vt.vt == VT_I1 && vt.cVal == -100)
2898                 return 0;
2899         return 1;
2900 }
2901
2902 LIBTEST_API int STDCALL 
2903 mono_test_marshal_variant_out_byte_unmanaged(VarRefFunc func)
2904 {
2905         VARIANT vt;
2906         VariantInit (&vt);
2907         func (VT_UI1, &vt);
2908         if (vt.vt == VT_UI1 && vt.bVal == 100)
2909                 return 0;
2910         return 1;
2911 }
2912
2913 LIBTEST_API int STDCALL 
2914 mono_test_marshal_variant_out_short_unmanaged(VarRefFunc func)
2915 {
2916         VARIANT vt;
2917         VariantInit (&vt);
2918         func (VT_I2, &vt);
2919         if (vt.vt == VT_I2 && vt.iVal == -100)
2920                 return 0;
2921         return 1;
2922 }
2923
2924 LIBTEST_API int STDCALL 
2925 mono_test_marshal_variant_out_ushort_unmanaged(VarRefFunc func)
2926 {
2927         VARIANT vt;
2928         VariantInit (&vt);
2929         func (VT_UI2, &vt);
2930         if (vt.vt == VT_UI2 && vt.uiVal == 100)
2931                 return 0;
2932         return 1;
2933 }
2934
2935 LIBTEST_API int STDCALL 
2936 mono_test_marshal_variant_out_int_unmanaged(VarRefFunc func)
2937 {
2938         VARIANT vt;
2939         VariantInit (&vt);
2940         func (VT_I4, &vt);
2941         if (vt.vt == VT_I4 && vt.lVal == -100)
2942                 return 0;
2943         return 1;
2944 }
2945
2946 LIBTEST_API int STDCALL 
2947 mono_test_marshal_variant_out_uint_unmanaged(VarRefFunc func)
2948 {
2949         VARIANT vt;
2950         VariantInit (&vt);
2951         func (VT_UI4, &vt);
2952         if (vt.vt == VT_UI4 && vt.ulVal == 100)
2953                 return 0;
2954         return 1;
2955 }
2956
2957 LIBTEST_API int STDCALL 
2958 mono_test_marshal_variant_out_long_unmanaged(VarRefFunc func)
2959 {
2960         VARIANT vt;
2961         VariantInit (&vt);
2962         func (VT_I8, &vt);
2963         if (vt.vt == VT_I8 && vt.llVal == -100)
2964                 return 0;
2965         return 1;
2966 }
2967
2968 LIBTEST_API int STDCALL 
2969 mono_test_marshal_variant_out_ulong_unmanaged(VarRefFunc func)
2970 {
2971         VARIANT vt;
2972         VariantInit (&vt);
2973         func (VT_UI8, &vt);
2974         if (vt.vt == VT_UI8 && vt.ullVal == 100)
2975                 return 0;
2976         return 1;
2977 }
2978
2979 LIBTEST_API int STDCALL 
2980 mono_test_marshal_variant_out_float_unmanaged(VarRefFunc func)
2981 {
2982         VARIANT vt;
2983         VariantInit (&vt);
2984         func (VT_R4, &vt);
2985         if (vt.vt == VT_R4 && fabs (vt.fltVal - 3.14f) < 1e-10)
2986                 return 0;
2987         return 1;
2988 }
2989
2990 LIBTEST_API int STDCALL 
2991 mono_test_marshal_variant_out_double_unmanaged(VarRefFunc func)
2992 {
2993         VARIANT vt;
2994         VariantInit (&vt);
2995         func (VT_R8, &vt);
2996         if (vt.vt == VT_R8 && fabs (vt.dblVal - 3.14) < 1e-10)
2997                 return 0;
2998         return 1;
2999 }
3000
3001 LIBTEST_API int STDCALL 
3002 mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func)
3003 {
3004         VARIANT vt;
3005         gchar* bstr_utf8;
3006         gint32 result = 0;
3007
3008
3009         VariantInit (&vt);
3010         func (VT_BSTR, &vt);
3011         bstr_utf8 = g_utf16_to_utf8 (vt.bstrVal, -1, NULL, NULL, NULL);
3012         result = strcmp("PI", bstr_utf8);
3013         g_free(bstr_utf8);
3014         if (vt.vt == VT_BSTR && !result)
3015                 return 0;
3016         return 1;
3017 }
3018
3019 LIBTEST_API int STDCALL 
3020 mono_test_marshal_variant_out_bool_true_unmanaged(VarRefFunc func)
3021 {
3022         VARIANT vt;
3023         VariantInit (&vt);
3024         func (VT_BOOL, &vt);
3025         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
3026                 return 0;
3027         return 1;
3028 }
3029
3030 LIBTEST_API int STDCALL 
3031 mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
3032 {
3033         VARIANT vt;
3034         VariantInit (&vt);
3035         func (VT_BOOL, &vt);
3036         if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
3037                 return 0;
3038         return 1;
3039 }
3040
3041 typedef struct MonoComObject MonoComObject;
3042
3043 typedef struct
3044 {
3045         int (STDCALL *QueryInterface)(MonoComObject* pUnk, gpointer riid, gpointer* ppv);
3046         int (STDCALL *AddRef)(MonoComObject* pUnk);
3047         int (STDCALL *Release)(MonoComObject* pUnk);
3048         int (STDCALL *get_ITest)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3049         int (STDCALL *SByteIn)(MonoComObject* pUnk, char a);
3050         int (STDCALL *ByteIn)(MonoComObject* pUnk, unsigned char a);
3051         int (STDCALL *ShortIn)(MonoComObject* pUnk, short a);
3052         int (STDCALL *UShortIn)(MonoComObject* pUnk, unsigned short a);
3053         int (STDCALL *IntIn)(MonoComObject* pUnk, int a);
3054         int (STDCALL *UIntIn)(MonoComObject* pUnk, unsigned int a);
3055         int (STDCALL *LongIn)(MonoComObject* pUnk, gint64 a);
3056         int (STDCALL *ULongIn)(MonoComObject* pUnk, guint64 a);
3057         int (STDCALL *FloatIn)(MonoComObject* pUnk, float a);
3058         int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a);
3059         int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
3060         int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
3061 } MonoIUnknown;
3062
3063 struct MonoComObject
3064 {
3065         MonoIUnknown* vtbl;
3066         int m_ref;
3067 };
3068
3069 static GUID IID_ITest = {0, 0, 0, {0,0,0,0,0,0,0,1}};
3070 static GUID IID_IMonoUnknown = {0, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3071 static GUID IID_IMonoDispatch = {0x00020400, 0, 0, {0xc0,0,0,0,0,0,0,0x46}};
3072
3073 LIBTEST_API int STDCALL
3074 MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv)
3075 {
3076
3077         *ppv = NULL;
3078         if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) {
3079                 *ppv = pUnk;
3080                 return S_OK;
3081         }
3082         else if (!memcmp(riid, &IID_ITest, sizeof(GUID))) {
3083                 *ppv = pUnk;
3084                 return S_OK;
3085         }
3086         else if (!memcmp(riid, &IID_IMonoDispatch, sizeof(GUID))) {
3087                 *ppv = pUnk;
3088                 return S_OK;
3089         }
3090         return 0x80004002; //E_NOINTERFACE;
3091 }
3092
3093 LIBTEST_API int STDCALL 
3094 MonoAddRef(MonoComObject* pUnk)
3095 {
3096         return ++(pUnk->m_ref);
3097 }
3098
3099 LIBTEST_API int STDCALL 
3100 MonoRelease(MonoComObject* pUnk)
3101 {
3102         return --(pUnk->m_ref);
3103 }
3104
3105 LIBTEST_API int STDCALL 
3106 SByteIn(MonoComObject* pUnk, char a)
3107 {
3108         return S_OK;
3109 }
3110
3111 LIBTEST_API int STDCALL 
3112 ByteIn(MonoComObject* pUnk, unsigned char a)
3113 {
3114         return S_OK;
3115 }
3116
3117 LIBTEST_API int STDCALL 
3118 ShortIn(MonoComObject* pUnk, short a)
3119 {
3120         return S_OK;
3121 }
3122
3123 LIBTEST_API int STDCALL 
3124 UShortIn(MonoComObject* pUnk, unsigned short a)
3125 {
3126         return S_OK;
3127 }
3128
3129 LIBTEST_API int STDCALL 
3130 IntIn(MonoComObject* pUnk, int a)
3131 {
3132         return S_OK;
3133 }
3134
3135 LIBTEST_API int STDCALL 
3136 UIntIn(MonoComObject* pUnk, unsigned int a)
3137 {
3138         return S_OK;
3139 }
3140
3141 LIBTEST_API int STDCALL 
3142 LongIn(MonoComObject* pUnk, gint64 a)
3143 {
3144         return S_OK;
3145 }
3146
3147 LIBTEST_API int STDCALL 
3148 ULongIn(MonoComObject* pUnk, guint64 a)
3149 {
3150         return S_OK;
3151 }
3152
3153 LIBTEST_API int STDCALL 
3154 FloatIn(MonoComObject* pUnk, float a)
3155 {
3156         return S_OK;
3157 }
3158
3159 LIBTEST_API int STDCALL 
3160 DoubleIn(MonoComObject* pUnk, double a)
3161 {
3162         return S_OK;
3163 }
3164
3165 LIBTEST_API int STDCALL 
3166 ITestIn(MonoComObject* pUnk, MonoComObject *pUnk2)
3167 {
3168         return S_OK;
3169 }
3170
3171 LIBTEST_API int STDCALL 
3172 ITestOut(MonoComObject* pUnk, MonoComObject* *ppUnk)
3173 {
3174         return S_OK;
3175 }
3176
3177 static void create_com_object (MonoComObject** pOut);
3178
3179 LIBTEST_API int STDCALL 
3180 get_ITest(MonoComObject* pUnk, MonoComObject* *ppUnk)
3181 {
3182         create_com_object (ppUnk);
3183         return S_OK;
3184 }
3185
3186 static void create_com_object (MonoComObject** pOut)
3187 {
3188         *pOut = marshal_new0 (MonoComObject, 1);
3189         (*pOut)->vtbl = marshal_new0 (MonoIUnknown, 1);
3190
3191         (*pOut)->m_ref = 1;
3192         (*pOut)->vtbl->QueryInterface = MonoQueryInterface;
3193         (*pOut)->vtbl->AddRef = MonoAddRef;
3194         (*pOut)->vtbl->Release = MonoRelease;
3195         (*pOut)->vtbl->SByteIn = SByteIn;
3196         (*pOut)->vtbl->ByteIn = ByteIn;
3197         (*pOut)->vtbl->ShortIn = ShortIn;
3198         (*pOut)->vtbl->UShortIn = UShortIn;
3199         (*pOut)->vtbl->IntIn = IntIn;
3200         (*pOut)->vtbl->UIntIn = UIntIn;
3201         (*pOut)->vtbl->LongIn = LongIn;
3202         (*pOut)->vtbl->ULongIn = ULongIn;
3203         (*pOut)->vtbl->FloatIn = FloatIn;
3204         (*pOut)->vtbl->DoubleIn = DoubleIn;
3205         (*pOut)->vtbl->ITestIn = ITestIn;
3206         (*pOut)->vtbl->ITestOut = ITestOut;
3207         (*pOut)->vtbl->get_ITest = get_ITest;
3208 }
3209
3210 static MonoComObject* same_object = NULL;
3211
3212 LIBTEST_API int STDCALL 
3213 mono_test_marshal_com_object_create(MonoComObject* *pUnk)
3214 {
3215         create_com_object (pUnk);
3216
3217         if (!same_object)
3218                 same_object = *pUnk;
3219
3220         return 0;
3221 }
3222
3223 LIBTEST_API int STDCALL 
3224 mono_test_marshal_com_object_same(MonoComObject* *pUnk)
3225 {
3226         *pUnk = same_object;
3227
3228         return 0;
3229 }
3230
3231 LIBTEST_API int STDCALL 
3232 mono_test_marshal_com_object_destroy(MonoComObject *pUnk)
3233 {
3234         int ref = --(pUnk->m_ref);
3235         g_free(pUnk->vtbl);
3236         g_free(pUnk);
3237
3238         return ref;
3239 }
3240
3241 LIBTEST_API int STDCALL 
3242 mono_test_marshal_com_object_ref_count(MonoComObject *pUnk)
3243 {
3244         return pUnk->m_ref;
3245 }
3246
3247 LIBTEST_API int STDCALL 
3248 mono_test_marshal_ccw_itest (MonoComObject *pUnk)
3249 {
3250         int hr = 0;
3251         MonoComObject* pTest;
3252
3253         if (!pUnk)
3254                 return 1;
3255
3256         hr = pUnk->vtbl->SByteIn (pUnk, -100);
3257         if (hr != 0)
3258                 return 2;
3259         hr = pUnk->vtbl->ByteIn (pUnk, 100);
3260         if (hr != 0)
3261                 return 3;
3262         hr = pUnk->vtbl->ShortIn (pUnk, -100);
3263         if (hr != 0)
3264                 return 4;
3265         hr = pUnk->vtbl->UShortIn (pUnk, 100);
3266         if (hr != 0)
3267                 return 5;
3268         hr = pUnk->vtbl->IntIn (pUnk, -100);
3269         if (hr != 0)
3270                 return 6;
3271         hr = pUnk->vtbl->UIntIn (pUnk, 100);
3272         if (hr != 0)
3273                 return 7;
3274         hr = pUnk->vtbl->LongIn (pUnk, -100);
3275         if (hr != 0)
3276                 return 8;
3277         hr = pUnk->vtbl->ULongIn (pUnk, 100);
3278         if (hr != 0)
3279                 return 9;
3280         hr = pUnk->vtbl->FloatIn (pUnk, 3.14f);
3281         if (hr != 0)
3282                 return 10;
3283         hr = pUnk->vtbl->DoubleIn (pUnk, 3.14);
3284         if (hr != 0)
3285                 return 11;
3286         hr = pUnk->vtbl->ITestIn (pUnk, pUnk);
3287         if (hr != 0)
3288                 return 12;
3289         hr = pUnk->vtbl->ITestOut (pUnk, &pTest);
3290         if (hr != 0)
3291                 return 13;
3292
3293         return 0;
3294 }
3295
3296 /*
3297  * mono_method_get_unmanaged_thunk tests
3298  */
3299
3300 #if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__) || defined(__OpenBSD__)) || (defined(__ppc__) && defined(__APPLE__)))
3301 #define ALIGN(size) __attribute__ ((aligned(size)))
3302 #else
3303 #define ALIGN(size)
3304 #endif
3305
3306
3307 /* thunks.cs:TestStruct */
3308 typedef struct _TestStruct {
3309         int A;
3310         double B;
3311 } TestStruct;
3312
3313 /* Searches for mono symbols in all loaded modules */
3314 static gpointer
3315 lookup_mono_symbol (const char *symbol_name)
3316 {
3317         gpointer symbol;
3318         if (g_module_symbol (g_module_open (NULL, G_MODULE_BIND_LAZY), symbol_name, &symbol))
3319                 return symbol;
3320         else
3321                 return NULL;
3322 }
3323
3324 LIBTEST_API gpointer STDCALL
3325 mono_test_marshal_lookup_symbol (const char *symbol_name)
3326 {
3327         return lookup_mono_symbol (symbol_name);
3328 }
3329
3330 /**
3331  * test_method_thunk:
3332  *
3333  * @test_id: the test number
3334  * @test_method_handle: MonoMethod* of the C# test method
3335  * @create_object_method_handle: MonoMethod* of thunks.cs:Test.CreateObject
3336  */
3337 LIBTEST_API int STDCALL  
3338 test_method_thunk (int test_id, gpointer test_method_handle, gpointer create_object_method_handle)
3339 {
3340         gpointer (*mono_method_get_unmanaged_thunk)(gpointer)
3341                 = lookup_mono_symbol ("mono_method_get_unmanaged_thunk");
3342
3343         gpointer (*mono_string_new_wrapper)(const char *)
3344                 = lookup_mono_symbol ("mono_string_new_wrapper");
3345
3346         char* (*mono_string_to_utf8)(gpointer)
3347                 = lookup_mono_symbol ("mono_string_to_utf8");
3348
3349         gpointer (*mono_object_unbox)(gpointer)
3350                 = lookup_mono_symbol ("mono_object_unbox");
3351
3352         gpointer test_method, ex = NULL;
3353         gpointer (STDCALL *CreateObject)(gpointer*);
3354
3355
3356         if (!mono_method_get_unmanaged_thunk)
3357                 return 1;
3358
3359         test_method =  mono_method_get_unmanaged_thunk (test_method_handle);
3360         if (!test_method)
3361                 return 2;
3362
3363         CreateObject = mono_method_get_unmanaged_thunk (create_object_method_handle);
3364         if (!CreateObject)
3365                 return 3;
3366
3367
3368         switch (test_id) {
3369
3370         case 0: {
3371                 /* thunks.cs:Test.Test0 */
3372                 void (STDCALL *F)(gpointer*) = test_method;
3373                 F (&ex);
3374                 break;
3375         }
3376
3377         case 1: {
3378                 /* thunks.cs:Test.Test1 */
3379                 int (STDCALL *F)(gpointer*) = test_method;
3380                 if (F (&ex) != 42)
3381                         return 4;
3382                 break;
3383         }
3384
3385         case 2: {
3386                 /* thunks.cs:Test.Test2 */
3387                 gpointer (STDCALL *F)(gpointer, gpointer*) = test_method;
3388                 gpointer str = mono_string_new_wrapper ("foo");
3389                 if (str != F (str, &ex))
3390                         return 4;
3391                 break;
3392         }
3393
3394         case 3: {
3395                 /* thunks.cs:Test.Test3 */
3396                 gpointer (STDCALL *F)(gpointer, gpointer, 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                 if (str != F (obj, str, &ex))
3405                         return 4;
3406                 break;
3407         }
3408
3409         case 4: {
3410                 /* thunks.cs:Test.Test4 */
3411                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3412                 gpointer obj;
3413                 gpointer str;
3414
3415                 F = test_method;
3416                 obj = CreateObject (&ex);
3417                 str = mono_string_new_wrapper ("bar");
3418
3419                 if (42 != F (obj, str, 42, &ex))
3420                         return 4;
3421
3422                 break;
3423         }
3424
3425         case 5: {
3426                 /* thunks.cs:Test.Test5 */
3427                 int (STDCALL *F)(gpointer, gpointer, int, gpointer*);
3428                 gpointer obj;
3429                 gpointer str;
3430
3431                 F = test_method;
3432                 obj = CreateObject (&ex);
3433                 str = mono_string_new_wrapper ("bar");
3434
3435                 F (obj, str, 42, &ex);
3436                 if (!ex)
3437                     return 4;
3438
3439                 break;
3440         }
3441
3442         case 6: {
3443                 /* thunks.cs:Test.Test6 */
3444                 int (STDCALL *F)(gpointer, guint8, gint16, gint32, gint64, float, double,
3445                                  gpointer, gpointer*);
3446                 gpointer obj;
3447                 gpointer str = mono_string_new_wrapper ("Test6");
3448                 int res;
3449
3450                 F = test_method;
3451                 obj = CreateObject (&ex);
3452
3453                 res = F (obj, 254, 32700, -245378, 6789600, 3.1415, 3.1415, str, &ex);
3454                 if (ex)
3455                         return 4;
3456
3457                 if (!res)
3458                         return 5;
3459
3460                 break;
3461         }
3462
3463         case 7: {
3464                 /* thunks.cs:Test.Test7 */
3465                 gint64 (STDCALL *F)(gpointer*) = test_method;
3466                 if (F (&ex) != G_MAXINT64)
3467                         return 4;
3468                 break;
3469         }
3470
3471         case 8: {
3472                 /* thunks.cs:Test.Test8 */
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                 if (!(a1 == 254 &&
3491                       a2 == 32700 &&
3492                       a3 == -245378 &&
3493                       a4 == 6789600 &&
3494                       (fabs (a5 - 3.1415) < 0.001) &&
3495                       (fabs (a6 - 3.1415) < 0.001) &&
3496                       strcmp (mono_string_to_utf8 (a7), "Test8") == 0))
3497                         return 5;
3498
3499                 break;
3500         }
3501
3502         case 9: {
3503                 /* thunks.cs:Test.Test9 */
3504                 void (STDCALL *F)(guint8*, gint16*, gint32*, gint64*, float*, double*,
3505                                  gpointer*, gpointer*);
3506
3507                 guint8 a1;
3508                 gint16 a2;
3509                 gint32 a3;
3510                 gint64 a4;
3511                 float a5;
3512                 double a6;
3513                 gpointer a7;
3514
3515                 F = test_method;
3516
3517                 F (&a1, &a2, &a3, &a4, &a5, &a6, &a7, &ex);
3518                 if (!ex)
3519                         return 4;
3520
3521                 break;
3522         }
3523
3524         case 10: {
3525                 /* thunks.cs:Test.Test10 */
3526                 void (STDCALL *F)(gpointer*, gpointer*);
3527
3528                 gpointer obj1, obj2;
3529
3530                 obj1 = obj2 = CreateObject (&ex);
3531                 if (ex)
3532                         return 4;
3533
3534                 F = test_method;
3535
3536                 F (&obj1, &ex);
3537                 if (ex)
3538                         return 5;
3539
3540                 if (obj1 == obj2)
3541                         return 6;
3542
3543                 break;
3544         }
3545
3546         case 100: {
3547                 /* thunks.cs:TestStruct.Test0 */
3548                 int (STDCALL *F)(gpointer*, gpointer*);
3549
3550                 gpointer obj;
3551                 TestStruct *a1;
3552                 int res;
3553
3554                 obj = CreateObject (&ex);
3555                 if (ex)
3556                         return 4;
3557
3558                 if (!obj)
3559                         return 5;
3560
3561                 a1 = mono_object_unbox (obj);
3562                 if (!a1)
3563                         return 6;
3564
3565                 a1->A = 42;
3566                 a1->B = 3.1415;
3567
3568                 F = test_method;
3569
3570                 res = F (obj, &ex);
3571                 if (ex)
3572                         return 7;
3573
3574                 if (!res)
3575                         return 8;
3576
3577                 /* check whether the call was really by value */
3578                 if (a1->A != 42 || a1->B != 3.1415)
3579                         return 9;
3580
3581                 break;
3582         }
3583
3584         case 101: {
3585                 /* thunks.cs:TestStruct.Test1 */
3586                 void (STDCALL *F)(gpointer, gpointer*);
3587
3588                 TestStruct *a1;
3589                 gpointer obj;
3590
3591                 obj = CreateObject (&ex);
3592                 if (ex)
3593                         return 4;
3594
3595                 if (!obj)
3596                         return 5;
3597
3598                 a1 = mono_object_unbox (obj);
3599                 if (!a1)
3600                         return 6;
3601
3602                 F = test_method;
3603
3604                 F (obj, &ex);
3605                 if (ex)
3606                         return 7;
3607
3608                 if (a1->A != 42)
3609                         return 8;
3610
3611                 if (!fabs (a1->B - 3.1415) < 0.001)
3612                         return 9;
3613
3614                 break;
3615         }
3616
3617         case 102: {
3618                 /* thunks.cs:TestStruct.Test2 */
3619                 gpointer (STDCALL *F)(gpointer*);
3620
3621                 TestStruct *a1;
3622                 gpointer obj;
3623
3624                 F = test_method;
3625
3626                 obj = F (&ex);
3627                 if (ex)
3628                         return 4;
3629
3630                 if (!obj)
3631                         return 5;
3632
3633                 a1 = mono_object_unbox (obj);
3634
3635                 if (a1->A != 42)
3636                         return 5;
3637
3638                 if (!fabs (a1->B - 3.1415) < 0.001)
3639                         return 6;
3640
3641                 break;
3642         }
3643
3644         case 103: {
3645                 /* thunks.cs:TestStruct.Test3 */
3646                 void (STDCALL *F)(gpointer, gpointer*);
3647
3648                 TestStruct *a1;
3649                 gpointer obj;
3650
3651                 obj = CreateObject (&ex);
3652                 if (ex)
3653                         return 4;
3654
3655                 if (!obj)
3656                         return 5;
3657                 
3658                 a1 = mono_object_unbox (obj);
3659
3660                 if (!a1)
3661                         return 6;
3662
3663                 a1->A = 42;
3664                 a1->B = 3.1415;
3665
3666                 F = test_method;
3667
3668                 F (obj, &ex);
3669                 if (ex)
3670                         return 4;
3671
3672                 if (a1->A != 1)
3673                         return 5;
3674
3675                 if (a1->B != 17)
3676                         return 6;
3677
3678                 break;
3679         }
3680
3681         default:
3682                 return 9;
3683
3684         }
3685
3686         return 0;
3687 }
3688
3689 typedef struct 
3690 {
3691         char a;
3692 } winx64_struct1;
3693
3694 LIBTEST_API int STDCALL  
3695 mono_test_Winx64_struct1_in (winx64_struct1 var)
3696 {
3697         if (var.a != 123)
3698                 return 1;
3699         return 0;
3700 }
3701
3702 typedef struct
3703 {
3704         char a;
3705         char b;
3706 } winx64_struct2;
3707
3708 LIBTEST_API int STDCALL  
3709 mono_test_Winx64_struct2_in (winx64_struct2 var)
3710 {
3711         if (var.a != 4)
3712                 return 1;
3713         if (var.b != 5)
3714                 return 2;
3715         return 0;
3716 }
3717
3718
3719 typedef struct
3720 {
3721         char a;
3722         char b;
3723         short c;
3724 } winx64_struct3;
3725
3726 LIBTEST_API int STDCALL  
3727 mono_test_Winx64_struct3_in (winx64_struct3 var)
3728 {
3729         if (var.a != 4)
3730                 return 1;
3731         if (var.b != 5)
3732                 return 2;
3733         if (var.c != 0x1234)
3734                 return 3;
3735         return 0;
3736 }
3737
3738 typedef struct
3739 {
3740         char a;
3741         char b;
3742         short c;
3743         unsigned int d;
3744 } winx64_struct4;
3745
3746 LIBTEST_API int STDCALL  
3747 mono_test_Winx64_struct4_in (winx64_struct4 var)
3748 {
3749         if (var.a != 4)
3750                 return 1;
3751         if (var.b != 5)
3752                 return 2;
3753         if (var.c != 0x1234)
3754                 return 3;
3755         if (var.d != 0x87654321)
3756                 return 4;
3757         return 0;
3758 }
3759
3760 typedef struct
3761 {
3762         char a;
3763         char b;
3764         char c;
3765 } winx64_struct5;
3766
3767 LIBTEST_API int STDCALL  
3768 mono_test_Winx64_struct5_in (winx64_struct5 var)
3769 {
3770         if (var.a != 4)
3771                 return 1;
3772         if (var.b != 5)
3773                 return 2;
3774         if (var.c != 6)
3775                 return 3;
3776         return 0;
3777 }
3778
3779 typedef struct
3780 {
3781         winx64_struct1 a;
3782         short b;
3783         char c;
3784 } winx64_struct6;
3785
3786 LIBTEST_API int STDCALL  
3787 mono_test_Winx64_struct6_in (winx64_struct6 var)
3788 {
3789         if (var.a.a != 4)
3790                 return 1;
3791         if (var.b != 5)
3792                 return 2;
3793         if (var.c != 6)
3794                 return 3;
3795         return 0;
3796 }
3797
3798 LIBTEST_API int STDCALL  
3799 mono_test_Winx64_structs_in1 (winx64_struct1 var1,
3800                          winx64_struct2 var2,
3801                          winx64_struct3 var3,
3802                          winx64_struct4 var4)
3803 {
3804         if (var1.a != 123)
3805                 return 1;
3806         
3807         if (var2.a != 4)
3808                 return 2;
3809         if (var2.b != 5)
3810                 return 3;
3811         
3812         if (var3.a != 4)
3813                 return 4;
3814         if (var3.b != 5)
3815                 return 2;
3816         if (var3.c != 0x1234)
3817                 return 5;
3818         
3819         if (var4.a != 4)
3820                 return 6;
3821         if (var4.b != 5)
3822                 return 7;
3823         if (var4.c != 0x1234)
3824                 return 8;
3825         if (var4.d != 0x87654321)
3826                 return 9;
3827         return 0;
3828 }
3829
3830 LIBTEST_API int STDCALL  
3831 mono_test_Winx64_structs_in2 (winx64_struct1 var1,
3832                          winx64_struct1 var2,
3833                          winx64_struct1 var3,
3834                          winx64_struct1 var4,
3835                          winx64_struct1 var5)
3836 {
3837         if (var1.a != 1)
3838                 return 1;
3839         if (var2.a != 2)
3840                 return 2;
3841         if (var3.a != 3)
3842                 return 3;
3843         if (var4.a != 4)
3844                 return 4;
3845         if (var5.a != 5)
3846                 return 5;
3847         
3848         return 0;
3849 }
3850
3851 LIBTEST_API int STDCALL  
3852 mono_test_Winx64_structs_in3 (winx64_struct1 var1,
3853                          winx64_struct5 var2,
3854                          winx64_struct1 var3,
3855                          winx64_struct5 var4,
3856                          winx64_struct1 var5,
3857                          winx64_struct5 var6)
3858 {
3859         if (var1.a != 1)
3860                 return 1;
3861         
3862         if (var2.a != 2)
3863                 return 2;
3864         if (var2.b != 3)
3865                 return 2;
3866         if (var2.c != 4)
3867                 return 4;
3868         
3869         if (var3.a != 5)
3870                 return 5;
3871         
3872         if (var4.a != 6)
3873                 return 6;
3874         if (var4.b != 7)
3875                 return 7;
3876         if (var4.c != 8)
3877                 return 8;
3878         
3879         if (var5.a != 9)
3880                 return 9;
3881
3882         if (var6.a != 10)
3883                 return 10;
3884         if (var6.b != 11)
3885                 return 11;
3886         if (var6.c != 12)
3887                 return 12;
3888         
3889         return 0;
3890 }
3891
3892 LIBTEST_API winx64_struct1 STDCALL  
3893 mono_test_Winx64_struct1_ret (void)
3894 {
3895         winx64_struct1 ret;
3896         ret.a = 123;
3897         return ret;
3898 }
3899
3900 LIBTEST_API winx64_struct2 STDCALL  
3901 mono_test_Winx64_struct2_ret (void)
3902 {
3903         winx64_struct2 ret;
3904         ret.a = 4;
3905         ret.b = 5;
3906         return ret;
3907 }
3908
3909 LIBTEST_API winx64_struct3 STDCALL  
3910 mono_test_Winx64_struct3_ret (void)
3911 {
3912         winx64_struct3 ret;
3913         ret.a = 4;
3914         ret.b = 5;
3915         ret.c = 0x1234;
3916         return ret;
3917 }
3918
3919 LIBTEST_API winx64_struct4 STDCALL  
3920 mono_test_Winx64_struct4_ret (void)
3921 {
3922         winx64_struct4 ret;
3923         ret.a = 4;
3924         ret.b = 5;
3925         ret.c = 0x1234;
3926         ret.d = 0x87654321;
3927         return ret;
3928 }
3929
3930 LIBTEST_API winx64_struct5 STDCALL  
3931 mono_test_Winx64_struct5_ret (void)
3932 {
3933         winx64_struct5 ret;
3934         ret.a = 4;
3935         ret.b = 5;
3936         ret.c = 6;
3937         return ret;
3938 }
3939
3940 LIBTEST_API winx64_struct1 STDCALL  
3941 mono_test_Winx64_struct1_ret_5_args (char a, char b, char c, char d, char e)
3942 {
3943         winx64_struct1 ret;
3944         ret.a = a + b + c + d + e;
3945         return ret;
3946 }
3947
3948 LIBTEST_API winx64_struct5 STDCALL
3949 mono_test_Winx64_struct5_ret6_args (char a, char b, char c, char d, char e)
3950 {
3951         winx64_struct5 ret;
3952         ret.a = a + b;
3953         ret.b = c + d;
3954         ret.c = e;
3955         return ret;
3956 }
3957
3958 typedef struct
3959 {
3960         float a;
3961         float b;
3962 } winx64_floatStruct;
3963
3964 LIBTEST_API int STDCALL  
3965 mono_test_Winx64_floatStruct (winx64_floatStruct a)
3966 {
3967         if (a.a > 5.6 || a.a < 5.4)
3968                 return 1;
3969
3970         if (a.b > 9.6 || a.b < 9.4)
3971                 return 2;
3972         
3973         return 0;
3974 }
3975
3976 typedef struct
3977 {
3978         double a;
3979 } winx64_doubleStruct;
3980
3981 LIBTEST_API int STDCALL  
3982 mono_test_Winx64_doubleStruct (winx64_doubleStruct a)
3983 {
3984         if (a.a > 5.6 || a.a < 5.4)
3985                 return 1;
3986         
3987         return 0;
3988 }
3989
3990 typedef int (STDCALL *managed_struct1_delegate) (winx64_struct1 a);
3991
3992 LIBTEST_API int STDCALL 
3993 mono_test_managed_Winx64_struct1_in(managed_struct1_delegate func)
3994 {
3995         winx64_struct1 val;
3996         val.a = 5;
3997         return func (val);
3998 }
3999
4000 typedef int (STDCALL *managed_struct5_delegate) (winx64_struct5 a);
4001
4002 LIBTEST_API int STDCALL 
4003 mono_test_managed_Winx64_struct5_in(managed_struct5_delegate func)
4004 {
4005         winx64_struct5 val;
4006         val.a = 5;
4007         val.b = 0x10;
4008         val.c = 0x99;
4009         return func (val);
4010 }
4011
4012 typedef int (STDCALL *managed_struct1_struct5_delegate) (winx64_struct1 a, winx64_struct5 b,
4013                                                          winx64_struct1 c, winx64_struct5 d,
4014                                                          winx64_struct1 e, winx64_struct5 f);
4015
4016 LIBTEST_API int STDCALL 
4017 mono_test_managed_Winx64_struct1_struct5_in(managed_struct1_struct5_delegate func)
4018 {
4019         winx64_struct1 a, c, e;
4020         winx64_struct5 b, d, f;
4021         a.a = 1;
4022         b.a = 2; b.b = 3; b.c = 4;
4023         c.a = 5;
4024         d.a = 6; d.b = 7; d.c = 8;
4025         e.a = 9;
4026         f.a = 10; f.b = 11; f.c = 12;
4027
4028         return func (a, b, c, d, e, f);
4029 }
4030
4031 typedef winx64_struct1 (STDCALL *managed_struct1_ret_delegate) (void);
4032
4033 LIBTEST_API int STDCALL 
4034 mono_test_Winx64_struct1_ret_managed (managed_struct1_ret_delegate func)
4035 {
4036         winx64_struct1 ret;
4037
4038         ret = func ();
4039
4040         if (ret.a != 0x45)
4041                 return 1;
4042         
4043         return 0;
4044 }
4045
4046 typedef winx64_struct5 (STDCALL *managed_struct5_ret_delegate) (void);
4047
4048 LIBTEST_API int STDCALL 
4049 mono_test_Winx64_struct5_ret_managed (managed_struct5_ret_delegate func)
4050 {
4051         winx64_struct5 ret;
4052
4053         ret = func ();
4054
4055         if (ret.a != 0x12)
4056                 return 1;
4057         if (ret.b != 0x34)
4058                 return 2;
4059         if (ret.c != 0x56)
4060                 return 3;
4061         
4062         return 0;
4063 }
4064
4065 LIBTEST_API int STDCALL 
4066 mono_test_marshal_bool_in (int arg, unsigned int expected, unsigned int bDefaultMarsh, unsigned int bBoolCustMarsh,
4067                            char bI1CustMarsh, unsigned char bU1CustMarsh, short bVBCustMarsh)
4068 {
4069         switch (arg) {
4070         case 1: 
4071                 if (bDefaultMarsh != expected)
4072                         return 1;
4073                 break;
4074         case 2: 
4075                 if (bBoolCustMarsh != expected)
4076                         return 2;
4077                 break;
4078         case 3: 
4079                 if (bI1CustMarsh != expected)
4080                         return 3;
4081                 break;
4082         case 4: 
4083                 if (bU1CustMarsh != expected)
4084                         return 4;
4085                 break;
4086         case 5: 
4087                 if (bVBCustMarsh != expected)
4088                         return 5;
4089                 break;
4090         default:
4091                 return 999;             
4092         }
4093         return 0;
4094 }
4095
4096 LIBTEST_API int STDCALL 
4097 mono_test_marshal_bool_out (int arg, unsigned int testVal, unsigned int* bDefaultMarsh, unsigned int* bBoolCustMarsh,
4098                            char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh)
4099 {
4100         switch (arg) {
4101         case 1: 
4102                 if (!bDefaultMarsh)
4103                         return 1;
4104                 *bDefaultMarsh = testVal;
4105                 break;  
4106         case 2: 
4107                 if (!bBoolCustMarsh)
4108                         return 2;
4109                 *bBoolCustMarsh = testVal;
4110                 break;  
4111         case 3: 
4112                 if (!bI1CustMarsh)
4113                         return 3;
4114                 *bI1CustMarsh = (char)testVal;
4115                 break;  
4116         case 4: 
4117                 if (!bU1CustMarsh)
4118                         return 4;
4119                 *bU1CustMarsh = (unsigned char)testVal;
4120                 break;  
4121         case 5: 
4122                 if (!bVBCustMarsh)
4123                         return 5;
4124                 *bVBCustMarsh = (unsigned short)testVal;
4125                 break;  
4126         default:
4127                 return 999;
4128         }
4129         return 0;
4130 }
4131
4132 LIBTEST_API int STDCALL 
4133 mono_test_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4134                             unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, 
4135                             unsigned short* bVBCustMarsh)
4136 {
4137         switch (arg) {
4138         case 1: 
4139                 if (!bDefaultMarsh)
4140                         return 1;
4141                 if (*bDefaultMarsh != expected)
4142                         return 2;
4143                 *bDefaultMarsh = testVal;
4144                 break;
4145         case 2: 
4146                 if (!bBoolCustMarsh)
4147                         return 3;
4148                 if (*bBoolCustMarsh != expected)
4149                         return 4;
4150                 *bBoolCustMarsh = testVal;
4151                 break;
4152         case 3: 
4153                 if (!bI1CustMarsh)
4154                         return 5;
4155                 if (*bI1CustMarsh != expected)
4156                         return 6;
4157                 *bI1CustMarsh = (char)testVal;
4158                 break;
4159         case 4: 
4160                 if (!bU1CustMarsh)
4161                         return 7;
4162                 if (*bU1CustMarsh != expected)
4163                         return 8;
4164                 *bU1CustMarsh = (unsigned char)testVal;
4165                 break;
4166         case 5: 
4167                 if (!bVBCustMarsh)
4168                         return 9;
4169                 if (*bVBCustMarsh != expected)
4170                         return 10;
4171                 *bVBCustMarsh = (unsigned short)testVal;
4172                 break;
4173         default:
4174                 return 999;             
4175         }
4176         return 0;
4177 }
4178
4179
4180 typedef int (STDCALL *MarshalBoolInDelegate) (int arg, unsigned int expected, unsigned int bDefaultMarsh,
4181         unsigned int bBoolCustMarsh, char bI1CustMarsh, unsigned char bU1CustMarsh, unsigned short bVBCustMarsh);
4182
4183 LIBTEST_API int STDCALL 
4184 mono_test_managed_marshal_bool_in (int arg, unsigned int expected, unsigned int testVal, MarshalBoolInDelegate pfcn)
4185 {
4186         if (!pfcn)
4187                 return 0x9900;
4188
4189         switch (arg) {
4190         case 1:
4191                 return pfcn (arg, expected, testVal, 0, 0, 0, 0);
4192         case 2:
4193                 return pfcn (arg, expected, 0, testVal,  0, 0, 0);
4194         case 3:
4195                 return pfcn (arg, expected, 0, 0, testVal, 0, 0);
4196         case 4:
4197                 return pfcn (arg, expected, 0, 0, 0, testVal, 0);
4198         case 5:
4199                 return pfcn (arg, expected, 0, 0, 0, 0, testVal);
4200         default:
4201                 return 0x9800;
4202         }
4203
4204         return 0;
4205 }
4206
4207 typedef int (STDCALL *MarshalBoolOutDelegate) (int arg, unsigned int expected, unsigned int* bDefaultMarsh,
4208         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4209
4210 LIBTEST_API int STDCALL 
4211 mono_test_managed_marshal_bool_out (int arg, unsigned int expected, unsigned int testVal, MarshalBoolOutDelegate pfcn)
4212 {
4213         int ret;
4214         unsigned int lDefaultMarsh, lBoolCustMarsh;
4215         char lI1CustMarsh = 0;
4216         unsigned char lU1CustMarsh = 0;
4217         unsigned short lVBCustMarsh = 0;
4218         lDefaultMarsh = lBoolCustMarsh = 0;
4219
4220         if (!pfcn)
4221                 return 0x9900;
4222
4223         switch (arg) {
4224         case 1: {
4225                 unsigned int ltVal = 0;
4226                 ret = pfcn (arg, testVal, &ltVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4227                 if (ret)
4228                         return 0x0100 + ret;
4229                 if (expected != ltVal)
4230                         return 0x0200;
4231                 break;
4232         }
4233         case 2: {
4234                 unsigned int ltVal = 0;
4235                 ret = pfcn (arg, testVal, &lDefaultMarsh, &ltVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4236                 if (ret)
4237                         return 0x0300 + ret;
4238                 if (expected != ltVal)
4239                         return 0x0400;
4240                 break;
4241         }
4242         case 3: {
4243                 char ltVal = 0;
4244                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &ltVal, &lU1CustMarsh, &lVBCustMarsh);
4245                 if (ret)
4246                         return 0x0500 + ret;
4247                 if (expected != ltVal)
4248                         return 0x0600;
4249                 break;
4250         }
4251         case 4: {
4252                 unsigned char ltVal = 0;
4253                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltVal, &lVBCustMarsh);
4254                 if (ret)
4255                         return 0x0700 + ret;
4256                 if (expected != ltVal)
4257                         return 0x0800;
4258                 break;
4259         }
4260         case 5: {
4261                 unsigned short ltVal = 0;
4262                 ret = pfcn (arg, testVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltVal);
4263                 if (ret)
4264                         return 0x0900 + ret;
4265                 if (expected != ltVal)
4266                         return 0x1000;
4267                 break;
4268         }
4269         default:
4270                 return 0x9800;
4271         }
4272
4273         return 0;
4274 }
4275
4276 typedef int (STDCALL *MarshalBoolRefDelegate) (int arg, unsigned int expected, unsigned int testVal, unsigned int* bDefaultMarsh,
4277         unsigned int* bBoolCustMarsh, char* bI1CustMarsh, unsigned char* bU1CustMarsh, unsigned short* bVBCustMarsh);
4278
4279 LIBTEST_API int STDCALL 
4280 mono_test_managed_marshal_bool_ref (int arg, unsigned int expected, unsigned int testVal, unsigned int outExpected,
4281                                     unsigned int outTestVal, MarshalBoolRefDelegate pfcn)
4282 {
4283         int ret;
4284         unsigned int lDefaultMarsh, lBoolCustMarsh;
4285         char lI1CustMarsh = 0;
4286         unsigned char lU1CustMarsh = 0;
4287         unsigned short lVBCustMarsh = 0;
4288         lDefaultMarsh = lBoolCustMarsh = 0;
4289
4290         if (!pfcn)
4291                 return 0x9900;
4292
4293         switch (arg) {
4294         case 1:
4295         {
4296                 unsigned int ltestVal = testVal;
4297                 ret = pfcn (arg, expected, outTestVal, &ltestVal, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4298                 if (ret)
4299                         return 0x0100 + ret;
4300                 if (outExpected != ltestVal)
4301                         return 0x0200;
4302                 break;
4303         }
4304         case 2:
4305         {
4306                 unsigned int ltestVal = testVal;
4307                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &ltestVal, &lI1CustMarsh, &lU1CustMarsh, &lVBCustMarsh);
4308                 if (ret)
4309                         return 0x0300 + ret;
4310                 if (outExpected != ltestVal)
4311                         return 0x0400;
4312                 break;
4313         }
4314         case 3:
4315         {
4316                 char ltestVal = testVal;
4317                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &ltestVal, &lU1CustMarsh, &lVBCustMarsh);
4318                 if (ret)
4319                         return 0x0500 + ret;
4320                 if (outExpected != ltestVal)
4321                         return 0x0600;
4322                 break;
4323         }
4324         case 4:
4325         {
4326                 unsigned char ltestVal = testVal;
4327                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &ltestVal, &lVBCustMarsh);
4328                 if (ret)
4329                         return 0x0700 + ret;
4330                 if (outExpected != ltestVal)
4331                         return 0x0800;
4332                 break;
4333         }
4334         case 5:
4335         {
4336                 unsigned short ltestVal = testVal;
4337                 ret = pfcn (arg, expected, outTestVal, &lDefaultMarsh, &lBoolCustMarsh, &lI1CustMarsh, &lU1CustMarsh, &ltestVal);
4338                 if (ret)
4339                         return 0x0900 + ret;
4340                 if (outExpected != ltestVal)
4341                         return 0x1000;
4342                 break;
4343         }
4344         default:
4345                 return 0x9800;
4346         }
4347
4348         return 0;
4349 }
4350
4351 #ifdef WIN32
4352
4353 LIBTEST_API int STDCALL 
4354 mono_test_marshal_safearray_out_1dim_vt_bstr_empty (SAFEARRAY** safearray)
4355 {
4356         /* Create an empty one-dimensional array of variants */
4357         SAFEARRAY *pSA;
4358         SAFEARRAYBOUND dimensions [1];
4359
4360         dimensions [0].lLbound = 0;
4361         dimensions [0].cElements = 0;
4362
4363         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4364         *safearray = pSA;
4365         return S_OK;
4366 }
4367
4368 LIBTEST_API int STDCALL 
4369 mono_test_marshal_safearray_out_1dim_vt_bstr (SAFEARRAY** safearray)
4370 {
4371         /* Create a one-dimensional array of 10 variants filled with "0" to "9" */
4372         SAFEARRAY *pSA;
4373         SAFEARRAYBOUND dimensions [1];
4374         long i;
4375         gchar buffer [20];
4376         HRESULT hr = S_OK;
4377         long indices [1];
4378
4379         dimensions [0].lLbound = 0;
4380         dimensions [0].cElements = 10;
4381
4382         pSA= SafeArrayCreate (VT_VARIANT, 1, dimensions);
4383         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4384                 VARIANT vOut;
4385                 VariantInit (&vOut);
4386                 vOut.vt = VT_BSTR;
4387                 _ltoa (i,buffer,10);
4388                 vOut.bstrVal= marshal_bstr_alloc (buffer);
4389                 indices [0] = i;
4390                 if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4391                         VariantClear (&vOut);
4392                         SafeArrayDestroy (pSA);
4393                         return hr;
4394                 }
4395                 VariantClear (&vOut);
4396         }
4397         *safearray = pSA;
4398         return hr;
4399 }
4400
4401 LIBTEST_API int STDCALL 
4402 mono_test_marshal_safearray_out_2dim_vt_i4 (SAFEARRAY** safearray)
4403 {
4404         /* Create a two-dimensional array of 4x3 variants filled with 11, 12, 13, etc. */
4405         SAFEARRAY *pSA;
4406         SAFEARRAYBOUND dimensions [2];
4407         long i, j;
4408         HRESULT hr = S_OK;
4409         long indices [2];
4410
4411         dimensions [0].lLbound = 0;
4412         dimensions [0].cElements = 4;
4413         dimensions [1].lLbound = 0;
4414         dimensions [1].cElements = 3;
4415
4416         pSA= SafeArrayCreate(VT_VARIANT, 2, dimensions);
4417         for (i= dimensions [0].lLbound; i< (dimensions [0].cElements + dimensions [0].lLbound); i++) {
4418                 for (j= dimensions [1].lLbound; j< (dimensions [1].cElements + dimensions [1].lLbound); j++) {
4419                         VARIANT vOut;
4420                         VariantInit (&vOut);
4421                         vOut.vt = VT_I4;
4422                         vOut.lVal = (i+1)*10+(j+1);
4423                         indices [0] = i;
4424                         indices [1] = j;
4425                         if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) {
4426                                 VariantClear (&vOut);
4427                                 SafeArrayDestroy (pSA);
4428                                 return hr;
4429                         }
4430                         VariantClear (&vOut);  // does a deep destroy of source VARIANT 
4431                 }
4432         }
4433         *safearray = pSA;
4434         return hr;
4435 }
4436
4437 LIBTEST_API int STDCALL 
4438 mono_test_marshal_safearray_out_4dim_vt_i4 (SAFEARRAY** safearray)
4439 {
4440         /* Create a four-dimensional array of 10x3x6x7 variants filled with their indices */
4441         /* Also use non zero lower bounds                                                 */
4442         SAFEARRAY *pSA;
4443         SAFEARRAYBOUND dimensions [4];
4444         long i;
4445         HRESULT hr = S_OK;
4446         VARIANT *pData;
4447
4448         dimensions [0].lLbound = 15;
4449         dimensions [0].cElements = 10;
4450         dimensions [1].lLbound = 20;
4451         dimensions [1].cElements = 3;
4452         dimensions [2].lLbound = 5;
4453         dimensions [2].cElements = 6;
4454         dimensions [3].lLbound = 12;
4455         dimensions [3].cElements = 7;
4456
4457         pSA= SafeArrayCreate (VT_VARIANT, 4, dimensions);
4458
4459         SafeArrayAccessData (pSA, (void **)&pData);
4460
4461         for (i= 0; i< 10*3*6*7; i++) {
4462                 VariantInit(&pData [i]);
4463                 pData [i].vt = VT_I4;
4464                 pData [i].lVal = i;
4465         }
4466         SafeArrayUnaccessData (pSA);
4467         *safearray = pSA;
4468         return hr;
4469 }
4470
4471 LIBTEST_API int STDCALL 
4472 mono_test_marshal_safearray_in_byval_1dim_empty (SAFEARRAY* safearray)
4473 {
4474         /* Check that array is one dimensional and empty */
4475
4476         UINT dim;
4477         long lbound, ubound;
4478         
4479         dim = SafeArrayGetDim (safearray);
4480         if (dim != 1)
4481                 return 1;
4482
4483         SafeArrayGetLBound (safearray, 1, &lbound);
4484         SafeArrayGetUBound (safearray, 1, &ubound);
4485
4486         if ((lbound > 0) || (ubound > 0))
4487                 return 1;
4488
4489         return 0;
4490 }
4491
4492 LIBTEST_API int STDCALL 
4493 mono_test_marshal_safearray_in_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4494 {
4495         /* Check that array is one dimensional containing integers from 1 to 10 */
4496
4497         UINT dim;
4498         long lbound, ubound;
4499         VARIANT *pData; 
4500         long i;
4501         int result=0;
4502
4503         dim = SafeArrayGetDim (safearray);
4504         if (dim != 1)
4505                 return 1;
4506
4507         SafeArrayGetLBound (safearray, 1, &lbound);
4508         SafeArrayGetUBound (safearray, 1, &ubound);
4509
4510         if ((lbound != 0) || (ubound != 9))
4511                 return 1;
4512
4513         SafeArrayAccessData (safearray, (void **)&pData);
4514         for (i= lbound; i <= ubound; i++) {
4515                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i + 1))
4516                         result = 1;
4517         }
4518         SafeArrayUnaccessData (safearray);
4519
4520         return result;
4521 }
4522
4523 LIBTEST_API int STDCALL 
4524 mono_test_marshal_safearray_in_byval_1dim_vt_mixed (SAFEARRAY* safearray)
4525 {
4526         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4527
4528         UINT dim;
4529         long lbound, ubound;
4530         VARIANT *pData; 
4531         long i;
4532         long indices [1];
4533         VARIANT element;
4534         int result=0;
4535
4536         VariantInit (&element);
4537
4538         dim = SafeArrayGetDim (safearray);
4539         if (dim != 1)
4540                 return 1;
4541
4542         SafeArrayGetLBound (safearray, 1, &lbound);
4543         SafeArrayGetUBound (safearray, 1, &ubound);
4544                 
4545         if ((lbound != 0) || (ubound != 12))
4546                 return 1;
4547
4548         SafeArrayAccessData (safearray, (void **)&pData);
4549         for (i= lbound; i <= ubound; i++) {
4550                 if ((i%2 == 0) && (pData [i].vt != VT_I4))
4551                         result = 1;
4552                 if ((i%2 == 1) && (pData [i].vt != VT_BSTR))
4553                         result = 1;
4554                 if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i))
4555                         result = 1;
4556         }
4557         SafeArrayUnaccessData (safearray);
4558
4559         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4560
4561         indices [0] = 0;
4562         element.vt = VT_I4;
4563         element.lVal = 333;
4564         SafeArrayPutElement (safearray, indices, &element);
4565         VariantClear (&element);
4566
4567         return result;
4568 }
4569
4570 LIBTEST_API int STDCALL 
4571 mono_test_marshal_safearray_in_byval_2dim_vt_i4 (SAFEARRAY* safearray)
4572 {
4573         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4574
4575         UINT dim;
4576         long lbound1, ubound1, lbound2, ubound2;
4577         long i, j, failed;
4578         long indices [2];
4579         VARIANT element;
4580
4581         VariantInit (&element);
4582
4583         dim = SafeArrayGetDim (safearray);
4584         if (dim != 2)
4585                 return 1;
4586
4587         SafeArrayGetLBound (safearray, 1, &lbound1);
4588         SafeArrayGetUBound (safearray, 1, &ubound1);
4589
4590         if ((lbound1 != 0) || (ubound1 != 1))
4591                 return 1;
4592
4593         SafeArrayGetLBound (safearray, 2, &lbound2);
4594         SafeArrayGetUBound (safearray, 2, &ubound2);
4595
4596         if ((lbound2 != 0) || (ubound2 != 3)) {
4597                 return 1;
4598         }
4599
4600         for (i= lbound1; i <= ubound1; i++) {
4601                 indices [0] = i;
4602                 for (j= lbound2; j <= ubound2; j++) {
4603                         indices [1] = j;
4604                         if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4605                                 return 1;
4606                         failed = ((element.vt != VT_I4) || (element.lVal != 10*(i+1)+(j+1)));
4607                         VariantClear (&element);
4608                         if (failed)
4609                                 return 1;
4610                 }
4611         }
4612
4613         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4614
4615         indices [0] = 0;
4616         indices [1] = 0;
4617         element.vt = VT_I4;
4618         element.lVal = 333;
4619         SafeArrayPutElement (safearray, indices, &element);
4620         VariantClear (&element);
4621
4622         return 0;
4623 }
4624
4625 LIBTEST_API int STDCALL 
4626 mono_test_marshal_safearray_in_byval_3dim_vt_bstr (SAFEARRAY* safearray)
4627 {
4628         /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */
4629
4630         UINT dim;
4631         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4632         long i, j, k, failed;
4633         long indices [3];
4634         VARIANT element;
4635
4636         VariantInit (&element);
4637
4638         dim = SafeArrayGetDim (safearray);
4639         if (dim != 3)
4640                 return 1;
4641
4642         SafeArrayGetLBound (safearray, 1, &lbound1);
4643         SafeArrayGetUBound (safearray, 1, &ubound1);
4644
4645         if ((lbound1 != 0) || (ubound1 != 1))
4646                 return 1;
4647
4648         SafeArrayGetLBound (safearray, 2, &lbound2);
4649         SafeArrayGetUBound (safearray, 2, &ubound2);
4650
4651         if ((lbound2 != 0) || (ubound2 != 1))
4652                 return 1;
4653
4654         SafeArrayGetLBound (safearray, 3, &lbound3);
4655         SafeArrayGetUBound (safearray, 3, &ubound3);
4656
4657         if ((lbound3 != 0) || (ubound3 != 2))
4658                 return 1;
4659
4660         for (i= lbound1; i <= ubound1; i++) {
4661                 indices [0] = i;
4662                 for (j= lbound2; j <= ubound2; j++) {
4663                         indices [1] = j;
4664                 for (k= lbound3; k <= ubound3; k++) {
4665                                 indices [2] = k;
4666                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4667                                         return 1;
4668                                 failed = ((element.vt != VT_BSTR) 
4669                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4670                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4671                                 VariantClear (&element);
4672                                 if (failed)
4673                                         return 1;
4674                         }
4675                 }
4676         }
4677
4678         /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */
4679
4680         indices [0] = 0;
4681         indices [1] = 0;
4682         indices [2] = 0;
4683         element.vt = VT_BSTR;
4684         element.bstrVal = SysAllocString(L"Should not be copied");
4685         SafeArrayPutElement (safearray, indices, &element);
4686         VariantClear (&element);
4687
4688         return 0;
4689 }
4690
4691 LIBTEST_API int STDCALL 
4692 mono_test_marshal_safearray_in_byref_3dim_vt_bstr (SAFEARRAY** safearray)
4693 {
4694         return mono_test_marshal_safearray_in_byval_3dim_vt_bstr (*safearray);
4695 }
4696
4697 LIBTEST_API int STDCALL 
4698 mono_test_marshal_safearray_in_out_byref_1dim_empty (SAFEARRAY** safearray)
4699 {
4700         /* Check that the input array is what is expected and change it so the caller can check */
4701         /* correct marshalling back to managed code                                             */
4702
4703         UINT dim;
4704         long lbound, ubound;
4705         SAFEARRAYBOUND dimensions [1];
4706         long i;
4707         wchar_t buffer [20];
4708         HRESULT hr = S_OK;
4709         long indices [1];
4710
4711         /* Check that in array is one dimensional and empty */
4712
4713         dim = SafeArrayGetDim (*safearray);
4714         if (dim != 1) {
4715                 return 1;
4716         }
4717
4718         SafeArrayGetLBound (*safearray, 1, &lbound);
4719         SafeArrayGetUBound (*safearray, 1, &ubound);
4720                 
4721         if ((lbound > 0) || (ubound > 0)) {
4722                 return 1;
4723         }
4724
4725         /* Re-dimension the array and return a one-dimensional array of 8 variants filled with "0" to "7" */
4726
4727         dimensions [0].lLbound = 0;
4728         dimensions [0].cElements = 8;
4729
4730         hr = SafeArrayRedim (*safearray, dimensions);
4731         if (hr != S_OK)
4732                 return 1;
4733
4734         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
4735                 VARIANT vOut;
4736                 VariantInit (&vOut);
4737                 vOut.vt = VT_BSTR;
4738                 _ltow (i,buffer,10);
4739                 vOut.bstrVal = SysAllocString (buffer);
4740                 indices [0] = i;
4741                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
4742                         VariantClear (&vOut);
4743                         SafeArrayDestroy (*safearray);
4744                         return hr;
4745                 }
4746                 VariantClear (&vOut);
4747         }
4748         return hr;
4749 }
4750
4751 LIBTEST_API int STDCALL 
4752 mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (SAFEARRAY** safearray)
4753 {
4754         /* Check that the input array is what is expected and change it so the caller can check */
4755         /* correct marshalling back to managed code                                             */
4756
4757         UINT dim;
4758         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4759         SAFEARRAYBOUND dimensions [1];
4760         long i, j, k, failed;
4761         wchar_t buffer [20];
4762         HRESULT hr = S_OK;
4763         long indices [3];
4764         VARIANT element;
4765
4766         VariantInit (&element);
4767
4768         /* Check that in array is three dimensional and contains the expected values */
4769
4770         dim = SafeArrayGetDim (*safearray);
4771         if (dim != 3)
4772                 return 1;
4773
4774         SafeArrayGetLBound (*safearray, 1, &lbound1);
4775         SafeArrayGetUBound (*safearray, 1, &ubound1);
4776
4777         if ((lbound1 != 0) || (ubound1 != 1))
4778                 return 1;
4779
4780         SafeArrayGetLBound (*safearray, 2, &lbound2);
4781         SafeArrayGetUBound (*safearray, 2, &ubound2);
4782
4783         if ((lbound2 != 0) || (ubound2 != 1))
4784                 return 1;
4785
4786         SafeArrayGetLBound (*safearray, 3, &lbound3);
4787         SafeArrayGetUBound (*safearray, 3, &ubound3);
4788
4789         if ((lbound3 != 0) || (ubound3 != 2))
4790                 return 1;
4791
4792         for (i= lbound1; i <= ubound1; i++) {
4793                 indices [0] = i;
4794                 for (j= lbound2; j <= ubound2; j++) {
4795                         indices [1] = j;
4796                         for (k= lbound3; k <= ubound3; k++) {
4797                                 indices [2] = k;
4798                                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
4799                                         return 1;
4800                                 failed = ((element.vt != VT_BSTR) 
4801                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4802                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4803                                 VariantClear (&element);
4804                                 if (failed)
4805                                         return 1;
4806                         }
4807                 }
4808         }
4809
4810         hr = SafeArrayDestroy (*safearray);
4811         if (hr != S_OK)
4812                 return 1;
4813
4814         /* Return a new one-dimensional array of 8 variants filled with "0" to "7" */
4815
4816         dimensions [0].lLbound = 0;
4817         dimensions [0].cElements = 8;
4818
4819         *safearray = SafeArrayCreate (VT_VARIANT, 1, dimensions);
4820
4821         for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) {
4822                 VARIANT vOut;
4823                 VariantInit (&vOut);
4824                 vOut.vt = VT_BSTR;
4825                 _ltow (i,buffer,10);
4826                 vOut.bstrVal = SysAllocString (buffer);
4827                 indices [0] = i;
4828                 if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) {
4829                         VariantClear (&vOut);
4830                         SafeArrayDestroy (*safearray);
4831                         return hr;
4832                 }
4833                 VariantClear (&vOut);
4834         }
4835         return hr;
4836 }
4837
4838 LIBTEST_API int STDCALL 
4839 mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (SAFEARRAY** safearray)
4840 {
4841         /* Check that the input array is what is expected and change it so the caller can check */
4842         /* correct marshalling back to managed code                                             */
4843
4844         UINT dim;
4845         long lbound1, ubound1;
4846         long i, failed;
4847         HRESULT hr = S_OK;
4848         long indices [1];
4849         VARIANT element;
4850         
4851         VariantInit (&element);
4852
4853         /* Check that in array is one dimensional and contains the expected value */
4854
4855         dim = SafeArrayGetDim (*safearray);
4856         if (dim != 1)
4857                 return 1;
4858
4859         SafeArrayGetLBound (*safearray, 1, &lbound1);
4860         SafeArrayGetUBound (*safearray, 1, &ubound1);
4861
4862         ubound1 = 1;
4863         if ((lbound1 != 0) || (ubound1 != 1))
4864                 return 1;
4865         ubound1 = 0;
4866
4867         for (i= lbound1; i <= ubound1; i++) {
4868                 indices [0] = i;
4869                 if (SafeArrayGetElement (*safearray, indices, &element) != S_OK)
4870                         return 1;
4871                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
4872                 VariantClear (&element);
4873                 if (failed)
4874                         return 1;
4875         }
4876
4877         /* Change one of the elements of the array to verify that [out] parameter is marshalled back to the managed side */
4878
4879         indices [0] = 0;
4880         element.vt = VT_I4;
4881         element.lVal = -1;
4882         SafeArrayPutElement (*safearray, indices, &element);
4883         VariantClear (&element);
4884
4885         return hr;
4886 }
4887
4888 LIBTEST_API int STDCALL 
4889 mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (SAFEARRAY* safearray)
4890 {
4891         /* Check that the input array is what is expected and change it so the caller can check */
4892         /* correct marshalling back to managed code                                             */
4893
4894         UINT dim;
4895         long lbound1, ubound1;
4896         SAFEARRAYBOUND dimensions [1];
4897         long i, failed;
4898         HRESULT hr = S_OK;
4899         long indices [1];
4900         VARIANT element;
4901
4902         VariantInit (&element);
4903
4904         /* Check that in array is one dimensional and contains the expected value */
4905
4906         dim = SafeArrayGetDim (safearray);
4907         if (dim != 1)
4908                 return 1;
4909
4910         SafeArrayGetLBound (safearray, 1, &lbound1);
4911         SafeArrayGetUBound (safearray, 1, &ubound1);
4912                 
4913         if ((lbound1 != 0) || (ubound1 != 0))
4914                 return 1;
4915
4916         for (i= lbound1; i <= ubound1; i++) {
4917                 indices [0] = i;
4918                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4919                         return 1;
4920                 failed = (element.vt != VT_I4) || (element.lVal != i+1);
4921                 VariantClear (&element);
4922                 if (failed)
4923                         return 1;
4924         }
4925
4926         /* Change the array to verify how [out] parameter is marshalled back to the managed side */
4927
4928         /* Redimension the array */
4929         dimensions [0].lLbound = lbound1;
4930         dimensions [0].cElements = 2;
4931         hr = SafeArrayRedim(safearray, dimensions);
4932
4933         indices [0] = 0;
4934         element.vt = VT_I4;
4935         element.lVal = 12345;
4936         SafeArrayPutElement (safearray, indices, &element);
4937         VariantClear (&element);
4938
4939         indices [0] = 1;
4940         element.vt = VT_I4;
4941         element.lVal = -12345;
4942         SafeArrayPutElement (safearray, indices, &element);
4943         VariantClear (&element);
4944
4945         return hr;
4946 }
4947
4948 LIBTEST_API int STDCALL 
4949 mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (SAFEARRAY* safearray)
4950 {
4951         /* Check that the input array is what is expected and change it so the caller can check */
4952         /* correct marshalling back to managed code                                             */
4953
4954         UINT dim;
4955         long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3;
4956         long i, j, k, failed;
4957         HRESULT hr = S_OK;
4958         long indices [3];
4959         VARIANT element;
4960
4961         VariantInit (&element);
4962
4963         /* Check that in array is three dimensional and contains the expected values */
4964
4965         dim = SafeArrayGetDim (safearray);
4966         if (dim != 3)
4967                 return 1;
4968
4969         SafeArrayGetLBound (safearray, 1, &lbound1);
4970         SafeArrayGetUBound (safearray, 1, &ubound1);
4971
4972         if ((lbound1 != 0) || (ubound1 != 1))
4973                 return 1;
4974
4975         SafeArrayGetLBound (safearray, 2, &lbound2);
4976         SafeArrayGetUBound (safearray, 2, &ubound2);
4977
4978         if ((lbound2 != 0) || (ubound2 != 1))
4979                 return 1;
4980
4981         SafeArrayGetLBound (safearray, 3, &lbound3);
4982         SafeArrayGetUBound (safearray, 3, &ubound3);
4983
4984         if ((lbound3 != 0) || (ubound3 != 2))
4985                 return 1;
4986
4987         for (i= lbound1; i <= ubound1; i++) {
4988                 indices [0] = i;
4989                 for (j= lbound2; j <= ubound2; j++) {
4990                         indices [1] = j;
4991                         for (k= lbound3; k <= ubound3; k++) {
4992                                 indices [2] = k;
4993                                 if (SafeArrayGetElement (safearray, indices, &element) != S_OK)
4994                                         return 1;
4995                                 failed = ((element.vt != VT_BSTR) 
4996                                         || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) 
4997                                         || (element.lVal != 100*(i+1)+10*(j+1)+(k+1)));
4998                                 VariantClear (&element);
4999                                 if (failed)
5000                                         return 1;
5001                         }
5002                 }
5003         }
5004
5005         /* Change the elements of the array to verify that [out] parameter is marshalled back to the managed side */
5006
5007         indices [0] = 1;
5008         indices [1] = 1;
5009         indices [2] = 2;
5010         element.vt = VT_I4;
5011         element.lVal = 333;
5012         SafeArrayPutElement (safearray, indices, &element);
5013         VariantClear (&element);
5014
5015         indices [0] = 1;
5016         indices [1] = 1;
5017         indices [2] = 1;
5018         element.vt = VT_I4;
5019         element.lVal = 111;
5020         SafeArrayPutElement (safearray, indices, &element);
5021         VariantClear (&element);
5022
5023         indices [0] = 0;
5024         indices [1] = 1;
5025         indices [2] = 0;
5026         element.vt = VT_BSTR;
5027         element.bstrVal = marshal_bstr_alloc("ABCDEFG");
5028         SafeArrayPutElement (safearray, indices, &element);
5029         VariantClear (&element);
5030
5031         return hr;
5032 }
5033
5034 LIBTEST_API int STDCALL 
5035 mono_test_marshal_safearray_mixed(
5036                 SAFEARRAY  *safearray1,
5037                 SAFEARRAY **safearray2,
5038                 SAFEARRAY  *safearray3,
5039                 SAFEARRAY **safearray4
5040                 )
5041 {
5042         HRESULT hr = S_OK;
5043
5044         /* Initialize out parameters */
5045         *safearray2 = NULL;
5046
5047         /* array1: Check that in array is one dimensional and contains the expected value */
5048         hr = mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (safearray1);
5049
5050         /* array2: Fill in with some values to check on the managed side */
5051         if (hr == S_OK)
5052                 hr = mono_test_marshal_safearray_out_1dim_vt_bstr (safearray2);
5053
5054         /* array3: Check that in array is one dimensional and contains the expected value */
5055         if (hr == S_OK)
5056                 hr = mono_test_marshal_safearray_in_byval_1dim_vt_mixed(safearray3);
5057
5058         /* array4: Check input values and fill in with some values to check on the managed side */
5059         if (hr == S_OK)
5060                 hr = mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr(safearray4);
5061
5062         return hr;
5063 }
5064
5065 #endif
5066
5067 static int call_managed_res;
5068
5069 static void
5070 call_managed (gpointer arg)
5071 {
5072         SimpleDelegate del = arg;
5073
5074         call_managed_res = del (42);
5075 }
5076
5077 LIBTEST_API int STDCALL 
5078 mono_test_marshal_thread_attach (SimpleDelegate del)
5079 {
5080 #ifdef WIN32
5081         return 43;
5082 #else
5083         int res;
5084         pthread_t t;
5085
5086         res = pthread_create (&t, NULL, (gpointer)call_managed, del);
5087         g_assert (res == 0);
5088         pthread_join (t, NULL);
5089
5090         return call_managed_res;
5091 #endif
5092 }
5093
5094 typedef int (STDCALL *Callback) (void);
5095
5096 static Callback callback;
5097
5098 LIBTEST_API void STDCALL 
5099 mono_test_marshal_set_callback (Callback cb)
5100 {
5101         callback = cb;
5102 }
5103
5104 LIBTEST_API int STDCALL 
5105 mono_test_marshal_call_callback (void)
5106 {
5107         return callback ();
5108 }
5109
5110 LIBTEST_API int STDCALL
5111 mono_test_marshal_lpstr (char *str)
5112 {
5113         return strcmp ("ABC", str);
5114 }
5115
5116 LIBTEST_API int STDCALL
5117 mono_test_marshal_lpwstr (gunichar2 *str)
5118 {
5119         char *s;
5120         int res;
5121
5122         s = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
5123         res = strcmp ("ABC", s);
5124         g_free (s);
5125
5126         return res;
5127 }
5128
5129 LIBTEST_API char* STDCALL
5130 mono_test_marshal_return_lpstr (void)
5131 {
5132         char *res = marshal_alloc (4);
5133         strcpy (res, "XYZ");
5134         return res;
5135 }
5136
5137
5138 LIBTEST_API gunichar2* STDCALL
5139 mono_test_marshal_return_lpwstr (void)
5140 {
5141         gunichar2 *res = marshal_alloc (8);
5142         gunichar2* tmp = g_utf8_to_utf16 ("XYZ", -1, NULL, NULL, NULL);
5143
5144         memcpy (res, tmp, 8);
5145         g_free (tmp);
5146
5147         return res;
5148 }