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 < ARRAY_SIZE(vttypes); 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 < ARRAY_SIZE(vttypes); 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   UINT 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) == 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   UINT dimension;
832 
833   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
834   {
835     sab[dimension].lLbound = 0;
836     sab[dimension].cElements = 8;
837   }
838 
839   /* Failure cases */
840 /* This test crashes very early versions with no error checking...
841   sa = SafeArrayCreate(VT_UI1, 1, NULL);
842   ok(sa == NULL, "NULL bounds didn't fail\n");
843 */
844   sa = SafeArrayCreate(VT_UI1, 65536, sab);
845   ok(!sa, "Max bounds didn't fail\n");
846 
847   memset(sab, 0, sizeof(sab));
848 
849   /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
850 
851   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
852     sab[dimension].cElements = 8;
853 
854   /* Test all VARTYPES in 1-4 dimensions */
855   for (dimension = 1; dimension < 4; dimension++)
856   {
857     for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
858     {
859       DWORD dwLen = SAFEARRAY_GetVTSize(vt);
860 
861       sa = SafeArrayCreate(vt, dimension, sab);
862 
863       if (dwLen)
864         ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
865       else
866         ok(sa == NULL || vt == VT_R8,
867            "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
868 
869       if (sa)
870       {
871         ok(SafeArrayGetDim(sa) == dimension,
872            "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
873            vt, dimension, SafeArrayGetDim(sa), dimension);
874         ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
875            "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
876            vt, dimension, SafeArrayGetElemsize(sa), dwLen);
877 
878         if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
879         {
880           ok((sa->fFeatures & FADF_HAVEIID) == 0,
881              "Non interface type should not have FADF_HAVEIID\n");
882           hres = SafeArraySetIID(sa, &IID_IUnknown);
883           ok(hres == E_INVALIDARG, "Unexpected ret value %#x.\n", hres);
884           if (vt != VT_RECORD)
885           {
886             VARTYPE aVt;
887 
888             ok(sa->fFeatures & FADF_HAVEVARTYPE,
889                "Non interface type should have FADF_HAVEVARTYPE\n");
890             if (pSafeArrayGetVartype)
891             {
892               hres = pSafeArrayGetVartype(sa, &aVt);
893               ok(hres == S_OK && aVt == vt,
894                  "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres);
895             }
896           }
897         }
898         else
899         {
900           ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n");
901           hres = SafeArraySetIID(sa, &IID_IUnknown);
902           ok(hres == S_OK, "Failed to set array IID, hres %#x.\n", hres);
903           ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
904              "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
905         }
906 
907         hres = SafeArrayLock(sa);
908         ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
909            vt, dimension, hres);
910 
911         if (hres == S_OK)
912         {
913           hres = SafeArrayDestroy(sa);
914           ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres);
915 
916           hres = SafeArrayDestroyData(sa);
917           ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres);
918 
919           hres = SafeArrayDestroyDescriptor(sa);
920           ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres);
921 
922           hres = SafeArrayUnlock(sa);
923           ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
924              vt, dimension, hres);
925 
926           hres = SafeArrayDestroy(sa);
927           ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
928              vt, dimension, hres);
929         }
930       }
931     }
932   }
933 }
934 
935 static void test_VectorCreateLockDestroy(void)
936 {
937   SAFEARRAY *sa;
938   HRESULT hres;
939   VARTYPE vt;
940   int element;
941 
942   if (!pSafeArrayCreateVector)
943   {
944     win_skip("SafeArrayCreateVector not supported\n");
945     return;
946   }
947   sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
948   ok(sa != NULL, "SACV with 0 elements failed.\n");
949 
950   hres = SafeArrayDestroy(sa);
951   ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres);
952 
953   /* Test all VARTYPES in different lengths */
954   for (element = 1; element <= 101; element += 10)
955   {
956     for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
957     {
958       DWORD dwLen = SAFEARRAY_GetVTSize(vt);
959 
960       sa = pSafeArrayCreateVector(vt, 0, element);
961 
962       if (dwLen)
963         ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element);
964       else
965         ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
966 
967       if (sa)
968       {
969         ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
970            vt, element, SafeArrayGetDim(sa));
971         ok(SafeArrayGetElemsize(sa) == dwLen,
972            "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
973            vt, element, SafeArrayGetElemsize(sa), dwLen);
974 
975         hres = SafeArrayLock(sa);
976         ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
977            vt, element, hres);
978 
979         if (hres == S_OK)
980         {
981           hres = SafeArrayUnlock(sa);
982           ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
983              vt, element, hres);
984 
985           hres = SafeArrayDestroy(sa);
986           ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
987              vt, element, hres);
988         }
989       }
990     }
991   }
992 }
993 
994 static void test_LockUnlock(void)
995 {
996   SAFEARRAYBOUND sab[4];
997   SAFEARRAY *sa;
998   HRESULT hres;
999   BOOL bVector = FALSE;
1000   int dimension;
1001 
1002   /* Failure cases */
1003   hres = SafeArrayLock(NULL);
1004   ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1005   hres = SafeArrayUnlock(NULL);
1006   ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
1007 
1008   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1009   {
1010     sab[dimension].lLbound = 0;
1011     sab[dimension].cElements = 8;
1012   }
1013 
1014   sa = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1015 
1016   /* Test maximum locks */
1017 test_LockUnlock_Vector:
1018   if (sa)
1019   {
1020     int count = 0;
1021 
1022     hres = SafeArrayUnlock(sa);
1023     ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n",
1024         bVector ? "vector " : "\n", hres);
1025 
1026     while ((hres = SafeArrayLock(sa)) == S_OK)
1027       count++;
1028     ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n",
1029         bVector ? "vector " : "\n", count, hres);
1030 
1031     if (count == 65535 && hres == E_UNEXPECTED)
1032     {
1033       while ((hres = SafeArrayUnlock(sa)) == S_OK)
1034         count--;
1035       ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n",
1036           bVector ? "vector " : "\n", count, hres);
1037     }
1038 
1039     hres = SafeArrayDestroy(sa);
1040     ok(hres == S_OK, "got 0x%08x\n", hres);
1041   }
1042 
1043   if (bVector == FALSE && pSafeArrayCreateVector)
1044   {
1045     /* Test again with a vector */
1046     sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
1047     bVector = TRUE;
1048     goto test_LockUnlock_Vector;
1049   }
1050 }
1051 
1052 static void test_SafeArrayGetPutElement(void)
1053 {
1054   SAFEARRAYBOUND sab[4];
1055   LONG indices[ARRAY_SIZE(sab)], index;
1056   SAFEARRAY *sa;
1057   HRESULT hres;
1058   int value = 0, gotvalue, dimension;
1059   IRecordInfoImpl *irec;
1060   unsigned int x,y,z,a;
1061 
1062   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1063   {
1064     sab[dimension].lLbound = dimension * 2 + 1;
1065     sab[dimension].cElements = dimension * 3 + 1;
1066   }
1067 
1068   sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1069   if (!sa)
1070     return; /* Some early versions can't handle > 3 dims */
1071 
1072   ok(sa->cbElements == sizeof(value), "int size mismatch\n");
1073 
1074   /* Failure cases */
1075   for (x = 0; x < ARRAY_SIZE(sab); x++)
1076   {
1077     indices[0] = sab[0].lLbound;
1078     indices[1] = sab[1].lLbound;
1079     indices[2] = sab[2].lLbound;
1080     indices[3] = sab[3].lLbound;
1081 
1082     indices[x] = indices[x] - 1;
1083     hres = SafeArrayPutElement(sa, indices, &value);
1084     ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
1085     hres = SafeArrayGetElement(sa, indices, &value);
1086     ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
1087 
1088     indices[x] = sab[x].lLbound + sab[x].cElements;
1089     hres = SafeArrayPutElement(sa, indices, &value);
1090     ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
1091     hres = SafeArrayGetElement(sa, indices, &value);
1092     ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
1093   }
1094 
1095   indices[0] = sab[0].lLbound;
1096   indices[1] = sab[1].lLbound;
1097   indices[2] = sab[2].lLbound;
1098   indices[3] = sab[3].lLbound;
1099 
1100   hres = SafeArrayPutElement(NULL, indices, &value);
1101   ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres);
1102   hres = SafeArrayGetElement(NULL, indices, &value);
1103   ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres);
1104 
1105   hres = SafeArrayPutElement(sa, NULL, &value);
1106   ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres);
1107   hres = SafeArrayGetElement(sa, NULL, &value);
1108   ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres);
1109 
1110   if (0)
1111   {
1112   /* This is retarded. Windows checks every case of invalid parameters
1113    * except the following, which crashes. We ERR this in Wine.
1114    */
1115   hres = SafeArrayPutElement(sa, indices, NULL);
1116   ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres);
1117   }
1118 
1119   hres = SafeArrayGetElement(sa, indices, NULL);
1120   ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres);
1121 
1122   value = 0;
1123 
1124   /* Make sure we can read and get back the correct values in 4 dimensions,
1125    * Each with a different size and lower bound.
1126    */
1127   for (x = 0; x < sab[0].cElements; x++)
1128   {
1129     indices[0] = sab[0].lLbound + x;
1130     for (y = 0; y < sab[1].cElements; y++)
1131     {
1132       indices[1] = sab[1].lLbound + y;
1133       for (z = 0; z < sab[2].cElements; z++)
1134       {
1135         indices[2] = sab[2].lLbound + z;
1136         for (a = 0; a < sab[3].cElements; a++)
1137         {
1138           indices[3] = sab[3].lLbound + a;
1139           hres = SafeArrayPutElement(sa, indices, &value);
1140           ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1141              x, y, z, a, hres);
1142           value++;
1143         }
1144       }
1145     }
1146   }
1147 
1148   value = 0;
1149 
1150   for (x = 0; x < sab[0].cElements; x++)
1151   {
1152     indices[0] = sab[0].lLbound + x;
1153     for (y = 0; y < sab[1].cElements; y++)
1154     {
1155       indices[1] = sab[1].lLbound + y;
1156       for (z = 0; z < sab[2].cElements; z++)
1157       {
1158         indices[2] = sab[2].lLbound + z;
1159         for (a = 0; a < sab[3].cElements; a++)
1160         {
1161           indices[3] = sab[3].lLbound + a;
1162           gotvalue = value / 3;
1163           hres = SafeArrayGetElement(sa, indices, &gotvalue);
1164           ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1165              x, y, z, a, hres);
1166           if (hres == S_OK)
1167             ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1168                gotvalue, value, x, y, z, a);
1169           value++;
1170         }
1171       }
1172     }
1173   }
1174   hres = SafeArrayDestroy(sa);
1175   ok(hres == S_OK, "got 0x%08x\n", hres);
1176 
1177   /* VT_RECORD array */
1178   irec = IRecordInfoImpl_Construct();
1179   irec->ref = 1;
1180 
1181   sab[0].lLbound = 0;
1182   sab[0].cElements = 8;
1183 
1184   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface);
1185   ok(sa != NULL, "failed to create array\n");
1186   ok(irec->ref == 2, "got %d\n", irec->ref);
1187 
1188   index = 0;
1189   irec->recordcopy = 0;
1190   hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef);
1191   ok(hres == S_OK, "got 0x%08x\n", hres);
1192   ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1193 
1194   index = 0;
1195   irec->recordcopy = 0;
1196   hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef);
1197   ok(hres == S_OK, "got 0x%08x\n", hres);
1198   ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
1199 
1200   hres = SafeArrayDestroy(sa);
1201   ok(hres == S_OK, "got 0x%08x\n", hres);
1202   ok(irec->ref == 1, "got %d\n", irec->ref);
1203   IRecordInfo_Release(&irec->IRecordInfo_iface);
1204 }
1205 
1206 static void test_SafeArrayGetPutElement_BSTR(void)
1207 {
1208   SAFEARRAYBOUND sab;
1209   LONG indices[1];
1210   SAFEARRAY *sa;
1211   HRESULT hres;
1212   BSTR value = 0, gotvalue;
1213   const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1214 
1215   sab.lLbound = 1;
1216   sab.cElements = 1;
1217 
1218   sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1219   ok(sa != NULL, "BSTR test couldn't create array\n");
1220   if (!sa)
1221     return;
1222 
1223   ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1224 
1225   indices[0] = sab.lLbound;
1226   value = SysAllocString(szTest);
1227   ok (value != NULL, "Expected non-NULL\n");
1228   hres = SafeArrayPutElement(sa, indices, value);
1229   ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1230   gotvalue = NULL;
1231   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1232   ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1233   if (hres == S_OK)
1234     ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1235   hres = SafeArrayDestroy(sa);
1236   ok(hres == S_OK, "got 0x%08x\n", hres);
1237   SysFreeString(value);
1238   SysFreeString(gotvalue);
1239 }
1240 
1241 struct xtunk_impl {
1242   IUnknown IUnknown_iface;
1243   LONG ref;
1244 };
1245 static const IUnknownVtbl xtunk_vtbl;
1246 
1247 static struct xtunk_impl xtunk = {{&xtunk_vtbl}, 0};
1248 
1249 static HRESULT WINAPI tunk_QueryInterface(IUnknown *punk, REFIID riid, void **x)
1250 {
1251   return E_FAIL;
1252 }
1253 
1254 static ULONG WINAPI tunk_AddRef(IUnknown *punk)
1255 {
1256   return ++xtunk.ref;
1257 }
1258 
1259 static ULONG WINAPI tunk_Release(IUnknown *punk)
1260 {
1261   return --xtunk.ref;
1262 }
1263 
1264 static const IUnknownVtbl xtunk_vtbl = {
1265 	tunk_QueryInterface,
1266 	tunk_AddRef,
1267 	tunk_Release
1268 };
1269 
1270 static void test_SafeArrayGetPutElement_IUnknown(void)
1271 {
1272   SAFEARRAYBOUND sab;
1273   LONG indices[1];
1274   SAFEARRAY *sa;
1275   HRESULT hres;
1276   IUnknown *gotvalue;
1277 
1278   sab.lLbound = 1;
1279   sab.cElements = 1;
1280   sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1281   ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1282   if (!sa)
1283     return;
1284 
1285   ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1286 
1287   indices[0] = sab.lLbound;
1288   xtunk.ref = 1;
1289   hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1290   ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1291   ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1292   gotvalue = NULL;
1293   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1294   ok(xtunk.ref == 3,"Failed to increment refcount of iface.\n");
1295   ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1296   if (hres == S_OK)
1297     ok(gotvalue == &xtunk.IUnknown_iface, "Got %p instead of %p\n", gotvalue, &xtunk.IUnknown_iface);
1298   hres = SafeArrayDestroy(sa);
1299   ok(hres == S_OK, "got 0x%08x\n", hres);
1300   ok(xtunk.ref == 2,"Failed to decrement refcount of iface.\n");
1301 }
1302 
1303 static void test_SafeArrayRedim_IUnknown(void)
1304 {
1305   SAFEARRAYBOUND sab;
1306   LONG indices[1];
1307   SAFEARRAY *sa;
1308   HRESULT hres;
1309 
1310   sab.lLbound = 1;
1311   sab.cElements = 2;
1312   sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1313   ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1314   if (!sa)
1315     return;
1316 
1317   ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1318 
1319   indices[0] = 2;
1320   xtunk.ref = 1;
1321   hres = SafeArrayPutElement(sa, indices, &xtunk.IUnknown_iface);
1322   ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres);
1323   ok(xtunk.ref == 2,"Failed to increment refcount of iface.\n");
1324   sab.cElements = 1;
1325   hres = SafeArrayRedim(sa, &sab);
1326   ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres);
1327   ok(xtunk.ref == 1, "Failed to decrement refcount\n");
1328   hres = SafeArrayDestroy(sa);
1329   ok(hres == S_OK, "got 0x%08x\n", hres);
1330 }
1331 
1332 static void test_SafeArrayGetPutElement_VARIANT(void)
1333 {
1334   SAFEARRAYBOUND sab;
1335   LONG indices[1];
1336   SAFEARRAY *sa;
1337   HRESULT hres;
1338   VARIANT value, gotvalue;
1339 
1340   sab.lLbound = 1;
1341   sab.cElements = 1;
1342   sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1343   ok(sa != NULL, "VARIANT test couldn't create array\n");
1344   if (!sa)
1345     return;
1346 
1347   ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1348 
1349   indices[0] = sab.lLbound;
1350   V_VT(&value) = VT_I4;
1351   V_I4(&value) = 0x42424242;
1352   hres = SafeArrayPutElement(sa, indices, &value);
1353   ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres);
1354 
1355   V_VT(&gotvalue) = 0xdead;
1356   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1357   ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1358 
1359   V_VT(&gotvalue) = VT_EMPTY;
1360   hres = SafeArrayGetElement(sa, indices, &gotvalue);
1361   ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1362   if (hres == S_OK) {
1363     ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1364     if (V_VT(&value) == V_VT(&gotvalue))
1365         ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1366   }
1367   hres = SafeArrayDestroy(sa);
1368   ok(hres == S_OK, "got 0x%08x\n", hres);
1369 }
1370 
1371 static void test_SafeArrayCopyData(void)
1372 {
1373   SAFEARRAYBOUND sab[4];
1374   SAFEARRAY *sa;
1375   SAFEARRAY *sacopy;
1376   HRESULT hres;
1377   int dimension, size = 1, i;
1378 
1379   if (!pSafeArrayCopyData)
1380   {
1381     win_skip("SafeArrayCopyData not supported\n");
1382     return;
1383   }
1384 
1385   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1386   {
1387     sab[dimension].lLbound = dimension * 2 + 2;
1388     sab[dimension].cElements = dimension * 3 + 1;
1389     size *= sab[dimension].cElements;
1390   }
1391 
1392   sa = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1393   ok(sa != NULL, "Copy test couldn't create array\n");
1394   sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1395   ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1396 
1397   if (!sa || !sacopy)
1398     return;
1399 
1400   ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1401 
1402   /* Fill the source array with some data; it doesn't matter what */
1403   for (dimension = 0; dimension < size; dimension++)
1404   {
1405     int* data = sa->pvData;
1406     data[dimension] = dimension;
1407   }
1408 
1409   hres = pSafeArrayCopyData(sa, sacopy);
1410   ok(hres == S_OK, "copy data failed hres 0x%x\n", hres);
1411   if (hres == S_OK)
1412   {
1413     ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1414   }
1415 
1416   /* Failure cases */
1417   hres = pSafeArrayCopyData(NULL, sacopy);
1418   ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres);
1419   hres = pSafeArrayCopyData(sa, NULL);
1420   ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres);
1421 
1422   sacopy->rgsabound[0].cElements += 1;
1423   hres = pSafeArrayCopyData(sa, sacopy);
1424   ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres);
1425 
1426   sacopy->rgsabound[0].cElements -= 2;
1427   hres = pSafeArrayCopyData(sa, sacopy);
1428   ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres);
1429   sacopy->rgsabound[0].cElements += 1;
1430 
1431   sacopy->rgsabound[3].cElements += 1;
1432   hres = pSafeArrayCopyData(sa, sacopy);
1433   ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres);
1434 
1435   sacopy->rgsabound[3].cElements -= 2;
1436   hres = pSafeArrayCopyData(sa, sacopy);
1437   ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres);
1438   sacopy->rgsabound[3].cElements += 1;
1439 
1440   hres = SafeArrayDestroy(sacopy);
1441   ok(hres == S_OK, "got 0x%08x\n", hres);
1442   sacopy = NULL;
1443   hres = pSafeArrayCopyData(sa, sacopy);
1444   ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres);
1445 
1446   hres = SafeArrayCopy(sa, &sacopy);
1447   ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
1448   ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1449   ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1450   ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1451   hres = SafeArrayDestroy(sacopy);
1452   ok(hres == S_OK, "got 0x%08x\n", hres);
1453 
1454   sacopy = SafeArrayCreate(VT_INT, ARRAY_SIZE(sab), sab);
1455   ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1456   ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1457 
1458   for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++)
1459   {
1460       USHORT feature = ignored_copy_features[i];
1461       USHORT orig = sacopy->fFeatures;
1462 
1463       sa->fFeatures |= feature;
1464       hres = SafeArrayCopyData(sa, sacopy);
1465       ok(hres == S_OK, "got 0x%08x\n", hres);
1466       ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures);
1467       sa->fFeatures &= ~feature;
1468   }
1469 
1470   hres = SafeArrayDestroy(sacopy);
1471   ok(hres == S_OK, "got 0x%08x\n", hres);
1472   hres = SafeArrayDestroy(sa);
1473   ok(hres == S_OK, "got 0x%08x\n", hres);
1474 
1475   /* copy data from a vector */
1476   sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1477 
1478   sacopy = SafeArrayCreateVector(VT_UI1, 0, 2);
1479   ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1480      broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1481      "got 0x%08x\n", sa->fFeatures);
1482   ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1483      broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1484      "got 0x%08x\n", sacopy->fFeatures);
1485   hres = SafeArrayCopyData(sa, sacopy);
1486   ok(hres == S_OK, "got 0x%08x\n", hres);
1487   ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1488      broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
1489      "got 0x%04x\n", sacopy->fFeatures);
1490   SafeArrayDestroy(sacopy);
1491 
1492   sacopy = SafeArrayCreate(VT_UI1, ARRAY_SIZE(sab), sab);
1493   ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1494   ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
1495   hres = SafeArrayCopyData(sa, sacopy);
1496   ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
1497   SafeArrayDestroy(sacopy);
1498 
1499   SafeArrayDestroy(sa);
1500 }
1501 
1502 static void test_SafeArrayCreateEx(void)
1503 {
1504   IRecordInfoImpl* iRec;
1505   SAFEARRAYBOUND sab[4];
1506   SAFEARRAY *sa;
1507   HRESULT hres;
1508   UINT dimension;
1509 
1510   if (!pSafeArrayCreateEx)
1511   {
1512     win_skip("SafeArrayCreateEx not supported\n");
1513     return;
1514   }
1515 
1516   for (dimension = 0; dimension < ARRAY_SIZE(sab); dimension++)
1517   {
1518     sab[dimension].lLbound = 0;
1519     sab[dimension].cElements = 8;
1520   }
1521 
1522   /* Failure cases */
1523   sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1524   ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1525 
1526   /* test IID storage & defaulting */
1527   sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1528   ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1529 
1530   if (sa)
1531   {
1532     GUID guid;
1533 
1534     hres = SafeArrayGetIID(sa, &guid);
1535     ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1536     ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1537     hres = SafeArraySetIID(sa, &IID_IUnknown);
1538     ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1539     hres = SafeArrayGetIID(sa, &guid);
1540     ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1541     hres = SafeArrayDestroy(sa);
1542     ok(hres == S_OK, "got 0x%08x\n", hres);
1543   }
1544 
1545   sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1546   ok(sa != NULL, "CreateEx (NULL) failed\n");
1547 
1548   if (sa)
1549   {
1550     GUID guid;
1551 
1552     hres = SafeArrayGetIID(sa, &guid);
1553     ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1554     ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1555     hres = SafeArrayDestroy(sa);
1556     ok(hres == S_OK, "got 0x%08x\n", hres);
1557   }
1558 
1559   sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1560   ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1561 
1562   if (sa)
1563   {
1564     GUID guid;
1565 
1566     hres = SafeArrayGetIID(sa, &guid);
1567     ok(hres == S_OK, "Failed to get array IID, hres %#x.\n", hres);
1568     ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1569     hres = SafeArrayDestroy(sa);
1570     ok(hres == S_OK, "got 0x%08x\n", hres);
1571   }
1572 
1573   /* VT_RECORD failure case */
1574   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1575   ok(sa == NULL, "CreateEx (NULL-Rec) succeeded\n");
1576 
1577   iRec = IRecordInfoImpl_Construct();
1578 
1579   /* Win32 doesn't care if GetSize fails */
1580   fail_GetSize = TRUE;
1581   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1582   ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1583   ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1584   ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1585   ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1586   if (sa)
1587   {
1588     ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements);
1589     hres = SafeArrayDestroy(sa);
1590     ok(hres == S_OK, "got 0x%08x\n", hres);
1591     ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1592     ok(iRec->ref == START_REF_COUNT, "got %d, expected %d\n", iRec->ref, START_REF_COUNT);
1593   }
1594 
1595   /* Test VT_RECORD array */
1596   fail_GetSize = FALSE;
1597   iRec->ref = START_REF_COUNT;
1598   iRec->sizeCalled = 0;
1599   iRec->clearCalled = 0;
1600   sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1601   ok(sa != NULL, "CreateEx (Rec) failed\n");
1602   ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1603   ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1604   ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1605   if (sa && pSafeArrayGetRecordInfo)
1606   {
1607     IRecordInfo* saRec = NULL;
1608     SAFEARRAY *sacopy;
1609 
1610     hres = pSafeArrayGetRecordInfo(sa, &saRec);
1611     ok(hres == S_OK,"GRI failed\n");
1612     ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n");
1613     ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
1614     IRecordInfo_Release(saRec);
1615 
1616     ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
1617 
1618     /* try to copy record based arrays */
1619     sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
1620     iRec->recordcopy = 0;
1621     iRec->clearCalled = 0;
1622     /* array copy code doesn't explicitly clear a record */
1623     hres = SafeArrayCopyData(sa, sacopy);
1624     ok(hres == S_OK, "got 0x%08x\n", hres);
1625     ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy);
1626     ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled);
1627 
1628     hres = SafeArrayDestroy(sacopy);
1629     ok(hres == S_OK, "got 0x%08x\n", hres);
1630 
1631     iRec->clearCalled = 0;
1632     iRec->sizeCalled = 0;
1633     hres = SafeArrayDestroy(sa);
1634     ok(hres == S_OK, "got 0x%08x\n", hres);
1635     ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
1636     ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1637     ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref);
1638   }
1639   else
1640   {
1641     hres = SafeArrayDestroy(sa);
1642     ok(hres == S_OK, "got 0x%08x\n", hres);
1643   }
1644 
1645   IRecordInfo_Release(&iRec->IRecordInfo_iface);
1646 }
1647 
1648 static void test_SafeArrayClear(void)
1649 {
1650   SAFEARRAYBOUND sab;
1651   SAFEARRAY *sa;
1652   VARIANTARG v;
1653   HRESULT hres;
1654 
1655   sab.lLbound = 0;
1656   sab.cElements = 10;
1657   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1658   ok(sa != NULL, "Create() failed.\n");
1659   if (!sa)
1660     return;
1661 
1662   /* Test clearing non-NULL variants containing arrays */
1663   V_VT(&v) = VT_ARRAY|VT_UI1;
1664   V_ARRAY(&v) = sa;
1665   hres = VariantClear(&v);
1666   ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v));
1667   ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1668 
1669   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1670   ok(sa != NULL, "Create() failed.\n");
1671   if (!sa)
1672     return;
1673 
1674   V_VT(&v) = VT_SAFEARRAY;
1675   V_ARRAY(&v) = sa;
1676   hres = VariantClear(&v);
1677   ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1678 
1679   V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1680   V_ARRAYREF(&v) = &sa;
1681   hres = VariantClear(&v);
1682   ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1683 
1684   hres = SafeArrayDestroy(sa);
1685   ok(hres == S_OK, "got 0x%08x\n", hres);
1686 }
1687 
1688 static void test_SafeArrayCopy(void)
1689 {
1690   SAFEARRAYBOUND sab;
1691   SAFEARRAY *sa, *sa2;
1692   VARIANTARG vSrc, vDst;
1693   HRESULT hres;
1694   int i;
1695 
1696   sab.lLbound = 0;
1697   sab.cElements = 10;
1698   sa = SafeArrayCreate(VT_UI1, 1, &sab);
1699   ok(sa != NULL, "Create() failed.\n");
1700   if (!sa)
1701     return;
1702 
1703   /* Test copying non-NULL variants containing arrays */
1704   V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1705   V_ARRAYREF(&vSrc) = &sa;
1706   V_VT(&vDst) = VT_EMPTY;
1707 
1708   hres = VariantCopy(&vDst, &vSrc);
1709   ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1710      "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1711   ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1712 
1713   V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1714   V_ARRAY(&vSrc) = sa;
1715   V_VT(&vDst) = VT_EMPTY;
1716 
1717   hres = VariantCopy(&vDst, &vSrc);
1718   ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1719      "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1720   ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1721 
1722   hres = SafeArrayDestroy(V_ARRAY(&vSrc));
1723   ok(hres == S_OK, "got 0x%08x\n", hres);
1724   hres = SafeArrayDestroy(V_ARRAY(&vDst));
1725   ok(hres == S_OK, "got 0x%08x\n", hres);
1726 
1727   hres = SafeArrayAllocDescriptor(1, &sa);
1728   ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1729 
1730   sa->cbElements = 16;
1731   hres = SafeArrayCopy(sa, &sa2);
1732   ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1733   ok(sa != sa2, "SafeArrayCopy performed shallow copy\n");
1734 
1735   hres = SafeArrayDestroy(sa2);
1736   ok(hres == S_OK, "got 0x%08x\n", hres);
1737   hres = SafeArrayDestroy(sa);
1738   ok(hres == S_OK, "got 0x%08x\n", hres);
1739 
1740   sa2 = (void*)0xdeadbeef;
1741   hres = SafeArrayCopy(NULL, &sa2);
1742   ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1743   ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1744 
1745   hres = SafeArrayAllocDescriptor(1, &sa);
1746   ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1747 
1748   sa2 = (void*)0xdeadbeef;
1749   hres = SafeArrayCopy(sa, &sa2);
1750   ok(hres == E_INVALIDARG,
1751     "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1752     hres);
1753   ok(!sa2, "SafeArrayCopy didn't return NULL for output array\n");
1754 
1755   hres = SafeArrayDestroy(sa2);
1756   ok(hres == S_OK, "got 0x%08x\n", hres);
1757   hres = SafeArrayDestroy(sa);
1758   ok(hres == S_OK, "got 0x%08x\n", hres);
1759 
1760   /* test feature copy */
1761   hres = SafeArrayAllocDescriptor(1, &sa);
1762   ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1763   ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures);
1764   sa->cbElements = 16;
1765 
1766   for (i = 0; i < ARRAY_SIZE(ignored_copy_features); i++)
1767   {
1768       USHORT feature = ignored_copy_features[i];
1769 
1770       sa->fFeatures |= feature;
1771       hres = SafeArrayCopy(sa, &sa2);
1772       ok(hres == S_OK, "got 0x%08x\n", hres);
1773       ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures);
1774       hres = SafeArrayDestroy(sa2);
1775       ok(hres == S_OK, "got 0x%08x\n", hres);
1776       sa->fFeatures &= ~feature;
1777   }
1778 
1779   SafeArrayDestroy(sa);
1780 
1781   /* copy from a vector */
1782   sa = SafeArrayCreateVector(VT_UI1, 0, 2);
1783   ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
1784      broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
1785      "got 0x%08x\n", sa->fFeatures);
1786   hres = SafeArrayCopy(sa, &sa2);
1787   ok(hres == S_OK, "got 0x%08x\n", hres);
1788   ok(sa2->fFeatures == FADF_HAVEVARTYPE ||
1789      broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n",
1790      sa2->fFeatures);
1791 
1792   SafeArrayDestroy(sa2);
1793   SafeArrayDestroy(sa);
1794 }
1795 
1796 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1797   sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1798   if (!sa) return; \
1799   V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1800 
1801 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1802   sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1803   V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1804 
1805 static void test_SafeArrayChangeTypeEx(void)
1806 {
1807   static const char *szHello = "Hello World";
1808   SAFEARRAYBOUND sab;
1809   SAFEARRAY *sa;
1810   VARIANTARG v,v2;
1811   VARTYPE vt;
1812   HRESULT hres;
1813 
1814   /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1815   MKARRAY(0,strlen(szHello)+1,VT_UI1);
1816   memcpy(sa->pvData, szHello, strlen(szHello)+1);
1817 
1818   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1819   ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1820   if (hres == S_OK)
1821   {
1822     ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1823     ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1824        (char*)V_BSTR(&v2));
1825     VariantClear(&v2);
1826   }
1827 
1828   /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1829   hres = SafeArrayDestroy(sa);
1830   ok(hres == S_OK, "got 0x%08x\n", hres);
1831   if (pSafeArrayCreateVector)
1832   {
1833     sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1834     ok(sa != NULL, "CreateVector() failed.\n");
1835     if (!sa)
1836       return;
1837 
1838     memcpy(sa->pvData, szHello, strlen(szHello)+1);
1839     V_VT(&v) = VT_VECTOR|VT_UI1;
1840     V_ARRAY(&v) = sa;
1841     VariantInit(&v2);
1842 
1843     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1844     ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres);
1845 
1846     /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1847     V_VT(&v) = VT_ARRAY|VT_UI1;
1848     hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1849     ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1850     if (hres == S_OK)
1851     {
1852       ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1853       ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1854               (char*)V_BSTR(&v));
1855       VariantClear(&v);
1856     }
1857   }
1858 
1859   /* To/from BSTR only works with arrays of VT_UI1 */
1860   for (vt = VT_EMPTY; vt <= VT_CLSID; vt++)
1861   {
1862     if (vt == VT_UI1)
1863       continue;
1864 
1865     sab.lLbound = 0;
1866     sab.cElements = 1;
1867     sa = SafeArrayCreate(vt, 1, &sab);
1868     if (!sa) continue;
1869 
1870     V_VT(&v) = VT_ARRAY|vt;
1871     V_ARRAY(&v) = sa;
1872     VariantInit(&v2);
1873 
1874     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1875     if (vt == VT_INT_PTR || vt == VT_UINT_PTR)
1876     {
1877         ok(hres == DISP_E_BADVARTYPE, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres);
1878         SafeArrayDestroy(sa);
1879     }
1880     else
1881     {
1882         ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres, vt);
1883         hres = VariantClear(&v);
1884         ok(hres == S_OK, "expected S_OK, got 0x%08x\n", hres);
1885     }
1886     VariantClear(&v2);
1887   }
1888 
1889   /* Can't change an array of one type into array of another type , even
1890    * if the other type is the same size
1891    */
1892   if (pSafeArrayCreateVector)
1893   {
1894     sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1895     ok(sa != NULL, "CreateVector() failed.\n");
1896     if (!sa)
1897       return;
1898 
1899     V_VT(&v) = VT_ARRAY|VT_UI1;
1900     V_ARRAY(&v) = sa;
1901     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1902     ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres);
1903 
1904     /* But can change to the same array type */
1905     hres = SafeArrayDestroy(sa);
1906     ok(hres == S_OK, "got 0x%08x\n", hres);
1907     sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1908     ok(sa != NULL, "CreateVector() failed.\n");
1909     if (!sa)
1910       return;
1911     V_VT(&v) = VT_ARRAY|VT_UI1;
1912     V_ARRAY(&v) = sa;
1913     hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1914     ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
1915     hres = SafeArrayDestroy(sa);
1916     ok(hres == S_OK, "got 0x%08x\n", hres);
1917     VariantClear(&v2);
1918   }
1919 
1920   /* NULL/EMPTY */
1921   MKARRAY(0,1,VT_UI1);
1922   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1923   ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1924   VariantClear(&v);
1925   MKARRAY(0,1,VT_UI1);
1926   hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1927   ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1928   VariantClear(&v);
1929 }
1930 
1931 static void test_SafeArrayDestroyData (void)
1932 {
1933   SAFEARRAYBOUND sab[2];
1934   SAFEARRAY *sa;
1935   HRESULT hres;
1936   int value = 0xdeadbeef;
1937   LONG index[1];
1938   void *temp_pvData;
1939   USHORT features;
1940 
1941   sab[0].lLbound = 0;
1942   sab[0].cElements = 10;
1943   sa = SafeArrayCreate(VT_INT, 1, sab);
1944   ok(sa != NULL, "Create() failed.\n");
1945   ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1946 
1947   index[0] = 1;
1948   SafeArrayPutElement (sa, index, &value);
1949 
1950 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1951   features = (sa->fFeatures |= FADF_STATIC);
1952   temp_pvData = sa->pvData;
1953   hres = SafeArrayDestroyData(sa);
1954   ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres);
1955   ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1956   ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1957     sa->pvData, temp_pvData, sa->fFeatures);
1958   SafeArrayGetElement (sa, index, &value);
1959   ok(value == 0, "Data not cleared after SADData\n");
1960 
1961 /* Clear FADF_STATIC, now really destroy the data. */
1962   features = (sa->fFeatures ^= FADF_STATIC);
1963   hres = SafeArrayDestroyData(sa);
1964   ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres);
1965   ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1966   ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
1967 
1968   hres = SafeArrayDestroy(sa);
1969   ok(hres == S_OK, "SAD failed, error code %x.\n", hres);
1970 
1971   /* two dimensions */
1972   sab[0].lLbound = 0;
1973   sab[0].cElements = 10;
1974   sab[1].lLbound = 0;
1975   sab[1].cElements = 10;
1976 
1977   sa = SafeArrayCreate(VT_INT, 2, sab);
1978   ok(sa != NULL, "Create() failed.\n");
1979   ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
1980 
1981   features = sa->fFeatures;
1982   hres = SafeArrayDestroyData(sa);
1983   ok(hres == S_OK, "got 0x%08x\n",hres);
1984   ok(features == sa->fFeatures, "got 0x%x\n", sa->fFeatures);
1985 
1986   SafeArrayDestroy(sa);
1987 
1988   /* try to destroy data from descriptor */
1989   hres = SafeArrayAllocDescriptor(1, &sa);
1990   ok(hres == S_OK, "got 0x%08x\n", hres);
1991   ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1992 
1993   hres = SafeArrayDestroyData(sa);
1994   ok(hres == S_OK, "got 0x%08x\n", hres);
1995   ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
1996 
1997   hres = SafeArrayDestroyDescriptor(sa);
1998   ok(hres == S_OK, "got 0x%08x\n", hres);
1999 
2000   hres = SafeArrayAllocDescriptor(2, &sa);
2001   ok(hres == S_OK, "got 0x%08x\n", hres);
2002   ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2003 
2004   hres = SafeArrayDestroyData(sa);
2005   ok(hres == S_OK, "got 0x%08x\n", hres);
2006   ok(sa->fFeatures == 0, "got 0x%x\n", sa->fFeatures);
2007 
2008   hres = SafeArrayDestroyDescriptor(sa);
2009   ok(hres == S_OK, "got 0x%08x\n", hres);
2010 
2011   /* vector case */
2012   sa = SafeArrayCreateVector(VT_I4, 0, 10);
2013   ok(sa != NULL, "got %p\n", sa);
2014   ok(sa->fFeatures == (FADF_CREATEVECTOR|FADF_HAVEVARTYPE), "got 0x%x\n", sa->fFeatures);
2015 
2016   ok(sa->pvData != NULL, "got %p\n", sa->pvData);
2017   hres = SafeArrayDestroyData(sa);
2018   ok(hres == S_OK, "got 0x%08x\n", hres);
2019 todo_wine
2020   ok(sa->fFeatures == FADF_HAVEVARTYPE, "got 0x%x\n", sa->fFeatures);
2021 todo_wine
2022   ok(sa->pvData == NULL || broken(sa->pvData != NULL), "got %p\n", sa->pvData);
2023   /* There was a bug on windows, especially visible on 64bit systems,
2024      probably double-free or similar issue. */
2025   sa->pvData = NULL;
2026   SafeArrayDestroy(sa);
2027 }
2028 
2029 static void test_safearray_layout(void)
2030 {
2031     IRecordInfoImpl *irec;
2032     IRecordInfo *record;
2033     GUID guid, *guidptr;
2034     SAFEARRAYBOUND sab;
2035     SAFEARRAY *sa;
2036     DWORD *dwptr;
2037     HRESULT hr;
2038 
2039     sab.lLbound = 0;
2040     sab.cElements = 10;
2041 
2042     /* GUID field */
2043     sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
2044     ok(sa != NULL, "got %p\n", sa);
2045 
2046     guidptr = (GUID*)sa - 1;
2047     ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr));
2048 
2049     hr = SafeArraySetIID(sa, &IID_IDispatch);
2050     ok(hr == S_OK, "got 0x%08x\n", hr);
2051     ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr));
2052 
2053     memcpy(guidptr, &IID_IUnknown, sizeof(GUID));
2054     hr = SafeArrayGetIID(sa, &guid);
2055     ok(hr == S_OK, "got 0x%08x\n", hr);
2056     ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
2057 
2058     hr = SafeArrayDestroy(sa);
2059     ok(hr == S_OK, "got 0x%08x\n", hr);
2060 
2061     /* VARTYPE field */
2062     sa = SafeArrayCreate(VT_UI1, 1, &sab);
2063     ok(sa != NULL, "got %p\n", sa);
2064 
2065     dwptr = (DWORD*)sa - 1;
2066     ok(*dwptr == VT_UI1, "got %d\n", *dwptr);
2067 
2068     hr = SafeArrayDestroy(sa);
2069     ok(hr == S_OK, "got 0x%08x\n", hr);
2070 
2071     /* IRecordInfo pointer */
2072     irec = IRecordInfoImpl_Construct();
2073     irec->ref = 1;
2074 
2075     sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface);
2076     ok(sa != NULL, "failed to create array\n");
2077 
2078     record = *((IRecordInfo**)sa - 1);
2079     ok(record == &irec->IRecordInfo_iface, "got %p\n", record);
2080 
2081     hr = SafeArrayDestroy(sa);
2082     ok(hr == S_OK, "got 0x%08x\n", hr);
2083     IRecordInfo_Release(&irec->IRecordInfo_iface);
2084 }
2085 
2086 START_TEST(safearray)
2087 {
2088     hOleaut32 = GetModuleHandleA("oleaut32.dll");
2089 
2090     has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
2091 
2092     GETPTR(SafeArrayAllocDescriptorEx);
2093     GETPTR(SafeArrayCopyData);
2094     GETPTR(SafeArrayGetVartype);
2095     GETPTR(SafeArrayCreateEx);
2096     GETPTR(SafeArrayCreateVector);
2097     GETPTR(SafeArrayGetRecordInfo);
2098 
2099     check_for_VT_INT_PTR();
2100     test_safearray();
2101     test_SafeArrayAllocDestroyDescriptor();
2102     test_SafeArrayCreateLockDestroy();
2103     test_VectorCreateLockDestroy();
2104     test_LockUnlock();
2105     test_SafeArrayChangeTypeEx();
2106     test_SafeArrayCopy();
2107     test_SafeArrayClear();
2108     test_SafeArrayCreateEx();
2109     test_SafeArrayCopyData();
2110     test_SafeArrayDestroyData();
2111     test_SafeArrayGetPutElement();
2112     test_SafeArrayGetPutElement_BSTR();
2113     test_SafeArrayGetPutElement_IUnknown();
2114     test_SafeArrayRedim_IUnknown();
2115     test_SafeArrayGetPutElement_VARIANT();
2116     test_safearray_layout();
2117 }
2118