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