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