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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 I8/UI8 data type? */
61 #define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
62 /* Have the decimal type? */
63 #define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
64 /* very old version? */
65 #define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
67 #define START_REF_COUNT 1
68 #define RECORD_SIZE 64
69 #define RECORD_SIZE_FAIL 17
70 /************************************************************************
71 * Dummy IRecordInfo Implementation
73 typedef struct IRecordInfoImpl
75 IRecordInfoVtbl
*lpvtbl
;
81 static IRecordInfoVtbl IRecordInfoImpl_VTable
;
83 static IRecordInfoImpl
*IRecordInfoImpl_Construct()
87 rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl
));
88 rec
->lpvtbl
= &IRecordInfoImpl_VTable
;
89 rec
->ref
= START_REF_COUNT
;
95 static ULONG CALLBACK
IRecordInfoImpl_AddRef(IRecordInfo
*iface
)
97 ICOM_THIS(IRecordInfoImpl
, iface
);
101 static ULONG CALLBACK
IRecordInfoImpl_Release(IRecordInfo
*iface
)
103 ICOM_THIS(IRecordInfoImpl
, iface
);
107 static BOOL fail_GetSize
; /* Whether to fail the GetSize call */
109 static HRESULT CALLBACK
IRecordInfoImpl_RecordClear(IRecordInfo
*iface
, PVOID pvExisting WINE_UNUSED
)
111 ICOM_THIS(IRecordInfoImpl
, iface
);
116 static HRESULT CALLBACK
IRecordInfoImpl_GetSize(IRecordInfo
*iface
, ULONG
* size
)
118 ICOM_THIS(IRecordInfoImpl
, iface
);
127 static HRESULT CALLBACK
IRecordInfoImpl_Dummy(IRecordInfo
*iface WINE_UNUSED
)
129 trace("Called an unexpected IRecordInfo method - please report!\n");
130 /* Quit because we'll just crash anyway */
135 static IRecordInfoVtbl IRecordInfoImpl_VTable
=
137 (PVOID
)IRecordInfoImpl_Dummy
,
138 IRecordInfoImpl_AddRef
,
139 IRecordInfoImpl_Release
,
140 (PVOID
)IRecordInfoImpl_Dummy
,
141 IRecordInfoImpl_RecordClear
,
142 (PVOID
)IRecordInfoImpl_Dummy
,
143 (PVOID
)IRecordInfoImpl_Dummy
,
144 (PVOID
)IRecordInfoImpl_Dummy
,
145 (PVOID
)IRecordInfoImpl_GetSize
,
146 (PVOID
)IRecordInfoImpl_Dummy
,
147 (PVOID
)IRecordInfoImpl_Dummy
,
148 (PVOID
)IRecordInfoImpl_Dummy
,
149 (PVOID
)IRecordInfoImpl_Dummy
,
150 (PVOID
)IRecordInfoImpl_Dummy
,
151 (PVOID
)IRecordInfoImpl_Dummy
,
152 (PVOID
)IRecordInfoImpl_Dummy
,
153 (PVOID
)IRecordInfoImpl_Dummy
,
154 (PVOID
)IRecordInfoImpl_Dummy
,
155 (PVOID
)IRecordInfoImpl_Dummy
158 static DWORD
SAFEARRAY_GetVTSize(VARTYPE vt
)
163 case VT_UI1
: return sizeof(BYTE
);
166 case VT_UI2
: return sizeof(SHORT
);
170 case VT_ERROR
: return sizeof(LONG
);
174 if (HAVE_OLEAUT32_I8
)
175 return sizeof(LONG64
);
178 case VT_UINT
: return sizeof(INT
);
180 case VT_UINT_PTR
: return sizeof(UINT_PTR
);
181 case VT_CY
: return sizeof(CY
);
182 case VT_DATE
: return sizeof(DATE
);
183 case VT_BSTR
: return sizeof(BSTR
);
184 case VT_DISPATCH
: return sizeof(LPDISPATCH
);
185 case VT_VARIANT
: return sizeof(VARIANT
);
186 case VT_UNKNOWN
: return sizeof(LPUNKNOWN
);
188 if (HAVE_OLEAUT32_DECIMAL
)
189 return sizeof(DECIMAL
);
195 #define VARTYPE_NOT_SUPPORTED 0
198 UINT elemsize
; /* elementsize by VT */
199 UINT expflags
; /* fFeatures from SafeArrayAllocDescriptorEx */
200 UINT addflags
; /* additional fFeatures from SafeArrayCreate */
202 {VT_EMPTY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
203 {VT_NULL
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
204 {VT_I2
, 2, FADF_HAVEVARTYPE
,0},
205 {VT_I4
, 4, FADF_HAVEVARTYPE
,0},
206 {VT_R4
, 4, FADF_HAVEVARTYPE
,0},
207 {VT_R8
, 8, FADF_HAVEVARTYPE
,0},
208 {VT_CY
, 8, FADF_HAVEVARTYPE
,0},
209 {VT_DATE
, 8, FADF_HAVEVARTYPE
,0},
210 {VT_BSTR
, sizeof(BSTR
), FADF_HAVEVARTYPE
,FADF_BSTR
},
211 {VT_DISPATCH
, sizeof(LPDISPATCH
), FADF_HAVEIID
, FADF_DISPATCH
},
212 {VT_ERROR
, 4, FADF_HAVEVARTYPE
,0},
213 {VT_BOOL
, 2, FADF_HAVEVARTYPE
,0},
214 {VT_VARIANT
, sizeof(VARIANT
), FADF_HAVEVARTYPE
,FADF_VARIANT
},
215 {VT_UNKNOWN
, sizeof(LPUNKNOWN
), FADF_HAVEIID
, FADF_UNKNOWN
},
216 {VT_DECIMAL
, sizeof(DECIMAL
), FADF_HAVEVARTYPE
,0},
217 {15, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0}, /* no VT_xxx */
218 {VT_I1
, 1, FADF_HAVEVARTYPE
,0},
219 {VT_UI1
, 1, FADF_HAVEVARTYPE
,0},
220 {VT_UI2
, 2, FADF_HAVEVARTYPE
,0},
221 {VT_UI4
, 4, FADF_HAVEVARTYPE
,0},
222 {VT_I8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
223 {VT_UI8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
224 {VT_INT
, sizeof(INT
), FADF_HAVEVARTYPE
,0},
225 {VT_UINT
, sizeof(UINT
), FADF_HAVEVARTYPE
,0},
226 {VT_VOID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
227 {VT_HRESULT
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
228 {VT_PTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
229 {VT_SAFEARRAY
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
230 {VT_CARRAY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
231 {VT_USERDEFINED
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
232 {VT_LPSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
233 {VT_LPWSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
234 {VT_FILETIME
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
235 {VT_RECORD
, VARTYPE_NOT_SUPPORTED
,FADF_RECORD
,0},
236 {VT_BLOB
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
237 {VT_STREAM
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
238 {VT_STORAGE
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
239 {VT_STREAMED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
240 {VT_STORED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
241 {VT_BLOB_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
242 {VT_CF
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
243 {VT_CLSID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
246 static void test_safearray(void)
252 SAFEARRAYBOUND bound
, bounds
[2];
258 unsigned char *ptr1
, *ptr2
;
262 a
= SafeArrayCreate(-1, 1, &bound
);
263 ok(NULL
== a
,"SAC(-1,1,[1,0]) not failed?\n");
267 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
268 ok(NULL
!= a
,"SAC(VT_I4,1,[0,0]) failed.\n");
270 hres
= SafeArrayGetLBound(a
, 1, &l
);
271 ok(hres
== S_OK
, "SAGLB of 0 size dimensioned array failed with %lx\n",hres
);
272 ok(l
== 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %ld\n",l
);
273 hres
= SafeArrayGetUBound(a
, 1, &l
);
274 ok(hres
== S_OK
, "SAGUB of 0 size dimensioned array failed with %lx\n",hres
);
275 ok(l
== 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %ld\n",l
);
277 hres
= SafeArrayRedim(a
, &bound
);
278 ok(hres
== S_OK
,"SAR of a 0 elements dimension failed with hres %lx\n", hres
);
280 hres
= SafeArrayRedim(a
, &bound
);
281 ok(hres
== S_OK
|| hres
== E_OUTOFMEMORY
,
282 "SAR to a 0 elements dimension failed with hres %lx\n", hres
);
283 hres
= SafeArrayDestroy(a
);
284 ok(hres
== S_OK
,"SAD of 0 dim array faild with hres %lx\n", hres
);
286 bounds
[0].cElements
= 0; bounds
[0].lLbound
= 1;
287 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
288 a
= SafeArrayCreate(VT_I4
,2,bounds
);
289 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
290 bounds
[0].cElements
= 1; bounds
[0].lLbound
= 1;
291 bounds
[1].cElements
= 0; bounds
[1].lLbound
= 23;
292 a
= SafeArrayCreate(VT_I4
,2,bounds
);
293 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
295 bounds
[0].cElements
= 42; bounds
[0].lLbound
= 1;
296 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
297 a
= SafeArrayCreate(VT_I4
,2,bounds
);
298 ok(a
!= NULL
,"SAC(VT_INT32,2,...) failed.\n");
300 hres
= SafeArrayGetLBound (a
, 0, &l
);
301 ok (hres
== DISP_E_BADINDEX
, "SAGLB 0 failed with %lx\n", hres
);
302 hres
= SafeArrayGetLBound (a
, 1, &l
);
303 ok (hres
== S_OK
, "SAGLB 1 failed with %lx\n", hres
);
304 ok (l
== 1, "SAGLB 1 returned %ld instead of 1\n", l
);
305 hres
= SafeArrayGetLBound (a
, 2, &l
);
306 ok (hres
== S_OK
, "SAGLB 2 failed with %lx\n", hres
);
307 ok (l
== 23, "SAGLB 2 returned %ld instead of 23\n", l
);
308 hres
= SafeArrayGetLBound (a
, 3, &l
);
309 ok (hres
== DISP_E_BADINDEX
, "SAGLB 3 failed with %lx\n", hres
);
311 hres
= SafeArrayGetUBound (a
, 0, &l
);
312 ok (hres
== DISP_E_BADINDEX
, "SAGUB 0 failed with %lx\n", hres
);
313 hres
= SafeArrayGetUBound (a
, 1, &l
);
314 ok (hres
== S_OK
, "SAGUB 1 failed with %lx\n", hres
);
315 ok (l
== 42, "SAGUB 1 returned %ld instead of 42\n", l
);
316 hres
= SafeArrayGetUBound (a
, 2, &l
);
317 ok (hres
== S_OK
, "SAGUB 2 failed with %lx\n", hres
);
318 ok (l
== 24, "SAGUB 2 returned %ld instead of 24\n", l
);
319 hres
= SafeArrayGetUBound (a
, 3, &l
);
320 ok (hres
== DISP_E_BADINDEX
, "SAGUB 3 failed with %lx\n", hres
);
322 i
= SafeArrayGetDim(a
);
323 ok(i
== 2, "getdims of 2 din array returned %d\n",i
);
327 hres
= SafeArrayGetElement(a
, indices
, &i
);
328 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [0,23], hres 0x%lx\n",hres
);
332 hres
= SafeArrayGetElement(a
, indices
, &i
);
333 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,22], hres 0x%lx\n",hres
);
337 hres
= SafeArrayGetElement(a
, indices
, &i
);
338 ok(S_OK
== hres
,"SAGE failed [1,23], hres 0x%lx\n",hres
);
342 hres
= SafeArrayGetElement(a
, indices
, &i
);
343 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,24], hres 0x%lx\n",hres
);
347 hres
= SafeArrayGetElement(a
, indices
, &i
);
348 ok(S_OK
== hres
,"SAGE failed [42,23], hres 0x%lx\n",hres
);
350 hres
= SafeArrayAccessData(a
, (void**)&ptr1
);
351 ok(S_OK
== hres
, "SAAD failed with 0x%lx\n", hres
);
355 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
356 ok(S_OK
== hres
,"SAPOI failed [1,23], hres 0x%lx\n",hres
);
357 ok(ptr2
- ptr1
== 8,"ptr difference is not 8, but %d (%p vs %p)\n", ptr2
-ptr1
, ptr2
, ptr1
);
361 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
362 ok(S_OK
== hres
,"SAPOI failed [5,24], hres 0x%lx\n",hres
);
363 ok(ptr2
- ptr1
== 176,"ptr difference is not 176, but %d (%p vs %p)\n", ptr2
-ptr1
, ptr2
, ptr1
);
367 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
368 ok(S_OK
== hres
,"SAPOI failed [20,23], hres 0x%lx\n",hres
);
369 ok(ptr2
- ptr1
== 76,"ptr difference is not 76, but %d (%p vs %p)\n", ptr2
-ptr1
, ptr2
, ptr1
);
371 hres
= SafeArrayUnaccessData(a
);
372 ok(S_OK
== hres
, "SAUAD failed with 0x%lx\n", hres
);
374 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
375 if ((i
== VT_I8
|| i
== VT_UI8
) && HAVE_OLEAUT32_I8
)
377 vttypes
[i
].elemsize
= sizeof(LONG64
);
380 a
= SafeArrayCreate(vttypes
[i
].vt
, 1, &bound
);
382 ok((!a
&& !vttypes
[i
].elemsize
) ||
383 (a
&& vttypes
[i
].elemsize
== a
->cbElements
) ||
384 (IS_ANCIENT
&& (vttypes
[i
].vt
== VT_DECIMAL
|| vttypes
[i
].vt
== VT_I1
||
385 vttypes
[i
].vt
== VT_UI2
|| vttypes
[i
].vt
== VT_UI4
|| vttypes
[i
].vt
== VT_INT
||
386 vttypes
[i
].vt
== VT_UINT
)),
387 "SAC(%d,1,[1,0]), %p result %ld, expected %d\n",
388 vttypes
[i
].vt
,a
,(a
?a
->cbElements
:0),vttypes
[i
].elemsize
);
392 if (!HAVE_OLEAUT32_RECORD
)
393 vttypes
[i
].expflags
= 0;
394 ok(a
->fFeatures
== (vttypes
[i
].expflags
| vttypes
[i
].addflags
),
395 "SAC of %d returned feature flags %x, expected %x\n",
396 vttypes
[i
].vt
, a
->fFeatures
,
397 vttypes
[i
].expflags
|vttypes
[i
].addflags
);
398 ok(SafeArrayGetElemsize(a
) == vttypes
[i
].elemsize
,
399 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
400 vttypes
[i
].vt
, SafeArrayGetElemsize(a
),vttypes
[i
].elemsize
);
405 if (pSafeArrayGetVartype
)
407 hres
= pSafeArrayGetVartype(a
, &vt
);
408 ok(hres
== S_OK
, "SAGVT of arra y with vt %d failed with %lx\n", vttypes
[i
].vt
, hres
);
409 if (vttypes
[i
].vt
== VT_DISPATCH
) {
410 /* Special case. Checked against Windows. */
411 ok(vt
== VT_UNKNOWN
, "SAGVT of a rray with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
413 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
417 hres
= SafeArrayCopy(a
, &c
);
418 ok(hres
== S_OK
, "failed to copy safearray of vt %d with hres %lx\n", vttypes
[i
].vt
, hres
);
420 ok(vttypes
[i
].elemsize
== c
->cbElements
,"copy of SAC(%d,1,[1,0]), result %ld, expected %d\n",vttypes
[i
].vt
,(c
?c
->cbElements
:0),vttypes
[i
].elemsize
422 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
);
423 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
);
425 if (pSafeArrayGetVartype
) {
426 hres
= pSafeArrayGetVartype(c
, &vt
);
427 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %lx\n", vttypes
[i
].vt
, hres
);
428 if (vttypes
[i
].vt
== VT_DISPATCH
) {
429 /* Special case. Checked against Windows. */
430 ok(vt
== VT_UNKNOWN
, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
432 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
436 if (pSafeArrayCopyData
) {
437 hres
= pSafeArrayCopyData(a
, c
);
438 ok(hres
== S_OK
, "failed to copy safearray data of vt %d with hres %lx\n", vttypes
[i
].vt
, hres
);
440 hres
= SafeArrayDestroyData(c
);
441 ok(hres
== S_OK
,"SADD of copy of array with vt %d failed with hres %lx\n", vttypes
[i
].vt
, hres
);
444 hres
= SafeArrayDestroy(a
);
445 ok(hres
== S_OK
,"SAD of array with vt %d failed with hres %lx\n", vttypes
[i
].vt
, hres
);
448 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
450 bound
.cElements
= 10;
451 a
= SafeArrayCreate(VT_UI1
, 1, &bound
);
452 ok(a
!= NULL
, "SAC failed.\n");
453 ok(S_OK
== SafeArrayAccessData(a
, &data
),"SACD failed\n");
454 memcpy(data
,"Hello World\n",10);
455 ok(S_OK
== SafeArrayUnaccessData(a
),"SAUD failed\n");
456 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
458 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
459 ok(hres
==S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n",hres
);
460 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
));
461 ok(V_BSTR(&v
)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v
)[0]);
463 /* check locking functions */
464 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
465 ok(a
!=NULL
,"SAC should not fail\n");
467 hres
= SafeArrayAccessData(a
, &data
);
468 ok(hres
== S_OK
,"SAAD failed with hres %lx\n",hres
);
470 hres
= SafeArrayDestroy(a
);
471 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres
);
473 hres
= SafeArrayDestroyData(a
);
474 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres
);
476 hres
= SafeArrayDestroyDescriptor(a
);
477 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %lx\n", hres
);
479 hres
= SafeArrayUnaccessData(a
);
480 ok(hres
== S_OK
,"SAUD failed after lock/destroy test\n");
482 hres
= SafeArrayDestroy(a
);
483 ok(hres
== S_OK
,"SAD failed after lock/destroy test\n");
485 /* Test if we need to destroy data before descriptor */
486 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
487 ok(a
!=NULL
,"SAC should not fail\n");
488 hres
= SafeArrayDestroyDescriptor(a
);
489 ok(hres
== S_OK
,"SADD with data in array failed with hres %lx\n",hres
);
493 /* init a small stack safearray */
494 if (pSafeArraySetIID
) {
495 memset(&b
, 0, sizeof(b
));
497 memset(&iid
, 0x42, sizeof(IID
));
498 hres
= pSafeArraySetIID(&b
,&iid
);
499 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %lx\n",hres
);
501 hres
= SafeArrayAllocDescriptor(1,&a
);
502 ok((a
->fFeatures
& FADF_HAVEIID
) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
503 hres
= pSafeArraySetIID(a
,&iid
);
504 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %lx\n",hres
);
507 if (!pSafeArrayAllocDescriptorEx
)
510 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
512 hres
= pSafeArrayAllocDescriptorEx(vttypes
[i
].vt
,1,&a
);
513 ok(a
->fFeatures
== vttypes
[i
].expflags
,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes
[i
].vt
, a
->fFeatures
, vttypes
[i
].expflags
);
514 if (a
->fFeatures
& FADF_HAVEIID
) {
515 hres
= pSafeArrayGetIID(a
, &iid
);
516 ok(hres
== S_OK
,"SAGIID failed for vt %d with hres %lx\n", vttypes
[i
].vt
,hres
);
517 switch (vttypes
[i
].vt
) {
519 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IUnknown
),"guid for VT_UNKNOWN is not IID_IUnknown\n");
520 ok(IsEqualGUID(&iid
, &IID_IUnknown
),"SAGIID returned wrong GUID for IUnknown\n");
523 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IDispatch
),"guid for VT_UNKNOWN is not IID_IDispatch\n");
524 ok(IsEqualGUID(&iid
, &IID_IDispatch
),"SAGIID returned wrong GUID for IDispatch\n");
527 ok(FALSE
,"unknown vt %d with FADF_HAVEIID\n",vttypes
[i
].vt
);
531 hres
= pSafeArrayGetIID(a
, &iid
);
532 ok(hres
== E_INVALIDARG
,"SAGIID did not fail for vt %d with hres %lx\n", vttypes
[i
].vt
,hres
);
534 if (a
->fFeatures
& FADF_RECORD
) {
535 ok(vttypes
[i
].vt
== VT_RECORD
,"FADF_RECORD for non record %d\n",vttypes
[i
].vt
);
537 if (a
->fFeatures
& FADF_HAVEVARTYPE
) {
538 ok(vttypes
[i
].vt
== ((DWORD
*)a
)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %ld\n",vttypes
[i
].vt
,((DWORD
*)a
)[-1]);
541 hres
= pSafeArrayGetVartype(a
, &vt
);
542 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %lx\n", vttypes
[i
].vt
, hres
);
544 if (vttypes
[i
].vt
== VT_DISPATCH
) {
545 /* Special case. Checked against Windows. */
546 ok(vt
== VT_UNKNOWN
, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
548 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
551 if (a
->fFeatures
& FADF_HAVEIID
) {
552 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
553 ok(hres
== S_OK
,"SASIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes
[i
].vt
, hres
);
554 hres
= pSafeArrayGetIID(a
, &iid
);
555 ok(hres
== S_OK
,"SAGIID failed with FADF_HAVEIID set for vt %d with %lx\n", vttypes
[i
].vt
, hres
);
556 ok(IsEqualGUID(&iid
, &IID_IStorage
),"returned iid is not IID_IStorage\n");
558 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
559 ok(hres
== E_INVALIDARG
,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %lx\n", vttypes
[i
].vt
, hres
);
561 hres
= SafeArrayDestroyDescriptor(a
);
562 ok(hres
== S_OK
,"SADD failed with hres %lx\n",hres
);
566 static void test_SafeArrayAllocDestroyDescriptor(void)
573 hres
= SafeArrayAllocDescriptor(0, &sa
);
574 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%lx\n", hres
);
576 hres
= SafeArrayAllocDescriptor(65536, &sa
);
577 ok(IS_ANCIENT
|| hres
== E_INVALIDARG
,
578 "65536 dimensions gave hres 0x%lx\n", hres
);
581 /* Crashes on 95: XP & Wine return E_POINTER */
582 hres
=SafeArrayAllocDescriptor(1, NULL
);
583 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%lx\n", hres
);
586 /* Test up to the dimension boundary case */
587 for (i
= 5; i
<= 65535; i
+= 30)
589 hres
= SafeArrayAllocDescriptor(i
, &sa
);
590 ok(hres
== S_OK
, "%d dimensions failed; hres 0x%lx\n", i
, hres
);
594 ok(SafeArrayGetDim(sa
) == (UINT
)i
, "Dimension is %d; should be %d\n",
595 SafeArrayGetDim(sa
), i
);
597 hres
= SafeArrayDestroyDescriptor(sa
);
598 ok(hres
== S_OK
, "destroy failed; hres 0x%lx\n", hres
);
602 if (!pSafeArrayAllocDescriptorEx
)
605 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 0, &sa
);
606 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%lx\n", hres
);
608 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 65536, &sa
);
609 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%lx\n", hres
);
611 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 1, NULL
);
612 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%lx\n", hres
);
615 static void test_SafeArrayCreateLockDestroy(void)
617 SAFEARRAYBOUND sab
[4];
623 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
625 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
627 sab
[dimension
].lLbound
= 0;
628 sab
[dimension
].cElements
= 8;
632 /* This test crashes very early versions with no error checking...
633 sa = SafeArrayCreate(VT_UI1, 1, NULL);
634 ok(sa == NULL, "NULL bounds didn't fail\n");
636 sa
= SafeArrayCreate(VT_UI1
, 65536, sab
);
637 ok(IS_ANCIENT
|| !sa
, "Max bounds didn't fail\n");
639 memset(sab
, 0, sizeof(sab
));
641 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
643 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
644 sab
[dimension
].cElements
= 8;
646 /* Test all VARTYPES in 1-4 dimensions */
647 for (dimension
= 1; dimension
< 4; dimension
++)
649 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
651 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
653 sa
= SafeArrayCreate(vt
, dimension
, sab
);
656 ok(sa
|| (IS_ANCIENT
&& (vt
== VT_DECIMAL
|| vt
== VT_I1
|| vt
== VT_UI2
||
657 vt
== VT_UI4
|| vt
== VT_INT
|| vt
== VT_UINT
|| vt
== VT_UINT_PTR
||
659 "VARTYPE %d (@%d dimensions) failed\n", vt
, dimension
);
661 ok(sa
== NULL
|| vt
== VT_R8
,
662 "VARTYPE %d (@%d dimensions) succeeded!\n", vt
, dimension
);
666 ok(SafeArrayGetDim(sa
) == (UINT
)dimension
,
667 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
668 vt
, dimension
, SafeArrayGetDim(sa
), dimension
);
669 ok(SafeArrayGetElemsize(sa
) == dwLen
|| vt
== VT_R8
,
670 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %ld\n",
671 vt
, dimension
, SafeArrayGetElemsize(sa
), dwLen
);
673 if (vt
!= VT_UNKNOWN
&& vt
!= VT_DISPATCH
)
675 ok((sa
->fFeatures
& FADF_HAVEIID
) == 0,
676 "Non interface type should not have FADF_HAVEIID\n");
677 if (pSafeArraySetIID
)
679 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
680 ok(hres
== E_INVALIDARG
,
681 "Non interface type allowed SetIID(), hres %lx\n", hres
);
687 ok(IS_ANCIENT
|| sa
->fFeatures
& FADF_HAVEVARTYPE
,
688 "Non interface type should have FADF_HAVEVARTYPE\n");
689 if (pSafeArrayGetVartype
)
691 hres
= pSafeArrayGetVartype(sa
, &aVt
);
692 ok(hres
== S_OK
&& aVt
== vt
,
693 "Non interface type %d: bad type %d, hres %lx\n", vt
, aVt
, hres
);
699 ok(IS_ANCIENT
|| sa
->fFeatures
& FADF_HAVEIID
,
700 "Interface type should have FADF_HAVEIID\n");
701 if (pSafeArraySetIID
)
703 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
705 "Non interface type disallowed SetIID(), hres %lx\n", hres
);
707 ok((sa
->fFeatures
& FADF_HAVEVARTYPE
) == 0,
708 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt
);
711 hres
= SafeArrayLock(sa
);
712 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%lx\n",
713 vt
, dimension
, hres
);
717 hres
= SafeArrayDestroy(sa
);
718 ok(hres
== DISP_E_ARRAYISLOCKED
,"Destroy() got hres %lx\n", hres
);
720 hres
= SafeArrayDestroyData(sa
);
721 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyData() got hres %lx\n", hres
);
723 hres
= SafeArrayDestroyDescriptor(sa
);
724 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyDescriptor() got hres %lx\n", hres
);
726 hres
= SafeArrayUnlock(sa
);
727 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d dims) hres 0x%lx\n",
728 vt
, dimension
, hres
);
730 hres
= SafeArrayDestroyDescriptor(sa
);
731 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d dims) hres 0x%lx\n",
732 vt
, dimension
, hres
);
739 static void test_VectorCreateLockDestroy(void)
746 if (!pSafeArrayCreateVector
)
748 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 0);
749 ok(sa
!= NULL
, "SACV with 0 elements failed.\n");
751 /* Test all VARTYPES in different lengths */
752 for (element
= 1; element
<= 101; element
+= 10)
754 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
756 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
758 sa
= pSafeArrayCreateVector(vt
, 0, element
);
762 /* win2000 has a bug where U/INT_PTR aren't accepted */
763 ok(sa
!= NULL
|| vt
== VT_INT_PTR
|| vt
== VT_UINT_PTR
,
764 "VARTYPE %d (@%d elements) failed\n", vt
, element
);
767 ok(sa
== NULL
, "VARTYPE %d (@%d elements) succeeded!\n", vt
, element
);
771 ok(SafeArrayGetDim(sa
) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
772 vt
, element
, SafeArrayGetDim(sa
));
773 ok(SafeArrayGetElemsize(sa
) == dwLen
,
774 "VARTYPE %d (@%d elements) cbElements is %d, expected %ld\n",
775 vt
, element
, SafeArrayGetElemsize(sa
), dwLen
);
777 hres
= SafeArrayLock(sa
);
778 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
783 hres
= SafeArrayUnlock(sa
);
784 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
787 hres
= SafeArrayDestroyDescriptor(sa
);
788 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d elements) failed; hres 0x%lx\n",
796 static void test_LockUnlock(void)
798 SAFEARRAYBOUND sab
[4];
801 BOOL bVector
= FALSE
;
805 hres
= SafeArrayLock(NULL
);
806 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%lx\n", hres
);
807 hres
= SafeArrayUnlock(NULL
);
808 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%lx\n", hres
);
810 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
812 sab
[dimension
].lLbound
= 0;
813 sab
[dimension
].cElements
= 8;
816 sa
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
818 /* Test maximum locks */
819 test_LockUnlock_Vector
:
824 hres
= SafeArrayUnlock(sa
);
825 ok (hres
== E_UNEXPECTED
, "Bad %sUnlock gave hres 0x%lx\n",
826 bVector
? "vector " : "\n", hres
);
828 while ((hres
= SafeArrayLock(sa
)) == S_OK
)
830 ok (count
== 65535 && hres
== E_UNEXPECTED
, "Lock %sfailed at %d; hres 0x%lx\n",
831 bVector
? "vector " : "\n", count
, hres
);
833 if (count
== 65535 && hres
== E_UNEXPECTED
)
835 while ((hres
= SafeArrayUnlock(sa
)) == S_OK
)
837 ok (count
== 0 && hres
== E_UNEXPECTED
, "Unlock %sfailed at %d; hres 0x%lx\n",
838 bVector
? "vector " : "\n", count
, hres
);
841 SafeArrayDestroy(sa
);
844 if (bVector
== FALSE
&& pSafeArrayCreateVector
)
846 /* Test again with a vector */
847 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 100);
849 goto test_LockUnlock_Vector
;
853 static void test_SafeArrayGetPutElement(void)
855 SAFEARRAYBOUND sab
[4];
856 LONG indices
[NUM_DIMENSIONS
];
859 int value
= 0, gotvalue
, dimension
;
860 unsigned int x
,y
,z
,a
;
862 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
864 sab
[dimension
].lLbound
= dimension
* 2 + 1;
865 sab
[dimension
].cElements
= dimension
* 3 + 1;
868 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
870 return; /* Some early versions can't handle > 3 dims */
872 ok(sa
->cbElements
== sizeof(value
), "int size mismatch\n");
873 if (sa
->cbElements
!= sizeof(value
))
877 for (x
= 0; x
< NUM_DIMENSIONS
; x
++)
879 indices
[0] = sab
[0].lLbound
;
880 indices
[1] = sab
[1].lLbound
;
881 indices
[2] = sab
[2].lLbound
;
882 indices
[3] = sab
[3].lLbound
;
884 indices
[x
] = indices
[x
] - 1;
885 hres
= SafeArrayPutElement(sa
, indices
, &value
);
886 ok(hres
== DISP_E_BADINDEX
, "Put allowed too small index in dimension %d\n", x
);
887 hres
= SafeArrayGetElement(sa
, indices
, &value
);
888 ok(hres
== DISP_E_BADINDEX
, "Get allowed too small index in dimension %d\n", x
);
890 indices
[x
] = sab
[x
].lLbound
+ sab
[x
].cElements
;
891 hres
= SafeArrayPutElement(sa
, indices
, &value
);
892 ok(hres
== DISP_E_BADINDEX
, "Put allowed too big index in dimension %d\n", x
);
893 hres
= SafeArrayGetElement(sa
, indices
, &value
);
894 ok(hres
== DISP_E_BADINDEX
, "Get allowed too big index in dimension %d\n", x
);
897 indices
[0] = sab
[0].lLbound
;
898 indices
[1] = sab
[1].lLbound
;
899 indices
[2] = sab
[2].lLbound
;
900 indices
[3] = sab
[3].lLbound
;
902 hres
= SafeArrayPutElement(NULL
, indices
, &value
);
903 ok(hres
== E_INVALIDARG
, "Put NULL array hres 0x%lx\n", hres
);
904 hres
= SafeArrayGetElement(NULL
, indices
, &value
);
905 ok(hres
== E_INVALIDARG
, "Get NULL array hres 0x%lx\n", hres
);
907 hres
= SafeArrayPutElement(sa
, NULL
, &value
);
908 ok(hres
== E_INVALIDARG
, "Put NULL indices hres 0x%lx\n", hres
);
909 hres
= SafeArrayGetElement(sa
, NULL
, &value
);
910 ok(hres
== E_INVALIDARG
, "Get NULL indices hres 0x%lx\n", hres
);
913 /* This is retarded. Windows checks every case of invalid parameters
914 * except the following, which crashes. We ERR this in Wine.
916 hres
= SafeArrayPutElement(sa
, indices
, NULL
);
917 ok(hres
== E_INVALIDARG
, "Put NULL value hres 0x%lx\n", hres
);
920 hres
= SafeArrayGetElement(sa
, indices
, NULL
);
921 ok(hres
== E_INVALIDARG
, "Get NULL value hres 0x%lx\n", hres
);
925 /* Make sure we can read and get back the correct values in 4 dimensions,
926 * Each with a different size and lower bound.
928 for (x
= 0; x
< sab
[0].cElements
; x
++)
930 indices
[0] = sab
[0].lLbound
+ x
;
931 for (y
= 0; y
< sab
[1].cElements
; y
++)
933 indices
[1] = sab
[1].lLbound
+ y
;
934 for (z
= 0; z
< sab
[2].cElements
; z
++)
936 indices
[2] = sab
[2].lLbound
+ z
;
937 for (a
= 0; a
< sab
[3].cElements
; a
++)
939 indices
[3] = sab
[3].lLbound
+ a
;
940 hres
= SafeArrayPutElement(sa
, indices
, &value
);
941 ok(hres
== S_OK
, "Failed to put element at (%d,%d,%d,%d) hres 0x%lx\n",
951 for (x
= 0; x
< sab
[0].cElements
; x
++)
953 indices
[0] = sab
[0].lLbound
+ x
;
954 for (y
= 0; y
< sab
[1].cElements
; y
++)
956 indices
[1] = sab
[1].lLbound
+ y
;
957 for (z
= 0; z
< sab
[2].cElements
; z
++)
959 indices
[2] = sab
[2].lLbound
+ z
;
960 for (a
= 0; a
< sab
[3].cElements
; a
++)
962 indices
[3] = sab
[3].lLbound
+ a
;
963 gotvalue
= value
/ 3;
964 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
965 ok(hres
== S_OK
, "Failed to get element at (%d,%d,%d,%d) hres 0x%lx\n",
968 ok(value
== gotvalue
, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
969 gotvalue
, value
, x
, y
, z
, a
);
975 SafeArrayDestroy(sa
);
978 static void test_SafeArrayGetPutElement_BSTR(void)
984 BSTR value
= 0, gotvalue
;
985 const OLECHAR szTest
[5] = { 'T','e','s','t','\0' };
990 sa
= SafeArrayCreate(VT_BSTR
, 1, &sab
);
991 ok(sa
!= NULL
, "BSTR test couldn't create array\n");
995 ok(sa
->cbElements
== sizeof(BSTR
), "BSTR size mismatch\n");
996 if (sa
->cbElements
!= sizeof(BSTR
))
999 indices
[0] = sab
.lLbound
;
1000 value
= SysAllocString(szTest
);
1001 ok (value
!= NULL
, "Expected non-NULL\n");
1002 hres
= SafeArrayPutElement(sa
, indices
, value
);
1003 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%lx\n", hres
);
1005 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1006 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%lx\n", hres
);
1008 ok(SysStringLen(value
) == SysStringLen(gotvalue
), "Got len %d instead of %d\n", SysStringLen(gotvalue
), SysStringLen(value
));
1009 SafeArrayDestroy(sa
);
1012 static int tunk_xref
= 0;
1013 static HRESULT WINAPI
tunk_QueryInterface(LPUNKNOWN punk
,REFIID riid
, LPVOID
*x
) {
1016 static ULONG WINAPI
tunk_AddRef(LPUNKNOWN punk
) {
1020 static ULONG WINAPI
tunk_Release(LPUNKNOWN punk
) {
1024 static IUnknownVtbl xtunk_vtbl
= {
1025 tunk_QueryInterface
,
1030 static struct xtunk_iface
{
1031 IUnknownVtbl
*lpvtbl
;
1035 static void test_SafeArrayGetPutElement_IUnknown(void)
1041 LPUNKNOWN value
= 0, gotvalue
;
1045 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1046 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1050 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1051 if (sa
->cbElements
!= sizeof(LPUNKNOWN
))
1054 indices
[0] = sab
.lLbound
;
1055 xtunk_iface
.lpvtbl
= &xtunk_vtbl
;
1056 value
= (LPUNKNOWN
)&xtunk_iface
;
1058 ok (value
!= NULL
, "Expected non-NULL\n");
1059 hres
= SafeArrayPutElement(sa
, indices
, value
);
1060 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%lx\n", hres
);
1061 ok(tunk_xref
== 2,"Failed to increment refcount of iface.\n");
1063 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1064 ok(tunk_xref
== 3,"Failed to increment refcount of iface.\n");
1065 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%lx\n", hres
);
1067 ok(value
== gotvalue
, "Got %p instead of %p\n", gotvalue
, value
);
1068 SafeArrayDestroy(sa
);
1069 ok(tunk_xref
== 2,"Failed to decrement refcount of iface.\n");
1072 static void test_SafeArrayCopyData(void)
1074 SAFEARRAYBOUND sab
[4];
1078 int dimension
,size
=1;
1080 if (!pSafeArrayCopyData
)
1083 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1085 sab
[dimension
].lLbound
= dimension
* 2 + 2;
1086 sab
[dimension
].cElements
= dimension
* 3 + 1;
1087 size
*= sab
[dimension
].cElements
;
1090 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1091 ok(sa
!= NULL
, "Copy test couldn't create array\n");
1092 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1093 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1098 ok(sa
->cbElements
== sizeof(int), "int size mismatch\n");
1099 if (sa
->cbElements
!= sizeof(int))
1102 /* Fill the source array with some data; it doesn't matter what */
1103 for (dimension
= 0; dimension
< size
; dimension
++)
1105 int* data
= (int*)sa
->pvData
;
1106 data
[dimension
] = dimension
;
1109 hres
= pSafeArrayCopyData(sa
, sacopy
);
1110 ok(hres
== S_OK
, "copy data failed hres 0x%lx\n", hres
);
1113 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1117 hres
= pSafeArrayCopyData(NULL
, sacopy
);
1118 ok(hres
== E_INVALIDARG
, "Null copy source hres 0x%lx\n", hres
);
1119 hres
= pSafeArrayCopyData(sa
, NULL
);
1120 ok(hres
== E_INVALIDARG
, "Null copy hres 0x%lx\n", hres
);
1122 sacopy
->rgsabound
[0].cElements
+= 1;
1123 hres
= pSafeArrayCopyData(sa
, sacopy
);
1124 ok(hres
== E_INVALIDARG
, "Bigger copy first dimension hres 0x%lx\n", hres
);
1126 sacopy
->rgsabound
[0].cElements
-= 2;
1127 hres
= pSafeArrayCopyData(sa
, sacopy
);
1128 ok(hres
== E_INVALIDARG
, "Smaller copy first dimension hres 0x%lx\n", hres
);
1129 sacopy
->rgsabound
[0].cElements
+= 1;
1131 sacopy
->rgsabound
[3].cElements
+= 1;
1132 hres
= pSafeArrayCopyData(sa
, sacopy
);
1133 ok(hres
== E_INVALIDARG
, "Bigger copy last dimension hres 0x%lx\n", hres
);
1135 sacopy
->rgsabound
[3].cElements
-= 2;
1136 hres
= pSafeArrayCopyData(sa
, sacopy
);
1137 ok(hres
== E_INVALIDARG
, "Smaller copy last dimension hres 0x%lx\n", hres
);
1138 sacopy
->rgsabound
[3].cElements
+= 1;
1140 SafeArrayDestroy(sacopy
);
1142 hres
= pSafeArrayCopyData(sa
, sacopy
);
1143 ok(hres
== E_INVALIDARG
, "->Null copy hres 0x%lx\n", hres
);
1145 hres
= SafeArrayCopy(sa
, &sacopy
);
1146 ok(hres
== S_OK
, "copy failed hres 0x%lx\n", hres
);
1149 ok(SafeArrayGetElemsize(sa
) == SafeArrayGetElemsize(sacopy
),"elemsize wrong\n");
1150 ok(SafeArrayGetDim(sa
) == SafeArrayGetDim(sacopy
),"dimensions wrong\n");
1151 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1154 SafeArrayDestroy(sa
);
1157 static void test_SafeArrayCreateEx(void)
1159 IRecordInfoImpl
* iRec
;
1160 SAFEARRAYBOUND sab
[4];
1165 if (!pSafeArrayCreateEx
)
1168 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1170 sab
[dimension
].lLbound
= 0;
1171 sab
[dimension
].cElements
= 8;
1175 sa
= pSafeArrayCreateEx(VT_UI1
, 1, NULL
, NULL
);
1176 ok(sa
== NULL
, "CreateEx NULL bounds didn't fail\n");
1178 /* test IID storage & defaulting */
1179 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, (PVOID
)&IID_ITypeInfo
);
1180 ok(sa
!= NULL
, "CreateEx (ITypeInfo) failed\n");
1185 if (pSafeArrayGetIID
)
1187 hres
= pSafeArrayGetIID(sa
, &guid
);
1188 ok(hres
== S_OK
, "CreateEx (ITypeInfo) no IID hres 0x%lx\n", hres
);
1191 ok(IsEqualGUID(&guid
, &IID_ITypeInfo
), "CreateEx (ITypeInfo) bad IID\n");
1194 if (pSafeArraySetIID
)
1196 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
1197 ok(hres
== S_OK
, "Failed to set IID, hres = %8lx\n", hres
);
1198 if (hres
== S_OK
&& pSafeArrayGetIID
)
1200 hres
= pSafeArrayGetIID(sa
, &guid
);
1201 ok(hres
== S_OK
&& IsEqualGUID(&guid
, &IID_IUnknown
), "Set bad IID\n");
1204 SafeArrayDestroy(sa
);
1207 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, NULL
);
1208 ok(sa
!= NULL
, "CreateEx (NULL) failed\n");
1213 if (pSafeArrayGetIID
)
1215 hres
= pSafeArrayGetIID(sa
, &guid
);
1216 ok(hres
== S_OK
, "CreateEx (NULL) no IID hres 0x%lx\n", hres
);
1219 ok(IsEqualGUID(&guid
, &IID_IDispatch
), "CreateEx (NULL) bad IID\n");
1222 SafeArrayDestroy(sa
);
1225 sa
= pSafeArrayCreateEx(VT_UNKNOWN
, 1, sab
, NULL
);
1226 ok(sa
!= NULL
, "CreateEx (NULL-Unk) failed\n");
1231 if (pSafeArrayGetIID
)
1233 hres
= pSafeArrayGetIID(sa
, &guid
);
1234 ok(hres
== S_OK
, "CreateEx (NULL-Unk) no IID hres 0x%lx\n", hres
);
1237 ok(IsEqualGUID(&guid
, &IID_IUnknown
), "CreateEx (NULL-Unk) bad IID\n");
1240 SafeArrayDestroy(sa
);
1243 /* VT_RECORD failure case */
1244 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, NULL
);
1245 ok(sa
== NULL
, "CreateEx (NULL-Rec) succeded\n");
1247 iRec
= IRecordInfoImpl_Construct();
1249 /* Win32 doesn't care if GetSize fails */
1250 fail_GetSize
= TRUE
;
1251 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, (LPVOID
)iRec
);
1252 ok(sa
!= NULL
, "CreateEx (Fail Size) failed\n");
1253 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %ld\n", iRec
->ref
);
1254 ok(iRec
->sizeCalled
== 1, "GetSize called %ld times\n", iRec
->sizeCalled
);
1255 ok(iRec
->clearCalled
== 0, "Clear called %ld times\n", iRec
->clearCalled
);
1258 ok(sa
->cbElements
== RECORD_SIZE_FAIL
, "Altered size to %ld\n", sa
->cbElements
);
1259 SafeArrayDestroy(sa
);
1260 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %ld times\n", iRec
->clearCalled
);
1263 /* Test VT_RECORD array */
1264 fail_GetSize
= FALSE
;
1265 iRec
->ref
= START_REF_COUNT
;
1266 iRec
->sizeCalled
= 0;
1267 iRec
->clearCalled
= 0;
1268 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, (LPVOID
)iRec
);
1269 ok(sa
!= NULL
, "CreateEx (Rec) failed\n");
1270 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %ld\n", iRec
->ref
);
1271 ok(iRec
->sizeCalled
== 1, "GetSize called %ld times\n", iRec
->sizeCalled
);
1272 ok(iRec
->clearCalled
== 0, "Clear called %ld times\n", iRec
->clearCalled
);
1273 if (sa
&& pSafeArrayGetRecordInfo
)
1275 IRecordInfo
* saRec
= NULL
;
1276 hres
= pSafeArrayGetRecordInfo(sa
, &saRec
);
1278 ok(hres
== S_OK
,"GRI failed\n");
1279 ok(saRec
== (IRecordInfo
*)iRec
,"Different saRec\n");
1280 ok(iRec
->ref
== START_REF_COUNT
+ 2, "Didn't AddRef %ld\n", iRec
->ref
);
1281 if (iRec
->ref
== START_REF_COUNT
+ 2)
1282 IRecordInfo_Release(saRec
);
1284 ok(sa
->cbElements
== RECORD_SIZE
,"Elemsize is %ld\n", sa
->cbElements
);
1286 SafeArrayDestroy(sa
);
1287 ok(iRec
->sizeCalled
== 1, "Destroy->GetSize called %ld times\n", iRec
->sizeCalled
);
1288 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %ld times\n", iRec
->clearCalled
);
1289 ok(iRec
->ref
== START_REF_COUNT
, "Wrong iRec refcount %ld\n", iRec
->ref
);
1293 static void test_SafeArrayClear(void)
1302 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1303 ok(sa
!= NULL
, "Create() failed.\n");
1307 /* Test clearing non-NULL variants containing arrays */
1308 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1310 hres
= VariantClear(&v
);
1311 ok(hres
== S_OK
&& V_VT(&v
) == VT_EMPTY
, "VariantClear: hres 0x%lx, Type %d\n", hres
, V_VT(&v
));
1312 ok(V_ARRAY(&v
) == sa
, "VariantClear: Overwrote value\n");
1314 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1315 ok(sa
!= NULL
, "Create() failed.\n");
1319 V_VT(&v
) = VT_SAFEARRAY
;
1321 hres
= VariantClear(&v
);
1322 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%lx\n", hres
);
1324 V_VT(&v
) = VT_SAFEARRAY
|VT_BYREF
;
1325 V_ARRAYREF(&v
) = &sa
;
1326 hres
= VariantClear(&v
);
1327 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%lx\n", hres
);
1329 SafeArrayDestroy(sa
);
1332 static void test_SafeArrayCopy(void)
1336 VARIANTARG vSrc
, vDst
;
1341 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1342 ok(sa
!= NULL
, "Create() failed.\n");
1346 /* Test copying non-NULL variants containing arrays */
1347 V_VT(&vSrc
) = (VT_ARRAY
|VT_BYREF
|VT_UI1
);
1348 V_ARRAYREF(&vSrc
) = &sa
;
1349 V_VT(&vDst
) = VT_EMPTY
;
1351 hres
= VariantCopy(&vDst
, &vSrc
);
1352 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_BYREF
|VT_UI1
),
1353 "VariantCopy: hres 0x%lx, Type %d\n", hres
, V_VT(&vDst
));
1354 ok(V_ARRAYREF(&vDst
) == &sa
, "VariantClear: Performed deep copy\n");
1356 V_VT(&vSrc
) = (VT_ARRAY
|VT_UI1
);
1357 V_ARRAY(&vSrc
) = sa
;
1358 V_VT(&vDst
) = VT_EMPTY
;
1360 hres
= VariantCopy(&vDst
, &vSrc
);
1361 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_UI1
),
1362 "VariantCopy: hres 0x%lx, Type %d\n", hres
, V_VT(&vDst
));
1363 ok(V_ARRAY(&vDst
) != sa
, "VariantClear: Performed shallow copy\n");
1365 SafeArrayDestroy(V_ARRAY(&vSrc
));
1366 SafeArrayDestroy(V_ARRAY(&vDst
));
1369 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1370 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1372 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1374 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1375 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1376 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1378 static void test_SafeArrayChangeTypeEx(void)
1380 static const char *szHello
= "Hello World";
1387 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1388 MKARRAY(0,strlen(szHello
)+1,VT_UI1
);
1389 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1391 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1392 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres
);
1395 ok(V_VT(&v2
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2
));
1396 ok(strcmp((char*)V_BSTR(&v2
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1397 (char*)V_BSTR(&v2
));
1401 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1402 SafeArrayDestroy(sa
);
1403 if (pSafeArrayCreateVector
)
1405 sa
= pSafeArrayCreateVector(VT_UI1
, 0, strlen(szHello
)+1);
1406 ok(sa
!= NULL
, "CreateVector() failed.\n");
1410 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1411 V_VT(&v
) = VT_VECTOR
|VT_UI1
;
1415 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1416 ok(hres
== DISP_E_BADVARTYPE
, "CTE VT_VECTOR|VT_UI1 returned %lx\n", hres
);
1418 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1419 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1420 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
1421 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx\n", hres
);
1424 ok(V_VT(&v
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v
));
1425 ok(strcmp((char*)V_BSTR(&v
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1431 /* To/from BSTR only works with arrays of VT_UI1 */
1432 for (vt
= 0; vt
<= VT_CLSID
; vt
++)
1437 MKARRAYCONT(0,1,vt
);
1438 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1439 ok(hres
!= S_OK
, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt
);
1443 /* Can't change an array of one type into array of another type , even
1444 * if the other type is the same size
1446 if (pSafeArrayCreateVector
)
1448 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1449 ok(sa
!= NULL
, "CreateVector() failed.\n");
1453 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1455 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_I1
);
1456 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %lx\n", hres
);
1458 /* But can change to the same array type */
1459 SafeArrayDestroy(sa
);
1460 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1461 ok(sa
!= NULL
, "CreateVector() failed.\n");
1464 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1466 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_UI1
);
1467 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %lx\n", hres
);
1471 MKARRAY(0,1,VT_UI1
);
1472 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_NULL
);
1473 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres
);
1474 MKARRAY(0,1,VT_UI1
);
1475 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_EMPTY
);
1476 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %lx\n", hres
);
1480 START_TEST(safearray
)
1482 hOleaut32
= LoadLibraryA("oleaut32.dll");
1484 GETPTR(SafeArrayAllocDescriptorEx
);
1485 GETPTR(SafeArrayCopyData
);
1486 GETPTR(SafeArrayGetIID
);
1487 GETPTR(SafeArraySetIID
);
1488 GETPTR(SafeArrayGetVartype
);
1489 GETPTR(SafeArrayCreateEx
);
1490 GETPTR(SafeArrayCreateVector
);
1493 test_SafeArrayAllocDestroyDescriptor();
1494 test_SafeArrayCreateLockDestroy();
1495 test_VectorCreateLockDestroy();
1497 test_SafeArrayChangeTypeEx();
1498 test_SafeArrayCopy();
1499 test_SafeArrayClear();
1500 test_SafeArrayCreateEx();
1501 test_SafeArrayCopyData();
1502 test_SafeArrayGetPutElement();
1503 test_SafeArrayGetPutElement_BSTR();
1504 test_SafeArrayGetPutElement_IUnknown();