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