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