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