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
28 #include "wine/test.h"
41 static HMODULE hOleaut32;
43 static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
44 static HRESULT (WINAPI *pSafeArrayCopyData)(SAFEARRAY*,SAFEARRAY*);
45 static HRESULT (WINAPI *pSafeArrayGetIID)(SAFEARRAY*,GUID*);
46 static HRESULT (WINAPI *pSafeArraySetIID)(SAFEARRAY*,REFGUID);
47 static HRESULT (WINAPI *pSafeArrayGetVartype)(SAFEARRAY*,VARTYPE*);
48 static HRESULT (WINAPI *pSafeArrayGetRecordInfo)(SAFEARRAY*,IRecordInfo**);
49 static SAFEARRAY* (WINAPI *pSafeArrayCreateEx)(VARTYPE,UINT,SAFEARRAYBOUND*,LPVOID);
50 static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
52 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
54 /* Is a given function exported from oleaut32? */
55 #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
57 /* Have IRecordInfo data type? */
58 #define HAVE_OLEAUT32_RECORD HAVE_FUNC(SafeArraySetRecordInfo)
59 /* Have R8 data type? */
60 #define HAVE_OLEAUT32_R8 HAVE_FUNC(VarR8FromI1)
61 /* Have I8/UI8 data type? */
62 #define HAVE_OLEAUT32_I8 HAVE_FUNC(VarI8FromI1)
63 /* Have the decimal type? */
64 #define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
65 /* Have INT_PTR/UINT_PTR type? */
66 static BOOL HAVE_OLEAUT32_INT_PTR;
68 /* very old version? */
69 #define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
71 #define START_REF_COUNT 1
72 #define RECORD_SIZE 64
73 #define RECORD_SIZE_FAIL 17
74 /************************************************************************
75 * Dummy IRecordInfo Implementation
77 typedef struct IRecordInfoImpl
79 const IRecordInfoVtbl *lpvtbl;
85 static const IRecordInfoVtbl IRecordInfoImpl_VTable;
87 static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
91 rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
92 rec->lpvtbl = &IRecordInfoImpl_VTable;
93 rec->ref = START_REF_COUNT;
99 static ULONG CALLBACK IRecordInfoImpl_AddRef(IRecordInfo *iface)
101 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
102 return InterlockedIncrement(&This->ref);
105 static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
107 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
108 return InterlockedDecrement(&This->ref);
111 static BOOL fail_GetSize; /* Whether to fail the GetSize call */
113 static HRESULT CALLBACK IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
115 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
120 static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
122 IRecordInfoImpl* This=(IRecordInfoImpl*)iface;
131 static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface)
133 trace("Called an unexpected IRecordInfo method - please report!\n");
134 /* Quit because we'll just crash anyway */
139 static const IRecordInfoVtbl IRecordInfoImpl_VTable =
141 (PVOID)IRecordInfoImpl_Dummy,
142 IRecordInfoImpl_AddRef,
143 IRecordInfoImpl_Release,
144 (PVOID)IRecordInfoImpl_Dummy,
145 IRecordInfoImpl_RecordClear,
146 (PVOID)IRecordInfoImpl_Dummy,
147 (PVOID)IRecordInfoImpl_Dummy,
148 (PVOID)IRecordInfoImpl_Dummy,
149 (PVOID)IRecordInfoImpl_GetSize,
150 (PVOID)IRecordInfoImpl_Dummy,
151 (PVOID)IRecordInfoImpl_Dummy,
152 (PVOID)IRecordInfoImpl_Dummy,
153 (PVOID)IRecordInfoImpl_Dummy,
154 (PVOID)IRecordInfoImpl_Dummy,
155 (PVOID)IRecordInfoImpl_Dummy,
156 (PVOID)IRecordInfoImpl_Dummy,
157 (PVOID)IRecordInfoImpl_Dummy,
158 (PVOID)IRecordInfoImpl_Dummy,
159 (PVOID)IRecordInfoImpl_Dummy
162 static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
167 case VT_UI1: return sizeof(BYTE);
170 case VT_UI2: return sizeof(SHORT);
174 case VT_ERROR: return sizeof(LONG);
176 if (HAVE_OLEAUT32_R8)
177 return sizeof(LONG64);
180 if (HAVE_OLEAUT32_I8)
181 return sizeof(LONG64);
184 case VT_UINT: return sizeof(INT);
187 if (HAVE_OLEAUT32_INT_PTR)
188 return sizeof(UINT_PTR);
190 case VT_CY: return sizeof(CY);
191 case VT_DATE: return sizeof(DATE);
192 case VT_BSTR: return sizeof(BSTR);
193 case VT_DISPATCH: return sizeof(LPDISPATCH);
194 case VT_VARIANT: return sizeof(VARIANT);
195 case VT_UNKNOWN: return sizeof(LPUNKNOWN);
197 if (HAVE_OLEAUT32_DECIMAL)
198 return sizeof(DECIMAL);
204 static void check_for_VT_INT_PTR(void)
206 /* Set a global flag if VT_INT_PTR is supported */
209 SAFEARRAYBOUND bound;
212 a = SafeArrayCreate(VT_INT_PTR, 1, &bound);
214 trace("VT_INT_PTR is supported\n");
215 HAVE_OLEAUT32_INT_PTR = TRUE;
219 trace("VT_INT_PTR is not supported\n");
220 HAVE_OLEAUT32_INT_PTR = FALSE;
224 #define VARTYPE_NOT_SUPPORTED 0
227 UINT elemsize; /* elementsize by VT */
228 UINT expflags; /* fFeatures from SafeArrayAllocDescriptorEx */
229 UINT addflags; /* additional fFeatures from SafeArrayCreate */
231 {VT_EMPTY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
232 {VT_NULL, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
233 {VT_I2, 2, FADF_HAVEVARTYPE,0},
234 {VT_I4, 4, FADF_HAVEVARTYPE,0},
235 {VT_R4, 4, FADF_HAVEVARTYPE,0},
236 {VT_R8, 8, FADF_HAVEVARTYPE,0},
237 {VT_CY, 8, FADF_HAVEVARTYPE,0},
238 {VT_DATE, 8, FADF_HAVEVARTYPE,0},
239 {VT_BSTR, sizeof(BSTR), FADF_HAVEVARTYPE,FADF_BSTR},
240 {VT_DISPATCH, sizeof(LPDISPATCH), FADF_HAVEIID, FADF_DISPATCH},
241 {VT_ERROR, 4, FADF_HAVEVARTYPE,0},
242 {VT_BOOL, 2, FADF_HAVEVARTYPE,0},
243 {VT_VARIANT, sizeof(VARIANT), FADF_HAVEVARTYPE,FADF_VARIANT},
244 {VT_UNKNOWN, sizeof(LPUNKNOWN), FADF_HAVEIID, FADF_UNKNOWN},
245 {VT_DECIMAL, sizeof(DECIMAL), FADF_HAVEVARTYPE,0},
246 {15, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0}, /* no VT_xxx */
247 {VT_I1, 1, FADF_HAVEVARTYPE,0},
248 {VT_UI1, 1, FADF_HAVEVARTYPE,0},
249 {VT_UI2, 2, FADF_HAVEVARTYPE,0},
250 {VT_UI4, 4, FADF_HAVEVARTYPE,0},
251 {VT_I8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
252 {VT_UI8, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
253 {VT_INT, sizeof(INT), FADF_HAVEVARTYPE,0},
254 {VT_UINT, sizeof(UINT), FADF_HAVEVARTYPE,0},
255 {VT_VOID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
256 {VT_HRESULT, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
257 {VT_PTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
258 {VT_SAFEARRAY,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
259 {VT_CARRAY, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
260 {VT_USERDEFINED,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
261 {VT_LPSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
262 {VT_LPWSTR, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
263 {VT_FILETIME, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
264 {VT_RECORD, VARTYPE_NOT_SUPPORTED,FADF_RECORD,0},
265 {VT_BLOB, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
266 {VT_STREAM, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
267 {VT_STORAGE, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
268 {VT_STREAMED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
269 {VT_STORED_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
270 {VT_BLOB_OBJECT,VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
271 {VT_CF, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
272 {VT_CLSID, VARTYPE_NOT_SUPPORTED,FADF_HAVEVARTYPE,0},
275 static void test_safearray(void)
281 SAFEARRAYBOUND bound, bounds[2];
287 unsigned char *ptr1, *ptr2;
289 hres = SafeArrayDestroy( NULL);
290 ok( hres == S_OK, "SafeArrayDestroy( NULL) returned 0x%x\n", hres);
294 a = SafeArrayCreate(-1, 1, &bound);
295 ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
299 a = SafeArrayCreate(VT_I4, 1, &bound);
300 ok(NULL != a,"SAC(VT_I4,1,[0,0]) failed.\n");
302 hres = SafeArrayGetLBound(a, 1, &l);
303 ok(hres == S_OK, "SAGLB of 0 size dimensioned array failed with %x\n",hres);
304 ok(l == 42, "SAGLB of 0 size dimensioned array failed to return 42, but returned %d\n",l);
305 hres = SafeArrayGetUBound(a, 1, &l);
306 ok(hres == S_OK, "SAGUB of 0 size dimensioned array failed with %x\n",hres);
307 ok(l == 41, "SAGUB of 0 size dimensioned array failed to return 41, but returned %d\n",l);
309 hres = SafeArrayAccessData(a, &data);
310 ok(hres == S_OK, "SafeArrayAccessData of 0 size dimensioned array failed with %x\n", hres);
311 SafeArrayUnaccessData(a);
314 hres = SafeArrayRedim(a, &bound);
315 ok(hres == S_OK,"SAR of a 0 elements dimension failed with hres %x\n", hres);
317 hres = SafeArrayRedim(a, &bound);
318 ok(hres == S_OK || hres == E_OUTOFMEMORY,
319 "SAR to a 0 elements dimension failed with hres %x\n", hres);
320 hres = SafeArrayDestroy(a);
321 ok(hres == S_OK,"SAD of 0 dim array faild with hres %x\n", hres);
323 SafeArrayAllocDescriptor(2, &a);
324 a->rgsabound[0].cElements = 2;
325 a->rgsabound[0].lLbound = 1;
326 a->rgsabound[1].cElements = 4;
327 a->rgsabound[1].lLbound = 1;
329 SafeArrayAllocData(a);
333 hres = SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
334 ok(hres == S_OK, "SAPOI failed with hres %x\n", hres);
335 SafeArrayAccessData(a, (void **)&ptr2);
336 ok(ptr1 - ptr2 == 14, "SAPOI got wrong ptr\n");
337 *(WORD *)ptr1 = 0x55aa;
338 SafeArrayUnaccessData(a);
340 bound.cElements = 10;
342 SafeArrayRedim(a, &bound);
344 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
345 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
347 bound.cElements = 10;
349 SafeArrayRedim(a, &bound);
350 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
351 ok(*(WORD *)ptr1 == 0, "Expanded area not zero-initialized\n");
354 SafeArrayPtrOfIndex(a, indices, (void **)&ptr1);
355 ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n");
357 hres = SafeArrayDestroy(a);
358 ok(hres == S_OK,"SAD faild with hres %x\n", hres);
360 bounds[0].cElements = 0; bounds[0].lLbound = 1;
361 bounds[1].cElements = 2; bounds[1].lLbound = 23;
362 a = SafeArrayCreate(VT_I4,2,bounds);
363 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
365 hres = SafeArrayDestroy(a);
366 ok(hres == S_OK,"SAD faild with hres %x\n", hres);
367 bounds[0].cElements = 1; bounds[0].lLbound = 1;
368 bounds[1].cElements = 0; bounds[1].lLbound = 23;
369 a = SafeArrayCreate(VT_I4,2,bounds);
370 ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n");
372 hres = SafeArrayDestroy(a);
373 ok(hres == S_OK,"SAD faild with hres %x\n", hres);
375 bounds[0].cElements = 42; bounds[0].lLbound = 1;
376 bounds[1].cElements = 2; bounds[1].lLbound = 23;
377 a = SafeArrayCreate(VT_I4,2,bounds);
378 ok(a != NULL,"SAC(VT_INT32,2,...) failed.\n");
380 hres = SafeArrayGetLBound (a, 0, &l);
381 ok (hres == DISP_E_BADINDEX, "SAGLB 0 failed with %x\n", hres);
382 hres = SafeArrayGetLBound (a, 1, &l);
383 ok (hres == S_OK, "SAGLB 1 failed with %x\n", hres);
384 ok (l == 1, "SAGLB 1 returned %d instead of 1\n", l);
385 hres = SafeArrayGetLBound (a, 2, &l);
386 ok (hres == S_OK, "SAGLB 2 failed with %x\n", hres);
387 ok (l == 23, "SAGLB 2 returned %d instead of 23\n", l);
388 hres = SafeArrayGetLBound (a, 3, &l);
389 ok (hres == DISP_E_BADINDEX, "SAGLB 3 failed with %x\n", hres);
391 hres = SafeArrayGetUBound (a, 0, &l);
392 ok (hres == DISP_E_BADINDEX, "SAGUB 0 failed with %x\n", hres);
393 hres = SafeArrayGetUBound (a, 1, &l);
394 ok (hres == S_OK, "SAGUB 1 failed with %x\n", hres);
395 ok (l == 42, "SAGUB 1 returned %d instead of 42\n", l);
396 hres = SafeArrayGetUBound (a, 2, &l);
397 ok (hres == S_OK, "SAGUB 2 failed with %x\n", hres);
398 ok (l == 24, "SAGUB 2 returned %d instead of 24\n", l);
399 hres = SafeArrayGetUBound (a, 3, &l);
400 ok (hres == DISP_E_BADINDEX, "SAGUB 3 failed with %x\n", hres);
402 i = SafeArrayGetDim(a);
403 ok(i == 2, "getdims of 2 din array returned %d\n",i);
407 hres = SafeArrayGetElement(a, indices, &i);
408 ok(DISP_E_BADINDEX == hres,"SAGE failed [0,23], hres 0x%x\n",hres);
412 hres = SafeArrayGetElement(a, indices, &i);
413 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,22], hres 0x%x\n",hres);
417 hres = SafeArrayGetElement(a, indices, &i);
418 ok(S_OK == hres,"SAGE failed [1,23], hres 0x%x\n",hres);
422 hres = SafeArrayGetElement(a, indices, &i);
423 ok(DISP_E_BADINDEX == hres,"SAGE failed [1,24], hres 0x%x\n",hres);
427 hres = SafeArrayGetElement(a, indices, &i);
428 ok(S_OK == hres,"SAGE failed [42,23], hres 0x%x\n",hres);
430 hres = SafeArrayAccessData(a, (void**)&ptr1);
431 ok(S_OK == hres, "SAAD failed with 0x%x\n", hres);
435 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
436 ok(S_OK == hres,"SAPOI failed [1,23], hres 0x%x\n",hres);
437 ok(ptr2 - ptr1 == 8,"ptr difference is not 8, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
441 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
442 ok(S_OK == hres,"SAPOI failed [5,24], hres 0x%x\n",hres);
443 ok(ptr2 - ptr1 == 176,"ptr difference is not 176, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
447 hres = SafeArrayPtrOfIndex(a, indices, (void**)&ptr2);
448 ok(S_OK == hres,"SAPOI failed [20,23], hres 0x%x\n",hres);
449 ok(ptr2 - ptr1 == 76,"ptr difference is not 76, but %d (%p vs %p)\n", ptr2-ptr1, ptr2, ptr1);
451 hres = SafeArrayUnaccessData(a);
452 ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres);
454 hres = SafeArrayDestroy(a);
455 ok(hres == S_OK,"SAD faild with hres %x\n", hres);
457 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
458 if ((i == VT_I8 || i == VT_UI8) && HAVE_OLEAUT32_I8)
460 vttypes[i].elemsize = sizeof(LONG64);
463 a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
465 ok((!a && !vttypes[i].elemsize) ||
466 (a && vttypes[i].elemsize == a->cbElements) ||
467 (IS_ANCIENT && (vttypes[i].vt == VT_DECIMAL || vttypes[i].vt == VT_I1 ||
468 vttypes[i].vt == VT_UI2 || vttypes[i].vt == VT_UI4 || vttypes[i].vt == VT_INT ||
469 vttypes[i].vt == VT_UINT)),
470 "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
471 vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
475 if (!HAVE_OLEAUT32_RECORD)
476 vttypes[i].expflags = 0;
477 ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
478 "SAC of %d returned feature flags %x, expected %x\n",
479 vttypes[i].vt, a->fFeatures,
480 vttypes[i].expflags|vttypes[i].addflags);
481 ok(SafeArrayGetElemsize(a) == vttypes[i].elemsize,
482 "SAGE for vt %d returned elemsize %d instead of expected %d\n",
483 vttypes[i].vt, SafeArrayGetElemsize(a),vttypes[i].elemsize);
488 if (pSafeArrayGetVartype)
490 hres = pSafeArrayGetVartype(a, &vt);
491 ok(hres == S_OK, "SAGVT of arra y with vt %d failed with %x\n", vttypes[i].vt, hres);
492 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
493 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
496 hres = SafeArrayCopy(a, &c);
497 ok(hres == S_OK, "failed to copy safearray of vt %d with hres %x\n", vttypes[i].vt, hres);
499 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
501 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);
502 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);
504 if (pSafeArrayGetVartype) {
505 hres = pSafeArrayGetVartype(c, &vt);
506 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
507 /* Windows prior to Vista returns VT_UNKNOWN instead of VT_DISPATCH */
508 ok(broken(vt == VT_UNKNOWN) || vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
511 if (pSafeArrayCopyData) {
512 hres = pSafeArrayCopyData(a, c);
513 ok(hres == S_OK, "failed to copy safearray data of vt %d with hres %x\n", vttypes[i].vt, hres);
515 hres = SafeArrayDestroyData(c);
516 ok(hres == S_OK,"SADD of copy of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
519 hres = SafeArrayDestroy(c);
520 ok(hres == S_OK,"SAD faild with hres %x\n", hres);
522 hres = SafeArrayDestroy(a);
523 ok(hres == S_OK,"SAD of array with vt %d failed with hres %x\n", vttypes[i].vt, hres);
526 /* Test conversion of type|VT_ARRAY <-> VT_BSTR */
528 bound.cElements = 10;
529 a = SafeArrayCreate(VT_UI1, 1, &bound);
530 ok(a != NULL, "SAC failed.\n");
531 ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed\n");
532 memcpy(data,"Hello World\n",10);
533 ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed\n");
534 V_VT(&v) = VT_ARRAY|VT_UI1;
536 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
537 ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n",hres);
538 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));
539 ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]);
542 /* check locking functions */
543 a = SafeArrayCreate(VT_I4, 1, &bound);
544 ok(a!=NULL,"SAC should not fail\n");
546 hres = SafeArrayAccessData(a, &data);
547 ok(hres == S_OK,"SAAD failed with hres %x\n",hres);
549 hres = SafeArrayDestroy(a);
550 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
552 hres = SafeArrayDestroyData(a);
553 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy data not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
555 hres = SafeArrayDestroyDescriptor(a);
556 ok(hres == DISP_E_ARRAYISLOCKED,"locked safe array destroy descriptor not failed with DISP_E_ARRAYISLOCKED, but with hres %x\n", hres);
558 hres = SafeArrayUnaccessData(a);
559 ok(hres == S_OK,"SAUD failed after lock/destroy test\n");
561 hres = SafeArrayDestroy(a);
562 ok(hres == S_OK,"SAD failed after lock/destroy test\n");
564 /* Test if we need to destroy data before descriptor */
565 a = SafeArrayCreate(VT_I4, 1, &bound);
566 ok(a!=NULL,"SAC should not fail\n");
567 hres = SafeArrayDestroyDescriptor(a);
568 ok(hres == S_OK,"SADD with data in array failed with hres %x\n",hres);
571 /* init a small stack safearray */
572 if (pSafeArraySetIID) {
573 memset(&b, 0, sizeof(b));
575 memset(&iid, 0x42, sizeof(IID));
576 hres = pSafeArraySetIID(&b,&iid);
577 ok(hres == E_INVALIDARG,"SafeArraySetIID of non IID capable safearray did not return E_INVALIDARG, but %x\n",hres);
579 hres = SafeArrayAllocDescriptor(1,&a);
580 ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n");
581 hres = pSafeArraySetIID(a,&iid);
582 ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %x\n",hres);
584 hres = SafeArrayDestroyDescriptor(a);
585 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
588 if (!pSafeArrayAllocDescriptorEx)
591 for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
593 hres = pSafeArrayAllocDescriptorEx(vttypes[i].vt,1,&a);
594 ok(a->fFeatures == vttypes[i].expflags,"SAADE(%d) resulted with flags %x, expected %x\n", vttypes[i].vt, a->fFeatures, vttypes[i].expflags);
595 if (a->fFeatures & FADF_HAVEIID) {
596 hres = pSafeArrayGetIID(a, &iid);
597 ok(hres == S_OK,"SAGIID failed for vt %d with hres %x\n", vttypes[i].vt,hres);
598 switch (vttypes[i].vt) {
600 ok(IsEqualGUID(((GUID*)a)-1,&IID_IUnknown),"guid for VT_UNKNOWN is not IID_IUnknown\n");
601 ok(IsEqualGUID(&iid, &IID_IUnknown),"SAGIID returned wrong GUID for IUnknown\n");
604 ok(IsEqualGUID(((GUID*)a)-1,&IID_IDispatch),"guid for VT_UNKNOWN is not IID_IDispatch\n");
605 ok(IsEqualGUID(&iid, &IID_IDispatch),"SAGIID returned wrong GUID for IDispatch\n");
608 ok(FALSE,"unknown vt %d with FADF_HAVEIID\n",vttypes[i].vt);
612 hres = pSafeArrayGetIID(a, &iid);
613 ok(hres == E_INVALIDARG,"SAGIID did not fail for vt %d with hres %x\n", vttypes[i].vt,hres);
615 if (a->fFeatures & FADF_RECORD) {
616 ok(vttypes[i].vt == VT_RECORD,"FADF_RECORD for non record %d\n",vttypes[i].vt);
618 if (a->fFeatures & FADF_HAVEVARTYPE) {
619 ok(vttypes[i].vt == ((DWORD*)a)[-1], "FADF_HAVEVARTYPE set, but vt %d mismatch stored %d\n",vttypes[i].vt,((DWORD*)a)[-1]);
622 hres = pSafeArrayGetVartype(a, &vt);
623 ok(hres == S_OK, "SAGVT of array with vt %d failed with %x\n", vttypes[i].vt, hres);
625 if (vttypes[i].vt == VT_DISPATCH) {
626 /* Special case. Checked against Windows. */
627 ok(vt == VT_UNKNOWN, "SAGVT of array with VT_DISPATCH returned not VT_UNKNOWN, but %d\n", vt);
629 ok(vt == vttypes[i].vt, "SAGVT of array with vt %d returned %d\n", vttypes[i].vt, vt);
632 if (a->fFeatures & FADF_HAVEIID) {
633 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
634 ok(hres == S_OK,"SASIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
635 hres = pSafeArrayGetIID(a, &iid);
636 ok(hres == S_OK,"SAGIID failed with FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
637 ok(IsEqualGUID(&iid, &IID_IStorage),"returned iid is not IID_IStorage\n");
639 hres = pSafeArraySetIID(a, &IID_IStorage); /* random IID */
640 ok(hres == E_INVALIDARG,"SASIID did not failed with !FADF_HAVEIID set for vt %d with %x\n", vttypes[i].vt, hres);
642 hres = SafeArrayDestroyDescriptor(a);
643 ok(hres == S_OK,"SADD failed with hres %x\n",hres);
647 static void test_SafeArrayAllocDestroyDescriptor(void)
654 hres = SafeArrayAllocDescriptor(0, &sa);
655 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
657 hres = SafeArrayAllocDescriptor(65536, &sa);
658 ok(IS_ANCIENT || hres == E_INVALIDARG,
659 "65536 dimensions gave hres 0x%x\n", hres);
663 /* Crashes on 95: XP & Wine return E_POINTER */
664 hres=SafeArrayAllocDescriptor(1, NULL);
665 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
668 /* Test up to the dimension boundary case */
669 for (i = 5; i <= 65535; i += 30)
671 hres = SafeArrayAllocDescriptor(i, &sa);
672 ok(hres == S_OK, "%d dimensions failed; hres 0x%x\n", i, hres);
676 ok(SafeArrayGetDim(sa) == (UINT)i, "Dimension is %d; should be %d\n",
677 SafeArrayGetDim(sa), i);
679 hres = SafeArrayDestroyDescriptor(sa);
680 ok(hres == S_OK, "destroy failed; hres 0x%x\n", hres);
684 if (!pSafeArrayAllocDescriptorEx)
687 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 0, &sa);
688 ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
690 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 65536, &sa);
691 ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
693 hres = pSafeArrayAllocDescriptorEx(VT_UI1, 1, NULL);
694 ok(hres == E_POINTER,"NULL parm gave hres 0x%x\n", hres);
696 hres = pSafeArrayAllocDescriptorEx(-1, 1, &sa);
697 ok(hres == S_OK, "VT = -1 gave hres 0x%x\n", hres);
699 sa->rgsabound[0].cElements = 0;
700 sa->rgsabound[0].lLbound = 1;
702 hres = SafeArrayAllocData(sa);
703 ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres);
705 hres = SafeArrayDestroy(sa);
706 ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres);
709 static void test_SafeArrayCreateLockDestroy(void)
711 SAFEARRAYBOUND sab[4];
717 #define NUM_DIMENSIONS (int)(sizeof(sab) / sizeof(sab[0]))
719 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
721 sab[dimension].lLbound = 0;
722 sab[dimension].cElements = 8;
726 /* This test crashes very early versions with no error checking...
727 sa = SafeArrayCreate(VT_UI1, 1, NULL);
728 ok(sa == NULL, "NULL bounds didn't fail\n");
730 sa = SafeArrayCreate(VT_UI1, 65536, sab);
731 ok(IS_ANCIENT || !sa, "Max bounds didn't fail\n");
733 memset(sab, 0, sizeof(sab));
735 /* Don't test 0 sized dimensions, as Windows has a bug which allows this */
737 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
738 sab[dimension].cElements = 8;
740 /* Test all VARTYPES in 1-4 dimensions */
741 for (dimension = 1; dimension < 4; dimension++)
743 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
745 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
747 sa = SafeArrayCreate(vt, dimension, sab);
750 ok(sa || (IS_ANCIENT && (vt == VT_DECIMAL || vt == VT_I1 || vt == VT_UI2 ||
751 vt == VT_UI4 || vt == VT_INT || vt == VT_UINT)),
752 "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
754 ok(sa == NULL || vt == VT_R8,
755 "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
759 ok(SafeArrayGetDim(sa) == (UINT)dimension,
760 "VARTYPE %d (@%d dimensions) cDims is %d, expected %d\n",
761 vt, dimension, SafeArrayGetDim(sa), dimension);
762 ok(SafeArrayGetElemsize(sa) == dwLen || vt == VT_R8,
763 "VARTYPE %d (@%d dimensions) cbElements is %d, expected %d\n",
764 vt, dimension, SafeArrayGetElemsize(sa), dwLen);
766 if (vt != VT_UNKNOWN && vt != VT_DISPATCH)
768 ok((sa->fFeatures & FADF_HAVEIID) == 0,
769 "Non interface type should not have FADF_HAVEIID\n");
770 if (pSafeArraySetIID)
772 hres = pSafeArraySetIID(sa, &IID_IUnknown);
773 ok(hres == E_INVALIDARG,
774 "Non interface type allowed SetIID(), hres %x\n", hres);
780 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEVARTYPE,
781 "Non interface type should have FADF_HAVEVARTYPE\n");
782 if (pSafeArrayGetVartype)
784 hres = pSafeArrayGetVartype(sa, &aVt);
785 ok(hres == S_OK && aVt == vt,
786 "Non interface type %d: bad type %d, hres %x\n", vt, aVt, hres);
792 ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEIID,
793 "Interface type should have FADF_HAVEIID\n");
794 if (pSafeArraySetIID)
796 hres = pSafeArraySetIID(sa, &IID_IUnknown);
798 "Non interface type disallowed SetIID(), hres %x\n", hres);
800 ok((sa->fFeatures & FADF_HAVEVARTYPE) == 0,
801 "Interface type %d should not have FADF_HAVEVARTYPE\n", vt);
804 hres = SafeArrayLock(sa);
805 ok(hres == S_OK, "Lock VARTYPE %d (@%d dimensions) failed; hres 0x%x\n",
806 vt, dimension, hres);
810 hres = SafeArrayDestroy(sa);
811 ok(hres == DISP_E_ARRAYISLOCKED,"Destroy() got hres %x\n", hres);
813 hres = SafeArrayDestroyData(sa);
814 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyData() got hres %x\n", hres);
816 hres = SafeArrayDestroyDescriptor(sa);
817 ok(hres == DISP_E_ARRAYISLOCKED,"DestroyDescriptor() got hres %x\n", hres);
819 hres = SafeArrayUnlock(sa);
820 ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n",
821 vt, dimension, hres);
823 hres = SafeArrayDestroy(sa);
824 ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n",
825 vt, dimension, hres);
832 static void test_VectorCreateLockDestroy(void)
839 if (!pSafeArrayCreateVector)
841 sa = pSafeArrayCreateVector(VT_UI1, 0, 0);
842 ok(sa != NULL, "SACV with 0 elements failed.\n");
844 hres = SafeArrayDestroy(sa);
845 ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres);
847 /* Test all VARTYPES in different lengths */
848 for (element = 1; element <= 101; element += 10)
850 for (vt = VT_EMPTY; vt < VT_CLSID; vt++)
852 DWORD dwLen = SAFEARRAY_GetVTSize(vt);
854 sa = pSafeArrayCreateVector(vt, 0, element);
857 ok(sa != NULL, "VARTYPE %d (@%d elements) failed\n", vt, element);
859 ok(sa == NULL, "VARTYPE %d (@%d elements) succeeded!\n", vt, element);
863 ok(SafeArrayGetDim(sa) == 1, "VARTYPE %d (@%d elements) cDims %d, not 1\n",
864 vt, element, SafeArrayGetDim(sa));
865 ok(SafeArrayGetElemsize(sa) == dwLen,
866 "VARTYPE %d (@%d elements) cbElements is %d, expected %d\n",
867 vt, element, SafeArrayGetElemsize(sa), dwLen);
869 hres = SafeArrayLock(sa);
870 ok(hres == S_OK, "Lock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
875 hres = SafeArrayUnlock(sa);
876 ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n",
879 hres = SafeArrayDestroy(sa);
880 ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n",
888 static void test_LockUnlock(void)
890 SAFEARRAYBOUND sab[4];
893 BOOL bVector = FALSE;
897 hres = SafeArrayLock(NULL);
898 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
899 hres = SafeArrayUnlock(NULL);
900 ok(hres == E_INVALIDARG, "Lock NULL array hres 0x%x\n", hres);
902 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
904 sab[dimension].lLbound = 0;
905 sab[dimension].cElements = 8;
908 sa = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
910 /* Test maximum locks */
911 test_LockUnlock_Vector:
916 hres = SafeArrayUnlock(sa);
917 ok (hres == E_UNEXPECTED, "Bad %sUnlock gave hres 0x%x\n",
918 bVector ? "vector " : "\n", hres);
920 while ((hres = SafeArrayLock(sa)) == S_OK)
922 ok (count == 65535 && hres == E_UNEXPECTED, "Lock %sfailed at %d; hres 0x%x\n",
923 bVector ? "vector " : "\n", count, hres);
925 if (count == 65535 && hres == E_UNEXPECTED)
927 while ((hres = SafeArrayUnlock(sa)) == S_OK)
929 ok (count == 0 && hres == E_UNEXPECTED, "Unlock %sfailed at %d; hres 0x%x\n",
930 bVector ? "vector " : "\n", count, hres);
933 SafeArrayDestroy(sa);
936 if (bVector == FALSE && pSafeArrayCreateVector)
938 /* Test again with a vector */
939 sa = pSafeArrayCreateVector(VT_UI1, 0, 100);
941 goto test_LockUnlock_Vector;
945 static void test_SafeArrayGetPutElement(void)
947 SAFEARRAYBOUND sab[4];
948 LONG indices[NUM_DIMENSIONS];
951 int value = 0, gotvalue, dimension;
952 unsigned int x,y,z,a;
954 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
956 sab[dimension].lLbound = dimension * 2 + 1;
957 sab[dimension].cElements = dimension * 3 + 1;
960 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
962 return; /* Some early versions can't handle > 3 dims */
964 ok(sa->cbElements == sizeof(value), "int size mismatch\n");
965 if (sa->cbElements != sizeof(value))
969 for (x = 0; x < NUM_DIMENSIONS; x++)
971 indices[0] = sab[0].lLbound;
972 indices[1] = sab[1].lLbound;
973 indices[2] = sab[2].lLbound;
974 indices[3] = sab[3].lLbound;
976 indices[x] = indices[x] - 1;
977 hres = SafeArrayPutElement(sa, indices, &value);
978 ok(hres == DISP_E_BADINDEX, "Put allowed too small index in dimension %d\n", x);
979 hres = SafeArrayGetElement(sa, indices, &value);
980 ok(hres == DISP_E_BADINDEX, "Get allowed too small index in dimension %d\n", x);
982 indices[x] = sab[x].lLbound + sab[x].cElements;
983 hres = SafeArrayPutElement(sa, indices, &value);
984 ok(hres == DISP_E_BADINDEX, "Put allowed too big index in dimension %d\n", x);
985 hres = SafeArrayGetElement(sa, indices, &value);
986 ok(hres == DISP_E_BADINDEX, "Get allowed too big index in dimension %d\n", x);
989 indices[0] = sab[0].lLbound;
990 indices[1] = sab[1].lLbound;
991 indices[2] = sab[2].lLbound;
992 indices[3] = sab[3].lLbound;
994 hres = SafeArrayPutElement(NULL, indices, &value);
995 ok(hres == E_INVALIDARG, "Put NULL array hres 0x%x\n", hres);
996 hres = SafeArrayGetElement(NULL, indices, &value);
997 ok(hres == E_INVALIDARG, "Get NULL array hres 0x%x\n", hres);
999 hres = SafeArrayPutElement(sa, NULL, &value);
1000 ok(hres == E_INVALIDARG, "Put NULL indices hres 0x%x\n", hres);
1001 hres = SafeArrayGetElement(sa, NULL, &value);
1002 ok(hres == E_INVALIDARG, "Get NULL indices hres 0x%x\n", hres);
1006 /* This is retarded. Windows checks every case of invalid parameters
1007 * except the following, which crashes. We ERR this in Wine.
1009 hres = SafeArrayPutElement(sa, indices, NULL);
1010 ok(hres == E_INVALIDARG, "Put NULL value hres 0x%x\n", hres);
1013 hres = SafeArrayGetElement(sa, indices, NULL);
1014 ok(hres == E_INVALIDARG, "Get NULL value hres 0x%x\n", hres);
1018 /* Make sure we can read and get back the correct values in 4 dimensions,
1019 * Each with a different size and lower bound.
1021 for (x = 0; x < sab[0].cElements; x++)
1023 indices[0] = sab[0].lLbound + x;
1024 for (y = 0; y < sab[1].cElements; y++)
1026 indices[1] = sab[1].lLbound + y;
1027 for (z = 0; z < sab[2].cElements; z++)
1029 indices[2] = sab[2].lLbound + z;
1030 for (a = 0; a < sab[3].cElements; a++)
1032 indices[3] = sab[3].lLbound + a;
1033 hres = SafeArrayPutElement(sa, indices, &value);
1034 ok(hres == S_OK, "Failed to put element at (%d,%d,%d,%d) hres 0x%x\n",
1044 for (x = 0; x < sab[0].cElements; x++)
1046 indices[0] = sab[0].lLbound + x;
1047 for (y = 0; y < sab[1].cElements; y++)
1049 indices[1] = sab[1].lLbound + y;
1050 for (z = 0; z < sab[2].cElements; z++)
1052 indices[2] = sab[2].lLbound + z;
1053 for (a = 0; a < sab[3].cElements; a++)
1055 indices[3] = sab[3].lLbound + a;
1056 gotvalue = value / 3;
1057 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1058 ok(hres == S_OK, "Failed to get element at (%d,%d,%d,%d) hres 0x%x\n",
1061 ok(value == gotvalue, "Got value %d instead of %d at (%d,%d,%d,%d)\n",
1062 gotvalue, value, x, y, z, a);
1068 SafeArrayDestroy(sa);
1071 static void test_SafeArrayGetPutElement_BSTR(void)
1077 BSTR value = 0, gotvalue;
1078 const OLECHAR szTest[5] = { 'T','e','s','t','\0' };
1083 sa = SafeArrayCreate(VT_BSTR, 1, &sab);
1084 ok(sa != NULL, "BSTR test couldn't create array\n");
1088 ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
1089 if (sa->cbElements != sizeof(BSTR))
1092 indices[0] = sab.lLbound;
1093 value = SysAllocString(szTest);
1094 ok (value != NULL, "Expected non-NULL\n");
1095 hres = SafeArrayPutElement(sa, indices, value);
1096 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1098 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1099 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1101 ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value));
1102 SafeArrayDestroy(sa);
1103 SysFreeString(value);
1104 SysFreeString(gotvalue);
1107 static int tunk_xref = 0;
1108 static HRESULT WINAPI tunk_QueryInterface(LPUNKNOWN punk,REFIID riid, LPVOID *x) {
1111 static ULONG WINAPI tunk_AddRef(LPUNKNOWN punk) {
1115 static ULONG WINAPI tunk_Release(LPUNKNOWN punk) {
1119 static const IUnknownVtbl xtunk_vtbl = {
1120 tunk_QueryInterface,
1125 static struct xtunk_iface {
1126 const IUnknownVtbl *lpvtbl;
1130 static void test_SafeArrayGetPutElement_IUnknown(void)
1136 LPUNKNOWN value = 0, gotvalue;
1140 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1141 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1145 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1146 if (sa->cbElements != sizeof(LPUNKNOWN))
1149 indices[0] = sab.lLbound;
1150 xtunk_iface.lpvtbl = &xtunk_vtbl;
1151 value = (LPUNKNOWN)&xtunk_iface;
1153 ok (value != NULL, "Expected non-NULL\n");
1154 hres = SafeArrayPutElement(sa, indices, value);
1155 ok(hres == S_OK, "Failed to put bstr element hres 0x%x\n", hres);
1156 ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1158 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1159 ok(tunk_xref == 3,"Failed to increment refcount of iface.\n");
1160 ok(hres == S_OK, "Failed to get bstr element at hres 0x%x\n", hres);
1162 ok(value == gotvalue, "Got %p instead of %p\n", gotvalue, value);
1163 SafeArrayDestroy(sa);
1164 ok(tunk_xref == 2,"Failed to decrement refcount of iface.\n");
1167 static void test_SafeArrayRedim_IUnknown(void)
1177 sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
1178 ok(sa != NULL, "UNKNOWN test couldn't create array\n");
1182 ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
1183 if (sa->cbElements != sizeof(LPUNKNOWN))
1187 xtunk_iface.lpvtbl = &xtunk_vtbl;
1188 value = (LPUNKNOWN)&xtunk_iface;
1190 hres = SafeArrayPutElement(sa, indices, value);
1191 ok(hres == S_OK, "Failed to put IUnknown element hres 0x%x\n", hres);
1192 ok(tunk_xref == 2,"Failed to increment refcount of iface.\n");
1194 hres = SafeArrayRedim(sa, &sab);
1195 ok(hres == S_OK, "Failed to shrink array hres 0x%x\n", hres);
1196 ok(tunk_xref == 1, "Failed to decrement refcount\n");
1197 SafeArrayDestroy(sa);
1200 static void test_SafeArrayGetPutElement_VARIANT(void)
1206 VARIANT value, gotvalue;
1210 sa = SafeArrayCreate(VT_VARIANT, 1, &sab);
1211 ok(sa != NULL, "VARIANT test couldn't create array\n");
1215 ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
1216 if (sa->cbElements != sizeof(VARIANT))
1219 indices[0] = sab.lLbound;
1220 V_VT(&value) = VT_I4;
1221 V_I4(&value) = 0x42424242;
1222 hres = SafeArrayPutElement(sa, indices, &value);
1223 ok(hres == S_OK, "Failed to put Variant I4 element hres 0x%x\n", hres);
1225 V_VT(&gotvalue) = 0xdead;
1226 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1227 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1229 V_VT(&gotvalue) = VT_EMPTY;
1230 hres = SafeArrayGetElement(sa, indices, &gotvalue);
1231 ok(hres == S_OK, "Failed to get variant element at hres 0x%x\n", hres);
1233 ok(V_VT(&value) == V_VT(&gotvalue), "Got type 0x%x instead of 0x%x\n", V_VT(&value), V_VT(&gotvalue));
1234 if (V_VT(&value) == V_VT(&gotvalue))
1235 ok(V_I4(&value) == V_I4(&gotvalue), "Got %d instead of %d\n", V_I4(&value), V_VT(&gotvalue));
1237 SafeArrayDestroy(sa);
1241 static void test_SafeArrayCopyData(void)
1243 SAFEARRAYBOUND sab[4];
1247 int dimension,size=1;
1249 if (!pSafeArrayCopyData)
1252 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1254 sab[dimension].lLbound = dimension * 2 + 2;
1255 sab[dimension].cElements = dimension * 3 + 1;
1256 size *= sab[dimension].cElements;
1259 sa = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1260 ok(sa != NULL, "Copy test couldn't create array\n");
1261 sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
1262 ok(sacopy != NULL, "Copy test couldn't create copy array\n");
1267 ok(sa->cbElements == sizeof(int), "int size mismatch\n");
1268 if (sa->cbElements != sizeof(int))
1271 /* Fill the source array with some data; it doesn't matter what */
1272 for (dimension = 0; dimension < size; dimension++)
1274 int* data = (int*)sa->pvData;
1275 data[dimension] = dimension;
1278 hres = pSafeArrayCopyData(sa, sacopy);
1279 ok(hres == S_OK, "copy data failed hres 0x%x\n", hres);
1282 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1286 hres = pSafeArrayCopyData(NULL, sacopy);
1287 ok(hres == E_INVALIDARG, "Null copy source hres 0x%x\n", hres);
1288 hres = pSafeArrayCopyData(sa, NULL);
1289 ok(hres == E_INVALIDARG, "Null copy hres 0x%x\n", hres);
1291 sacopy->rgsabound[0].cElements += 1;
1292 hres = pSafeArrayCopyData(sa, sacopy);
1293 ok(hres == E_INVALIDARG, "Bigger copy first dimension hres 0x%x\n", hres);
1295 sacopy->rgsabound[0].cElements -= 2;
1296 hres = pSafeArrayCopyData(sa, sacopy);
1297 ok(hres == E_INVALIDARG, "Smaller copy first dimension hres 0x%x\n", hres);
1298 sacopy->rgsabound[0].cElements += 1;
1300 sacopy->rgsabound[3].cElements += 1;
1301 hres = pSafeArrayCopyData(sa, sacopy);
1302 ok(hres == E_INVALIDARG, "Bigger copy last dimension hres 0x%x\n", hres);
1304 sacopy->rgsabound[3].cElements -= 2;
1305 hres = pSafeArrayCopyData(sa, sacopy);
1306 ok(hres == E_INVALIDARG, "Smaller copy last dimension hres 0x%x\n", hres);
1307 sacopy->rgsabound[3].cElements += 1;
1309 SafeArrayDestroy(sacopy);
1311 hres = pSafeArrayCopyData(sa, sacopy);
1312 ok(hres == E_INVALIDARG, "->Null copy hres 0x%x\n", hres);
1314 hres = SafeArrayCopy(sa, &sacopy);
1315 ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
1318 ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
1319 ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
1320 ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
1323 SafeArrayDestroy(sa);
1326 static void test_SafeArrayCreateEx(void)
1328 IRecordInfoImpl* iRec;
1329 SAFEARRAYBOUND sab[4];
1334 if (!pSafeArrayCreateEx)
1337 for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
1339 sab[dimension].lLbound = 0;
1340 sab[dimension].cElements = 8;
1344 sa = pSafeArrayCreateEx(VT_UI1, 1, NULL, NULL);
1345 ok(sa == NULL, "CreateEx NULL bounds didn't fail\n");
1347 /* test IID storage & defaulting */
1348 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, (PVOID)&IID_ITypeInfo);
1349 ok(sa != NULL, "CreateEx (ITypeInfo) failed\n");
1354 if (pSafeArrayGetIID)
1356 hres = pSafeArrayGetIID(sa, &guid);
1357 ok(hres == S_OK, "CreateEx (ITypeInfo) no IID hres 0x%x\n", hres);
1360 ok(IsEqualGUID(&guid, &IID_ITypeInfo), "CreateEx (ITypeInfo) bad IID\n");
1363 if (pSafeArraySetIID)
1365 hres = pSafeArraySetIID(sa, &IID_IUnknown);
1366 ok(hres == S_OK, "Failed to set IID, hres = %8x\n", hres);
1367 if (hres == S_OK && pSafeArrayGetIID)
1369 hres = pSafeArrayGetIID(sa, &guid);
1370 ok(hres == S_OK && IsEqualGUID(&guid, &IID_IUnknown), "Set bad IID\n");
1373 SafeArrayDestroy(sa);
1376 sa = pSafeArrayCreateEx(VT_DISPATCH, 1, sab, NULL);
1377 ok(sa != NULL, "CreateEx (NULL) failed\n");
1382 if (pSafeArrayGetIID)
1384 hres = pSafeArrayGetIID(sa, &guid);
1385 ok(hres == S_OK, "CreateEx (NULL) no IID hres 0x%x\n", hres);
1388 ok(IsEqualGUID(&guid, &IID_IDispatch), "CreateEx (NULL) bad IID\n");
1391 SafeArrayDestroy(sa);
1394 sa = pSafeArrayCreateEx(VT_UNKNOWN, 1, sab, NULL);
1395 ok(sa != NULL, "CreateEx (NULL-Unk) failed\n");
1400 if (pSafeArrayGetIID)
1402 hres = pSafeArrayGetIID(sa, &guid);
1403 ok(hres == S_OK, "CreateEx (NULL-Unk) no IID hres 0x%x\n", hres);
1406 ok(IsEqualGUID(&guid, &IID_IUnknown), "CreateEx (NULL-Unk) bad IID\n");
1409 SafeArrayDestroy(sa);
1412 /* VT_RECORD failure case */
1413 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, NULL);
1414 ok(sa == NULL, "CreateEx (NULL-Rec) succeded\n");
1416 iRec = IRecordInfoImpl_Construct();
1418 /* Win32 doesn't care if GetSize fails */
1419 fail_GetSize = TRUE;
1420 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1421 ok(sa != NULL, "CreateEx (Fail Size) failed\n");
1422 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1423 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1424 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1427 ok(sa->cbElements == RECORD_SIZE_FAIL, "Altered size to %d\n", sa->cbElements);
1428 SafeArrayDestroy(sa);
1429 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1432 /* Test VT_RECORD array */
1433 fail_GetSize = FALSE;
1434 iRec->ref = START_REF_COUNT;
1435 iRec->sizeCalled = 0;
1436 iRec->clearCalled = 0;
1437 sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, (LPVOID)iRec);
1438 ok(sa != NULL, "CreateEx (Rec) failed\n");
1439 ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
1440 ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
1441 ok(iRec->clearCalled == 0, "Clear called %d times\n", iRec->clearCalled);
1442 if (sa && pSafeArrayGetRecordInfo)
1444 IRecordInfo* saRec = NULL;
1445 hres = pSafeArrayGetRecordInfo(sa, &saRec);
1447 ok(hres == S_OK,"GRI failed\n");
1448 ok(saRec == (IRecordInfo*)iRec,"Different saRec\n");
1449 ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
1450 if (iRec->ref == START_REF_COUNT + 2)
1451 IRecordInfo_Release(saRec);
1453 ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
1455 SafeArrayDestroy(sa);
1456 ok(iRec->sizeCalled == 1, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
1457 ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
1458 ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref);
1462 static void test_SafeArrayClear(void)
1471 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1472 ok(sa != NULL, "Create() failed.\n");
1476 /* Test clearing non-NULL variants containing arrays */
1477 V_VT(&v) = VT_ARRAY|VT_UI1;
1479 hres = VariantClear(&v);
1480 ok(hres == S_OK && V_VT(&v) == VT_EMPTY, "VariantClear: hres 0x%x, Type %d\n", hres, V_VT(&v));
1481 ok(V_ARRAY(&v) == sa, "VariantClear: Overwrote value\n");
1483 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1484 ok(sa != NULL, "Create() failed.\n");
1488 V_VT(&v) = VT_SAFEARRAY;
1490 hres = VariantClear(&v);
1491 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1493 V_VT(&v) = VT_SAFEARRAY|VT_BYREF;
1494 V_ARRAYREF(&v) = &sa;
1495 hres = VariantClear(&v);
1496 ok(hres == DISP_E_BADVARTYPE, "VariantClear: hres 0x%x\n", hres);
1498 SafeArrayDestroy(sa);
1501 static void test_SafeArrayCopy(void)
1504 SAFEARRAY *sa, *sa2;
1505 VARIANTARG vSrc, vDst;
1510 sa = SafeArrayCreate(VT_UI1, 1, &sab);
1511 ok(sa != NULL, "Create() failed.\n");
1515 /* Test copying non-NULL variants containing arrays */
1516 V_VT(&vSrc) = (VT_ARRAY|VT_BYREF|VT_UI1);
1517 V_ARRAYREF(&vSrc) = &sa;
1518 V_VT(&vDst) = VT_EMPTY;
1520 hres = VariantCopy(&vDst, &vSrc);
1521 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_BYREF|VT_UI1),
1522 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1523 ok(V_ARRAYREF(&vDst) == &sa, "VariantClear: Performed deep copy\n");
1525 V_VT(&vSrc) = (VT_ARRAY|VT_UI1);
1526 V_ARRAY(&vSrc) = sa;
1527 V_VT(&vDst) = VT_EMPTY;
1529 hres = VariantCopy(&vDst, &vSrc);
1530 ok(hres == S_OK && V_VT(&vDst) == (VT_ARRAY|VT_UI1),
1531 "VariantCopy: hres 0x%x, Type %d\n", hres, V_VT(&vDst));
1532 ok(V_ARRAY(&vDst) != sa, "VariantClear: Performed shallow copy\n");
1534 SafeArrayDestroy(V_ARRAY(&vSrc));
1535 SafeArrayDestroy(V_ARRAY(&vDst));
1537 hres = SafeArrayAllocDescriptor(1, &sa);
1538 ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
1540 hres = SafeArrayCopy(sa, &sa2);
1541 ok(hres == E_INVALIDARG,
1542 "SafeArrayCopy with empty array should have failed with error E_INVALIDARG instead of 0x%08x\n",
1544 sa->cbElements = 16;
1545 hres = SafeArrayCopy(sa, &sa2);
1546 ok(hres == S_OK, "SafeArrayCopy failed with error 0x%08x\n", hres);
1548 SafeArrayDestroy(sa);
1551 #define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1552 sa = SafeArrayCreate(typ, 1, &sab); ok(sa != NULL, "Create() failed.\n"); \
1554 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1556 #define MKARRAYCONT(low,num,typ) sab.lLbound = low; sab.cElements = num; \
1557 sa = SafeArrayCreate(typ, 1, &sab); if (!sa) continue; \
1558 V_VT(&v) = VT_ARRAY|typ; V_ARRAY(&v) = sa; VariantInit(&v2)
1560 static void test_SafeArrayChangeTypeEx(void)
1562 static const char *szHello = "Hello World";
1569 /* VT_ARRAY|VT_UI1 -> VT_BSTR */
1570 MKARRAY(0,strlen(szHello)+1,VT_UI1);
1571 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1573 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1574 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1577 ok(V_VT(&v2) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v2));
1578 ok(strcmp((char*)V_BSTR(&v2),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1579 (char*)V_BSTR(&v2));
1583 /* VT_VECTOR|VT_UI1 -> VT_BSTR */
1584 SafeArrayDestroy(sa);
1585 if (pSafeArrayCreateVector)
1587 sa = pSafeArrayCreateVector(VT_UI1, 0, strlen(szHello)+1);
1588 ok(sa != NULL, "CreateVector() failed.\n");
1592 memcpy(sa->pvData, szHello, strlen(szHello)+1);
1593 V_VT(&v) = VT_VECTOR|VT_UI1;
1597 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1598 ok(hres == DISP_E_BADVARTYPE, "CTE VT_VECTOR|VT_UI1 returned %x\n", hres);
1600 /* (vector)VT_ARRAY|VT_UI1 -> VT_BSTR (In place) */
1601 V_VT(&v) = VT_ARRAY|VT_UI1;
1602 hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
1603 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %x\n", hres);
1606 ok(V_VT(&v) == VT_BSTR, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.\n",V_VT(&v));
1607 ok(strcmp((char*)V_BSTR(&v),szHello) == 0,"Expected string '%s', got '%s'\n", szHello,
1613 /* To/from BSTR only works with arrays of VT_UI1 */
1614 for (vt = 0; vt <= VT_CLSID; vt++)
1619 MKARRAYCONT(0,1,vt);
1620 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR);
1621 ok(hres != S_OK, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt);
1626 /* Can't change an array of one type into array of another type , even
1627 * if the other type is the same size
1629 if (pSafeArrayCreateVector)
1631 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1632 ok(sa != NULL, "CreateVector() failed.\n");
1636 V_VT(&v) = VT_ARRAY|VT_UI1;
1638 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_I1);
1639 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_I1 returned %x\n", hres);
1641 /* But can change to the same array type */
1642 SafeArrayDestroy(sa);
1643 sa = pSafeArrayCreateVector(VT_UI1, 0, 1);
1644 ok(sa != NULL, "CreateVector() failed.\n");
1647 V_VT(&v) = VT_ARRAY|VT_UI1;
1649 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1);
1650 ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres);
1651 SafeArrayDestroy(sa);
1655 MKARRAY(0,1,VT_UI1);
1656 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_NULL);
1657 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1658 MKARRAY(0,1,VT_UI1);
1659 hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_EMPTY);
1660 ok(hres == DISP_E_TYPEMISMATCH, "CTE VT_ARRAY|VT_UI1 returned %x\n", hres);
1664 static void test_SafeArrayDestroyData (void)
1669 int value = 0xdeadbeef;
1671 void HUGEP *temp_pvData;
1675 sa = SafeArrayCreate(VT_INT, 1, &sab);
1676 ok(sa != NULL, "Create() failed.\n");
1680 SafeArrayPutElement (sa, index, &value);
1682 /* SafeArrayDestroyData shouldn't free pvData if FADF_STATIC is set. */
1683 sa->fFeatures |= FADF_STATIC;
1684 temp_pvData = sa->pvData;
1685 hres = SafeArrayDestroyData(sa);
1686 ok(hres == S_OK, "SADData FADF_STATIC failed, error code %x.\n",hres);
1687 ok(sa->pvData == temp_pvData, "SADData FADF_STATIC: pvData=%p, expected %p (fFeatures = %d).\n",
1688 sa->pvData, temp_pvData, sa->fFeatures);
1689 SafeArrayGetElement (sa, index, &value);
1690 ok(value == 0, "Data not cleared after SADData\n");
1692 /* Clear FADF_STATIC, now really destroy the data. */
1693 sa->fFeatures ^= FADF_STATIC;
1694 hres = SafeArrayDestroyData(sa);
1695 ok(hres == S_OK, "SADData !FADF_STATIC failed, error code %x.\n",hres);
1696 ok(sa->pvData == NULL, "SADData !FADF_STATIC: pvData=%p, expected NULL.\n", sa->pvData);
1698 hres = SafeArrayDestroy(sa);
1699 ok(hres == S_OK, "SAD failed, error code %x.\n", hres);
1702 START_TEST(safearray)
1704 hOleaut32 = GetModuleHandleA("oleaut32.dll");
1706 GETPTR(SafeArrayAllocDescriptorEx);
1707 GETPTR(SafeArrayCopyData);
1708 GETPTR(SafeArrayGetIID);
1709 GETPTR(SafeArraySetIID);
1710 GETPTR(SafeArrayGetVartype);
1711 GETPTR(SafeArrayCreateEx);
1712 GETPTR(SafeArrayCreateVector);
1714 check_for_VT_INT_PTR();
1716 test_SafeArrayAllocDestroyDescriptor();
1717 test_SafeArrayCreateLockDestroy();
1718 test_VectorCreateLockDestroy();
1720 test_SafeArrayChangeTypeEx();
1721 test_SafeArrayCopy();
1722 test_SafeArrayClear();
1723 test_SafeArrayCreateEx();
1724 test_SafeArrayCopyData();
1725 test_SafeArrayDestroyData();
1726 test_SafeArrayGetPutElement();
1727 test_SafeArrayGetPutElement_BSTR();
1728 test_SafeArrayGetPutElement_IUnknown();
1729 test_SafeArrayRedim_IUnknown();
1730 test_SafeArrayGetPutElement_VARIANT();