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