Added environ support for Darwin.
[wine] / dlls / oleaut32 / tests / safearray.c
1 /*
2  * SafeArray test program
3  *
4  * Copyright 2002 Marcus Meissner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include <float.h>
27 #include <time.h>
28
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "winnls.h"
35 #include "winsock.h"
36 #include "winerror.h"
37 #include "winnt.h"
38
39 #include "wtypes.h"
40 #include "oleauto.h"
41
42 static HMODULE hOleaut32;
43
44 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
45 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
46 static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
47 static HRESULT (WINAPI *pSafeArraySetIID)(SAFEARRAY*,REFGUID);
48 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
49 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
50 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID);
51 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
52
53 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
54
55 /* Is a given function exported from oleaut32? */
56 #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
57
58 /* Have IRecordInfo data type? */
59 #define HAVE_OLEAUT32_RECORD  HAVE_FUNC(SafeArraySetRecordInfo)
60 /* Have I8/UI8 data type? */
61 #define HAVE_OLEAUT32_I8      HAVE_FUNC(VarI8FromI1)
62 /* Have the decimal type? */
63 #define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
64 /* very old version? */
65 #define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
66
67 #define START_REF_COUNT 1
68 #define RECORD_SIZE 64
69 #define RECORD_SIZE_FAIL 17
70 /************************************************************************
71  * Dummy IRecordInfo Implementation
72  */
73 typedef struct IRecordInfoImpl
74 {
75   ICOM_VTABLE(IRecordInfo) *lpvtbl;
76   DWORD ref;
77   DWORD sizeCalled;
78   DWORD clearCalled;
79 } IRecordInfoImpl;
80
81 static ICOM_VTABLE(IRecordInfo) IRecordInfoImpl_VTable;
82
83 static IRecordInfoImpl *IRecordInfoImpl_Construct()
84 {
85   IRecordInfoImpl *rec;
86
87   rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
88   rec->lpvtbl = &IRecordInfoImpl_VTable;
89   rec->ref = START_REF_COUNT;
90   rec->clearCalled = 0;
91   rec->sizeCalled = 0;
92   return rec;
93 }
94
95 static ULONG CALLBACK IRecordInfoImpl_AddRef(IRecordInfo *iface)
96 {
97   ICOM_THIS(IRecordInfoImpl, iface);
98   return ++This->ref;
99 }
100
101 static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
102 {
103   ICOM_THIS(IRecordInfoImpl, iface);
104   return --This->ref;
105 }
106
107 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
108
109 static HRESULT CALLBACK IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting WINE_UNUSED)
110 {
111   ICOM_THIS(IRecordInfoImpl, iface);
112   This->clearCalled++;
113   return S_OK;
114 }
115
116 static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
117 {
118   ICOM_THIS(IRecordInfoImpl, iface);
119   This->sizeCalled++;
120   *size = 17;
121   if (fail_GetSize)
122     return E_UNEXPECTED;
123   *size = RECORD_SIZE;
124   return S_OK;
125 }
126
127 static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface WINE_UNUSED)
128 {
129   trace("Called an unexpected IRecordInfo method - please report!\n");
130   /* Quit because we'll just crash anyway */
131   fflush(NULL);
132   exit(255);
133 }
134
135 static ICOM_VTABLE(IRecordInfo) IRecordInfoImpl_VTable =
136 {
137   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
138   (PVOID)IRecordInfoImpl_Dummy,
139   IRecordInfoImpl_AddRef,
140   IRecordInfoImpl_Release,
141   (PVOID)IRecordInfoImpl_Dummy,
142   IRecordInfoImpl_RecordClear,
143   (PVOID)IRecordInfoImpl_Dummy,
144   (PVOID)IRecordInfoImpl_Dummy,
145   (PVOID)IRecordInfoImpl_Dummy,
146   (PVOID)IRecordInfoImpl_GetSize,
147   (PVOID)IRecordInfoImpl_Dummy,
148   (PVOID)IRecordInfoImpl_Dummy,
149   (PVOID)IRecordInfoImpl_Dummy,
150   (PVOID)IRecordInfoImpl_Dummy,
151   (PVOID)IRecordInfoImpl_Dummy,
152   (PVOID)IRecordInfoImpl_Dummy,
153   (PVOID)IRecordInfoImpl_Dummy,
154   (PVOID)IRecordInfoImpl_Dummy,
155   (PVOID)IRecordInfoImpl_Dummy,
156   (PVOID)IRecordInfoImpl_Dummy
157 };
158
159 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
160 {
161   switch (vt)
162   {
163     case VT_I1:
164     case VT_UI1:      return sizeof(BYTE);
165     case VT_BOOL:
166     case VT_I2:
167     case VT_UI2:      return sizeof(SHORT);
168     case VT_I4:
169     case VT_UI4:
170     case VT_R4:
171     case VT_ERROR:    return sizeof(LONG);
172     case VT_R8:
173     case VT_I8:
174     case VT_UI8:
175       if (HAVE_OLEAUT32_I8)
176         return sizeof(LONG64);
177       break;
178     case VT_INT:
179     case VT_UINT:     return sizeof(INT);
180     case VT_INT_PTR:
181     case VT_UINT_PTR: return sizeof(UINT_PTR);
182     case VT_CY:       return sizeof(CY);
183     case VT_DATE:     return sizeof(DATE);
184     case VT_BSTR:     return sizeof(BSTR);
185     case VT_DISPATCH: return sizeof(LPDISPATCH);
186     case VT_VARIANT:  return sizeof(VARIANT);
187     case VT_UNKNOWN:  return sizeof(LPUNKNOWN);
188     case VT_DECIMAL:
189       if (HAVE_OLEAUT32_DECIMAL)
190         return sizeof(DECIMAL);
191       break;
192   }
193   return 0;
194 }
195
196 #define VARTYPE_NOT_SUPPORTED 0
197 static struct {
198         VARTYPE vt;    /* VT */
199         UINT elemsize; /* elementsize by VT */
200         UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
201         UINT addflags; /* additional fFeatures from SafeArrayCreate */
202 } vttypes[] = {
203 {VT_EMPTY,    VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
204 {VT_NULL,     VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
205 {VT_I2,       2,                    FADF_HAVEVARTYPE,0},
206 {VT_I4,       4,                    FADF_HAVEVARTYPE,0},
207 {VT_R4,       4,                    FADF_HAVEVARTYPE,0},
208 {VT_R8,       8,                    FADF_HAVEVARTYPE,0},
209 {VT_CY,       8,                    FADF_HAVEVARTYPE,0},
210 {VT_DATE,     8,                    FADF_HAVEVARTYPE,0},
211 {VT_BSTR,     sizeof(BSTR),         FADF_HAVEVARTYPE,FADF_BSTR},
212 {VT_DISPATCH, sizeof(LPDISPATCH),   FADF_HAVEIID,    FADF_DISPATCH},
213 {VT_ERROR,    4,                    FADF_HAVEVARTYPE,0},
214 {VT_BOOL,     2,                    FADF_HAVEVARTYPE,0},
215 {VT_VARIANT,  sizeof(VARIANT),      FADF_HAVEVARTYPE,FADF_VARIANT},
216 {VT_UNKNOWN,  sizeof(LPUNKNOWN),    FADF_HAVEIID,    FADF_UNKNOWN},
217 {VT_DECIMAL,  sizeof(DECIMAL),      FADF_HAVEVARTYPE,0},
218 {15,          VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
219 {VT_I1,       1,                    FADF_HAVEVARTYPE,0},
220 {VT_UI1,      1,                    FADF_HAVEVARTYPE,0},
221 {VT_UI2,      2,                    FADF_HAVEVARTYPE,0},
222 {VT_UI4,      4,                    FADF_HAVEVARTYPE,0},
223 {VT_I8,       VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
224 {VT_UI8,      VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
225 {VT_INT,      sizeof(INT),          FADF_HAVEVARTYPE,0},
226 {VT_UINT,     sizeof(UINT),         FADF_HAVEVARTYPE,0},
227 {VT_VOID,     VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
228 {VT_HRESULT,  VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
229 {VT_PTR,      VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
230 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
231 {VT_CARRAY,   VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
232 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
233 {VT_LPSTR,    VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
234 {VT_LPWSTR,   VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
235 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
236 {VT_RECORD,   VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
237 {VT_BLOB,     VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
238 {VT_STREAM,   VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
239 {VT_STORAGE,  VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
240 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
241 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
242 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
243 {VT_CF,       VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
244 {VT_CLSID,    VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
245 };
246
247 static void test_safearray(void)
248 {
249         SAFEARRAY       *a, b, *c;
250         unsigned int    i;
251         long            indices[2];
252         HRESULT         hres;
253         SAFEARRAYBOUND  bound, bounds[2];
254         VARIANT         v;
255         LPVOID          data;
256         IID             iid;
257         VARTYPE         vt;
258         LONG            l;
259         unsigned char   *ptr1, *ptr2;
260
261         bound.cElements = 1;
262         bound.lLbound   = 0;
263         a = SafeArrayCreate(-1, 1, &bound);
264         ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
265
266         bound.cElements = 0;
267         bound.lLbound   = 42;
268         a = SafeArrayCreate(VT_I4, 1, &bound);
269         ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
270
271         hres = SafeArrayGetLBound(a, 1, &l);
272         ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %lx\n",hres);
273         ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %ld\n",l);
274         hres = SafeArrayGetUBound(a, 1, &l);
275         ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %lx\n",hres);
276         ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %ld\n",l);
277         bound.cElements = 2;
278         hres = SafeArrayRedim(a, &bound);
279         ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %lx\n", hres);
280         bound.cElements = 0;
281         hres = SafeArrayRedim(a, &bound);
282         ok(hres == S_OK || hres == E_OUTOFMEMORY,
283           "SAR to a 0 elements dimension failed with hres %lx\n", hres);
284         hres = SafeArrayDestroy(a);
285         ok(hres == S_OK,"SAD of 0 dim array faild with hres %lx\n", hres);
286
287         bounds[0].cElements = 0;        bounds[0].lLbound =  1;
288         bounds[1].cElements =  2;       bounds[1].lLbound = 23;
289         a = SafeArrayCreate(VT_I4,2,bounds);
290         ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
291         bounds[0].cElements = 1;        bounds[0].lLbound =  1;
292         bounds[1].cElements = 0;        bounds[1].lLbound = 23;
293         a = SafeArrayCreate(VT_I4,2,bounds);
294         ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
295
296         bounds[0].cElements = 42;       bounds[0].lLbound =  1;
297         bounds[1].cElements =  2;       bounds[1].lLbound = 23;
298     a = SafeArrayCreate(VT_I4,2,bounds);
299     ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
300
301         hres = SafeArrayGetLBound (a, 0, &l);
302         ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %lx\n", hres);
303         hres = SafeArrayGetLBound (a, 1, &l);
304         ok (hres == S_OK, "SAGLB 1 failed with %lx\n", hres);
305         ok (l == 1, "SAGLB 1 returned %ld instead of 1\n", l);
306         hres = SafeArrayGetLBound (a, 2, &l);
307         ok (hres == S_OK, "SAGLB 2 failed with %lx\n", hres);
308         ok (l == 23, "SAGLB 2 returned %ld instead of 23\n", l);
309         hres = SafeArrayGetLBound (a, 3, &l);
310         ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %lx\n", hres);
311
312         hres = SafeArrayGetUBound (a, 0, &l);
313         ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %lx\n", hres);
314         hres = SafeArrayGetUBound (a, 1, &l);
315         ok (hres == S_OK, "SAGUB 1 failed with %lx\n", hres);
316         ok (l == 42, "SAGUB 1 returned %ld instead of 42\n", l);
317         hres = SafeArrayGetUBound (a, 2, &l);
318         ok (hres == S_OK, "SAGUB 2 failed with %lx\n", hres);
319         ok (l == 24, "SAGUB 2 returned %ld instead of 24\n", l);
320         hres = SafeArrayGetUBound (a, 3, &l);
321         ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %lx\n", hres);
322
323         i = SafeArrayGetDim(a);
324         ok(i == 2, "getdims of 2 din array returned %d\n",i);
325
326         indices[0] = 0;
327         indices[1] = 23;
328         hres = SafeArrayGetElement(a, indices, &i);
329         ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%lx\n",hres);
330
331         indices[0] = 1;
332         indices[1] = 22;
333         hres = SafeArrayGetElement(a, indices, &i);
334         ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%lx\n",hres);
335
336         indices[0] = 1;
337         indices[1] = 23;
338         hres = SafeArrayGetElement(a, indices, &i);
339         ok(S_OK == hres,"SAGE failed [1,23], hres 0x%lx\n",hres);
340
341         indices[0] = 1;
342         indices[1] = 25;
343         hres = SafeArrayGetElement(a, indices, &i);
344         ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%lx\n",hres);
345
346         indices[0] = 3;
347         indices[1] = 23;
348         hres = SafeArrayGetElement(a, indices, &i);
349         ok(S_OK == hres,"SAGE failed [42,23], hres 0x%lx\n",hres);
350
351         hres = SafeArrayAccessData(a, (void**)&ptr1);
352         ok(S_OK == hres, "SAAD failed with 0x%lx\n", hres);
353
354         indices[0] = 3;
355         indices[1] = 23;
356         hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
357         ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%lx\n",hres);
358         ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
359
360         indices[0] = 3;
361         indices[1] = 24;
362         hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
363         ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%lx\n",hres);
364         ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
365
366         indices[0] = 20;
367         indices[1] = 23;
368         hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
369         ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%lx\n",hres);
370         ok(ptr2 - ptr1 == 76,"ptr difference is not 76, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
371
372         hres = SafeArrayUnaccessData(a);
373         ok(S_OK == hres, "SAUAD failed with 0x%lx\n", hres);
374
375         for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
376         if ((i == VT_I8 || i == VT_UI8) && HAVE_OLEAUT32_I8)
377         {
378           vttypes[i].elemsize = sizeof(LONG64);
379         }
380
381         a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
382
383         ok((!a && !vttypes[i].elemsize) ||
384            (a && vttypes[i].elemsize == a->cbElements) ||
385            (IS_ANCIENT && (vttypes[i].vt == VT_DECIMAL || vttypes[i].vt == VT_I1 ||
386             vttypes[i].vt == VT_UI2 || vttypes[i].vt == VT_UI4 || vttypes[i].vt == VT_INT ||
387             vttypes[i].vt == VT_UINT)),
388            "SAC(%d,1,[1,0]), %p result %ld, expected %d\n",
389            vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
390
391         if (a)
392         {
393           if (!HAVE_OLEAUT32_RECORD)
394             vttypes[i].expflags = 0;
395           ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
396              "SAC of %d returned feature flags %x, expected %x\n",
397           vttypes[i].vt, a->fFeatures,
398           vttypes[i].expflags|vttypes[i].addflags);
399           ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
400              "SAGE for vt %d returned elemsize %d instead of expected %d\n",
401              vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
402         }
403
404                 if (!a) continue;
405
406         if (pSafeArrayGetVartype)
407         {
408             hres = pSafeArrayGetVartype(a, &vt);
409             ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %lx\n", vttypes[i].vt, hres);
410             if (vttypes[i].vt == VT_DISPATCH) {
411                         /* Special case. Checked against Windows. */
412                         ok(vt == VT_UNKNOWN, "SAGVT of a        rray with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
413             } else {
414                         ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
415             }
416         }
417
418                 hres = SafeArrayCopy(a, &c);
419                 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %lx\n", vttypes[i].vt, hres);
420
421                 ok(vttypes[i].elemsize == c->cbElements,"copy of SAC(%d,1,[1,0]), result %ld, expected %d\n",vttypes[i].vt,(c?c->cbElements:0),vttypes[i].elemsize
422                 );
423                 ok(c->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),"SAC of %d returned feature flags %x, expected %x\n", vttypes[i].vt, c->fFeatures, vttypes[i].expflags|vttypes[i].addflags);
424                 ok(SafeArrayGetElemsize(c) == vttypes[i].elemsize,"SAGE for vt %d returned elemsize %d instead of expected %d\n",vttypes[i].vt, SafeArrayGetElemsize(c),vttypes[i].elemsize);
425
426         if (pSafeArrayGetVartype) {
427             hres = pSafeArrayGetVartype(c, &vt);
428             ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
429             if (vttypes[i].vt == VT_DISPATCH) {
430                 /* Special case. Checked against Windows. */
431                 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
432             } else {
433                 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
434             }
435         }
436
437         if (pSafeArrayCopyData) {
438             hres = pSafeArrayCopyData(a, c);
439             ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %lx\n", vttypes[i].vt, hres);
440
441             hres = SafeArrayDestroyData(c);
442             ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
443         }
444
445                 hres = SafeArrayDestroy(a);
446                 ok(hres == S_OK,"SAD of array with vt %d failed with hres %lx\n", vttypes[i].vt, hres);
447         }
448
449         /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
450         bound.lLbound = 0;
451         bound.cElements = 10;
452         a = SafeArrayCreate(VT_UI1, 1, &bound);
453         ok(a != NULL, "SAC failed.\n");
454         ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
455         memcpy(data,"Hello World\n",10);
456         ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
457         V_VT(&v) = VT_ARRAY|VT_UI1;
458         V_ARRAY(&v) = a;
459         hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
460         ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n",hres);
461         ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.v\n",V_VT(&v));
462         ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
463
464         /* check locking functions */
465         a = SafeArrayCreate(VT_I4, 1, &bound);
466         ok(a!=NULL,"SAC should not fail\n");
467
468         hres = SafeArrayAccessData(a, &data);
469         ok(hres == S_OK,"SAAD failed with hres %lx\n",hres);
470
471         hres = SafeArrayDestroy(a);
472         ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
473
474         hres = SafeArrayDestroyData(a);
475         ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
476
477         hres = SafeArrayDestroyDescriptor(a);
478         ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres);
479
480         hres = SafeArrayUnaccessData(a);
481         ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
482
483         hres = SafeArrayDestroy(a);
484         ok(hres == S_OK,"SAD failed after lock/destroy test\n");
485
486         /* Test if we need to destroy data before descriptor */
487         a = SafeArrayCreate(VT_I4, 1, &bound);
488         ok(a!=NULL,"SAC should not fail\n");
489         hres = SafeArrayDestroyDescriptor(a);
490         ok(hres == S_OK,"SADD with data in array failed with hres %lx\n",hres);
491
492
493         /* IID functions */
494         /* init a small stack safearray */
495     if (pSafeArraySetIID) {
496         memset(&b, 0, sizeof(b));
497         b.cDims = 1;
498         memset(&iid, 0x42, sizeof(IID));
499         hres = pSafeArraySetIID(&b,&iid);
500         ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx\n",hres);
501
502         hres = SafeArrayAllocDescriptor(1,&a);
503         ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
504         hres = pSafeArraySetIID(a,&iid);
505         ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx\n",hres);
506     }
507
508     if (!pSafeArrayAllocDescriptorEx)
509         return;
510
511         for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
512         a = NULL;
513                 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
514                 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
515                 if (a->fFeatures & FADF_HAVEIID) {
516                         hres = pSafeArrayGetIID(a, &iid);
517                         ok(hres == S_OK,"SAGIID failed for vt %d with hres %lx\n", vttypes[i].vt,hres);
518                         switch (vttypes[i].vt) {
519                         case VT_UNKNOWN:
520                                 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
521                                 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
522                                 break;
523                         case VT_DISPATCH:
524                                 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
525                                 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
526                                 break;
527                         default:
528                                 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
529                                 break;
530                         }
531                 } else {
532                         hres = pSafeArrayGetIID(a, &iid);
533                         ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %lx\n", vttypes[i].vt,hres);
534                 }
535                 if (a->fFeatures & FADF_RECORD) {
536                         ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
537                 }
538                 if (a->fFeatures & FADF_HAVEVARTYPE) {
539                         ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld\n",vttypes[i].vt,((DWORD*)a)[-1]);
540                 }
541
542                 hres = pSafeArrayGetVartype(a, &vt);
543                 ok(hres == S_OK, "SAGVT of array with vt %d failed with %lx\n", vttypes[i].vt, hres);
544
545                 if (vttypes[i].vt == VT_DISPATCH) {
546                         /* Special case. Checked against Windows. */
547                         ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
548                 } else {
549                         ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
550                 }
551
552                 if (a->fFeatures & FADF_HAVEIID) {
553                         hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
554                         ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
555                         hres = pSafeArrayGetIID(a, &iid);
556                         ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
557                         ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
558                 } else {
559                         hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
560                         ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx\n", vttypes[i].vt, hres);
561                 }
562                 hres = SafeArrayDestroyDescriptor(a);
563                 ok(hres == S_OK,"SADD failed with hres %lx\n",hres);
564         }
565 }
566
567 static void test_SafeArrayAllocDestroyDescriptor(void)
568 {
569   SAFEARRAY *sa;
570   HRESULT hres;
571   int i;
572
573   /* Failure cases */
574   hres = SafeArrayAllocDescriptor(0, &sa);
575   ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
576
577   hres = SafeArrayAllocDescriptor(65536, &sa);
578   ok(IS_ANCIENT || hres == E_INVALIDARG,
579      "65536 dimensions gave hres 0x%lx\n", hres);
580
581 #if 0
582   /* Crashes on 95: XP & Wine return E_POINTER */
583   hres=SafeArrayAllocDescriptor(1, NULL);
584   ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
585 #endif
586
587   /* Test up to the dimension boundary case */
588   for (i = 5; i <= 65535; i += 30)
589   {
590     hres = SafeArrayAllocDescriptor(i, &sa);
591     ok(hres == S_OK, "%d dimensions failed; hres 0x%lx\n", i, hres);
592
593     if (hres == S_OK)
594     {
595       ok(SafeArrayGetDim(sa) == (UINT)i, "Dimension is %d; should be %d\n",
596          SafeArrayGetDim(sa), i);
597
598       hres = SafeArrayDestroyDescriptor(sa);
599       ok(hres == S_OK, "destroy failed; hres 0x%lx\n", hres);
600     }
601   }
602
603   if (!pSafeArrayAllocDescriptorEx)
604     return;
605
606   hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
607   ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%lx\n", hres);
608
609   hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
610   ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%lx\n", hres);
611
612   hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
613   ok(hres == E_POINTER,"NULL parm gave hres 0x%lx\n", hres);
614 }
615
616 static void test_SafeArrayCreateLockDestroy(void)
617 {
618   SAFEARRAYBOUND sab[4];
619   SAFEARRAY *sa;
620   HRESULT hres;
621   VARTYPE vt;
622   int dimension;
623
624 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
625
626   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
627   {
628     sab[dimension].lLbound = 0;
629     sab[dimension].cElements = 8;
630   }
631
632   /* Failure cases */
633 /* This test crashes very early versions with no error checking...
634   sa = SafeArrayCreate(VT_UI1, 1, NULL);
635   ok(sa == NULL, "NULL bounds didn't fail\n");
636 */
637   sa = SafeArrayCreate(VT_UI1, 65536, sab);
638   ok(IS_ANCIENT || !sa, "Max bounds didn't fail\n");
639
640   memset(sab, 0, sizeof(sab));
641
642   /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
643
644   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
645     sab[dimension].cElements = 8;
646
647   /* Test all VARTYPES in 1-4 dimensions */
648   for (dimension = 1; dimension < 4; dimension++)
649   {
650     for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
651     {
652       DWORD dwLen = SAFEARRAY_GetVTSize(vt);
653
654       sa = SafeArrayCreate(vt, dimension, sab);
655
656       if (dwLen)
657         ok(sa || (IS_ANCIENT && (vt == VT_DECIMAL || vt == VT_I1 || vt == VT_UI2 ||
658            vt == VT_UI4 || vt == VT_INT || vt == VT_UINT || vt == VT_UINT_PTR ||
659            vt == VT_INT_PTR)),
660            "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
661       else
662         ok(sa == NULL || vt == VT_R8,
663            "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
664
665       if (sa)
666       {
667         ok(SafeArrayGetDim(sa) == (UINT)dimension,
668            "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
669            vt, dimension, SafeArrayGetDim(sa), dimension);
670         ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
671            "VARTYPE %d (@%d dimensions) cbElements is %d, expected %ld\n",
672            vt, dimension, SafeArrayGetElemsize(sa), dwLen);
673
674         if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
675         {
676           ok((sa->fFeatures & FADF_HAVEIID) == 0,
677              "Non interface type should not have FADF_HAVEIID\n");
678           if (pSafeArraySetIID)
679           {
680             hres = pSafeArraySetIID(sa, &IID_IUnknown);
681             ok(hres == E_INVALIDARG,
682                "Non interface type allowed SetIID(), hres %lx\n", hres);
683           }
684           if (vt != VT_RECORD)
685           {
686             VARTYPE aVt;
687
688             ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEVARTYPE,
689                "Non interface type should have FADF_HAVEVARTYPE\n");
690             if (pSafeArrayGetVartype)
691             {
692               hres = pSafeArrayGetVartype(sa, &aVt);
693               ok(hres == S_OK && aVt == vt,
694                  "Non interface type %d: bad type %d, hres %lx\n", vt, aVt, hres);
695             }
696           }
697         }
698         else
699         {
700           ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEIID,
701              "Interface type should have FADF_HAVEIID\n");
702           if (pSafeArraySetIID)
703           {
704             hres = pSafeArraySetIID(sa, &IID_IUnknown);
705             ok(hres == S_OK,
706                "Non interface type disallowed SetIID(), hres %lx\n", hres);
707           }
708           ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
709              "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
710         }
711
712         hres = SafeArrayLock(sa);
713         ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%lx\n",
714            vt, dimension, hres);
715
716         if (hres == S_OK)
717         {
718           hres = SafeArrayDestroy(sa);
719           ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %lx\n", hres);
720
721           hres = SafeArrayDestroyData(sa);
722           ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %lx\n", hres);
723
724           hres = SafeArrayDestroyDescriptor(sa);
725           ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %lx\n", hres);
726
727           hres = SafeArrayUnlock(sa);
728           ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%lx\n",
729              vt, dimension, hres);
730
731           hres = SafeArrayDestroyDescriptor(sa);
732           ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%lx\n",
733              vt, dimension, hres);
734         }
735       }
736     }
737   }
738 }
739
740 static void test_VectorCreateLockDestroy(void)
741 {
742   SAFEARRAY *sa;
743   HRESULT hres;
744   VARTYPE vt;
745   int element;
746
747   if (!pSafeArrayCreateVector)
748     return;
749   sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
750   ok(sa != NULL, "SACV with 0 elements failed.\n");
751
752   /* Test all VARTYPES in different lengths */
753   for (element = 1; element <= 101; element += 10)
754   {
755     for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
756     {
757       DWORD dwLen = SAFEARRAY_GetVTSize(vt);
758
759       sa = pSafeArrayCreateVector(vt, 0, element);
760
761       if (dwLen)
762       {
763         /* win2000 has a bug where U/INT_PTR aren't accepted */
764         ok(sa != NULL || vt == VT_INT_PTR || vt == VT_UINT_PTR,
765            "VARTYPE %d (@%d elements) failed\n", vt, element);
766       }
767       else
768         ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
769
770       if (sa)
771       {
772         ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
773            vt, element, SafeArrayGetDim(sa));
774         ok(SafeArrayGetElemsize(sa) == dwLen,
775            "VARTYPE %d (@%d elements) cbElements is %d, expected %ld\n",
776            vt, element, SafeArrayGetElemsize(sa), dwLen);
777
778         hres = SafeArrayLock(sa);
779         ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
780            vt, element, hres);
781
782         if (hres == S_OK)
783         {
784           hres = SafeArrayUnlock(sa);
785           ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
786              vt, element, hres);
787
788           hres = SafeArrayDestroyDescriptor(sa);
789           ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
790              vt, element, hres);
791         }
792       }
793     }
794   }
795 }
796
797 static void test_LockUnlock(void)
798 {
799   SAFEARRAYBOUND sab[4];
800   SAFEARRAY *sa;
801   HRESULT hres;
802   BOOL bVector = FALSE;
803   int dimension;
804
805   /* Failure cases */
806   hres = SafeArrayLock(NULL);
807   ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
808   hres = SafeArrayUnlock(NULL);
809   ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%lx\n", hres);
810
811   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
812   {
813     sab[dimension].lLbound = 0;
814     sab[dimension].cElements = 8;
815   }
816
817   sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
818
819   /* Test maximum locks */
820 test_LockUnlock_Vector:
821   if (sa)
822   {
823     int count = 0;
824
825     hres = SafeArrayUnlock(sa);
826     ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%lx\n",
827         bVector ? "vector " : "\n", hres);
828
829     while ((hres = SafeArrayLock(sa)) == S_OK)
830       count++;
831     ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%lx\n",
832         bVector ? "vector " : "\n", count, hres);
833
834     if (count == 65535 && hres == E_UNEXPECTED)
835     {
836       while ((hres = SafeArrayUnlock(sa)) == S_OK)
837         count--;
838       ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%lx\n",
839           bVector ? "vector " : "\n", count, hres);
840     }
841
842     SafeArrayDestroy(sa);
843   }
844
845   if (bVector == FALSE && pSafeArrayCreateVector)
846   {
847     /* Test again with a vector */
848     sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
849     bVector = TRUE;
850     goto test_LockUnlock_Vector;
851   }
852 }
853
854 static void test_SafeArrayGetPutElement(void)
855 {
856   SAFEARRAYBOUND sab[4];
857   LONG indices[NUM_DIMENSIONS];
858   SAFEARRAY *sa;
859   HRESULT hres;
860   int value = 0, gotvalue, dimension;
861   unsigned int x,y,z,a;
862
863   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
864   {
865     sab[dimension].lLbound = dimension * 2 + 1;
866     sab[dimension].cElements = dimension * 3 + 1;
867   }
868
869   sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
870   if (!sa)
871     return; /* Some early versions can't handle > 3 dims */
872
873   ok(sa->cbElements == sizeof(value), "int size mismatch\n");
874   if (sa->cbElements != sizeof(value))
875     return;
876
877   /* Failure cases */
878   for (x = 0; x < NUM_DIMENSIONS; x++)
879   {
880     indices[0] = sab[0].lLbound;
881     indices[1] = sab[1].lLbound;
882     indices[2] = sab[2].lLbound;
883     indices[3] = sab[3].lLbound;
884
885     indices[x] = indices[x] - 1;
886     hres = SafeArrayPutElement(sa, indices, &value);
887     ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
888     hres = SafeArrayGetElement(sa, indices, &value);
889     ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
890
891     indices[x] = sab[x].lLbound + sab[x].cElements;
892     hres = SafeArrayPutElement(sa, indices, &value);
893     ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
894     hres = SafeArrayGetElement(sa, indices, &value);
895     ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
896   }
897
898   indices[0] = sab[0].lLbound;
899   indices[1] = sab[1].lLbound;
900   indices[2] = sab[2].lLbound;
901   indices[3] = sab[3].lLbound;
902
903   hres = SafeArrayPutElement(NULL, indices, &value);
904   ok(hres == E_INVALIDARG, "Put NULL array hres 0x%lx\n", hres);
905   hres = SafeArrayGetElement(NULL, indices, &value);
906   ok(hres == E_INVALIDARG, "Get NULL array hres 0x%lx\n", hres);
907
908   hres = SafeArrayPutElement(sa, NULL, &value);
909   ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%lx\n", hres);
910   hres = SafeArrayGetElement(sa, NULL, &value);
911   ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%lx\n", hres);
912
913 #if 0
914   /* This is retarded. Windows checks every case of invalid parameters
915    * except the following, which crashes. We ERR this in Wine.
916    */
917   hres = SafeArrayPutElement(sa, indices, NULL);
918   ok(hres == E_INVALIDARG, "Put NULL value hres 0x%lx\n", hres);
919 #endif
920
921   hres = SafeArrayGetElement(sa, indices, NULL);
922   ok(hres == E_INVALIDARG, "Get NULL value hres 0x%lx\n", hres);
923
924   value = 0;
925
926   /* Make sure we can read and get back the correct values in 4 dimensions,
927    * Each with a different size and lower bound.
928    */
929   for (x = 0; x < sab[0].cElements; x++)
930   {
931     indices[0] = sab[0].lLbound + x;
932     for (y = 0; y < sab[1].cElements; y++)
933     {
934       indices[1] = sab[1].lLbound + y;
935       for (z = 0; z < sab[2].cElements; z++)
936       {
937         indices[2] = sab[2].lLbound + z;
938         for (a = 0; a < sab[3].cElements; a++)
939         {
940           indices[3] = sab[3].lLbound + a;
941           hres = SafeArrayPutElement(sa, indices, &value);
942           ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%lx\n",
943              x, y, z, a, hres);
944           value++;
945         }
946       }
947     }
948   }
949
950   value = 0;
951
952   for (x = 0; x < sab[0].cElements; x++)
953   {
954     indices[0] = sab[0].lLbound + x;
955     for (y = 0; y < sab[1].cElements; y++)
956     {
957       indices[1] = sab[1].lLbound + y;
958       for (z = 0; z < sab[2].cElements; z++)
959       {
960         indices[2] = sab[2].lLbound + z;
961         for (a = 0; a < sab[3].cElements; a++)
962         {
963           indices[3] = sab[3].lLbound + a;
964           gotvalue = value / 3;
965           hres = SafeArrayGetElement(sa, indices, &gotvalue);
966           ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%lx\n",
967              x, y, z, a, hres);
968           if (hres == S_OK)
969             ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
970                gotvalue, value, x, y, z, a);
971           value++;
972         }
973       }
974     }
975   }
976   SafeArrayDestroy(sa);
977 }
978
979 static void test_SafeArrayGetPutElement_BSTR(void)
980 {
981   SAFEARRAYBOUND sab;
982   LONG indices[1];
983   SAFEARRAY *sa;
984   HRESULT hres;
985   BSTR value = 0, gotvalue;
986   const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
987
988   sab.lLbound = 1;
989   sab.cElements = 1;
990
991   sa = SafeArrayCreate(VT_BSTR, 1, &sab);
992   ok(sa != NULL, "BSTR test couldn't create array\n");
993   if (!sa)
994     return;
995
996   ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
997   if (sa->cbElements != sizeof(BSTR))
998     return;
999
1000   indices[0] = sab.lLbound;
1001   value = SysAllocString(szTest);
1002   ok (value != NULL, "Expected non-NULL\n");
1003   hres = SafeArrayPutElement(sa, indices, value);
1004   ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1005   gotvalue = NULL;
1006   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1007   ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1008   if (hres == S_OK)
1009     ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1010   SafeArrayDestroy(sa);
1011 }
1012
1013 static int tunk_xref = 0;
1014 static HRESULT WINAPI tunk_QueryInterface(LPUNKNOWN punk,REFIID riid, LPVOID *x) {
1015         return E_FAIL;
1016 }
1017 static ULONG WINAPI tunk_AddRef(LPUNKNOWN punk) {
1018         return ++tunk_xref;
1019 }
1020
1021 static ULONG WINAPI tunk_Release(LPUNKNOWN punk) {
1022         return --tunk_xref;
1023 }
1024
1025 static ICOM_VTABLE(IUnknown) xtunk_vtbl = {
1026         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1027         tunk_QueryInterface,
1028         tunk_AddRef,
1029         tunk_Release
1030 };
1031
1032 static struct xtunk_iface {
1033         ICOM_VTABLE(IUnknown)   *lpvtbl;
1034 } xtunk_iface;
1035
1036
1037 static void test_SafeArrayGetPutElement_IUnknown(void)
1038 {
1039   SAFEARRAYBOUND sab;
1040   LONG indices[1];
1041   SAFEARRAY *sa;
1042   HRESULT hres;
1043   LPUNKNOWN value = 0, gotvalue;
1044
1045   sab.lLbound = 1;
1046   sab.cElements = 1;
1047   sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1048   ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1049   if (!sa)
1050     return;
1051
1052   ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1053   if (sa->cbElements != sizeof(LPUNKNOWN))
1054     return;
1055
1056   indices[0] = sab.lLbound;
1057   xtunk_iface.lpvtbl = &xtunk_vtbl;
1058   value = (LPUNKNOWN)&xtunk_iface;
1059   tunk_xref = 1;
1060   ok (value != NULL, "Expected non-NULL\n");
1061   hres = SafeArrayPutElement(sa, indices, value);
1062   ok(hres == S_OK, "Failed to put bstr element hres 0x%lx\n", hres);
1063   ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1064   gotvalue = NULL;
1065   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1066   ok(tunk_xref == 3,"Failed to increment refcount of iface.\n");
1067   ok(hres == S_OK, "Failed to get bstr element at hres 0x%lx\n", hres);
1068   if (hres == S_OK)
1069     ok(value == gotvalue, "Got %p instead of %p\n", gotvalue, value);
1070   SafeArrayDestroy(sa);
1071   ok(tunk_xref == 2,"Failed to decrement refcount of iface.\n");
1072 }
1073
1074 static void test_SafeArrayCopyData(void)
1075 {
1076   SAFEARRAYBOUND sab[4];
1077   SAFEARRAY *sa;
1078   SAFEARRAY *sacopy;
1079   HRESULT hres;
1080   int dimension,size=1;
1081
1082   if (!pSafeArrayCopyData)
1083     return;
1084
1085   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1086   {
1087     sab[dimension].lLbound = dimension * 2 + 2;
1088     sab[dimension].cElements = dimension * 3 + 1;
1089     size *= sab[dimension].cElements;
1090   }
1091
1092   sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1093   ok(sa != NULL, "Copy test couldn't create array\n");
1094   sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1095   ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1096
1097   if (!sa || !sacopy)
1098     return;
1099
1100   ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1101   if (sa->cbElements != sizeof(int))
1102     return;
1103
1104   /* Fill the source array with some data; it doesn't matter what */
1105   for (dimension = 0; dimension < size; dimension++)
1106   {
1107     int* data = (int*)sa->pvData;
1108     data[dimension] = dimension;
1109   }
1110
1111   hres = pSafeArrayCopyData(sa, sacopy);
1112   ok(hres == S_OK, "copy data failed hres 0x%lx\n", hres);
1113   if (hres == S_OK)
1114   {
1115     ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1116   }
1117
1118   /* Failure cases */
1119   hres = pSafeArrayCopyData(NULL, sacopy);
1120   ok(hres == E_INVALIDARG, "Null copy source hres 0x%lx\n", hres);
1121   hres = pSafeArrayCopyData(sa, NULL);
1122   ok(hres == E_INVALIDARG, "Null copy hres 0x%lx\n", hres);
1123
1124   sacopy->rgsabound[0].cElements += 1;
1125   hres = pSafeArrayCopyData(sa, sacopy);
1126   ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%lx\n", hres);
1127
1128   sacopy->rgsabound[0].cElements -= 2;
1129   hres = pSafeArrayCopyData(sa, sacopy);
1130   ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%lx\n", hres);
1131   sacopy->rgsabound[0].cElements += 1;
1132
1133   sacopy->rgsabound[3].cElements += 1;
1134   hres = pSafeArrayCopyData(sa, sacopy);
1135   ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%lx\n", hres);
1136
1137   sacopy->rgsabound[3].cElements -= 2;
1138   hres = pSafeArrayCopyData(sa, sacopy);
1139   ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%lx\n", hres);
1140   sacopy->rgsabound[3].cElements += 1;
1141
1142   SafeArrayDestroy(sacopy);
1143   sacopy = NULL;
1144   hres = pSafeArrayCopyData(sa, sacopy);
1145   ok(hres == E_INVALIDARG, "->Null copy hres 0x%lx\n", hres);
1146
1147   hres = SafeArrayCopy(sa, &sacopy);
1148   ok(hres == S_OK, "copy failed hres 0x%lx\n", hres);
1149   if (hres == S_OK)
1150   {
1151     ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1152     ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1153     ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1154   }
1155
1156   SafeArrayDestroy(sa);
1157 }
1158
1159 static void test_SafeArrayCreateEx(void)
1160 {
1161   IRecordInfoImpl* iRec;
1162   SAFEARRAYBOUND sab[4];
1163   SAFEARRAY *sa;
1164   HRESULT hres;
1165   int dimension;
1166
1167   if (!pSafeArrayCreateEx)
1168     return;
1169
1170   for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1171   {
1172     sab[dimension].lLbound = 0;
1173     sab[dimension].cElements = 8;
1174   }
1175
1176   /* Failure cases */
1177   sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1178   ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1179
1180   /* test IID storage & defaulting */
1181   sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1182   ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1183
1184   if (sa)
1185   {
1186     GUID guid;
1187     if (pSafeArrayGetIID)
1188     {
1189       hres = pSafeArrayGetIID(sa, &guid);
1190       ok(hres == S_OK, "CreateEx (ITypeInfo) no IID hres 0x%lx\n", hres);
1191       if (hres == S_OK)
1192       {
1193         ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1194       }
1195     }
1196     if (pSafeArraySetIID)
1197     {
1198       hres = pSafeArraySetIID(sa, &IID_IUnknown);
1199       ok(hres == S_OK, "Failed to set IID, hres = %8lx\n", hres);
1200       if (hres == S_OK && pSafeArrayGetIID)
1201       {
1202         hres = pSafeArrayGetIID(sa, &guid);
1203         ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1204       }
1205     }
1206     SafeArrayDestroy(sa);
1207   }
1208
1209   sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1210   ok(sa != NULL, "CreateEx (NULL) failed\n");
1211
1212   if (sa)
1213   {
1214     GUID guid;
1215     if (pSafeArrayGetIID)
1216     {
1217       hres = pSafeArrayGetIID(sa, &guid);
1218       ok(hres == S_OK, "CreateEx (NULL) no IID hres 0x%lx\n", hres);
1219       if (hres == S_OK)
1220       {
1221         ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1222       }
1223     }
1224     SafeArrayDestroy(sa);
1225   }
1226
1227   sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1228   ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1229
1230   if (sa)
1231   {
1232     GUID guid;
1233     if (pSafeArrayGetIID)
1234     {
1235       hres = pSafeArrayGetIID(sa, &guid);
1236       ok(hres == S_OK, "CreateEx (NULL-Unk) no IID hres 0x%lx\n", hres);
1237       if (hres == S_OK)
1238       {
1239         ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1240       }
1241     }
1242     SafeArrayDestroy(sa);
1243   }
1244
1245   /* VT_RECORD failure case */
1246   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1247   ok(sa == NULL, "CreateEx (NULL-Rec) succeded\n");
1248
1249   iRec = IRecordInfoImpl_Construct();
1250
1251   /* Win32 doesn't care if GetSize fails */
1252   fail_GetSize = TRUE;
1253   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1254   ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1255   ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1256   ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1257   ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1258   if (sa)
1259   {
1260     ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %ld\n", sa->cbElements);
1261     SafeArrayDestroy(sa);
1262     ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1263   }
1264
1265   /* Test VT_RECORD array */
1266   fail_GetSize = FALSE;
1267   iRec->ref = START_REF_COUNT;
1268   iRec->sizeCalled = 0;
1269   iRec->clearCalled = 0;
1270   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1271   ok(sa != NULL, "CreateEx (Rec) failed\n");
1272   ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %ld\n", iRec->ref);
1273   ok(iRec->sizeCalled == 1, "GetSize called %ld times\n", iRec->sizeCalled);
1274   ok(iRec->clearCalled == 0, "Clear called %ld times\n", iRec->clearCalled);
1275   if (sa && pSafeArrayGetRecordInfo)
1276   {
1277     IRecordInfo* saRec = NULL;
1278     hres = pSafeArrayGetRecordInfo(sa, &saRec);
1279
1280     ok(hres == S_OK,"GRI failed\n");
1281     ok(saRec == (IRecordInfo*)iRec,"Different saRec\n");
1282     ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %ld\n", iRec->ref);
1283     if (iRec->ref == START_REF_COUNT + 2)
1284       IRecordInfo_Release(saRec);
1285
1286     ok(sa->cbElements == RECORD_SIZE,"Elemsize is %ld\n", sa->cbElements);
1287
1288     SafeArrayDestroy(sa);
1289     ok(iRec->sizeCalled == 1, "Destroy->GetSize called %ld times\n", iRec->sizeCalled);
1290     ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %ld times\n", iRec->clearCalled);
1291     ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %ld\n", iRec->ref);
1292   }
1293 }
1294
1295 static void test_SafeArrayClear(void)
1296 {
1297   SAFEARRAYBOUND sab;
1298   SAFEARRAY *sa;
1299   VARIANTARG v;
1300   HRESULT hres;
1301
1302   sab.lLbound = 0;
1303   sab.cElements = 10;
1304   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1305   ok(sa != NULL, "Create() failed.\n");
1306   if (!sa)
1307     return;
1308
1309   /* Test clearing non-NULL variants containing arrays */
1310   V_VT(&v) = VT_ARRAY|VT_UI1;
1311   V_ARRAY(&v) = sa;
1312   hres = VariantClear(&v);
1313   ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%lx, Type %d\n", hres, V_VT(&v));
1314   ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1315
1316   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1317   ok(sa != NULL, "Create() failed.\n");
1318   if (!sa)
1319     return;
1320
1321   V_VT(&v) = VT_SAFEARRAY;
1322   V_ARRAY(&v) = sa;
1323   hres = VariantClear(&v);
1324   ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1325
1326   V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1327   V_ARRAYREF(&v) = &sa;
1328   hres = VariantClear(&v);
1329   ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%lx\n", hres);
1330
1331   SafeArrayDestroy(sa);
1332 }
1333
1334 static void test_SafeArrayCopy(void)
1335 {
1336   SAFEARRAYBOUND sab;
1337   SAFEARRAY *sa;
1338   VARIANTARG vSrc, vDst;
1339   HRESULT hres;
1340
1341   sab.lLbound = 0;
1342   sab.cElements = 10;
1343   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1344   ok(sa != NULL, "Create() failed.\n");
1345   if (!sa)
1346     return;
1347
1348   /* Test copying non-NULL variants containing arrays */
1349   V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1350   V_ARRAYREF(&vSrc) = &sa;
1351   V_VT(&vDst) = VT_EMPTY;
1352
1353   hres = VariantCopy(&vDst, &vSrc);
1354   ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1355      "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1356   ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1357
1358   V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1359   V_ARRAY(&vSrc) = sa;
1360   V_VT(&vDst) = VT_EMPTY;
1361
1362   hres = VariantCopy(&vDst, &vSrc);
1363   ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1364      "VariantCopy: hres 0x%lx, Type %d\n", hres, V_VT(&vDst));
1365   ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1366
1367   SafeArrayDestroy(V_ARRAY(&vSrc));
1368   SafeArrayDestroy(V_ARRAY(&vDst));
1369 }
1370
1371 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1372   sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1373   if (!sa) return; \
1374   V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1375
1376 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1377   sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1378   V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1379
1380 static void test_SafeArrayChangeTypeEx(void)
1381 {
1382   static const char *szHello = "Hello World";
1383   SAFEARRAYBOUND sab;
1384   SAFEARRAY *sa;
1385   VARIANTARG v,v2;
1386   VARTYPE vt;
1387   HRESULT hres;
1388
1389   /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1390   MKARRAY(0,strlen(szHello)+1,VT_UI1);
1391   memcpy(sa->pvData, szHello, strlen(szHello)+1);
1392
1393   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1394   ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1395   if (hres == S_OK)
1396   {
1397     ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1398     ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1399        (char*)V_BSTR(&v2));
1400     VariantClear(&v2);
1401   }
1402
1403   /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1404   SafeArrayDestroy(sa);
1405   if (pSafeArrayCreateVector)
1406   {
1407     sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1408     ok(sa != NULL, "CreateVector() failed.\n");
1409     if (!sa)
1410       return;
1411
1412     memcpy(sa->pvData, szHello, strlen(szHello)+1);
1413     V_VT(&v) = VT_VECTOR|VT_UI1;
1414     V_ARRAY(&v) = sa;
1415     VariantInit(&v2);
1416
1417     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1418     ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %lx\n", hres);
1419
1420     /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1421     V_VT(&v) = VT_ARRAY|VT_UI1;
1422     hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1423     ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres);
1424     if (hres == S_OK)
1425     {
1426       ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1427       ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1428               (char*)V_BSTR(&v));
1429       VariantClear(&v);
1430     }
1431   }
1432
1433   /* To/from BSTR only works with arrays of VT_UI1 */
1434   for (vt = 0; vt <= VT_CLSID; vt++)
1435   {
1436     if (vt == VT_UI1)
1437       continue;
1438
1439     MKARRAYCONT(0,1,vt);
1440     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1441     ok(hres != S_OK, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt);
1442     VariantClear(&v2);
1443   }
1444
1445   /* Can't change an array of one type into array of another type , even
1446    * if the other type is the same size
1447    */
1448   if (pSafeArrayCreateVector)
1449   {
1450     sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1451     ok(sa != NULL, "CreateVector() failed.\n");
1452     if (!sa)
1453       return;
1454
1455     V_VT(&v) = VT_ARRAY|VT_UI1;
1456     V_ARRAY(&v) = sa;
1457     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1458     ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %lx\n", hres);
1459
1460     /* But can change to the same array type */
1461     SafeArrayDestroy(sa);
1462     sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1463     ok(sa != NULL, "CreateVector() failed.\n");
1464     if (!sa)
1465       return;
1466     V_VT(&v) = VT_ARRAY|VT_UI1;
1467     V_ARRAY(&v) = sa;
1468     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1469     ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %lx\n", hres);
1470   }
1471
1472   /* NULL/EMPTY */
1473   MKARRAY(0,1,VT_UI1);
1474   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1475   ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1476   MKARRAY(0,1,VT_UI1);
1477   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1478   ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres);
1479
1480 }
1481
1482 START_TEST(safearray)
1483 {
1484     hOleaut32 = LoadLibraryA("oleaut32.dll");
1485
1486     GETPTR(SafeArrayAllocDescriptorEx);
1487     GETPTR(SafeArrayCopyData);
1488     GETPTR(SafeArrayGetIID);
1489     GETPTR(SafeArraySetIID);
1490     GETPTR(SafeArrayGetVartype);
1491     GETPTR(SafeArrayCreateEx);
1492     GETPTR(SafeArrayCreateVector);
1493
1494     test_safearray();
1495     test_SafeArrayAllocDestroyDescriptor();
1496     test_SafeArrayCreateLockDestroy();
1497     test_VectorCreateLockDestroy();
1498     test_LockUnlock();
1499     test_SafeArrayChangeTypeEx();
1500     test_SafeArrayCopy();
1501     test_SafeArrayClear();
1502     test_SafeArrayCreateEx();
1503     test_SafeArrayCopyData();
1504     test_SafeArrayGetPutElement();
1505     test_SafeArrayGetPutElement_BSTR();
1506     test_SafeArrayGetPutElement_IUnknown();
1507 }