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 #ifndef FADF_CREATEVECTOR
43 const USHORT FADF_CREATEVECTOR
= 0x2000;
46 static HMODULE hOleaut32
;
48 static HRESULT (WINAPI
*pSafeArrayAllocDescriptorEx
)(VARTYPE
,UINT
,SAFEARRAY
**);
49 static HRESULT (WINAPI
*pSafeArrayCopyData
)(SAFEARRAY
*,SAFEARRAY
*);
50 static HRESULT (WINAPI
*pSafeArrayGetIID
)(SAFEARRAY
*,GUID
*);
51 static HRESULT (WINAPI
*pSafeArraySetIID
)(SAFEARRAY
*,REFGUID
);
52 static HRESULT (WINAPI
*pSafeArrayGetVartype
)(SAFEARRAY
*,VARTYPE
*);
53 static HRESULT (WINAPI
*pSafeArrayGetRecordInfo
)(SAFEARRAY
*,IRecordInfo
**);
54 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateEx
)(VARTYPE
,UINT
,SAFEARRAYBOUND
*,LPVOID
);
55 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateVector
)(VARTYPE
,LONG
,ULONG
);
57 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
59 /* Has I8/UI8 data type? */
61 /* Has INT_PTR/UINT_PTR type? */
62 static BOOL has_int_ptr
;
64 static const USHORT ignored_copy_features
[] =
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
;
82 unsigned int sizeCalled
;
83 unsigned int clearCalled
;
84 unsigned int recordcopy
;
87 static inline IRecordInfoImpl
*impl_from_IRecordInfo(IRecordInfo
*iface
)
89 return CONTAINING_RECORD(iface
, IRecordInfoImpl
, IRecordInfo_iface
);
92 static HRESULT WINAPI
RecordInfo_QueryInterface(IRecordInfo
*iface
, REFIID riid
, void **obj
)
96 if (IsEqualIID(riid
, &IID_IUnknown
) ||
97 IsEqualIID(riid
, &IID_IRecordInfo
))
100 IRecordInfo_AddRef(iface
);
104 return E_NOINTERFACE
;
107 static ULONG WINAPI
RecordInfo_AddRef(IRecordInfo
*iface
)
109 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
110 return InterlockedIncrement(&This
->ref
);
113 static ULONG WINAPI
RecordInfo_Release(IRecordInfo
*iface
)
115 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
116 ULONG ref
= InterlockedDecrement(&This
->ref
);
119 HeapFree(GetProcessHeap(), 0, This
);
124 static HRESULT WINAPI
RecordInfo_RecordInit(IRecordInfo
*iface
, PVOID pvNew
)
126 ok(0, "unexpected call\n");
130 static BOOL fail_GetSize
; /* Whether to fail the GetSize call */
132 static HRESULT WINAPI
RecordInfo_RecordClear(IRecordInfo
*iface
, PVOID pvExisting
)
134 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
139 static HRESULT WINAPI
RecordInfo_RecordCopy(IRecordInfo
*iface
, PVOID pvExisting
, PVOID pvNew
)
141 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
146 static HRESULT WINAPI
RecordInfo_GetGuid(IRecordInfo
*iface
, GUID
*pguid
)
148 ok(0, "unexpected call\n");
152 static HRESULT WINAPI
RecordInfo_GetName(IRecordInfo
*iface
, BSTR
*pbstrName
)
154 ok(0, "unexpected call\n");
158 static HRESULT WINAPI
RecordInfo_GetSize(IRecordInfo
*iface
, ULONG
* size
)
160 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
164 *size
= RECORD_SIZE_FAIL
;
171 static HRESULT WINAPI
RecordInfo_GetTypeInfo(IRecordInfo
*iface
, ITypeInfo
**ppTypeInfo
)
173 ok(0, "unexpected call\n");
177 static HRESULT WINAPI
RecordInfo_GetField(IRecordInfo
*iface
, PVOID pvData
,
178 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
180 ok(0, "unexpected call\n");
184 static HRESULT WINAPI
RecordInfo_GetFieldNoCopy(IRecordInfo
*iface
, PVOID pvData
,
185 LPCOLESTR szFieldName
, VARIANT
*pvarField
, PVOID
*ppvDataCArray
)
187 ok(0, "unexpected call\n");
191 static HRESULT WINAPI
RecordInfo_PutField(IRecordInfo
*iface
, ULONG wFlags
, PVOID pvData
,
192 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
194 ok(0, "unexpected call\n");
198 static HRESULT WINAPI
RecordInfo_PutFieldNoCopy(IRecordInfo
*iface
, ULONG wFlags
,
199 PVOID pvData
, LPCOLESTR szFieldName
, VARIANT
*pvarField
)
201 ok(0, "unexpected call\n");
205 static HRESULT WINAPI
RecordInfo_GetFieldNames(IRecordInfo
*iface
, ULONG
*pcNames
,
208 ok(0, "unexpected call\n");
212 static BOOL WINAPI
RecordInfo_IsMatchingType(IRecordInfo
*iface
, IRecordInfo
*info2
)
214 ok(0, "unexpected call\n");
218 static PVOID WINAPI
RecordInfo_RecordCreate(IRecordInfo
*iface
)
220 ok(0, "unexpected call\n");
224 static HRESULT WINAPI
RecordInfo_RecordCreateCopy(IRecordInfo
*iface
, PVOID pvSource
,
227 ok(0, "unexpected call\n");
231 static HRESULT WINAPI
RecordInfo_RecordDestroy(IRecordInfo
*iface
, PVOID pvRecord
)
233 ok(0, "unexpected call\n");
237 static const IRecordInfoVtbl RecordInfoVtbl
=
239 RecordInfo_QueryInterface
,
242 RecordInfo_RecordInit
,
243 RecordInfo_RecordClear
,
244 RecordInfo_RecordCopy
,
248 RecordInfo_GetTypeInfo
,
250 RecordInfo_GetFieldNoCopy
,
252 RecordInfo_PutFieldNoCopy
,
253 RecordInfo_GetFieldNames
,
254 RecordInfo_IsMatchingType
,
255 RecordInfo_RecordCreate
,
256 RecordInfo_RecordCreateCopy
,
257 RecordInfo_RecordDestroy
260 static IRecordInfoImpl
*IRecordInfoImpl_Construct(void)
262 IRecordInfoImpl
*rec
;
264 rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl
));
265 rec
->IRecordInfo_iface
.lpVtbl
= &RecordInfoVtbl
;
266 rec
->ref
= START_REF_COUNT
;
267 rec
->clearCalled
= 0;
272 static DWORD
SAFEARRAY_GetVTSize(VARTYPE vt
)
277 case VT_UI1
: return sizeof(BYTE
);
280 case VT_UI2
: return sizeof(SHORT
);
284 case VT_ERROR
: return sizeof(LONG
);
285 case VT_R8
: return sizeof(LONG64
);
289 return sizeof(LONG64
);
292 case VT_UINT
: return sizeof(INT
);
296 return sizeof(UINT_PTR
);
298 case VT_CY
: return sizeof(CY
);
299 case VT_DATE
: return sizeof(DATE
);
300 case VT_BSTR
: return sizeof(BSTR
);
301 case VT_DISPATCH
: return sizeof(LPDISPATCH
);
302 case VT_VARIANT
: return sizeof(VARIANT
);
303 case VT_UNKNOWN
: return sizeof(LPUNKNOWN
);
304 case VT_DECIMAL
: return sizeof(DECIMAL
);
309 static void check_for_VT_INT_PTR(void)
311 /* Set a global flag if VT_INT_PTR is supported */
314 SAFEARRAYBOUND bound
;
317 a
= SafeArrayCreate(VT_INT_PTR
, 1, &bound
);
320 trace("VT_INT_PTR is supported\n");
322 hres
= SafeArrayDestroy(a
);
323 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
326 trace("VT_INT_PTR is not supported\n");
331 #define VARTYPE_NOT_SUPPORTED 0
334 UINT elemsize
; /* elementsize by VT */
335 UINT expflags
; /* fFeatures from SafeArrayAllocDescriptorEx */
336 UINT addflags
; /* additional fFeatures from SafeArrayCreate */
338 {VT_EMPTY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
339 {VT_NULL
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
340 {VT_I2
, 2, FADF_HAVEVARTYPE
,0},
341 {VT_I4
, 4, FADF_HAVEVARTYPE
,0},
342 {VT_R4
, 4, FADF_HAVEVARTYPE
,0},
343 {VT_R8
, 8, FADF_HAVEVARTYPE
,0},
344 {VT_CY
, 8, FADF_HAVEVARTYPE
,0},
345 {VT_DATE
, 8, FADF_HAVEVARTYPE
,0},
346 {VT_BSTR
, sizeof(BSTR
), FADF_HAVEVARTYPE
,FADF_BSTR
},
347 {VT_DISPATCH
, sizeof(LPDISPATCH
), FADF_HAVEIID
, FADF_DISPATCH
},
348 {VT_ERROR
, 4, FADF_HAVEVARTYPE
,0},
349 {VT_BOOL
, 2, FADF_HAVEVARTYPE
,0},
350 {VT_VARIANT
, sizeof(VARIANT
), FADF_HAVEVARTYPE
,FADF_VARIANT
},
351 {VT_UNKNOWN
, sizeof(LPUNKNOWN
), FADF_HAVEIID
, FADF_UNKNOWN
},
352 {VT_DECIMAL
, sizeof(DECIMAL
), FADF_HAVEVARTYPE
,0},
353 {15, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0}, /* no VT_xxx */
354 {VT_I1
, 1, FADF_HAVEVARTYPE
,0},
355 {VT_UI1
, 1, FADF_HAVEVARTYPE
,0},
356 {VT_UI2
, 2, FADF_HAVEVARTYPE
,0},
357 {VT_UI4
, 4, FADF_HAVEVARTYPE
,0},
358 {VT_I8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
359 {VT_UI8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
360 {VT_INT
, sizeof(INT
), FADF_HAVEVARTYPE
,0},
361 {VT_UINT
, sizeof(UINT
), FADF_HAVEVARTYPE
,0},
362 {VT_VOID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
363 {VT_HRESULT
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
364 {VT_PTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
365 {VT_SAFEARRAY
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
366 {VT_CARRAY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
367 {VT_USERDEFINED
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
368 {VT_LPSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
369 {VT_LPWSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
370 {VT_FILETIME
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
371 {VT_RECORD
, VARTYPE_NOT_SUPPORTED
,FADF_RECORD
,0},
372 {VT_BLOB
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
373 {VT_STREAM
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
374 {VT_STORAGE
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
375 {VT_STREAMED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
376 {VT_STORED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
377 {VT_BLOB_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
378 {VT_CF
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
379 {VT_CLSID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
382 static void test_safearray(void)
385 unsigned int i
, diff
;
388 SAFEARRAYBOUND bound
, bounds
[2];
394 unsigned char *ptr1
, *ptr2
;
396 hres
= SafeArrayDestroy( NULL
);
397 ok( hres
== S_OK
, "SafeArrayDestroy( NULL) returned 0x%x\n", hres
);
401 a
= SafeArrayCreate(-1, 1, &bound
);
402 ok(NULL
== a
,"SAC(-1,1,[1,0]) not failed?\n");
406 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
407 ok(NULL
!= a
,"SAC(VT_I4,1,[0,0]) failed.\n");
409 hres
= SafeArrayGetLBound(a
, 1, &l
);
410 ok(hres
== S_OK
, "SAGLB of 0 size dimensioned array failed with %x\n",hres
);
411 ok(l
== 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l
);
412 hres
= SafeArrayGetUBound(a
, 1, &l
);
413 ok(hres
== S_OK
, "SAGUB of 0 size dimensioned array failed with %x\n",hres
);
414 ok(l
== 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l
);
416 hres
= SafeArrayAccessData(a
, &data
);
417 ok(hres
== S_OK
, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres
);
418 SafeArrayUnaccessData(a
);
421 hres
= SafeArrayRedim(a
, &bound
);
422 ok(hres
== S_OK
,"SAR of a 0 elements dimension failed with hres %x\n", hres
);
424 hres
= SafeArrayRedim(a
, &bound
);
425 ok(hres
== S_OK
|| hres
== E_OUTOFMEMORY
,
426 "SAR to a 0 elements dimension failed with hres %x\n", hres
);
427 hres
= SafeArrayDestroy(a
);
428 ok(hres
== S_OK
,"SAD of 0 dim array failed with hres %x\n", hres
);
430 SafeArrayAllocDescriptor(2, &a
);
431 a
->rgsabound
[0].cElements
= 2;
432 a
->rgsabound
[0].lLbound
= 1;
433 a
->rgsabound
[1].cElements
= 4;
434 a
->rgsabound
[1].lLbound
= 1;
436 hres
= SafeArrayAllocData(a
);
437 ok(hres
== S_OK
, "SafeArrayAllocData failed with hres %x\n", hres
);
441 hres
= SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
442 ok(hres
== S_OK
, "SAPOI failed with hres %x\n", hres
);
443 SafeArrayAccessData(a
, (void **)&ptr2
);
444 ok(ptr1
- ptr2
== 14, "SAPOI got wrong ptr\n");
445 *(WORD
*)ptr1
= 0x55aa;
446 SafeArrayUnaccessData(a
);
448 bound
.cElements
= 10;
450 SafeArrayRedim(a
, &bound
);
452 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
453 ok(*(WORD
*)ptr1
== 0x55aa, "Data not preserved when resizing array\n");
455 bound
.cElements
= 10;
457 SafeArrayRedim(a
, &bound
);
458 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
459 ok(*(WORD
*)ptr1
== 0 ||
460 broken(*(WORD
*)ptr1
!= 0), /* Win 2003 */
461 "Expanded area not zero-initialized\n");
464 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
465 ok(*(WORD
*)ptr1
== 0x55aa ||
466 broken(*(WORD
*)ptr1
!= 0x55aa), /* Win 2003 */
467 "Data not preserved when resizing array\n");
469 hres
= SafeArrayDestroy(a
);
470 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
472 bounds
[0].cElements
= 0; bounds
[0].lLbound
= 1;
473 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
474 a
= SafeArrayCreate(VT_I4
,2,bounds
);
475 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
477 hres
= SafeArrayDestroy(a
);
478 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
479 bounds
[0].cElements
= 1; bounds
[0].lLbound
= 1;
480 bounds
[1].cElements
= 0; bounds
[1].lLbound
= 23;
481 a
= SafeArrayCreate(VT_I4
,2,bounds
);
482 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
484 hres
= SafeArrayDestroy(a
);
485 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
487 bounds
[0].cElements
= 42; bounds
[0].lLbound
= 1;
488 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
489 a
= SafeArrayCreate(VT_I4
,2,bounds
);
490 ok(a
!= NULL
,"SAC(VT_INT32,2,...) failed.\n");
492 hres
= SafeArrayGetLBound (a
, 0, &l
);
493 ok (hres
== DISP_E_BADINDEX
, "SAGLB 0 failed with %x\n", hres
);
494 hres
= SafeArrayGetLBound (a
, 1, &l
);
495 ok (hres
== S_OK
, "SAGLB 1 failed with %x\n", hres
);
496 ok (l
== 1, "SAGLB 1 returned %d instead of 1\n", l
);
497 hres
= SafeArrayGetLBound (a
, 2, &l
);
498 ok (hres
== S_OK
, "SAGLB 2 failed with %x\n", hres
);
499 ok (l
== 23, "SAGLB 2 returned %d instead of 23\n", l
);
500 hres
= SafeArrayGetLBound (a
, 3, &l
);
501 ok (hres
== DISP_E_BADINDEX
, "SAGLB 3 failed with %x\n", hres
);
503 hres
= SafeArrayGetUBound (a
, 0, &l
);
504 ok (hres
== DISP_E_BADINDEX
, "SAGUB 0 failed with %x\n", hres
);
505 hres
= SafeArrayGetUBound (a
, 1, &l
);
506 ok (hres
== S_OK
, "SAGUB 1 failed with %x\n", hres
);
507 ok (l
== 42, "SAGUB 1 returned %d instead of 42\n", l
);
508 hres
= SafeArrayGetUBound (a
, 2, &l
);
509 ok (hres
== S_OK
, "SAGUB 2 failed with %x\n", hres
);
510 ok (l
== 24, "SAGUB 2 returned %d instead of 24\n", l
);
511 hres
= SafeArrayGetUBound (a
, 3, &l
);
512 ok (hres
== DISP_E_BADINDEX
, "SAGUB 3 failed with %x\n", hres
);
514 i
= SafeArrayGetDim(a
);
515 ok(i
== 2, "getdims of 2 din array returned %d\n",i
);
519 hres
= SafeArrayGetElement(a
, indices
, &i
);
520 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [0,23], hres 0x%x\n",hres
);
524 hres
= SafeArrayGetElement(a
, indices
, &i
);
525 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,22], hres 0x%x\n",hres
);
529 hres
= SafeArrayGetElement(a
, indices
, &i
);
530 ok(S_OK
== hres
,"SAGE failed [1,23], hres 0x%x\n",hres
);
534 hres
= SafeArrayGetElement(a
, indices
, &i
);
535 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,24], hres 0x%x\n",hres
);
539 hres
= SafeArrayGetElement(a
, indices
, &i
);
540 ok(S_OK
== hres
,"SAGE failed [42,23], hres 0x%x\n",hres
);
542 hres
= SafeArrayAccessData(a
, (void**)&ptr1
);
543 ok(S_OK
== hres
, "SAAD failed with 0x%x\n", hres
);
547 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
548 ok(S_OK
== hres
,"SAPOI failed [1,23], hres 0x%x\n",hres
);
550 ok(diff
== 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
554 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
555 ok(S_OK
== hres
,"SAPOI failed [5,24], hres 0x%x\n",hres
);
557 ok(diff
== 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
561 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
562 ok(S_OK
== hres
,"SAPOI failed [20,23], hres 0x%x\n",hres
);
564 ok(diff
== 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
566 hres
= SafeArrayUnaccessData(a
);
567 ok(S_OK
== hres
, "SAUAD failed with 0x%x\n", hres
);
569 hres
= SafeArrayDestroy(a
);
570 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
572 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
573 if ((i
== VT_I8
|| i
== VT_UI8
) && has_i8
)
575 vttypes
[i
].elemsize
= sizeof(LONG64
);
578 a
= SafeArrayCreate(vttypes
[i
].vt
, 1, &bound
);
580 ok((!a
&& !vttypes
[i
].elemsize
) ||
581 (a
&& vttypes
[i
].elemsize
== a
->cbElements
),
582 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
583 vttypes
[i
].vt
,a
,(a
?a
->cbElements
:0),vttypes
[i
].elemsize
);
587 ok(a
->fFeatures
== (vttypes
[i
].expflags
| vttypes
[i
].addflags
),
588 "SAC of %d returned feature flags %x, expected %x\n",
589 vttypes
[i
].vt
, a
->fFeatures
,
590 vttypes
[i
].expflags
|vttypes
[i
].addflags
);
591 ok(SafeArrayGetElemsize(a
) == vttypes
[i
].elemsize
,
592 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
593 vttypes
[i
].vt
, SafeArrayGetElemsize(a
),vttypes
[i
].elemsize
);
598 if (pSafeArrayGetVartype
)
600 hres
= pSafeArrayGetVartype(a
, &vt
);
601 ok(hres
== S_OK
, "SAGVT of arra y with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
602 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
603 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
606 hres
= SafeArrayCopy(a
, &c
);
607 ok(hres
== S_OK
, "failed to copy safearray of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
609 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
611 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
);
612 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
);
614 if (pSafeArrayGetVartype
) {
615 hres
= pSafeArrayGetVartype(c
, &vt
);
616 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
617 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
618 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
621 if (pSafeArrayCopyData
) {
622 hres
= pSafeArrayCopyData(a
, c
);
623 ok(hres
== S_OK
, "failed to copy safearray data of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
625 hres
= SafeArrayDestroyData(c
);
626 ok(hres
== S_OK
,"SADD of copy of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
629 hres
= SafeArrayDestroy(c
);
630 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
632 hres
= SafeArrayDestroy(a
);
633 ok(hres
== S_OK
,"SAD of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
636 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
638 bound
.cElements
= 10;
639 a
= SafeArrayCreate(VT_UI1
, 1, &bound
);
640 ok(a
!= NULL
, "SAC failed.\n");
641 ok(S_OK
== SafeArrayAccessData(a
, &data
),"SACD failed\n");
642 memcpy(data
,"Hello World\n",10);
643 ok(S_OK
== SafeArrayUnaccessData(a
),"SAUD failed\n");
644 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
646 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
647 ok(hres
==S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres
);
648 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
));
649 ok(V_BSTR(&v
)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v
)[0]);
654 V_BSTR(&v
) = SysAllocStringLen(NULL
, 0);
655 hres
= VariantChangeTypeEx(&d
, &v
, 0, 0, VT_UI1
|VT_ARRAY
);
656 ok(hres
==S_OK
, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres
);
657 ok(V_VT(&d
) == (VT_UI1
|VT_ARRAY
),"CTE BSTR -> VT_UI1|VT_ARRAY did not return VT_UI1|VT_ARRAY, but %d.v\n",V_VT(&v
));
661 /* check locking functions */
662 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
663 ok(a
!=NULL
,"SAC should not fail\n");
665 hres
= SafeArrayAccessData(a
, &data
);
666 ok(hres
== S_OK
,"SAAD failed with hres %x\n",hres
);
668 hres
= SafeArrayDestroy(a
);
669 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
671 hres
= SafeArrayDestroyData(a
);
672 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
674 hres
= SafeArrayDestroyDescriptor(a
);
675 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
677 hres
= SafeArrayUnaccessData(a
);
678 ok(hres
== S_OK
,"SAUD failed after lock/destroy test\n");
680 hres
= SafeArrayDestroy(a
);
681 ok(hres
== S_OK
,"SAD failed after lock/destroy test\n");
683 /* Test if we need to destroy data before descriptor */
684 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
685 ok(a
!=NULL
,"SAC should not fail\n");
686 hres
= SafeArrayDestroyDescriptor(a
);
687 ok(hres
== S_OK
,"SADD with data in array failed with hres %x\n",hres
);
690 /* init a small stack safearray */
691 if (pSafeArraySetIID
) {
692 memset(&b
, 0, sizeof(b
));
694 memset(&iid
, 0x42, sizeof(IID
));
695 hres
= pSafeArraySetIID(&b
,&iid
);
696 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %x\n",hres
);
698 hres
= SafeArrayAllocDescriptor(1,&a
);
699 ok(hres
== S_OK
,"SafeArrayAllocDescriptor should return S_OK, but got %x\n",hres
);
700 ok((a
->fFeatures
& FADF_HAVEIID
) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
701 hres
= pSafeArraySetIID(a
,&iid
);
702 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but got %x\n",hres
);
704 hres
= SafeArrayDestroyDescriptor(a
);
705 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
708 if (!pSafeArrayAllocDescriptorEx
)
711 for (i
= 0; i
< sizeof(vttypes
)/sizeof(vttypes
[0]); i
++) {
713 hres
= pSafeArrayAllocDescriptorEx(vttypes
[i
].vt
,1,&a
);
714 ok(hres
== S_OK
, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres
);
715 ok(a
->fFeatures
== vttypes
[i
].expflags
,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes
[i
].vt
, a
->fFeatures
, vttypes
[i
].expflags
);
716 if (a
->fFeatures
& FADF_HAVEIID
) {
717 hres
= pSafeArrayGetIID(a
, &iid
);
718 ok(hres
== S_OK
,"SAGIID failed for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
719 switch (vttypes
[i
].vt
) {
721 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IUnknown
),"guid for VT_UNKNOWN is not IID_IUnknown\n");
722 ok(IsEqualGUID(&iid
, &IID_IUnknown
),"SAGIID returned wrong GUID for IUnknown\n");
725 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IDispatch
),"guid for VT_UNKNOWN is not IID_IDispatch\n");
726 ok(IsEqualGUID(&iid
, &IID_IDispatch
),"SAGIID returned wrong GUID for IDispatch\n");
729 ok(FALSE
,"unknown vt %d with FADF_HAVEIID\n",vttypes
[i
].vt
);
733 hres
= pSafeArrayGetIID(a
, &iid
);
734 ok(hres
== E_INVALIDARG
,"SAGIID did not fail for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
736 if (a
->fFeatures
& FADF_RECORD
) {
737 ok(vttypes
[i
].vt
== VT_RECORD
,"FADF_RECORD for non record %d\n",vttypes
[i
].vt
);
739 if (a
->fFeatures
& FADF_HAVEVARTYPE
) {
740 ok(vttypes
[i
].vt
== ((DWORD
*)a
)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes
[i
].vt
,((DWORD
*)a
)[-1]);
743 hres
= pSafeArrayGetVartype(a
, &vt
);
744 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
746 if (vttypes
[i
].vt
== VT_DISPATCH
) {
747 /* Special case. Checked against Windows. */
748 ok(vt
== VT_UNKNOWN
, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
750 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
753 if (a
->fFeatures
& FADF_HAVEIID
) {
754 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
755 ok(hres
== S_OK
,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
756 hres
= pSafeArrayGetIID(a
, &iid
);
757 ok(hres
== S_OK
,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
758 ok(IsEqualGUID(&iid
, &IID_IStorage
),"returned iid is not IID_IStorage\n");
760 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
761 ok(hres
== E_INVALIDARG
,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
763 hres
= SafeArrayDestroyDescriptor(a
);
764 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
768 static void test_SafeArrayAllocDestroyDescriptor(void)
775 hres
= SafeArrayAllocDescriptor(0, &sa
);
776 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
778 hres
= SafeArrayAllocDescriptor(65536, &sa
);
779 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%x\n", hres
);
783 /* Crashes on 95: XP & Wine return E_POINTER */
784 hres
=SafeArrayAllocDescriptor(1, NULL
);
785 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
788 /* Test up to the dimension boundary case */
789 for (i
= 5; i
<= 65535; i
+= 30)
791 hres
= SafeArrayAllocDescriptor(i
, &sa
);
792 ok(hres
== S_OK
, "%d dimensions failed; hres 0x%x\n", i
, hres
);
796 ok(SafeArrayGetDim(sa
) == (UINT
)i
, "Dimension is %d; should be %d\n",
797 SafeArrayGetDim(sa
), i
);
799 hres
= SafeArrayDestroyDescriptor(sa
);
800 ok(hres
== S_OK
, "destroy failed; hres 0x%x\n", hres
);
804 if (!pSafeArrayAllocDescriptorEx
)
807 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 0, &sa
);
808 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
810 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 65536, &sa
);
811 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%x\n", hres
);
813 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 1, NULL
);
814 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
816 hres
= pSafeArrayAllocDescriptorEx(-1, 1, &sa
);
817 ok(hres
== S_OK
, "VT = -1 gave hres 0x%x\n", hres
);
819 sa
->rgsabound
[0].cElements
= 0;
820 sa
->rgsabound
[0].lLbound
= 1;
822 hres
= SafeArrayAllocData(sa
);
823 ok(hres
== S_OK
, "SafeArrayAllocData gave hres 0x%x\n", hres
);
825 hres
= SafeArrayDestroy(sa
);
826 ok(hres
== S_OK
,"SafeArrayDestroy failed with hres %x\n",hres
);
829 static void test_SafeArrayCreateLockDestroy(void)
831 SAFEARRAYBOUND sab
[4];
837 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
839 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
841 sab
[dimension
].lLbound
= 0;
842 sab
[dimension
].cElements
= 8;
846 /* This test crashes very early versions with no error checking...
847 sa = SafeArrayCreate(VT_UI1, 1, NULL);
848 ok(sa == NULL, "NULL bounds didn't fail\n");
850 sa
= SafeArrayCreate(VT_UI1
, 65536, sab
);
851 ok(!sa
, "Max bounds didn't fail\n");
853 memset(sab
, 0, sizeof(sab
));
855 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
857 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
858 sab
[dimension
].cElements
= 8;
860 /* Test all VARTYPES in 1-4 dimensions */
861 for (dimension
= 1; dimension
< 4; dimension
++)
863 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
865 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
867 sa
= SafeArrayCreate(vt
, dimension
, sab
);
870 ok(sa
!= NULL
, "VARTYPE %d (@%d dimensions) failed\n", vt
, dimension
);
872 ok(sa
== NULL
|| vt
== VT_R8
,
873 "VARTYPE %d (@%d dimensions) succeeded!\n", vt
, dimension
);
877 ok(SafeArrayGetDim(sa
) == (UINT
)dimension
,
878 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
879 vt
, dimension
, SafeArrayGetDim(sa
), dimension
);
880 ok(SafeArrayGetElemsize(sa
) == dwLen
|| vt
== VT_R8
,
881 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
882 vt
, dimension
, SafeArrayGetElemsize(sa
), dwLen
);
884 if (vt
!= VT_UNKNOWN
&& vt
!= VT_DISPATCH
)
886 ok((sa
->fFeatures
& FADF_HAVEIID
) == 0,
887 "Non interface type should not have FADF_HAVEIID\n");
888 if (pSafeArraySetIID
)
890 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
891 ok(hres
== E_INVALIDARG
,
892 "Non interface type allowed SetIID(), hres %x\n", hres
);
898 ok(sa
->fFeatures
& FADF_HAVEVARTYPE
,
899 "Non interface type should have FADF_HAVEVARTYPE\n");
900 if (pSafeArrayGetVartype
)
902 hres
= pSafeArrayGetVartype(sa
, &aVt
);
903 ok(hres
== S_OK
&& aVt
== vt
,
904 "Non interface type %d: bad type %d, hres %x\n", vt
, aVt
, hres
);
910 ok(sa
->fFeatures
& FADF_HAVEIID
, "Interface type should have FADF_HAVEIID\n");
911 if (pSafeArraySetIID
)
913 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
915 "Non interface type disallowed SetIID(), hres %x\n", hres
);
917 ok((sa
->fFeatures
& FADF_HAVEVARTYPE
) == 0,
918 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt
);
921 hres
= SafeArrayLock(sa
);
922 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
923 vt
, dimension
, hres
);
927 hres
= SafeArrayDestroy(sa
);
928 ok(hres
== DISP_E_ARRAYISLOCKED
,"Destroy() got hres %x\n", hres
);
930 hres
= SafeArrayDestroyData(sa
);
931 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyData() got hres %x\n", hres
);
933 hres
= SafeArrayDestroyDescriptor(sa
);
934 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyDescriptor() got hres %x\n", hres
);
936 hres
= SafeArrayUnlock(sa
);
937 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
938 vt
, dimension
, hres
);
940 hres
= SafeArrayDestroy(sa
);
941 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
942 vt
, dimension
, hres
);
949 static void test_VectorCreateLockDestroy(void)
956 if (!pSafeArrayCreateVector
)
958 win_skip("SafeArrayCreateVector not supported\n");
961 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 0);
962 ok(sa
!= NULL
, "SACV with 0 elements failed.\n");
964 hres
= SafeArrayDestroy(sa
);
965 ok(hres
== S_OK
, "SafeArrayDestroy failed with hres %x\n",hres
);
967 /* Test all VARTYPES in different lengths */
968 for (element
= 1; element
<= 101; element
+= 10)
970 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
972 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
974 sa
= pSafeArrayCreateVector(vt
, 0, element
);
977 ok(sa
!= NULL
, "VARTYPE %d (@%d elements) failed\n", vt
, element
);
979 ok(sa
== NULL
, "VARTYPE %d (@%d elements) succeeded!\n", vt
, element
);
983 ok(SafeArrayGetDim(sa
) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
984 vt
, element
, SafeArrayGetDim(sa
));
985 ok(SafeArrayGetElemsize(sa
) == dwLen
,
986 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
987 vt
, element
, SafeArrayGetElemsize(sa
), dwLen
);
989 hres
= SafeArrayLock(sa
);
990 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
995 hres
= SafeArrayUnlock(sa
);
996 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
999 hres
= SafeArrayDestroy(sa
);
1000 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
1008 static void test_LockUnlock(void)
1010 SAFEARRAYBOUND sab
[4];
1013 BOOL bVector
= FALSE
;
1017 hres
= SafeArrayLock(NULL
);
1018 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
1019 hres
= SafeArrayUnlock(NULL
);
1020 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
1022 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1024 sab
[dimension
].lLbound
= 0;
1025 sab
[dimension
].cElements
= 8;
1028 sa
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
1030 /* Test maximum locks */
1031 test_LockUnlock_Vector
:
1036 hres
= SafeArrayUnlock(sa
);
1037 ok (hres
== E_UNEXPECTED
, "Bad %sUnlock gave hres 0x%x\n",
1038 bVector
? "vector " : "\n", hres
);
1040 while ((hres
= SafeArrayLock(sa
)) == S_OK
)
1042 ok (count
== 65535 && hres
== E_UNEXPECTED
, "Lock %sfailed at %d; hres 0x%x\n",
1043 bVector
? "vector " : "\n", count
, hres
);
1045 if (count
== 65535 && hres
== E_UNEXPECTED
)
1047 while ((hres
= SafeArrayUnlock(sa
)) == S_OK
)
1049 ok (count
== 0 && hres
== E_UNEXPECTED
, "Unlock %sfailed at %d; hres 0x%x\n",
1050 bVector
? "vector " : "\n", count
, hres
);
1053 hres
= SafeArrayDestroy(sa
);
1054 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1057 if (bVector
== FALSE
&& pSafeArrayCreateVector
)
1059 /* Test again with a vector */
1060 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 100);
1062 goto test_LockUnlock_Vector
;
1066 static void test_SafeArrayGetPutElement(void)
1068 SAFEARRAYBOUND sab
[4];
1069 LONG indices
[NUM_DIMENSIONS
], index
;
1072 int value
= 0, gotvalue
, dimension
;
1073 IRecordInfoImpl
*irec
;
1074 unsigned int x
,y
,z
,a
;
1076 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1078 sab
[dimension
].lLbound
= dimension
* 2 + 1;
1079 sab
[dimension
].cElements
= dimension
* 3 + 1;
1082 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1084 return; /* Some early versions can't handle > 3 dims */
1086 ok(sa
->cbElements
== sizeof(value
), "int size mismatch\n");
1089 for (x
= 0; x
< NUM_DIMENSIONS
; x
++)
1091 indices
[0] = sab
[0].lLbound
;
1092 indices
[1] = sab
[1].lLbound
;
1093 indices
[2] = sab
[2].lLbound
;
1094 indices
[3] = sab
[3].lLbound
;
1096 indices
[x
] = indices
[x
] - 1;
1097 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1098 ok(hres
== DISP_E_BADINDEX
, "Put allowed too small index in dimension %d\n", x
);
1099 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1100 ok(hres
== DISP_E_BADINDEX
, "Get allowed too small index in dimension %d\n", x
);
1102 indices
[x
] = sab
[x
].lLbound
+ sab
[x
].cElements
;
1103 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1104 ok(hres
== DISP_E_BADINDEX
, "Put allowed too big index in dimension %d\n", x
);
1105 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1106 ok(hres
== DISP_E_BADINDEX
, "Get allowed too big index in dimension %d\n", x
);
1109 indices
[0] = sab
[0].lLbound
;
1110 indices
[1] = sab
[1].lLbound
;
1111 indices
[2] = sab
[2].lLbound
;
1112 indices
[3] = sab
[3].lLbound
;
1114 hres
= SafeArrayPutElement(NULL
, indices
, &value
);
1115 ok(hres
== E_INVALIDARG
, "Put NULL array hres 0x%x\n", hres
);
1116 hres
= SafeArrayGetElement(NULL
, indices
, &value
);
1117 ok(hres
== E_INVALIDARG
, "Get NULL array hres 0x%x\n", hres
);
1119 hres
= SafeArrayPutElement(sa
, NULL
, &value
);
1120 ok(hres
== E_INVALIDARG
, "Put NULL indices hres 0x%x\n", hres
);
1121 hres
= SafeArrayGetElement(sa
, NULL
, &value
);
1122 ok(hres
== E_INVALIDARG
, "Get NULL indices hres 0x%x\n", hres
);
1126 /* This is retarded. Windows checks every case of invalid parameters
1127 * except the following, which crashes. We ERR this in Wine.
1129 hres
= SafeArrayPutElement(sa
, indices
, NULL
);
1130 ok(hres
== E_INVALIDARG
, "Put NULL value hres 0x%x\n", hres
);
1133 hres
= SafeArrayGetElement(sa
, indices
, NULL
);
1134 ok(hres
== E_INVALIDARG
, "Get NULL value hres 0x%x\n", hres
);
1138 /* Make sure we can read and get back the correct values in 4 dimensions,
1139 * Each with a different size and lower bound.
1141 for (x
= 0; x
< sab
[0].cElements
; x
++)
1143 indices
[0] = sab
[0].lLbound
+ x
;
1144 for (y
= 0; y
< sab
[1].cElements
; y
++)
1146 indices
[1] = sab
[1].lLbound
+ y
;
1147 for (z
= 0; z
< sab
[2].cElements
; z
++)
1149 indices
[2] = sab
[2].lLbound
+ z
;
1150 for (a
= 0; a
< sab
[3].cElements
; a
++)
1152 indices
[3] = sab
[3].lLbound
+ a
;
1153 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1154 ok(hres
== S_OK
, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1164 for (x
= 0; x
< sab
[0].cElements
; x
++)
1166 indices
[0] = sab
[0].lLbound
+ x
;
1167 for (y
= 0; y
< sab
[1].cElements
; y
++)
1169 indices
[1] = sab
[1].lLbound
+ y
;
1170 for (z
= 0; z
< sab
[2].cElements
; z
++)
1172 indices
[2] = sab
[2].lLbound
+ z
;
1173 for (a
= 0; a
< sab
[3].cElements
; a
++)
1175 indices
[3] = sab
[3].lLbound
+ a
;
1176 gotvalue
= value
/ 3;
1177 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1178 ok(hres
== S_OK
, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1181 ok(value
== gotvalue
, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1182 gotvalue
, value
, x
, y
, z
, a
);
1188 hres
= SafeArrayDestroy(sa
);
1189 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1191 /* VT_RECORD array */
1192 irec
= IRecordInfoImpl_Construct();
1196 sab
[0].cElements
= 8;
1198 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &irec
->IRecordInfo_iface
);
1199 ok(sa
!= NULL
, "failed to create array\n");
1200 ok(irec
->ref
== 2, "got %d\n", irec
->ref
);
1203 irec
->recordcopy
= 0;
1204 hres
= SafeArrayPutElement(sa
, &index
, (void*)0xdeadbeef);
1205 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1206 ok(irec
->recordcopy
== 1, "got %d\n", irec
->recordcopy
);
1209 irec
->recordcopy
= 0;
1210 hres
= SafeArrayGetElement(sa
, &index
, (void*)0xdeadbeef);
1211 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1212 ok(irec
->recordcopy
== 1, "got %d\n", irec
->recordcopy
);
1214 hres
= SafeArrayDestroy(sa
);
1215 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1216 ok(irec
->ref
== 1, "got %d\n", irec
->ref
);
1217 IRecordInfo_Release(&irec
->IRecordInfo_iface
);
1220 static void test_SafeArrayGetPutElement_BSTR(void)
1226 BSTR value
= 0, gotvalue
;
1227 const OLECHAR szTest
[5] = { 'T','e','s','t','\0' };
1232 sa
= SafeArrayCreate(VT_BSTR
, 1, &sab
);
1233 ok(sa
!= NULL
, "BSTR test couldn't create array\n");
1237 ok(sa
->cbElements
== sizeof(BSTR
), "BSTR size mismatch\n");
1239 indices
[0] = sab
.lLbound
;
1240 value
= SysAllocString(szTest
);
1241 ok (value
!= NULL
, "Expected non-NULL\n");
1242 hres
= SafeArrayPutElement(sa
, indices
, value
);
1243 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1245 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1246 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1248 ok(SysStringLen(value
) == SysStringLen(gotvalue
), "Got len %d instead of %d\n", SysStringLen(gotvalue
), SysStringLen(value
));
1249 hres
= SafeArrayDestroy(sa
);
1250 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1251 SysFreeString(value
);
1252 SysFreeString(gotvalue
);
1256 IUnknown IUnknown_iface
;
1259 static const IUnknownVtbl xtunk_vtbl
;
1261 static struct xtunk_impl xtunk
= {{&xtunk_vtbl
}, 0};
1263 static HRESULT WINAPI
tunk_QueryInterface(IUnknown
*punk
, REFIID riid
, void **x
)
1268 static ULONG WINAPI
tunk_AddRef(IUnknown
*punk
)
1273 static ULONG WINAPI
tunk_Release(IUnknown
*punk
)
1278 static const IUnknownVtbl xtunk_vtbl
= {
1279 tunk_QueryInterface
,
1284 static void test_SafeArrayGetPutElement_IUnknown(void)
1294 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1295 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1299 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1301 indices
[0] = sab
.lLbound
;
1303 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1304 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1305 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1307 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1308 ok(xtunk
.ref
== 3,"Failed to increment refcount of iface.\n");
1309 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1311 ok(gotvalue
== &xtunk
.IUnknown_iface
, "Got %p instead of %p\n", gotvalue
, &xtunk
.IUnknown_iface
);
1312 hres
= SafeArrayDestroy(sa
);
1313 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1314 ok(xtunk
.ref
== 2,"Failed to decrement refcount of iface.\n");
1317 static void test_SafeArrayRedim_IUnknown(void)
1326 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1327 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1331 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1335 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1336 ok(hres
== S_OK
, "Failed to put IUnknown element hres 0x%x\n", hres
);
1337 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1339 hres
= SafeArrayRedim(sa
, &sab
);
1340 ok(hres
== S_OK
, "Failed to shrink array hres 0x%x\n", hres
);
1341 ok(xtunk
.ref
== 1, "Failed to decrement refcount\n");
1342 hres
= SafeArrayDestroy(sa
);
1343 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1346 static void test_SafeArrayGetPutElement_VARIANT(void)
1352 VARIANT value
, gotvalue
;
1356 sa
= SafeArrayCreate(VT_VARIANT
, 1, &sab
);
1357 ok(sa
!= NULL
, "VARIANT test couldn't create array\n");
1361 ok(sa
->cbElements
== sizeof(VARIANT
), "VARIANT size mismatch\n");
1363 indices
[0] = sab
.lLbound
;
1364 V_VT(&value
) = VT_I4
;
1365 V_I4(&value
) = 0x42424242;
1366 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1367 ok(hres
== S_OK
, "Failed to put Variant I4 element hres 0x%x\n", hres
);
1369 V_VT(&gotvalue
) = 0xdead;
1370 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1371 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1373 V_VT(&gotvalue
) = VT_EMPTY
;
1374 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1375 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1377 ok(V_VT(&value
) == V_VT(&gotvalue
), "Got type 0x%x instead of 0x%x\n", V_VT(&value
), V_VT(&gotvalue
));
1378 if (V_VT(&value
) == V_VT(&gotvalue
))
1379 ok(V_I4(&value
) == V_I4(&gotvalue
), "Got %d instead of %d\n", V_I4(&value
), V_VT(&gotvalue
));
1381 hres
= SafeArrayDestroy(sa
);
1382 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1385 static void test_SafeArrayCopyData(void)
1387 SAFEARRAYBOUND sab
[4];
1391 int dimension
, size
= 1, i
;
1393 if (!pSafeArrayCopyData
)
1395 win_skip("SafeArrayCopyData not supported\n");
1399 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1401 sab
[dimension
].lLbound
= dimension
* 2 + 2;
1402 sab
[dimension
].cElements
= dimension
* 3 + 1;
1403 size
*= sab
[dimension
].cElements
;
1406 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1407 ok(sa
!= NULL
, "Copy test couldn't create array\n");
1408 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1409 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1414 ok(sa
->cbElements
== sizeof(int), "int size mismatch\n");
1416 /* Fill the source array with some data; it doesn't matter what */
1417 for (dimension
= 0; dimension
< size
; dimension
++)
1419 int* data
= sa
->pvData
;
1420 data
[dimension
] = dimension
;
1423 hres
= pSafeArrayCopyData(sa
, sacopy
);
1424 ok(hres
== S_OK
, "copy data failed hres 0x%x\n", hres
);
1427 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1431 hres
= pSafeArrayCopyData(NULL
, sacopy
);
1432 ok(hres
== E_INVALIDARG
, "Null copy source hres 0x%x\n", hres
);
1433 hres
= pSafeArrayCopyData(sa
, NULL
);
1434 ok(hres
== E_INVALIDARG
, "Null copy hres 0x%x\n", hres
);
1436 sacopy
->rgsabound
[0].cElements
+= 1;
1437 hres
= pSafeArrayCopyData(sa
, sacopy
);
1438 ok(hres
== E_INVALIDARG
, "Bigger copy first dimension hres 0x%x\n", hres
);
1440 sacopy
->rgsabound
[0].cElements
-= 2;
1441 hres
= pSafeArrayCopyData(sa
, sacopy
);
1442 ok(hres
== E_INVALIDARG
, "Smaller copy first dimension hres 0x%x\n", hres
);
1443 sacopy
->rgsabound
[0].cElements
+= 1;
1445 sacopy
->rgsabound
[3].cElements
+= 1;
1446 hres
= pSafeArrayCopyData(sa
, sacopy
);
1447 ok(hres
== E_INVALIDARG
, "Bigger copy last dimension hres 0x%x\n", hres
);
1449 sacopy
->rgsabound
[3].cElements
-= 2;
1450 hres
= pSafeArrayCopyData(sa
, sacopy
);
1451 ok(hres
== E_INVALIDARG
, "Smaller copy last dimension hres 0x%x\n", hres
);
1452 sacopy
->rgsabound
[3].cElements
+= 1;
1454 hres
= SafeArrayDestroy(sacopy
);
1455 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1457 hres
= pSafeArrayCopyData(sa
, sacopy
);
1458 ok(hres
== E_INVALIDARG
, "->Null copy hres 0x%x\n", hres
);
1460 hres
= SafeArrayCopy(sa
, &sacopy
);
1461 ok(hres
== S_OK
, "copy failed hres 0x%x\n", hres
);
1462 ok(SafeArrayGetElemsize(sa
) == SafeArrayGetElemsize(sacopy
),"elemsize wrong\n");
1463 ok(SafeArrayGetDim(sa
) == SafeArrayGetDim(sacopy
),"dimensions wrong\n");
1464 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1465 hres
= SafeArrayDestroy(sacopy
);
1466 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1468 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1469 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1470 ok(sacopy
->fFeatures
== FADF_HAVEVARTYPE
, "0x%04x\n", sacopy
->fFeatures
);
1472 for (i
= 0; i
< sizeof(ignored_copy_features
)/sizeof(USHORT
); i
++)
1474 USHORT feature
= ignored_copy_features
[i
];
1475 USHORT orig
= sacopy
->fFeatures
;
1477 sa
->fFeatures
|= feature
;
1478 hres
= SafeArrayCopyData(sa
, sacopy
);
1479 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1480 ok(sacopy
->fFeatures
== orig
&& orig
== FADF_HAVEVARTYPE
, "got features 0x%04x\n", sacopy
->fFeatures
);
1481 sa
->fFeatures
&= ~feature
;
1484 hres
= SafeArrayDestroy(sacopy
);
1485 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1486 hres
= SafeArrayDestroy(sa
);
1487 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1489 /* copy data from a vector */
1490 sa
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1492 sacopy
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1493 ok(sa
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1494 broken(sa
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1495 "got 0x%08x\n", sa
->fFeatures
);
1496 ok(sacopy
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1497 broken(sacopy
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1498 "got 0x%08x\n", sacopy
->fFeatures
);
1499 hres
= SafeArrayCopyData(sa
, sacopy
);
1500 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1501 ok(sacopy
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1502 broken(sacopy
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1503 "got 0x%04x\n", sacopy
->fFeatures
);
1504 SafeArrayDestroy(sacopy
);
1506 sacopy
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
1507 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1508 ok(sacopy
->fFeatures
== FADF_HAVEVARTYPE
, "0x%04x\n", sacopy
->fFeatures
);
1509 hres
= SafeArrayCopyData(sa
, sacopy
);
1510 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
1511 SafeArrayDestroy(sacopy
);
1513 SafeArrayDestroy(sa
);
1516 static void test_SafeArrayCreateEx(void)
1518 IRecordInfoImpl
* iRec
;
1519 SAFEARRAYBOUND sab
[4];
1524 if (!pSafeArrayCreateEx
)
1526 win_skip("SafeArrayCreateEx not supported\n");
1530 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1532 sab
[dimension
].lLbound
= 0;
1533 sab
[dimension
].cElements
= 8;
1537 sa
= pSafeArrayCreateEx(VT_UI1
, 1, NULL
, NULL
);
1538 ok(sa
== NULL
, "CreateEx NULL bounds didn't fail\n");
1540 /* test IID storage & defaulting */
1541 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, (PVOID
)&IID_ITypeInfo
);
1542 ok(sa
!= NULL
, "CreateEx (ITypeInfo) failed\n");
1547 if (pSafeArrayGetIID
)
1549 hres
= pSafeArrayGetIID(sa
, &guid
);
1550 ok(hres
== S_OK
, "CreateEx (ITypeInfo) no IID hres 0x%x\n", hres
);
1553 ok(IsEqualGUID(&guid
, &IID_ITypeInfo
), "CreateEx (ITypeInfo) bad IID\n");
1556 if (pSafeArraySetIID
)
1558 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
1559 ok(hres
== S_OK
, "Failed to set IID, hres = %8x\n", hres
);
1560 if (hres
== S_OK
&& pSafeArrayGetIID
)
1562 hres
= pSafeArrayGetIID(sa
, &guid
);
1563 ok(hres
== S_OK
&& IsEqualGUID(&guid
, &IID_IUnknown
), "Set bad IID\n");
1566 hres
= SafeArrayDestroy(sa
);
1567 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1570 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, NULL
);
1571 ok(sa
!= NULL
, "CreateEx (NULL) failed\n");
1576 if (pSafeArrayGetIID
)
1578 hres
= pSafeArrayGetIID(sa
, &guid
);
1579 ok(hres
== S_OK
, "CreateEx (NULL) no IID hres 0x%x\n", hres
);
1582 ok(IsEqualGUID(&guid
, &IID_IDispatch
), "CreateEx (NULL) bad IID\n");
1585 hres
= SafeArrayDestroy(sa
);
1586 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1589 sa
= pSafeArrayCreateEx(VT_UNKNOWN
, 1, sab
, NULL
);
1590 ok(sa
!= NULL
, "CreateEx (NULL-Unk) failed\n");
1595 if (pSafeArrayGetIID
)
1597 hres
= pSafeArrayGetIID(sa
, &guid
);
1598 ok(hres
== S_OK
, "CreateEx (NULL-Unk) no IID hres 0x%x\n", hres
);
1601 ok(IsEqualGUID(&guid
, &IID_IUnknown
), "CreateEx (NULL-Unk) bad IID\n");
1604 hres
= SafeArrayDestroy(sa
);
1605 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1608 /* VT_RECORD failure case */
1609 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, NULL
);
1610 ok(sa
== NULL
, "CreateEx (NULL-Rec) succeeded\n");
1612 iRec
= IRecordInfoImpl_Construct();
1614 /* Win32 doesn't care if GetSize fails */
1615 fail_GetSize
= TRUE
;
1616 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1617 ok(sa
!= NULL
, "CreateEx (Fail Size) failed\n");
1618 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1619 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1620 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1623 ok(sa
->cbElements
== RECORD_SIZE_FAIL
, "Altered size to %d\n", sa
->cbElements
);
1624 hres
= SafeArrayDestroy(sa
);
1625 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1626 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1627 ok(iRec
->ref
== START_REF_COUNT
, "got %d, expected %d\n", iRec
->ref
, START_REF_COUNT
);
1630 /* Test VT_RECORD array */
1631 fail_GetSize
= FALSE
;
1632 iRec
->ref
= START_REF_COUNT
;
1633 iRec
->sizeCalled
= 0;
1634 iRec
->clearCalled
= 0;
1635 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1636 ok(sa
!= NULL
, "CreateEx (Rec) failed\n");
1637 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1638 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1639 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1640 if (sa
&& pSafeArrayGetRecordInfo
)
1642 IRecordInfo
* saRec
= NULL
;
1645 hres
= pSafeArrayGetRecordInfo(sa
, &saRec
);
1646 ok(hres
== S_OK
,"GRI failed\n");
1647 ok(saRec
== &iRec
->IRecordInfo_iface
, "Different saRec\n");
1648 ok(iRec
->ref
== START_REF_COUNT
+ 2, "Didn't AddRef %d\n", iRec
->ref
);
1649 IRecordInfo_Release(saRec
);
1651 ok(sa
->cbElements
== RECORD_SIZE
,"Elemsize is %d\n", sa
->cbElements
);
1653 /* try to copy record based arrays */
1654 sacopy
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1655 iRec
->recordcopy
= 0;
1656 iRec
->clearCalled
= 0;
1657 /* array copy code doesn't explicitly clear a record */
1658 hres
= SafeArrayCopyData(sa
, sacopy
);
1659 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1660 ok(iRec
->recordcopy
== sab
[0].cElements
, "got %d\n", iRec
->recordcopy
);
1661 ok(iRec
->clearCalled
== 0, "got %d\n", iRec
->clearCalled
);
1663 hres
= SafeArrayDestroy(sacopy
);
1664 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1666 iRec
->clearCalled
= 0;
1667 iRec
->sizeCalled
= 0;
1668 hres
= SafeArrayDestroy(sa
);
1669 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1670 ok(iRec
->sizeCalled
== 0, "Destroy->GetSize called %d times\n", iRec
->sizeCalled
);
1671 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1672 ok(iRec
->ref
== START_REF_COUNT
, "Wrong iRec refcount %d\n", iRec
->ref
);
1676 hres
= SafeArrayDestroy(sa
);
1677 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1680 IRecordInfo_Release(&iRec
->IRecordInfo_iface
);
1683 static void test_SafeArrayClear(void)
1692 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1693 ok(sa
!= NULL
, "Create() failed.\n");
1697 /* Test clearing non-NULL variants containing arrays */
1698 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1700 hres
= VariantClear(&v
);
1701 ok(hres
== S_OK
&& V_VT(&v
) == VT_EMPTY
, "VariantClear: hres 0x%x, Type %d\n", hres
, V_VT(&v
));
1702 ok(V_ARRAY(&v
) == sa
, "VariantClear: Overwrote value\n");
1704 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1705 ok(sa
!= NULL
, "Create() failed.\n");
1709 V_VT(&v
) = VT_SAFEARRAY
;
1711 hres
= VariantClear(&v
);
1712 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1714 V_VT(&v
) = VT_SAFEARRAY
|VT_BYREF
;
1715 V_ARRAYREF(&v
) = &sa
;
1716 hres
= VariantClear(&v
);
1717 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1719 hres
= SafeArrayDestroy(sa
);
1720 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1723 static void test_SafeArrayCopy(void)
1726 SAFEARRAY
*sa
, *sa2
;
1727 VARIANTARG vSrc
, vDst
;
1733 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1734 ok(sa
!= NULL
, "Create() failed.\n");
1738 /* Test copying non-NULL variants containing arrays */
1739 V_VT(&vSrc
) = (VT_ARRAY
|VT_BYREF
|VT_UI1
);
1740 V_ARRAYREF(&vSrc
) = &sa
;
1741 V_VT(&vDst
) = VT_EMPTY
;
1743 hres
= VariantCopy(&vDst
, &vSrc
);
1744 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_BYREF
|VT_UI1
),
1745 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1746 ok(V_ARRAYREF(&vDst
) == &sa
, "VariantClear: Performed deep copy\n");
1748 V_VT(&vSrc
) = (VT_ARRAY
|VT_UI1
);
1749 V_ARRAY(&vSrc
) = sa
;
1750 V_VT(&vDst
) = VT_EMPTY
;
1752 hres
= VariantCopy(&vDst
, &vSrc
);
1753 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_UI1
),
1754 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1755 ok(V_ARRAY(&vDst
) != sa
, "VariantClear: Performed shallow copy\n");
1757 hres
= SafeArrayDestroy(V_ARRAY(&vSrc
));
1758 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1759 hres
= SafeArrayDestroy(V_ARRAY(&vDst
));
1760 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1762 hres
= SafeArrayAllocDescriptor(1, &sa
);
1763 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1765 sa
->cbElements
= 16;
1766 hres
= SafeArrayCopy(sa
, &sa2
);
1767 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1768 ok(sa
!= sa2
, "SafeArrayCopy performed shallow copy\n");
1770 hres
= SafeArrayDestroy(sa2
);
1771 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1772 hres
= SafeArrayDestroy(sa
);
1773 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1775 sa2
= (void*)0xdeadbeef;
1776 hres
= SafeArrayCopy(NULL
, &sa2
);
1777 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1778 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1780 hres
= SafeArrayAllocDescriptor(1, &sa
);
1781 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1783 sa2
= (void*)0xdeadbeef;
1784 hres
= SafeArrayCopy(sa
, &sa2
);
1785 ok(hres
== E_INVALIDARG
,
1786 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1788 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1790 hres
= SafeArrayDestroy(sa2
);
1791 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1792 hres
= SafeArrayDestroy(sa
);
1793 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1795 /* test feature copy */
1796 hres
= SafeArrayAllocDescriptor(1, &sa
);
1797 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1798 ok(sa
->fFeatures
== 0, "got src features 0x%04x\n", sa
->fFeatures
);
1799 sa
->cbElements
= 16;
1801 for (i
= 0; i
< sizeof(ignored_copy_features
)/sizeof(USHORT
); i
++)
1803 USHORT feature
= ignored_copy_features
[i
];
1805 sa
->fFeatures
|= feature
;
1806 hres
= SafeArrayCopy(sa
, &sa2
);
1807 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1808 ok(sa2
->fFeatures
== 0, "got features 0x%04x\n", sa2
->fFeatures
);
1809 hres
= SafeArrayDestroy(sa2
);
1810 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1811 sa
->fFeatures
&= ~feature
;
1814 SafeArrayDestroy(sa
);
1816 /* copy from a vector */
1817 sa
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1818 ok(sa
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1819 broken(sa
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1820 "got 0x%08x\n", sa
->fFeatures
);
1821 hres
= SafeArrayCopy(sa
, &sa2
);
1822 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1823 ok(sa2
->fFeatures
== FADF_HAVEVARTYPE
||
1824 broken(!sa2
->fFeatures
/* W2k */), "got 0x%04x\n",
1827 SafeArrayDestroy(sa2
);
1828 SafeArrayDestroy(sa
);
1831 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1832 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1834 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1836 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1837 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1838 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1840 static void test_SafeArrayChangeTypeEx(void)
1842 static const char *szHello
= "Hello World";
1849 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1850 MKARRAY(0,strlen(szHello
)+1,VT_UI1
);
1851 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1853 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1854 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1857 ok(V_VT(&v2
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2
));
1858 ok(strcmp((char*)V_BSTR(&v2
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1859 (char*)V_BSTR(&v2
));
1863 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1864 hres
= SafeArrayDestroy(sa
);
1865 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1866 if (pSafeArrayCreateVector
)
1868 sa
= pSafeArrayCreateVector(VT_UI1
, 0, strlen(szHello
)+1);
1869 ok(sa
!= NULL
, "CreateVector() failed.\n");
1873 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1874 V_VT(&v
) = VT_VECTOR
|VT_UI1
;
1878 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1879 ok(hres
== DISP_E_BADVARTYPE
, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres
);
1881 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1882 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1883 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
1884 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1887 ok(V_VT(&v
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v
));
1888 ok(strcmp((char*)V_BSTR(&v
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1894 /* To/from BSTR only works with arrays of VT_UI1 */
1895 for (vt
= VT_EMPTY
; vt
<= VT_CLSID
; vt
++)
1902 sa
= SafeArrayCreate(vt
, 1, &sab
);
1905 V_VT(&v
) = VT_ARRAY
|vt
;
1909 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1910 if (vt
== VT_INT_PTR
|| vt
== VT_UINT_PTR
)
1912 ok(hres
== DISP_E_BADVARTYPE
, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres
);
1913 SafeArrayDestroy(sa
);
1917 ok(hres
== DISP_E_TYPEMISMATCH
, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres
, vt
);
1918 hres
= VariantClear(&v
);
1919 ok(hres
== S_OK
, "expected S_OK, got 0x%08x\n", hres
);
1924 /* Can't change an array of one type into array of another type , even
1925 * if the other type is the same size
1927 if (pSafeArrayCreateVector
)
1929 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1930 ok(sa
!= NULL
, "CreateVector() failed.\n");
1934 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1936 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_I1
);
1937 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres
);
1939 /* But can change to the same array type */
1940 hres
= SafeArrayDestroy(sa
);
1941 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1942 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1943 ok(sa
!= NULL
, "CreateVector() failed.\n");
1946 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1948 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_UI1
);
1949 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres
);
1950 hres
= SafeArrayDestroy(sa
);
1951 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1956 MKARRAY(0,1,VT_UI1
);
1957 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_NULL
);
1958 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1960 MKARRAY(0,1,VT_UI1
);
1961 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_EMPTY
);
1962 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1966 static void test_SafeArrayDestroyData (void)
1968 SAFEARRAYBOUND sab
[2];
1971 int value
= 0xdeadbeef;
1977 sab
[0].cElements
= 10;
1978 sa
= SafeArrayCreate(VT_INT
, 1, sab
);
1979 ok(sa
!= NULL
, "Create() failed.\n");
1980 ok(sa
->fFeatures
== FADF_HAVEVARTYPE
, "got 0x%x\n", sa
->fFeatures
);
1983 SafeArrayPutElement (sa
, index
, &value
);
1985 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1986 features
= (sa
->fFeatures
|= FADF_STATIC
);
1987 temp_pvData
= sa
->pvData
;
1988 hres
= SafeArrayDestroyData(sa
);
1989 ok(hres
== S_OK
, "SADData FADF_STATIC failed, error code %x.\n",hres
);
1990 ok(features
== sa
->fFeatures
, "got 0x%x\n", sa
->fFeatures
);
1991 ok(sa
->pvData
== temp_pvData
, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1992 sa
->pvData
, temp_pvData
, sa
->fFeatures
);
1993 SafeArrayGetElement (sa
, index
, &value
);
1994 ok(value
== 0, "Data not cleared after SADData\n");
1996 /* Clear FADF_STATIC, now really destroy the data. */
1997 features
= (sa
->fFeatures
^= FADF_STATIC
);
1998 hres
= SafeArrayDestroyData(sa
);
1999 ok(hres
== S_OK
, "SADData !FADF_STATIC failed, error code %x.\n",hres
);
2000 ok(features
== sa
->fFeatures
, "got 0x%x\n", sa
->fFeatures
);
2001 ok(sa
->pvData
== NULL
, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa
->pvData
);
2003 hres
= SafeArrayDestroy(sa
);
2004 ok(hres
== S_OK
, "SAD failed, error code %x.\n", hres
);
2006 /* two dimensions */
2008 sab
[0].cElements
= 10;
2010 sab
[1].cElements
= 10;
2012 sa
= SafeArrayCreate(VT_INT
, 2, sab
);
2013 ok(sa
!= NULL
, "Create() failed.\n");
2014 ok(sa
->fFeatures
== FADF_HAVEVARTYPE
, "got 0x%x\n", sa
->fFeatures
);
2016 features
= sa
->fFeatures
;
2017 hres
= SafeArrayDestroyData(sa
);
2018 ok(hres
== S_OK
, "got 0x%08x\n",hres
);
2019 ok(features
== sa
->fFeatures
, "got 0x%x\n", sa
->fFeatures
);
2021 SafeArrayDestroy(sa
);
2023 /* try to destroy data from descriptor */
2024 hres
= SafeArrayAllocDescriptor(1, &sa
);
2025 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2026 ok(sa
->fFeatures
== 0, "got 0x%x\n", sa
->fFeatures
);
2028 hres
= SafeArrayDestroyData(sa
);
2029 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2030 ok(sa
->fFeatures
== 0, "got 0x%x\n", sa
->fFeatures
);
2032 hres
= SafeArrayDestroyDescriptor(sa
);
2033 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2035 hres
= SafeArrayAllocDescriptor(2, &sa
);
2036 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2037 ok(sa
->fFeatures
== 0, "got 0x%x\n", sa
->fFeatures
);
2039 hres
= SafeArrayDestroyData(sa
);
2040 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2041 ok(sa
->fFeatures
== 0, "got 0x%x\n", sa
->fFeatures
);
2043 hres
= SafeArrayDestroyDescriptor(sa
);
2044 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2047 sa
= SafeArrayCreateVector(VT_I4
, 0, 10);
2048 ok(sa
!= NULL
, "got %p\n", sa
);
2049 ok(sa
->fFeatures
== (FADF_CREATEVECTOR
|FADF_HAVEVARTYPE
), "got 0x%x\n", sa
->fFeatures
);
2051 ok(sa
->pvData
!= NULL
, "got %p\n", sa
->pvData
);
2052 hres
= SafeArrayDestroyData(sa
);
2053 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
2055 ok(sa
->fFeatures
== FADF_HAVEVARTYPE
, "got 0x%x\n", sa
->fFeatures
);
2056 ok(sa
->pvData
!= NULL
, "got %p\n", sa
->pvData
);
2057 /* There seems to be a bug on windows, especially visible on 64bit systems,
2058 probably double-free of similar issue. */
2060 SafeArrayDestroy(sa
);
2063 static void test_safearray_layout(void)
2065 IRecordInfoImpl
*irec
;
2066 IRecordInfo
*record
;
2067 GUID guid
, *guidptr
;
2077 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
2078 ok(sa
!= NULL
, "got %p\n", sa
);
2080 guidptr
= (GUID
*)sa
- 1;
2081 ok(IsEqualIID(guidptr
, &IID_IUnknown
), "got %s\n", wine_dbgstr_guid(guidptr
));
2083 hr
= SafeArraySetIID(sa
, &IID_IDispatch
);
2084 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2085 ok(IsEqualIID(guidptr
, &IID_IDispatch
), "got %s\n", wine_dbgstr_guid(guidptr
));
2087 memcpy(guidptr
, &IID_IUnknown
, sizeof(GUID
));
2088 hr
= SafeArrayGetIID(sa
, &guid
);
2089 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2090 ok(IsEqualIID(&guid
, &IID_IUnknown
), "got %s\n", wine_dbgstr_guid(&guid
));
2092 hr
= SafeArrayDestroy(sa
);
2093 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2096 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
2097 ok(sa
!= NULL
, "got %p\n", sa
);
2099 dwptr
= (DWORD
*)sa
- 1;
2100 ok(*dwptr
== VT_UI1
, "got %d\n", *dwptr
);
2102 hr
= SafeArrayDestroy(sa
);
2103 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2105 /* IRecordInfo pointer */
2106 irec
= IRecordInfoImpl_Construct();
2109 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, &sab
, &irec
->IRecordInfo_iface
);
2110 ok(sa
!= NULL
, "failed to create array\n");
2112 record
= *((IRecordInfo
**)sa
- 1);
2113 ok(record
== &irec
->IRecordInfo_iface
, "got %p\n", record
);
2115 hr
= SafeArrayDestroy(sa
);
2116 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2117 IRecordInfo_Release(&irec
->IRecordInfo_iface
);
2120 START_TEST(safearray
)
2122 hOleaut32
= GetModuleHandleA("oleaut32.dll");
2124 has_i8
= GetProcAddress(hOleaut32
, "VarI8FromI1") != NULL
;
2126 GETPTR(SafeArrayAllocDescriptorEx
);
2127 GETPTR(SafeArrayCopyData
);
2128 GETPTR(SafeArrayGetIID
);
2129 GETPTR(SafeArraySetIID
);
2130 GETPTR(SafeArrayGetVartype
);
2131 GETPTR(SafeArrayCreateEx
);
2132 GETPTR(SafeArrayCreateVector
);
2133 GETPTR(SafeArrayGetRecordInfo
);
2135 check_for_VT_INT_PTR();
2137 test_SafeArrayAllocDestroyDescriptor();
2138 test_SafeArrayCreateLockDestroy();
2139 test_VectorCreateLockDestroy();
2141 test_SafeArrayChangeTypeEx();
2142 test_SafeArrayCopy();
2143 test_SafeArrayClear();
2144 test_SafeArrayCreateEx();
2145 test_SafeArrayCopyData();
2146 test_SafeArrayDestroyData();
2147 test_SafeArrayGetPutElement();
2148 test_SafeArrayGetPutElement_BSTR();
2149 test_SafeArrayGetPutElement_IUnknown();
2150 test_SafeArrayRedim_IUnknown();
2151 test_SafeArrayGetPutElement_VARIANT();
2152 test_safearray_layout();