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