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