2007-10-04 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / tests / libtest.c
index 174867080f34a3949bf267a4a43064672c87308e..731382d0b0a01aa26e5e61c9ddcfe7b2451dbe60 100644 (file)
@@ -5,6 +5,11 @@
 #include <errno.h>
 #include <time.h>
 
+#ifdef WIN32
+#include <windows.h>
+#include "initguid.h"
+#endif
+
 #ifdef WIN32
 #define STDCALL __stdcall
 #else
@@ -271,6 +276,18 @@ mono_test_marshal_inout_array (int *a1)
        return sum;
 }
 
+STDCALL int 
+mono_test_marshal_out_array (int *a1)
+{
+       int i;
+
+       for (i = 0; i < 50; i++) {
+               a1 [i] = i;
+       }
+       
+       return 0;
+}
+
 STDCALL int 
 mono_test_marshal_inout_nonblittable_array (gunichar2 *a1)
 {
@@ -291,6 +308,11 @@ typedef struct {
        gunichar2 *d2;
 } simplestruct;
 
+typedef struct {
+       double x;
+       double y;
+} point;
+
 STDCALL simplestruct
 mono_test_return_vtype (int i)
 {
@@ -339,7 +361,7 @@ mono_test_ref_vtype (int a, simplestruct *ss, int b, RefVTypeDelegate func)
                ss->b = 0;
                ss->c = 1;
                ss->d = "TEST2";
-       
+
                return func (a, ss, b);
        }
 
@@ -367,10 +389,16 @@ typedef struct {
        SimpleDelegate func, func2;
 } DelegateStruct;
 
-STDCALL int 
+STDCALL DelegateStruct
 mono_test_marshal_delegate_struct (DelegateStruct ds)
 {
-       return ds.func (ds.a) + ds.func2 (ds.a);
+       DelegateStruct res;
+
+       res.a = ds.func (ds.a) + ds.func2 (ds.a);
+       res.func = ds.func;
+       res.func2 = ds.func2;
+
+       return res;
 }
 
 STDCALL int 
@@ -383,6 +411,21 @@ mono_test_marshal_struct (simplestruct ss)
        return 1;
 }
 
+STDCALL int
+mono_test_marshal_byref_struct (simplestruct *ss, int a, int b, int c, char *d)
+{
+       gboolean res = (ss->a == a && ss->b == b && ss->c == c && strcmp (ss->d, d) == 0);
+
+       marshal_free (ss->d);
+
+       ss->a = !ss->a;
+       ss->b = !ss->b;
+       ss->c = !ss->c;
+       ss->d = g_strdup ("DEF");
+
+       return res ? 0 : 1;
+}
+
 typedef struct {
        int a;
        int b;
@@ -419,6 +462,25 @@ mono_test_marshal_struct2_2 (int i, int j, int k, simplestruct2 ss)
        return 1;
 }
 
+STDCALL int 
+mono_test_marshal_lpstruct (simplestruct *ss)
+{
+       if (ss->a == 0 && ss->b == 1 && ss->c == 0 &&
+           !strcmp (ss->d, "TEST"))
+               return 0;
+
+       return 1;
+}
+
+STDCALL int 
+mono_test_marshal_lpstruct_blittable (point *p)
+{
+       if (p->x == 1.0 && p->y == 2.0)
+               return 0;
+       else
+               return 1;
+}
+
 STDCALL int
 mono_test_marshal_struct_array (simplestruct2 *ss)
 {
@@ -493,6 +555,7 @@ get_sp (void)
        int i;
        void *p;
 
+       /* Yes, this is correct, we are only trying to determine the value of the stack here */
        p = &i;
        return p;
 }
@@ -672,6 +735,29 @@ mono_test_marshal_delegate7 (SimpleDelegate7 delegate)
        return 0;
 }
 
+typedef int (STDCALL *InOutByvalClassDelegate) (simplestruct *ss);
+
+STDCALL int
+mono_test_marshal_inout_byval_class_delegate (InOutByvalClassDelegate delegate)
+{
+       int res;
+       simplestruct ss;
+
+       ss.a = FALSE;
+       ss.b = TRUE;
+       ss.c = FALSE;
+       ss.d = g_strdup_printf ("%s", "FOO");
+
+       res = delegate (&ss);
+       if (res != 0)
+               return 1;
+
+       if (!(ss.a && !ss.b && ss.c && !strcmp (ss.d, "RES")))
+               return 2;
+
+       return 0;
+}
+
 typedef int (STDCALL *SimpleDelegate8) (gunichar2 *s);
 
 STDCALL int
@@ -736,6 +822,17 @@ mono_test_marshal_stringbuilder (char *s, int n)
        if (strcmp (s, "ABCD") != 0)
                return 1;
        strncpy(s, m, n);
+       s [n] = '\0';
+       return 0;
+}
+
+STDCALL int 
+mono_test_marshal_stringbuilder_default (char *s, int n)
+{
+       const char m[] = "This is my message.  Isn't it nice?";
+
+       strncpy(s, m, n);
+       s [n] = '\0';
        return 0;
 }
 
@@ -749,8 +846,8 @@ mono_test_marshal_stringbuilder_unicode (gunichar2 *s, int n)
        s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
        
        len = (len * 2) + 2;
-       if (len > n)
-               len = n;
+       if (len > (n * 2))
+               len = n * 2;
        memcpy (s, s2, len);
 
        g_free (s2);
@@ -851,9 +948,14 @@ mono_test_empty_struct (int a, EmptyStruct es, int b)
 {
        // printf ("mono_test_empty_struct %d %d\n", a, b);
 
+       // Intel icc on ia64 passes 'es' in 2 registers
+#if defined(__ia64) && defined(__INTEL_COMPILER)
+       return 0;
+#else
        if (a == 1 && b == 2)
                return 0;
        return 1;
+#endif
 }
 
 typedef struct {
@@ -885,6 +987,35 @@ mono_test_byvalstr_check (ByValStrStruct* data, char* correctString)
        return (ret != 0);
 }
 
+typedef struct {
+       guint16 a[4];
+       int  flag;
+} ByValStrStruct_Unicode;
+
+STDCALL int
+mono_test_byvalstr_check_unicode (ByValStrStruct_Unicode *ref, int test)
+{
+       if (ref->flag != 0x1234abcd){
+               printf ("overwritten data");
+               return 1;
+       }
+           
+       if (test == 1 || test == 3){
+               if (ref->a [0] != '1' ||
+                   ref->a [1] != '2'   ||
+                   ref->a [2] != '3')
+                       return 1;
+               return 0;
+       }
+       if (test == 2){
+               if (ref->a [0] != '1' ||
+                   ref->a [1] != '2')
+                       return 1;
+               return 0;
+       }
+       return 10;
+}
+
 STDCALL int
 NameManglingAnsi (char *data)
 {
@@ -1050,32 +1181,38 @@ string_marshal_test3 (char *str)
 typedef struct {
        int a;
        int b;
-} VectorList;
+} BlittableClass;
 
-STDCALL VectorList
-TestVectorList (VectorList *vl)
+STDCALL BlittableClass
+TestBlittableClass (BlittableClass *vl)
 {
-       VectorList *res;
+       BlittableClass *res;
 
-       // printf ("TestVectorList %d %d\n", vl->a, vl->b);
+       // printf ("TestBlittableClass %d %d\n", vl->a, vl->b);
 
-       vl->a++;
-       vl->b++;
+       if (vl) {
+               vl->a++;
+               vl->b++;
 
-       res = g_new0 (VectorList, 1);
-       memcpy (res, vl, sizeof (VectorList));
+               res = g_new0 (BlittableClass, 1);
+               memcpy (res, vl, sizeof (BlittableClass));
+       } else {
+               res = g_new0 (BlittableClass, 1);
+               res->a = 42;
+               res->b = 43;
+       }
 
        return res;
 }
 
-typedef struct _OSVERSIONINFO
+typedef struct OSVERSIONINFO_STRUCT
 { 
        int a; 
        int b; 
-} OSVERSIONINFO
+} OSVERSIONINFO_STRUCT;
 
 STDCALL int 
-GetVersionEx (OSVERSIONINFO *osvi)
+MyGetVersionEx (OSVERSIONINFO_STRUCT *osvi)
 {
 
        // printf ("GOT %d %d\n", osvi->a, osvi->b);
@@ -1087,7 +1224,7 @@ GetVersionEx (OSVERSIONINFO *osvi)
 }
 
 STDCALL int 
-BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSIONINFO *osvi)
+BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSIONINFO_STRUCT *osvi)
 {
 
        // printf ("GOT %d %d\n", osvi->a, osvi->b);
@@ -1098,11 +1235,6 @@ BugGetVersionEx (int a, int b, int c, int d, int e, int f, int g, int h, OSVERSI
        return osvi->a + osvi->b;
 }
 
-typedef struct {
-       double x;
-       double y;
-} point;
-
 STDCALL int
 mono_test_marshal_point (point pt)
 {
@@ -1184,10 +1316,6 @@ marshal_test_bool_struct(struct BoolStruct *s)
     return res;
 }
 
-#ifdef WIN32
-extern __declspec(dllimport) __stdcall void SetLastError(int x);
-#endif
-
 STDCALL void
 mono_test_last_error (int err)
 {
@@ -1237,6 +1365,53 @@ mono_test_asany (void *ptr, int what)
        return 1;
 }
 
+typedef struct
+{
+       int i;
+       int j;
+       int k;
+       char *s;
+} AsAnyStruct;
+
+STDCALL int
+mono_test_marshal_asany_in (void* ptr)
+{
+       AsAnyStruct* asAny = ptr;
+       int res = asAny->i + asAny->j + asAny->k;
+
+       return res;
+}
+
+STDCALL int
+mono_test_marshal_asany_inout (void* ptr)
+{
+       AsAnyStruct* asAny = ptr;
+       int res = asAny->i + asAny->j + asAny->k;
+
+       marshal_free (asAny->s);
+
+       asAny->i = 10;
+       asAny->j = 20;
+       asAny->k = 30;
+       asAny->s = 0;
+
+       return res;
+}
+
+STDCALL int
+mono_test_marshal_asany_out (void* ptr)
+{
+       AsAnyStruct* asAny = ptr;
+       int res = asAny->i + asAny->j + asAny->k;
+
+       asAny->i = 10;
+       asAny->j = 20;
+       asAny->k = 30;
+       asAny->s = 0;
+
+       return res;
+}
+
 /*
  * AMD64 marshalling tests.
  */
@@ -1298,6 +1473,35 @@ mono_test_marshal_amd64_pass_return_struct4 (amd64_struct4 s)
        return s;
 }
 
+/*
+ * IA64 marshalling tests.
+ */
+typedef struct test_struct5 {
+       float d1, d2;
+} test_struct5;
+
+STDCALL test_struct5
+mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, test_struct5 s, double d3, double d4)
+{
+       s.d1 += d1 + d2;
+       s.d2 += d3 + d4;
+
+       return s;
+}
+
+typedef struct test_struct6 {
+       double d1, d2;
+} test_struct6;
+
+STDCALL test_struct6
+mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, test_struct6 s, double d3, double d4)
+{
+       s.d1 += d1 + d2;
+       s.d2 += d3 + d4;
+
+       return s;
+}
+
 static guint32 custom_res [2];
 
 STDCALL void*
@@ -1310,6 +1514,56 @@ mono_test_marshal_pass_return_custom (int i, guint32 *ptr, int j)
        return &custom_res;
 }
 
+STDCALL int
+mono_test_marshal_pass_out_custom (int i, guint32 **ptr, int j)
+{
+       custom_res [0] = 0;
+       custom_res [1] = i + j + 10;
+
+       *ptr = custom_res;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_pass_inout_custom (int i, guint32 *ptr, int j)
+{
+       ptr [0] = 0;
+       ptr [1] = i + ptr [1] + j;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_pass_out_byval_custom (int i, guint32 *ptr, int j)
+{
+       return ptr == NULL ? 0 : 1;
+}
+
+STDCALL int
+mono_test_marshal_pass_byref_custom (int i, guint32 **ptr, int j)
+{
+       (*ptr)[1] += i + j;
+
+       return 0;
+}
+
+STDCALL void*
+mono_test_marshal_pass_return_custom2 (int i, guint32 *ptr, int j)
+{
+       g_assert_not_reached ();
+
+       return NULL;
+}
+
+STDCALL void*
+mono_test_marshal_pass_return_custom_null (int i, guint32 *ptr, int j)
+{
+       g_assert (ptr == NULL);
+
+       return NULL;
+}
+
 typedef void *(STDCALL *PassReturnPtrDelegate) (void *ptr);
 
 STDCALL int
@@ -1335,6 +1589,29 @@ mono_test_marshal_pass_return_custom_in_delegate (PassReturnPtrDelegate del)
        return res;
 }
 
+STDCALL int
+mono_test_marshal_pass_return_custom_null_in_delegate (PassReturnPtrDelegate del)
+{
+       void *ptr = del (NULL);
+
+       return (ptr == NULL) ? 15 : 0;
+}
+
+typedef void (STDCALL *CustomOutParamDelegate) (void **pptr);
+
+STDCALL int
+mono_test_marshal_custom_out_param_delegate (CustomOutParamDelegate del)
+{
+       void* pptr = del;
+
+       del (&pptr);
+
+       if(pptr != NULL)
+               return 1;
+
+       return 0;
+}
+
 typedef int (STDCALL *ReturnEnumDelegate) (int e);
 
 STDCALL int
@@ -1614,3 +1891,937 @@ mono_test_marshal_array_delegate (void *arr, int len, ArrayDelegate del)
        return del (len, NULL, arr);
 }
 
+STDCALL int
+mono_test_marshal_out_array_delegate (int *arr, int len, ArrayDelegate del)
+{
+       del (len, NULL, arr);
+
+       if ((arr [0] != 1) || (arr [1] != 2))
+               return 1;
+       else
+               return 0;
+}
+
+typedef gunichar2* (STDCALL *UnicodeStringDelegate) (gunichar2 *message);
+
+STDCALL int
+mono_test_marshal_return_unicode_string_delegate (UnicodeStringDelegate del)
+{
+       const char m[] = "abcdef";
+       gunichar2 *s2, *res;
+       glong len;
+
+       s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL);
+
+       res = del (s2);
+
+       marshal_free (res);
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_out_string_array_delegate (char **arr, int len, ArrayDelegate del)
+{
+       del (len, NULL, arr);
+
+       if (!strcmp (arr [0], "ABC") && !strcmp (arr [1], "DEF"))
+               return 0;
+       else
+               return 1;
+}
+
+typedef int (*CdeclDelegate) (int i, int j);
+
+STDCALL int
+mono_test_marshal_cdecl_delegate (CdeclDelegate del)
+{
+       int i;
+
+       for (i = 0; i < 1000; ++i)
+               del (1, 2);
+
+       return 0;
+}
+
+typedef char** (*ReturnStringArrayDelegate) (int i);
+
+STDCALL int
+mono_test_marshal_return_string_array_delegate (ReturnStringArrayDelegate d)
+{
+       char **arr = d (2);
+       int res;
+
+       if (arr == NULL)
+               return 3;
+
+       if (strcmp (arr [0], "ABC") || strcmp (arr [1], "DEF"))
+               res = 1;
+       else
+               res = 0;
+
+       marshal_free (arr);
+
+       return res;
+}
+
+STDCALL int
+add_delegate (int i, int j)
+{
+       return i + j;
+}
+
+STDCALL gpointer
+mono_test_marshal_return_fnptr (void)
+{
+       return &add_delegate;
+}
+
+STDCALL int
+mono_xr (int code)
+{
+       printf ("codigo %x\n", code);
+       return code + 1234;
+}
+
+typedef struct {
+       int handle;
+} HandleRef;
+
+STDCALL HandleRef
+mono_xr_as_handle (int code)
+{
+       HandleRef ref;
+
+       return ref;
+}
+typedef struct {
+       int   a;
+       void *handle1;
+       void *handle2;
+       int   b;
+} HandleStructs;
+
+STDCALL int
+mono_safe_handle_struct_ref (HandleStructs *x)
+{
+       printf ("Dingus Ref! \n");
+       printf ("Values: %d %d %d %d\n", x->a, x->b, x->handle1, x->handle2);
+       if (x->a != 1234)
+               return 1;
+       if (x->b != 8743)
+               return 2;
+
+       if (x->handle1 != (void*) 0x7080feed)
+               return 3;
+
+       if (x->handle2 != (void*) 0x1234abcd)
+               return 4;
+
+       return 0xf00d;
+}
+
+STDCALL int
+mono_safe_handle_struct (HandleStructs x)
+{
+       printf ("Dingus Standard! \n");
+       printf ("Values: %d %d %d %d\n", x.a, x.b, x.handle1, x.handle2);
+       if (x.a != 1234)
+               return 1;
+       if (x.b != 8743)
+               return 2;
+
+       if (x.handle1 != (void*) 0x7080feed)
+               return 3;
+
+       if (x.handle2 != (void*) 0x1234abcd)
+               return 4;
+       
+       return 0xf00f;
+}
+
+typedef struct {
+       void *a;
+} TrivialHandle;
+
+STDCALL int
+mono_safe_handle_struct_simple (TrivialHandle x)
+{
+       printf ("The value is %d\n", x.a);
+       return ((int)x.a) * 2;
+}
+
+STDCALL int
+mono_safe_handle_return ()
+{
+       return 0x1000f00d;
+}
+
+STDCALL void
+mono_safe_handle_ref (void **handle)
+{
+       if (*handle != 0){
+               *handle = (void *) 0xbad;
+               return;
+       }
+
+       *handle = (void *) 0x800d;
+}
+/*
+ * COM INTEROP TESTS
+ */
+
+#ifdef WIN32
+
+STDCALL int
+mono_test_marshal_bstr_in(BSTR bstr)
+{
+       if (!wcscmp(bstr, L"mono_test_marshal_bstr_in"))
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_bstr_out(BSTR* bstr)
+{
+       *bstr = SysAllocString(L"mono_test_marshal_bstr_out");
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_bstr_in_null(BSTR bstr)
+{
+       if (!bstr)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_bstr_out_null(BSTR* bstr)
+{
+       *bstr = NULL;
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_sbyte(VARIANT variant)
+{
+       if (variant.vt == VT_I1 && variant.cVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_byte(VARIANT variant)
+{
+       if (variant.vt == VT_UI1 && variant.bVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_short(VARIANT variant)
+{
+       if (variant.vt == VT_I2 && variant.iVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ushort(VARIANT variant)
+{
+       if (variant.vt == VT_UI2 && variant.uiVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_int(VARIANT variant)
+{
+       if (variant.vt == VT_I4 && variant.lVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_uint(VARIANT variant)
+{
+       if (variant.vt == VT_UI4 && variant.ulVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_long(VARIANT variant)
+{
+       if (variant.vt == VT_I8 && variant.llVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ulong(VARIANT variant)
+{
+       if (variant.vt == VT_UI8 && variant.ullVal == 314)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_float(VARIANT variant)
+{
+       if (variant.vt == VT_R4 && (variant.fltVal - 3.14)/3.14 < .001)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_double(VARIANT variant)
+{
+       if (variant.vt == VT_R8 && (variant.dblVal - 3.14)/3.14 < .001)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bstr(VARIANT variant)
+{
+       if (variant.vt == VT_BSTR && !wcscmp(variant.bstrVal, L"PI"))
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_true (VARIANT variant)
+{
+       if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_TRUE)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_false (VARIANT variant)
+{
+       if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_FALSE)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_sbyte(VARIANT* variant)
+{
+       variant->vt = VT_I1;
+       variant->cVal = 100;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_byte(VARIANT* variant)
+{      
+       variant->vt = VT_UI1;
+       variant->bVal = 100;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_short(VARIANT* variant)
+{
+       variant->vt = VT_I2;
+       variant->iVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ushort(VARIANT* variant)
+{
+       variant->vt = VT_UI2;
+       variant->uiVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_int(VARIANT* variant)
+{
+       variant->vt = VT_I4;
+       variant->lVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_uint(VARIANT* variant)
+{
+       variant->vt = VT_UI4;
+       variant->ulVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_long(VARIANT* variant)
+{
+       variant->vt = VT_I8;
+       variant->llVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ulong(VARIANT* variant)
+{
+       variant->vt = VT_UI8;
+       variant->ullVal = 314;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_float(VARIANT* variant)
+{
+       variant->vt = VT_R4;
+       variant->fltVal = 3.14;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_double(VARIANT* variant)
+{
+       variant->vt = VT_R8;
+       variant->dblVal = 3.14;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bstr(VARIANT* variant)
+{
+       variant->vt = VT_BSTR;
+       variant->bstrVal = SysAllocString(L"PI");
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_true (VARIANT* variant)
+{
+       variant->vt = VT_BOOL;
+       variant->boolVal = VARIANT_TRUE;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_false (VARIANT* variant)
+{
+       variant->vt = VT_BOOL;
+       variant->boolVal = VARIANT_FALSE;
+
+       return 0;
+}
+
+typedef int (STDCALL *VarFunc) (int vt, VARIANT variant);
+typedef int (STDCALL *VarRefFunc) (int vt, VARIANT* variant);
+
+STDCALL int
+mono_test_marshal_variant_in_sbyte_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_I1;
+       vt.cVal = -100;
+       return func (VT_I1, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_byte_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_UI1;
+       vt.bVal = 100;
+       return func (VT_UI1, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_short_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_I2;
+       vt.iVal = -100;
+       return func (VT_I2, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ushort_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_UI2;
+       vt.uiVal = 100;
+       return func (VT_UI2, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_int_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_I4;
+       vt.lVal = -100;
+       return func (VT_I4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_uint_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_UI4;
+       vt.ulVal = 100;
+       return func (VT_UI4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_long_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_I8;
+       vt.llVal = -100;
+       return func (VT_I8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ulong_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_UI8;
+       vt.ullVal = 100;
+       return func (VT_UI8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_float_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_R4;
+       vt.fltVal = 3.14;
+       return func (VT_R4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_double_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_R8;
+       vt.dblVal = 3.14;
+       return func (VT_R8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_BSTR;
+       vt.bstrVal = SysAllocString(L"PI");
+       return func (VT_BSTR, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_true_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_BOOL;
+       vt.boolVal = VARIANT_TRUE;
+       return func (VT_BOOL, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_false_unmanaged(VarFunc func)
+{
+       VARIANT vt;
+       vt.vt = VT_BOOL;
+       vt.boolVal = VARIANT_FALSE;
+       return func (VT_BOOL, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_out_sbyte_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_I1, &vt);
+       if (vt.vt == VT_I1 && vt.cVal == -100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_byte_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_UI1, &vt);
+       if (vt.vt == VT_UI1 && vt.bVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_short_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_I2, &vt);
+       if (vt.vt == VT_I2 && vt.iVal == -100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ushort_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_UI2, &vt);
+       if (vt.vt == VT_UI2 && vt.uiVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_int_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_I4, &vt);
+       if (vt.vt == VT_I4 && vt.lVal == -100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_uint_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_UI4, &vt);
+       if (vt.vt == VT_UI4 && vt.ulVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_long_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_I8, &vt);
+       if (vt.vt == VT_I8 && vt.llVal == -100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ulong_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_UI8, &vt);
+       if (vt.vt == VT_UI8 && vt.ullVal == 100)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_float_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_R4, &vt);
+       if (vt.vt == VT_R4 && fabs (vt.fltVal - 3.14f) < 1e-10)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_double_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_R8, &vt);
+       if (vt.vt == VT_R8 && fabs (vt.dblVal - 3.14) < 1e-10)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_BSTR, &vt);
+       if (vt.vt == VT_BSTR && !wcscmp(vt.bstrVal, L"PI"))
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_true_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_BOOL, &vt);
+       if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
+               return 0;
+       return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
+{
+       VARIANT vt;
+       VariantInit (&vt);
+       func (VT_BOOL, &vt);
+       if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
+               return 0;
+       return 1;
+}
+
+typedef struct MonoComObject MonoComObject;
+
+typedef struct
+{
+       int (STDCALL *QueryInterface)(MonoComObject* pUnk, gpointer riid, gpointer* ppv);
+       int (STDCALL *AddRef)(MonoComObject* pUnk);
+       int (STDCALL *Release)(MonoComObject* pUnk);
+       int (STDCALL *get_ITest)(MonoComObject* pUnk, MonoComObject* *ppUnk);
+       int (STDCALL *SByteIn)(MonoComObject* pUnk, char a);
+       int (STDCALL *ByteIn)(MonoComObject* pUnk, unsigned char a);
+       int (STDCALL *ShortIn)(MonoComObject* pUnk, short a);
+       int (STDCALL *UShortIn)(MonoComObject* pUnk, unsigned short a);
+       int (STDCALL *IntIn)(MonoComObject* pUnk, int a);
+       int (STDCALL *UIntIn)(MonoComObject* pUnk, unsigned int a);
+       int (STDCALL *LongIn)(MonoComObject* pUnk, LONGLONG a);
+       int (STDCALL *ULongIn)(MonoComObject* pUnk, ULONGLONG a);
+       int (STDCALL *FloatIn)(MonoComObject* pUnk, float a);
+       int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a);
+       int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
+       int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
+} MonoIUnknown;
+
+struct MonoComObject
+{
+       MonoIUnknown* vtbl;
+       int m_ref;
+};
+
+DEFINE_GUID(IID_ITest, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+DEFINE_GUID(IID_IMonoUnknown, 0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
+DEFINE_GUID(IID_IMonoDispatch, 0x00020400, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
+
+int STDCALL MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv)
+{
+       *ppv = NULL;
+       if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) {
+               *ppv = pUnk;
+               return S_OK;
+       }
+       else if (!memcmp(riid, &IID_ITest, sizeof(GUID))) {
+               *ppv = pUnk;
+               return S_OK;
+       }
+       else if (!memcmp(riid, &IID_IMonoDispatch, sizeof(GUID))) {
+               *ppv = pUnk;
+               return S_OK;
+       }
+       return E_NOINTERFACE;
+}
+
+int STDCALL MonoAddRef(MonoComObject* pUnk)
+{
+       return ++(pUnk->m_ref);
+}
+
+int STDCALL MonoRelease(MonoComObject* pUnk)
+{
+       return --(pUnk->m_ref);
+}
+
+int STDCALL SByteIn(MonoComObject* pUnk, char a)
+{
+       return S_OK;
+}
+
+int STDCALL ByteIn(MonoComObject* pUnk, unsigned char a)
+{
+       return S_OK;
+}
+
+int STDCALL ShortIn(MonoComObject* pUnk, short a)
+{
+       return S_OK;
+}
+
+int STDCALL UShortIn(MonoComObject* pUnk, unsigned short a)
+{
+       return S_OK;
+}
+
+int STDCALL IntIn(MonoComObject* pUnk, int a)
+{
+       return S_OK;
+}
+
+int STDCALL UIntIn(MonoComObject* pUnk, unsigned int a)
+{
+       return S_OK;
+}
+
+int STDCALL LongIn(MonoComObject* pUnk, LONGLONG a)
+{
+       return S_OK;
+}
+
+int STDCALL ULongIn(MonoComObject* pUnk, ULONGLONG a)
+{
+       return S_OK;
+}
+
+int STDCALL FloatIn(MonoComObject* pUnk, float a)
+{
+       return S_OK;
+}
+
+int STDCALL DoubleIn(MonoComObject* pUnk, double a)
+{
+       return S_OK;
+}
+
+int STDCALL ITestIn(MonoComObject* pUnk, MonoComObject *pUnk2)
+{
+       return S_OK;
+}
+
+int STDCALL ITestOut(MonoComObject* pUnk, MonoComObject* *ppUnk)
+{
+       return S_OK;
+}
+
+int STDCALL get_ITest(MonoComObject* pUnk, MonoComObject* *ppUnk)
+{
+       return S_OK;
+}
+
+static void create_com_object (MonoComObject** pOut)
+{
+       *pOut = g_new0 (MonoComObject, 1);
+       (*pOut)->vtbl = g_new0 (MonoIUnknown, 1);
+
+       (*pOut)->m_ref = 1;
+       (*pOut)->vtbl->QueryInterface = MonoQueryInterface;
+       (*pOut)->vtbl->AddRef = MonoAddRef;
+       (*pOut)->vtbl->Release = MonoRelease;
+       (*pOut)->vtbl->SByteIn = SByteIn;
+       (*pOut)->vtbl->ByteIn = ByteIn;
+       (*pOut)->vtbl->ShortIn = ShortIn;
+       (*pOut)->vtbl->UShortIn = UShortIn;
+       (*pOut)->vtbl->IntIn = IntIn;
+       (*pOut)->vtbl->UIntIn = UIntIn;
+       (*pOut)->vtbl->LongIn = LongIn;
+       (*pOut)->vtbl->ULongIn = ULongIn;
+       (*pOut)->vtbl->FloatIn = FloatIn;
+       (*pOut)->vtbl->DoubleIn = DoubleIn;
+       (*pOut)->vtbl->ITestIn = ITestIn;
+       (*pOut)->vtbl->ITestOut = ITestOut;
+       (*pOut)->vtbl->get_ITest = get_ITest;
+}
+
+static MonoComObject* same_object = NULL;
+
+STDCALL int
+mono_test_marshal_com_object_create(MonoComObject* *pUnk)
+{
+       create_com_object (pUnk);
+
+       if (!same_object)
+               same_object = *pUnk;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_com_object_same(MonoComObject* *pUnk)
+{
+       *pUnk = same_object;
+
+       return 0;
+}
+
+STDCALL int
+mono_test_marshal_com_object_destroy(MonoComObject *pUnk)
+{
+       int ref = --(pUnk->m_ref);
+       g_free(pUnk->vtbl);
+       g_free(pUnk);
+
+       return ref;
+}
+
+STDCALL int
+mono_test_marshal_com_object_ref_count(MonoComObject *pUnk)
+{
+       return pUnk->m_ref;
+}
+
+STDCALL int
+mono_test_marshal_ccw_itest (MonoComObject *pUnk)
+{
+       int hr = 0;
+       MonoComObject* pTest;
+
+       if (!pUnk)
+               return 1;
+
+       hr = pUnk->vtbl->SByteIn (pUnk, -100);
+       if (hr != 0)
+               return 2;
+       hr = pUnk->vtbl->ByteIn (pUnk, 100);
+       if (hr != 0)
+               return 3;
+       hr = pUnk->vtbl->ShortIn (pUnk, -100);
+       if (hr != 0)
+               return 4;
+       hr = pUnk->vtbl->UShortIn (pUnk, 100);
+       if (hr != 0)
+               return 5;
+       hr = pUnk->vtbl->IntIn (pUnk, -100);
+       if (hr != 0)
+               return 6;
+       hr = pUnk->vtbl->UIntIn (pUnk, 100);
+       if (hr != 0)
+               return 7;
+       hr = pUnk->vtbl->LongIn (pUnk, -100);
+       if (hr != 0)
+               return 8;
+       hr = pUnk->vtbl->ULongIn (pUnk, 100);
+       if (hr != 0)
+               return 9;
+       hr = pUnk->vtbl->FloatIn (pUnk, 3.14f);
+       if (hr != 0)
+               return 10;
+       hr = pUnk->vtbl->DoubleIn (pUnk, 3.14);
+       if (hr != 0)
+               return 11;
+       hr = pUnk->vtbl->ITestIn (pUnk, pUnk);
+       if (hr != 0)
+               return 12;
+       hr = pUnk->vtbl->ITestOut (pUnk, &pTest);
+       if (hr != 0)
+               return 13;
+
+       return 0;
+}
+
+
+#endif //NOT_YET