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