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