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