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
22 #define WIN32_NO_STATUS
24 #define COM_NO_WINDOWS_H
33 #include <wine/test.h>
35 //#include "winbase.h"
36 //#include "winuser.h"
39 //#include "winsock.h"
40 //#include "winerror.h"
46 #ifndef FADF_CREATEVECTOR
47 const USHORT FADF_CREATEVECTOR
= 0x2000;
50 static HMODULE hOleaut32
;
52 static HRESULT (WINAPI
*pSafeArrayAllocDescriptorEx
)(VARTYPE
,UINT
,SAFEARRAY
**);
53 static HRESULT (WINAPI
*pSafeArrayCopyData
)(SAFEARRAY
*,SAFEARRAY
*);
54 static HRESULT (WINAPI
*pSafeArrayGetIID
)(SAFEARRAY
*,GUID
*);
55 static HRESULT (WINAPI
*pSafeArraySetIID
)(SAFEARRAY
*,REFGUID
);
56 static HRESULT (WINAPI
*pSafeArrayGetVartype
)(SAFEARRAY
*,VARTYPE
*);
57 static HRESULT (WINAPI
*pSafeArrayGetRecordInfo
)(SAFEARRAY
*,IRecordInfo
**);
58 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateEx
)(VARTYPE
,UINT
,SAFEARRAYBOUND
*,LPVOID
);
59 static SAFEARRAY
* (WINAPI
*pSafeArrayCreateVector
)(VARTYPE
,LONG
,ULONG
);
61 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
63 /* Has I8/UI8 data type? */
65 /* Has INT_PTR/UINT_PTR type? */
66 static BOOL has_int_ptr
;
68 static const USHORT ignored_copy_features
[] =
76 #define START_REF_COUNT 1
77 #define RECORD_SIZE 64
78 #define RECORD_SIZE_FAIL 17
79 /************************************************************************
80 * Dummy IRecordInfo Implementation
82 typedef struct IRecordInfoImpl
84 IRecordInfo IRecordInfo_iface
;
86 unsigned int sizeCalled
;
87 unsigned int clearCalled
;
88 unsigned int recordcopy
;
91 static inline IRecordInfoImpl
*impl_from_IRecordInfo(IRecordInfo
*iface
)
93 return CONTAINING_RECORD(iface
, IRecordInfoImpl
, IRecordInfo_iface
);
96 static HRESULT WINAPI
RecordInfo_QueryInterface(IRecordInfo
*iface
, REFIID riid
, void **obj
)
100 if (IsEqualIID(riid
, &IID_IUnknown
) ||
101 IsEqualIID(riid
, &IID_IRecordInfo
))
104 IRecordInfo_AddRef(iface
);
108 return E_NOINTERFACE
;
111 static ULONG WINAPI
RecordInfo_AddRef(IRecordInfo
*iface
)
113 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
114 return InterlockedIncrement(&This
->ref
);
117 static ULONG WINAPI
RecordInfo_Release(IRecordInfo
*iface
)
119 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
120 ULONG ref
= InterlockedDecrement(&This
->ref
);
123 HeapFree(GetProcessHeap(), 0, This
);
128 static HRESULT WINAPI
RecordInfo_RecordInit(IRecordInfo
*iface
, PVOID pvNew
)
130 ok(0, "unexpected call\n");
134 static BOOL fail_GetSize
; /* Whether to fail the GetSize call */
136 static HRESULT WINAPI
RecordInfo_RecordClear(IRecordInfo
*iface
, PVOID pvExisting
)
138 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
143 static HRESULT WINAPI
RecordInfo_RecordCopy(IRecordInfo
*iface
, PVOID pvExisting
, PVOID pvNew
)
145 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
150 static HRESULT WINAPI
RecordInfo_GetGuid(IRecordInfo
*iface
, GUID
*pguid
)
152 ok(0, "unexpected call\n");
156 static HRESULT WINAPI
RecordInfo_GetName(IRecordInfo
*iface
, BSTR
*pbstrName
)
158 ok(0, "unexpected call\n");
162 static HRESULT WINAPI
RecordInfo_GetSize(IRecordInfo
*iface
, ULONG
* size
)
164 IRecordInfoImpl
* This
= impl_from_IRecordInfo(iface
);
168 *size
= RECORD_SIZE_FAIL
;
175 static HRESULT WINAPI
RecordInfo_GetTypeInfo(IRecordInfo
*iface
, ITypeInfo
**ppTypeInfo
)
177 ok(0, "unexpected call\n");
181 static HRESULT WINAPI
RecordInfo_GetField(IRecordInfo
*iface
, PVOID pvData
,
182 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
184 ok(0, "unexpected call\n");
188 static HRESULT WINAPI
RecordInfo_GetFieldNoCopy(IRecordInfo
*iface
, PVOID pvData
,
189 LPCOLESTR szFieldName
, VARIANT
*pvarField
, PVOID
*ppvDataCArray
)
191 ok(0, "unexpected call\n");
195 static HRESULT WINAPI
RecordInfo_PutField(IRecordInfo
*iface
, ULONG wFlags
, PVOID pvData
,
196 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
198 ok(0, "unexpected call\n");
202 static HRESULT WINAPI
RecordInfo_PutFieldNoCopy(IRecordInfo
*iface
, ULONG wFlags
,
203 PVOID pvData
, LPCOLESTR szFieldName
, VARIANT
*pvarField
)
205 ok(0, "unexpected call\n");
209 static HRESULT WINAPI
RecordInfo_GetFieldNames(IRecordInfo
*iface
, ULONG
*pcNames
,
212 ok(0, "unexpected call\n");
216 static BOOL WINAPI
RecordInfo_IsMatchingType(IRecordInfo
*iface
, IRecordInfo
*info2
)
218 ok(0, "unexpected call\n");
222 static PVOID WINAPI
RecordInfo_RecordCreate(IRecordInfo
*iface
)
224 ok(0, "unexpected call\n");
228 static HRESULT WINAPI
RecordInfo_RecordCreateCopy(IRecordInfo
*iface
, PVOID pvSource
,
231 ok(0, "unexpected call\n");
235 static HRESULT WINAPI
RecordInfo_RecordDestroy(IRecordInfo
*iface
, PVOID pvRecord
)
237 ok(0, "unexpected call\n");
241 static const IRecordInfoVtbl RecordInfoVtbl
=
243 RecordInfo_QueryInterface
,
246 RecordInfo_RecordInit
,
247 RecordInfo_RecordClear
,
248 RecordInfo_RecordCopy
,
252 RecordInfo_GetTypeInfo
,
254 RecordInfo_GetFieldNoCopy
,
256 RecordInfo_PutFieldNoCopy
,
257 RecordInfo_GetFieldNames
,
258 RecordInfo_IsMatchingType
,
259 RecordInfo_RecordCreate
,
260 RecordInfo_RecordCreateCopy
,
261 RecordInfo_RecordDestroy
264 static IRecordInfoImpl
*IRecordInfoImpl_Construct(void)
266 IRecordInfoImpl
*rec
;
268 rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl
));
269 rec
->IRecordInfo_iface
.lpVtbl
= &RecordInfoVtbl
;
270 rec
->ref
= START_REF_COUNT
;
271 rec
->clearCalled
= 0;
276 static DWORD
SAFEARRAY_GetVTSize(VARTYPE vt
)
281 case VT_UI1
: return sizeof(BYTE
);
284 case VT_UI2
: return sizeof(SHORT
);
288 case VT_ERROR
: return sizeof(LONG
);
289 case VT_R8
: return sizeof(LONG64
);
293 return sizeof(LONG64
);
296 case VT_UINT
: return sizeof(INT
);
300 return sizeof(UINT_PTR
);
302 case VT_CY
: return sizeof(CY
);
303 case VT_DATE
: return sizeof(DATE
);
304 case VT_BSTR
: return sizeof(BSTR
);
305 case VT_DISPATCH
: return sizeof(LPDISPATCH
);
306 case VT_VARIANT
: return sizeof(VARIANT
);
307 case VT_UNKNOWN
: return sizeof(LPUNKNOWN
);
308 case VT_DECIMAL
: return sizeof(DECIMAL
);
313 static void check_for_VT_INT_PTR(void)
315 /* Set a global flag if VT_INT_PTR is supported */
318 SAFEARRAYBOUND bound
;
321 a
= SafeArrayCreate(VT_INT_PTR
, 1, &bound
);
324 trace("VT_INT_PTR is supported\n");
326 hres
= SafeArrayDestroy(a
);
327 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
330 trace("VT_INT_PTR is not supported\n");
335 #define VARTYPE_NOT_SUPPORTED 0
338 UINT elemsize
; /* elementsize by VT */
339 UINT expflags
; /* fFeatures from SafeArrayAllocDescriptorEx */
340 UINT addflags
; /* additional fFeatures from SafeArrayCreate */
342 {VT_EMPTY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
343 {VT_NULL
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
344 {VT_I2
, 2, FADF_HAVEVARTYPE
,0},
345 {VT_I4
, 4, FADF_HAVEVARTYPE
,0},
346 {VT_R4
, 4, FADF_HAVEVARTYPE
,0},
347 {VT_R8
, 8, FADF_HAVEVARTYPE
,0},
348 {VT_CY
, 8, FADF_HAVEVARTYPE
,0},
349 {VT_DATE
, 8, FADF_HAVEVARTYPE
,0},
350 {VT_BSTR
, sizeof(BSTR
), FADF_HAVEVARTYPE
,FADF_BSTR
},
351 {VT_DISPATCH
, sizeof(LPDISPATCH
), FADF_HAVEIID
, FADF_DISPATCH
},
352 {VT_ERROR
, 4, FADF_HAVEVARTYPE
,0},
353 {VT_BOOL
, 2, FADF_HAVEVARTYPE
,0},
354 {VT_VARIANT
, sizeof(VARIANT
), FADF_HAVEVARTYPE
,FADF_VARIANT
},
355 {VT_UNKNOWN
, sizeof(LPUNKNOWN
), FADF_HAVEIID
, FADF_UNKNOWN
},
356 {VT_DECIMAL
, sizeof(DECIMAL
), FADF_HAVEVARTYPE
,0},
357 {15, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0}, /* no VT_xxx */
358 {VT_I1
, 1, FADF_HAVEVARTYPE
,0},
359 {VT_UI1
, 1, FADF_HAVEVARTYPE
,0},
360 {VT_UI2
, 2, FADF_HAVEVARTYPE
,0},
361 {VT_UI4
, 4, FADF_HAVEVARTYPE
,0},
362 {VT_I8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
363 {VT_UI8
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
364 {VT_INT
, sizeof(INT
), FADF_HAVEVARTYPE
,0},
365 {VT_UINT
, sizeof(UINT
), FADF_HAVEVARTYPE
,0},
366 {VT_VOID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
367 {VT_HRESULT
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
368 {VT_PTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
369 {VT_SAFEARRAY
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
370 {VT_CARRAY
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
371 {VT_USERDEFINED
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
372 {VT_LPSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
373 {VT_LPWSTR
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
374 {VT_FILETIME
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
375 {VT_RECORD
, VARTYPE_NOT_SUPPORTED
,FADF_RECORD
,0},
376 {VT_BLOB
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
377 {VT_STREAM
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
378 {VT_STORAGE
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
379 {VT_STREAMED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
380 {VT_STORED_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
381 {VT_BLOB_OBJECT
,VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
382 {VT_CF
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
383 {VT_CLSID
, VARTYPE_NOT_SUPPORTED
,FADF_HAVEVARTYPE
,0},
386 static void test_safearray(void)
389 unsigned int i
, diff
;
392 SAFEARRAYBOUND bound
, bounds
[2];
398 unsigned char *ptr1
, *ptr2
;
400 hres
= SafeArrayDestroy( NULL
);
401 ok( hres
== S_OK
, "SafeArrayDestroy( NULL) returned 0x%x\n", hres
);
405 a
= SafeArrayCreate(-1, 1, &bound
);
406 ok(NULL
== a
,"SAC(-1,1,[1,0]) not failed?\n");
410 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
411 ok(NULL
!= a
,"SAC(VT_I4,1,[0,0]) failed.\n");
413 hres
= SafeArrayGetLBound(a
, 1, &l
);
414 ok(hres
== S_OK
, "SAGLB of 0 size dimensioned array failed with %x\n",hres
);
415 ok(l
== 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l
);
416 hres
= SafeArrayGetUBound(a
, 1, &l
);
417 ok(hres
== S_OK
, "SAGUB of 0 size dimensioned array failed with %x\n",hres
);
418 ok(l
== 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l
);
420 hres
= SafeArrayAccessData(a
, &data
);
421 ok(hres
== S_OK
, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres
);
422 SafeArrayUnaccessData(a
);
425 hres
= SafeArrayRedim(a
, &bound
);
426 ok(hres
== S_OK
,"SAR of a 0 elements dimension failed with hres %x\n", hres
);
428 hres
= SafeArrayRedim(a
, &bound
);
429 ok(hres
== S_OK
|| hres
== E_OUTOFMEMORY
,
430 "SAR to a 0 elements dimension failed with hres %x\n", hres
);
431 hres
= SafeArrayDestroy(a
);
432 ok(hres
== S_OK
,"SAD of 0 dim array failed with hres %x\n", hres
);
434 SafeArrayAllocDescriptor(2, &a
);
435 a
->rgsabound
[0].cElements
= 2;
436 a
->rgsabound
[0].lLbound
= 1;
437 a
->rgsabound
[1].cElements
= 4;
438 a
->rgsabound
[1].lLbound
= 1;
440 hres
= SafeArrayAllocData(a
);
441 ok(hres
== S_OK
, "SafeArrayAllocData failed with hres %x\n", hres
);
445 hres
= SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
446 ok(hres
== S_OK
, "SAPOI failed with hres %x\n", hres
);
447 SafeArrayAccessData(a
, (void **)&ptr2
);
448 ok(ptr1
- ptr2
== 14, "SAPOI got wrong ptr\n");
449 *(WORD
*)ptr1
= 0x55aa;
450 SafeArrayUnaccessData(a
);
452 bound
.cElements
= 10;
454 SafeArrayRedim(a
, &bound
);
456 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
457 ok(*(WORD
*)ptr1
== 0x55aa, "Data not preserved when resizing array\n");
459 bound
.cElements
= 10;
461 SafeArrayRedim(a
, &bound
);
462 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
463 ok(*(WORD
*)ptr1
== 0 ||
464 broken(*(WORD
*)ptr1
!= 0), /* Win 2003 */
465 "Expanded area not zero-initialized\n");
468 SafeArrayPtrOfIndex(a
, indices
, (void **)&ptr1
);
469 ok(*(WORD
*)ptr1
== 0x55aa ||
470 broken(*(WORD
*)ptr1
!= 0x55aa), /* Win 2003 */
471 "Data not preserved when resizing array\n");
473 hres
= SafeArrayDestroy(a
);
474 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
476 bounds
[0].cElements
= 0; bounds
[0].lLbound
= 1;
477 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
478 a
= SafeArrayCreate(VT_I4
,2,bounds
);
479 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
481 hres
= SafeArrayDestroy(a
);
482 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
483 bounds
[0].cElements
= 1; bounds
[0].lLbound
= 1;
484 bounds
[1].cElements
= 0; bounds
[1].lLbound
= 23;
485 a
= SafeArrayCreate(VT_I4
,2,bounds
);
486 ok(a
!= NULL
,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
488 hres
= SafeArrayDestroy(a
);
489 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
491 bounds
[0].cElements
= 42; bounds
[0].lLbound
= 1;
492 bounds
[1].cElements
= 2; bounds
[1].lLbound
= 23;
493 a
= SafeArrayCreate(VT_I4
,2,bounds
);
494 ok(a
!= NULL
,"SAC(VT_INT32,2,...) failed.\n");
496 hres
= SafeArrayGetLBound (a
, 0, &l
);
497 ok (hres
== DISP_E_BADINDEX
, "SAGLB 0 failed with %x\n", hres
);
498 hres
= SafeArrayGetLBound (a
, 1, &l
);
499 ok (hres
== S_OK
, "SAGLB 1 failed with %x\n", hres
);
500 ok (l
== 1, "SAGLB 1 returned %d instead of 1\n", l
);
501 hres
= SafeArrayGetLBound (a
, 2, &l
);
502 ok (hres
== S_OK
, "SAGLB 2 failed with %x\n", hres
);
503 ok (l
== 23, "SAGLB 2 returned %d instead of 23\n", l
);
504 hres
= SafeArrayGetLBound (a
, 3, &l
);
505 ok (hres
== DISP_E_BADINDEX
, "SAGLB 3 failed with %x\n", hres
);
507 hres
= SafeArrayGetUBound (a
, 0, &l
);
508 ok (hres
== DISP_E_BADINDEX
, "SAGUB 0 failed with %x\n", hres
);
509 hres
= SafeArrayGetUBound (a
, 1, &l
);
510 ok (hres
== S_OK
, "SAGUB 1 failed with %x\n", hres
);
511 ok (l
== 42, "SAGUB 1 returned %d instead of 42\n", l
);
512 hres
= SafeArrayGetUBound (a
, 2, &l
);
513 ok (hres
== S_OK
, "SAGUB 2 failed with %x\n", hres
);
514 ok (l
== 24, "SAGUB 2 returned %d instead of 24\n", l
);
515 hres
= SafeArrayGetUBound (a
, 3, &l
);
516 ok (hres
== DISP_E_BADINDEX
, "SAGUB 3 failed with %x\n", hres
);
518 i
= SafeArrayGetDim(a
);
519 ok(i
== 2, "getdims of 2 din array returned %d\n",i
);
523 hres
= SafeArrayGetElement(a
, indices
, &i
);
524 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [0,23], hres 0x%x\n",hres
);
528 hres
= SafeArrayGetElement(a
, indices
, &i
);
529 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,22], hres 0x%x\n",hres
);
533 hres
= SafeArrayGetElement(a
, indices
, &i
);
534 ok(S_OK
== hres
,"SAGE failed [1,23], hres 0x%x\n",hres
);
538 hres
= SafeArrayGetElement(a
, indices
, &i
);
539 ok(DISP_E_BADINDEX
== hres
,"SAGE failed [1,24], hres 0x%x\n",hres
);
543 hres
= SafeArrayGetElement(a
, indices
, &i
);
544 ok(S_OK
== hres
,"SAGE failed [42,23], hres 0x%x\n",hres
);
546 hres
= SafeArrayAccessData(a
, (void**)&ptr1
);
547 ok(S_OK
== hres
, "SAAD failed with 0x%x\n", hres
);
551 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
552 ok(S_OK
== hres
,"SAPOI failed [1,23], hres 0x%x\n",hres
);
554 ok(diff
== 8,"ptr difference is not 8, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
558 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
559 ok(S_OK
== hres
,"SAPOI failed [5,24], hres 0x%x\n",hres
);
561 ok(diff
== 176,"ptr difference is not 176, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
565 hres
= SafeArrayPtrOfIndex(a
, indices
, (void**)&ptr2
);
566 ok(S_OK
== hres
,"SAPOI failed [20,23], hres 0x%x\n",hres
);
568 ok(diff
== 76,"ptr difference is not 76, but %d (%p vs %p)\n", diff
, ptr2
, ptr1
);
570 hres
= SafeArrayUnaccessData(a
);
571 ok(S_OK
== hres
, "SAUAD failed with 0x%x\n", hres
);
573 hres
= SafeArrayDestroy(a
);
574 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
576 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
577 if ((i
== VT_I8
|| i
== VT_UI8
) && has_i8
)
579 vttypes
[i
].elemsize
= sizeof(LONG64
);
582 a
= SafeArrayCreate(vttypes
[i
].vt
, 1, &bound
);
584 ok((!a
&& !vttypes
[i
].elemsize
) ||
585 (a
&& vttypes
[i
].elemsize
== a
->cbElements
),
586 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
587 vttypes
[i
].vt
,a
,(a
?a
->cbElements
:0),vttypes
[i
].elemsize
);
591 ok(a
->fFeatures
== (vttypes
[i
].expflags
| vttypes
[i
].addflags
),
592 "SAC of %d returned feature flags %x, expected %x\n",
593 vttypes
[i
].vt
, a
->fFeatures
,
594 vttypes
[i
].expflags
|vttypes
[i
].addflags
);
595 ok(SafeArrayGetElemsize(a
) == vttypes
[i
].elemsize
,
596 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
597 vttypes
[i
].vt
, SafeArrayGetElemsize(a
),vttypes
[i
].elemsize
);
602 if (pSafeArrayGetVartype
)
604 hres
= pSafeArrayGetVartype(a
, &vt
);
605 ok(hres
== S_OK
, "SAGVT of arra y with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
606 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
607 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
610 hres
= SafeArrayCopy(a
, &c
);
611 ok(hres
== S_OK
, "failed to copy safearray of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
613 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
615 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
);
616 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
);
618 if (pSafeArrayGetVartype
) {
619 hres
= pSafeArrayGetVartype(c
, &vt
);
620 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
621 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
622 ok(broken(vt
== VT_UNKNOWN
) || vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
625 if (pSafeArrayCopyData
) {
626 hres
= pSafeArrayCopyData(a
, c
);
627 ok(hres
== S_OK
, "failed to copy safearray data of vt %d with hres %x\n", vttypes
[i
].vt
, hres
);
629 hres
= SafeArrayDestroyData(c
);
630 ok(hres
== S_OK
,"SADD of copy of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
633 hres
= SafeArrayDestroy(c
);
634 ok(hres
== S_OK
,"SAD failed with hres %x\n", hres
);
636 hres
= SafeArrayDestroy(a
);
637 ok(hres
== S_OK
,"SAD of array with vt %d failed with hres %x\n", vttypes
[i
].vt
, hres
);
640 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
642 bound
.cElements
= 10;
643 a
= SafeArrayCreate(VT_UI1
, 1, &bound
);
644 ok(a
!= NULL
, "SAC failed.\n");
645 ok(S_OK
== SafeArrayAccessData(a
, &data
),"SACD failed\n");
646 memcpy(data
,"Hello World\n",10);
647 ok(S_OK
== SafeArrayUnaccessData(a
),"SAUD failed\n");
648 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
650 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
651 ok(hres
==S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres
);
652 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
));
653 ok(V_BSTR(&v
)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v
)[0]);
658 V_BSTR(&v
) = SysAllocStringLen(NULL
, 0);
659 hres
= VariantChangeTypeEx(&d
, &v
, 0, 0, VT_UI1
|VT_ARRAY
);
660 ok(hres
==S_OK
, "CTE VT_BSTR -> VT_UI1|VT_ARRAY failed with %x\n",hres
);
661 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
));
665 /* check locking functions */
666 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
667 ok(a
!=NULL
,"SAC should not fail\n");
669 hres
= SafeArrayAccessData(a
, &data
);
670 ok(hres
== S_OK
,"SAAD failed with hres %x\n",hres
);
672 hres
= SafeArrayDestroy(a
);
673 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
675 hres
= SafeArrayDestroyData(a
);
676 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
678 hres
= SafeArrayDestroyDescriptor(a
);
679 ok(hres
== DISP_E_ARRAYISLOCKED
,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres
);
681 hres
= SafeArrayUnaccessData(a
);
682 ok(hres
== S_OK
,"SAUD failed after lock/destroy test\n");
684 hres
= SafeArrayDestroy(a
);
685 ok(hres
== S_OK
,"SAD failed after lock/destroy test\n");
687 /* Test if we need to destroy data before descriptor */
688 a
= SafeArrayCreate(VT_I4
, 1, &bound
);
689 ok(a
!=NULL
,"SAC should not fail\n");
690 hres
= SafeArrayDestroyDescriptor(a
);
691 ok(hres
== S_OK
,"SADD with data in array failed with hres %x\n",hres
);
694 /* init a small stack safearray */
695 if (pSafeArraySetIID
) {
696 memset(&b
, 0, sizeof(b
));
698 memset(&iid
, 0x42, sizeof(IID
));
699 hres
= pSafeArraySetIID(&b
,&iid
);
700 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %x\n",hres
);
702 hres
= SafeArrayAllocDescriptor(1,&a
);
703 ok(hres
== S_OK
,"SafeArrayAllocDescriptor should return S_OK, but got %x\n",hres
);
704 ok((a
->fFeatures
& FADF_HAVEIID
) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
705 hres
= pSafeArraySetIID(a
,&iid
);
706 ok(hres
== E_INVALIDARG
,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but got %x\n",hres
);
708 hres
= SafeArrayDestroyDescriptor(a
);
709 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
712 if (!pSafeArrayAllocDescriptorEx
)
715 for (i
=0;i
<sizeof(vttypes
)/sizeof(vttypes
[0]);i
++) {
717 hres
= pSafeArrayAllocDescriptorEx(vttypes
[i
].vt
,1,&a
);
718 ok(hres
== S_OK
, "SafeArrayAllocDescriptorEx gave hres 0x%x\n", hres
);
719 ok(a
->fFeatures
== vttypes
[i
].expflags
,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes
[i
].vt
, a
->fFeatures
, vttypes
[i
].expflags
);
720 if (a
->fFeatures
& FADF_HAVEIID
) {
721 hres
= pSafeArrayGetIID(a
, &iid
);
722 ok(hres
== S_OK
,"SAGIID failed for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
723 switch (vttypes
[i
].vt
) {
725 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IUnknown
),"guid for VT_UNKNOWN is not IID_IUnknown\n");
726 ok(IsEqualGUID(&iid
, &IID_IUnknown
),"SAGIID returned wrong GUID for IUnknown\n");
729 ok(IsEqualGUID(((GUID
*)a
)-1,&IID_IDispatch
),"guid for VT_UNKNOWN is not IID_IDispatch\n");
730 ok(IsEqualGUID(&iid
, &IID_IDispatch
),"SAGIID returned wrong GUID for IDispatch\n");
733 ok(FALSE
,"unknown vt %d with FADF_HAVEIID\n",vttypes
[i
].vt
);
737 hres
= pSafeArrayGetIID(a
, &iid
);
738 ok(hres
== E_INVALIDARG
,"SAGIID did not fail for vt %d with hres %x\n", vttypes
[i
].vt
,hres
);
740 if (a
->fFeatures
& FADF_RECORD
) {
741 ok(vttypes
[i
].vt
== VT_RECORD
,"FADF_RECORD for non record %d\n",vttypes
[i
].vt
);
743 if (a
->fFeatures
& FADF_HAVEVARTYPE
) {
744 ok(vttypes
[i
].vt
== ((DWORD
*)a
)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes
[i
].vt
,((DWORD
*)a
)[-1]);
747 hres
= pSafeArrayGetVartype(a
, &vt
);
748 ok(hres
== S_OK
, "SAGVT of array with vt %d failed with %x\n", vttypes
[i
].vt
, hres
);
750 if (vttypes
[i
].vt
== VT_DISPATCH
) {
751 /* Special case. Checked against Windows. */
752 ok(vt
== VT_UNKNOWN
, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt
);
754 ok(vt
== vttypes
[i
].vt
, "SAGVT of array with vt %d returned %d\n", vttypes
[i
].vt
, vt
);
757 if (a
->fFeatures
& FADF_HAVEIID
) {
758 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
759 ok(hres
== S_OK
,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
760 hres
= pSafeArrayGetIID(a
, &iid
);
761 ok(hres
== S_OK
,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
762 ok(IsEqualGUID(&iid
, &IID_IStorage
),"returned iid is not IID_IStorage\n");
764 hres
= pSafeArraySetIID(a
, &IID_IStorage
); /* random IID */
765 ok(hres
== E_INVALIDARG
,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes
[i
].vt
, hres
);
767 hres
= SafeArrayDestroyDescriptor(a
);
768 ok(hres
== S_OK
,"SADD failed with hres %x\n",hres
);
772 static void test_SafeArrayAllocDestroyDescriptor(void)
779 hres
= SafeArrayAllocDescriptor(0, &sa
);
780 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
782 hres
= SafeArrayAllocDescriptor(65536, &sa
);
783 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%x\n", hres
);
787 /* Crashes on 95: XP & Wine return E_POINTER */
788 hres
=SafeArrayAllocDescriptor(1, NULL
);
789 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
792 /* Test up to the dimension boundary case */
793 for (i
= 5; i
<= 65535; i
+= 30)
795 hres
= SafeArrayAllocDescriptor(i
, &sa
);
796 ok(hres
== S_OK
, "%d dimensions failed; hres 0x%x\n", i
, hres
);
800 ok(SafeArrayGetDim(sa
) == (UINT
)i
, "Dimension is %d; should be %d\n",
801 SafeArrayGetDim(sa
), i
);
803 hres
= SafeArrayDestroyDescriptor(sa
);
804 ok(hres
== S_OK
, "destroy failed; hres 0x%x\n", hres
);
808 if (!pSafeArrayAllocDescriptorEx
)
811 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 0, &sa
);
812 ok(hres
== E_INVALIDARG
, "0 dimensions gave hres 0x%x\n", hres
);
814 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 65536, &sa
);
815 ok(hres
== E_INVALIDARG
, "65536 dimensions gave hres 0x%x\n", hres
);
817 hres
= pSafeArrayAllocDescriptorEx(VT_UI1
, 1, NULL
);
818 ok(hres
== E_POINTER
,"NULL parm gave hres 0x%x\n", hres
);
820 hres
= pSafeArrayAllocDescriptorEx(-1, 1, &sa
);
821 ok(hres
== S_OK
, "VT = -1 gave hres 0x%x\n", hres
);
823 sa
->rgsabound
[0].cElements
= 0;
824 sa
->rgsabound
[0].lLbound
= 1;
826 hres
= SafeArrayAllocData(sa
);
827 ok(hres
== S_OK
, "SafeArrayAllocData gave hres 0x%x\n", hres
);
829 hres
= SafeArrayDestroy(sa
);
830 ok(hres
== S_OK
,"SafeArrayDestroy failed with hres %x\n",hres
);
833 static void test_SafeArrayCreateLockDestroy(void)
835 SAFEARRAYBOUND sab
[4];
841 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
843 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
845 sab
[dimension
].lLbound
= 0;
846 sab
[dimension
].cElements
= 8;
850 /* This test crashes very early versions with no error checking...
851 sa = SafeArrayCreate(VT_UI1, 1, NULL);
852 ok(sa == NULL, "NULL bounds didn't fail\n");
854 sa
= SafeArrayCreate(VT_UI1
, 65536, sab
);
855 ok(!sa
, "Max bounds didn't fail\n");
857 memset(sab
, 0, sizeof(sab
));
859 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
861 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
862 sab
[dimension
].cElements
= 8;
864 /* Test all VARTYPES in 1-4 dimensions */
865 for (dimension
= 1; dimension
< 4; dimension
++)
867 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
869 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
871 sa
= SafeArrayCreate(vt
, dimension
, sab
);
874 ok(sa
!= NULL
, "VARTYPE %d (@%d dimensions) failed\n", vt
, dimension
);
876 ok(sa
== NULL
|| vt
== VT_R8
,
877 "VARTYPE %d (@%d dimensions) succeeded!\n", vt
, dimension
);
881 ok(SafeArrayGetDim(sa
) == (UINT
)dimension
,
882 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
883 vt
, dimension
, SafeArrayGetDim(sa
), dimension
);
884 ok(SafeArrayGetElemsize(sa
) == dwLen
|| vt
== VT_R8
,
885 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
886 vt
, dimension
, SafeArrayGetElemsize(sa
), dwLen
);
888 if (vt
!= VT_UNKNOWN
&& vt
!= VT_DISPATCH
)
890 ok((sa
->fFeatures
& FADF_HAVEIID
) == 0,
891 "Non interface type should not have FADF_HAVEIID\n");
892 if (pSafeArraySetIID
)
894 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
895 ok(hres
== E_INVALIDARG
,
896 "Non interface type allowed SetIID(), hres %x\n", hres
);
902 ok(sa
->fFeatures
& FADF_HAVEVARTYPE
,
903 "Non interface type should have FADF_HAVEVARTYPE\n");
904 if (pSafeArrayGetVartype
)
906 hres
= pSafeArrayGetVartype(sa
, &aVt
);
907 ok(hres
== S_OK
&& aVt
== vt
,
908 "Non interface type %d: bad type %d, hres %x\n", vt
, aVt
, hres
);
914 ok(sa
->fFeatures
& FADF_HAVEIID
, "Interface type should have FADF_HAVEIID\n");
915 if (pSafeArraySetIID
)
917 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
919 "Non interface type disallowed SetIID(), hres %x\n", hres
);
921 ok((sa
->fFeatures
& FADF_HAVEVARTYPE
) == 0,
922 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt
);
925 hres
= SafeArrayLock(sa
);
926 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
927 vt
, dimension
, hres
);
931 hres
= SafeArrayDestroy(sa
);
932 ok(hres
== DISP_E_ARRAYISLOCKED
,"Destroy() got hres %x\n", hres
);
934 hres
= SafeArrayDestroyData(sa
);
935 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyData() got hres %x\n", hres
);
937 hres
= SafeArrayDestroyDescriptor(sa
);
938 ok(hres
== DISP_E_ARRAYISLOCKED
,"DestroyDescriptor() got hres %x\n", hres
);
940 hres
= SafeArrayUnlock(sa
);
941 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
942 vt
, dimension
, hres
);
944 hres
= SafeArrayDestroy(sa
);
945 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
946 vt
, dimension
, hres
);
953 static void test_VectorCreateLockDestroy(void)
960 if (!pSafeArrayCreateVector
)
962 win_skip("SafeArrayCreateVector not supported\n");
965 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 0);
966 ok(sa
!= NULL
, "SACV with 0 elements failed.\n");
968 hres
= SafeArrayDestroy(sa
);
969 ok(hres
== S_OK
, "SafeArrayDestroy failed with hres %x\n",hres
);
971 /* Test all VARTYPES in different lengths */
972 for (element
= 1; element
<= 101; element
+= 10)
974 for (vt
= VT_EMPTY
; vt
< VT_CLSID
; vt
++)
976 DWORD dwLen
= SAFEARRAY_GetVTSize(vt
);
978 sa
= pSafeArrayCreateVector(vt
, 0, element
);
981 ok(sa
!= NULL
, "VARTYPE %d (@%d elements) failed\n", vt
, element
);
983 ok(sa
== NULL
, "VARTYPE %d (@%d elements) succeeded!\n", vt
, element
);
987 ok(SafeArrayGetDim(sa
) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
988 vt
, element
, SafeArrayGetDim(sa
));
989 ok(SafeArrayGetElemsize(sa
) == dwLen
,
990 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
991 vt
, element
, SafeArrayGetElemsize(sa
), dwLen
);
993 hres
= SafeArrayLock(sa
);
994 ok(hres
== S_OK
, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
999 hres
= SafeArrayUnlock(sa
);
1000 ok(hres
== S_OK
, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
1003 hres
= SafeArrayDestroy(sa
);
1004 ok(hres
== S_OK
, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
1012 static void test_LockUnlock(void)
1014 SAFEARRAYBOUND sab
[4];
1017 BOOL bVector
= FALSE
;
1021 hres
= SafeArrayLock(NULL
);
1022 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
1023 hres
= SafeArrayUnlock(NULL
);
1024 ok(hres
== E_INVALIDARG
, "Lock NULL array hres 0x%x\n", hres
);
1026 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1028 sab
[dimension
].lLbound
= 0;
1029 sab
[dimension
].cElements
= 8;
1032 sa
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
1034 /* Test maximum locks */
1035 test_LockUnlock_Vector
:
1040 hres
= SafeArrayUnlock(sa
);
1041 ok (hres
== E_UNEXPECTED
, "Bad %sUnlock gave hres 0x%x\n",
1042 bVector
? "vector " : "\n", hres
);
1044 while ((hres
= SafeArrayLock(sa
)) == S_OK
)
1046 ok (count
== 65535 && hres
== E_UNEXPECTED
, "Lock %sfailed at %d; hres 0x%x\n",
1047 bVector
? "vector " : "\n", count
, hres
);
1049 if (count
== 65535 && hres
== E_UNEXPECTED
)
1051 while ((hres
= SafeArrayUnlock(sa
)) == S_OK
)
1053 ok (count
== 0 && hres
== E_UNEXPECTED
, "Unlock %sfailed at %d; hres 0x%x\n",
1054 bVector
? "vector " : "\n", count
, hres
);
1057 hres
= SafeArrayDestroy(sa
);
1058 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1061 if (bVector
== FALSE
&& pSafeArrayCreateVector
)
1063 /* Test again with a vector */
1064 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 100);
1066 goto test_LockUnlock_Vector
;
1070 static void test_SafeArrayGetPutElement(void)
1072 SAFEARRAYBOUND sab
[4];
1073 LONG indices
[NUM_DIMENSIONS
], index
;
1076 int value
= 0, gotvalue
, dimension
;
1077 IRecordInfoImpl
*irec
;
1078 unsigned int x
,y
,z
,a
;
1080 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1082 sab
[dimension
].lLbound
= dimension
* 2 + 1;
1083 sab
[dimension
].cElements
= dimension
* 3 + 1;
1086 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1088 return; /* Some early versions can't handle > 3 dims */
1090 ok(sa
->cbElements
== sizeof(value
), "int size mismatch\n");
1093 for (x
= 0; x
< NUM_DIMENSIONS
; x
++)
1095 indices
[0] = sab
[0].lLbound
;
1096 indices
[1] = sab
[1].lLbound
;
1097 indices
[2] = sab
[2].lLbound
;
1098 indices
[3] = sab
[3].lLbound
;
1100 indices
[x
] = indices
[x
] - 1;
1101 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1102 ok(hres
== DISP_E_BADINDEX
, "Put allowed too small index in dimension %d\n", x
);
1103 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1104 ok(hres
== DISP_E_BADINDEX
, "Get allowed too small index in dimension %d\n", x
);
1106 indices
[x
] = sab
[x
].lLbound
+ sab
[x
].cElements
;
1107 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1108 ok(hres
== DISP_E_BADINDEX
, "Put allowed too big index in dimension %d\n", x
);
1109 hres
= SafeArrayGetElement(sa
, indices
, &value
);
1110 ok(hres
== DISP_E_BADINDEX
, "Get allowed too big index in dimension %d\n", x
);
1113 indices
[0] = sab
[0].lLbound
;
1114 indices
[1] = sab
[1].lLbound
;
1115 indices
[2] = sab
[2].lLbound
;
1116 indices
[3] = sab
[3].lLbound
;
1118 hres
= SafeArrayPutElement(NULL
, indices
, &value
);
1119 ok(hres
== E_INVALIDARG
, "Put NULL array hres 0x%x\n", hres
);
1120 hres
= SafeArrayGetElement(NULL
, indices
, &value
);
1121 ok(hres
== E_INVALIDARG
, "Get NULL array hres 0x%x\n", hres
);
1123 hres
= SafeArrayPutElement(sa
, NULL
, &value
);
1124 ok(hres
== E_INVALIDARG
, "Put NULL indices hres 0x%x\n", hres
);
1125 hres
= SafeArrayGetElement(sa
, NULL
, &value
);
1126 ok(hres
== E_INVALIDARG
, "Get NULL indices hres 0x%x\n", hres
);
1130 /* This is retarded. Windows checks every case of invalid parameters
1131 * except the following, which crashes. We ERR this in Wine.
1133 hres
= SafeArrayPutElement(sa
, indices
, NULL
);
1134 ok(hres
== E_INVALIDARG
, "Put NULL value hres 0x%x\n", hres
);
1137 hres
= SafeArrayGetElement(sa
, indices
, NULL
);
1138 ok(hres
== E_INVALIDARG
, "Get NULL value hres 0x%x\n", hres
);
1142 /* Make sure we can read and get back the correct values in 4 dimensions,
1143 * Each with a different size and lower bound.
1145 for (x
= 0; x
< sab
[0].cElements
; x
++)
1147 indices
[0] = sab
[0].lLbound
+ x
;
1148 for (y
= 0; y
< sab
[1].cElements
; y
++)
1150 indices
[1] = sab
[1].lLbound
+ y
;
1151 for (z
= 0; z
< sab
[2].cElements
; z
++)
1153 indices
[2] = sab
[2].lLbound
+ z
;
1154 for (a
= 0; a
< sab
[3].cElements
; a
++)
1156 indices
[3] = sab
[3].lLbound
+ a
;
1157 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1158 ok(hres
== S_OK
, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1168 for (x
= 0; x
< sab
[0].cElements
; x
++)
1170 indices
[0] = sab
[0].lLbound
+ x
;
1171 for (y
= 0; y
< sab
[1].cElements
; y
++)
1173 indices
[1] = sab
[1].lLbound
+ y
;
1174 for (z
= 0; z
< sab
[2].cElements
; z
++)
1176 indices
[2] = sab
[2].lLbound
+ z
;
1177 for (a
= 0; a
< sab
[3].cElements
; a
++)
1179 indices
[3] = sab
[3].lLbound
+ a
;
1180 gotvalue
= value
/ 3;
1181 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1182 ok(hres
== S_OK
, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1185 ok(value
== gotvalue
, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1186 gotvalue
, value
, x
, y
, z
, a
);
1192 hres
= SafeArrayDestroy(sa
);
1193 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1195 /* VT_RECORD array */
1196 irec
= IRecordInfoImpl_Construct();
1200 sab
[0].cElements
= 8;
1202 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &irec
->IRecordInfo_iface
);
1203 ok(sa
!= NULL
, "failed to create array\n");
1204 ok(irec
->ref
== 2, "got %d\n", irec
->ref
);
1207 irec
->recordcopy
= 0;
1208 hres
= SafeArrayPutElement(sa
, &index
, (void*)0xdeadbeef);
1209 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1210 ok(irec
->recordcopy
== 1, "got %d\n", irec
->recordcopy
);
1213 irec
->recordcopy
= 0;
1214 hres
= SafeArrayGetElement(sa
, &index
, (void*)0xdeadbeef);
1215 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1216 ok(irec
->recordcopy
== 1, "got %d\n", irec
->recordcopy
);
1218 hres
= SafeArrayDestroy(sa
);
1219 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1220 ok(irec
->ref
== 1, "got %d\n", irec
->ref
);
1221 IRecordInfo_Release(&irec
->IRecordInfo_iface
);
1224 static void test_SafeArrayGetPutElement_BSTR(void)
1230 BSTR value
= 0, gotvalue
;
1231 const OLECHAR szTest
[5] = { 'T','e','s','t','\0' };
1236 sa
= SafeArrayCreate(VT_BSTR
, 1, &sab
);
1237 ok(sa
!= NULL
, "BSTR test couldn't create array\n");
1241 ok(sa
->cbElements
== sizeof(BSTR
), "BSTR size mismatch\n");
1243 indices
[0] = sab
.lLbound
;
1244 value
= SysAllocString(szTest
);
1245 ok (value
!= NULL
, "Expected non-NULL\n");
1246 hres
= SafeArrayPutElement(sa
, indices
, value
);
1247 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1249 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1250 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1252 ok(SysStringLen(value
) == SysStringLen(gotvalue
), "Got len %d instead of %d\n", SysStringLen(gotvalue
), SysStringLen(value
));
1253 hres
= SafeArrayDestroy(sa
);
1254 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1255 SysFreeString(value
);
1256 SysFreeString(gotvalue
);
1260 IUnknown IUnknown_iface
;
1263 static const IUnknownVtbl xtunk_vtbl
;
1265 static struct xtunk_impl xtunk
= {{&xtunk_vtbl
}, 0};
1267 static HRESULT WINAPI
tunk_QueryInterface(IUnknown
*punk
, REFIID riid
, void **x
)
1272 static ULONG WINAPI
tunk_AddRef(IUnknown
*punk
)
1277 static ULONG WINAPI
tunk_Release(IUnknown
*punk
)
1282 static const IUnknownVtbl xtunk_vtbl
= {
1283 tunk_QueryInterface
,
1288 static void test_SafeArrayGetPutElement_IUnknown(void)
1298 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1299 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1303 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1305 indices
[0] = sab
.lLbound
;
1307 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1308 ok(hres
== S_OK
, "Failed to put bstr element hres 0x%x\n", hres
);
1309 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1311 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1312 ok(xtunk
.ref
== 3,"Failed to increment refcount of iface.\n");
1313 ok(hres
== S_OK
, "Failed to get bstr element at hres 0x%x\n", hres
);
1315 ok(gotvalue
== &xtunk
.IUnknown_iface
, "Got %p instead of %p\n", gotvalue
, &xtunk
.IUnknown_iface
);
1316 hres
= SafeArrayDestroy(sa
);
1317 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1318 ok(xtunk
.ref
== 2,"Failed to decrement refcount of iface.\n");
1321 static void test_SafeArrayRedim_IUnknown(void)
1330 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
1331 ok(sa
!= NULL
, "UNKNOWN test couldn't create array\n");
1335 ok(sa
->cbElements
== sizeof(LPUNKNOWN
), "LPUNKNOWN size mismatch\n");
1339 hres
= SafeArrayPutElement(sa
, indices
, &xtunk
.IUnknown_iface
);
1340 ok(hres
== S_OK
, "Failed to put IUnknown element hres 0x%x\n", hres
);
1341 ok(xtunk
.ref
== 2,"Failed to increment refcount of iface.\n");
1343 hres
= SafeArrayRedim(sa
, &sab
);
1344 ok(hres
== S_OK
, "Failed to shrink array hres 0x%x\n", hres
);
1345 ok(xtunk
.ref
== 1, "Failed to decrement refcount\n");
1346 hres
= SafeArrayDestroy(sa
);
1347 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1350 static void test_SafeArrayGetPutElement_VARIANT(void)
1356 VARIANT value
, gotvalue
;
1360 sa
= SafeArrayCreate(VT_VARIANT
, 1, &sab
);
1361 ok(sa
!= NULL
, "VARIANT test couldn't create array\n");
1365 ok(sa
->cbElements
== sizeof(VARIANT
), "VARIANT size mismatch\n");
1367 indices
[0] = sab
.lLbound
;
1368 V_VT(&value
) = VT_I4
;
1369 V_I4(&value
) = 0x42424242;
1370 hres
= SafeArrayPutElement(sa
, indices
, &value
);
1371 ok(hres
== S_OK
, "Failed to put Variant I4 element hres 0x%x\n", hres
);
1373 V_VT(&gotvalue
) = 0xdead;
1374 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1375 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1377 V_VT(&gotvalue
) = VT_EMPTY
;
1378 hres
= SafeArrayGetElement(sa
, indices
, &gotvalue
);
1379 ok(hres
== S_OK
, "Failed to get variant element at hres 0x%x\n", hres
);
1381 ok(V_VT(&value
) == V_VT(&gotvalue
), "Got type 0x%x instead of 0x%x\n", V_VT(&value
), V_VT(&gotvalue
));
1382 if (V_VT(&value
) == V_VT(&gotvalue
))
1383 ok(V_I4(&value
) == V_I4(&gotvalue
), "Got %d instead of %d\n", V_I4(&value
), V_VT(&gotvalue
));
1385 hres
= SafeArrayDestroy(sa
);
1386 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1389 static void test_SafeArrayCopyData(void)
1391 SAFEARRAYBOUND sab
[4];
1395 int dimension
, size
= 1, i
;
1397 if (!pSafeArrayCopyData
)
1399 win_skip("SafeArrayCopyData not supported\n");
1403 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1405 sab
[dimension
].lLbound
= dimension
* 2 + 2;
1406 sab
[dimension
].cElements
= dimension
* 3 + 1;
1407 size
*= sab
[dimension
].cElements
;
1410 sa
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1411 ok(sa
!= NULL
, "Copy test couldn't create array\n");
1412 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1413 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1418 ok(sa
->cbElements
== sizeof(int), "int size mismatch\n");
1420 /* Fill the source array with some data; it doesn't matter what */
1421 for (dimension
= 0; dimension
< size
; dimension
++)
1423 int* data
= sa
->pvData
;
1424 data
[dimension
] = dimension
;
1427 hres
= pSafeArrayCopyData(sa
, sacopy
);
1428 ok(hres
== S_OK
, "copy data failed hres 0x%x\n", hres
);
1431 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1435 hres
= pSafeArrayCopyData(NULL
, sacopy
);
1436 ok(hres
== E_INVALIDARG
, "Null copy source hres 0x%x\n", hres
);
1437 hres
= pSafeArrayCopyData(sa
, NULL
);
1438 ok(hres
== E_INVALIDARG
, "Null copy hres 0x%x\n", hres
);
1440 sacopy
->rgsabound
[0].cElements
+= 1;
1441 hres
= pSafeArrayCopyData(sa
, sacopy
);
1442 ok(hres
== E_INVALIDARG
, "Bigger copy first dimension hres 0x%x\n", hres
);
1444 sacopy
->rgsabound
[0].cElements
-= 2;
1445 hres
= pSafeArrayCopyData(sa
, sacopy
);
1446 ok(hres
== E_INVALIDARG
, "Smaller copy first dimension hres 0x%x\n", hres
);
1447 sacopy
->rgsabound
[0].cElements
+= 1;
1449 sacopy
->rgsabound
[3].cElements
+= 1;
1450 hres
= pSafeArrayCopyData(sa
, sacopy
);
1451 ok(hres
== E_INVALIDARG
, "Bigger copy last dimension hres 0x%x\n", hres
);
1453 sacopy
->rgsabound
[3].cElements
-= 2;
1454 hres
= pSafeArrayCopyData(sa
, sacopy
);
1455 ok(hres
== E_INVALIDARG
, "Smaller copy last dimension hres 0x%x\n", hres
);
1456 sacopy
->rgsabound
[3].cElements
+= 1;
1458 hres
= SafeArrayDestroy(sacopy
);
1459 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1461 hres
= pSafeArrayCopyData(sa
, sacopy
);
1462 ok(hres
== E_INVALIDARG
, "->Null copy hres 0x%x\n", hres
);
1464 hres
= SafeArrayCopy(sa
, &sacopy
);
1465 ok(hres
== S_OK
, "copy failed hres 0x%x\n", hres
);
1466 ok(SafeArrayGetElemsize(sa
) == SafeArrayGetElemsize(sacopy
),"elemsize wrong\n");
1467 ok(SafeArrayGetDim(sa
) == SafeArrayGetDim(sacopy
),"dimensions wrong\n");
1468 ok(!memcmp(sa
->pvData
, sacopy
->pvData
, size
* sizeof(int)), "compared different\n");
1469 hres
= SafeArrayDestroy(sacopy
);
1470 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1472 sacopy
= SafeArrayCreate(VT_INT
, NUM_DIMENSIONS
, sab
);
1473 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1474 ok(sacopy
->fFeatures
== FADF_HAVEVARTYPE
, "0x%04x\n", sacopy
->fFeatures
);
1476 for (i
= 0; i
< sizeof(ignored_copy_features
)/sizeof(USHORT
); i
++)
1478 USHORT feature
= ignored_copy_features
[i
];
1479 USHORT orig
= sacopy
->fFeatures
;
1481 sa
->fFeatures
|= feature
;
1482 hres
= SafeArrayCopyData(sa
, sacopy
);
1483 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1484 ok(sacopy
->fFeatures
== orig
&& orig
== FADF_HAVEVARTYPE
, "got features 0x%04x\n", sacopy
->fFeatures
);
1485 sa
->fFeatures
&= ~feature
;
1488 hres
= SafeArrayDestroy(sacopy
);
1489 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1490 hres
= SafeArrayDestroy(sa
);
1491 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1493 /* copy data from a vector */
1494 sa
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1496 sacopy
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1497 ok(sa
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1498 broken(sa
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1499 "got 0x%08x\n", sa
->fFeatures
);
1500 ok(sacopy
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1501 broken(sacopy
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1502 "got 0x%08x\n", sacopy
->fFeatures
);
1503 hres
= SafeArrayCopyData(sa
, sacopy
);
1504 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1505 ok(sacopy
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1506 broken(sacopy
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1507 "got 0x%04x\n", sacopy
->fFeatures
);
1508 SafeArrayDestroy(sacopy
);
1510 sacopy
= SafeArrayCreate(VT_UI1
, NUM_DIMENSIONS
, sab
);
1511 ok(sacopy
!= NULL
, "Copy test couldn't create copy array\n");
1512 ok(sacopy
->fFeatures
== FADF_HAVEVARTYPE
, "0x%04x\n", sacopy
->fFeatures
);
1513 hres
= SafeArrayCopyData(sa
, sacopy
);
1514 ok(hres
== E_INVALIDARG
, "got 0x%08x\n", hres
);
1515 SafeArrayDestroy(sacopy
);
1517 SafeArrayDestroy(sa
);
1520 static void test_SafeArrayCreateEx(void)
1522 IRecordInfoImpl
* iRec
;
1523 SAFEARRAYBOUND sab
[4];
1528 if (!pSafeArrayCreateEx
)
1530 win_skip("SafeArrayCreateEx not supported\n");
1534 for (dimension
= 0; dimension
< NUM_DIMENSIONS
; dimension
++)
1536 sab
[dimension
].lLbound
= 0;
1537 sab
[dimension
].cElements
= 8;
1541 sa
= pSafeArrayCreateEx(VT_UI1
, 1, NULL
, NULL
);
1542 ok(sa
== NULL
, "CreateEx NULL bounds didn't fail\n");
1544 /* test IID storage & defaulting */
1545 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, (PVOID
)&IID_ITypeInfo
);
1546 ok(sa
!= NULL
, "CreateEx (ITypeInfo) failed\n");
1551 if (pSafeArrayGetIID
)
1553 hres
= pSafeArrayGetIID(sa
, &guid
);
1554 ok(hres
== S_OK
, "CreateEx (ITypeInfo) no IID hres 0x%x\n", hres
);
1557 ok(IsEqualGUID(&guid
, &IID_ITypeInfo
), "CreateEx (ITypeInfo) bad IID\n");
1560 if (pSafeArraySetIID
)
1562 hres
= pSafeArraySetIID(sa
, &IID_IUnknown
);
1563 ok(hres
== S_OK
, "Failed to set IID, hres = %8x\n", hres
);
1564 if (hres
== S_OK
&& pSafeArrayGetIID
)
1566 hres
= pSafeArrayGetIID(sa
, &guid
);
1567 ok(hres
== S_OK
&& IsEqualGUID(&guid
, &IID_IUnknown
), "Set bad IID\n");
1570 hres
= SafeArrayDestroy(sa
);
1571 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1574 sa
= pSafeArrayCreateEx(VT_DISPATCH
, 1, sab
, NULL
);
1575 ok(sa
!= NULL
, "CreateEx (NULL) failed\n");
1580 if (pSafeArrayGetIID
)
1582 hres
= pSafeArrayGetIID(sa
, &guid
);
1583 ok(hres
== S_OK
, "CreateEx (NULL) no IID hres 0x%x\n", hres
);
1586 ok(IsEqualGUID(&guid
, &IID_IDispatch
), "CreateEx (NULL) bad IID\n");
1589 hres
= SafeArrayDestroy(sa
);
1590 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1593 sa
= pSafeArrayCreateEx(VT_UNKNOWN
, 1, sab
, NULL
);
1594 ok(sa
!= NULL
, "CreateEx (NULL-Unk) failed\n");
1599 if (pSafeArrayGetIID
)
1601 hres
= pSafeArrayGetIID(sa
, &guid
);
1602 ok(hres
== S_OK
, "CreateEx (NULL-Unk) no IID hres 0x%x\n", hres
);
1605 ok(IsEqualGUID(&guid
, &IID_IUnknown
), "CreateEx (NULL-Unk) bad IID\n");
1608 hres
= SafeArrayDestroy(sa
);
1609 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1612 /* VT_RECORD failure case */
1613 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, NULL
);
1614 ok(sa
== NULL
, "CreateEx (NULL-Rec) succeeded\n");
1616 iRec
= IRecordInfoImpl_Construct();
1618 /* Win32 doesn't care if GetSize fails */
1619 fail_GetSize
= TRUE
;
1620 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1621 ok(sa
!= NULL
, "CreateEx (Fail Size) failed\n");
1622 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1623 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1624 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1627 ok(sa
->cbElements
== RECORD_SIZE_FAIL
, "Altered size to %d\n", sa
->cbElements
);
1628 hres
= SafeArrayDestroy(sa
);
1629 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1630 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1631 ok(iRec
->ref
== START_REF_COUNT
, "got %d, expected %d\n", iRec
->ref
, START_REF_COUNT
);
1634 /* Test VT_RECORD array */
1635 fail_GetSize
= FALSE
;
1636 iRec
->ref
= START_REF_COUNT
;
1637 iRec
->sizeCalled
= 0;
1638 iRec
->clearCalled
= 0;
1639 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1640 ok(sa
!= NULL
, "CreateEx (Rec) failed\n");
1641 ok(iRec
->ref
== START_REF_COUNT
+ 1, "Wrong iRec refcount %d\n", iRec
->ref
);
1642 ok(iRec
->sizeCalled
== 1, "GetSize called %d times\n", iRec
->sizeCalled
);
1643 ok(iRec
->clearCalled
== 0, "Clear called %d times\n", iRec
->clearCalled
);
1644 if (sa
&& pSafeArrayGetRecordInfo
)
1646 IRecordInfo
* saRec
= NULL
;
1649 hres
= pSafeArrayGetRecordInfo(sa
, &saRec
);
1650 ok(hres
== S_OK
,"GRI failed\n");
1651 ok(saRec
== &iRec
->IRecordInfo_iface
, "Different saRec\n");
1652 ok(iRec
->ref
== START_REF_COUNT
+ 2, "Didn't AddRef %d\n", iRec
->ref
);
1653 IRecordInfo_Release(saRec
);
1655 ok(sa
->cbElements
== RECORD_SIZE
,"Elemsize is %d\n", sa
->cbElements
);
1657 /* try to copy record based arrays */
1658 sacopy
= pSafeArrayCreateEx(VT_RECORD
, 1, sab
, &iRec
->IRecordInfo_iface
);
1659 iRec
->recordcopy
= 0;
1660 iRec
->clearCalled
= 0;
1661 /* array copy code doesn't explicitly clear a record */
1662 hres
= SafeArrayCopyData(sa
, sacopy
);
1663 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1664 ok(iRec
->recordcopy
== sab
[0].cElements
, "got %d\n", iRec
->recordcopy
);
1665 ok(iRec
->clearCalled
== 0, "got %d\n", iRec
->clearCalled
);
1667 hres
= SafeArrayDestroy(sacopy
);
1668 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1670 iRec
->clearCalled
= 0;
1671 iRec
->sizeCalled
= 0;
1672 hres
= SafeArrayDestroy(sa
);
1673 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1674 ok(iRec
->sizeCalled
== 0, "Destroy->GetSize called %d times\n", iRec
->sizeCalled
);
1675 ok(iRec
->clearCalled
== sab
[0].cElements
, "Destroy->Clear called %d times\n", iRec
->clearCalled
);
1676 ok(iRec
->ref
== START_REF_COUNT
, "Wrong iRec refcount %d\n", iRec
->ref
);
1680 hres
= SafeArrayDestroy(sa
);
1681 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1684 IRecordInfo_Release(&iRec
->IRecordInfo_iface
);
1687 static void test_SafeArrayClear(void)
1696 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1697 ok(sa
!= NULL
, "Create() failed.\n");
1701 /* Test clearing non-NULL variants containing arrays */
1702 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1704 hres
= VariantClear(&v
);
1705 ok(hres
== S_OK
&& V_VT(&v
) == VT_EMPTY
, "VariantClear: hres 0x%x, Type %d\n", hres
, V_VT(&v
));
1706 ok(V_ARRAY(&v
) == sa
, "VariantClear: Overwrote value\n");
1708 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1709 ok(sa
!= NULL
, "Create() failed.\n");
1713 V_VT(&v
) = VT_SAFEARRAY
;
1715 hres
= VariantClear(&v
);
1716 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1718 V_VT(&v
) = VT_SAFEARRAY
|VT_BYREF
;
1719 V_ARRAYREF(&v
) = &sa
;
1720 hres
= VariantClear(&v
);
1721 ok(hres
== DISP_E_BADVARTYPE
, "VariantClear: hres 0x%x\n", hres
);
1723 hres
= SafeArrayDestroy(sa
);
1724 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1727 static void test_SafeArrayCopy(void)
1730 SAFEARRAY
*sa
, *sa2
;
1731 VARIANTARG vSrc
, vDst
;
1737 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
1738 ok(sa
!= NULL
, "Create() failed.\n");
1742 /* Test copying non-NULL variants containing arrays */
1743 V_VT(&vSrc
) = (VT_ARRAY
|VT_BYREF
|VT_UI1
);
1744 V_ARRAYREF(&vSrc
) = &sa
;
1745 V_VT(&vDst
) = VT_EMPTY
;
1747 hres
= VariantCopy(&vDst
, &vSrc
);
1748 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_BYREF
|VT_UI1
),
1749 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1750 ok(V_ARRAYREF(&vDst
) == &sa
, "VariantClear: Performed deep copy\n");
1752 V_VT(&vSrc
) = (VT_ARRAY
|VT_UI1
);
1753 V_ARRAY(&vSrc
) = sa
;
1754 V_VT(&vDst
) = VT_EMPTY
;
1756 hres
= VariantCopy(&vDst
, &vSrc
);
1757 ok(hres
== S_OK
&& V_VT(&vDst
) == (VT_ARRAY
|VT_UI1
),
1758 "VariantCopy: hres 0x%x, Type %d\n", hres
, V_VT(&vDst
));
1759 ok(V_ARRAY(&vDst
) != sa
, "VariantClear: Performed shallow copy\n");
1761 hres
= SafeArrayDestroy(V_ARRAY(&vSrc
));
1762 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1763 hres
= SafeArrayDestroy(V_ARRAY(&vDst
));
1764 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1766 hres
= SafeArrayAllocDescriptor(1, &sa
);
1767 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1769 sa
->cbElements
= 16;
1770 hres
= SafeArrayCopy(sa
, &sa2
);
1771 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1772 ok(sa
!= sa2
, "SafeArrayCopy performed shallow copy\n");
1774 hres
= SafeArrayDestroy(sa2
);
1775 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1776 hres
= SafeArrayDestroy(sa
);
1777 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1779 sa2
= (void*)0xdeadbeef;
1780 hres
= SafeArrayCopy(NULL
, &sa2
);
1781 ok(hres
== S_OK
, "SafeArrayCopy failed with error 0x%08x\n", hres
);
1782 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1784 hres
= SafeArrayAllocDescriptor(1, &sa
);
1785 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1787 sa2
= (void*)0xdeadbeef;
1788 hres
= SafeArrayCopy(sa
, &sa2
);
1789 ok(hres
== E_INVALIDARG
,
1790 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1792 ok(!sa2
, "SafeArrayCopy didn't return NULL for output array\n");
1794 hres
= SafeArrayDestroy(sa2
);
1795 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1796 hres
= SafeArrayDestroy(sa
);
1797 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1799 /* test feature copy */
1800 hres
= SafeArrayAllocDescriptor(1, &sa
);
1801 ok(hres
== S_OK
, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres
);
1802 ok(sa
->fFeatures
== 0, "got src features 0x%04x\n", sa
->fFeatures
);
1803 sa
->cbElements
= 16;
1805 for (i
= 0; i
< sizeof(ignored_copy_features
)/sizeof(USHORT
); i
++)
1807 USHORT feature
= ignored_copy_features
[i
];
1809 sa
->fFeatures
|= feature
;
1810 hres
= SafeArrayCopy(sa
, &sa2
);
1811 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1812 ok(sa2
->fFeatures
== 0, "got features 0x%04x\n", sa2
->fFeatures
);
1813 hres
= SafeArrayDestroy(sa2
);
1814 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1815 sa
->fFeatures
&= ~feature
;
1818 SafeArrayDestroy(sa
);
1820 /* copy from a vector */
1821 sa
= SafeArrayCreateVector(VT_UI1
, 0, 2);
1822 ok(sa
->fFeatures
== (FADF_HAVEVARTYPE
|FADF_CREATEVECTOR
) ||
1823 broken(sa
->fFeatures
== FADF_CREATEVECTOR
/* W2k */),
1824 "got 0x%08x\n", sa
->fFeatures
);
1825 hres
= SafeArrayCopy(sa
, &sa2
);
1826 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1827 ok(sa2
->fFeatures
== FADF_HAVEVARTYPE
||
1828 broken(!sa2
->fFeatures
/* W2k */), "got 0x%04x\n",
1831 SafeArrayDestroy(sa2
);
1832 SafeArrayDestroy(sa
);
1835 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1836 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1838 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1840 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1841 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1842 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1844 static void test_SafeArrayChangeTypeEx(void)
1846 static const char *szHello
= "Hello World";
1853 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1854 MKARRAY(0,strlen(szHello
)+1,VT_UI1
);
1855 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1857 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1858 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1861 ok(V_VT(&v2
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2
));
1862 ok(strcmp((char*)V_BSTR(&v2
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1863 (char*)V_BSTR(&v2
));
1867 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1868 hres
= SafeArrayDestroy(sa
);
1869 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1870 if (pSafeArrayCreateVector
)
1872 sa
= pSafeArrayCreateVector(VT_UI1
, 0, strlen(szHello
)+1);
1873 ok(sa
!= NULL
, "CreateVector() failed.\n");
1877 memcpy(sa
->pvData
, szHello
, strlen(szHello
)+1);
1878 V_VT(&v
) = VT_VECTOR
|VT_UI1
;
1882 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1883 ok(hres
== DISP_E_BADVARTYPE
, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres
);
1885 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1886 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1887 hres
= VariantChangeTypeEx(&v
, &v
, 0, 0, VT_BSTR
);
1888 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres
);
1891 ok(V_VT(&v
) == VT_BSTR
, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v
));
1892 ok(strcmp((char*)V_BSTR(&v
),szHello
) == 0,"Expected string '%s', got '%s'\n", szHello
,
1898 /* To/from BSTR only works with arrays of VT_UI1 */
1899 for (vt
= VT_EMPTY
; vt
<= VT_CLSID
; vt
++)
1906 sa
= SafeArrayCreate(vt
, 1, &sab
);
1909 V_VT(&v
) = VT_ARRAY
|vt
;
1913 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_BSTR
);
1914 if (vt
== VT_INT_PTR
|| vt
== VT_UINT_PTR
)
1916 ok(hres
== DISP_E_BADVARTYPE
, "expected DISP_E_BADVARTYPE, got 0x%08x\n", hres
);
1917 SafeArrayDestroy(sa
);
1921 ok(hres
== DISP_E_TYPEMISMATCH
, "got 0x%08x for vt=%d, instead of DISP_E_TYPEMISMATCH\n", hres
, vt
);
1922 hres
= VariantClear(&v
);
1923 ok(hres
== S_OK
, "expected S_OK, got 0x%08x\n", hres
);
1928 /* Can't change an array of one type into array of another type , even
1929 * if the other type is the same size
1931 if (pSafeArrayCreateVector
)
1933 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1934 ok(sa
!= NULL
, "CreateVector() failed.\n");
1938 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1940 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_I1
);
1941 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres
);
1943 /* But can change to the same array type */
1944 hres
= SafeArrayDestroy(sa
);
1945 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1946 sa
= pSafeArrayCreateVector(VT_UI1
, 0, 1);
1947 ok(sa
!= NULL
, "CreateVector() failed.\n");
1950 V_VT(&v
) = VT_ARRAY
|VT_UI1
;
1952 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_ARRAY
|VT_UI1
);
1953 ok(hres
== S_OK
, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres
);
1954 hres
= SafeArrayDestroy(sa
);
1955 ok(hres
== S_OK
, "got 0x%08x\n", hres
);
1960 MKARRAY(0,1,VT_UI1
);
1961 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_NULL
);
1962 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1964 MKARRAY(0,1,VT_UI1
);
1965 hres
= VariantChangeTypeEx(&v2
, &v
, 0, 0, VT_EMPTY
);
1966 ok(hres
== DISP_E_TYPEMISMATCH
, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres
);
1970 static void test_SafeArrayDestroyData (void)
1975 int value
= 0xdeadbeef;
1981 sa
= SafeArrayCreate(VT_INT
, 1, &sab
);
1982 ok(sa
!= NULL
, "Create() failed.\n");
1986 SafeArrayPutElement (sa
, index
, &value
);
1988 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1989 sa
->fFeatures
|= FADF_STATIC
;
1990 temp_pvData
= sa
->pvData
;
1991 hres
= SafeArrayDestroyData(sa
);
1992 ok(hres
== S_OK
, "SADData FADF_STATIC failed, error code %x.\n",hres
);
1993 ok(sa
->pvData
== temp_pvData
, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1994 sa
->pvData
, temp_pvData
, sa
->fFeatures
);
1995 SafeArrayGetElement (sa
, index
, &value
);
1996 ok(value
== 0, "Data not cleared after SADData\n");
1998 /* Clear FADF_STATIC, now really destroy the data. */
1999 sa
->fFeatures
^= FADF_STATIC
;
2000 hres
= SafeArrayDestroyData(sa
);
2001 ok(hres
== S_OK
, "SADData !FADF_STATIC failed, error code %x.\n",hres
);
2002 ok(sa
->pvData
== NULL
, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa
->pvData
);
2004 hres
= SafeArrayDestroy(sa
);
2005 ok(hres
== S_OK
, "SAD failed, error code %x.\n", hres
);
2008 static void test_safearray_layout(void)
2010 IRecordInfoImpl
*irec
;
2011 IRecordInfo
*record
;
2012 GUID guid
, *guidptr
;
2022 sa
= SafeArrayCreate(VT_UNKNOWN
, 1, &sab
);
2023 ok(sa
!= NULL
, "got %p\n", sa
);
2025 guidptr
= (GUID
*)sa
- 1;
2026 ok(IsEqualIID(guidptr
, &IID_IUnknown
), "got %s\n", wine_dbgstr_guid(guidptr
));
2028 hr
= SafeArraySetIID(sa
, &IID_IDispatch
);
2029 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2030 ok(IsEqualIID(guidptr
, &IID_IDispatch
), "got %s\n", wine_dbgstr_guid(guidptr
));
2032 memcpy(guidptr
, &IID_IUnknown
, sizeof(GUID
));
2033 hr
= SafeArrayGetIID(sa
, &guid
);
2034 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2035 ok(IsEqualIID(&guid
, &IID_IUnknown
), "got %s\n", wine_dbgstr_guid(&guid
));
2037 hr
= SafeArrayDestroy(sa
);
2038 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2041 sa
= SafeArrayCreate(VT_UI1
, 1, &sab
);
2042 ok(sa
!= NULL
, "got %p\n", sa
);
2044 dwptr
= (DWORD
*)sa
- 1;
2045 ok(*dwptr
== VT_UI1
, "got %d\n", *dwptr
);
2047 hr
= SafeArrayDestroy(sa
);
2048 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2050 /* IRecordInfo pointer */
2051 irec
= IRecordInfoImpl_Construct();
2054 sa
= pSafeArrayCreateEx(VT_RECORD
, 1, &sab
, &irec
->IRecordInfo_iface
);
2055 ok(sa
!= NULL
, "failed to create array\n");
2057 record
= *((IRecordInfo
**)sa
- 1);
2058 ok(record
== &irec
->IRecordInfo_iface
, "got %p\n", record
);
2060 hr
= SafeArrayDestroy(sa
);
2061 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2062 IRecordInfo_Release(&irec
->IRecordInfo_iface
);
2065 START_TEST(safearray
)
2067 hOleaut32
= GetModuleHandleA("oleaut32.dll");
2069 has_i8
= GetProcAddress(hOleaut32
, "VarI8FromI1") != NULL
;
2071 GETPTR(SafeArrayAllocDescriptorEx
);
2072 GETPTR(SafeArrayCopyData
);
2073 GETPTR(SafeArrayGetIID
);
2074 GETPTR(SafeArraySetIID
);
2075 GETPTR(SafeArrayGetVartype
);
2076 GETPTR(SafeArrayCreateEx
);
2077 GETPTR(SafeArrayCreateVector
);
2078 GETPTR(SafeArrayGetRecordInfo
);
2080 check_for_VT_INT_PTR();
2082 test_SafeArrayAllocDestroyDescriptor();
2083 test_SafeArrayCreateLockDestroy();
2084 test_VectorCreateLockDestroy();
2086 test_SafeArrayChangeTypeEx();
2087 test_SafeArrayCopy();
2088 test_SafeArrayClear();
2089 test_SafeArrayCreateEx();
2090 test_SafeArrayCopyData();
2091 test_SafeArrayDestroyData();
2092 test_SafeArrayGetPutElement();
2093 test_SafeArrayGetPutElement_BSTR();
2094 test_SafeArrayGetPutElement_IUnknown();
2095 test_SafeArrayRedim_IUnknown();
2096 test_SafeArrayGetPutElement_VARIANT();
2097 test_safearray_layout();