X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Ftests%2Flibtest.c;h=57e8f700f6c57184f7007a278fd2292cff8f9e1e;hb=ff8ebae6a4558e59a16334e98d839a4cd60c8786;hp=59a338fc2495dc412d8845061fa3e11a48ed9173;hpb=95dc3521c07b15316c0087fb5f088e65162077e4;p=mono.git diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c index 59a338fc249..57e8f700f6c 100644 --- a/mono/tests/libtest.c +++ b/mono/tests/libtest.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -52,6 +53,43 @@ static void* marshal_alloc (gsize size) #endif } + +static gunichar2* marshal_bstr_alloc(const gchar* str) +{ +#ifdef WIN32 + gunichar2* ret = NULL; + gunichar2* temp = NULL; + temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL); + ret = SysAllocString (temp); + g_free (temp); + return ret; +#else + gchar* ret = NULL; + int slen = strlen (str); + gunichar2* temp; + /* allocate len + 1 utf16 characters plus 4 byte integer for length*/ + ret = g_malloc ((slen + 1) * sizeof(gunichar2) + sizeof(guint32)); + if (ret == NULL) + return NULL; + temp = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL); + memcpy (ret + sizeof(guint32), temp, slen * sizeof(gunichar2)); + * ((guint32 *) ret) = slen * sizeof(gunichar2); + ret [4 + slen * sizeof(gunichar2)] = 0; + ret [5 + slen * sizeof(gunichar2)] = 0; + + return (gunichar2*)(ret + 4); +#endif +} + +LIBTEST_API int STDCALL +mono_cominterop_is_supported (void) +{ +#if defined(TARGET_X86) || defined(TARGET_AMD64) + return 1; +#endif + return 0; +} + LIBTEST_API unsigned short* STDCALL test_lpwstr_marshal (unsigned short* chars, long length) { @@ -958,6 +996,36 @@ mono_test_marshal_stringbuilder_unicode (gunichar2 *s, int n) return 0; } +LIBTEST_API void STDCALL +mono_test_marshal_stringbuilder_out (char **s) +{ + const char m[] = "This is my message. Isn't it nice?"; + char *str; + + str = g_malloc (strlen (m) + 1); + memcpy (str, m, strlen (m) + 1); + + *s = str; +} + +LIBTEST_API int STDCALL +mono_test_marshal_stringbuilder_out_unicode (gunichar2 **s) +{ + const char m[] = "This is my message. Isn't it nice?"; + gunichar2 *s2; + glong len; + + s2 = g_utf8_to_utf16 (m, -1, NULL, &len, NULL); + + len = (len * 2) + 2; + *s = g_malloc (len); + memcpy (*s, s2, len); + + g_free (s2); + + return 0; +} + typedef struct { #ifndef __GNUC__ char a; @@ -2020,6 +2088,14 @@ mono_test_marshal_array_delegate (void *arr, int len, ArrayDelegate del) return del (len, NULL, arr); } +typedef int (STDCALL *ArrayDelegateLong) (gint64 i, char *j, void *arr); + +LIBTEST_API int STDCALL +mono_test_marshal_array_delegate_long (void *arr, gint64 len, ArrayDelegateLong del) +{ + return del (len, NULL, arr); +} + LIBTEST_API int STDCALL mono_test_marshal_out_array_delegate (int *arr, int len, ArrayDelegate del) { @@ -2221,29 +2297,135 @@ mono_safe_handle_ref (void **handle) *handle = (void *) 0x800d; } + +LIBTEST_API double STDCALL +mono_test_marshal_date_time (double d, double *d2) +{ + *d2 = d; + return d; +} + /* * COM INTEROP TESTS */ -#ifdef WIN32 +#ifndef WIN32 + +typedef struct { + guint16 vt; + guint16 wReserved1; + guint16 wReserved2; + guint16 wReserved3; + union { + gint64 llVal; + gint32 lVal; + guint8 bVal; + gint16 iVal; + float fltVal; + double dblVal; + gint16 boolVal; + gunichar2* bstrVal; + gint8 cVal; + guint16 uiVal; + guint32 ulVal; + guint64 ullVal; + struct { + gpointer pvRecord; + gpointer pRecInfo; + }; + }; +} VARIANT; + +typedef enum { + VARIANT_TRUE = -1, + VARIANT_FALSE = 0 +} VariantBool; + +typedef enum { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + VT_VECTOR = 4096, + VT_ARRAY = 8192, + VT_BYREF = 16384 +} VarEnum; + +void VariantInit(VARIANT* vt) +{ + vt->vt = VT_EMPTY; +} + +typedef struct +{ + guint32 a; + guint16 b; + guint16 c; + guint8 d[8]; +} GUID; + +#define S_OK 0 + +#endif LIBTEST_API int STDCALL -mono_test_marshal_bstr_in(BSTR bstr) +mono_test_marshal_bstr_in(gunichar2* bstr) { - if (!wcscmp(bstr, L"mono_test_marshal_bstr_in")) + gint32 result = 0; + gchar* bstr_utf8 = g_utf16_to_utf8 (bstr, -1, NULL, NULL, NULL); + result = strcmp("mono_test_marshal_bstr_in", bstr_utf8); + g_free(bstr_utf8); + if (result == 0) return 0; return 1; } LIBTEST_API int STDCALL -mono_test_marshal_bstr_out(BSTR* bstr) +mono_test_marshal_bstr_out(gunichar2** bstr) { - *bstr = SysAllocString(L"mono_test_marshal_bstr_out"); + *bstr = marshal_bstr_alloc ("mono_test_marshal_bstr_out"); return 0; } LIBTEST_API int STDCALL -mono_test_marshal_bstr_in_null(BSTR bstr) +mono_test_marshal_bstr_in_null(gunichar2* bstr) { if (!bstr) return 0; @@ -2251,7 +2433,7 @@ mono_test_marshal_bstr_in_null(BSTR bstr) } LIBTEST_API int STDCALL -mono_test_marshal_bstr_out_null(BSTR* bstr) +mono_test_marshal_bstr_out_null(gunichar2** bstr) { *bstr = NULL; return 0; @@ -2340,7 +2522,12 @@ mono_test_marshal_variant_in_double(VARIANT variant) LIBTEST_API int STDCALL mono_test_marshal_variant_in_bstr(VARIANT variant) { - if (variant.vt == VT_BSTR && !wcscmp(variant.bstrVal, L"PI")) + gint32 result = 0; + gchar* bstr_utf8 = g_utf16_to_utf8 (variant.bstrVal, -1, NULL, NULL, NULL); + result = strcmp("PI", bstr_utf8); + g_free(bstr_utf8); + + if (variant.vt == VT_BSTR && !result) return 0; return 1; } @@ -2455,7 +2642,7 @@ LIBTEST_API int STDCALL mono_test_marshal_variant_out_bstr(VARIANT* variant) { variant->vt = VT_BSTR; - variant->bstrVal = SysAllocString(L"PI"); + variant->bstrVal = marshal_bstr_alloc("PI"); return 0; } @@ -2576,7 +2763,7 @@ mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func) { VARIANT vt; vt.vt = VT_BSTR; - vt.bstrVal = SysAllocString(L"PI"); + vt.bstrVal = marshal_bstr_alloc("PI"); return func (VT_BSTR, vt); } @@ -2712,9 +2899,16 @@ LIBTEST_API int STDCALL mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func) { VARIANT vt; + gchar* bstr_utf8; + gint32 result = 0; + + VariantInit (&vt); func (VT_BSTR, &vt); - if (vt.vt == VT_BSTR && !wcscmp(vt.bstrVal, L"PI")) + bstr_utf8 = g_utf16_to_utf8 (vt.bstrVal, -1, NULL, NULL, NULL); + result = strcmp("PI", bstr_utf8); + g_free(bstr_utf8); + if (vt.vt == VT_BSTR && !result) return 0; return 1; } @@ -2755,8 +2949,8 @@ typedef struct 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 *LongIn)(MonoComObject* pUnk, gint64 a); + int (STDCALL *ULongIn)(MonoComObject* pUnk, guint64 a); int (STDCALL *FloatIn)(MonoComObject* pUnk, float a); int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a); int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2); @@ -2769,13 +2963,14 @@ struct MonoComObject 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); +static GUID IID_ITest = {0, 0, 0, {0,0,0,0,0,0,0,1}}; +static GUID IID_IMonoUnknown = {0, 0, 0, {0xc0,0,0,0,0,0,0,0x46}}; +static GUID IID_IMonoDispatch = {0x00020400, 0, 0, {0xc0,0,0,0,0,0,0,0x46}}; LIBTEST_API int STDCALL MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv) { + *ppv = NULL; if (!memcmp(riid, &IID_IMonoUnknown, sizeof(GUID))) { *ppv = pUnk; @@ -2789,7 +2984,7 @@ MonoQueryInterface(MonoComObject* pUnk, gpointer riid, gpointer* ppv) *ppv = pUnk; return S_OK; } - return E_NOINTERFACE; + return 0x80004002; //E_NOINTERFACE; } LIBTEST_API int STDCALL @@ -2841,13 +3036,13 @@ UIntIn(MonoComObject* pUnk, unsigned int a) } LIBTEST_API int STDCALL -LongIn(MonoComObject* pUnk, LONGLONG a) +LongIn(MonoComObject* pUnk, gint64 a) { return S_OK; } LIBTEST_API int STDCALL -ULongIn(MonoComObject* pUnk, ULONGLONG a) +ULongIn(MonoComObject* pUnk, guint64 a) { return S_OK; } @@ -2992,15 +3187,11 @@ mono_test_marshal_ccw_itest (MonoComObject *pUnk) return 0; } - -#endif //NOT_YET - - /* * mono_method_get_unmanaged_thunk tests */ -#if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__)) || (defined(__ppc__) && defined(__APPLE__))) +#if defined(__GNUC__) && ((defined(__i386__) && (defined(__linux__) || defined (__APPLE__)) || defined (__FreeBSD__) || defined(__OpenBSD__)) || (defined(__ppc__) && defined(__APPLE__))) #define ALIGN(size) __attribute__ ((aligned(size))) #else #define ALIGN(size) @@ -3024,6 +3215,12 @@ lookup_mono_symbol (const char *symbol_name) return NULL; } +gpointer +mono_test_marshal_lookup_symbol (const char *symbol_name) +{ + return lookup_mono_symbol (symbol_name); +} + /** * test_method_thunk: * @@ -3761,7 +3958,7 @@ mono_test_Winx64_struct5_ret_managed (managed_struct5_ret_delegate func) LIBTEST_API int STDCALL mono_test_marshal_bool_in (int arg, unsigned int expected, unsigned int bDefaultMarsh, unsigned int bBoolCustMarsh, - char bI1CustMarsh, unsigned char bU1CustMarsh, unsigned short bVBCustMarsh) + char bI1CustMarsh, unsigned char bU1CustMarsh, short bVBCustMarsh) { switch (arg) { case 1: @@ -4048,7 +4245,7 @@ mono_test_managed_marshal_bool_ref (int arg, unsigned int expected, unsigned int #ifdef WIN32 LIBTEST_API int STDCALL -mono_test_marshal_variant_out_safearray_1dim_vt_bstr_empty (SAFEARRAY** safearray) +mono_test_marshal_safearray_out_1dim_vt_bstr_empty (SAFEARRAY** safearray) { /* Create an empty one-dimensional array of variants */ SAFEARRAY *pSA; @@ -4063,13 +4260,13 @@ mono_test_marshal_variant_out_safearray_1dim_vt_bstr_empty (SAFEARRAY** safearra } LIBTEST_API int STDCALL -mono_test_marshal_variant_out_safearray_1dim_vt_bstr (SAFEARRAY** safearray) +mono_test_marshal_safearray_out_1dim_vt_bstr (SAFEARRAY** safearray) { /* Create a one-dimensional array of 10 variants filled with "0" to "9" */ SAFEARRAY *pSA; SAFEARRAYBOUND dimensions [1]; long i; - wchar_t buffer [20]; + gchar buffer [20]; HRESULT hr = S_OK; long indices [1]; @@ -4081,8 +4278,8 @@ mono_test_marshal_variant_out_safearray_1dim_vt_bstr (SAFEARRAY** safearray) VARIANT vOut; VariantInit (&vOut); vOut.vt = VT_BSTR; - _ltow (i,buffer,10); - vOut.bstrVal= SysAllocString (buffer); + _ltoa (i,buffer,10); + vOut.bstrVal= marshal_bstr_alloc (buffer); indices [0] = i; if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) { VariantClear (&vOut); @@ -4096,7 +4293,7 @@ mono_test_marshal_variant_out_safearray_1dim_vt_bstr (SAFEARRAY** safearray) } LIBTEST_API int STDCALL -mono_test_marshal_variant_out_safearray_2dim_vt_int (SAFEARRAY** safearray) +mono_test_marshal_safearray_out_2dim_vt_i4 (SAFEARRAY** safearray) { /* Create a two-dimensional array of 4x3 variants filled with 11, 12, 13, etc. */ SAFEARRAY *pSA; @@ -4116,7 +4313,7 @@ mono_test_marshal_variant_out_safearray_2dim_vt_int (SAFEARRAY** safearray) VARIANT vOut; VariantInit (&vOut); vOut.vt = VT_I4; - vOut.intVal = (i+1)*10+(j+1); + vOut.lVal = (i+1)*10+(j+1); indices [0] = i; indices [1] = j; if ((hr = SafeArrayPutElement (pSA, indices, &vOut)) != S_OK) { @@ -4132,7 +4329,7 @@ mono_test_marshal_variant_out_safearray_2dim_vt_int (SAFEARRAY** safearray) } LIBTEST_API int STDCALL -mono_test_marshal_variant_out_safearray_4dim_vt_int (SAFEARRAY** safearray) +mono_test_marshal_safearray_out_4dim_vt_i4 (SAFEARRAY** safearray) { /* Create a four-dimensional array of 10x3x6x7 variants filled with their indices */ /* Also use non zero lower bounds */ @@ -4158,13 +4355,607 @@ mono_test_marshal_variant_out_safearray_4dim_vt_int (SAFEARRAY** safearray) for (i= 0; i< 10*3*6*7; i++) { VariantInit(&pData [i]); pData [i].vt = VT_I4; - pData [i].intVal = i; + pData [i].lVal = i; } - SafeArrayUnaccessData(pSA); + SafeArrayUnaccessData (pSA); *safearray = pSA; return hr; } +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byval_1dim_empty (SAFEARRAY* safearray) +{ + /* Check that array is one dimensional and empty */ + + UINT dim; + long lbound, ubound; + + dim = SafeArrayGetDim (safearray); + if (dim != 1) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound); + SafeArrayGetUBound (safearray, 1, &ubound); + + if ((lbound > 0) || (ubound > 0)) + return 1; + + return 0; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byval_1dim_vt_i4 (SAFEARRAY* safearray) +{ + /* Check that array is one dimensional containing integers from 1 to 10 */ + + UINT dim; + long lbound, ubound; + VARIANT *pData; + long i; + int result=0; + + dim = SafeArrayGetDim (safearray); + if (dim != 1) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound); + SafeArrayGetUBound (safearray, 1, &ubound); + + if ((lbound != 0) || (ubound != 9)) + return 1; + + SafeArrayAccessData (safearray, (void **)&pData); + for (i= lbound; i <= ubound; i++) { + if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i + 1)) + result = 1; + } + SafeArrayUnaccessData (safearray); + + return result; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byval_1dim_vt_mixed (SAFEARRAY* safearray) +{ + /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */ + + UINT dim; + long lbound, ubound; + VARIANT *pData; + long i; + long indices [1]; + VARIANT element; + int result=0; + + VariantInit (&element); + + dim = SafeArrayGetDim (safearray); + if (dim != 1) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound); + SafeArrayGetUBound (safearray, 1, &ubound); + + if ((lbound != 0) || (ubound != 12)) + return 1; + + SafeArrayAccessData (safearray, (void **)&pData); + for (i= lbound; i <= ubound; i++) { + if ((i%2 == 0) && (pData [i].vt != VT_I4)) + result = 1; + if ((i%2 == 1) && (pData [i].vt != VT_BSTR)) + result = 1; + if ((VariantChangeType (&pData [i], &pData [i], VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) || (pData [i].lVal != i)) + result = 1; + } + SafeArrayUnaccessData (safearray); + + /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */ + + indices [0] = 0; + element.vt = VT_I4; + element.lVal = 333; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + return result; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byval_2dim_vt_i4 (SAFEARRAY* safearray) +{ + /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */ + + UINT dim; + long lbound1, ubound1, lbound2, ubound2; + long i, j, failed; + long indices [2]; + VARIANT element; + + VariantInit (&element); + + dim = SafeArrayGetDim (safearray); + if (dim != 2) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound1); + SafeArrayGetUBound (safearray, 1, &ubound1); + + if ((lbound1 != 0) || (ubound1 != 1)) + return 1; + + SafeArrayGetLBound (safearray, 2, &lbound2); + SafeArrayGetUBound (safearray, 2, &ubound2); + + if ((lbound2 != 0) || (ubound2 != 3)) { + return 1; + } + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + for (j= lbound2; j <= ubound2; j++) { + indices [1] = j; + if (SafeArrayGetElement (safearray, indices, &element) != S_OK) + return 1; + failed = ((element.vt != VT_I4) || (element.lVal != 10*(i+1)+(j+1))); + VariantClear (&element); + if (failed) + return 1; + } + } + + /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */ + + indices [0] = 0; + indices [1] = 0; + element.vt = VT_I4; + element.lVal = 333; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + return 0; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byval_3dim_vt_bstr (SAFEARRAY* safearray) +{ + /* Check that array is one dimensional containing integers mixed with strings from 0 to 12 */ + + UINT dim; + long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3; + long i, j, k, failed; + long indices [3]; + VARIANT element; + + VariantInit (&element); + + dim = SafeArrayGetDim (safearray); + if (dim != 3) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound1); + SafeArrayGetUBound (safearray, 1, &ubound1); + + if ((lbound1 != 0) || (ubound1 != 1)) + return 1; + + SafeArrayGetLBound (safearray, 2, &lbound2); + SafeArrayGetUBound (safearray, 2, &ubound2); + + if ((lbound2 != 0) || (ubound2 != 1)) + return 1; + + SafeArrayGetLBound (safearray, 3, &lbound3); + SafeArrayGetUBound (safearray, 3, &ubound3); + + if ((lbound3 != 0) || (ubound3 != 2)) + return 1; + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + for (j= lbound2; j <= ubound2; j++) { + indices [1] = j; + for (k= lbound3; k <= ubound3; k++) { + indices [2] = k; + if (SafeArrayGetElement (safearray, indices, &element) != S_OK) + return 1; + failed = ((element.vt != VT_BSTR) + || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) + || (element.lVal != 100*(i+1)+10*(j+1)+(k+1))); + VariantClear (&element); + if (failed) + return 1; + } + } + } + + /* Change the first element of the array to verify that [in] parameters are not marshalled back to the managed side */ + + indices [0] = 0; + indices [1] = 0; + indices [2] = 0; + element.vt = VT_BSTR; + element.bstrVal = SysAllocString(L"Should not be copied"); + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + return 0; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_byref_3dim_vt_bstr (SAFEARRAY** safearray) +{ + return mono_test_marshal_safearray_in_byval_3dim_vt_bstr (*safearray); +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_out_byref_1dim_empty (SAFEARRAY** safearray) +{ + /* Check that the input array is what is expected and change it so the caller can check */ + /* correct marshalling back to managed code */ + + UINT dim; + long lbound, ubound; + SAFEARRAYBOUND dimensions [1]; + long i; + wchar_t buffer [20]; + HRESULT hr = S_OK; + long indices [1]; + + /* Check that in array is one dimensional and empty */ + + dim = SafeArrayGetDim (*safearray); + if (dim != 1) { + return 1; + } + + SafeArrayGetLBound (*safearray, 1, &lbound); + SafeArrayGetUBound (*safearray, 1, &ubound); + + if ((lbound > 0) || (ubound > 0)) { + return 1; + } + + /* Re-dimension the array and return a one-dimensional array of 8 variants filled with "0" to "7" */ + + dimensions [0].lLbound = 0; + dimensions [0].cElements = 8; + + hr = SafeArrayRedim (*safearray, dimensions); + if (hr != S_OK) + return 1; + + for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) { + VARIANT vOut; + VariantInit (&vOut); + vOut.vt = VT_BSTR; + _ltow (i,buffer,10); + vOut.bstrVal = SysAllocString (buffer); + indices [0] = i; + if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) { + VariantClear (&vOut); + SafeArrayDestroy (*safearray); + return hr; + } + VariantClear (&vOut); + } + return hr; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr (SAFEARRAY** safearray) +{ + /* Check that the input array is what is expected and change it so the caller can check */ + /* correct marshalling back to managed code */ + + UINT dim; + long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3; + SAFEARRAYBOUND dimensions [1]; + long i, j, k, failed; + wchar_t buffer [20]; + HRESULT hr = S_OK; + long indices [3]; + VARIANT element; + + VariantInit (&element); + + /* Check that in array is three dimensional and contains the expected values */ + + dim = SafeArrayGetDim (*safearray); + if (dim != 3) + return 1; + + SafeArrayGetLBound (*safearray, 1, &lbound1); + SafeArrayGetUBound (*safearray, 1, &ubound1); + + if ((lbound1 != 0) || (ubound1 != 1)) + return 1; + + SafeArrayGetLBound (*safearray, 2, &lbound2); + SafeArrayGetUBound (*safearray, 2, &ubound2); + + if ((lbound2 != 0) || (ubound2 != 1)) + return 1; + + SafeArrayGetLBound (*safearray, 3, &lbound3); + SafeArrayGetUBound (*safearray, 3, &ubound3); + + if ((lbound3 != 0) || (ubound3 != 2)) + return 1; + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + for (j= lbound2; j <= ubound2; j++) { + indices [1] = j; + for (k= lbound3; k <= ubound3; k++) { + indices [2] = k; + if (SafeArrayGetElement (*safearray, indices, &element) != S_OK) + return 1; + failed = ((element.vt != VT_BSTR) + || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) + || (element.lVal != 100*(i+1)+10*(j+1)+(k+1))); + VariantClear (&element); + if (failed) + return 1; + } + } + } + + hr = SafeArrayDestroy (*safearray); + if (hr != S_OK) + return 1; + + /* Return a new one-dimensional array of 8 variants filled with "0" to "7" */ + + dimensions [0].lLbound = 0; + dimensions [0].cElements = 8; + + *safearray = SafeArrayCreate (VT_VARIANT, 1, dimensions); + + for (i= dimensions [0].lLbound; i< (dimensions [0].lLbound + dimensions [0].cElements); i++) { + VARIANT vOut; + VariantInit (&vOut); + vOut.vt = VT_BSTR; + _ltow (i,buffer,10); + vOut.bstrVal = SysAllocString (buffer); + indices [0] = i; + if ((hr = SafeArrayPutElement (*safearray, indices, &vOut)) != S_OK) { + VariantClear (&vOut); + SafeArrayDestroy (*safearray); + return hr; + } + VariantClear (&vOut); + } + return hr; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_out_byref_1dim_vt_i4 (SAFEARRAY** safearray) +{ + /* Check that the input array is what is expected and change it so the caller can check */ + /* correct marshalling back to managed code */ + + UINT dim; + long lbound1, ubound1; + long i, failed; + HRESULT hr = S_OK; + long indices [1]; + VARIANT element; + + VariantInit (&element); + + /* Check that in array is one dimensional and contains the expected value */ + + dim = SafeArrayGetDim (*safearray); + if (dim != 1) + return 1; + + SafeArrayGetLBound (*safearray, 1, &lbound1); + SafeArrayGetUBound (*safearray, 1, &ubound1); + + ubound1 = 1; + if ((lbound1 != 0) || (ubound1 != 1)) + return 1; + ubound1 = 0; + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + if (SafeArrayGetElement (*safearray, indices, &element) != S_OK) + return 1; + failed = (element.vt != VT_I4) || (element.lVal != i+1); + VariantClear (&element); + if (failed) + return 1; + } + + /* Change one of the elements of the array to verify that [out] parameter is marshalled back to the managed side */ + + indices [0] = 0; + element.vt = VT_I4; + element.lVal = -1; + SafeArrayPutElement (*safearray, indices, &element); + VariantClear (&element); + + return hr; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (SAFEARRAY* safearray) +{ + /* Check that the input array is what is expected and change it so the caller can check */ + /* correct marshalling back to managed code */ + + UINT dim; + long lbound1, ubound1; + SAFEARRAYBOUND dimensions [1]; + long i, failed; + HRESULT hr = S_OK; + long indices [1]; + VARIANT element; + + VariantInit (&element); + + /* Check that in array is one dimensional and contains the expected value */ + + dim = SafeArrayGetDim (safearray); + if (dim != 1) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound1); + SafeArrayGetUBound (safearray, 1, &ubound1); + + if ((lbound1 != 0) || (ubound1 != 0)) + return 1; + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + if (SafeArrayGetElement (safearray, indices, &element) != S_OK) + return 1; + failed = (element.vt != VT_I4) || (element.lVal != i+1); + VariantClear (&element); + if (failed) + return 1; + } + + /* Change the array to verify how [out] parameter is marshalled back to the managed side */ + + /* Redimension the array */ + dimensions [0].lLbound = lbound1; + dimensions [0].cElements = 2; + hr = SafeArrayRedim(safearray, dimensions); + + indices [0] = 0; + element.vt = VT_I4; + element.lVal = 12345; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + indices [0] = 1; + element.vt = VT_I4; + element.lVal = -12345; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + return hr; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_in_out_byval_3dim_vt_bstr (SAFEARRAY* safearray) +{ + /* Check that the input array is what is expected and change it so the caller can check */ + /* correct marshalling back to managed code */ + + UINT dim; + long lbound1, ubound1, lbound2, ubound2, lbound3, ubound3; + long i, j, k, failed; + HRESULT hr = S_OK; + long indices [3]; + VARIANT element; + + VariantInit (&element); + + /* Check that in array is three dimensional and contains the expected values */ + + dim = SafeArrayGetDim (safearray); + if (dim != 3) + return 1; + + SafeArrayGetLBound (safearray, 1, &lbound1); + SafeArrayGetUBound (safearray, 1, &ubound1); + + if ((lbound1 != 0) || (ubound1 != 1)) + return 1; + + SafeArrayGetLBound (safearray, 2, &lbound2); + SafeArrayGetUBound (safearray, 2, &ubound2); + + if ((lbound2 != 0) || (ubound2 != 1)) + return 1; + + SafeArrayGetLBound (safearray, 3, &lbound3); + SafeArrayGetUBound (safearray, 3, &ubound3); + + if ((lbound3 != 0) || (ubound3 != 2)) + return 1; + + for (i= lbound1; i <= ubound1; i++) { + indices [0] = i; + for (j= lbound2; j <= ubound2; j++) { + indices [1] = j; + for (k= lbound3; k <= ubound3; k++) { + indices [2] = k; + if (SafeArrayGetElement (safearray, indices, &element) != S_OK) + return 1; + failed = ((element.vt != VT_BSTR) + || (VariantChangeType (&element, &element, VARIANT_NOUSEROVERRIDE, VT_I4) != S_OK) + || (element.lVal != 100*(i+1)+10*(j+1)+(k+1))); + VariantClear (&element); + if (failed) + return 1; + } + } + } + + /* Change the elements of the array to verify that [out] parameter is marshalled back to the managed side */ + + indices [0] = 1; + indices [1] = 1; + indices [2] = 2; + element.vt = VT_I4; + element.lVal = 333; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + indices [0] = 1; + indices [1] = 1; + indices [2] = 1; + element.vt = VT_I4; + element.lVal = 111; + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + indices [0] = 0; + indices [1] = 1; + indices [2] = 0; + element.vt = VT_BSTR; + element.bstrVal = marshal_bstr_alloc("ABCDEFG"); + SafeArrayPutElement (safearray, indices, &element); + VariantClear (&element); + + return hr; +} + +LIBTEST_API int STDCALL +mono_test_marshal_safearray_mixed( + SAFEARRAY *safearray1, + SAFEARRAY **safearray2, + SAFEARRAY *safearray3, + SAFEARRAY **safearray4 + ) +{ + HRESULT hr = S_OK; + + /* Initialize out parameters */ + *safearray2 = NULL; + + /* array1: Check that in array is one dimensional and contains the expected value */ + hr = mono_test_marshal_safearray_in_out_byval_1dim_vt_i4 (safearray1); + + /* array2: Fill in with some values to check on the managed side */ + if (hr == S_OK) + hr = mono_test_marshal_safearray_out_1dim_vt_bstr (safearray2); + + /* array3: Check that in array is one dimensional and contains the expected value */ + if (hr == S_OK) + hr = mono_test_marshal_safearray_in_byval_1dim_vt_mixed(safearray3); + + /* array4: Check input values and fill in with some values to check on the managed side */ + if (hr == S_OK) + hr = mono_test_marshal_safearray_in_out_byref_3dim_vt_bstr(safearray4); + + return hr; +} + #endif