2 * SafeArray test program
4 * Copyright 2002 Marcus Meissner
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.
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.
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
29 #include "wine/test.h"
42 static HMODULE hOleaut32
;
44 static HRESULT (WINAPI
*pSafeArrayAllocDescriptorEx
)(VARTYPE
,UINT
,SAFEARRAY
**);
45 static HRESULT (WINAPI
*pSafeArrayCopyData
)(SAFEARRAY
*,SAFEARRAY
*);
46 static HRESULT (WINAPI
*pSafeArrayGetIID
)(SAFEARRAY
*,GUID
*);
47 static HRESULT (WINAPI
*pSafeArraySetIID
)(SAFEARRAY
*,REFGUID
);
48 static HRESULT (WINAPI
*pSafeArrayGetVartype
)(SAFEARRAY
*,VARTYPE
*);
49 static HRESULT (WINAPI
*pSafeArrayGetRecordInfo
)(SAFEARRAY
*,IRecordInfo
**);
50 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateEx
)(VARTYPE
,UINT
,SAFEARRAYBOUND
*,LPVOID
);
51 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateVector
)(VARTYPE
,LONG
,ULONG
);
53 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
55 /* Is a given function exported from oleaut32? */
56 #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
58 /* Have IRecordInfo data type? */
59 #define HAVE_OLEAUT32_RECORD HAVE_FUNC(SafeArraySetRecordInfo)
60 /* Have R8 data type? */
61 #define HAVE_OLEAUT32_R8 HAVE_FUNC(VarR8FromI1)
62 /* Have I8/UI8 data type? */
63 #define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
64 /* Have the decimal type? */
65 #define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
66 /* Have INT_PTR/UINT_PTR type? */
67 static BOOL HAVE_OLEAUT32_INT_PTR
;
69 /* very old version? */
70 #define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
72 #define START_REF_COUNT 1
73 #define RECORD_SIZE 64
74 #define RECORD_SIZE_FAIL 17
75 /************************************************************************
76 * Dummy IRecordInfo Implementation
78 typedef struct IRecordInfoImpl
80 IRecordInfo IRecordInfo_iface
;
86 static const IRecordInfoVtbl IRecordInfoImpl_VTable
;
88 static inline IRecordInfoImpl
*impl_from_IRecordInfo(IRecordInfo
*iface
)
90 return CONTAINING_RECORD(iface
, IRecordInfoImpl
, IRecordInfo_iface
);
93 static IRecordInfoImpl
*IRecordInfoImpl_Construct(void)
97 rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl
));
98 rec
->IRecordInfo_iface
.lpVtbl
= &IRecordInfoImpl_VTable
;
99 rec
->ref
= START_REF_COUNT
;
100 rec
->clearCalled
= 0;
105 static ULONG CALLBACK
IRecordInfoImpl_AddRef(IRecordInfo
*iface
)
107 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
108 return InterlockedIncrement(&This
->ref
);
111 static ULONG CALLBACK
IRecordInfoImpl_Release(IRecordInfo
*iface
)
113 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
114 ULONG ref
= InterlockedDecrement(&This
->ref
);
117 HeapFree(GetProcessHeap(), 0, This
);
122 static BOOL fail_GetSize
; /* Whether to fail the GetSize call */
124 static HRESULT CALLBACK
IRecordInfoImpl_RecordClear(IRecordInfo
*iface
, PVOID pvExisting
)
126 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
131 static HRESULT CALLBACK
IRecordInfoImpl_GetSize(IRecordInfo
*iface
, ULONG
* size
)
133 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
137 *size
= RECORD_SIZE_FAIL
;
144 static HRESULT CALLBACK
IRecordInfoImpl_Dummy(IRecordInfo
*iface
)
146 trace("Called an unexpected IRecordInfo method - please report!\n");
147 /* Quit because we'll just crash anyway */
152 static const IRecordInfoVtbl IRecordInfoImpl_VTable
=
154 (PVOID
)IRecordInfoImpl_Dummy
,
155 IRecordInfoImpl_AddRef
,
156 IRecordInfoImpl_Release
,
157 (PVOID
)IRecordInfoImpl_Dummy
,
158 IRecordInfoImpl_RecordClear
,
159 (PVOID
)IRecordInfoImpl_Dummy
,
160 (PVOID
)IRecordInfoImpl_Dummy
,
161 (PVOID
)IRecordInfoImpl_Dummy
,
162 IRecordInfoImpl_GetSize
,
163 (PVOID
)IRecordInfoImpl_Dummy
,
164 (PVOID
)IRecordInfoImpl_Dummy
,
165 (PVOID
)IRecordInfoImpl_Dummy
,
166 (PVOID
)IRecordInfoImpl_Dummy
,
167 (PVOID
)IRecordInfoImpl_Dummy
,
168 (PVOID
)IRecordInfoImpl_Dummy
,
169 (PVOID
)IRecordInfoImpl_Dummy
,
170 (PVOID
)IRecordInfoImpl_Dummy
,
171 (PVOID
)IRecordInfoImpl_Dummy
,
172 (PVOID
)IRecordInfoImpl_Dummy
175 static DWORD
SAFEARRAY_GetVTSize(VARTYPE vt
)
180 case VT_UI1
: return sizeof(BYTE
);
183 case VT_UI2
: return sizeof(SHORT
);
187 case VT_ERROR
: return sizeof(LONG
);
189 if (HAVE_OLEAUT32_R8
)
190 return sizeof(LONG64
);
193 if (HAVE_OLEAUT32_I8
)
194 return sizeof(LONG64
);
197 case VT_UINT
: return sizeof(INT
);
200 if (HAVE_OLEAUT32_INT_PTR
)
201 return sizeof(UINT_PTR
);
203 case VT_CY
: return sizeof(CY
);
204 case VT_DATE
: return sizeof(DATE
);
205 case VT_BSTR
: return sizeof(BSTR
);
206 case VT_DISPATCH
: return sizeof(LPDISPATCH
);
207 case VT_VARIANT
: return sizeof(VARIANT
);
208 case VT_UNKNOWN
: return sizeof(LPUNKNOWN
);
210 if (HAVE_OLEAUT32_DECIMAL
)
211 return sizeof(DECIMAL
);
217 static void check_for_VT_INT_PTR(void)
219 /* Set a global flag if VT_INT_PTR is supported */
222 SAFEARRAYBOUND bound
;
225 a
= SafeArrayCreate(VT_INT_PTR
, 1, &bound
);
228 trace("VT_INT_PTR is supported\n");
229 HAVE_OLEAUT32_INT_PTR
= TRUE
;
230 hres
= SafeArrayDestroy(a
);
231 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
234 trace("VT_INT_PTR is not supported\n");
235 HAVE_OLEAUT32_INT_PTR
= FALSE
;
239 #define VARTYPE_NOT_SUPPORTED 0
242 UINT elemsize
; /* elementsize by VT */
243 UINT expflags
; /* fFeatures from SafeArrayAllocDescriptorEx */
244 UINT addflags
; /* additional fFeatures from SafeArrayCreate */
246 {VT_EMPTY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
247 {VT_NULL
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
248 {VT_I2
, 2, FADF_HAVEVARTYPE
,0},
249 {VT_I4
, 4, FADF_HAVEVARTYPE
,0},
250 {VT_R4
, 4, FADF_HAVEVARTYPE
,0},
251 {VT_R8
, 8, FADF_HAVEVARTYPE
,0},
252 {VT_CY
, 8, FADF_HAVEVARTYPE
,0},
253 {VT_DATE
, 8, FADF_HAVEVARTYPE
,0},
254 {VT_BSTR
, sizeof(BSTR
), FADF_HAVEVARTYPE
,FADF_BSTR
},
255 {VT_DISPATCH
, sizeof(LPDISPATCH
), FADF_HAVEIID
, FADF_DISPATCH
},
256 {VT_ERROR
, 4, FADF_HAVEVARTYPE
,0},
257 {VT_BOOL
, 2, FADF_HAVEVARTYPE
,0},
258 {VT_VARIANT
, sizeof(VARIANT
), FADF_HAVEVARTYPE
,FADF_VARIANT
},
259 {VT_UNKNOWN
, sizeof(LPUNKNOWN
), FADF_HAVEIID
, FADF_UNKNOWN
},
260 {VT_DECIMAL
, sizeof(DECIMAL
), FADF_HAVEVARTYPE
,0},
261 {15, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0}, /* no VT_xxx */
262 {VT_I1
, 1, FADF_HAVEVARTYPE
,0},
263 {VT_UI1
, 1, FADF_HAVEVARTYPE
,0},
264 {VT_UI2
, 2, FADF_HAVEVARTYPE
,0},
265 {VT_UI4
, 4, FADF_HAVEVARTYPE
,0},
266 {VT_I8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
267 {VT_UI8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
268 {VT_INT
, sizeof(INT
), FADF_HAVEVARTYPE
,0},
269 {VT_UINT
, sizeof(UINT
), FADF_HAVEVARTYPE
,0},
270 {VT_VOID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
271 {VT_HRESULT
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
272 {VT_PTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
273 {VT_SAFEARRAY
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
274 {VT_CARRAY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
275 {VT_USERDEFINED
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
276 {VT_LPSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
277 {VT_LPWSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
278 {VT_FILETIME
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
279 {VT_RECORD
, VARTYPE_NOT_SUPPORTED
,FADF_RECORD
,0},
280 {VT_BLOB
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
281 {VT_STREAM
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
282 {VT_STORAGE
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
283 {VT_STREAMED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
284 {VT_STORED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
285 {VT_BLOB_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
286 {VT_CF
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
287 {VT_CLSID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
290 static void test_safearray(void)
293 unsigned int i
, diff
;
296 SAFEARRAYBOUND bound
, bounds
[2];
302 unsigned char *ptr1
, *ptr2
;
304 hres
= SafeArrayDestroy( NULL
);
305 ok( hres
== S_OK
, "SafeArrayDestroy( NULL) returned 0x%x\n", hres
);
309 a
= SafeArrayCreate(-1, 1, &bound
);
310 ok(NULL
== a
,"SAC(-1,1,[1,0]) not failed?\n");
314 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
315 ok(NULL
!= a
,"SAC(VT_I4,1,[0,0]) failed.\n");
317 hres
= SafeArrayGetLBound(a
, 1, &l
);
318 ok(hres
== S_OK
, "SAGLB of 0 size dimensioned array failed with %x\n",hres
);
319 ok(l
== 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l
);
320 hres
= SafeArrayGetUBound(a
, 1, &l
);
321 ok(hres
== S_OK
, "SAGUB of 0 size dimensioned array failed with %x\n",hres
);
322 ok(l
== 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l
);
324 hres
= SafeArrayAccessData(a
, &data
);
325 ok(hres
== S_OK
, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres
);
326 SafeArrayUnaccessData(a
);
329 hres
= SafeArrayRedim(a
, &bound
);
330 ok(hres
== S_OK
,"SAR of a 0 elements dimension failed with hres %x\n", hres
);
332 hres
= SafeArrayRedim(a
, &bound
);
333 ok(hres
== S_OK
|| hres
== E_OUTOFMEMORY
,
334 "SAR to a 0 elements dimension failed with hres %x\n", hres
);
335 hres
= SafeArrayDestroy(a
);
336 ok(hres
== S_OK
,"SAD of 0 dim array failed with hres %x\n", hres
);
338 SafeArrayAllocDescriptor(2, &a
);
339 a
->rgsabound
[0].cElements
= 2;
340 a
->rgsabound
[0].lLbound
= 1;
341 a
->rgsabound
[1].cElements
= 4;
342 a
->rgsabound
[1].lLbound
= 1;
344 SafeArrayAllocData(a
);
348 hres
= SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
349 ok(hres
== S_OK
, "SAPOI failed with hres %x\n", hres
);
350 SafeArrayAccessData(a
, (void **)&ptr2
);
351 ok(ptr1
- ptr2
== 14, "SAPOI got wrong ptr\n");
352 *(WORD
*)ptr1
= 0x55aa;
353 SafeArrayUnaccessData(a
);
355 bound
.cElements
= 10;
357 SafeArrayRedim(a
, &bound
);
359 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
360 ok(*(WORD
*)ptr1
== 0x55aa, "Data not preserved when resizing array\n");
362 bound
.cElements
= 10;
364 SafeArrayRedim(a
, &bound
);
365 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
366 ok(*(WORD
*)ptr1
== 0, "Expanded area not zero-initialized\n");
369 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
370 ok(*(WORD
*)ptr1
== 0x55aa, "Data not preserved when resizing array\n");
372 hres
= SafeArrayDestroy(a
);
373 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
375 bounds
[0].cElements
= 0; bounds
[0].lLbound
= 1;
376 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
377 a
= SafeArrayCreate(VT_I4
,2,bounds
);
378 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
380 hres
= SafeArrayDestroy(a
);
381 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
382 bounds
[0].cElements
= 1; bounds
[0].lLbound
= 1;
383 bounds
[1].cElements
= 0; bounds
[1].lLbound
= 23;
384 a
= SafeArrayCreate(VT_I4
,2,bounds
);
385 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
387 hres
= SafeArrayDestroy(a
);
388 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
390 bounds
[0].cElements
= 42; bounds
[0].lLbound
= 1;
391 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
392 a
= SafeArrayCreate(VT_I4
,2,bounds
);
393 ok(a
!= NULL
,"SAC(VT_INT32,2,...) failed.\n");
395 hres
= SafeArrayGetLBound (a
, 0, &l
);
396 ok (hres
== DISP_E_BADINDEX
, "SAGLB 0 failed with %x\n", hres
);
397 hres
= SafeArrayGetLBound (a
, 1, &l
);
398 ok (hres
== S_OK
, "SAGLB 1 failed with %x\n", hres
);
399 ok (l
== 1, "SAGLB 1 returned %d instead of 1\n", l
);
400 hres
= SafeArrayGetLBound (a
, 2, &l
);
401 ok (hres
== S_OK
, "SAGLB 2 failed with %x\n", hres
);
402 ok (l
== 23, "SAGLB 2 returned %d instead of 23\n", l
);
403 hres
= SafeArrayGetLBound (a
, 3, &l
);
404 ok (hres
== DISP_E_BADINDEX
, "SAGLB 3 failed with %x\n", hres
);
406 hres
= SafeArrayGetUBound (a
, 0, &l
);
407 ok (hres
== DISP_E_BADINDEX
, "SAGUB 0 failed with %x\n", hres
);
408 hres
= SafeArrayGetUBound (a
, 1, &l
);
409 ok (hres
== S_OK
, "SAGUB 1 failed with %x\n", hres
);
410 ok (l
== 42, "SAGUB 1 returned %d instead of 42\n", l
);
411 hres
= SafeArrayGetUBound (a
, 2, &l
);
412 ok (hres
== S_OK
, "SAGUB 2 failed with %x\n", hres
);
413 ok (l
== 24, "SAGUB 2 returned %d instead of 24\n", l
);
414 hres
= SafeArrayGetUBound (a
, 3, &l
);
415 ok (hres
== DISP_E_BADINDEX
, "SAGUB 3 failed with %x\n", hres
);
417 i
= SafeArrayGetDim(a
);
418 ok(i
== 2, "getdims of 2 din array returned %d\n",i
);
422 hres
= SafeArrayGetElement(a
, indices
, &i
);
423 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [0,23], hres 0x%x\n",hres
);
427 hres
= SafeArrayGetElement(a
, indices
, &i
);
428 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,22], hres 0x%x\n",hres
);
432 hres
= SafeArrayGetElement(a
, indices
, &i
);
433 ok(S_OK
== hres
,"SAGE failed [1,23], hres 0x%x\n",hres
);
437 hres
= SafeArrayGetElement(a
, indices
, &i
);
438 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,24], hres 0x%x\n",hres
);
442 hres
= SafeArrayGetElement(a
, indices
, &i
);
443 ok(S_OK
== hres
,"SAGE failed [42,23], hres 0x%x\n",hres
);
445 hres
= SafeArrayAccessData(a
, (void**)&ptr1
);
446 ok(S_OK
== hres
, "SAAD failed with 0x%x\n", hres
);
450 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
451 ok(S_OK
== hres
,"SAPOI failed [1,23], hres 0x%x\n",hres
);
453 ok(diff
== 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
457 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
458 ok(S_OK
== hres
,"SAPOI failed [5,24], hres 0x%x\n",hres
);
460 ok(diff
== 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
464 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
465 ok(S_OK
== hres
,"SAPOI failed [20,23], hres 0x%x\n",hres
);
467 ok(diff
== 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
469 hres
= SafeArrayUnaccessData(a
);
470 ok(S_OK
== hres
, "SAUAD failed with 0x%x\n", hres
);
472 hres
= SafeArrayDestroy(a
);
473 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
475 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
476 if ((i
== VT_I8
|| i
== VT_UI8
) && HAVE_OLEAUT32_I8
)
478 vttypes
[i
].elemsize
= sizeof(LONG64
);
481 a
= SafeArrayCreate(vttypes
[i
].vt
, 1, &bound
);
483 ok((!a
&& !vttypes
[i
].elemsize
) ||
484 (a
&& vttypes
[i
].elemsize
== a
->cbElements
) ||
485 (IS_ANCIENT
&& (vttypes
[i
].vt
== VT_DECIMAL
|| vttypes
[i
].vt
== VT_I1
||
486 vttypes
[i
].vt
== VT_UI2
|| vttypes
[i
].vt
== VT_UI4
|| vttypes
[i
].vt
== VT_INT
||
487 vttypes
[i
].vt
== VT_UINT
)),
488 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
489 vttypes
[i
].vt
,a
,(a
?a
->cbElements
:0),vttypes
[i
].elemsize
);
493 if (!HAVE_OLEAUT32_RECORD
)
494 vttypes
[i
].expflags
= 0;
495 ok(a
->fFeatures
== (vttypes
[i
].expflags
| vttypes
[i
].addflags
),
496 "SAC of %d returned feature flags %x, expected %x\n",
497 vttypes
[i
].vt
, a
->fFeatures
,
498 vttypes
[i
].expflags
|vttypes
[i
].addflags
);
499 ok(SafeArrayGetElemsize(a
) == vttypes
[i
].elemsize
,
500 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
501 vttypes
[i
].vt
, SafeArrayGetElemsize(a
),vttypes
[i
].elemsize
);
506 if (pSafeArrayGetVartype
)
508 hres
= pSafeArrayGetVartype(a
, &vt
);
509 ok(hres
== S_OK
, "SAGVT of arra y with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
510 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
511 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
514 hres
= SafeArrayCopy(a
, &c
);
515 ok(hres
== S_OK
, "failed to copy safearray of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
517 ok(vttypes
[i
].elemsize
== c
->cbElements
,"copy of SAC(%d,1,[1,0]), result %d, expected %d\n",vttypes
[i
].vt
,(c
?c
->cbElements
:0),vttypes
[i
].elemsize
519 ok(c
->fFeatures
== (vttypes
[i
].expflags
| vttypes
[i
].addflags
),"SAC of %d returned feature flags %x, expected %x\n", vttypes
[i
].vt
, c
->fFeatures
, vttypes
[i
].expflags
|vttypes
[i
].addflags
);
520 ok(SafeArrayGetElemsize(c
) == vttypes
[i
].elemsize
,"SAGE for vt %d returned elemsize %d instead of expected %d\n",vttypes
[i
].vt
, SafeArrayGetElemsize(c
),vttypes
[i
].elemsize
);
522 if (pSafeArrayGetVartype
) {
523 hres
= pSafeArrayGetVartype(c
, &vt
);
524 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
525 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
526 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
529 if (pSafeArrayCopyData
) {
530 hres
= pSafeArrayCopyData(a
, c
);
531 ok(hres
== S_OK
, "failed to copy safearray data of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
533 hres
= SafeArrayDestroyData(c
);
534 ok(hres
== S_OK
,"SADD of copy of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
537 hres
= SafeArrayDestroy(c
);
538 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
540 hres
= SafeArrayDestroy(a
);
541 ok(hres
== S_OK
,"SAD of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
544 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
546 bound
.cElements
= 10;
547 a
= SafeArrayCreate(VT_UI1
, 1, &bound
);
548 ok(a
!= NULL
, "SAC failed.\n");
549 ok(S_OK
== SafeArrayAccessData(a
, &data
),"SACD failed\n");
550 memcpy(data
,"Hello World\n",10);
551 ok(S_OK
== SafeArrayUnaccessData(a
),"SAUD failed\n");
552 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
554 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
555 ok(hres
==S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres
);
556 ok(V_VT(&v
) == VT_BSTR
,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.v\n",V_VT(&v
));
557 ok(V_BSTR(&v
)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v
)[0]);
560 /* check locking functions */
561 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
562 ok(a
!=NULL
,"SAC should not fail\n");
564 hres
= SafeArrayAccessData(a
, &data
);
565 ok(hres
== S_OK
,"SAAD failed with hres %x\n",hres
);
567 hres
= SafeArrayDestroy(a
);
568 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
570 hres
= SafeArrayDestroyData(a
);
571 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
573 hres
= SafeArrayDestroyDescriptor(a
);
574 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
576 hres
= SafeArrayUnaccessData(a
);
577 ok(hres
== S_OK
,"SAUD failed after lock/destroy test\n");
579 hres
= SafeArrayDestroy(a
);
580 ok(hres
== S_OK
,"SAD failed after lock/destroy test\n");
582 /* Test if we need to destroy data before descriptor */
583 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
584 ok(a
!=NULL
,"SAC should not fail\n");
585 hres
= SafeArrayDestroyDescriptor(a
);
586 ok(hres
== S_OK
,"SADD with data in array failed with hres %x\n",hres
);
589 /* init a small stack safearray */
590 if (pSafeArraySetIID
) {
591 memset(&b
, 0, sizeof(b
));
593 memset(&iid
, 0x42, sizeof(IID
));
594 hres
= pSafeArraySetIID(&b
,&iid
);
595 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %x\n",hres
);
597 hres
= SafeArrayAllocDescriptor(1,&a
);
598 ok(hres
== S_OK
,"SafeArrayAllocDescriptor should return S_OK, but got %x\n",hres
);
599 ok((a
->fFeatures
& FADF_HAVEIID
) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
600 hres
= pSafeArraySetIID(a
,&iid
);
601 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but got %x\n",hres
);
603 hres
= SafeArrayDestroyDescriptor(a
);
604 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
607 if (!pSafeArrayAllocDescriptorEx
)
610 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
612 hres
= pSafeArrayAllocDescriptorEx(vttypes
[i
].vt
,1,&a
);
613 ok(hres
== S_OK
, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres
);
614 ok(a
->fFeatures
== vttypes
[i
].expflags
,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes
[i
].vt
, a
->fFeatures
, vttypes
[i
].expflags
);
615 if (a
->fFeatures
& FADF_HAVEIID
) {
616 hres
= pSafeArrayGetIID(a
, &iid
);
617 ok(hres
== S_OK
,"SAGIID failed for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
618 switch (vttypes
[i
].vt
) {
620 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IUnknown
),"guid for VT_UNKNOWN is not IID_IUnknown\n");
621 ok(IsEqualGUID(&iid
, &IID_IUnknown
),"SAGIID returned wrong GUID for IUnknown\n");
624 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IDispatch
),"guid for VT_UNKNOWN is not IID_IDispatch\n");
625 ok(IsEqualGUID(&iid
, &IID_IDispatch
),"SAGIID returned wrong GUID for IDispatch\n");
628 ok(FALSE
,"unknown vt %d with FADF_HAVEIID\n",vttypes
[i
].vt
);
632 hres
= pSafeArrayGetIID(a
, &iid
);
633 ok(hres
== E_INVALIDARG
,"SAGIID did not fail for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
635 if (a
->fFeatures
& FADF_RECORD
) {
636 ok(vttypes
[i
].vt
== VT_RECORD
,"FADF_RECORD for non record %d\n",vttypes
[i
].vt
);
638 if (a
->fFeatures
& FADF_HAVEVARTYPE
) {
639 ok(vttypes
[i
].vt
== ((DWORD
*)a
)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes
[i
].vt
,((DWORD
*)a
)[-1]);
642 hres
= pSafeArrayGetVartype(a
, &vt
);
643 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
645 if (vttypes
[i
].vt
== VT_DISPATCH
) {
646 /* Special case. Checked against Windows. */
647 ok(vt
== VT_UNKNOWN
, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
649 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
652 if (a
->fFeatures
& FADF_HAVEIID
) {
653 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
654 ok(hres
== S_OK
,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
655 hres
= pSafeArrayGetIID(a
, &iid
);
656 ok(hres
== S_OK
,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
657 ok(IsEqualGUID(&iid
, &IID_IStorage
),"returned iid is not IID_IStorage\n");
659 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
660 ok(hres
== E_INVALIDARG
,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
662 hres
= SafeArrayDestroyDescriptor(a
);
663 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
667 static void test_SafeArrayAllocDestroyDescriptor(void)
674 hres
= SafeArrayAllocDescriptor(0, &sa
);
675 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
677 hres
= SafeArrayAllocDescriptor(65536, &sa
);
678 ok(IS_ANCIENT
|| hres
== E_INVALIDARG
,
679 "65536 dimensions gave hres 0x%x\n", hres
);
683 /* Crashes on 95: XP & Wine return E_POINTER */
684 hres
=SafeArrayAllocDescriptor(1, NULL
);
685 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
688 /* Test up to the dimension boundary case */
689 for (i
= 5; i
<= 65535; i
+= 30)
691 hres
= SafeArrayAllocDescriptor(i
, &sa
);
692 ok(hres
== S_OK
, "%d dimensions failed; hres 0x%x\n", i
, hres
);
696 ok(SafeArrayGetDim(sa
) == (UINT
)i
, "Dimension is %d; should be %d\n",
697 SafeArrayGetDim(sa
), i
);
699 hres
= SafeArrayDestroyDescriptor(sa
);
700 ok(hres
== S_OK
, "destroy failed; hres 0x%x\n", hres
);
704 if (!pSafeArrayAllocDescriptorEx
)
707 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 0, &sa
);
708 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
710 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 65536, &sa
);
711 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%x\n", hres
);
713 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 1, NULL
);
714 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
716 hres
= pSafeArrayAllocDescriptorEx(-1, 1, &sa
);
717 ok(hres
== S_OK
, "VT = -1 gave hres 0x%x\n", hres
);
719 sa
->rgsabound
[0].cElements
= 0;
720 sa
->rgsabound
[0].lLbound
= 1;
722 hres
= SafeArrayAllocData(sa
);
723 ok(hres
== S_OK
, "SafeArrayAllocData gave hres 0x%x\n", hres
);
725 hres
= SafeArrayDestroy(sa
);
726 ok(hres
== S_OK
,"SafeArrayDestroy failed with hres %x\n",hres
);
729 static void test_SafeArrayCreateLockDestroy(void)
731 SAFEARRAYBOUND sab
[4];
737 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
739 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
741 sab
[dimension
].lLbound
= 0;
742 sab
[dimension
].cElements
= 8;
746 /* This test crashes very early versions with no error checking...
747 sa = SafeArrayCreate(VT_UI1, 1, NULL);
748 ok(sa == NULL, "NULL bounds didn't fail\n");
750 sa
= SafeArrayCreate(VT_UI1
, 65536, sab
);
751 ok(IS_ANCIENT
|| !sa
, "Max bounds didn't fail\n");
753 memset(sab
, 0, sizeof(sab
));
755 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
757 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
758 sab
[dimension
].cElements
= 8;
760 /* Test all VARTYPES in 1-4 dimensions */
761 for (dimension
= 1; dimension
< 4; dimension
++)
763 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
765 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
767 sa
= SafeArrayCreate(vt
, dimension
, sab
);
770 ok(sa
|| (IS_ANCIENT
&& (vt
== VT_DECIMAL
|| vt
== VT_I1
|| vt
== VT_UI2
||
771 vt
== VT_UI4
|| vt
== VT_INT
|| vt
== VT_UINT
)),
772 "VARTYPE %d (@%d dimensions) failed\n", vt
, dimension
);
774 ok(sa
== NULL
|| vt
== VT_R8
,
775 "VARTYPE %d (@%d dimensions) succeeded!\n", vt
, dimension
);
779 ok(SafeArrayGetDim(sa
) == (UINT
)dimension
,
780 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
781 vt
, dimension
, SafeArrayGetDim(sa
), dimension
);
782 ok(SafeArrayGetElemsize(sa
) == dwLen
|| vt
== VT_R8
,
783 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
784 vt
, dimension
, SafeArrayGetElemsize(sa
), dwLen
);
786 if (vt
!= VT_UNKNOWN
&& vt
!= VT_DISPATCH
)
788 ok((sa
->fFeatures
& FADF_HAVEIID
) == 0,
789 "Non interface type should not have FADF_HAVEIID\n");
790 if (pSafeArraySetIID
)
792 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
793 ok(hres
== E_INVALIDARG
,
794 "Non interface type allowed SetIID(), hres %x\n", hres
);
800 ok(IS_ANCIENT
|| sa
->fFeatures
& FADF_HAVEVARTYPE
,
801 "Non interface type should have FADF_HAVEVARTYPE\n");
802 if (pSafeArrayGetVartype
)
804 hres
= pSafeArrayGetVartype(sa
, &aVt
);
805 ok(hres
== S_OK
&& aVt
== vt
,
806 "Non interface type %d: bad type %d, hres %x\n", vt
, aVt
, hres
);
812 ok(IS_ANCIENT
|| sa
->fFeatures
& FADF_HAVEIID
,
813 "Interface type should have FADF_HAVEIID\n");
814 if (pSafeArraySetIID
)
816 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
818 "Non interface type disallowed SetIID(), hres %x\n", hres
);
820 ok((sa
->fFeatures
& FADF_HAVEVARTYPE
) == 0,
821 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt
);
824 hres
= SafeArrayLock(sa
);
825 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
826 vt
, dimension
, hres
);
830 hres
= SafeArrayDestroy(sa
);
831 ok(hres
== DISP_E_ARRAYISLOCKED
,"Destroy() got hres %x\n", hres
);
833 hres
= SafeArrayDestroyData(sa
);
834 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyData() got hres %x\n", hres
);
836 hres
= SafeArrayDestroyDescriptor(sa
);
837 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyDescriptor() got hres %x\n", hres
);
839 hres
= SafeArrayUnlock(sa
);
840 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
841 vt
, dimension
, hres
);
843 hres
= SafeArrayDestroy(sa
);
844 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
845 vt
, dimension
, hres
);
852 static void test_VectorCreateLockDestroy(void)
859 if (!pSafeArrayCreateVector
)
861 win_skip("SafeArrayCreateVector not supported\n");
864 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 0);
865 ok(sa
!= NULL
, "SACV with 0 elements failed.\n");
867 hres
= SafeArrayDestroy(sa
);
868 ok(hres
== S_OK
, "SafeArrayDestroy failed with hres %x\n",hres
);
870 /* Test all VARTYPES in different lengths */
871 for (element
= 1; element
<= 101; element
+= 10)
873 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
875 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
877 sa
= pSafeArrayCreateVector(vt
, 0, element
);
880 ok(sa
!= NULL
, "VARTYPE %d (@%d elements) failed\n", vt
, element
);
882 ok(sa
== NULL
, "VARTYPE %d (@%d elements) succeeded!\n", vt
, element
);
886 ok(SafeArrayGetDim(sa
) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
887 vt
, element
, SafeArrayGetDim(sa
));
888 ok(SafeArrayGetElemsize(sa
) == dwLen
,
889 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
890 vt
, element
, SafeArrayGetElemsize(sa
), dwLen
);
892 hres
= SafeArrayLock(sa
);
893 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
898 hres
= SafeArrayUnlock(sa
);
899 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
902 hres
= SafeArrayDestroy(sa
);
903 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
911 static void test_LockUnlock(void)
913 SAFEARRAYBOUND sab
[4];
916 BOOL bVector
= FALSE
;
920 hres
= SafeArrayLock(NULL
);
921 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
922 hres
= SafeArrayUnlock(NULL
);
923 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
925 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
927 sab
[dimension
].lLbound
= 0;
928 sab
[dimension
].cElements
= 8;
931 sa
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
933 /* Test maximum locks */
934 test_LockUnlock_Vector
:
939 hres
= SafeArrayUnlock(sa
);
940 ok (hres
== E_UNEXPECTED
, "Bad %sUnlock gave hres 0x%x\n",
941 bVector
? "vector " : "\n", hres
);
943 while ((hres
= SafeArrayLock(sa
)) == S_OK
)
945 ok (count
== 65535 && hres
== E_UNEXPECTED
, "Lock %sfailed at %d; hres 0x%x\n",
946 bVector
? "vector " : "\n", count
, hres
);
948 if (count
== 65535 && hres
== E_UNEXPECTED
)
950 while ((hres
= SafeArrayUnlock(sa
)) == S_OK
)
952 ok (count
== 0 && hres
== E_UNEXPECTED
, "Unlock %sfailed at %d; hres 0x%x\n",
953 bVector
? "vector " : "\n", count
, hres
);
956 hres
= SafeArrayDestroy(sa
);
957 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
960 if (bVector
== FALSE
&& pSafeArrayCreateVector
)
962 /* Test again with a vector */
963 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 100);
965 goto test_LockUnlock_Vector
;
969 static void test_SafeArrayGetPutElement(void)
971 SAFEARRAYBOUND sab
[4];
972 LONG indices
[NUM_DIMENSIONS
];
975 int value
= 0, gotvalue
, dimension
;
976 unsigned int x
,y
,z
,a
;
978 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
980 sab
[dimension
].lLbound
= dimension
* 2 + 1;
981 sab
[dimension
].cElements
= dimension
* 3 + 1;
984 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
986 return; /* Some early versions can't handle > 3 dims */
988 ok(sa
->cbElements
== sizeof(value
), "int size mismatch\n");
989 if (sa
->cbElements
!= sizeof(value
))
993 for (x
= 0; x
< NUM_DIMENSIONS
; x
++)
995 indices
[0] = sab
[0].lLbound
;
996 indices
[1] = sab
[1].lLbound
;
997 indices
[2] = sab
[2].lLbound
;
998 indices
[3] = sab
[3].lLbound
;
1000 indices
[x
] = indices
[x
] - 1;
1001 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1002 ok(hres
== DISP_E_BADINDEX
, "Put allowed too small index in dimension %d\n", x
);
1003 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1004 ok(hres
== DISP_E_BADINDEX
, "Get allowed too small index in dimension %d\n", x
);
1006 indices
[x
] = sab
[x
].lLbound
+ sab
[x
].cElements
;
1007 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1008 ok(hres
== DISP_E_BADINDEX
, "Put allowed too big index in dimension %d\n", x
);
1009 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1010 ok(hres
== DISP_E_BADINDEX
, "Get allowed too big index in dimension %d\n", x
);
1013 indices
[0] = sab
[0].lLbound
;
1014 indices
[1] = sab
[1].lLbound
;
1015 indices
[2] = sab
[2].lLbound
;
1016 indices
[3] = sab
[3].lLbound
;
1018 hres
= SafeArrayPutElement(NULL
, indices
, &value
);
1019 ok(hres
== E_INVALIDARG
, "Put NULL array hres 0x%x\n", hres
);
1020 hres
= SafeArrayGetElement(NULL
, indices
, &value
);
1021 ok(hres
== E_INVALIDARG
, "Get NULL array hres 0x%x\n", hres
);
1023 hres
= SafeArrayPutElement(sa
, NULL
, &value
);
1024 ok(hres
== E_INVALIDARG
, "Put NULL indices hres 0x%x\n", hres
);
1025 hres
= SafeArrayGetElement(sa
, NULL
, &value
);
1026 ok(hres
== E_INVALIDARG
, "Get NULL indices hres 0x%x\n", hres
);
1030 /* This is retarded. Windows checks every case of invalid parameters
1031 * except the following, which crashes. We ERR this in Wine.
1033 hres
= SafeArrayPutElement(sa
, indices
, NULL
);
1034 ok(hres
== E_INVALIDARG
, "Put NULL value hres 0x%x\n", hres
);
1037 hres
= SafeArrayGetElement(sa
, indices
, NULL
);
1038 ok(hres
== E_INVALIDARG
, "Get NULL value hres 0x%x\n", hres
);
1042 /* Make sure we can read and get back the correct values in 4 dimensions,
1043 * Each with a different size and lower bound.
1045 for (x
= 0; x
< sab
[0].cElements
; x
++)
1047 indices
[0] = sab
[0].lLbound
+ x
;
1048 for (y
= 0; y
< sab
[1].cElements
; y
++)
1050 indices
[1] = sab
[1].lLbound
+ y
;
1051 for (z
= 0; z
< sab
[2].cElements
; z
++)
1053 indices
[2] = sab
[2].lLbound
+ z
;
1054 for (a
= 0; a
< sab
[3].cElements
; a
++)
1056 indices
[3] = sab
[3].lLbound
+ a
;
1057 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1058 ok(hres
== S_OK
, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1068 for (x
= 0; x
< sab
[0].cElements
; x
++)
1070 indices
[0] = sab
[0].lLbound
+ x
;
1071 for (y
= 0; y
< sab
[1].cElements
; y
++)
1073 indices
[1] = sab
[1].lLbound
+ y
;
1074 for (z
= 0; z
< sab
[2].cElements
; z
++)
1076 indices
[2] = sab
[2].lLbound
+ z
;
1077 for (a
= 0; a
< sab
[3].cElements
; a
++)
1079 indices
[3] = sab
[3].lLbound
+ a
;
1080 gotvalue
= value
/ 3;
1081 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1082 ok(hres
== S_OK
, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1085 ok(value
== gotvalue
, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1086 gotvalue
, value
, x
, y
, z
, a
);
1092 hres
= SafeArrayDestroy(sa
);
1093 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1096 static void test_SafeArrayGetPutElement_BSTR(void)
1102 BSTR value
= 0, gotvalue
;
1103 const OLECHAR szTest
[5] = { 'T','e','s','t','\0' };
1108 sa
= SafeArrayCreate(VT_BSTR
, 1, &sab
);
1109 ok(sa
!= NULL
, "BSTR test couldn't create array\n");
1113 ok(sa
->cbElements
== sizeof(BSTR
), "BSTR size mismatch\n");
1114 if (sa
->cbElements
!= sizeof(BSTR
))
1117 indices
[0] = sab
.lLbound
;
1118 value
= SysAllocString(szTest
);
1119 ok (value
!= NULL
, "Expected non-NULL\n");
1120 hres
= SafeArrayPutElement(sa
, indices
, value
);
1121 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1123 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1124 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1126 ok(SysStringLen(value
) == SysStringLen(gotvalue
), "Got len %d instead of %d\n", SysStringLen(gotvalue
), SysStringLen(value
));
1127 hres
= SafeArrayDestroy(sa
);
1128 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1129 SysFreeString(value
);
1130 SysFreeString(gotvalue
);
1134 IUnknown IUnknown_iface
;
1137 static const IUnknownVtbl xtunk_vtbl
;
1139 static struct xtunk_impl xtunk
= {{&xtunk_vtbl
}, 0};
1141 static HRESULT WINAPI
tunk_QueryInterface(IUnknown
*punk
, REFIID riid
, void **x
)
1146 static ULONG WINAPI
tunk_AddRef(IUnknown
*punk
)
1151 static ULONG WINAPI
tunk_Release(IUnknown
*punk
)
1156 static const IUnknownVtbl xtunk_vtbl
= {
1157 tunk_QueryInterface
,
1162 static void test_SafeArrayGetPutElement_IUnknown(void)
1172 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1173 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1177 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1178 if (sa
->cbElements
!= sizeof(LPUNKNOWN
))
1181 indices
[0] = sab
.lLbound
;
1183 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1184 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1185 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1187 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1188 ok(xtunk
.ref
== 3,"Failed to increment refcount of iface.\n");
1189 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1191 ok(gotvalue
== &xtunk
.IUnknown_iface
, "Got %p instead of %p\n", gotvalue
, &xtunk
.IUnknown_iface
);
1192 hres
= SafeArrayDestroy(sa
);
1193 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1194 ok(xtunk
.ref
== 2,"Failed to decrement refcount of iface.\n");
1197 static void test_SafeArrayRedim_IUnknown(void)
1206 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1207 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1211 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1212 if (sa
->cbElements
!= sizeof(LPUNKNOWN
))
1217 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1218 ok(hres
== S_OK
, "Failed to put IUnknown element hres 0x%x\n", hres
);
1219 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1221 hres
= SafeArrayRedim(sa
, &sab
);
1222 ok(hres
== S_OK
, "Failed to shrink array hres 0x%x\n", hres
);
1223 ok(xtunk
.ref
== 1, "Failed to decrement refcount\n");
1224 hres
= SafeArrayDestroy(sa
);
1225 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1228 static void test_SafeArrayGetPutElement_VARIANT(void)
1234 VARIANT value
, gotvalue
;
1238 sa
= SafeArrayCreate(VT_VARIANT
, 1, &sab
);
1239 ok(sa
!= NULL
, "VARIANT test couldn't create array\n");
1243 ok(sa
->cbElements
== sizeof(VARIANT
), "VARIANT size mismatch\n");
1244 if (sa
->cbElements
!= sizeof(VARIANT
))
1247 indices
[0] = sab
.lLbound
;
1248 V_VT(&value
) = VT_I4
;
1249 V_I4(&value
) = 0x42424242;
1250 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1251 ok(hres
== S_OK
, "Failed to put Variant I4 element hres 0x%x\n", hres
);
1253 V_VT(&gotvalue
) = 0xdead;
1254 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1255 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1257 V_VT(&gotvalue
) = VT_EMPTY
;
1258 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1259 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1261 ok(V_VT(&value
) == V_VT(&gotvalue
), "Got type 0x%x instead of 0x%x\n", V_VT(&value
), V_VT(&gotvalue
));
1262 if (V_VT(&value
) == V_VT(&gotvalue
))
1263 ok(V_I4(&value
) == V_I4(&gotvalue
), "Got %d instead of %d\n", V_I4(&value
), V_VT(&gotvalue
));
1265 hres
= SafeArrayDestroy(sa
);
1266 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1270 static void test_SafeArrayCopyData(void)
1272 SAFEARRAYBOUND sab
[4];
1276 int dimension
,size
=1;
1278 if (!pSafeArrayCopyData
)
1280 win_skip("SafeArrayCopyData not supported\n");
1284 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1286 sab
[dimension
].lLbound
= dimension
* 2 + 2;
1287 sab
[dimension
].cElements
= dimension
* 3 + 1;
1288 size
*= sab
[dimension
].cElements
;
1291 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1292 ok(sa
!= NULL
, "Copy test couldn't create array\n");
1293 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1294 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1299 ok(sa
->cbElements
== sizeof(int), "int size mismatch\n");
1300 if (sa
->cbElements
!= sizeof(int))
1303 /* Fill the source array with some data; it doesn't matter what */
1304 for (dimension
= 0; dimension
< size
; dimension
++)
1306 int* data
= sa
->pvData
;
1307 data
[dimension
] = dimension
;
1310 hres
= pSafeArrayCopyData(sa
, sacopy
);
1311 ok(hres
== S_OK
, "copy data failed hres 0x%x\n", hres
);
1314 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1318 hres
= pSafeArrayCopyData(NULL
, sacopy
);
1319 ok(hres
== E_INVALIDARG
, "Null copy source hres 0x%x\n", hres
);
1320 hres
= pSafeArrayCopyData(sa
, NULL
);
1321 ok(hres
== E_INVALIDARG
, "Null copy hres 0x%x\n", hres
);
1323 sacopy
->rgsabound
[0].cElements
+= 1;
1324 hres
= pSafeArrayCopyData(sa
, sacopy
);
1325 ok(hres
== E_INVALIDARG
, "Bigger copy first dimension hres 0x%x\n", hres
);
1327 sacopy
->rgsabound
[0].cElements
-= 2;
1328 hres
= pSafeArrayCopyData(sa
, sacopy
);
1329 ok(hres
== E_INVALIDARG
, "Smaller copy first dimension hres 0x%x\n", hres
);
1330 sacopy
->rgsabound
[0].cElements
+= 1;
1332 sacopy
->rgsabound
[3].cElements
+= 1;
1333 hres
= pSafeArrayCopyData(sa
, sacopy
);
1334 ok(hres
== E_INVALIDARG
, "Bigger copy last dimension hres 0x%x\n", hres
);
1336 sacopy
->rgsabound
[3].cElements
-= 2;
1337 hres
= pSafeArrayCopyData(sa
, sacopy
);
1338 ok(hres
== E_INVALIDARG
, "Smaller copy last dimension hres 0x%x\n", hres
);
1339 sacopy
->rgsabound
[3].cElements
+= 1;
1341 hres
= SafeArrayDestroy(sacopy
);
1342 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1344 hres
= pSafeArrayCopyData(sa
, sacopy
);
1345 ok(hres
== E_INVALIDARG
, "->Null copy hres 0x%x\n", hres
);
1347 hres
= SafeArrayCopy(sa
, &sacopy
);
1348 ok(hres
== S_OK
, "copy failed hres 0x%x\n", hres
);
1351 ok(SafeArrayGetElemsize(sa
) == SafeArrayGetElemsize(sacopy
),"elemsize wrong\n");
1352 ok(SafeArrayGetDim(sa
) == SafeArrayGetDim(sacopy
),"dimensions wrong\n");
1353 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1354 hres
= SafeArrayDestroy(sacopy
);
1355 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1358 hres
= SafeArrayDestroy(sa
);
1359 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1362 static void test_SafeArrayCreateEx(void)
1364 IRecordInfoImpl
* iRec
;
1365 SAFEARRAYBOUND sab
[4];
1370 if (!pSafeArrayCreateEx
)
1372 win_skip("SafeArrayCreateEx not supported\n");
1376 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1378 sab
[dimension
].lLbound
= 0;
1379 sab
[dimension
].cElements
= 8;
1383 sa
= pSafeArrayCreateEx(VT_UI1
, 1, NULL
, NULL
);
1384 ok(sa
== NULL
, "CreateEx NULL bounds didn't fail\n");
1386 /* test IID storage & defaulting */
1387 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, (PVOID
)&IID_ITypeInfo
);
1388 ok(sa
!= NULL
, "CreateEx (ITypeInfo) failed\n");
1393 if (pSafeArrayGetIID
)
1395 hres
= pSafeArrayGetIID(sa
, &guid
);
1396 ok(hres
== S_OK
, "CreateEx (ITypeInfo) no IID hres 0x%x\n", hres
);
1399 ok(IsEqualGUID(&guid
, &IID_ITypeInfo
), "CreateEx (ITypeInfo) bad IID\n");
1402 if (pSafeArraySetIID
)
1404 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
1405 ok(hres
== S_OK
, "Failed to set IID, hres = %8x\n", hres
);
1406 if (hres
== S_OK
&& pSafeArrayGetIID
)
1408 hres
= pSafeArrayGetIID(sa
, &guid
);
1409 ok(hres
== S_OK
&& IsEqualGUID(&guid
, &IID_IUnknown
), "Set bad IID\n");
1412 hres
= SafeArrayDestroy(sa
);
1413 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1416 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, NULL
);
1417 ok(sa
!= NULL
, "CreateEx (NULL) failed\n");
1422 if (pSafeArrayGetIID
)
1424 hres
= pSafeArrayGetIID(sa
, &guid
);
1425 ok(hres
== S_OK
, "CreateEx (NULL) no IID hres 0x%x\n", hres
);
1428 ok(IsEqualGUID(&guid
, &IID_IDispatch
), "CreateEx (NULL) bad IID\n");
1431 hres
= SafeArrayDestroy(sa
);
1432 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1435 sa
= pSafeArrayCreateEx(VT_UNKNOWN
, 1, sab
, NULL
);
1436 ok(sa
!= NULL
, "CreateEx (NULL-Unk) failed\n");
1441 if (pSafeArrayGetIID
)
1443 hres
= pSafeArrayGetIID(sa
, &guid
);
1444 ok(hres
== S_OK
, "CreateEx (NULL-Unk) no IID hres 0x%x\n", hres
);
1447 ok(IsEqualGUID(&guid
, &IID_IUnknown
), "CreateEx (NULL-Unk) bad IID\n");
1450 hres
= SafeArrayDestroy(sa
);
1451 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1454 /* VT_RECORD failure case */
1455 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, NULL
);
1456 ok(sa
== NULL
, "CreateEx (NULL-Rec) succeeded\n");
1458 iRec
= IRecordInfoImpl_Construct();
1460 /* Win32 doesn't care if GetSize fails */
1461 fail_GetSize
= TRUE
;
1462 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, iRec
);
1463 ok(sa
!= NULL
, "CreateEx (Fail Size) failed\n");
1464 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1465 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1466 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1469 ok(sa
->cbElements
== RECORD_SIZE_FAIL
, "Altered size to %d\n", sa
->cbElements
);
1470 hres
= SafeArrayDestroy(sa
);
1471 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1472 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1473 ok(iRec
->ref
== START_REF_COUNT
, "got %d, expected %d\n", iRec
->ref
, START_REF_COUNT
);
1476 /* Test VT_RECORD array */
1477 fail_GetSize
= FALSE
;
1478 iRec
->ref
= START_REF_COUNT
;
1479 iRec
->sizeCalled
= 0;
1480 iRec
->clearCalled
= 0;
1481 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, iRec
);
1482 ok(sa
!= NULL
, "CreateEx (Rec) failed\n");
1483 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1484 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1485 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1486 if (sa
&& pSafeArrayGetRecordInfo
)
1488 IRecordInfo
* saRec
= NULL
;
1489 hres
= pSafeArrayGetRecordInfo(sa
, &saRec
);
1491 ok(hres
== S_OK
,"GRI failed\n");
1492 ok(saRec
== &iRec
->IRecordInfo_iface
, "Different saRec\n");
1493 ok(iRec
->ref
== START_REF_COUNT
+ 2, "Didn't AddRef %d\n", iRec
->ref
);
1494 if (iRec
->ref
== START_REF_COUNT
+ 2)
1495 IRecordInfo_Release(saRec
);
1497 ok(sa
->cbElements
== RECORD_SIZE
,"Elemsize is %d\n", sa
->cbElements
);
1499 hres
= SafeArrayDestroy(sa
);
1500 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1501 ok(iRec
->sizeCalled
== 1, "Destroy->GetSize called %d times\n", iRec
->sizeCalled
);
1502 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1503 ok(iRec
->ref
== START_REF_COUNT
, "Wrong iRec refcount %d\n", iRec
->ref
);
1507 hres
= SafeArrayDestroy(sa
);
1508 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1511 IRecordInfo_Release(&iRec
->IRecordInfo_iface
);
1514 static void test_SafeArrayClear(void)
1523 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1524 ok(sa
!= NULL
, "Create() failed.\n");
1528 /* Test clearing non-NULL variants containing arrays */
1529 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1531 hres
= VariantClear(&v
);
1532 ok(hres
== S_OK
&& V_VT(&v
) == VT_EMPTY
, "VariantClear: hres 0x%x, Type %d\n", hres
, V_VT(&v
));
1533 ok(V_ARRAY(&v
) == sa
, "VariantClear: Overwrote value\n");
1535 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1536 ok(sa
!= NULL
, "Create() failed.\n");
1540 V_VT(&v
) = VT_SAFEARRAY
;
1542 hres
= VariantClear(&v
);
1543 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1545 V_VT(&v
) = VT_SAFEARRAY
|VT_BYREF
;
1546 V_ARRAYREF(&v
) = &sa
;
1547 hres
= VariantClear(&v
);
1548 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1550 hres
= SafeArrayDestroy(sa
);
1551 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1554 static void test_SafeArrayCopy(void)
1557 SAFEARRAY
*sa
, *sa2
;
1558 VARIANTARG vSrc
, vDst
;
1563 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1564 ok(sa
!= NULL
, "Create() failed.\n");
1568 /* Test copying non-NULL variants containing arrays */
1569 V_VT(&vSrc
) = (VT_ARRAY
|VT_BYREF
|VT_UI1
);
1570 V_ARRAYREF(&vSrc
) = &sa
;
1571 V_VT(&vDst
) = VT_EMPTY
;
1573 hres
= VariantCopy(&vDst
, &vSrc
);
1574 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_BYREF
|VT_UI1
),
1575 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1576 ok(V_ARRAYREF(&vDst
) == &sa
, "VariantClear: Performed deep copy\n");
1578 V_VT(&vSrc
) = (VT_ARRAY
|VT_UI1
);
1579 V_ARRAY(&vSrc
) = sa
;
1580 V_VT(&vDst
) = VT_EMPTY
;
1582 hres
= VariantCopy(&vDst
, &vSrc
);
1583 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_UI1
),
1584 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1585 ok(V_ARRAY(&vDst
) != sa
, "VariantClear: Performed shallow copy\n");
1587 hres
= SafeArrayDestroy(V_ARRAY(&vSrc
));
1588 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1589 hres
= SafeArrayDestroy(V_ARRAY(&vDst
));
1590 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1592 hres
= SafeArrayAllocDescriptor(1, &sa
);
1593 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1595 sa
->cbElements
= 16;
1596 hres
= SafeArrayCopy(sa
, &sa2
);
1597 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1598 ok(sa
!= sa2
, "SafeArrayCopy performed shallow copy\n");
1600 hres
= SafeArrayDestroy(sa2
);
1601 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1602 hres
= SafeArrayDestroy(sa
);
1603 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1605 sa2
= (void*)0xdeadbeef;
1606 hres
= SafeArrayCopy(NULL
, &sa2
);
1607 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1608 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1610 hres
= SafeArrayAllocDescriptor(1, &sa
);
1611 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1613 sa2
= (void*)0xdeadbeef;
1614 hres
= SafeArrayCopy(sa
, &sa2
);
1615 ok(hres
== E_INVALIDARG
,
1616 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1618 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1620 hres
= SafeArrayDestroy(sa2
);
1621 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1622 hres
= SafeArrayDestroy(sa
);
1623 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1626 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1627 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1629 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1631 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1632 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1633 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1635 static void test_SafeArrayChangeTypeEx(void)
1637 static const char *szHello
= "Hello World";
1644 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1645 MKARRAY(0,strlen(szHello
)+1,VT_UI1
);
1646 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1648 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1649 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1652 ok(V_VT(&v2
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2
));
1653 ok(strcmp((char*)V_BSTR(&v2
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1654 (char*)V_BSTR(&v2
));
1658 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1659 hres
= SafeArrayDestroy(sa
);
1660 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1661 if (pSafeArrayCreateVector
)
1663 sa
= pSafeArrayCreateVector(VT_UI1
, 0, strlen(szHello
)+1);
1664 ok(sa
!= NULL
, "CreateVector() failed.\n");
1668 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1669 V_VT(&v
) = VT_VECTOR
|VT_UI1
;
1673 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1674 ok(hres
== DISP_E_BADVARTYPE
, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres
);
1676 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1677 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1678 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
1679 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1682 ok(V_VT(&v
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v
));
1683 ok(strcmp((char*)V_BSTR(&v
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1689 /* To/from BSTR only works with arrays of VT_UI1 */
1690 for (vt
= VT_EMPTY
; vt
<= VT_CLSID
; vt
++)
1697 sa
= SafeArrayCreate(vt
, 1, &sab
);
1700 V_VT(&v
) = VT_ARRAY
|vt
;
1704 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1705 if (vt
== VT_INT_PTR
|| vt
== VT_UINT_PTR
)
1707 ok(hres
== DISP_E_BADVARTYPE
, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres
);
1708 SafeArrayDestroy(sa
);
1712 ok(hres
== DISP_E_TYPEMISMATCH
, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres
, vt
);
1713 hres
= VariantClear(&v
);
1714 ok(hres
== S_OK
, "expected S_OK, got 0x%08x\n", hres
);
1719 /* Can't change an array of one type into array of another type , even
1720 * if the other type is the same size
1722 if (pSafeArrayCreateVector
)
1724 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1725 ok(sa
!= NULL
, "CreateVector() failed.\n");
1729 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1731 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_I1
);
1732 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres
);
1734 /* But can change to the same array type */
1735 hres
= SafeArrayDestroy(sa
);
1736 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1737 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1738 ok(sa
!= NULL
, "CreateVector() failed.\n");
1741 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1743 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_UI1
);
1744 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres
);
1745 hres
= SafeArrayDestroy(sa
);
1746 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1751 MKARRAY(0,1,VT_UI1
);
1752 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_NULL
);
1753 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1755 MKARRAY(0,1,VT_UI1
);
1756 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_EMPTY
);
1757 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1761 static void test_SafeArrayDestroyData (void)
1766 int value
= 0xdeadbeef;
1768 void HUGEP
*temp_pvData
;
1772 sa
= SafeArrayCreate(VT_INT
, 1, &sab
);
1773 ok(sa
!= NULL
, "Create() failed.\n");
1777 SafeArrayPutElement (sa
, index
, &value
);
1779 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1780 sa
->fFeatures
|= FADF_STATIC
;
1781 temp_pvData
= sa
->pvData
;
1782 hres
= SafeArrayDestroyData(sa
);
1783 ok(hres
== S_OK
, "SADData FADF_STATIC failed, error code %x.\n",hres
);
1784 ok(sa
->pvData
== temp_pvData
, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1785 sa
->pvData
, temp_pvData
, sa
->fFeatures
);
1786 SafeArrayGetElement (sa
, index
, &value
);
1787 ok(value
== 0, "Data not cleared after SADData\n");
1789 /* Clear FADF_STATIC, now really destroy the data. */
1790 sa
->fFeatures
^= FADF_STATIC
;
1791 hres
= SafeArrayDestroyData(sa
);
1792 ok(hres
== S_OK
, "SADData !FADF_STATIC failed, error code %x.\n",hres
);
1793 ok(sa
->pvData
== NULL
, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa
->pvData
);
1795 hres
= SafeArrayDestroy(sa
);
1796 ok(hres
== S_OK
, "SAD failed, error code %x.\n", hres
);
1799 START_TEST(safearray
)
1801 hOleaut32
= GetModuleHandleA("oleaut32.dll");
1803 GETPTR(SafeArrayAllocDescriptorEx
);
1804 GETPTR(SafeArrayCopyData
);
1805 GETPTR(SafeArrayGetIID
);
1806 GETPTR(SafeArraySetIID
);
1807 GETPTR(SafeArrayGetVartype
);
1808 GETPTR(SafeArrayCreateEx
);
1809 GETPTR(SafeArrayCreateVector
);
1810 GETPTR(SafeArrayGetRecordInfo
);
1812 check_for_VT_INT_PTR();
1814 test_SafeArrayAllocDestroyDescriptor();
1815 test_SafeArrayCreateLockDestroy();
1816 test_VectorCreateLockDestroy();
1818 test_SafeArrayChangeTypeEx();
1819 test_SafeArrayCopy();
1820 test_SafeArrayClear();
1821 test_SafeArrayCreateEx();
1822 test_SafeArrayCopyData();
1823 test_SafeArrayDestroyData();
1824 test_SafeArrayGetPutElement();
1825 test_SafeArrayGetPutElement_BSTR();
1826 test_SafeArrayGetPutElement_IUnknown();
1827 test_SafeArrayRedim_IUnknown();
1828 test_SafeArrayGetPutElement_VARIANT();