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