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